From 2f90ce1049d99031d95709f7318327fcfc9a6356 Mon Sep 17 00:00:00 2001 From: Rajeswari <159857629+rajeswari1301@users.noreply.github.com> Date: Fri, 29 May 2026 12:08:41 -0500 Subject: [PATCH] Fix API key permissions (#35) When creating a new API key, Docassemble lets you select permissions during creation but they were dropped silently - add_api_key function had no permissions parameter and the POST handler never read them from the request. This fix adds permissions support to add_api_key and adds the same permissions validation to the POST handler that already existed in the PATCH handler, so permissions set at creation time are now saved correctly. This is a prerequisite for contributing #24 upstream. Closes #33 --- .../docassemble/webapp/server.py | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/docassemble_webapp/docassemble/webapp/server.py b/docassemble_webapp/docassemble/webapp/server.py index fcaadae83..73a80f3c0 100644 --- a/docassemble_webapp/docassemble/webapp/server.py +++ b/docassemble_webapp/docassemble/webapp/server.py @@ -22314,8 +22314,8 @@ def api_convert_file(): return ('File not found', 404) -def add_api_key(user_id, name, method, allowed): - info = {'constraints': allowed, 'method': method, 'name': name} +def add_api_key(user_id, name, method, allowed, permissions=None): + info = {'constraints': allowed, 'method': method, 'name': name, 'permissions': permissions if permissions is not None else []} success = False for attempt in range(10): # pylint: disable=unused-variable api_key = random_alphanumeric(32) @@ -22485,7 +22485,28 @@ def do_api_user_api(user_id): return jsonify_with_status("The given name already exists", 400) if len(name) > 255: return jsonify_with_status("The name is invalid", 400) - new_api_key = add_api_key(user_id, name, method, allowed) + permissions = None + if current_user.has_role('admin') and current_user.has_role_or_permission('admin'): + permissions = post_data.get('permissions', None) + if permissions is not None: + if isinstance(permissions, str): + try: + permissions = json.loads(permissions) + except: + return jsonify_with_status("Permissions list not valid json", 400) + if not isinstance(permissions, list): + return jsonify_with_status("Permissions list not a valid list", 400) + try: + for item in permissions: + assert isinstance(item, str) + except: + return jsonify_with_status("Permissions list should contain all strings", 400) + try: + for item in permissions: + assert item in PERMISSIONS_LIST + except: + return jsonify_with_status("Permissions list contained a permission that was not recognized", 400) + new_api_key = add_api_key(user_id, name, method, allowed, permissions=permissions) if new_api_key is None: return jsonify_with_status("Error creating API key", 400) return jsonify(new_api_key) @@ -22777,7 +22798,7 @@ def manage_api(): argu['tab_title'] = argu['title'] argu['page_title'] = argu['title'] permissions_data = form.permissions.data if is_admin else [] - info = {'name': form.name.data, 'method': form.method.data, 'constraints': constraints, 'limits': permissions_data} + info = {'name': form.name.data, 'method': form.method.data, 'constraints': constraints, 'permissions': permissions_data} success = False for attempt in range(10): # pylint: disable=unused-variable api_key = random_alphanumeric(32)