2020-12-27 16:54:06 +00:00
|
|
|
import dataclasses
|
|
|
|
import typing as t
|
2020-12-29 15:52:08 +00:00
|
|
|
from typing_extensions import Literal
|
2020-12-28 11:56:53 +00:00
|
|
|
import msgpack
|
2020-12-28 12:26:44 +00:00
|
|
|
import base64
|
2020-12-27 16:54:06 +00:00
|
|
|
|
2020-12-28 10:12:00 +00:00
|
|
|
from fastapi import status, Query, Depends
|
2020-12-28 07:25:28 +00:00
|
|
|
from pydantic import BaseModel as PyBaseModel
|
2020-12-27 16:34:23 +00:00
|
|
|
|
2020-12-29 15:18:09 +00:00
|
|
|
from django.db.models import Model, QuerySet
|
2020-12-27 16:34:23 +00:00
|
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
|
|
|
2022-05-08 14:32:29 +00:00
|
|
|
from etebase_server.django import app_settings
|
|
|
|
from etebase_server.django.models import AccessLevels
|
2022-05-08 13:10:48 +00:00
|
|
|
from etebase_server.myauth.models import UserType, get_typed_user_model
|
2020-12-27 19:08:00 +00:00
|
|
|
|
2020-12-28 08:00:35 +00:00
|
|
|
from .exceptions import HttpError, HttpErrorOut
|
2020-12-27 16:34:23 +00:00
|
|
|
|
2020-12-29 11:22:36 +00:00
|
|
|
User = get_typed_user_model()
|
2020-12-27 16:54:06 +00:00
|
|
|
|
2020-12-29 15:52:08 +00:00
|
|
|
Prefetch = Literal["auto", "medium"]
|
2020-12-27 16:54:06 +00:00
|
|
|
PrefetchQuery = Query(default="auto")
|
|
|
|
|
|
|
|
|
2020-12-29 15:18:09 +00:00
|
|
|
T = t.TypeVar("T", bound=Model, covariant=True)
|
|
|
|
|
|
|
|
|
2020-12-28 07:25:28 +00:00
|
|
|
class BaseModel(PyBaseModel):
|
|
|
|
class Config:
|
|
|
|
json_encoders = {
|
|
|
|
bytes: lambda x: x,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-27 16:54:06 +00:00
|
|
|
@dataclasses.dataclass
|
|
|
|
class Context:
|
2020-12-29 11:22:36 +00:00
|
|
|
user: t.Optional[UserType]
|
2020-12-27 16:54:06 +00:00
|
|
|
prefetch: t.Optional[Prefetch]
|
|
|
|
|
2020-12-27 16:34:23 +00:00
|
|
|
|
2020-12-29 15:18:09 +00:00
|
|
|
def get_object_or_404(queryset: QuerySet[T], **kwargs) -> T:
|
2020-12-27 16:34:23 +00:00
|
|
|
try:
|
|
|
|
return queryset.get(**kwargs)
|
|
|
|
except ObjectDoesNotExist as e:
|
2020-12-28 07:51:27 +00:00
|
|
|
raise HttpError("does_not_exist", str(e), status_code=status.HTTP_404_NOT_FOUND)
|
2020-12-27 19:08:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
def is_collection_admin(collection, user):
|
|
|
|
member = collection.members.filter(user=user).first()
|
|
|
|
return (member is not None) and (member.accessLevel == AccessLevels.ADMIN)
|
2020-12-28 08:00:35 +00:00
|
|
|
|
|
|
|
|
2021-01-04 09:56:17 +00:00
|
|
|
def msgpack_encode(content) -> bytes:
|
2020-12-29 13:44:52 +00:00
|
|
|
ret = msgpack.packb(content, use_bin_type=True)
|
|
|
|
assert ret is not None
|
|
|
|
return ret
|
2020-12-28 11:56:53 +00:00
|
|
|
|
|
|
|
|
2021-01-04 09:56:17 +00:00
|
|
|
def msgpack_decode(content: bytes):
|
2020-12-28 11:56:53 +00:00
|
|
|
return msgpack.unpackb(content, raw=False)
|
|
|
|
|
|
|
|
|
2021-01-04 09:56:17 +00:00
|
|
|
def b64encode(value: bytes):
|
2020-12-28 12:26:44 +00:00
|
|
|
return base64.urlsafe_b64encode(value).decode("ascii").strip("=")
|
|
|
|
|
|
|
|
|
2021-01-04 09:56:17 +00:00
|
|
|
def b64decode(data: str):
|
2020-12-28 12:26:44 +00:00
|
|
|
data += "=" * ((4 - len(data) % 4) % 4)
|
|
|
|
return base64.urlsafe_b64decode(data)
|
|
|
|
|
|
|
|
|
2021-01-27 07:35:36 +00:00
|
|
|
def get_user_username_email_kwargs(username: str):
|
|
|
|
field_name = User.EMAIL_FIELD if "@" in username else User.USERNAME_FIELD
|
|
|
|
return {field_name + "__iexact": username.lower()}
|
|
|
|
|
|
|
|
|
2020-12-28 10:12:00 +00:00
|
|
|
PERMISSIONS_READ = [Depends(x) for x in app_settings.API_PERMISSIONS_READ]
|
|
|
|
PERMISSIONS_READWRITE = PERMISSIONS_READ + [Depends(x) for x in app_settings.API_PERMISSIONS_WRITE]
|
|
|
|
|
|
|
|
|
2020-12-28 08:00:35 +00:00
|
|
|
response_model_dict = {"model": HttpErrorOut}
|
2020-12-28 13:26:34 +00:00
|
|
|
permission_responses: t.Dict[t.Union[int, str], t.Dict[str, t.Any]] = {
|
|
|
|
401: response_model_dict,
|
|
|
|
403: response_model_dict,
|
|
|
|
}
|