refactor(code): Cleaned-up the code base
This commit is contained in:
710
admin-overview.md
Normal file
710
admin-overview.md
Normal file
@@ -0,0 +1,710 @@
|
||||
# WarpBox Admin Overview
|
||||
|
||||
This document maps the current WarpBox admin area, explains how the existing pages and permission model work, then proposes an overhaul path for a more useful admin product: dashboard, account management, API keys, and a role/group based authorization system.
|
||||
|
||||
## Project Context
|
||||
|
||||
WarpBox is a small self-hosted file sharing app. Its core product is deliberately simple:
|
||||
|
||||
- create temporary upload boxes
|
||||
- upload one or more files
|
||||
- optionally protect the box with a password
|
||||
- share a generated link
|
||||
- allow individual downloads or ZIP downloads
|
||||
- support one-time ZIP handoff
|
||||
- store uploads on the local filesystem
|
||||
- store app metadata in local BadgerDB
|
||||
|
||||
The project has a strong retro desktop identity. The admin area should keep that personality, but become more operationally useful. Best direction: retro surface, modern information architecture. Admin actions should feel clear, forgiving, and inspectable rather than dense or mysterious.
|
||||
|
||||
## Current Admin Architecture
|
||||
|
||||
Admin routes are registered under `/admin` in `lib/server/admin.go`.
|
||||
|
||||
Current pages:
|
||||
|
||||
- `/admin/login`
|
||||
- `/admin`
|
||||
- `/admin/boxes`
|
||||
- `/admin/users`
|
||||
- `/admin/tags`
|
||||
- `/admin/settings`
|
||||
|
||||
Admin templates live in:
|
||||
|
||||
- `templates/admin_login.html`
|
||||
- `templates/admin.html`
|
||||
- `templates/admin_boxes.html`
|
||||
- `templates/admin_users.html`
|
||||
- `templates/admin_tags.html`
|
||||
- `templates/admin_settings.html`
|
||||
|
||||
Styling uses:
|
||||
|
||||
- `static/css/admin.css`
|
||||
- shared retro UI styles from `static/css/app.css` and `static/css/window.css`
|
||||
|
||||
Metadata lives in BadgerDB through `lib/metastore`. Current admin-relevant records are:
|
||||
|
||||
- users
|
||||
- tags
|
||||
- sessions
|
||||
- settings overrides
|
||||
|
||||
## Current Login And Session Flow
|
||||
|
||||
Admin login is bootstrapped from environment configuration:
|
||||
|
||||
- `WARPBOX_ADMIN_PASSWORD`
|
||||
- `WARPBOX_ADMIN_USERNAME`
|
||||
- `WARPBOX_ADMIN_EMAIL`
|
||||
- `WARPBOX_ADMIN_ENABLED`
|
||||
|
||||
On startup, `BootstrapAdmin` ensures a protected `admin` tag exists. If a user matching the admin username already exists, the admin tag is attached to that user. If no user exists and `WARPBOX_ADMIN_PASSWORD` is set, a first admin user is created.
|
||||
|
||||
Login behavior:
|
||||
|
||||
- `GET /admin/login` shows login form when admin login is enabled.
|
||||
- `POST /admin/login` checks username/password.
|
||||
- password hashes use bcrypt.
|
||||
- disabled users cannot log in.
|
||||
- user must have effective `AdminAccess`.
|
||||
- successful login creates a BadgerDB session with random session token and CSRF token.
|
||||
- session cookie name is `warpbox_admin_session`.
|
||||
- cookie path is `/admin`.
|
||||
- cookie is HTTP-only.
|
||||
- cookie Secure flag is controlled by `WARPBOX_ADMIN_COOKIE_SECURE`.
|
||||
- session TTL is controlled by `WARPBOX_SESSION_TTL_SECONDS`.
|
||||
|
||||
All protected admin routes require:
|
||||
|
||||
- valid session cookie
|
||||
- unexpired session
|
||||
- valid CSRF token for non-GET requests
|
||||
- existing enabled user
|
||||
- effective `AdminAccess`
|
||||
|
||||
Admin responses set no-store headers and `X-Content-Type-Options: nosniff`.
|
||||
|
||||
## Current Dashboard Page
|
||||
|
||||
Route:
|
||||
|
||||
- `GET /admin`
|
||||
|
||||
Template:
|
||||
|
||||
- `templates/admin.html`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- shows signed-in username
|
||||
- provides logout button
|
||||
- shows four large links:
|
||||
- Boxes
|
||||
- Users
|
||||
- Tags
|
||||
- Settings
|
||||
|
||||
Current limitation:
|
||||
|
||||
- this is not a dashboard yet. It has no statistics, recent activity, health status, quota information, user counts, storage totals, warnings, or next actions.
|
||||
|
||||
Good future role:
|
||||
|
||||
- make this the admin home screen, with live operational summary and clear links into deeper management pages.
|
||||
|
||||
## Current Boxes Page
|
||||
|
||||
Route:
|
||||
|
||||
- `GET /admin/boxes`
|
||||
|
||||
Required permission:
|
||||
|
||||
- `AdminBoxesView`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- loads all box summaries from filesystem via `boxstore.ListBoxSummaries()`
|
||||
- shows summary counters:
|
||||
- total boxes
|
||||
- total storage
|
||||
- expired boxes
|
||||
- table columns:
|
||||
- box id
|
||||
- file count
|
||||
- size
|
||||
- created time
|
||||
- expiry time
|
||||
- flags
|
||||
- flags include:
|
||||
- expired
|
||||
- one-time
|
||||
- password
|
||||
- box id links to `/box/{id}`
|
||||
|
||||
Current limitations:
|
||||
|
||||
- no search
|
||||
- no filters
|
||||
- no pagination
|
||||
- no delete action
|
||||
- no bulk cleanup
|
||||
- no storage trend
|
||||
- no per-box detail drawer
|
||||
- no visibility into failed uploads, incomplete boxes, thumbnail state, or one-time consumption state
|
||||
- expired boxes are counted but not directly actionable
|
||||
|
||||
Good future role:
|
||||
|
||||
- operational file-sharing monitor and cleanup center.
|
||||
|
||||
## Current Users Page
|
||||
|
||||
Routes:
|
||||
|
||||
- `GET /admin/users`
|
||||
- `POST /admin/users`
|
||||
|
||||
Required permission:
|
||||
|
||||
- `AdminUsersManage`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- create user with username, email, password, and selected tags
|
||||
- list users sorted by username
|
||||
- show username, email, assigned tags, created time, status
|
||||
- enable/disable user
|
||||
- active session user cannot disable themselves
|
||||
|
||||
Current user model:
|
||||
|
||||
- `ID`
|
||||
- `Username`
|
||||
- `Email`
|
||||
- `PasswordHash`
|
||||
- `TagIDs`
|
||||
- `CreatedAt`
|
||||
- `UpdatedAt`
|
||||
- `Disabled`
|
||||
- optional per-user max file size
|
||||
- optional per-user max box size
|
||||
- optional per-user max expiry seconds
|
||||
|
||||
Current limitations:
|
||||
|
||||
- no edit user page
|
||||
- no password reset flow
|
||||
- no email verification or invite flow
|
||||
- no delete/archive user action
|
||||
- no user detail screen
|
||||
- no role preview
|
||||
- no effective permissions display
|
||||
- no API key management
|
||||
- no account activity
|
||||
- no per-user storage/upload stats
|
||||
- per-user limit fields exist in the model but are not exposed in the admin UI
|
||||
|
||||
Good future role:
|
||||
|
||||
- user account command center, optimized for quick scanning, safe edits, and permission clarity.
|
||||
|
||||
## Current Tags Page
|
||||
|
||||
Routes:
|
||||
|
||||
- `GET /admin/tags`
|
||||
- `POST /admin/tags`
|
||||
|
||||
Required permission:
|
||||
|
||||
- `AdminUsersManage`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- create a tag
|
||||
- set description
|
||||
- attach permission booleans
|
||||
- attach optional limits
|
||||
- list existing tags
|
||||
- built-in `admin` tag is protected and forced to full admin permissions
|
||||
|
||||
Current tag permissions:
|
||||
|
||||
- upload allowed
|
||||
- one-time download allowed
|
||||
- ZIP download allowed
|
||||
- renewable allowed
|
||||
- admin access
|
||||
- manage users
|
||||
- manage settings
|
||||
- view boxes
|
||||
- max file size bytes
|
||||
- max box size bytes
|
||||
- allowed expiry seconds
|
||||
- renew on access seconds exists in model but is not exposed in current tag form
|
||||
- renew on download seconds exists in model but is not exposed in current tag form
|
||||
|
||||
Permission resolution:
|
||||
|
||||
- user permissions are resolved from all assigned tags plus user-level overrides
|
||||
- boolean permissions are additive: any tag can grant a permission
|
||||
- size limits use the more permissive value
|
||||
- global max file/box limits still cap resolved user limits
|
||||
- allowed expiry seconds are merged from all tags and sorted
|
||||
- global feature flags can still disable ZIP or one-time downloads even if a tag allows them
|
||||
|
||||
Current limitations:
|
||||
|
||||
- tags mix labels, roles, groups, limits, and admin capability grants in one concept
|
||||
- no edit tag page
|
||||
- no delete tag action
|
||||
- no user count per tag
|
||||
- no permission preview
|
||||
- no conflict detection
|
||||
- no clear distinction between "role grants access" and "plan defines quotas"
|
||||
- permission logic is powerful but hard to explain to administrators
|
||||
|
||||
Good future role:
|
||||
|
||||
- replace tags with explicit roles/groups/plans. Keep old tags only as migration input.
|
||||
|
||||
## Current Settings Page
|
||||
|
||||
Routes:
|
||||
|
||||
- `GET /admin/settings`
|
||||
- `POST /admin/settings`
|
||||
|
||||
Required permission:
|
||||
|
||||
- `AdminSettingsManage`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- shows configured settings table
|
||||
- columns:
|
||||
- setting
|
||||
- value
|
||||
- source
|
||||
- environment variable name
|
||||
- editable values can be overridden from admin UI when `WARPBOX_ALLOW_ADMIN_SETTINGS_OVERRIDE=true`
|
||||
- overrides are stored in BadgerDB
|
||||
- runtime config is updated after save
|
||||
|
||||
Editable settings currently include:
|
||||
|
||||
- guest uploads enabled
|
||||
- API enabled
|
||||
- ZIP downloads enabled
|
||||
- one-time downloads enabled
|
||||
- one-time download expiry seconds
|
||||
- renew on access enabled
|
||||
- renew on download enabled
|
||||
- default guest expiry seconds
|
||||
- max guest expiry seconds
|
||||
- default user max file size bytes
|
||||
- default user max box size bytes
|
||||
- session TTL seconds
|
||||
- box poll interval milliseconds
|
||||
- thumbnail batch size
|
||||
- thumbnail interval seconds
|
||||
|
||||
Non-editable/hard settings include:
|
||||
|
||||
- data directory
|
||||
- global max file size bytes
|
||||
- global max box size bytes
|
||||
- one-time download retry on failure
|
||||
|
||||
Current limitations:
|
||||
|
||||
- settings are presented as raw technical rows
|
||||
- no grouping
|
||||
- no descriptions
|
||||
- no validation hints beyond backend errors
|
||||
- byte fields require raw bytes
|
||||
- duration fields require raw seconds/milliseconds
|
||||
- no "restart required" or "runtime applied" distinction beyond current editability
|
||||
- no audit trail for setting changes
|
||||
|
||||
Good future role:
|
||||
|
||||
- organized system configuration, with human units, clear safety boundaries, and change history.
|
||||
|
||||
## Current API Key State
|
||||
|
||||
There is visible API key UX in the upload page:
|
||||
|
||||
- "Use API key for larger quota"
|
||||
- API key input
|
||||
- local validation with regex
|
||||
- value saved locally in browser localStorage
|
||||
- cURL command includes `Authorization: Bearer YOUR_API_KEY` when enabled
|
||||
|
||||
Important current reality:
|
||||
|
||||
- no backend API key model was found
|
||||
- no API key generation route was found
|
||||
- no server-side Authorization bearer validation was found
|
||||
- no per-user API key ownership or revocation exists yet
|
||||
- no current upload flow applies user permissions from an API key
|
||||
|
||||
So API keys are a product placeholder, not a functional feature yet.
|
||||
|
||||
## Main Current Gaps
|
||||
|
||||
- Dashboard is only navigation.
|
||||
- User management only creates and disables accounts.
|
||||
- Tags are doing too many jobs.
|
||||
- API keys are UI-only.
|
||||
- Admin pages lack search, filters, pagination, and detail views.
|
||||
- No audit log.
|
||||
- No admin-visible system health.
|
||||
- No storage cleanup controls.
|
||||
- No account self-service area for non-admin users.
|
||||
- Existing permission model is additive and permissive, which can surprise admins.
|
||||
|
||||
## Recommended Overhaul Direction
|
||||
|
||||
Build a full admin solution around four clear concepts:
|
||||
|
||||
- Dashboard: current health and useful actions.
|
||||
- Accounts: people who can sign in or use API keys.
|
||||
- Roles/Groups: permission bundles and admin capabilities.
|
||||
- Plans/Limits: quotas and upload policy.
|
||||
|
||||
This separates identity from authorization from quotas. It should make the system easier to explain and safer to operate.
|
||||
|
||||
## Proposed Dashboard
|
||||
|
||||
Recommended dashboard cards:
|
||||
|
||||
- total active boxes
|
||||
- total storage used
|
||||
- expired boxes waiting cleanup
|
||||
- boxes created today / last 24 hours
|
||||
- uploads completed today / last 24 hours
|
||||
- failed or incomplete uploads
|
||||
- active users
|
||||
- disabled users
|
||||
- API keys active
|
||||
- admin sessions active
|
||||
- thumbnail queue / worker state
|
||||
- current global limits
|
||||
- guest uploads status
|
||||
- ZIP downloads status
|
||||
- one-time downloads status
|
||||
|
||||
Recommended dashboard sections:
|
||||
|
||||
- "Needs attention"
|
||||
- expired boxes
|
||||
- failed uploads
|
||||
- one-time boxes stuck incomplete
|
||||
- high storage usage
|
||||
- disabled API setting while API key UI is visible
|
||||
- "Recent boxes"
|
||||
- latest boxes with flags and size
|
||||
- "Recent admin activity"
|
||||
- user created, role changed, setting changed, API key revoked
|
||||
- "System"
|
||||
- data directory
|
||||
- BadgerDB status
|
||||
- uploads directory size
|
||||
- thumbnail worker timing
|
||||
- config source summary
|
||||
|
||||
UX idea:
|
||||
|
||||
- dashboard should answer "is WarpBox healthy?", "what changed recently?", and "what should I do next?" in one glance.
|
||||
|
||||
## Proposed Account Management
|
||||
|
||||
Recommended account list:
|
||||
|
||||
- search by username/email
|
||||
- filter by status, role/group, plan, API key presence
|
||||
- columns:
|
||||
- user
|
||||
- email
|
||||
- status
|
||||
- roles/groups
|
||||
- plan/limits
|
||||
- API keys
|
||||
- created
|
||||
- last login / last API use
|
||||
- storage used
|
||||
- boxes created
|
||||
|
||||
Recommended account detail page:
|
||||
|
||||
- profile
|
||||
- status controls
|
||||
- password reset / force password change
|
||||
- roles/groups assignment
|
||||
- plan/limits assignment
|
||||
- effective permissions preview
|
||||
- API keys tab
|
||||
- recent activity tab
|
||||
- boxes owned by user
|
||||
|
||||
Recommended safe actions:
|
||||
|
||||
- disable user
|
||||
- revoke all sessions
|
||||
- revoke all API keys
|
||||
- reset password
|
||||
- assign role/group
|
||||
- assign plan
|
||||
- archive user
|
||||
|
||||
Recommended UX details:
|
||||
|
||||
- show effective permission summary before save
|
||||
- warn when removing own admin access
|
||||
- require confirmation for disabling final admin
|
||||
- prevent accidental lockout at backend level
|
||||
- show inherited vs direct settings clearly
|
||||
|
||||
## Proposed API Key System
|
||||
|
||||
Data model idea:
|
||||
|
||||
- API key id
|
||||
- user id
|
||||
- name/label
|
||||
- hashed secret
|
||||
- secret prefix for display
|
||||
- scopes
|
||||
- created at
|
||||
- expires at
|
||||
- last used at
|
||||
- revoked at
|
||||
- created by
|
||||
- optional allowed IP/CIDR list
|
||||
|
||||
Security rules:
|
||||
|
||||
- show raw key only once on creation
|
||||
- store only hash server-side
|
||||
- allow revoke, rotate, rename
|
||||
- support expiry dates
|
||||
- log last-used timestamp
|
||||
- rate limit failed key attempts
|
||||
- avoid putting API keys in URLs
|
||||
|
||||
User-facing API key page:
|
||||
|
||||
- create key
|
||||
- name key
|
||||
- choose expiry
|
||||
- view active/revoked keys
|
||||
- revoke key
|
||||
- copy cURL example
|
||||
- see last used time
|
||||
|
||||
Admin-facing API key controls:
|
||||
|
||||
- view user key count and last use
|
||||
- revoke a user key
|
||||
- revoke all keys for disabled user
|
||||
- optionally create key on behalf of user
|
||||
- audit key creation/revocation
|
||||
|
||||
Permission behavior:
|
||||
|
||||
- bearer key resolves to user
|
||||
- user roles/groups/plans determine upload policy
|
||||
- key scopes can further restrict user permission but not exceed it
|
||||
- API key can enable higher quota only if assigned user's plan allows it
|
||||
|
||||
Initial scopes:
|
||||
|
||||
- `box:create`
|
||||
- `box:upload`
|
||||
- `box:read`
|
||||
- `box:download`
|
||||
- `box:delete-own`
|
||||
|
||||
## Proposed Role/Group System
|
||||
|
||||
Replace tags with explicit authorization objects.
|
||||
|
||||
Recommended models:
|
||||
|
||||
- Role: permission bundle, e.g. `admin`, `operator`, `uploader`, `viewer`
|
||||
- Group: collection of users with assigned roles and optional plan
|
||||
- Plan: quota/limit policy, e.g. `guest`, `standard`, `trusted`, `unlimited`
|
||||
|
||||
Roles should answer:
|
||||
|
||||
- what can this user do?
|
||||
|
||||
Plans should answer:
|
||||
|
||||
- how much can this user use?
|
||||
|
||||
Groups should answer:
|
||||
|
||||
- who receives these defaults together?
|
||||
|
||||
Recommended permissions:
|
||||
|
||||
- admin.access
|
||||
- admin.dashboard.view
|
||||
- admin.users.view
|
||||
- admin.users.manage
|
||||
- admin.roles.manage
|
||||
- admin.settings.view
|
||||
- admin.settings.manage
|
||||
- admin.boxes.view
|
||||
- admin.boxes.manage
|
||||
- boxes.create
|
||||
- boxes.download.zip
|
||||
- boxes.download.one_time
|
||||
- boxes.password.set
|
||||
- boxes.renew
|
||||
- api_keys.manage_own
|
||||
- api_keys.manage_any
|
||||
|
||||
Recommended limit fields:
|
||||
|
||||
- max file size
|
||||
- max box size
|
||||
- max boxes per day
|
||||
- max storage active at once
|
||||
- max expiry
|
||||
- allowed expiry choices
|
||||
- max API keys
|
||||
- API key max TTL
|
||||
- guest upload allowed
|
||||
- ZIP allowed
|
||||
- one-time allowed
|
||||
- renew allowed
|
||||
|
||||
Recommended resolver:
|
||||
|
||||
- start with system defaults
|
||||
- apply assigned plan quotas
|
||||
- apply group plan when user has no direct plan
|
||||
- apply direct user overrides last
|
||||
- roles grant permissions
|
||||
- scopes restrict API key actions
|
||||
- hard global limits cap everything
|
||||
|
||||
Migration strategy:
|
||||
|
||||
- create role equivalents from current tag admin booleans
|
||||
- create plan equivalents from current tag upload limits
|
||||
- assign users based on existing `TagIDs`
|
||||
- keep read-only legacy tag view during migration
|
||||
- remove tag creation from final UI
|
||||
|
||||
## Extra Feature Ideas
|
||||
|
||||
Storage and cleanup:
|
||||
|
||||
- expired box cleanup page
|
||||
- bulk delete expired boxes
|
||||
- storage by age chart
|
||||
- largest boxes list
|
||||
- orphaned manifest/file scanner
|
||||
- thumbnail cleanup/rebuild tools
|
||||
|
||||
Security:
|
||||
|
||||
- audit log
|
||||
- active admin sessions page
|
||||
- revoke sessions
|
||||
- failed login tracking
|
||||
- optional two-factor auth for admins
|
||||
- final-admin protection
|
||||
- configurable password policy
|
||||
|
||||
Operations:
|
||||
|
||||
- system health page
|
||||
- config export
|
||||
- backup/restore notes for data directory and BadgerDB
|
||||
- maintenance mode
|
||||
- manual thumbnail worker run
|
||||
- background job status
|
||||
|
||||
User experience:
|
||||
|
||||
- account self-service page
|
||||
- personal upload history
|
||||
- personal quota meter
|
||||
- personal API keys
|
||||
- upload presets
|
||||
- saved retention preferences
|
||||
|
||||
Admin UX:
|
||||
|
||||
- global search
|
||||
- command palette
|
||||
- filters saved per admin
|
||||
- CSV export for users/boxes
|
||||
- inline detail drawer for boxes/users
|
||||
- change preview before saving roles/plans
|
||||
|
||||
Product:
|
||||
|
||||
- named boxes supported server-side
|
||||
- custom slug support server-side
|
||||
- private/listed boxes if public listing is added
|
||||
- max view count server-side
|
||||
- ownership model: boxes created by user/API key belong to that user
|
||||
- public share page controls based on owner plan
|
||||
|
||||
## Suggested Implementation Phases
|
||||
|
||||
Phase 1: make current admin useful
|
||||
|
||||
- add real dashboard statistics
|
||||
- add search/filter/pagination to boxes and users
|
||||
- expose effective permissions on user rows/details
|
||||
- add user edit form
|
||||
- add storage cleanup actions
|
||||
|
||||
Phase 2: implement API keys
|
||||
|
||||
- add API key model in BadgerDB
|
||||
- add create/revoke/list routes
|
||||
- hash keys server-side
|
||||
- validate bearer keys on API endpoints
|
||||
- connect key to user permissions
|
||||
- add self-service API key UI
|
||||
|
||||
Phase 3: replace tags
|
||||
|
||||
- add roles/plans/groups models
|
||||
- add resolver
|
||||
- add migration from tags
|
||||
- update user management UI
|
||||
- deprecate tag creation
|
||||
|
||||
Phase 4: polish into full admin solution
|
||||
|
||||
- audit log
|
||||
- account detail pages
|
||||
- system health
|
||||
- advanced cleanup
|
||||
- activity timeline
|
||||
- safer setting editor
|
||||
|
||||
## Product Principle For The Overhaul
|
||||
|
||||
Keep WarpBox small, local, and understandable. The admin area should not become enterprise software cosplay. It should give the operator sharp tools:
|
||||
|
||||
- see what is happening
|
||||
- fix common problems
|
||||
- manage people safely
|
||||
- give trusted users more power
|
||||
- keep storage under control
|
||||
- make permission decisions obvious
|
||||
|
||||
Best version: a retro control panel that behaves like a modern, careful admin console.
|
||||
Reference in New Issue
Block a user