Skip to main content

Admin Management

Creating a Staff Account

Staff accounts are created via a CLI script inside the running API container. They cannot be created via the web UI — self-registration is blocked for @ctsolutions.gr emails.

sudo docker exec -it <api_container_name> sh -c \
"node dist/scripts/create-admin.js <email> <tempPassword> <firstName> <lastName> <role>"

Example:

sudo docker exec -it pcmr-api sh -c \
"node dist/scripts/create-admin.js [email protected] TempPass123! John Smith admin"

Valid roles: admin, superadmin

The account is created with mustChangePassword: true. The new staff member must complete the first-login flow before accessing the portal:

  1. Log in at staff.pcmr.gr/staff/login
  2. Change the temporary password
  3. Verify their email (check inbox for verification email)
  4. Set up TOTP 2FA (scan QR code with any TOTP app)
  5. Access the portal

Finding the Container Name

sudo docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"

Look for the container running the API image. In Coolify, the container name typically includes the app name and a hash.


Changing a User's Role

Via the staff portal UI:

  1. Navigate to /staff/portal/users
  2. Find the user
  3. Click on the user
  4. Use the role dropdown to change

Via API (if UI unavailable):

curl -X PATCH https://api.pcmr.gr/admin/users/<userId>/role \
-H "Cookie: __Secure-better-auth.session_token=<your_session>" \
-H "Content-Type: application/json" \
-d '{"role": "superadmin"}'

Restrictions:

  • Cannot change your own role
  • RolesGuard requires @ctsolutions.gr email for admin/superadmin roles — assigning these roles to non-staff emails is blocked

Banning a Customer

Customer accounts (role: user) can be banned. Staff accounts cannot be banned via the UI — use the database directly if needed.

Via the staff portal UI:

  1. Navigate to /staff/portal/users
  2. Find the customer
  3. Click "Ban user"
  4. Enter ban reason and optional expiry date

What banning does:

  • Sets User.banned = true, User.banReason, User.banExpires
  • Revokes all active sessions for the user immediately
  • The user will be logged out on their next request

Unbanning:

  • Navigate to the user in the staff portal
  • Click "Unban user"
  • Clears banned, banReason, banExpires
  • The user can log in again immediately

What the First-Login Flow Looks Like (for a New Staff Member)

The new staff member receives their temporary password from the person who created their account.

  1. Go to staff.pcmr.gr — Cloudflare Access will ask for email OTP verification first
  2. Log in at /staff/login with the temporary password
  3. Step 1 — Change password: Required immediately. The new password must meet minimum requirements.
  4. Step 2 — Verify email: A verification email is sent to their @ctsolutions.gr address. They click the link to verify.
  5. Step 3 — TOTP setup: Scan the QR code with any authenticator app (Google Authenticator, Authy, 1Password, etc.). Enter the 6-digit code to confirm setup.
  6. Portal access is granted.

If a step fails:

  • Email not received: Check Zoho SMTP logs; check spam folder; verify the email address is correct
  • TOTP not working: Verify device clock is synchronized (TOTP is time-based); try another authenticator app
  • Locked out after 10 failed sign-in attempts: The rate limit resets after 15 minutes

Resetting a Staff Member's MFA

If a staff member loses their TOTP device, there is currently no self-service MFA reset. Options:

  1. Direct database update (requires prod DB access):

    UPDATE "user"
    SET "twoFactorEnabled" = false
    WHERE email = '[email protected]';

    DELETE FROM "twoFactor"
    WHERE "userId" = (SELECT id FROM "user" WHERE email = '[email protected]');

    Then the user goes through TOTP setup again.

  2. Create a new account: If the old account can't be recovered, create a new staff account and delete the old one (archive their data first if needed).


Security Notes

  • Never share session tokens or temporary passwords over unencrypted channels
  • Temporary passwords should be changed before first use — mustChangePassword: true enforces this
  • The CLI script is the only way to create superadmin accounts — no API endpoint can elevate to superadmin
  • All role changes are audit-logged in the API logs (Loki)