Skip to content

Bootstrap initial SystemAdmin user from config on first boot #36

@matthewhorridge

Description

@matthewhorridge

Problem

On a fresh WebProtege install, no user has the SystemAdmin role. This blocks every admin-only operation:

  • Cannot open Application Settings (the EditApplicationSettings capability is required)
  • Cannot enable "Empty project creation allowed" for any signed-in user
  • Cannot assign roles to other users
  • Cannot create projects (unless a role is granted individually)

The only way out today is to manually insert a RoleAssignment document into MongoDB:

db.RoleAssignments.insertOne({
  userName: "<some-user>",
  projectId: null,
  assignedRoles: ["SystemAdmin"],
  roleClosure: ["SystemAdmin", "UserAdmin", "ProjectCreator", "ProjectUploader", "AccountCreator"],
  capabilityClosure: [ ...every capability spelled out... ]
})

This is brittle, hard to discover, and requires operators to reason about an internal schema.

Proposed solution

Add a config property (webprotege.auth.initialAdminUsername or similar) that the authorization service reads on startup. If set:

  1. Check whether any user already has SystemAdmin
  2. If not, create a RoleAssignment granting SystemAdmin to the configured username
  3. Compute roleClosure and capabilityClosure via the existing role-resolution logic — no hand-rolled closure arrays
  4. Log the action clearly (so operators know who became the first admin)
  5. Idempotent: if the user already has SystemAdmin, do nothing

Implementation sketch — a Spring ApplicationRunner or @EventListener(ApplicationReadyEvent.class) bean in the authorization service, reading the config property via @Value or @ConfigurationProperties.

Considerations

  • What happens if the configured user doesn't exist yet in Keycloak? Still create the RoleAssignment — the authorization service works off username strings, not Keycloak user records, so the role applies as soon as that user signs in.

  • What if the property is changed later to a different username? The new username gets SystemAdmin; the old user keeps theirs. Admins can be revoked manually through the UI once EditApplicationSettings is accessible. Not trying to do anything clever here.

  • Should this be a one-shot (runs only if no admin exists) or continuous (always ensures the configured user has admin)? One-shot is safer — avoids clobbering intentional role removals. The property is a bootstrap aid, not a source of truth.

Deploy-side changes

The webprotege-deploy compose should set this env var from .env:

webprotege-authorization-service:
  environment:
    WEBPROTEGE_AUTH_INITIALADMINUSERNAME: ${INITIAL_ADMIN_USERNAME:-}

And .env.example should document: "On first boot, set this to the webprotege_username of the user who should become the initial admin. Leave blank for existing installs where an admin already exists."

Tracking issue in the deploy repo will reference this one.

Context

Came up during protegeproject/webprotege-deploy#59 while testing a fresh install end-to-end. After registering a new user, there was no way to reach Application Settings or create projects without direct MongoDB manipulation.

Related: protegeproject/webprotege-backend-service#167 (separating internal user ID from display name — will change the shape of userName in role assignments).

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