about summary refs log tree commit diff
path: root/gn_auth/auth/system/admin
diff options
context:
space:
mode:
Diffstat (limited to 'gn_auth/auth/system/admin')
-rw-r--r--gn_auth/auth/system/admin/users.py67
-rw-r--r--gn_auth/auth/system/admin/views.py2
2 files changed, 69 insertions, 0 deletions
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")