|
7 | 7 |
|
8 | 8 |
|
9 | 9 | async def flush_pending_perm_ops(request): |
10 | | - """Execute any pending direct-permission writes on the request's session. |
11 | | -
|
12 | | - Called after ``after_create`` / ``after_update`` so the ops run on the |
13 | | - same session (and thus the same SQLite connection) as the main request. |
14 | | - """ |
15 | | - from sqlalchemy import text |
16 | | - |
17 | | - from fastapi_admin_kit.db import get_db_session |
18 | | - |
19 | | - ops = getattr(request.state, "_admin_perm_pending_ops", None) |
20 | | - if not ops: |
21 | | - return |
22 | | - request.state._admin_perm_pending_ops = [] |
23 | | - session = get_db_session(request) |
24 | | - if session is None: |
25 | | - return |
26 | | - for sql_str, params in ops: |
27 | | - await session.execute(text(sql_str), params) |
| 10 | + """No-op — direct permissions are now saved immediately.""" |
| 11 | + pass |
28 | 12 |
|
29 | 13 |
|
30 | 14 | def _get_table_names() -> list[str]: |
@@ -115,66 +99,72 @@ def after_update(self, obj, request=None): |
115 | 99 | self._save_direct_permissions_after_commit(obj, perm_data, request) |
116 | 100 |
|
117 | 101 | def _save_direct_permissions_after_commit(self, obj, perm_data, request): |
118 | | - delete_sql = "DELETE FROM admin_user_permissions WHERE user_id = :uid" |
119 | | - insert_sql = ( |
120 | | - "INSERT INTO admin_user_permissions" |
121 | | - " (user_id, table_name, can_view, can_create, can_edit, can_delete)" |
122 | | - " VALUES (:uid, :tn, :cv, :cc, :ce, :cd)" |
123 | | - ) |
124 | | - |
125 | | - ops = [] |
126 | | - ops.append((delete_sql, {"uid": obj.id})) |
127 | | - |
128 | | - for table_name, perms in perm_data.items(): |
129 | | - if not any(perms.get(a) for a in ["view", "create", "edit", "delete"]): |
130 | | - continue |
131 | | - ops.append( |
132 | | - ( |
133 | | - insert_sql, |
134 | | - { |
135 | | - "uid": obj.id, |
136 | | - "tn": table_name, |
137 | | - "cv": 1 if perms.get("view") else 0, |
138 | | - "cc": 1 if perms.get("create") else 0, |
139 | | - "ce": 1 if perms.get("edit") else 0, |
140 | | - "cd": 1 if perms.get("delete") else 0, |
141 | | - }, |
142 | | - ) |
143 | | - ) |
| 102 | + """Save direct user permissions after the user object is committed. |
| 103 | +
|
| 104 | + perm_data: list of permission IDs, e.g. [1, 3, 5] |
| 105 | + """ |
| 106 | + import asyncio |
| 107 | + |
| 108 | + from sqlalchemy import delete |
| 109 | + |
| 110 | + from fastapi_admin_kit.auth.models import UserPermission |
| 111 | + |
| 112 | + perm_ids = perm_data if isinstance(perm_data, list) else [] |
| 113 | + |
| 114 | + async def _do_save(): |
| 115 | + from fastapi_admin_kit.db import get_db_session |
| 116 | + |
| 117 | + session = get_db_session(request) |
| 118 | + # Delete existing direct permissions for this user |
| 119 | + await session.execute(delete(UserPermission).where(UserPermission.user_id == obj.id)) |
144 | 120 |
|
145 | | - if not hasattr(request.state, "_admin_perm_pending_ops"): |
146 | | - request.state._admin_perm_pending_ops = [] |
147 | | - request.state._admin_perm_pending_ops.extend(ops) |
| 121 | + # Insert new direct permissions |
| 122 | + for perm_id in perm_ids: |
| 123 | + up = UserPermission(user_id=obj.id, permission_id=perm_id) |
| 124 | + session.add(up) |
| 125 | + |
| 126 | + await session.commit() |
| 127 | + |
| 128 | + try: |
| 129 | + loop = asyncio.get_event_loop() |
| 130 | + if loop.is_running(): |
| 131 | + asyncio.ensure_future(_do_save()) |
| 132 | + else: |
| 133 | + loop.run_until_complete(_do_save()) |
| 134 | + except RuntimeError: |
| 135 | + asyncio.run(_do_save()) |
148 | 136 |
|
149 | 137 | async def get_form_context(self, context, obj=None, request=None): |
150 | 138 | """Load direct permissions for the user being edited.""" |
151 | 139 | from sqlalchemy import select |
152 | 140 |
|
153 | | - from fastapi_admin_kit.auth.models import UserPermission |
| 141 | + from fastapi_admin_kit.auth.models import Permission, UserPermission |
154 | 142 | from fastapi_admin_kit.db import get_db_session |
155 | 143 |
|
156 | | - perm_data = {} |
| 144 | + perm_data = [] |
157 | 145 | if obj is not None and request is not None: |
158 | 146 | try: |
159 | 147 | session = get_db_session(request) |
160 | 148 | result = await session.execute( |
161 | | - select(UserPermission).where(UserPermission.user_id == obj.id) |
| 149 | + select(UserPermission, Permission) |
| 150 | + .join(Permission, UserPermission.permission_id == Permission.id) |
| 151 | + .where(UserPermission.user_id == obj.id) |
162 | 152 | ) |
163 | | - for p in result.scalars(): |
164 | | - perm_data[p.table_name] = { |
165 | | - "_label": p.table_name, |
166 | | - "view": p.can_view, |
167 | | - "create": p.can_create, |
168 | | - "edit": p.can_edit, |
169 | | - "delete": p.can_delete, |
170 | | - } |
| 153 | + for up, perm in result: |
| 154 | + perm_data.append( |
| 155 | + { |
| 156 | + "id": perm.id, |
| 157 | + "name": perm.name, |
| 158 | + "table_name": perm.table_name, |
| 159 | + } |
| 160 | + ) |
171 | 161 | except Exception as exc: |
172 | 162 | import logging |
173 | 163 |
|
174 | 164 | logging.getLogger(__name__).debug("Permission load failed: %s", exc) |
175 | 165 |
|
176 | 166 | context["perm_data"] = perm_data |
177 | | - context["search_url"] = "/admin/tables/search" |
| 167 | + context["search_url"] = "/admin/permissions/search" |
178 | 168 | return context |
179 | 169 |
|
180 | 170 | def process_form_data(self, data, request=None): |
|
0 commit comments