def delete_user( cls, *, delete_user_usecase: DeleteUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase ) -> Callable[..., JsonEntity.of(_type=_A)]: async def wrapper(request: Request) -> JSONResponse: """ parameters: - in: header name: username schema: type: string description: The username of the user who has an access-token require: true - in: header name: access-token schema: type: string description: The access-token of the user currently doing this request require: true - in: query name: id schema: type: string description: The id of the user - in: query name: name schema: type: string description: The name of the user - in: query name: email schema: type: string description: The email of the user responses: 200: description: User deleted 400: description: Error deleting the user content: application/json: schema: Failure examples: - {"error": "Delete selector should be within this list ['id', 'name', 'email']"} 401: description: unauthorized content: application/json: schema: Failure examples: - {"error": "You should provide username and access-token into the headers."} """ return await delete_user_framework( delete_user_usecase=delete_user_usecase, fetch_user_usecase=fetch_user_usecase, fetch_access_token_usecase=fetch_access_token_usecase, request=request) return wrapper
def post_user(cls, *, add_user_usecase: AddUserUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface) -> Callable[..., JsonEntity.of(_type=_A)]: @abstractmethod def wrapper(*args, **kwargs) -> JsonEntity.of(_type=_A): pass return wrapper
def update_user(cls, *, update_user_usecase: UpdateUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface) -> Callable[..., JsonEntity.of(_type=_A)]: @abstractmethod def wrapper(*args, **kwargs) -> JsonEntity.of(_type=_A): pass return wrapper
def health_check( cls, *, services: List[Service] ) -> Callable[..., JsonEntity.of(_type=_A)]: async def wrapper(_request: Request) -> JSONResponse: """ responses: 200: description: health check of all services examples: - {"InMemoryDatabase": "HEALTHY"} - {"InMemoryDatabase": "UNHEALTHY"} """ return JSONResponse(health_check_common(services=services)) return wrapper
def get_access_token( cls, *, add_access_token_usecase: AddAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface ) -> Callable[..., JsonEntity.of(_type=_A)]: @dataclass(frozen=True) class UserLoginJson: username: str password: str marshmallow_dataclass.class_schema(UserLoginJson) async def wrapper(request: Request) -> JSONResponse: """ requestBody: description: Data to login a user and generate an access token for this particular user required: true content: application/json: schema: UserLoginJson responses: 200: description: AccessToken created content: application/json: schema: AccessToken examples: - {"token": "token"} 400: description: error generating an access token content: application/json: schema: Failure examples: - {"error": "Invalid password for this user"} """ json_data: Dict[Any, Any] = await request.json() return await get_access_token_framework( add_access_token_usecase=add_access_token_usecase, json_schema=json_schema, json_schema_validator=json_schema_validator, json_data=json_data) return wrapper
async def get_access_token( *, add_access_token_usecase: AddAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface, json_data: Dict[Any, Any]) -> Callable[..., JsonEntity.of(_type=_A)]: json_validation_status: Either[Failure, Success] = json_schema_validator.validate( schema=json_schema, data=json_data) if isinstance(json_validation_status, Success): add_access_token_status = add_access_token_usecase.execute( username=json_data["username"], password=json_data["password"], ) if isinstance(add_access_token_status, AccessToken): return JSONResponse(add_access_token_status.as_dict(), status_code=200) return JSONResponse(add_access_token_status.as_dict(), status_code=400) return JSONResponse(json_validation_status.as_dict(), status_code=400)
async def post_user( *, add_user_usecase: AddUserUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface, json_data: Dict[Any, Any]) -> Callable[..., JsonEntity.of(_type=_A)]: json_validation_status: Either[Failure, Success] = json_schema_validator.validate( schema=json_schema, data=json_data) if isinstance(json_validation_status, Success): add_user_status = add_user_usecase.execute( username=json_data["name"], age=json_data["age"], password=json_data["password"], email=json_data.get("email", None), role=UserRole.USER) if isinstance(add_user_status, ApplicationUser): user_json: UserJson = from_application_user_to_json_user( application_user=add_user_status) return JSONResponse(user_json.as_dict(), status_code=200) return JSONResponse(add_user_status.as_dict(), status_code=400) return JSONResponse(json_validation_status.as_dict(), status_code=400)
def post_user( cls, *, add_user_usecase: AddUserUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface ) -> Callable[..., JsonEntity.of(_type=_A)]: async def wrapper(request: Request) -> JSONResponse: """ requestBody: description: Data to create a user required: true content: application/json: schema: DomainUser responses: 200: description: User created content: application/json: schema: UserJson examples: - {"name": "test", "age": 26, "email": "*****@*****.**", "role": "USER"} 400: description: error creating a user content: application/json: schema: Failure examples: - {"error": "Username string is already exist, please use a different name."} """ json_data: Dict[Any, Any] = await request.json() return await post_user_framework( add_user_usecase=add_user_usecase, json_schema=json_schema, json_schema_validator=json_schema_validator, json_data=json_data) return wrapper
def get_user(cls, *, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase) -> Callable[..., JsonEntity.of(_type=_A)]: @abstractmethod def wrapper(*args, **kwargs) -> JsonEntity.of(_type=_A): pass return wrapper
def get_access_token(cls, *, add_access_token_usecase: AddAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface) -> Callable[..., JsonEntity.of(_type=_A)]: @abstractmethod def wrapper(*args, **kwargs) -> JsonEntity.of(_type=_A): pass return wrapper
def health_check(cls, *, services: List[Service]) -> Callable[..., JsonEntity.of(_type=_A)]: @abstractmethod def wrapper(*args, **kwargs) -> JsonEntity.of(_type=_A): pass return wrapper
async def update_user(*, update_user_usecase: UpdateUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface, request: Request) -> Callable[..., JsonEntity.of(_type=_A)]: # simple validation for now, will be better later ;) username = request.headers.get("username", None) token = request.headers.get("access-token", None) if username is not None and token is not None: current_logged_user_fetch_status = fetch_user_usecase.execute( fetch_by_selector='name', fetch_by_data=username ) access_token_status = fetch_access_token_usecase.execute( username=username ) if isinstance(access_token_status, Failure): return JSONResponse(access_token_status.as_dict(), 401) if access_token_status.token != token: return JSONResponse(Failure(error=f"Invalid access token for the user {username}").as_dict(), 401) if isinstance(current_logged_user_fetch_status, ApplicationUser): json_data: Dict[Any, Any] = await request.json() json_validation_status: Either[Failure, Success] = json_schema_validator.validate( schema=json_schema, data=json_data ) if isinstance(json_validation_status, Success): # will make this better later ;) json_data["updated_user"]["role"] = UserRole.USER create_domain_user_status = create_user( **json_data["updated_user"] ) if isinstance(create_domain_user_status, Failure): return JSONResponse(create_domain_user_status.as_dict()) if current_logged_user_fetch_status.role.name == UserRole.ADMIN.name: pass elif current_logged_user_fetch_status.role.name == UserRole.USER.name: if current_logged_user_fetch_status.name != username: return JSONResponse( Failure( error="Your current user permission is not satisfying this operation." ).as_dict(), status_code=401 ) update_user_status = update_user_usecase.execute( update_by_selector=json_data["update_by_selector"], update_by_data=json_data["update_by_data"], updated_user=create_domain_user_status ) if isinstance(update_user_status, ApplicationUser): user_json = from_application_user_to_json_user( application_user=update_user_status ) return JSONResponse(user_json.as_dict(), status_code=200) return JSONResponse(update_user_status.as_dict(), status_code=400) return JSONResponse(json_validation_status.as_dict(), status_code=400) return JSONResponse(current_logged_user_fetch_status.as_dict(), 401) return JSONResponse( Failure(error="You should provide username and access-token into the headers.").as_dict(), 401 )
def get_user( cls, *, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase ) -> Callable[..., JsonEntity.of(_type=_A)]: async def wrapper(request: Request) -> JSONResponse: """ parameters: - in: header name: username schema: type: string description: The username of the user who has an access-token require: true - in: header name: access-token schema: type: string description: The access-token of the user currently doing this request require: true - in: query name: id schema: type: string description: The id of the user - in: query name: name schema: type: string description: The name of the user - in: query name: email schema: type: string description: The email of the user responses: 200: description: the user you fetched content: application/json: schema: UserJson examples: - {"name": "test", "age": 26, "email": "*****@*****.**", "role": "USER"} 400: description: error fetching the user content: application/json: schema: Failure examples: - {"error": "You should provide params as one of these [id, name, email]"} 401: description: unauthorized content: application/json: schema: Failure examples: - {"error": "You should provide username and access-token into the headers."} """ return await get_user_framework( fetch_user_usecase=fetch_user_usecase, fetch_access_token_usecase=fetch_access_token_usecase, request=request) return wrapper
async def delete_user( *, delete_user_usecase: DeleteUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase, request: Request) -> Callable[..., JsonEntity.of(_type=_A)]: username = request.headers.get("username", None) token = request.headers.get("access-token", None) if username is not None and token is not None: current_logged_user_fetch_status = fetch_user_usecase.execute( fetch_by_selector='name', fetch_by_data=username) access_token_status = fetch_access_token_usecase.execute( username=username) if isinstance(access_token_status, Failure): return JSONResponse(access_token_status.as_dict(), 401) if access_token_status.token != token: return JSONResponse( Failure(error=f"Invalid access token for the user {username}"). as_dict(), 401) if isinstance(current_logged_user_fetch_status, ApplicationUser): params = request.query_params if len(params) > 0: selector_key = list(params.keys())[0] selector_value = params[selector_key] if current_logged_user_fetch_status.role.name == UserRole.ADMIN.name: pass elif current_logged_user_fetch_status.role.name == UserRole.USER.name: permission_error_json = JSONResponse(Failure( error= "Your current user permission is not satisfying this operation." ).as_dict(), status_code=401) if selector_key == "id": if current_logged_user_fetch_status.id != selector_value: return permission_error_json if selector_key == "name": if current_logged_user_fetch_status.name != selector_value: return permission_error_json if selector_key == "email": if current_logged_user_fetch_status.email != selector_value: return permission_error_json delete_user_status = delete_user_usecase.execute( delete_by_selector=selector_key, delete_by_data=selector_value) return JSONResponse(delete_user_status.as_dict(), status_code=200) return JSONResponse(Failure( error= "You should provide params as one of these [id, name, email]"). as_dict(), status_code=400) return JSONResponse(current_logged_user_fetch_status.as_dict(), 401) return JSONResponse( Failure( error= "You should provide username and access-token into the headers."). as_dict(), 401)
def wrapper(*args, **kwargs) -> JsonEntity.of(_type=_A): pass return wrapper
class Route(NamedTuple): url: str methods: List[str] handler: Callable[..., JsonEntity.of(_type=_A)] args: Maybe[Tuple[Any, ...]] kwargs: Maybe[Dict[str, Any]]
def update_user( cls, *, update_user_usecase: UpdateUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface ) -> Callable[..., JsonEntity.of(_type=_A)]: @dataclass(frozen=True) class UpdateUserData: update_by_selector: str update_by_data: str updated_user: DomainUser marshmallow_dataclass.class_schema(UpdateUserData) async def wrapper(request: Request) -> JSONResponse: """ parameters: - in: header name: username schema: type: string description: The username of the user who has an access-token require: true - in: header name: access-token schema: type: string description: The access-token of the user currently doing this request require: true requestBody: description: Data to update a user required: true content: application/json: schema: UpdateUserData responses: 200: description: User updated content: application/json: schema: ApplicationUser examples: - {"name": "test", "age": 26, "email": "*****@*****.**", "password": "******", "role": "USER"} 400: description: Error updating the user content: application/json: schema: Failure examples: - {"error": "Update selector should be within this list ['id', 'name', 'email']"} 401: description: unauthorized content: application/json: schema: Failure examples: - {"error": "You should provide username and access-token into the headers."} """ return await update_user_framework( update_user_usecase=update_user_usecase, fetch_user_usecase=fetch_user_usecase, fetch_access_token_usecase=fetch_access_token_usecase, json_schema=json_schema, json_schema_validator=json_schema_validator, request=request) return wrapper