Permissions
Strawberry provides a way to define permissions for your fields. This is useful if you want to restrict access to certain fields based on the user that is making the request.
Subscribing to a podcast
Let's see how this work by creating a new mutation that allows the current user
to subscribe to a podcast. In api/podcasts/mutations.py
, add the following
code:
import strawberry
from strawberry.types import Info
from api.authentication.permissions import IsAuthenticated
from api.views import Context
from db import data
@strawberry.type
class PodcastsMutation:
@strawberry.mutation(permission_classes=[IsAuthenticated])
async def subscribe_to_podcast(
self, info: Info[Context, None], id: strawberry.ID
) -> bool:
request = info.context["request"]
db_podcast = await data.find_podcast_by_id(id)
if not db_podcast:
return False
user = await request.get_user()
try:
await data.subscribe_to_podcast(user, db_podcast)
except data.AlreadySubscribedToPodcastError:
return False
return True
This mutation requires the user to be authenticated, otherwise it will return an
error. If the user is authenticated, we try to subscribe the user to the
podcast. If the user is already subscribed to the podcast (or the podcast
doesn't exist), we return False
, otherwise we return True
.
Note: this API design is not ideal, we'll see how to improve it in the next section.
Permissions classes
The permission we used above is already implemented, but let's see how it work anyway:
from typing import Any
from strawberry.permission import BasePermission
from strawberry.types import Info
from api.views import Context
class IsAuthenticated(BasePermission):
message = "User is not authenticated"
async def has_permission(
self, source: Any, info: Info[Context, None], **kwargs
) -> bool:
user = await info.context["request"].get_user()
return user.is_authenticated
The API is inspired by Django Rest Framework. There's a method called
has_permission
that received the source
, info
and kwargs
and returns a
boolean.
Source is parent of the field that is being resolved, info is the info object and kwargs are the arguments passed to the field.
I personally don't use permission classes for many things, I mostly use them for making sure the user is authenticated and that's it. You can use them for more complex things, but it is also worth making sure that the same logic is also implemented in data layer.