From 62d5de0dd63ed1afa3488276f50e5010ff51787e Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 3 Oct 2023 16:41:09 +0300 Subject: [PATCH 1/6] refactor(ssh): Remove unused add_root_ssh_key function --- selfprivacy_api/actions/ssh.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/selfprivacy_api/actions/ssh.py b/selfprivacy_api/actions/ssh.py index 3f79ff8..8a92735 100644 --- a/selfprivacy_api/actions/ssh.py +++ b/selfprivacy_api/actions/ssh.py @@ -49,19 +49,6 @@ def set_ssh_settings( data["ssh"]["passwordAuthentication"] = password_authentication -def add_root_ssh_key(public_key: str): - with WriteUserData() as data: - if "ssh" not in data: - data["ssh"] = {} - if "rootKeys" not in data["ssh"]: - data["ssh"]["rootKeys"] = [] - # Return 409 if key already in array - for key in data["ssh"]["rootKeys"]: - if key == public_key: - raise KeyAlreadyExists() - data["ssh"]["rootKeys"].append(public_key) - - class KeyAlreadyExists(Exception): """Key already exists""" From cebb71ff4a5851864f66699a679d5875a3142154 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 3 Oct 2023 16:51:06 +0300 Subject: [PATCH 2/6] feat(ssh): Add support for ecdsa keys --- selfprivacy_api/graphql/mutations/users_mutations.py | 2 +- selfprivacy_api/utils/__init__.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/selfprivacy_api/graphql/mutations/users_mutations.py b/selfprivacy_api/graphql/mutations/users_mutations.py index f7317fb..57825bc 100644 --- a/selfprivacy_api/graphql/mutations/users_mutations.py +++ b/selfprivacy_api/graphql/mutations/users_mutations.py @@ -147,7 +147,7 @@ class UsersMutations: except InvalidPublicKey: return UserMutationReturn( success=False, - message="Invalid key type. Only ssh-ed25519 and ssh-rsa are supported", + message="Invalid key type. Only ssh-ed25519, ssh-rsa and ecdsa are supported", code=400, ) except UserNotFound: diff --git a/selfprivacy_api/utils/__init__.py b/selfprivacy_api/utils/__init__.py index 96bf9d8..40ed5b6 100644 --- a/selfprivacy_api/utils/__init__.py +++ b/selfprivacy_api/utils/__init__.py @@ -88,10 +88,12 @@ class ReadUserData(object): def validate_ssh_public_key(key): - """Validate SSH public key. It may be ssh-ed25519 or ssh-rsa.""" + """Validate SSH public key. + It may be ssh-ed25519, ssh-rsa or ecdsa-sha2-nistp256.""" if not key.startswith("ssh-ed25519"): if not key.startswith("ssh-rsa"): - return False + if not key.startswith("ecdsa-sha2-nistp256"): + return False return True From 07aaa21602e9afb0088b06ba17f973b30d49cb5d Mon Sep 17 00:00:00 2001 From: Inex Code Date: Mon, 9 Oct 2023 12:45:22 +0300 Subject: [PATCH 3/6] chore: bump version --- selfprivacy_api/dependencies.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfprivacy_api/dependencies.py b/selfprivacy_api/dependencies.py index 35cf9e1..1955601 100644 --- a/selfprivacy_api/dependencies.py +++ b/selfprivacy_api/dependencies.py @@ -27,4 +27,4 @@ async def get_token_header( def get_api_version() -> str: """Get API version""" - return "2.4.1" + return "2.4.2" diff --git a/setup.py b/setup.py index 44d2336..399b157 100755 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="selfprivacy_api", - version="2.4.1", + version="2.4.2", packages=find_packages(), scripts=[ "selfprivacy_api/app.py", From 0912ac183198f7882d60dafd1d3d1333043752d9 Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Fri, 22 Sep 2023 17:56:04 +0000 Subject: [PATCH 4/6] feature(jobs): set ttl via method --- selfprivacy_api/jobs/__init__.py | 8 ++++++++ tests/test_jobs.py | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/selfprivacy_api/jobs/__init__.py b/selfprivacy_api/jobs/__init__.py index 3fe452b..05b5ab8 100644 --- a/selfprivacy_api/jobs/__init__.py +++ b/selfprivacy_api/jobs/__init__.py @@ -224,6 +224,14 @@ class Jobs: return job + @staticmethod + def set_expiration(job: Job, expiration_seconds: int) -> Job: + redis = RedisPool().get_connection() + key = _redis_key_from_uuid(job.uid) + if redis.exists(key): + redis.expire(key, expiration_seconds) + return job + @staticmethod def get_job(uid: str) -> typing.Optional[Job]: """ diff --git a/tests/test_jobs.py b/tests/test_jobs.py index 0a4271e..c0e2125 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -49,6 +49,12 @@ def test_remove_get_nonexistent(jobs_with_one_job): assert jobs_with_one_job.get_job(uid_str) is None +def test_set_zeroing_ttl(jobs_with_one_job): + test_job = jobs_with_one_job.get_jobs()[0] + jobs_with_one_job.set_expiration(test_job, 0) + assert jobs_with_one_job.get_jobs() == [] + + def test_jobs(jobs_with_one_job): jobs = jobs_with_one_job test_job = jobs_with_one_job.get_jobs()[0] From 26c0a8fafe3a76fddffedcbf2c5b8f6c21a78020 Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Fri, 22 Sep 2023 18:09:39 +0000 Subject: [PATCH 5/6] feature(jobs): set 1 hour ttl for successful autobackup jobs --- selfprivacy_api/backup/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/selfprivacy_api/backup/__init__.py b/selfprivacy_api/backup/__init__.py index 72d1567..aa11f7f 100644 --- a/selfprivacy_api/backup/__init__.py +++ b/selfprivacy_api/backup/__init__.py @@ -56,6 +56,8 @@ BACKUP_PROVIDER_ENVS = { "location": "BACKUP_LOCATION", } +AUTOBACKUP_JOB_EXPIRATION_SECONDS = 60 * 60 # one hour + class NotDeadError(AssertionError): """ @@ -316,6 +318,8 @@ class Backups: raise error Jobs.update(job, status=JobStatus.FINISHED) + if reason in [BackupReason.AUTO, BackupReason.PRE_RESTORE]: + Jobs.set_expiration(job, AUTOBACKUP_JOB_EXPIRATION_SECONDS) return snapshot @staticmethod From ece3258c7858ebf42c08d339dbd2320152acab26 Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Fri, 22 Sep 2023 18:13:22 +0000 Subject: [PATCH 6/6] test(jobs): test out setting ttl --- tests/test_jobs.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_jobs.py b/tests/test_jobs.py index c0e2125..64cf457 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -1,6 +1,7 @@ # pylint: disable=redefined-outer-name # pylint: disable=unused-argument import pytest +from time import sleep from selfprivacy_api.jobs import Jobs, JobStatus import selfprivacy_api.jobs as jobsmodule @@ -55,6 +56,14 @@ def test_set_zeroing_ttl(jobs_with_one_job): assert jobs_with_one_job.get_jobs() == [] +def test_not_zeroing_ttl(jobs_with_one_job): + test_job = jobs_with_one_job.get_jobs()[0] + jobs_with_one_job.set_expiration(test_job, 1) + assert len(jobs_with_one_job.get_jobs()) == 1 + sleep(1.2) + assert len(jobs_with_one_job.get_jobs()) == 0 + + def test_jobs(jobs_with_one_job): jobs = jobs_with_one_job test_job = jobs_with_one_job.get_jobs()[0]