import json from src import config from src.api_utils.errors import BadRequest, NotFound, Unauthorized from src.api_utils.handler import api_handler from src.api_utils.request import Request from src.api_utils.response import Response, redirect from src.api_utils.spec import cookies_schema, docs, path_schema, querystring_schema, response_schema from src.core.schemas import ApplicationRequestSchema from src.enums import ServiceType from src.logger import BoundLogger from src.utils import get_api_url, get_authorized_api_client from .authorizer import AppleMusicAuthorizer, get_authorizer from .authorizer.error import ServiceAuthorizationError # <<<<<<< HEAD # from .schemas import AddServiceAccountRequestSchema, AppleMusicTokenSchema, BaseCallbackSchema, \ # ListServiceAccountResponseSchema, MarketIdSchema, ServiceTypeSchema # ======= from .schemas import AddServiceAccountRequestSchema, AppleMusicTokenSchema, BaseCallbackSchema, \ ExtraInfoRequestSchema, ExtraInfoResponseSchema, ListServiceAccountResponseSchema, MarketIdSchema, \ ServiceTypeSchema # >>>>>>> develop from .services import ServiceAccountService @api_handler @docs(tags=("service_accounts",), summary="List service accounts") @path_schema(ApplicationRequestSchema) @response_schema(code=Unauthorized.status_code, description="Unauthorized") @response_schema(ListServiceAccountResponseSchema(many=True), description="List service accounts") def list_service_accounts(_request: Request, logger: BoundLogger, app_id: int) -> Response: service = ServiceAccountService() service_accounts = service.select_for_app(app_id) return Response(ListServiceAccountResponseSchema().dumps(service_accounts, many=True)) # @api_handler # @docs(tags=("service_accounts",), summary="Delete service account") # @response_schema(code=202, description="service account successfully deleted") # @response_schema(code=NotFound.status_code, description="playlist sync object doesn't exists") # def delete_service_account(_request: Request, logger: BoundLogger, app_id: int, acc_id: int) -> Response: # service = ServiceAccountService() # if not service.exists_by_pk(acc_id): # raise NotFound() # # service.delete_by_pk(acc_id) # # return Response(status_code=202) @api_handler @docs(tags=("service_accounts",), summary="Redirect to DSP oauth service") @path_schema(ServiceTypeSchema) @querystring_schema(AddServiceAccountRequestSchema) @response_schema(code=302, description="Redirect to DSP oauth service") @response_schema(code=NotFound.status_code, description="Unknown service") @response_schema(code=Unauthorized.status_code, description="Unauthorized") @response_schema(code=BadRequest.status_code, description="BadRequest") def authorize(request: Request, logger: BoundLogger, service_type: ServiceType) -> Response: authorizer = get_authorizer(service_type, logger=logger) if authorizer is None: raise NotFound(f"Unknown service '{service_type.name}'") authorizer.set_callback_host(get_api_url(request.schema, request.host)) data = AddServiceAccountRequestSchema().load(request.query_parameters) response = redirect(authorizer.get_auth_url()) response.set_cookie(config.MARKET_ID_COOKIE_NAME, data["market_id"], secure=True, rest={"HttpOnly": True}) return response @api_handler @docs(tags=("service_accounts",), summary="Returns DSP auth request") @path_schema(ServiceTypeSchema) @querystring_schema(AddServiceAccountRequestSchema) @response_schema(description="DSP auth request") @response_schema(code=NotFound.status_code, description="Unknown service") @response_schema(code=Unauthorized.status_code, description="Unauthorized") @response_schema(code=BadRequest.status_code, description="BadRequest") def authorize_data(request: Request, logger: BoundLogger, service_type: ServiceType) -> Response: authorizer = get_authorizer(service_type, logger=logger) if authorizer is None: raise NotFound(f"Unknown service '{service_type.name}'") authorizer.set_callback_host(get_api_url(request.schema, request.host)) data = AddServiceAccountRequestSchema().load(request.query_parameters) response = Response( json.dumps({"url": authorizer.get_auth_url(), "cookies": {config.MARKET_ID_COOKIE_NAME: data["market_id"]}}) ) response.set_cookie(config.MARKET_ID_COOKIE_NAME, data["market_id"], secure=True, rest={"HttpOnly": True}) return response @api_handler @docs(tags=("service_accounts",), summary="Webhook to be called by 3rd party oauth service") @path_schema(ServiceTypeSchema) @cookies_schema(MarketIdSchema) @querystring_schema(BaseCallbackSchema) @response_schema(description="Service account been added successfully") @response_schema(code=NotFound.status_code, description="Unknown service") @response_schema(code=Unauthorized.status_code, description="Unauthorized") @response_schema(code=BadRequest.status_code, description="BadRequest") def auth_callback(request: Request, logger: BoundLogger, service_type: ServiceType) -> Response: authorizer = get_authorizer(service_type, logger=logger) if authorizer is None: raise NotFound(f"Unknown service '{service_type.name}'") authorizer.set_callback_host(get_api_url(request.schema, request.host)) data = authorizer.callback_schema.load(request.query_parameters) app_id = request.cookies.get(config.MARKET_ID_COOKIE_NAME) or data.get(config.MARKET_ID_COOKIE_NAME) try: service_account = authorizer.complete_auth(app_id, **data) except ServiceAuthorizationError as e: raise Unauthorized from e # TODO: Consider upsert ServiceAccountService().insert_instance(service_account) return Response() @api_handler @docs(tags=("service_accounts",), summary="Returns apple music developer token (required for apple music auth)") @response_schema(AppleMusicTokenSchema) def apple_music_dt(request: Request, logger: BoundLogger) -> Response: authorizer = AppleMusicAuthorizer(logger=logger) return Response(AppleMusicTokenSchema().dumps({"token": authorizer.get_dev_token()})) @api_handler @path_schema(ApplicationRequestSchema) def apple_music_tmp(request: Request, logger: BoundLogger, app_id: int) -> Response: dt_url = "/dev/_serviceaccounts/apple_music_dt" callback_url = "/dev/_serviceaccounts/callback/apple_music" data = f"""