Skip to content

feat: admin role + /admin page to manage custom attributes#522

Open
JeromeBu wants to merge 1 commit into
mainfrom
feat/admin-page-attribute-definitions
Open

feat: admin role + /admin page to manage custom attributes#522
JeromeBu wants to merge 1 commit into
mainfrom
feat/admin-page-attribute-definitions

Conversation

@JeromeBu
Copy link
Copy Markdown
Collaborator

@JeromeBu JeromeBu commented May 7, 2026

Summary

  • Adds a role column on users (user | admin, default user, promote manually with SQL) and an adminProcedure middleware on tRPC.
  • New /admin page (admin-only) listing software_attribute_definitions with create/edit (delete deferred — values are stored in the softwares.customAttributes JSONB).
  • New web slice adminAttributes, shared icon module, conditional shield-icon link in the user menu.

Bootstrap an admin

Migration only sets the column. Promote a user manually:

UPDATE users SET role = 'admin' WHERE email = '...';

API surface

Route Auth Notes
getAttributeDefinitions logged Read-only list
createAttributeDefinition admin Rejects duplicate name and duplicate displayOrder (CONFLICT)
updateAttributeDefinition admin name and kind are not editable

Test plan

  • pnpm db:up (applies migration 1778168171859_add-user-role)
  • psql … -c "\d users" shows role text NOT NULL DEFAULT 'user' + check constraint
  • As a non-admin user: direct call to createAttributeDefinition returns FORBIDDEN; /admin redirects to home; admin link is hidden
  • UPDATE users SET role='admin' WHERE email='…' then re-login
  • Admin link appears (shield icon, label "Admin"); /admin shows the 4 existing definitions with FR labels + identifier underneath
  • Edit an attribute: name and kind are disabled, the rest is editable; saving updates the row
  • Create a new string attribute testField with displayInForm = true → appears in the table and in the software-form
  • Validation: identifier 123abc / with-dash are rejected; reusing an existing displayOrder returns a CONFLICT alert
  • pnpm fullcheck green

🤖 Generated with Claude Code

Adds a `role` column on users (default `user`, manual promote-by-SQL)
and a new `/admin` page reachable from the user menu (admin-only). The
page lists `software_attribute_definitions` and lets an administrator
create or edit them; deletion is intentionally deferred since values
are stored in the `softwares.customAttributes` JSONB.

API:
- Migration adding `users.role TEXT NOT NULL DEFAULT 'user'` with a
  `CHECK (role IN ('user','admin'))` constraint.
- `adminProcedure` middleware (FORBIDDEN if `currentUser.role !== "admin"`).
- New routes: `getAttributeDefinitions` (logged), `createAttributeDefinition`
  and `updateAttributeDefinition` (admin). Server-side check rejects a
  duplicate `displayOrder` with CONFLICT.
- `AttributeDefinitionRepository` gains `add` and `update`.

Web:
- New page `web/src/ui/pages/admin/{Admin,AttributeDefinitionFormModal}`
  + `adminAttributes` redux slice; admin link conditionally rendered in
  `<AuthButtons>` (shield icon).
- Shared `attributeIcons` module exposes the icon-name → DSFR class map
  and the value list, reused by the table and the form button group.

Bootstrap an admin manually:
`UPDATE users SET role = 'admin' WHERE email = '...';`

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant