about summary refs log tree commit diff
diff options
context:
space:
mode:
authorClaude Sonnet 4.62026-06-03 00:00:00 +0000
committerFrederick Muriuki Muriithi2026-06-03 14:07:32 -0500
commit6a0d09960be96619d26d080d8d4c420eb48adb25 (patch)
treea60a6990f90f4ee623a0d996e200c7cba21612d6
parenta16a0b5c9da77c20664027c659337db0ae521a9f (diff)
downloadgn-auth-6a0d09960be96619d26d080d8d4c420eb48adb25.tar.gz
wsgi: add create-test-users command
Add create_test_users which auto-generates timestamped emails and random
passwords for ephemeral test accounts, delegating DB creation to the
__create_one_user__ helper introduced in the previous commit.
-rw-r--r--gn_auth/wsgi.py61
1 files changed, 61 insertions, 0 deletions
diff --git a/gn_auth/wsgi.py b/gn_auth/wsgi.py
index 3b3b60b..a6d8b00 100644
--- a/gn_auth/wsgi.py
+++ b/gn_auth/wsgi.py
@@ -1,5 +1,7 @@
 """Main entry point for project"""
 import os
+import re
+import secrets
 import sys
 import uuid
 import json
@@ -134,6 +136,14 @@ def register_admin():
 
 _VALID_ROLES_ = ("system-admin", "none")
 
+_TEST_EMAIL_DOMAIN_ = "regression-tests.genenetwork.org"
+
+
+def __normalise_name_for_email__(name: str) -> str:
+    """Lowercase and strip non-alphanumeric characters for use in an email."""
+    return re.sub(r"[^a-z0-9]", "", name.lower())
+
+
 def __create_one_user__(cursor, name: str, email: str, password: str, role: str) -> dict:
     """Create a single user in the DB and return their credential record."""
     user = save_user(cursor, email, name, verified=True)
@@ -236,6 +246,57 @@ def delete_users(user_ids):
         deleted = delete_users_by_id(conn, tuple(user_ids))
         print(f"Deleted {deleted} user(s).")
 
+
+@app.cli.command()
+@click.option("--session-timestamp", required=True,
+              help="Compact ISO 8601 UTC timestamp (e.g. 20260602T122700Z)")
+@click.option("--user", "user_specs", multiple=True,
+              help='User spec: "name=...,role=..."')
+@click.option("--output", "output_path", required=True, type=click.Path(),
+              help="Write credentials as JSON to this file (0600 permissions)")
+def create_test_users(session_timestamp, user_specs, output_path):
+    """Create ephemeral test users with auto-generated email and password.
+
+    Each --user option takes a comma-separated key=value string with the
+    following keys: name, role.
+
+    Email: <normalised-name><timestamp>@regression-tests.genenetwork.org
+    Password: randomly generated.
+
+    Output is written with 0600 permissions. Valid roles: system-admin, none.
+    """
+    if not user_specs:
+        print("No users specified.", file=sys.stderr)
+        sys.exit(1)
+
+    records = []
+    with db.connection(app.config["AUTH_DB"]) as conn, db.cursor(conn) as cursor:
+        for spec_str in user_specs:
+            spec = __parse_user_spec__(spec_str)
+            name = spec.get("name", "").strip()
+            role = spec.get("role", "none").strip()
+
+            if not name:
+                print(f"Missing 'name' in user spec: {spec_str!r}", file=sys.stderr)
+                sys.exit(1)
+            if role not in _VALID_ROLES_:
+                print(
+                    f"Invalid role {role!r} in spec: {spec_str!r}. "
+                    f"Valid roles: {_VALID_ROLES_}",
+                    file=sys.stderr)
+                sys.exit(1)
+
+            email = (f"{__normalise_name_for_email__(name)}"
+                     f"{session_timestamp}@{_TEST_EMAIL_DOMAIN_}")
+            password = secrets.token_urlsafe(32)
+
+            records.append(
+                __create_one_user__(cursor, name, email, password, role))
+
+    __write_output__(
+        {"session_timestamp": session_timestamp, "users": records},
+        output_path)
+
 ##### END: CLI Commands #####
 
 if __name__ == '__main__':