adapt CanAccessLookup to api key auth

This commit is contained in:
imperosol 2025-05-20 21:04:49 +02:00
parent 1ff364e4a8
commit 65d43caf15
10 changed files with 75 additions and 9 deletions

View File

@ -8,7 +8,7 @@ from ninja_extra.schemas import PaginatedResponseSchema
from apikey.auth import ApiKeyAuth
from club.models import Club
from club.schemas import ClubSchema
from club.schemas import ClubSchema, SimpleClubSchema
from core.auth.api_permissions import CanAccessLookup, HasPerm
@ -16,8 +16,10 @@ from core.auth.api_permissions import CanAccessLookup, HasPerm
class ClubController(ControllerBase):
@route.get(
"/search",
response=PaginatedResponseSchema[ClubSchema],
response=PaginatedResponseSchema[SimpleClubSchema],
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[CanAccessLookup],
url_name="search_club",
)
@paginate(PageNumberPaginationExtra, page_size=50)
def search_club(self, search: Annotated[str, MinLen(1)]):
@ -28,6 +30,7 @@ class ClubController(ControllerBase):
response=ClubSchema,
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[HasPerm("club.view_club")],
url_name="fetch_club",
)
def fetch_club(self, club_id: int):
return self.get_object_or_exception(

View File

@ -1,16 +1,21 @@
import pytest
from django.test import Client
from django.urls import reverse
from model_bakery import baker
from ninja_extra.testing import TestClient
from pytest_django.asserts import assertNumQueries
from club.api import ClubController
from club.models import Club, Membership
from core.baker_recipes import subscriber_user
@pytest.mark.django_db
def test_fetch_club():
def test_fetch_club(client: Client):
club = baker.make(Club)
baker.make(Membership, club=club, _quantity=10, _bulk_create=True)
with assertNumQueries(3):
res = TestClient(ClubController).get(f"/{club.id}")
user = subscriber_user.make()
client.force_login(user)
with assertNumQueries(7):
# - 4 queries for authentication
# - 3 queries for the actual data
res = client.get(reverse("api:fetch_club", kwargs={"club_id": club.id}))
assert res.status_code == 200

View File

@ -5,11 +5,13 @@ from django.conf import settings
from django.db.models import F
from django.http import HttpResponse
from ninja import File, Query
from ninja.security import SessionAuth
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.exceptions import PermissionDenied
from ninja_extra.pagination import PageNumberPaginationExtra
from ninja_extra.schemas import PaginatedResponseSchema
from apikey.auth import ApiKeyAuth
from club.models import Mailing
from core.auth.api_permissions import CanAccessLookup, CanView, HasPerm
from core.models import Group, QuickUploadImage, SithFile, User
@ -90,6 +92,7 @@ class SithFileController(ControllerBase):
@route.get(
"/search",
response=PaginatedResponseSchema[SithFileSchema],
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[CanAccessLookup],
)
@paginate(PageNumberPaginationExtra, page_size=50)
@ -102,6 +105,7 @@ class GroupController(ControllerBase):
@route.get(
"/search",
response=PaginatedResponseSchema[GroupSchema],
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[CanAccessLookup],
)
@paginate(PageNumberPaginationExtra, page_size=50)

View File

@ -189,4 +189,4 @@ class IsLoggedInCounter(BasePermission):
return Counter.objects.filter(token=token).exists()
CanAccessLookup = IsOldSubscriber | IsRoot | IsLoggedInCounter
CanAccessLookup = IsLoggedInCounter | HasPerm("core.access_lookup")

View File

@ -805,6 +805,8 @@ class Command(BaseCommand):
"add_peoplepicturerelation",
"add_page",
"add_quickuploadimage",
"view_club",
"access_lookup",
]
)
)

View File

@ -0,0 +1,28 @@
# Generated by Django 5.2 on 2025-05-20 17:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("core", "0045_quickuploadimage")]
operations = [
migrations.CreateModel(
name="GlobalPermissionRights",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
options={
"permissions": [("access_lookup", "Can access any lookup in the sith")],
"managed": False,
"default_permissions": [],
},
),
]

View File

@ -754,6 +754,23 @@ class UserBan(models.Model):
return f"Ban of user {self.user.id}"
class GlobalPermissionRights(models.Model):
"""Little hack to have permissions not linked to a specific db table."""
class Meta:
# No database table creation or deletion
# operations will be performed for this model.
managed = False
# disable "add", "change", "delete" and "view" default permissions
default_permissions = []
permissions = [("access_lookup", "Can access any lookup in the sith")]
def __str__(self):
return self.__class__.__name__
class Preferences(models.Model):
user = models.OneToOneField(
User, related_name="_preferences", on_delete=models.CASCADE

View File

@ -16,10 +16,12 @@ from django.conf import settings
from django.db.models import F
from django.shortcuts import get_object_or_404
from ninja import Query
from ninja.security import SessionAuth
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.pagination import PageNumberPaginationExtra
from ninja_extra.schemas import PaginatedResponseSchema
from apikey.auth import ApiKeyAuth
from core.auth.api_permissions import CanAccessLookup, CanView, IsInGroup, IsRoot
from counter.models import Counter, Product, ProductType
from counter.schemas import (
@ -62,6 +64,7 @@ class CounterController(ControllerBase):
@route.get(
"/search",
response=PaginatedResponseSchema[SimplifiedCounterSchema],
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[CanAccessLookup],
)
@paginate(PageNumberPaginationExtra, page_size=50)
@ -74,6 +77,7 @@ class ProductController(ControllerBase):
@route.get(
"/search",
response=PaginatedResponseSchema[SimpleProductSchema],
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[CanAccessLookup],
)
@paginate(PageNumberPaginationExtra, page_size=50)

View File

@ -68,7 +68,7 @@ class TestUVSearch(TestCase):
def test_permissions(self):
# Test with anonymous user
response = self.client.get(self.url)
assert response.status_code == 403
assert response.status_code == 401
# Test with not subscribed user
self.client.force_login(baker.make(User))

View File

@ -5,6 +5,7 @@ from django.core.exceptions import ValidationError
from django.db.models import F
from django.urls import reverse
from ninja import Body, File, Query
from ninja.security import SessionAuth
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.exceptions import NotFound, PermissionDenied
from ninja_extra.pagination import PageNumberPaginationExtra
@ -12,6 +13,7 @@ from ninja_extra.permissions import IsAuthenticated
from ninja_extra.schemas import PaginatedResponseSchema
from pydantic import NonNegativeInt
from apikey.auth import ApiKeyAuth
from core.auth.api_permissions import (
CanAccessLookup,
CanEdit,
@ -53,6 +55,7 @@ class AlbumController(ControllerBase):
@route.get(
"/autocomplete-search",
response=PaginatedResponseSchema[AlbumAutocompleteSchema],
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[CanAccessLookup],
)
@paginate(PageNumberPaginationExtra, page_size=50)