Skip to content

Ban feature is a non-functional stub — banned users can still sign in (no persistence, no enforcement) #8

@rafiki270

Description

@rafiki270

Summary

The user ban capability is not actually implemented. There is a ban UI in the design template and an empty ban structure returned by the admin API, but no persistence, no create/list/delete endpoints, and no enforcement at login or registration. As a result, "banning" a user (or email/pattern/IP) has no effect — a banned user can still authenticate and obtain tokens.

This was discovered while building the per-scope email whitelist (allowed_emails). Filing for visibility; not implementing.

Evidence (current main)

  • The ban data is a hardcoded empty constant, never backed by storage:
    • API/src/services/internal-admin.service.base.ts:35
      export const emptyBans = { emails: [], patterns: [], ips: [], users: [] };
    • The admin settings/read endpoints always return that constant:
      • API/src/services/internal-admin.service.base.ts:210bans: emptyBans
      • API/src/services/internal-admin.service.ts:64return { bans: emptyBans, apps: await getAdminApps() }
    • The API schema advertises it as real backing data: API/src/routes/root/schema.internal-admin.ts:376 ("Admin settings backing data for bans and apps").
  • No ban model exists in API/prisma/schema.prisma (no table to store bans).
  • No admin endpoint to create/list/remove a ban (grep for ban CRUD under API/src/routes/internal/admin/ returns nothing).
  • No enforcement in the auth flow. The login gate finalizeAuthenticatedUserassertEmailDomainAllowedForLogin (API/src/services/login-domain-policy.service.ts) and the registration paths (auth-register.service.ts, social/social-login.service.ts) never read the ban lists. The status: 'blocked' results in those files are the registration domain policy, not bans.
  • The only "ban" implementation is mock UI in the design template: Docs/Admin/template-admin.html:199 ("Add Ban" modal) with hardcoded sample banned users (:357, :361-363). The React Admin app and API do not implement it.

Impact

  • Operators believe they can ban abusive users/emails/domains/IPs, but the action is a no-op — banned principals retain full access.
  • Silent security gap: there is no error or signal that the ban didn't take.

Suggested direction (for whoever picks this up)

Mirror the just-shipped allowed-emails whitelist pattern:

  1. Persistence: a Ban table (scope: global and/or per client-domain/org/team to match the hierarchy), with fields for type (email | pattern | ip | user), value, reason, createdBy, createdAt.
  2. Admin API: create/list/delete endpoints under /internal/admin/..., and have the settings endpoint return real bans instead of emptyBans. Keep /api + /llm in sync.
  3. Enforcement: check bans in the single login gate (finalizeAuthenticatedUser) and in the registration paths, failing closed with the existing generic auth error (no enumeration). Decide precedence vs. the allowlist (a ban should override an allow).
  4. Admin UI: wire the existing "Add Ban" template modal to the new endpoints.

Notes

  • Brief alignment: please confirm against Docs/brief.md before implementing — the template implies ban is in scope, but the brief should be the source of truth for the exact scope (global vs per-tenant) and semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions