Batch anonymous authorization checks per object - #6257
bram-atmire wants to merge 2 commits into
Conversation
An anonymous item render fires ~15 per-feature authorization checks, about ten of which ask about admin/edit/login-only capabilities an unauthenticated visitor can never hold. AuthorizationDataService.isAuthorized now answers false locally, without a REST call, for those features when no one is logged in, and waits for isAuthenticationLoaded() before deciding so authenticated users are never transiently treated as anonymous. Measured on a local DSpace 11 stack with OpenTelemetry tracing: an anonymous item render drops from 42 to 31 backend calls (15 to 5 authorization checks) and single-core SSR render throughput rises ~45%. Refs DSpace#6256, DSpace#3161 Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
|
Hi @bram-atmire, thanks for the PR! Would you be able to add the complete PR checklist to the description? Also you may have already seen, but this is currently running into a few errors in the CI (looks like just linting). |
|
This is a big step towards a good idea. Cutting waste on anonymous traffic-the largest load contributor-feels like exactly the right place to optimize After checking the code, I have a tiiiny comment regarding the open design question you asked:
Personally, I lean toward the backend-first approach rather than frontend changes. Genuine question, did you already consider defining the whitelist directly in the backend instead of the frontend? This is my "open design question for open design question", but how would you feel about this alternative:
Does that make sense? My reasoning for the backend-first approach is that:
Happy to see this moving. Overall, great work (on all your PRs lately)! |
|
@MMilosz, thank you for the review & feedback!! I agree that the backend should own the permission decisions. I removed the hardcoded frontend list. Your distinction between authentication, policy and configuration was important: QA/COAR can be enabled anonymously, and some edit/manage features can be granted through Anonymous resource policies. The companion backend PR, DSpace/DSpace#13134, adds a default-false For the HTTP request reduction, I switched Angular to the existing all-features object search. A conservative authentication-only list plus a catalogue fetch gave no net request saving on the tested item page. The revised batching shares one lookup per object and selects each feature from the grants returned by the backend. It follows pagination, uses the existing request cache/invalidation, and falls back to individual checks if a batch fails. Logged-in and explicit-EPerson checks retain their original path. No new public metadata endpoint/property is needed. The updated production SSR measurements are 14 → 2 authorization requests and 39 → 27 total API calls, consistent across 22 renders per variant. All 14 decisions matched the individual requests, and both HTML and HTTP COAR inbox links were preserved. Browser navigation required one authorization GET for a new item and none when returning to the cached item. I replaced the earlier performance claims; the timing sample does not establish a reliable throughput gain. @lgeggleston, the complete PR checklist and updated validation/reviewer instructions are now in the description. The original import-order lint issue is fixed. Local selected tests and production builds passed; the standard lint/circular checks still report generated-registry issues as documented in the description, and CI for this revision is pending. |
References
Fixes #6256. Related to the request-batching discussion in #3161.
Companion backend guard: DSpace/DSpace#13134. This request reduction uses the existing REST API and does not require that companion change or a REST contract change.
Description
Batch anonymous authorization checks per object using
/authz/authorizations/search/objectwithout a feature filter. The backend evaluates permissions once per object request; Angular selects each requested feature from the returned grants. This replaces the hardcoded list of features assumed to be denied anonymously.On the measured anonymous item page, 14 authorization requests become 2 (site and item), and total API requests fall from 39 to 27. All 14 individual decisions match the batched results, including public COAR discovery. There is no metadata catalogue request.
Authenticated visitors and explicit-EPerson queries retain individual checks. Anonymous batching uses the existing request cache for pending-request deduplication, expiry, invalidation and SSR transfer; it adds no separate permission cache. It follows all pagination links before deciding that a feature is absent. If any page fails, it falls back to the individual feature request, preserving behavior on installations with a broken custom feature.
Authentication readiness follows the same blocking flag used by application initialization. The previous
loadedcheck never completed for successful anonymous initialization.Measurements
Production builds, one public item, same local backend/data, HTML page caches disabled. Four process runs in baseline/revised/revised/baseline order; each includes one initial render and ten warm renders. The baseline is the pre-PR authorization service at
2f1bf85ce2ea.Counts were identical across all 22 renders per variant. Median warm full-response time was 270→262 ms; timings varied by run order, so this is not a demonstrated latency or throughput improvement. The measured benefit is 12 fewer HTTP requests (86% fewer authorization requests; 31% fewer total API requests). The original PR performance claims are superseded.
Browser verification: authorization GETs were 2 during hydration, 1 when navigating to a new item, and 0 on returning to the first item. CORS adds matching OPTIONS preflights. Item content and COAR inbox links were preserved with no JavaScript exceptions.
Instructions for Reviewers
ldn.enabledand visit a public item anonymously with server page caching disabled. Expect two unfiltered authorization searches (site and item), withembed=featureandsize=100, instead of one search per feature.Validation: 137 selected Angular tests passed (including a rerun of the affected tests); production browser and SSR builds passed. Full source lint passed with generated decorator registries excluded, and no source circular dependencies were found with those generated files excluded. The standard checks still encounter pre-existing generated-registry lint errors/cycles; full CI and Docker-based end-to-end tests remain pending. No new dependencies, UI text or configuration options.
Checklist
This checklist provides a reminder of what we are going to look for when reviewing your PR. You do not need to complete this checklist prior creating your PR (draft PRs are always welcome).
However, reviewers may request that you complete any actions in this list if you have not done so. If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!
mainbranch of code (unless it is a backport or is fixing an issue specific to an older branch).npm run lintnpm run check-circ-deps)package.json), I've made sure their licenses align with the DSpace BSD License based on the Licensing of Contributions documentation.Implementation and validation assisted by OpenAI Codex.