Skip to content

Commit

Permalink
add more API tests
Browse files Browse the repository at this point in the history
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
  • Loading branch information
BeryJu committed Oct 10, 2023
1 parent e935354 commit f1845b0
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 7 deletions.
12 changes: 9 additions & 3 deletions authentik/core/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ def create_test_flow(
)


def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test-admin user"""
def create_test_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test user"""
uid = generate_id(20) if not name else name
group = Group.objects.create(name=uid, is_superuser=True)
kwargs.setdefault("email", f"{uid}@goauthentik.io")
kwargs.setdefault("username", uid)
user: User = User.objects.create(
Expand All @@ -33,6 +32,13 @@ def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
)
user.set_password(uid)
user.save()
return user


def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test-admin user"""
user = create_test_user(name, **kwargs)
group = Group.objects.create(name=user.name or name, is_superuser=True)
group.users.add(user)
return user

Expand Down
11 changes: 11 additions & 0 deletions authentik/rbac/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"""RBAC models"""
from typing import Optional
from uuid import uuid4

from django.db import models
from django.db.transaction import atomic
from django.utils.translation import gettext_lazy as _
from guardian.shortcuts import assign_perm
from rest_framework.serializers import BaseSerializer

from authentik.lib.models import SerializerModel
Expand All @@ -27,6 +30,14 @@ class Role(SerializerModel):
# name field has the same constraints as the group model
name = models.TextField(max_length=150, unique=True)

def assign_permission(self, *perms: str, obj: Optional[models.Model] = None):
"""Assign permission to role, can handle multiple permissions,
but when assigning multiple permissions to an object the permissions
must all belong to the object given"""
with atomic():
for perm in perms:
assign_perm(perm, self.group, obj)

@property
def serializer(self) -> type[BaseSerializer]:
from authentik.rbac.api.roles import RoleSerializer
Expand Down
2 changes: 1 addition & 1 deletion authentik/rbac/permissions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""RBAC Permissions"""
from rest_framework.permissions import DjangoObjectPermissions
from django.db.models import Model
from rest_framework.permissions import DjangoObjectPermissions
from rest_framework.request import Request


Expand Down
169 changes: 169 additions & 0 deletions authentik/rbac/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
"""RBAC role tests"""
from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework.utils.encoders import JSONEncoder

from authentik.core.models import Group
from authentik.core.tests.utils import create_test_admin_user, create_test_user
from authentik.lib.generators import generate_id
from authentik.rbac.models import Role
from authentik.stages.invitation.models import Invitation


class TestAPIPerms(APITestCase):
"""Test API Permission and filtering"""

def setUp(self) -> None:
self.superuser = create_test_admin_user()

self.user = create_test_user()
self.role = Role.objects.create(name=generate_id())
self.group = Group.objects.create(name=generate_id())
self.group.roles.add(self.role)
self.group.users.add(self.user)

def test_list_simple(self):
"""Test list (single object, role has global permission)"""
self.client.force_login(self.user)
self.role.assign_permission("authentik_stages_invitation.view_invitation")

Invitation.objects.all().delete()
inv = Invitation.objects.create(
name=generate_id(),
created_by=self.superuser,
)
res = self.client.get(reverse("authentik_api:invitation-list"))
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content.decode(),
{
"pagination": {
"next": 0,
"previous": 0,
"count": 1,
"current": 1,
"total_pages": 1,
"start_index": 1,
"end_index": 1,
},
"results": [
{
"pk": str(inv.pk),
"name": inv.name,
"expires": JSONEncoder().default(inv.expires),
"fixed_data": {},
"created_by": {
"pk": self.superuser.pk,
"username": f"{self.superuser.username}",
"name": f"{self.superuser.username}",
"is_active": True,
"last_login": None,
"email": f"{self.superuser.username}@goauthentik.io",
"attributes": {},
"uid": self.superuser.uid,
},
"single_use": False,
"flow": None,
"flow_obj": None,
}
],
},
)

def test_list_object_perm(self):
"""Test list"""
self.client.force_login(self.user)

Invitation.objects.all().delete()
Invitation.objects.create(
name=generate_id(),
created_by=self.superuser,
)
inv2 = Invitation.objects.create(
name=generate_id(),
created_by=self.superuser,
)
self.role.assign_permission("authentik_stages_invitation.view_invitation", obj=inv2)

res = self.client.get(reverse("authentik_api:invitation-list"))
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content.decode(),
{
"pagination": {
"next": 0,
"previous": 0,
"count": 1,
"current": 1,
"total_pages": 1,
"start_index": 1,
"end_index": 1,
},
"results": [
{
"pk": str(inv2.pk),
"name": inv2.name,
"expires": JSONEncoder().default(inv2.expires),
"fixed_data": {},
"created_by": {
"pk": self.superuser.pk,
"username": f"{self.superuser.username}",
"name": f"{self.superuser.username}",
"is_active": True,
"last_login": None,
"email": f"{self.superuser.username}@goauthentik.io",
"attributes": {},
"uid": self.superuser.uid,
},
"single_use": False,
"flow": None,
"flow_obj": None,
}
],
},
)

def test_list_denied(self):
"""Test list without adding permission"""
self.client.force_login(self.user)

res = self.client.get(reverse("authentik_api:invitation-list"))
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content.decode(),
{
"pagination": {
"count": 0,
"current": 1,
"end_index": 0,
"next": 0,
"previous": 0,
"start_index": 0,
"total_pages": 1,
},
"results": [],
},
)

def test_create_simple(self):
"""Test create with permission"""
self.client.force_login(self.user)
self.role.assign_permission("authentik_stages_invitation.add_invitation")
res = self.client.post(
reverse("authentik_api:invitation-list"),
data={
"name": generate_id(),
},
)
self.assertEqual(res.status_code, 201)

def test_create_simple_denied(self):
"""Test create without assigning permission"""
self.client.force_login(self.user)
res = self.client.post(
reverse("authentik_api:invitation-list"),
data={
"name": generate_id(),
},
)
self.assertEqual(res.status_code, 403)
5 changes: 2 additions & 3 deletions authentik/rbac/tests/test_roles.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""RBAC role tests"""
from guardian.shortcuts import assign_perm
from rest_framework.test import APITestCase

from authentik.core.models import Group
Expand All @@ -16,7 +15,7 @@ def test_role_create(self):
user = create_test_admin_user()
group = Group.objects.create(name=generate_id())
role = Role.objects.create(name=generate_id())
assign_perm("authentik_core.view_application", role.group)
role.assign_permission("authentik_core.view_application")
group.roles.add(role)
group.users.add(user)
self.assertEqual(list(role.group.user_set.all()), [user])
Expand All @@ -27,7 +26,7 @@ def test_role_create_remove(self):
user = create_test_admin_user()
group = Group.objects.create(name=generate_id())
role = Role.objects.create(name=generate_id())
assign_perm("authentik_core.view_application", role.group)
role.assign_permission("authentik_core.view_application")
group.roles.add(role)
group.users.add(user)
self.assertEqual(list(role.group.user_set.all()), [user])
Expand Down

0 comments on commit f1845b0

Please sign in to comment.