pelagia-portal/App
Hardik 3556b1425f feat(profile): user profile page, manager signature, and SuperUser access requests
Schema (migration: 20260516103515_user_profile_signature):
- User.signatureKey String? — storage key for the manager's approval signature
- New RequestStatus enum (PENDING / APPROVED / DENIED)
- New SuperUserRequest model — tracks access-escalation requests from users

Profile page (/profile) — all roles:
- Account info panel (name, email, employee ID, role — read-only)
- Change password form (validates current password, bcrypt hash on save)
- Signature uploader (MANAGER / SUPERUSER only) — PNG/JPG/WebP up to 2 MB;
  previews before save; can remove existing signature
- SuperUser access request form — textarea for reason, shows current request
  status (pending / approved / denied) after submission

Signature gate on approval page (/approvals/[id]):
- Server checks if the current manager has uploaded a signatureKey
- If missing: shows an amber warning banner with a deep-link to /profile
  instead of rendering the approval action buttons; managers cannot
  approve, reject, or request edits without a signature on file

PDF and XLSX exports:
- Fetches the approver's signature image from storage after identifying
  the approval action
- PDF: embeds as base64 data URI <img> above the approver name in the
  left signature block
- XLSX: inserts the image into the sig-row cells via ExcelJS addImage;
  adds a name row below the image for legibility

SuperUser requests admin page (/admin/superuser-requests):
- Pending requests listed with user info, role, reason, and Approve/Deny buttons
- Approve: sets user.role = SUPERUSER and closes the request
- Deny: marks request DENIED, user role unchanged
- Resolved history table below

Admin user management updates (/admin/users):
- "SuperUser" button (ShieldCheck icon) on every non-superuser, non-admin row
- Directly grants SUPERUSER role and auto-closes any open request for that user

lib/storage.ts:
- buildSignatureKey(userId, ext) helper
- uploadBuffer(key, buffer, contentType) — server-side write to dev-uploads or R2
- downloadBuffer(key) — server-side read from dev-uploads or R2 presigned URL

Sidebar:
- "My Profile" link (UserCircle) visible to all roles
- "SuperUser Requests" link (ShieldCheck) in admin section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 16:09:30 +05:30
..
pelagia-portal feat(profile): user profile page, manager signature, and SuperUser access requests 2026-05-16 16:09:30 +05:30