تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Writing guest access test0:38

first step, I'm going to add a test here to ensure that this is the case. We'll call it impersonateUsersTest. Okay, so let's see. Well, what's the very first thing we want to make sure? Well, how about this? Non-administrator, anyone who's not an administrator cannot impersonate users. So we'll say non-admins cannot impersonate users. So we'll do something like this. We'll say, build up a factory, and we'll say, create a User here. And even if we're not signed in, we just want to, as a guest, try to impersonate that User by hitting the proper endpoint, maybe something like this, impersonate, and then you give the userId, maybe something like that. Now, what we want to say is, you're a guest, you have no permission to access this endpoint whatsoever. So we'll say, if you try to hit that endpoint, we are going to redirect you to the login page. Okay, so we are creating Users, which means we do want to roll back our database.

Setting up test database1:28

whatsoever. So we'll say, if you try to hit that endpoint, we are going to redirect you to the login page. Okay, so we are creating Users, which means we do want to roll back our database. So I'm going to use database transactions, and then clear up any non-used imports here. Okay, so we do have a fresh project here, which means I do need to configure it really quickly. What I'm going to do is reference a database.sqlite file, and then within my .env file, I will reference that. Okay, so nice and easy. We're just going to use a simple local database here. Of course, in real life, in your phpunit.xml file, you can override these to specify a custom testing database. But this should do the trick. So let's go ahead and cd into our project, migrate the database, and then run phpunit. So we got a 404 here, because there is no endpoint set up just yet. So that's our next step. We'll say right down here, if you visit impersonate,

Adding route and auth middleware2:19

migrate the database, and then run phpunit. So we got a 404 here, because there is no endpoint set up just yet. So that's our next step. We'll say right down here, if you visit impersonate/{user}, well, let's leave it at that, and then run it again. Okay, so now we got a 200 status, which means we hit the logic here. And what we wanted to say is, no, if you're a guest, and you try to hit this endpoint, you don't get access to anything here. But right now, they do. Okay, so let's do this. At the very least, as a very first step, we'll say, let's add a middleware, where you have to be authenticated. That's the very first step. Okay, let's run it. But now we're going to get a 500 error. And this can be a little confusing at first, why are we getting a 500? And what you might even do is go into your ExceptionHandler.php file. And if we scroll down to where we render it, if we just throw the exception so that

at first, why are we getting a 500? And what you might even do is go into your ExceptionsHandler file. And if we scroll down to where we render it, if we just throw the exception so that we can see it a little more easily, and run it again, you'll see that this is what we wanted, we get an UnauthenticatedException. So what's happening here is Laravel is trying to redirect you to the login page, but there is no login page yet. So that's why you get a 500 error. So let's do this, we're going to run php artisan make:auth to get some authentication scaffolding out of the box. So now if we go to our routes/web.php file, we do have all of these routes generated for us. Okay, so let's give it another shot. We run it, and now we do get green. Okay, but we're not done here yet. If you're not signed in, and you visit this endpoint, you should go to the login page. But let's imagine that you are signed in. So we'll say acting as this User. Well,

Restricting to admins4:45

signed in. So once again, you got access to this. Alright, so now we need some kind of custom, maybe a custom middleware to ensure that you are an admin. Or why don't we keep it really simple. And we'll say if you can administrate, something like that. So now, here's a little trick, you can go to your auth ServiceProvider, down to your boot method. And we'll just say Gate::before, accept the $user. And we'll then say if the $user is an administrator. And here, this is where you perform whatever logic you need to, to determine if the currently authenticated $user has permission to perform the action. Maybe you're checking their roles, maybe it's as simple as a type column in your users table, it doesn't matter, but you can add it here. So if the $user is an admin, then just immediately return true. Well, if I run it again, everything's going to fail. Now we get a 500 error. And that's because there is no isAdmin method on User. So we'll fix that.

then just immediately return true. Well, if I run it again, everything's going to fail. Now we get a 500 error. And that's because there is no isAdmin method on User. So we'll fix that this right down here. The logic I'm going to use is very simple. Maybe we'll have a type column. So we'll say return $this->type equals admin. And then we're going to go back to the migration to create the users table. And we'll add something like $table->enum('type', ['member', 'admin']);. And right now that can just be member or admin. Okay, so now that we've updated that table, let's refresh the migration. And now I'm going to rerun the test. Okay, so now it fails because we've added this new column. But in our ModelFactory class, where we define a factory for a User, we didn't specify this new column. So we'll say type, and by default, it'll be member. Okay, one more time. And we do get green. So that's great. That's passing now. Alright,

