7
7
from typing import Any , Literal , Optional , TypedDict , Union
8
8
9
9
from aiohttp import web
10
- from aiohttp_security import authorized_userid , check_permission , permits
10
+ from aiohttp_security import check_permission , permits
11
11
from pydantic import Json , parse_obj_as
12
12
13
13
from ..security import permissions_as_dict
@@ -87,7 +87,7 @@ async def filter_by_permissions(self, request: web.Request, perm_type: str,
87
87
"""Return a filtered record containing permissible fields only."""
88
88
return {k : v for k , v in record .items ()
89
89
if await permits (request , f"admin.{ self .name } .{ k } .{ perm_type } " ,
90
- context = original or record )}
90
+ context = ( request , original or record ) )}
91
91
92
92
@abstractmethod
93
93
async def get_list (self , params : GetListParams ) -> tuple [list [Record ], int ]:
@@ -120,71 +120,69 @@ async def delete_many(self, params: DeleteManyParams) -> list[Union[int, str]]:
120
120
# https://marmelab.com/react-admin/DataProviderWriting.html
121
121
122
122
async def _get_list (self , request : web .Request ) -> web .Response :
123
- await check_permission (request , f"admin.{ self .name } .view" )
123
+ await check_permission (request , f"admin.{ self .name } .view" , context = ( request , None ) )
124
124
query = parse_obj_as (GetListParams , request .query )
125
125
126
126
# Add filters from advanced permissions.
127
- if request .app ["identity_callback" ]:
128
- identity = await authorized_userid (request )
129
- user_details = await request .app ["identity_callback" ](identity )
130
- permissions = permissions_as_dict (user_details ["permissions" ])
131
- filters = permissions .get (f"admin.{ self .name } .view" ,
132
- permissions .get (f"admin.{ self .name } .*" , {}))
133
- for k , v in filters .items ():
134
- query ["filter" ][k ] = v
127
+ # The permissions will be cached on the request from a previous permissions check.
128
+ permissions = permissions_as_dict (request ["aiohttpadmin_permissions" ])
129
+ filters = permissions .get (f"admin.{ self .name } .view" ,
130
+ permissions .get (f"admin.{ self .name } .*" , {}))
131
+ for k , v in filters .items ():
132
+ query ["filter" ][k ] = v
135
133
136
134
results , total = await self .get_list (query )
137
135
results = [await self .filter_by_permissions (request , "view" , r ) for r in results ]
138
136
results = [r for r in results if await permits (request , f"admin.{ self .name } .view" ,
139
- context = r )]
137
+ context = ( request , r ) )]
140
138
return json_response ({"data" : results , "total" : total })
141
139
142
140
async def _get_one (self , request : web .Request ) -> web .Response :
143
- await check_permission (request , f"admin.{ self .name } .view" )
141
+ await check_permission (request , f"admin.{ self .name } .view" , context = ( request , None ) )
144
142
query = parse_obj_as (GetOneParams , request .query )
145
143
146
144
result = await self .get_one (query )
147
- if not await permits (request , f"admin.{ self .name } .view" , context = result ):
145
+ if not await permits (request , f"admin.{ self .name } .view" , context = ( request , result ) ):
148
146
raise web .HTTPForbidden ()
149
147
result = await self .filter_by_permissions (request , "view" , result )
150
148
return json_response ({"data" : result })
151
149
152
150
async def _get_many (self , request : web .Request ) -> web .Response :
153
- await check_permission (request , f"admin.{ self .name } .view" )
151
+ await check_permission (request , f"admin.{ self .name } .view" , context = ( request , None ) )
154
152
query = parse_obj_as (GetManyParams , request .query )
155
153
156
154
results = await self .get_many (query )
157
155
results = [await self .filter_by_permissions (request , "view" , r ) for r in results
158
- if await permits (request , f"admin.{ self .name } .view" , context = r )]
156
+ if await permits (request , f"admin.{ self .name } .view" , context = ( request , r ) )]
159
157
return json_response ({"data" : results })
160
158
161
159
async def _create (self , request : web .Request ) -> web .Response :
162
160
query = parse_obj_as (CreateParams , request .query )
163
- await check_permission (request , f"admin.{ self .name } .add" , context = query ["data" ])
161
+ await check_permission (request , f"admin.{ self .name } .add" , context = ( request , query ["data" ]) )
164
162
for k , v in query ["data" ].items ():
165
163
if v is not None :
166
164
await check_permission (request , f"admin.{ self .name } .{ k } .add" ,
167
- context = query ["data" ])
165
+ context = ( request , query ["data" ]) )
168
166
169
167
result = await self .create (query )
170
168
result = await self .filter_by_permissions (request , "view" , result )
171
169
return json_response ({"data" : result })
172
170
173
171
async def _update (self , request : web .Request ) -> web .Response :
174
- await check_permission (request , f"admin.{ self .name } .edit" )
172
+ await check_permission (request , f"admin.{ self .name } .edit" , context = ( request , None ) )
175
173
query = parse_obj_as (UpdateParams , request .query )
176
174
177
175
# Check original record is allowed by permission filters.
178
176
original = await self .get_one ({"id" : query ["id" ]})
179
- if not await permits (request , f"admin.{ self .name } .edit" , context = original ):
177
+ if not await permits (request , f"admin.{ self .name } .edit" , context = ( request , original ) ):
180
178
raise web .HTTPForbidden ()
181
179
182
180
# Filter rather than forbid because react-admin still sends fields without an
183
181
# input component. The query may not be the complete dict though, so we must
184
182
# pass original for testing.
185
183
query ["data" ] = await self .filter_by_permissions (request , "edit" , query ["data" ], original )
186
184
# Check new values are allowed by permission filters.
187
- if not await permits (request , f"admin.{ self .name } .edit" , context = query ["data" ]):
185
+ if not await permits (request , f"admin.{ self .name } .edit" , context = ( request , query ["data" ]) ):
188
186
raise web .HTTPForbidden ()
189
187
190
188
if not query ["data" ]:
@@ -195,24 +193,24 @@ async def _update(self, request: web.Request) -> web.Response:
195
193
return json_response ({"data" : result })
196
194
197
195
async def _delete (self , request : web .Request ) -> web .Response :
198
- await check_permission (request , f"admin.{ self .name } .delete" )
196
+ await check_permission (request , f"admin.{ self .name } .delete" , context = ( request , None ) )
199
197
query = parse_obj_as (DeleteParams , request .query )
200
198
201
199
original = await self .get_one ({"id" : query ["id" ]})
202
- if not await permits (request , f"admin.{ self .name } .delete" , context = original ):
200
+ if not await permits (request , f"admin.{ self .name } .delete" , context = ( request , original ) ):
203
201
raise web .HTTPForbidden ()
204
202
205
203
result = await self .delete (query )
206
204
result = await self .filter_by_permissions (request , "view" , result )
207
205
return json_response ({"data" : result })
208
206
209
207
async def _delete_many (self , request : web .Request ) -> web .Response :
210
- await check_permission (request , f"admin.{ self .name } .delete" )
208
+ await check_permission (request , f"admin.{ self .name } .delete" , context = ( request , None ) )
211
209
query = parse_obj_as (DeleteManyParams , request .query )
212
210
213
211
originals = await self .get_many (query )
214
212
allowed = await asyncio .gather (* (permits (request , f"admin.{ self .name } .delete" ,
215
- context = r ) for r in originals ))
213
+ context = ( request , r ) ) for r in originals ))
216
214
if not all (allowed ):
217
215
raise web .HTTPForbidden ()
218
216
0 commit comments