Skip to content

Instantly share code, notes, and snippets.

@simonw
Created October 24, 2025 19:20
Show Gist options
  • Select an option

  • Save simonw/f721ceef19df17b297f59b1b3d776fad to your computer and use it in GitHub Desktop.

Select an option

Save simonw/f721ceef19df17b297f59b1b3d776fad to your computer and use it in GitHub Desktop.
Terminal output HTML
<pre style="background: rgb(42, 42, 42); color: rgb(255, 255, 255); padding: 15px; border-radius: 4px;"><span style="color: rgb(255, 255, 255);">&gt; The logic in AllowedResourcesView has got very complex, could that be refactored to use the new </span>
<span style="color: rgb(255, 255, 255);">datasette.allowed_resources methods? </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Good idea! Yes, the </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">AllowedResourcesView</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> can be significantly simplified by using the </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette.allowed_resources()</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> method. Let me refactor it:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Read</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(datasette/views/special.py)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">Read </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">250</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> lines</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> You're absolutely right! This is way too complex. Let me refactor it to use </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette.allowed_resources()</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Update</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(datasette/views/special.py)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">Updated </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">datasette/views/special.py</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> with </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">42</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> additions and </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">136</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> removals </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 263 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> page_size = max_page_size</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 264 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> offset = (page - 1) * page_size</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 265 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 266 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_sql, candidate_params = self.CANDIDATE_SQL[action]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 267 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 268 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- db = self.ds.get_internal_database()</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 269 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_tables = set()</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 270 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if "catalog_tables" in candidate_sql:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 271 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_tables.add("catalog_tables")</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 272 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if "catalog_databases" in candidate_sql:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 273 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_tables.add("catalog_databases")</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 274 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 275 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for table in required_tables:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 276 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if not await db.table_exists(table):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 277 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- headers = </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">{</span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">}</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 278 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if self.ds.cors:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 279 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- add_cors_headers(headers)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 280 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- return Response.json(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 281 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">{</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 282 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "action": action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 283 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "actor_id": (actor or </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">{</span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">}).get("id") if actor else None,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 284 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "page": page,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 285 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "page_size": page_size,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 286 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "total": 0,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 287 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "items": [],</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 288 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">},</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 289 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- headers=headers,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 290 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- )</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 291 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 292 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Check if this action requires another action</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 293 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- action_obj = self.ds.actions.get(action)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 294 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if action_obj and action_obj.also_requires:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 295 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Need to combine results from both actions</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 296 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Get allowed resources for the main action</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 297 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 298 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for block in pm.hook.permission_resources_sql(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 299 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- datasette=self.ds,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 300 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- actor=actor,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 266 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Use the simplified allowed_resources method</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 267 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ try:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 268 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ allowed_resources = await self.ds.allowed_resources(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 269 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> action=action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 270 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- ):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 271 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- block = await await_me_maybe(block)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 272 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if block is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 273 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- continue</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 274 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if isinstance(block, (list, tuple)):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 275 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidates = block</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 276 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- else:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 277 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidates = [block]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 278 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for candidate in candidates:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 279 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if candidate is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 280 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- continue</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 281 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins.append(candidate)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 282 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 283 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- main_rows = await resolve_permissions_from_catalog(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 284 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- db,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 270 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> actor=actor,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 271 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins=plugins,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 272 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- action=action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 273 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_sql=candidate_sql,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 274 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_params=candidate_params,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 275 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- implicit_deny=True,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 271 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ parent=parent_filter,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 272 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> )</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 273 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- main_allowed = </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">{</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 274 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- (row["parent"], row["child"]) for row in main_rows if row["allow"] == 1</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 275 </span><span style="color: rgb(242, 242, 242); background: rgb(101, 28, 41);">- </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);"> </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">}</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 276 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 277 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Get allowed resources for the required action</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 278 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_action = action_obj.also_requires</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 279 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_candidate_sql, required_candidate_params = self.CANDIDATE_SQL.get(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 280 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_action, (None, None)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 273 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ except Exception:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 274 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # If catalog tables don't exist yet, return empty results</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 275 </span><span style="color: rgb(242, 242, 242); background: rgb(28, 75, 32);">+ </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);"> </span><span style="color: rgb(255, 255, 255); background: rgb(48, 153, 78);">headers = </span><span style="color: rgb(255, 255, 255); background: rgb(48, 153, 78);">{</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">}</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 276 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ if self.ds.cors:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 277 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ add_cors_headers(headers)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 278 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ return Response.json(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 279 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">{</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 280 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "action": action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 281 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "actor_id": actor_id,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 282 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "page": page,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 283 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "page_size": page_size,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 284 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "total": 0,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 285 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "items": [],</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 286 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">},</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 287 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ headers=headers,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 288 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> )</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 289 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if not required_candidate_sql:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 290 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # If the required action doesn't have candidate SQL, deny everything</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 291 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- allowed_rows = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 292 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- else:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 293 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_plugins = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 294 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for block in pm.hook.permission_resources_sql(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 295 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- datasette=self.ds,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 296 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- actor=actor,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 297 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- action=required_action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 298 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- ):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 299 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- block = await await_me_maybe(block)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 300 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if block is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 301 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- continue</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 302 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if isinstance(block, (list, tuple)):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 303 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidates = block</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 304 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- else:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 305 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidates = [block]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 306 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for candidate in candidates:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 307 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if candidate is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 308 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- continue</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 309 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_plugins.append(candidate)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 289 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 290 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_rows = await resolve_permissions_from_catalog(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 291 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- db,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 292 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- actor=actor,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 293 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins=required_plugins,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 294 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- action=required_action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 295 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_sql=required_candidate_sql,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 296 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_params=required_candidate_params,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 297 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- implicit_deny=True,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 298 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- )</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 299 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- required_allowed = </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">{</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 300 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- (row["parent"], row["child"])</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 301 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for row in required_rows</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 302 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if row["allow"] == 1</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 303 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">}</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 290 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Convert to list of dicts with resource path</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 291 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ allowed_rows = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 292 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ for resource in allowed_resources:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 293 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ parent_val = resource.parent</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 294 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ child_val = resource.child</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 295 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 296 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Intersect the two sets - only resources allowed by BOTH actions</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 297 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- allowed_resources = main_allowed &amp; required_allowed</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 296 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Build resource path</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 297 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ if parent_val is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 298 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ resource_path = "/"</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 299 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ elif child_val is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 300 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ resource_path = f"/</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">{parent_val</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">}"</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 301 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ else:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 302 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ resource_path = f"/</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">{parent_val</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">}/</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">{child_val</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">}"</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 303 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 304 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Get full row data for the allowed resources</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 305 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- allowed_rows = [</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 306 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- row</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 307 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for row in main_rows</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 308 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if row["allow"] == 1</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 309 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- and (row["parent"], row["child"]) in allowed_resources</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 310 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- ]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 311 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- else:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 312 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # No also_requires, use normal path</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 313 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 314 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for block in pm.hook.permission_resources_sql(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 315 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- datasette=self.ds,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 316 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- actor=actor,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 317 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- action=action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 318 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- ):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 319 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- block = await await_me_maybe(block)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 320 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if block is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 321 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- continue</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 322 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if isinstance(block, (list, tuple)):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 323 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidates = block</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 324 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- else:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 325 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidates = [block]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 326 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- for candidate in candidates:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 327 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if candidate is None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 328 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- continue</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 329 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins.append(candidate)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 304 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ row = </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">{</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 305 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "parent": parent_val,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 306 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "child": child_val,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 307 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ "resource": resource_path,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 308 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">}</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 309 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 310 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- rows = await resolve_permissions_from_catalog(</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 311 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- db,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 312 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- actor=actor,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 313 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- plugins=plugins,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 314 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- action=action,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 315 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_sql=candidate_sql,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 316 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- candidate_params=candidate_params,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 317 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- implicit_deny=True,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 318 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- )</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 310 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Add debug fields if available</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 311 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ if has_debug_permission and hasattr(resource, "_reason"):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 312 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ row["reason"] = resource._reason</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 313 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ if has_debug_permission and hasattr(resource, "_source_plugin"):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 314 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ row["source_plugin"] = resource._source_plugin</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 315 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 316 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- allowed_rows = [row for row in rows if row["allow"] == 1]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 316 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ allowed_rows.append(row)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 317 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> if parent_filter is not None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 318 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> allowed_rows = [</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 319 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> row for row in allowed_rows if row["parent"] == parent_filter</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Good! But I also need to remove the now-redundant parent_filter check and update how items are built. Let me continue:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Update</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(datasette/views/special.py)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">Updated </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">datasette/views/special.py</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> with </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">6</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> additions and </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">16</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> removals </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 314 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> row["source_plugin"] = resource._source_plugin</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 315 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 316 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> allowed_rows.append(row)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 317 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if parent_filter is not None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 318 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- allowed_rows = [</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 319 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- row for row in allowed_rows if row["parent"] == parent_filter</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 320 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- ]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 317 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 318 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Apply child filter if specified</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 319 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> if child_filter is not None:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 320 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> allowed_rows = [row for row in allowed_rows if row["child"] == child_filter]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 321 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 322 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Pagination</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 323 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> total = len(allowed_rows)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 324 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> paged_rows = allowed_rows[offset : offset + page_size]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 325 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 326 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- items = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 327 </span><span style="color: rgb(242, 242, 242); background: rgb(101, 28, 41);">- </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);"> </span><span style="color: rgb(255, 255, 255); background: rgb(162, 67, 88);">for</span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);"> </span><span style="color: rgb(255, 255, 255); background: rgb(162, 67, 88);">row</span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);"> </span><span style="color: rgb(255, 255, 255); background: rgb(162, 67, 88);">in </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">paged_rows</span><span style="color: rgb(255, 255, 255); background: rgb(162, 67, 88);">:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 328 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- item = </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">{</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 329 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "parent": row["parent"],</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 330 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "child": row["child"],</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 331 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- "resource": row["resource"],</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 332 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">}</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 333 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- # Only include sensitive fields if user has permissions-debug</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 334 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- if has_debug_permission:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 335 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- item["reason"] = row["reason"]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 336 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- item["source_plugin"] = row["source_plugin"]</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 337 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- items.append(item)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 326 </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);">+ # Items are already in the right format</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 327 </span><span style="color: rgb(242, 242, 242); background: rgb(28, 75, 32);">+ </span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);"> </span><span style="color: rgb(255, 255, 255); background: rgb(48, 153, 78);">items</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);"> </span><span style="color: rgb(255, 255, 255); background: rgb(48, 153, 78);">=</span><span style="color: rgb(255, 255, 255); background: rgb(28, 75, 32);"> paged_rows</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 328 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 329 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> def build_page_url(page_number):</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 330 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> pairs = []</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Now let me also remove the imports that are no longer needed:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Read</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(datasette/views/special.py)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">Read </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">30</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> lines</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> The imports for </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">pm</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">, </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">await_me_maybe</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">, </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">resolve_permissions_from_catalog</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">, and </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">PermissionSQL</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> are no longer needed by</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">AllowedResourcesView</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">. But let me check if they're used elsewhere in the file before removing them:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(grep -n "resolve_permissions_from_catalog</span>\<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">|await_me_maybe</span>\<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">|PermissionSQL" datasette/views/special.py | grep -v "^13:"</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> | head -10)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">8: await_me_maybe, </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> 12:from datasette.permissions import PermissionSQL</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> They're still in the imports but let me check if they're actually used:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(grep -n "resolve_permissions_from_catalog" datasette/views/special.py | grep -v "^13:")</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);">No matches found</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(grep -n "await_me_maybe" datasette/views/special.py | grep -v "^8:")</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);">No matches found</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(grep -n "PermissionSQL</span>\<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">|pm</span>\\<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">.hook" datasette/views/special.py | grep -v "^12:</span>\<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">|^14:")</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);">No matches found</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Good! None of these imports are used anymore. Let me remove them:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Update</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(datasette/views/special.py)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">Updated </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">datasette/views/special.py</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> with </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">4</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> removals </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 5 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> from datasette.utils import (</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 6 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> actor_matches_allow,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 7 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> add_cors_headers,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 8 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- await_me_maybe,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 8 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> tilde_encode,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 9 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> tilde_decode,</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 10 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> )</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 11 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- from datasette.permissions import PermissionSQL</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 12 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- from datasette.utils.permissions import resolve_permissions_from_catalog</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 13 </span><span style="color: rgb(255, 255, 255); background: rgb(101, 28, 41);">- from datasette.plugins import pm</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 11 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> from .base import BaseView, View</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 12 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> import secrets</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> 13 </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);"> import urllib</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Perfect! Now let me run the tests to make sure the refactoring works:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(pytest tests/test_permission_endpoints.py -xvs -k "test_allowed")</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> ============================= test session starts ============================== </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> platform darwin -- Python 3.10.4, pytest-8.4.2, pluggy-1.5.0 -- /Users/simon/.local/share/virtualenvs/datasette-AWNr</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Qs95/bin/python</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span>…<span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> +27 lines (ctrl+o to expand)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Excellent! All the allowed endpoint tests pass. Let me also run the execute-sql test to make sure the also_requires</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> feature still works:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(pytest tests/test_permission_endpoints.py::test_execute_sql_requires_view_database -xvs)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> ============================= test session starts ============================== </span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> platform darwin -- Python 3.10.4, pytest-8.4.2, pluggy-1.5.0 -- /Users/simon/.local/share/virtualenvs/datasette-AWNr</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Qs95/bin/python</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span>…<span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> +11 lines (ctrl+o to expand)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Perfect! Now let me run all the permission tests to make sure everything still works:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Bash</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">(pytest tests/test_permission_endpoints.py tests/test_utils_permissions.py)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span> <span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">============================= test session starts ==============================</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> platform darwin -- Python 3.10.4, pytest-8.4.2, pluggy-1.5.0</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> SQLite: 3.51.0</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span>…<span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);"> +10 lines (ctrl+o to expand)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> Excellent! All tests pass. Let me create a summary of the refactoring:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Summary</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> I successfully refactored </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">AllowedResourcesView</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> in </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette/views/special.py</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> to use the simplified</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette.allowed_resources()</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> method. This dramatically reduced the complexity of the code:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);">Changes Made:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> 1. </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Replaced complex plugin gathering and SQL resolution</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> with a simple call to </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette.allowed_resources()</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Removed ~150 lines of complex code that manually called plugin hooks, built CTEs, and performed set intersections</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> for </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">also_requires</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - The </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">also_requires</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> logic is now handled automatically by </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette.allowed_resources()</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> 2. </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Simplified resource conversion</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Directly iterate over the returned </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">Resource</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> objects</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Build the response format inline without intermediate data structures</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> 3. </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Removed unnecessary imports</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">await_me_maybe</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - no longer needed</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">PermissionSQL</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - no longer needed</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">resolve_permissions_from_catalog</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - no longer needed</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">pm</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> (plugin manager) - no longer needed</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> 4. </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Maintained all functionality</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Pagination still works</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Parent/child filtering still works</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Debug fields (reason, source_plugin) still included when user has permissions-debug</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - Error handling for missing catalog tables</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - All 33 tests pass</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> </span><span style="color: rgb(97, 97, 97); background: rgb(0, 0, 0);">Benefits:</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Much simpler code</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">: Reduced from ~150 lines of complex logic to ~50 lines</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Easier to maintain</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">: Uses a single, well-tested method instead of duplicating permission logic</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Automatically benefits from improvements</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">: Any enhancements to </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">allowed_resources()</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> (like the </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">also_requires</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> feature)</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> work automatically</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> - </span><span style="color: rgb(255, 255, 255); background: rgb(0, 0, 0);">Consistent behavior</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);">: The endpoint now uses the exact same logic as the rest of the codebase</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> The refactoring demonstrates that the new </span><span style="color: rgb(162, 168, 247); background: rgb(0, 0, 0);">datasette.allowed_resources()</span><span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> API is working as intended - it provides a</span>
<span style="color: rgb(242, 242, 242); background: rgb(0, 0, 0);"> simple, high-level interface that handles all the complexity internally.</span>
</pre>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment