diff --git a/selfprivacy_api/graphql/__init__.py b/selfprivacy_api/graphql/__init__.py index 5a08c3e..0897434 100644 --- a/selfprivacy_api/graphql/__init__.py +++ b/selfprivacy_api/graphql/__init__.py @@ -10,6 +10,9 @@ from selfprivacy_api.graphql.queries.api import Api class Query: """Root schema for queries""" system: System - api: Api + @strawberry.field + def api(self) -> Api: + """API access status""" + return Api() schema = strawberry.Schema(query=Query) diff --git a/selfprivacy_api/graphql/queries/api.py b/selfprivacy_api/graphql/queries/api.py index c890465..7424bee 100644 --- a/selfprivacy_api/graphql/queries/api.py +++ b/selfprivacy_api/graphql/queries/api.py @@ -4,24 +4,27 @@ import datetime import typing import strawberry -from selfprivacy_api.resolvers.api import get_api_version +from selfprivacy_api.resolvers.api import get_api_version, get_devices, get_recovery_key_status @strawberry.type class ApiDevice: + """A single device with SelfPrivacy app installed""" name: str creation_date: datetime.datetime is_caller: bool @strawberry.type class ApiRecoveryKeyStatus: + """Recovery key status""" exists: bool valid: bool - creation_date: datetime.datetime + creation_date: typing.Optional[datetime.datetime] expiration_date: typing.Optional[datetime.datetime] uses_left: typing.Optional[int] @strawberry.type class Api: + """API access status""" version: str = strawberry.field(resolver=get_api_version) - devices: typing.List[ApiDevice] - recovery_key: ApiRecoveryKeyStatus + devices: typing.List[ApiDevice] = strawberry.field(resolver=get_devices) + recovery_key: ApiRecoveryKeyStatus = strawberry.field(resolver=get_recovery_key_status) diff --git a/selfprivacy_api/resolvers/api.py b/selfprivacy_api/resolvers/api.py index 245a635..bbcebf9 100644 --- a/selfprivacy_api/resolvers/api.py +++ b/selfprivacy_api/resolvers/api.py @@ -1,5 +1,53 @@ """Resolvers for API module""" +import datetime +import typing +from flask import request + +from selfprivacy_api.graphql.queries.api import ApiDevice, ApiRecoveryKeyStatus + +from selfprivacy_api.utils.auth import ( + get_recovery_token_status, + get_tokens_info, + is_recovery_token_exists, + is_recovery_token_valid, + is_token_name_exists, + is_token_name_pair_valid, + refresh_token, + get_token_name, +) def get_api_version() -> str: """Get API version""" return "1.2.7" + +def get_devices() -> typing.List[ApiDevice]: + """Get list of devices""" + caller_name = get_token_name(request.headers.get("Authorization").split(" ")[1]) + tokens = get_tokens_info() + return [ + ApiDevice( + name=token["name"], + creation_date=datetime.datetime.strptime(token["date"], "%Y-%m-%dT%H:%M:%S.%fZ"), + is_caller=token["name"] == caller_name, + ) + for token in tokens + ] + +def get_recovery_key_status() -> ApiRecoveryKeyStatus: + """Get recovery key status""" + if not is_recovery_token_exists(): + return ApiRecoveryKeyStatus( + exists=False, valid=False, creation_date=None, expiration_date=None, uses_left=None + ) + status = get_recovery_token_status() + if status is None: + return ApiRecoveryKeyStatus( + exists=False, valid=False, creation_date=None, expiration_date=None, uses_left=None + ) + return ApiRecoveryKeyStatus( + exists=True, + valid=is_recovery_token_valid(), + creation_date=datetime.datetime.strptime(status["creation_date"], "%Y-%m-%dT%H:%M:%S.%fZ"), + expiration_date=datetime.datetime.strptime(status["expiration_date"], "%Y-%m-%dT%H:%M:%S.%fZ") if status["expiration_date"] is not None else None, + uses_left=status["uses_left"] if status["uses_left"] is not None else None, + ) diff --git a/selfprivacy_api/resources/api_auth/recovery_token.py b/selfprivacy_api/resources/api_auth/recovery_token.py index fbd80d9..e97c87a 100644 --- a/selfprivacy_api/resources/api_auth/recovery_token.py +++ b/selfprivacy_api/resources/api_auth/recovery_token.py @@ -60,6 +60,16 @@ class RecoveryToken(Resource): "uses_left": None, } status = get_recovery_token_status() + # check if status is None + if status is None: + return { + "exists": False, + "valid": False, + "date": None, + "expiration": None, + "uses_left": None, + } + if not is_recovery_token_valid(): return { "exists": True,