Heads up! To view this whole video, sign in with your Courses Plus account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Knowing who someone is is just the first step. Now you need to make sure they have the ability to do the thing they want.
With this new auth method,
0:00
it's time to start thinking about
permissions, also known as authorization.
0:02
Authentication is all about connecting
some credentials to the incoming request.
0:06
The token you pass in the header maps
to the user that has that token.
0:10
That authenticates the request
if it's from another user.
0:14
Authorization though, is about
ensuring that the user has permission
0:17
to do the action they want to do.
0:20
Like CRUD operations or
even just accessing the API.
0:22
In REST framework, authorization or
0:26
permission checks will typically use the
authentication information and a couple of
0:28
request properties to decide if
the incoming request should be authorized.
0:32
This happens before your view's
methods are ever evaluated.
0:36
If the user isn't authorized,
0:39
REST framework will return either
a 403 Forbidden or a 401 Unauthorized,
0:41
depending on whether the user failed
authentication or authorization.
0:45
Remember when I first started the project?
0:49
I set the default permission class
to be IsAuthenticated or ReadOnly.
0:51
This permission means that you have to
provide a real, valid user to perform any
0:55
action that involves creating,
updating, or deleting data.
0:59
Anyone can read the data, though.
1:02
What other options do we have?
1:04
AllowAny is wide open and
allows anyone to do as they please.
1:06
IsAuthenticated requires
the user to be authenticated,
1:10
like by providing a valid token.
1:13
Once they're authenticated,
they can do anything they want.
1:15
IsAdminUser will only allow access to
1:17
authenticated users that have
been marked as is_staff.
1:20
And DjangoModelPermissions ties into
Django's standard model permissions.
1:24
Authorization will only be granted
to authenticated users who have
1:29
been assigned to the relevant
model permissions.
1:31
That's a lot to take in.
1:34
So check the teacher's notes for
1:36
documentation on all of the different
built in permissions classes.
1:37
What about setting permissions per view,
though?
1:40
Let me show you how to protect
a single specific view in workspaces.
1:43
So I've created a new user.
1:47
I want to show you a couple
of things about him here.
1:49
So this is a test user and
1:52
they are active, they're not staff,
they're not a super user.
1:56
But they do have one permission,
which is that they can add a course.
2:00
So that's all they can do.
2:05
They can just add courses.
2:06
They can't add users,
groups, anything like that.
2:07
They can't log in the admin, nothing.
2:09
All they can do is add a course.
2:12
So I've saved them and
I've already created a token for
2:15
them, which I've put here into the readme.
2:17
So let's see about handling
these permissions.
2:22
So I'm gonna hop back
over here to views.py and
2:25
I need to add an import,
so that I'll go here.
2:29
From rest_framework import permissions,
2:33
and I'm gonna focus on the Django
model permissions class.
2:38
So like I said, I've already added
the user with a single permission, so
2:42
I'm gonna take care of that, I'm gonna
address that in my CourseViewSet.
2:45
So where's CourseViewSet?
2:51
Here's CourseViewSet.
2:52
All right, so queryset,
serializers, OPQ, right?
2:52
So permission_classes and its tuple.
2:58
So permissions.DjangoModelPermissions.
3:03
All right, so what this specifies
is that for this view set,
3:08
ignore the default permissions and
care about Django model permissions.
3:13
So make sure that any users who are trying
to do things inside this CourseViewSet,
3:19
they have the right permissions
as far as Django is concerned.
3:24
Okay, and since that's a tuple,
I could provide more if I wanted to,
3:27
they'd fall back, so
on and so forth, right.
3:30
All right, let's go back over here to
postman, postman holds on to your URLs,
3:33
as you can see, and
also holds on to header and body content.
3:38
So I'm gonna make sure and
3:42
delete this authorization header,
because I don't want that to hang out.
3:44
And on the body, I'm gonna make sure and
3:50
delete all of my body content,
because I want to get rid of all of those.
3:52
Okay, so
I wanna make sure the get still works.
3:57
And Authentication credentials were not
provided, so all right, that didn't work.
4:00
I got a 401, it's unauthorized,
because the Django model permissions,
4:06
you have to have the add,
the create, the view, whatever.
4:09
All right, so, cool.
4:12
Don't have that permission,
so I can't just do that.
4:13
By the way, let me show you real
quick the permissions here.
4:16
If I come down here to user permissions,
let's just filter to course.
4:20
So you can see here this change,
delete, add?
4:25
You have to have change in
order to be able to view one.
4:27
So I'm not authed, so
my unauthenticated user does not have
4:31
permission to view one, so all right.
4:36
So let's come back over here to Headers,
and we'll put in Authorization
4:40
and Token, and
then my new user's token there and I
4:46
will hit send, and yeah, it's the add, the
add and the change both let you see them.
4:52
I've got the results back, which is cool.
4:57
I can create or I can view them,
so that's cool.
5:00
All right, so now I want to try and
create a new course.
5:04
So let's go over here and
change this to POST again.
5:09
Go back to Body, form-data.
5:13
Title is gonna be Django Basics.
5:16
And my other key here is url
5:21
https://teamtreehouse.com/library/django--
basics.
5:23
All right, now I have the create,
the add permission, right.
5:30
So I should be able to do this.
5:36
So if I hit send, great, I got back
a 201 and django-basics now exists.
5:37
All right, so cool,
I'm super glad that works.
5:43
This user shouldn't be able to
delete anything, so let's make sure.
5:47
So I'm gonna go to POST,
I'm gonna go to delete, and
5:49
I wanna try to delete number five,
which is the one I just created, right.
5:52
And I can get rid of this body data.
5:58
That's cool, okay, my header is still
in there, my authentication header.
6:01
I'm gonna try and
delete the one that I just created.
6:05
Send, and I don't have permission
to perform this action.
6:09
So that's great.
6:12
I only gave them the add permission.
6:12
So they can add new ones,
6:15
they can't update, they can't delete,
nothing like that.
6:16
All they can do is view them or
add new ones.
6:19
Awesome, if I was using my
super user's credentials,
6:21
I'd be able to do all of the stuff
because they're marked as the super user,
6:25
they automatically have all permissions.
6:28
So what if I'm faced with a permissions
check that isn't built in to REST
6:30
framework?
6:34
What if I only wanted to apply
a permission check to a specific action?
6:34
Situations like this come up all the time.
6:39
I don't want regular users
deleting courses, of course.
6:41
I only want super users
to have that ability.
6:45
How do I handle that?
6:47
So first of all, I need to create my own
permission class to perform this check.
6:49
So I'm gonna do it right up
here above the CourseViewSet.
6:53
You probably would do this
in a permissions.py or
6:58
something like that if you were doing this
on your own and you had more than one.
7:00
So, whatever.
7:03
Okay, so class IsSuperUser.
7:05
And this will extend
the permissions.BasePermission class.
7:08
Pretty much all of your permissions
are going to extend this one.
7:14
And the thing that we override
here is has_permission,
7:17
and self, request and view.
7:22
Those are the arguments that come in.
7:25
So this way I can check the = request and
make sure it's of a particular type,
7:27
I can check the request user,
I can do all this kind of stuff.
7:31
So if request.method = delete and
7:34
request.user.is_superuser, then
we're gonna return true,
7:39
otherwise we're gonna return false.
7:46
I could actually write
this a little shorter and
7:51
I could just return
request.method = delete and
7:53
request.user.is_superuser and it checks
to make sure those are both true,
7:55
but it's fine to make
it a little bit longer.
7:59
And now I need to apply this
class to my CourseViewSet class.
8:03
So this is a tuple,
let's add in a new one.
8:09
And I want to put my special one,
IsSuperUser,
8:12
above the DjangoModelPermissions one,
because I want that one checked first.
8:15
So if it is a delete and
they aren't a super user,
8:20
we just immediately kick it out, we don't
ever even go to DjangoModelPermissions.
8:23
Cool, right?
8:27
I want to change my user here.
8:28
And I'm gonna give them
the ability to delete a course.
8:31
I'm actually gonna give them,
they can change a course too, why not?
8:33
All right, so I'll save and continue
editing so that it just comes right back.
8:36
All right, now this user has
the ability to delete courses, right?
8:40
But they're still not a super user.
8:45
So let's see if this works.
8:47
So they can delete, hit Send,
8:49
they still cannot delete that one
because they're not a super user.
8:52
If, however, I go to my user,
8:57
this is why it's really handy having
those tokens saved somewhere.
8:59
Come over here to Headers, change that
token, hit Send, and it's gone, all right?
9:05
And if I was to do a get on courses,
I should only see four of them.
9:13
How does a super user not have
permission to perform that action?
9:19
You know what?
9:25
I think I need to change my thing here.
9:25
So let's do this.
9:33
There we go.
9:38
Okay, so
if it's delete then we come inside here.
9:39
That should fix it.
9:42
What is that doing?
9:50
Let's try that one.
10:04
Cool, there we go.
10:06
And just to make sure,
I will go back over to the other user.
10:09
And try to delete one of these.
10:21
Let's try to delete number four.
10:25
Cool, so the users have to have
permission or be a super user.
10:29
They can't just delete things
just because they want to.
10:33
It is possible to check
permissions at the object level
10:37
with the DjangoObjectPermissions class.
10:39
But this requires the use of
an object level permissions package
10:42
such django-guardian.
10:45
Check the teacher's notes section for
links to the permissions documentation and
10:46
the django-guardian package.
10:50
Since I haven't hit my rate limit yet,
10:52
I'll see you in the next video
to take a look at throttling.
10:54
You need to sign up for Treehouse in order to download course files.
Sign up