aboutsummaryrefslogtreecommitdiff
path: root/gn3/auth/authorisation
diff options
context:
space:
mode:
Diffstat (limited to 'gn3/auth/authorisation')
-rw-r--r--gn3/auth/authorisation/users/collections.py83
-rw-r--r--gn3/auth/authorisation/users/views.py6
2 files changed, 67 insertions, 22 deletions
diff --git a/gn3/auth/authorisation/users/collections.py b/gn3/auth/authorisation/users/collections.py
index 9ddc138..2e2672c 100644
--- a/gn3/auth/authorisation/users/collections.py
+++ b/gn3/auth/authorisation/users/collections.py
@@ -1,30 +1,77 @@
"""Handle user collections."""
+import uuid
import json
from redis import Redis
+from email_validator import validate_email, EmailNotValidError
from .models import User
+def __valid_email__(email:str) -> bool:
+ """Check for email validity."""
+ try:
+ validate_email(email, check_deliverability=True)
+ except EmailNotValidError as _enve:
+ return False
+ return True
+
+def __toggle_boolean_field__(
+ rconn: Redis, email: str, field: str):
+ """Toggle the valuen of a boolean field"""
+ mig_dict = json.loads(rconn.hget("migratable-accounts", email) or "{}")
+ if bool(mig_dict):
+ rconn.hset("migratable-accounts", email,
+ {**mig_dict, field: not mig_dict.get(field, True)})
+
+def __build_email_uuid_bridge__(rconn: Redis):
+ """
+ Build a connection between new accounts and old user accounts.
+
+ The only thing that is common between the two is the email address,
+ therefore, we use that to link the two items.
+ """
+ old_accounts = {
+ account["email_address"]: {
+ "user_id": account["user_id"],
+ "collections-migrated": False,
+ "resources_migrated": False
+ } for account in (
+ acct for acct in
+ (json.loads(usr) for usr in rconn.hgetall("users").values())
+ if (bool(acct.get("email_address", False)) and
+ __valid_email__(acct["email_address"])))
+ }
+ if bool(old_accounts):
+ rconn.hset("migratable-accounts", mapping={
+ key: json.dumps(value) for key,value in old_accounts.items()
+ })
+ return old_accounts
+
+def __retrieve_old_accounts__(rconn: Redis) -> dict:
+ accounts = rconn.hgetall("migratable-accounts")
+ if accounts:
+ return {
+ key: json.loads(value) for key, value in accounts.items()
+ }
+ return __build_email_uuid_bridge__(rconn)
+
+def __retrieve_old_user_collections__(rconn: Redis, old_user_id: uuid.UUID) -> tuple:
+ """Retrieve any old collections relating to the user."""
+ return tuple(json.loads(rconn.hget("collections", old_user_id) or "[]"))
+
def user_collections(rconn: Redis, user: User) -> tuple:
"""Retrieve current user collections."""
- return tuple(json.loads(
+ collections = tuple(json.loads(
rconn.hget("collections", str(user.user_id)) or
"[]"))
-
-def old_user_collections(rconn: Redis, user: User) -> tuple:
- """
- Retrieve any old user collections and migrate them to new account.
- """
- collections = user_collections(rconn, user)
- old_user_accounts = [
- acct for acct in
- (json.loads(usr) for usr in rconn.hgetall("users").values())
- if acct.get("email_address", "") == user.email]
- for account in old_user_accounts:
- collections = collections + tuple(json.loads(
- rconn.hget("collections", account["user_id"]) or "[]"))
- rconn.hdel("collections", account["user_id"])
-
- rconn.hset(
- "collections", key=str(user.user_id), value=json.dumps(collections))
+ old_accounts = __retrieve_old_accounts__(rconn)
+ if (user.email in old_accounts and
+ not old_accounts[user.email]["collections-migrated"]):
+ old_user_id = old_accounts[user.email]["user_id"]
+ collections = tuple(set(collections + __retrieve_old_user_collections__(
+ rconn, uuid.UUID(old_user_id))))
+ rconn.hdel("collections", old_user_id)
+ __toggle_boolean_field__(rconn, user.email, "collections-migrated")
+ rconn.hset(
+ "collections", key=user.user_id, value=json.dumps(collections))
return collections
diff --git a/gn3/auth/authorisation/users/views.py b/gn3/auth/authorisation/users/views.py
index 0a82de3..2b4230e 100644
--- a/gn3/auth/authorisation/users/views.py
+++ b/gn3/auth/authorisation/users/views.py
@@ -13,7 +13,7 @@ from gn3.auth.dictify import dictify
from gn3.auth.db_utils import with_db_connection
from .models import list_users
-from .collections import user_collections, old_user_collections
+from .collections import user_collections
from ..groups.models import user_group as _user_group
from ..resources.models import user_resources as _user_resources
@@ -180,6 +180,4 @@ def list_user_collections() -> Response:
with (require_oauth.acquire("profile user") as the_token,
Redis.from_url(current_app.config["REDIS_URI"],
decode_responses=True) as redisconn):
- return jsonify(
- user_collections(redisconn, the_token.user) or
- old_user_collections(redisconn, the_token.user))
+ return jsonify(user_collections(redisconn, the_token.user))