Skip to content

feat(constance): let admins restrict anonymous user permissions DEV-2470#7286

Draft
platreth wants to merge 1 commit into
mainfrom
hugo/dev-2470-restrict-anonymous-permissions
Draft

feat(constance): let admins restrict anonymous user permissions DEV-2470#7286
platreth wants to merge 1 commit into
mainfrom
hugo/dev-2470-restrict-anonymous-permissions

Conversation

@platreth

Copy link
Copy Markdown
Contributor

📣 Summary

Server administrators can now limit which permissions may be granted to anonymous (public) users — for example, letting a form be viewed publicly while preventing its submitted data from being shared publicly.

📖 Description

Previously the set of permissions that could be handed to anonymous users was fixed for the whole server. A superuser can now narrow that set from the server configuration (Constance settings), for instance by removing "view submissions" so that public data sharing is no longer possible on that server. The server's built-in maximum still applies, so this can only make public access more restrictive, never broader.

💭 Notes

  • New Constance setting ALLOWED_ANONYMOUS_PERMISSIONS (one-per-line, in the Security fieldset). Default equals the existing settings.ALLOWED_ANONYMOUS_PERMISSIONS, so behaviour is unchanged out of the box.
  • Effective set = settings.ALLOWED_ANONYMOUS_PERMISSIONS (hard ceiling) the configured list, computed by a new get_allowed_anonymous_permissions() helper. It can only subtract from the ceiling; a permission listed outside the ceiling is ignored.
  • All 8 read sites (auth backend, object-permission mixin, permission-assignment serializer, grant utility) now go through the helper instead of reading settings directly.
  • UI is intentionally unchanged (per ticket scope): attempting to grant a now-blocked permission surfaces the existing "Failed to update permissions" toast.
  • No migration and no OpenAPI/orval regeneration — the setting is Django-admin-only and the serializer change is method-body logic, not a schema field.

👀 Preview steps

  1. ℹ️ have a superuser account and a project
  2. 🔴 [on main] there is no server setting to stop anonymous users from being granted "view submissions" — public data sharing can always be enabled
  3. 🟢 [on PR] go to /admin/constance/config/, find ALLOWED_ANONYMOUS_PERMISSIONS under Security, delete the kpi.view_submissions line, and save
  4. 🟢 in the project's Sharing settings, try to make submissions viewable publicly (assign view_submissions to the anonymous user) → it is rejected (standard "Failed to update permissions" toast)
  5. 🟢 "Anyone can view this form" (still listed) keeps working, confirming only the removed permission is blocked

@platreth platreth self-assigned this Jul 21, 2026
Add a superuser-editable Constance setting ALLOWED_ANONYMOUS_PERMISSIONS that
can further restrict which permissions anonymous (public) users may hold. The
hard-coded settings.ALLOWED_ANONYMOUS_PERMISSIONS remains the absolute ceiling;
the Constance value can only remove permissions from it, never add.

A new get_allowed_anonymous_permissions() helper returns the intersection of
the ceiling and the configured subset, and all read sites now go through it.
@platreth
platreth force-pushed the hugo/dev-2470-restrict-anonymous-permissions branch from 743dcaf to 80b88c3 Compare July 21, 2026 10:46
@platreth
platreth marked this pull request as ready for review July 21, 2026 11:07
@platreth
platreth requested review from jnm and noliveleger as code owners July 21, 2026 11:07
@platreth
platreth removed request for jnm and noliveleger July 21, 2026 11:08
@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR lets administrators restrict permissions granted to anonymous users. The main changes are:

  • Adds a Constance setting for the permitted anonymous-access subset.
  • Intersects the configured list with the server-defined maximum.
  • Routes permission checks and assignments through the new helper.
  • Adds tests for default, restricted, invalid, and empty configurations.

Confidence Score: 4/5

Existing deployment-level public access can remain active after the configuration removes its anonymous permission.

  • The new helper consistently restricts the inspected KPI permission paths.
  • Configuration changes skip the side effects that update KC/XForm access flags.
  • The new administrator-facing labels also bypass translation.

kpi/utils/permissions.py and kobo/settings/base.py

Security Review

Changing the configured permission list does not reconcile existing KC/XForm public-access flags. Previously enabled deployment endpoints may remain publicly accessible after their anonymous permission is removed from the configuration.

Reviews (1): Last reviewed commit: "feat(constance): let admins restrict ano..." | Re-trigger Greptile

Comment thread kpi/utils/permissions.py
from kpi.utils.strings import split_lines_to_list

ceiling = set(settings.ALLOWED_ANONYMOUS_PERMISSIONS)
configured = set(split_lines_to_list(config.ALLOWED_ANONYMOUS_PERMISSIONS))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Deployment Access Flags Stay Enabled

When an administrator removes a permission after a deployed form has already granted it anonymously, this intersection changes KPI authorization without running the permission-removal flow that updates KC/XForm access flags. The deployment endpoint can therefore remain public until another operation explicitly reconciles those flags.

Comment thread kobo/settings/base.py
Comment on lines +308 to +311
'ALLOWED_ANONYMOUS_PERMISSIONS': (
'\n'.join(ALLOWED_ANONYMOUS_PERMISSIONS),
'Permissions grantable to anonymous (public) users\nOne per line. '
'Can only narrow the server maximum; entries outside it are ignored.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Admin Labels Remain Untranslated

These new descriptions are displayed in the Constance admin UI but are fixed English strings. Repository policy requires user-visible backend text constants to use the translation wrapper, so administrators using another locale will still see these labels in English.

Rule Used: All text constants on both backend and frontend mu... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@platreth
platreth marked this pull request as draft July 22, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant