1
0
mirror of https://github.com/etesync/server synced 2024-11-25 18:28:46 +00:00
etesync-server/etebase_server/fastapi/routers/member.py

112 lines
3.6 KiB
Python
Raw Permalink Normal View History

2020-12-27 19:32:48 +00:00
import typing as t
2020-12-27 19:47:30 +00:00
from django.db import transaction
2020-12-27 19:32:48 +00:00
from django.db.models import QuerySet
2020-12-28 07:04:45 +00:00
from fastapi import APIRouter, Depends, status
2020-12-27 19:32:48 +00:00
from etebase_server.django import models
from etebase_server.myauth.models import UserType, get_typed_user_model
2024-06-08 21:51:44 +00:00
from ..db_hack import django_db_cleanup_decorator
2024-06-09 00:17:02 +00:00
from ..msgpack import MsgpackResponse, MsgpackRoute
from ..stoken_handler import filter_by_stoken_and_limit
2024-06-08 21:51:44 +00:00
from ..utils import PERMISSIONS_READ, PERMISSIONS_READWRITE, BaseModel, get_object_or_404, permission_responses
from .authentication import get_authenticated_user
2020-12-28 07:04:45 +00:00
from .collection import get_collection, verify_collection_admin
2020-12-27 19:32:48 +00:00
2020-12-29 11:22:36 +00:00
User = get_typed_user_model()
2020-12-28 08:00:35 +00:00
member_router = APIRouter(route_class=MsgpackRoute, responses=permission_responses)
2020-12-29 15:18:09 +00:00
MemberQuerySet = QuerySet[models.CollectionMember]
default_queryset: MemberQuerySet = models.CollectionMember.objects.all()
2020-12-27 19:32:48 +00:00
@django_db_cleanup_decorator
2020-12-29 15:18:09 +00:00
def get_queryset(collection: models.Collection = Depends(get_collection)) -> MemberQuerySet:
return default_queryset.filter(collection=collection)
@django_db_cleanup_decorator
2020-12-29 15:18:09 +00:00
def get_member(username: str, queryset: MemberQuerySet = Depends(get_queryset)) -> models.CollectionMember:
return get_object_or_404(queryset, user__username__iexact=username)
2020-12-27 19:32:48 +00:00
2020-12-27 19:47:30 +00:00
class CollectionMemberModifyAccessLevelIn(BaseModel):
accessLevel: models.AccessLevels
2020-12-27 19:32:48 +00:00
class CollectionMemberOut(BaseModel):
username: str
accessLevel: models.AccessLevels
class Config:
2024-06-08 22:10:34 +00:00
from_attributes = True
2020-12-27 19:32:48 +00:00
@classmethod
def from_orm(cls: t.Type["CollectionMemberOut"], obj: models.CollectionMember) -> "CollectionMemberOut":
return cls(username=obj.user.username, accessLevel=obj.accessLevel)
class MemberListResponse(BaseModel):
data: t.List[CollectionMemberOut]
iterator: t.Optional[str] = None
2020-12-27 19:32:48 +00:00
done: bool
@member_router.get(
"/member/", response_model=MemberListResponse, dependencies=[Depends(verify_collection_admin), *PERMISSIONS_READ]
)
2020-12-27 19:32:48 +00:00
def member_list(
iterator: t.Optional[str] = None,
limit: int = 50,
2020-12-29 15:18:09 +00:00
queryset: MemberQuerySet = Depends(get_queryset),
2020-12-27 19:32:48 +00:00
):
queryset = queryset.order_by("id")
result, new_stoken_obj, done = filter_by_stoken_and_limit(
iterator, limit, queryset, models.CollectionMember.stoken_annotation
)
new_stoken = new_stoken_obj and new_stoken_obj.uid
2024-06-09 00:17:02 +00:00
return MsgpackResponse(
MemberListResponse(
data=[CollectionMemberOut.from_orm(item) for item in result],
iterator=new_stoken,
done=done,
)
2020-12-27 19:32:48 +00:00
)
2020-12-28 07:04:45 +00:00
@member_router.delete(
2020-12-28 07:11:35 +00:00
"/member/{username}/",
2020-12-27 20:56:23 +00:00
status_code=status.HTTP_204_NO_CONTENT,
dependencies=[Depends(verify_collection_admin), *PERMISSIONS_READWRITE],
2020-12-27 20:56:23 +00:00
)
2020-12-27 19:32:48 +00:00
def member_delete(
obj: models.CollectionMember = Depends(get_member),
2020-12-27 19:32:48 +00:00
):
obj.revoke()
2020-12-28 07:04:45 +00:00
@member_router.patch(
2020-12-28 07:11:35 +00:00
"/member/{username}/",
2020-12-27 20:56:23 +00:00
status_code=status.HTTP_204_NO_CONTENT,
dependencies=[Depends(verify_collection_admin), *PERMISSIONS_READWRITE],
2020-12-27 20:56:23 +00:00
)
2020-12-27 19:47:30 +00:00
def member_patch(
data: CollectionMemberModifyAccessLevelIn,
instance: models.CollectionMember = Depends(get_member),
2020-12-27 19:47:30 +00:00
):
with transaction.atomic():
# We only allow updating accessLevel
if instance.accessLevel != data.accessLevel:
instance.stoken = models.Stoken.objects.create()
instance.accessLevel = data.accessLevel
instance.save()
@member_router.post("/member/leave/", status_code=status.HTTP_204_NO_CONTENT, dependencies=PERMISSIONS_READ)
2020-12-29 11:22:36 +00:00
def member_leave(
user: UserType = Depends(get_authenticated_user), collection: models.Collection = Depends(get_collection)
):
2020-12-27 19:32:48 +00:00
obj = get_object_or_404(collection.members, user=user)
obj.revoke()