feat: add avatars
This commit is contained in:
@@ -1,27 +1,50 @@
|
||||
from fastapi import APIRouter, Request, Depends
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import ORJSONResponse
|
||||
from starlette import status
|
||||
from src.application.commands import SetPhoneCommand, SetEncryptedMnemonicStartCommand, SetEncryptedMnemonicCompleteCommand, UpdateBankDetailsStartCommand, UpdateBankDetailsCompleteCommand, ChangePasswordStartCommand, ChangePasswordCompleteCommand, ChangeEmailStartCommand, ChangeEmailConfirmOldCommand, ChangeEmailCompleteCommand
|
||||
from src.application.commands import SetPhoneCommand, SetAvatarCommand
|
||||
from src.application.domain.dto import AuthContext
|
||||
from src.presentation.decorators import require_access_token
|
||||
from src.presentation.dependencies import (
|
||||
get_set_avatar_command,
|
||||
get_set_phone_command,
|
||||
get_set_encrypted_mnemonic_start_command,
|
||||
get_set_encrypted_mnemonic_complete_command,
|
||||
get_update_bank_details_start_command,
|
||||
get_update_bank_details_complete_command,
|
||||
get_change_password_start_command,
|
||||
get_change_password_complete_command,
|
||||
get_change_email_start_command,
|
||||
get_change_email_confirm_old_command,
|
||||
get_change_email_complete_command,
|
||||
)
|
||||
from src.presentation.schemas import SetPhoneRequest, EncryptedMnemonicConfirmRequest, BankConfirmRequest, ChangePasswordConfirmRequest, ChangeEmailConfirmOldRequest, ChangeEmailCompleteRequest
|
||||
from src.presentation.schemas import SetAvatarRequest, SetPhoneRequest
|
||||
from src.presentation.schemas.api_errors import ApiErrorPayload, ApiValidationErrorsPayload
|
||||
from src.presentation.schemas.me_public import SetAvatarPublicResponse
|
||||
from src.presentation.serializers import me_user_public
|
||||
|
||||
|
||||
account_settings_router = APIRouter(prefix='/settings')
|
||||
|
||||
|
||||
_SET_AVATAR_ERROR_RESPONSES: dict[int, dict[str, object]] = {
|
||||
status.HTTP_400_BAD_REQUEST: {
|
||||
'description': 'Битый или неподдерживаемый формат изображения, либо Base64 ошибочный.',
|
||||
'model': ApiErrorPayload,
|
||||
},
|
||||
status.HTTP_401_UNAUTHORIZED: {
|
||||
'description': 'Не передан или неверен access token.',
|
||||
'model': ApiErrorPayload,
|
||||
},
|
||||
status.HTTP_404_NOT_FOUND: {
|
||||
'description': 'Учётная запись не найдена.',
|
||||
'model': ApiErrorPayload,
|
||||
},
|
||||
status.HTTP_422_UNPROCESSABLE_ENTITY: {
|
||||
'description': 'Тело запроса не соответствует схеме (например, неверный Base64 или превышен размер).',
|
||||
'model': ApiValidationErrorsPayload,
|
||||
},
|
||||
status.HTTP_500_INTERNAL_SERVER_ERROR: {
|
||||
'description': 'Внутренняя ошибка сервера; клиенту отдаётся обобщённое сообщение.',
|
||||
'model': ApiErrorPayload,
|
||||
},
|
||||
status.HTTP_503_SERVICE_UNAVAILABLE: {
|
||||
'description': 'S3 не сконфигурирован, ошибка записи в хранилище или временная недоступность сервиса.',
|
||||
'model': ApiErrorPayload,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@account_settings_router.patch(path='/phone', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def set_phone(
|
||||
request: Request,
|
||||
@@ -33,118 +56,143 @@ async def set_phone(
|
||||
return ORJSONResponse(status_code=status.HTTP_200_OK, content={'phone': user.phone})
|
||||
|
||||
|
||||
@account_settings_router.post(path='/encrypted-mnemonic/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def encrypted_mnemonic_start(
|
||||
@account_settings_router.patch(
|
||||
path='/avatar',
|
||||
response_class=ORJSONResponse,
|
||||
status_code=status.HTTP_200_OK,
|
||||
response_model=SetAvatarPublicResponse,
|
||||
summary='Обновить аватар',
|
||||
description=(
|
||||
'Принимает фото в Base64, сохраняет как WebP в объектном хранилище и записывает публичный URL в профиль.'
|
||||
),
|
||||
response_description=(
|
||||
'Профиль пользователя в том же формате, что и GET /me, плюс размер сохранённого WebP.'
|
||||
),
|
||||
responses=_SET_AVATAR_ERROR_RESPONSES,
|
||||
)
|
||||
async def set_avatar(
|
||||
request: Request,
|
||||
body: SetAvatarRequest,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: SetEncryptedMnemonicStartCommand = Depends(get_set_encrypted_mnemonic_start_command),
|
||||
):
|
||||
result = await command(user_id=auth.user_id)
|
||||
return {'success': result}
|
||||
command: SetAvatarCommand = Depends(get_set_avatar_command),
|
||||
) -> SetAvatarPublicResponse:
|
||||
user, webp_size = await command(user_id=auth.user_id, image_bytes=body.decoded_bytes)
|
||||
pub = me_user_public(user)
|
||||
return SetAvatarPublicResponse(**pub.model_dump(), webp_size_bytes=webp_size)
|
||||
|
||||
|
||||
@account_settings_router.post(path='/encrypted-mnemonic/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def encrypted_mnemonic_complete(
|
||||
request: Request,
|
||||
body: EncryptedMnemonicConfirmRequest,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: SetEncryptedMnemonicCompleteCommand = Depends(get_set_encrypted_mnemonic_complete_command),
|
||||
):
|
||||
user = await command(
|
||||
user_id=auth.user_id,
|
||||
code=body.code,
|
||||
encrypted_mnemonic=body.encrypted_mnemonic,
|
||||
)
|
||||
return {'encrypted_mnemonic': user.encrypted_mnemonic}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/email/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def change_email_start(
|
||||
request: Request,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: ChangeEmailStartCommand = Depends(get_change_email_start_command),
|
||||
):
|
||||
result = await command(user_id=auth.user_id)
|
||||
return {'success': result}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/email/confirm-old', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def change_email_confirm_old(
|
||||
request: Request,
|
||||
body: ChangeEmailConfirmOldRequest,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: ChangeEmailConfirmOldCommand = Depends(get_change_email_confirm_old_command),
|
||||
):
|
||||
result = await command(user_id=auth.user_id, code=body.code, new_email=body.new_email)
|
||||
return {'success': result}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/email/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def change_email_complete(
|
||||
request: Request,
|
||||
body: ChangeEmailCompleteRequest,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: ChangeEmailCompleteCommand = Depends(get_change_email_complete_command),
|
||||
):
|
||||
result = await command(user_id=auth.user_id, code=body.code)
|
||||
return {'success': result}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/password/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def change_password_start(
|
||||
request: Request,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: ChangePasswordStartCommand = Depends(get_change_password_start_command),
|
||||
):
|
||||
result = await command(user_id=auth.user_id)
|
||||
return {'success': result}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/password/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def change_password_complete(
|
||||
request: Request,
|
||||
body: ChangePasswordConfirmRequest,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: ChangePasswordCompleteCommand = Depends(get_change_password_complete_command),
|
||||
):
|
||||
result = await command(
|
||||
user_id=auth.user_id,
|
||||
code=body.code,
|
||||
new_password=body.new_password,
|
||||
confirm_password=body.confirm_password,
|
||||
)
|
||||
return {'success': result}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/bank/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def bank_details_start(
|
||||
request: Request,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: UpdateBankDetailsStartCommand = Depends(get_update_bank_details_start_command),
|
||||
):
|
||||
result = await command(user_id=auth.user_id)
|
||||
return {'success': result}
|
||||
|
||||
|
||||
@account_settings_router.post(path='/bank/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
async def bank_details_complete(
|
||||
request: Request,
|
||||
body: BankConfirmRequest,
|
||||
auth: AuthContext = Depends(require_access_token),
|
||||
command: UpdateBankDetailsCompleteCommand = Depends(get_update_bank_details_complete_command),
|
||||
):
|
||||
user = await command(
|
||||
user_id=auth.user_id,
|
||||
code=body.code,
|
||||
passport_data=body.passport_data,
|
||||
inn=body.inn,
|
||||
erc20=body.erc20,
|
||||
)
|
||||
return ORJSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
'passport_data': user.passport_data,
|
||||
'inn': user.inn,
|
||||
'erc20': user.erc20,
|
||||
},
|
||||
)
|
||||
#
|
||||
# @account_settings_router.post(path='/encrypted-mnemonic/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def encrypted_mnemonic_start(
|
||||
# request: Request,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: SetEncryptedMnemonicStartCommand = Depends(get_set_encrypted_mnemonic_start_command),
|
||||
# ):
|
||||
# result = await command(user_id=auth.user_id)
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/encrypted-mnemonic/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def encrypted_mnemonic_complete(
|
||||
# request: Request,
|
||||
# body: EncryptedMnemonicConfirmRequest,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: SetEncryptedMnemonicCompleteCommand = Depends(get_set_encrypted_mnemonic_complete_command),
|
||||
# ):
|
||||
# user = await command(
|
||||
# user_id=auth.user_id,
|
||||
# code=body.code,
|
||||
# encrypted_mnemonic=body.encrypted_mnemonic,
|
||||
# )
|
||||
# return {'encrypted_mnemonic': user.encrypted_mnemonic}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/email/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def change_email_start(
|
||||
# request: Request,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: ChangeEmailStartCommand = Depends(get_change_email_start_command),
|
||||
# ):
|
||||
# result = await command(user_id=auth.user_id)
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/email/confirm-old', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def change_email_confirm_old(
|
||||
# request: Request,
|
||||
# body: ChangeEmailConfirmOldRequest,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: ChangeEmailConfirmOldCommand = Depends(get_change_email_confirm_old_command),
|
||||
# ):
|
||||
# result = await command(user_id=auth.user_id, code=body.code, new_email=body.new_email)
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/email/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def change_email_complete(
|
||||
# request: Request,
|
||||
# body: ChangeEmailCompleteRequest,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: ChangeEmailCompleteCommand = Depends(get_change_email_complete_command),
|
||||
# ):
|
||||
# result = await command(user_id=auth.user_id, code=body.code)
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/password/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def change_password_start(
|
||||
# request: Request,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: ChangePasswordStartCommand = Depends(get_change_password_start_command),
|
||||
# ):
|
||||
# result = await command(user_id=auth.user_id)
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/password/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def change_password_complete(
|
||||
# request: Request,
|
||||
# body: ChangePasswordConfirmRequest,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: ChangePasswordCompleteCommand = Depends(get_change_password_complete_command),
|
||||
# ):
|
||||
# result = await command(
|
||||
# user_id=auth.user_id,
|
||||
# code=body.code,
|
||||
# new_password=body.new_password,
|
||||
# confirm_password=body.confirm_password,
|
||||
# )
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/bank/start', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def bank_details_start(
|
||||
# request: Request,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: UpdateBankDetailsStartCommand = Depends(get_update_bank_details_start_command),
|
||||
# ):
|
||||
# result = await command(user_id=auth.user_id)
|
||||
# return {'success': result}
|
||||
#
|
||||
#
|
||||
# @account_settings_router.post(path='/bank/complete', response_class=ORJSONResponse, status_code=status.HTTP_200_OK)
|
||||
# async def bank_details_complete(
|
||||
# request: Request,
|
||||
# body: BankConfirmRequest,
|
||||
# auth: AuthContext = Depends(require_access_token),
|
||||
# command: UpdateBankDetailsCompleteCommand = Depends(get_update_bank_details_complete_command),
|
||||
# ):
|
||||
# user = await command(
|
||||
# user_id=auth.user_id,
|
||||
# code=body.code,
|
||||
# passport_data=body.passport_data,
|
||||
# inn=body.inn,
|
||||
# erc20=body.erc20,
|
||||
# )
|
||||
# return ORJSONResponse(
|
||||
# status_code=status.HTTP_200_OK,
|
||||
# content={
|
||||
# 'passport_data': user.passport_data,
|
||||
# 'inn': user.inn,
|
||||
# 'erc20': user.erc20,
|
||||
# },
|
||||
# )
|
||||
|
||||
Reference in New Issue
Block a user