From d0b27da641b9e1c4613867c6f9fd6c14727640f8 Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Mon, 29 May 2023 15:34:26 +0000 Subject: [PATCH] feature(backups): init repo mutation --- selfprivacy_api/backup/__init__.py | 34 ++++++++---- selfprivacy_api/backup/providers/provider.py | 6 ++- selfprivacy_api/backup/storage.py | 6 ++- .../graphql/mutations/backup_mutations.py | 53 +++++++++++++++++++ selfprivacy_api/models/backup/provider.py | 2 + 5 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 selfprivacy_api/graphql/mutations/backup_mutations.py diff --git a/selfprivacy_api/backup/__init__.py b/selfprivacy_api/backup/__init__.py index f3e2ba5..a5d5416 100644 --- a/selfprivacy_api/backup/__init__.py +++ b/selfprivacy_api/backup/__init__.py @@ -29,6 +29,9 @@ class Backups: Storage.store_testrepo_path(file_path) Storage.store_provider(provider) + def set_provider(provider: AbstractBackupProvider): + Storage.store_provider(provider) + @staticmethod def get_last_backed_up(service: Service) -> Optional[datetime]: """Get a timezone-aware time of the last backup of a service""" @@ -126,19 +129,21 @@ class Backups: return Backups.lookup_provider() @staticmethod - def set_provider(kind: str, login: str, key: str): - provider = Backups.construct_provider(kind, login, key) + def set_provider(kind: str, login: str, key: str, location: str, repo_id: str = ""): + provider = Backups.construct_provider(kind, login, key, location, id) Storage.store_provider(provider) @staticmethod - def construct_provider(kind: str, login: str, key: str): + def construct_provider( + kind: str, login: str, key: str, location: str, repo_id: str = "" + ): provider_class = get_provider(BackupProvider[kind]) if kind == "FILE": path = Storage.get_testrepo_path() return provider_class(path) - return provider_class(login=login, key=key) + return provider_class(login=login, key=key, location=location, repo_id=repo_id) @staticmethod def reset(): @@ -169,17 +174,19 @@ class Backups: if "backblaze" in user_data.keys(): account = user_data["backblaze"]["accountId"] key = user_data["backblaze"]["accountKey"] + location = user_data["backblaze"]["bucket"] provider_string = "BACKBLAZE" return Backups.construct_provider( - kind=provider_string, login=account, key=key + kind=provider_string, login=account, key=key, location=location ) return None account = user_data["backup"]["accountId"] key = user_data["backup"]["accountKey"] provider_string = user_data["backup"]["provider"] + location = user_data["backup"]["bucket"] return Backups.construct_provider( - kind=provider_string, login=account, key=key + kind=provider_string, login=account, key=key, location=location ) @staticmethod @@ -188,7 +195,11 @@ class Backups: if provider_model is None: return None return Backups.construct_provider( - provider_model.kind, provider_model.login, provider_model.key + provider_model.kind, + provider_model.login, + provider_model.key, + provider_model.location, + provider_model.repo_id, ) @staticmethod @@ -214,10 +225,13 @@ class Backups: Jobs.update(job, status=JobStatus.FINISHED) @staticmethod - def init_repo(service: Service): - repo_name = service.get_id() + def init_repo(service: Optional[Service] = None): + if service is not None: + repo_name = service.get_id() + Backups.provider().backuper.init(repo_name) - Storage.mark_as_init(service) + if service is not None: + Storage.mark_as_init(service) @staticmethod def is_initted(service: Service) -> bool: diff --git a/selfprivacy_api/backup/providers/provider.py b/selfprivacy_api/backup/providers/provider.py index ce9d055..c303d4e 100644 --- a/selfprivacy_api/backup/providers/provider.py +++ b/selfprivacy_api/backup/providers/provider.py @@ -12,7 +12,11 @@ class AbstractBackupProvider(ABC): def backuper(self) -> AbstractBackuper: raise NotImplementedError - def __init__(self, login="", key="", location=""): + def __init__(self, login="", key="", location="", repo_id=""): self.backuper.set_creds(login, key, location) self.login = login self.key = key + self.location = location + # We do not need to do anything with this one + # Just remember in case the app forgets + self.repo_id = repo_id diff --git a/selfprivacy_api/backup/storage.py b/selfprivacy_api/backup/storage.py index 7ca5f18..072c80f 100644 --- a/selfprivacy_api/backup/storage.py +++ b/selfprivacy_api/backup/storage.py @@ -146,7 +146,11 @@ class Storage: redis, REDIS_PROVIDER_KEY, BackupProviderModel( - kind=get_kind(provider), login=provider.login, key=provider.key + kind=get_kind(provider), + login=provider.login, + key=provider.key, + location=provider.location, + repo_id=provider.repo_id, ), ) diff --git a/selfprivacy_api/graphql/mutations/backup_mutations.py b/selfprivacy_api/graphql/mutations/backup_mutations.py new file mode 100644 index 0000000..4b61f43 --- /dev/null +++ b/selfprivacy_api/graphql/mutations/backup_mutations.py @@ -0,0 +1,53 @@ +import datetime +import typing +import strawberry +from strawberry.types import Info + +from selfprivacy_api.graphql import IsAuthenticated +from selfprivacy_api.graphql.mutations.mutation_interface import ( + GenericMutationReturn, + MutationReturnInterface, +) +from selfprivacy_api.graphql.queries.backup import BackupConfiguration +from selfprivacy_api.graphql.queries.providers import BackupProvider + +from selfprivacy_api.backup import Backups + + +@strawberry.input +class InitializeRepositoryInput: + """Initialize repository input""" + + provider: BackupProvider + # The following field may become optional for other providers? + # Backblaze takes bucket id and name + location_id: str + location_name: str + # Key ID and key for Backblaze + login: str + password: str + + +@strawberry.type +class GenericBackupConfigReturn(MutationReturnInterface): + """Generic backup config return""" + + configuration: typing.Optional[BackupConfiguration] + + +@strawberry.type +class BackupMutations: + @strawberry.mutation(permission_classes=[IsAuthenticated]) + def initialize_repository( + self, repository: InitializeRepositoryInput + ) -> GenericBackupConfigReturn: + """Initialize a new repository""" + provider = Backups.construct_provider( + kind=repository.provider, + login=repository.login, + key=repository.password, + location=repository.location_name, + repo_id=repository.location_id, + ) + Backups.set_provider(provider) + Backups.init_repo() diff --git a/selfprivacy_api/models/backup/provider.py b/selfprivacy_api/models/backup/provider.py index e454c39..e05a7f7 100644 --- a/selfprivacy_api/models/backup/provider.py +++ b/selfprivacy_api/models/backup/provider.py @@ -7,3 +7,5 @@ class BackupProviderModel(BaseModel): kind: str login: str key: str + location: str + repo_id: str # for app usage, not for us