about summary refs log tree commit diff
path: root/gn_auth/auth
diff options
context:
space:
mode:
Diffstat (limited to 'gn_auth/auth')
-rw-r--r--gn_auth/auth/authorisation/users/views.py59
-rw-r--r--gn_auth/auth/system/admin/users.py67
-rw-r--r--gn_auth/auth/system/admin/views.py2
3 files changed, 77 insertions, 51 deletions
diff --git a/gn_auth/auth/authorisation/users/views.py b/gn_auth/auth/authorisation/users/views.py
index e454a80..f0b1b0c 100644
--- a/gn_auth/auth/authorisation/users/views.py
+++ b/gn_auth/auth/authorisation/users/views.py
@@ -10,6 +10,9 @@ from functools import reduce, partial
 from typing import Any, Union, Sequence
 from datetime import datetime, timedelta
 from email.headerregistry import Address
+
+
+import werkzeug.wrappers.response
 from email_validator import validate_email, EmailNotValidError
 from flask import (
     flash,
@@ -17,15 +20,14 @@ from flask import (
     jsonify,
     url_for,
     redirect,
-    Response,
     Blueprint,
     current_app,
     make_response,
-    render_template)
+    render_template,
+    Response as _Response)
 
 from gn_libs import sqlite3 as db
 from gn_libs.sqlite3 import with_db_connection
-from gn_libs.privileges.system import can_create_or_delete_user
 from gn_libs.privileges.resources import can_assign_role
 
 from gn_auth.smtp import send_message, build_email_message
@@ -33,9 +35,7 @@ from gn_auth.smtp import send_message, build_email_message
 from gn_auth.auth.requests import request_json
 
 
-from gn_auth.auth.authorisation.resources.system.models import (
-    system_resource,
-    user_roles_on_system)
+from gn_auth.auth.authorisation.resources.system.models import system_resource
 
 from gn_auth.auth.authorisation.resources.checks import authorised_for2
 from gn_auth.auth.authorisation.resources.models import (
@@ -63,7 +63,6 @@ from gn_auth.auth.authentication.oauth2.models.oauth2token import (
     token_by_access_token)
 
 from .models import list_users
-from .admin.models import create_verified_user
 from .masquerade.views import masq
 from .collections.views import collections
 
@@ -73,6 +72,8 @@ users = Blueprint("users", __name__)
 users.register_blueprint(masq, url_prefix="/masquerade")
 users.register_blueprint(collections, url_prefix="/collections")
 
+Response = Union[_Response, werkzeug.wrappers.response.Response]
+
 @users.route("/", methods=["GET"])
 @require_oauth("profile")
 def user_details() -> Response:
@@ -761,50 +762,6 @@ def delete_users():
     }), 400
 
 
-@users.route("/create", methods=["POST"])
-def create_new_user() -> Response:
-    """Create a new User."""
-    with (require_oauth.acquire("profile") as token,
-          db.connection(current_app.config["AUTH_DB"]) as conn):
-        u_roles = user_roles_on_system(conn, token.user)
-        if not can_create_or_delete_user(tuple(
-                priv.privilege_id for role in u_roles
-                for priv in role.privileges)):
-            raise ForbiddenAccess(
-                "You need the `system:user:create-user` privilege.")
-        form = request_json()
-        errors = {}
-        try:
-            email = validate_email(
-                form.get("email", "").strip(), check_deliverability=False)
-        except EmailNotValidError as enve:
-            errors["email"] = (
-                f"E-Mail error: {'==>'.join(str(arg) for arg in enve.args)}")
-
-        try:
-            username = validate_username(form.get("name", "").strip())
-        except UsernameError as uerr:
-            errors["name"] = str(uerr.args[0])
-
-        try:
-            passwd = validate_password(
-                form.get("password", "").strip(),
-                form.get("password", "").strip())
-        except PasswordError as perr:
-            errors["password"] = str(perr.args[0])
-
-        if len(tuple(errors.keys())) > 0:
-            raise UserRegistrationError(tuple(errors.values()))
-
-        user = create_verified_user(conn, email.normalized, username, passwd)
-
-    return make_response(jsonify({
-        "user_id": str(user.user_id),
-        "email": user.email,
-        "name": user.name
-    }), 201)
-
-
 @users.route("/<uuid:user_id>/roles/assign", methods=["POST"])
 def assign_user_role(user_id: uuid.UUID) -> Response:
     """Assign a role to a user on a given resource."""
diff --git a/gn_auth/auth/system/admin/users.py b/gn_auth/auth/system/admin/users.py
new file mode 100644
index 0000000..f26518b
--- /dev/null
+++ b/gn_auth/auth/system/admin/users.py
@@ -0,0 +1,67 @@
+"""Administrative endpoints for user management."""
+from flask import jsonify, Response, Blueprint, make_response, current_app as app
+
+from gn_libs import sqlite3 as db
+
+from email_validator import validate_email, EmailNotValidError
+
+from gn_libs.privileges.system import can_create_or_delete_user
+
+from gn_auth.auth.errors import (
+    PasswordError,
+    UsernameError,
+    ForbiddenAccess,
+    UserRegistrationError)
+from gn_auth.auth.requests import request_json
+from gn_auth.auth.authentication.oauth2.resource_server import require_oauth
+from gn_auth.auth.authorisation.resources.system.models import user_roles_on_system
+from gn_auth.auth.authorisation.users.admin.models import create_verified_user
+from gn_auth.auth.authorisation.users.views import (
+    validate_password,
+    validate_username)
+
+users = Blueprint("users", __name__)
+
+
+@users.route("/create", methods=["POST"])
+def create_user() -> Response:
+    """Create a new user. Requires system:user:create-user privilege."""
+    with (require_oauth.acquire("profile") as token,
+          db.connection(app.config["AUTH_DB"]) as conn):
+        u_roles = user_roles_on_system(conn, token.user)
+        if not can_create_or_delete_user(tuple(
+                priv.privilege_id for role in u_roles
+                for priv in role.privileges)):
+            raise ForbiddenAccess(
+                "You need the `system:user:create-user` privilege.")
+        form = request_json()
+        errors = {}
+        try:
+            email = validate_email(
+                form.get("email", "").strip(), check_deliverability=False)
+        except EmailNotValidError as enve:
+            errors["email"] = (
+                f"E-Mail error: {'==>'.join(str(arg) for arg in enve.args)}")
+
+        try:
+            username = validate_username(form.get("name", "").strip())
+        except UsernameError as uerr:
+            errors["name"] = str(uerr.args[0])
+
+        try:
+            passwd = validate_password(
+                form.get("password", "").strip(),
+                form.get("password", "").strip())
+        except PasswordError as perr:
+            errors["password"] = str(perr.args[0])
+
+        if len(tuple(errors.keys())) > 0:
+            raise UserRegistrationError(tuple(errors.values()))
+
+        user = create_verified_user(conn, email.normalized, username, passwd)
+
+    return make_response(jsonify({
+        "user_id": str(user.user_id),
+        "email": user.email,
+        "name": user.name
+    }), 201)
diff --git a/gn_auth/auth/system/admin/views.py b/gn_auth/auth/system/admin/views.py
index 1ea8acd..f1f76f9 100644
--- a/gn_auth/auth/system/admin/views.py
+++ b/gn_auth/auth/system/admin/views.py
@@ -3,6 +3,8 @@
 from flask import Blueprint
 
 from .resources import resources
+from .users import users
 
 admin = Blueprint("admin", __name__)
 admin.register_blueprint(resources, url_prefix="/resources")
+admin.register_blueprint(users, url_prefix="/users")