Implementing impersonation login6:23

user, we didn't specify this new column. So we'll say type, and by default, it'll be member. Okay, one more time. And we do get green. So that's great. That's passing now. Alright, so now we have a little more security, or a little more peace of mind. Let's write one more now to make sure that admins can in fact impersonate users. So we'll say admins can impersonate users. So here's our basic logic here. We're going to say, well, given we have a User, but also given we have an Administrator, and we'll do this, we'll say the type is admin. So create a User set the type to admin. And now we're going to say, well, if we get this URL, and if we are signed in as the Administrator, so acting as the admin, get this page. And then finally, our assertion will be that the authenticated User, the currently authenticated User's ID is equal to the User's ID. Okay, does that make sense? So we're saying sign in as the

finally, our assertion will be that the authenticated user, the currently authenticated user's id is equal to the user's id. Okay, does that make sense? So we're saying sign in as the administrator, but then visit this URL here to impersonate that user. And if we did everything right, well, then the currently authenticated user should not be the administrator, it should now be the user that we are impersonating. So let's go ahead and run that. And of course, it fails because we did not update the authenticated user. All right, let's get started. So we'll say right here, if we impersonate a user, we'll accept the user using route model binding. And then I'm just going to say Auth::login that user. And finally, return a redirect wherever you want to go to the homepage. Okay, let's run it again. And now we get green. So it's really that simple. Now alternatively, you have a login using id. So if you just have the id of the user, that would be

Refactoring tests and routes8:07

homepage. Okay, let's run it again. And now we get green. So it's really that simple. Now alternatively, you have a login using ID. So if you just have the ID of the User, that would be fine as well. So a couple little refactors we might want to do from our test end, we could hardcode this or maybe just something like this, let the model factory be responsible for that. So I want to add a state of admin. So put this User into the admin state. Now, you may not be familiar with this one. So I'll show you how to set it up. We've already defined the factory for a User. So I'm now just going to set the state for this User, the state will be called admin. And then for our overrides, I'm just going to set the type to admin. So yeah, this can be useful. We have our basic factory for a User. But now if I want a special state, which means the User is an administrator, I'm just going to override this. So now with that update, if we switch back, we can now call this

factory for a User. But now if I want a special state, which means the User is an administrator, I'm just going to override this. So now with that update, if we switch back, we can now call this states method and pass it through. So now if I give it another run, it's still going to return green. Okay, great. Now another little tweak we might want to make is you can see here we reference the same endpoint over and over. Why don't we use a named route for that? We'll say get route impersonate, and then pass through the User. And we still want that to work. So if we run it, it'll fail because we don't have that route. So I'm going to switch over to my routes/web.php file, and we'll name it impersonate. Okay, run it again. And now that returns green, which means down here, I can do the exact same thing, impersonate User, and then it will automatically fetch the ID off of it. Finally, let's see,

Browser verification9:41

run it again. And now that returns green, which means down here, I can do the exact same thing, impersonate User, and then it will automatically fetch the ID off of it. Finally, let's see, I can join these lines together, can I run it, and that returns green. That one looks good to me. And then up here, we can clean this up as well. Acting as a User, get that route, and then assert that we have a forbidden response. Yeah, that looks fine to me. Okay, so now at this point, we can test it out in the browser, but we already know that it'll work. Impersonation, I'm using Laravel Valet. So I have a URL for that. Okay, so I already have two different Users set up. So we have one for an administrator. So Stanley is our admin. But now he's going to impersonate the User with an ID of two. So we run it, we are redirected to the homepage. But if we go to the dashboard, we can now see that we have successfully signed in as Tamara in this case. Now that'll do

Returning to admin homework11:23

original admin account. And I'll leave that as homework. But yeah, it should mostly be the same. You'll set up an endpoint where you will, once again, auth log in your original administrator account. And if you can't hard code that, you can of course store your original administrator ID in the session and then just fetch it when you want to return back. But that might be a fun homework project for you. All right, so thanks for coming along.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