326 lines
8.0 KiB
Python
326 lines
8.0 KiB
Python
"""Authentication-related API schemas."""
|
|
|
|
from datetime import datetime
|
|
from typing import List, Optional
|
|
|
|
from ninja import ModelSchema, Schema
|
|
|
|
from apps.users.models import User
|
|
from apps.blog.permissions import can_access_blog_admin, can_review_blog_posts, can_write_blog_posts
|
|
from core.media import PREVIEW_VARIANT, THUMBNAIL_VARIANT, derivative_url
|
|
|
|
|
|
class UserRegistrationSchema(Schema):
|
|
username: str
|
|
mobile: str
|
|
code: str
|
|
password: str
|
|
email: Optional[str] = None
|
|
first_name: Optional[str] = None
|
|
last_name: Optional[str] = None
|
|
university: Optional[str] = None
|
|
student_id: Optional[str] = None
|
|
year_of_study: Optional[int] = None
|
|
major: Optional[str] = None
|
|
|
|
|
|
class UserLoginSchema(Schema):
|
|
identifier: str
|
|
password: str
|
|
|
|
|
|
class UserOtpLoginSchema(Schema):
|
|
mobile: str
|
|
code: str
|
|
|
|
|
|
class RegisterOtpVerifySchema(Schema):
|
|
mobile: str
|
|
code: str
|
|
|
|
|
|
class OtpSendSchema(Schema):
|
|
mobile: str
|
|
mode: str
|
|
|
|
|
|
class MobileOtpSendSchema(Schema):
|
|
mobile: str
|
|
|
|
|
|
class MobileOtpVerifySchema(Schema):
|
|
mobile: str
|
|
code: str
|
|
|
|
|
|
class GoogleFlowSchema(Schema):
|
|
flow: str
|
|
|
|
|
|
class GoogleClaimVerifySchema(Schema):
|
|
flow: str
|
|
code: str
|
|
|
|
|
|
class GoogleCompleteSchema(Schema):
|
|
flow: str
|
|
mobile: str
|
|
username: Optional[str] = None
|
|
student_id: Optional[str] = None
|
|
year_of_study: Optional[int] = None
|
|
major: Optional[str] = None
|
|
university: Optional[str] = None
|
|
first_name: Optional[str] = None
|
|
last_name: Optional[str] = None
|
|
|
|
|
|
class GoogleFlowResponseSchema(Schema):
|
|
status: str
|
|
email: Optional[str] = None
|
|
first_name: Optional[str] = None
|
|
last_name: Optional[str] = None
|
|
avatar_url: Optional[str] = None
|
|
resolution: Optional[str] = None
|
|
mobile: Optional[str] = None
|
|
mobile_hint: Optional[str] = None
|
|
detail: Optional[str] = None
|
|
access_token: Optional[str] = None
|
|
refresh_token: Optional[str] = None
|
|
|
|
|
|
class UserProfileSchema(ModelSchema):
|
|
profile_picture: Optional[str] = None
|
|
profile_picture_thumbnail_url: Optional[str] = None
|
|
profile_picture_preview_url: Optional[str] = None
|
|
student_id: Optional[str] = None
|
|
major: Optional[str] = None
|
|
university: Optional[str] = None
|
|
mobile: Optional[str] = None
|
|
requires_mobile_verification: bool
|
|
has_google_link: bool
|
|
can_access_blog_admin: bool
|
|
can_write_blog_posts: bool
|
|
can_review_blog_posts: bool
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = [
|
|
"id",
|
|
"username",
|
|
"email",
|
|
"mobile",
|
|
"first_name",
|
|
"last_name",
|
|
"student_id",
|
|
"year_of_study",
|
|
"major",
|
|
"university",
|
|
"bio",
|
|
"date_joined",
|
|
"is_email_verified",
|
|
"is_mobile_verified",
|
|
"is_active",
|
|
"is_staff",
|
|
"is_superuser",
|
|
"is_deleted",
|
|
"deleted_at",
|
|
]
|
|
|
|
@staticmethod
|
|
def resolve_major(obj):
|
|
return obj.get_major_display()
|
|
|
|
@staticmethod
|
|
def resolve_university(obj):
|
|
return obj.get_university_display()
|
|
|
|
@staticmethod
|
|
def resolve_requires_mobile_verification(obj):
|
|
return obj.requires_mobile_verification
|
|
|
|
@staticmethod
|
|
def resolve_has_google_link(obj):
|
|
return obj.has_google_link
|
|
|
|
@staticmethod
|
|
def resolve_can_access_blog_admin(obj):
|
|
return can_access_blog_admin(obj)
|
|
|
|
@staticmethod
|
|
def resolve_can_write_blog_posts(obj):
|
|
return can_write_blog_posts(obj)
|
|
|
|
@staticmethod
|
|
def resolve_can_review_blog_posts(obj):
|
|
return can_review_blog_posts(obj)
|
|
|
|
@staticmethod
|
|
def resolve_profile_picture(obj, context):
|
|
request = context["request"]
|
|
if obj.profile_picture and hasattr(obj.profile_picture, "url"):
|
|
return request.build_absolute_uri(obj.profile_picture.url)
|
|
return None
|
|
|
|
@staticmethod
|
|
def resolve_profile_picture_thumbnail_url(obj, context):
|
|
request = context["request"]
|
|
url = derivative_url(obj.profile_picture, THUMBNAIL_VARIANT)
|
|
return request.build_absolute_uri(url) if url else None
|
|
|
|
@staticmethod
|
|
def resolve_profile_picture_preview_url(obj, context):
|
|
request = context["request"]
|
|
url = derivative_url(obj.profile_picture, PREVIEW_VARIANT)
|
|
return request.build_absolute_uri(url) if url else None
|
|
|
|
|
|
class UserListSchema(ModelSchema):
|
|
major: Optional[str] = None
|
|
university: Optional[str] = None
|
|
mobile: Optional[str] = None
|
|
profile_picture: Optional[str] = None
|
|
profile_picture_thumbnail_url: Optional[str] = None
|
|
profile_picture_preview_url: Optional[str] = None
|
|
student_id: Optional[str] = None
|
|
year_of_study: Optional[int] = None
|
|
bio: Optional[str] = None
|
|
is_email_verified: bool
|
|
is_mobile_verified: bool
|
|
is_deleted: bool
|
|
deleted_at: Optional[datetime] = None
|
|
can_access_blog_admin: bool
|
|
can_write_blog_posts: bool
|
|
can_review_blog_posts: bool
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = [
|
|
"id",
|
|
"username",
|
|
"email",
|
|
"mobile",
|
|
"first_name",
|
|
"last_name",
|
|
"student_id",
|
|
"year_of_study",
|
|
"bio",
|
|
"is_active",
|
|
"is_staff",
|
|
"is_superuser",
|
|
"date_joined",
|
|
"major",
|
|
"university",
|
|
"is_email_verified",
|
|
"is_mobile_verified",
|
|
"is_deleted",
|
|
"deleted_at",
|
|
]
|
|
|
|
@staticmethod
|
|
def resolve_major(obj):
|
|
return obj.get_major_display()
|
|
|
|
@staticmethod
|
|
def resolve_university(obj):
|
|
return obj.get_university_display()
|
|
|
|
@staticmethod
|
|
def resolve_can_access_blog_admin(obj):
|
|
return can_access_blog_admin(obj)
|
|
|
|
@staticmethod
|
|
def resolve_can_write_blog_posts(obj):
|
|
return can_write_blog_posts(obj)
|
|
|
|
@staticmethod
|
|
def resolve_can_review_blog_posts(obj):
|
|
return can_review_blog_posts(obj)
|
|
|
|
@staticmethod
|
|
def resolve_profile_picture(obj, context):
|
|
request = context["request"]
|
|
if obj.profile_picture and hasattr(obj.profile_picture, "url"):
|
|
return request.build_absolute_uri(obj.profile_picture.url)
|
|
return None
|
|
|
|
@staticmethod
|
|
def resolve_profile_picture_thumbnail_url(obj, context):
|
|
request = context["request"]
|
|
url = derivative_url(obj.profile_picture, THUMBNAIL_VARIANT)
|
|
return request.build_absolute_uri(url) if url else None
|
|
|
|
@staticmethod
|
|
def resolve_profile_picture_preview_url(obj, context):
|
|
request = context["request"]
|
|
url = derivative_url(obj.profile_picture, PREVIEW_VARIANT)
|
|
return request.build_absolute_uri(url) if url else None
|
|
|
|
|
|
class AuthorizationRoleSchema(Schema):
|
|
key: str
|
|
label: str
|
|
description: str
|
|
enabled: bool = False
|
|
locked: bool = False
|
|
|
|
|
|
class UserAuthorizationSchema(Schema):
|
|
id: int
|
|
username: str
|
|
email: Optional[str] = None
|
|
mobile: Optional[str] = None
|
|
first_name: str
|
|
last_name: str
|
|
is_active: bool
|
|
is_staff: bool
|
|
is_superuser: bool
|
|
groups: List[str]
|
|
roles: List[AuthorizationRoleSchema]
|
|
|
|
|
|
class UserAuthorizationUpdateSchema(Schema):
|
|
is_staff: bool = False
|
|
groups: List[str] = []
|
|
|
|
|
|
class UserUpdateSchema(Schema):
|
|
email: Optional[str] = None
|
|
first_name: Optional[str] = None
|
|
last_name: Optional[str] = None
|
|
bio: Optional[str] = None
|
|
year_of_study: Optional[int] = None
|
|
major: Optional[str] = None
|
|
university: Optional[str] = None
|
|
student_id: Optional[str] = None
|
|
|
|
|
|
class TokenSchema(Schema):
|
|
access_token: str
|
|
refresh_token: str
|
|
token_type: str = "bearer"
|
|
|
|
|
|
class TokenRefreshIn(Schema):
|
|
refresh_token: str
|
|
|
|
|
|
class PasswordResetSchema(Schema):
|
|
mobile: str
|
|
code: str
|
|
new_password: str
|
|
|
|
|
|
class UsernameCheckSchema(Schema):
|
|
exists: bool
|
|
|
|
|
|
class MobileLookupSchema(Schema):
|
|
exists: bool
|
|
has_password: bool
|
|
|
|
|
|
class OtpSendResponseSchema(Schema):
|
|
message: str
|
|
expires_in_seconds: int
|
|
expires_at: datetime
|