feat: add admin user system with role-based access control

Implement comprehensive admin user system for Kubernetes deployment:

Backend:
- Add isAdmin field to User model for role-based permissions
- Create adminAuth middleware to protect admin-only routes
- Protect 11 routes across rewards, cache, streets, and analytics endpoints
- Update setup-couchdb.js to seed default admin user at deployment

Kubernetes:
- Add ADMIN_EMAIL and ADMIN_PASSWORD to secrets.yaml
- Add ADMIN_EMAIL to configmap.yaml for non-sensitive config
- Create couchdb-init-job.yaml for automated database initialization
- Update secrets.yaml.example with admin user documentation

Frontend:
- Create AdminRoute component for admin-only page protection
- Create comprehensive AdminDashboard with 5 tabs:
  * Overview: Platform statistics and quick actions
  * Users: List, search, manage admin status, delete users
  * Streets: Create, edit, delete streets
  * Rewards: Create, edit, toggle, delete rewards
  * Content: Moderate posts and events
- Add Admin navigation link in Navbar (visible only to admins)
- Integrate admin routes in App.js

Default admin user:
- Email: will@wills-portal.com
- Created automatically by K8s init job at deployment

Routes protected:
- POST/PUT/DELETE /api/rewards (catalog management)
- POST /api/streets (street creation)
- DELETE /api/cache (cache operations)
- GET /api/analytics/* (platform statistics)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
William Valentin
2025-12-06 13:36:15 -08:00
parent 71c1d82e0e
commit fc23f4d098
15 changed files with 1159 additions and 22 deletions

View File

@@ -29,3 +29,6 @@ data:
# OpenAI Configuration (optional - for AI features)
# Note: OPENAI_API_KEY should be in secrets.yaml
OPENAI_MODEL: "gpt-3.5-turbo"
# Admin Configuration
ADMIN_EMAIL: "will@wills-portal.com"

View File

@@ -0,0 +1,66 @@
apiVersion: batch/v1
kind: Job
metadata:
name: couchdb-init
labels:
app: couchdb-init
spec:
backoffLimit: 3
template:
metadata:
labels:
app: couchdb-init
spec:
imagePullSecrets:
- name: regcred
initContainers:
- name: wait-for-couchdb
image: curlimages/curl:8.5.0
command:
- sh
- -c
- |
until curl -f -s http://adopt-a-street-couchdb:5984/_up > /dev/null 2>&1; do
echo "Waiting for CouchDB to be ready..."
sleep 3
done
echo "CouchDB is ready!"
containers:
- name: couchdb-init
image: gitea-http.taildb3494.ts.net/will/adopt-a-street-backend:latest
imagePullPolicy: Always
command: ["node", "scripts/setup-couchdb.js"]
envFrom:
- configMapRef:
name: adopt-a-street-config
- secretRef:
name: adopt-a-street-secrets
env:
- name: COUCHDB_USER
valueFrom:
secretKeyRef:
name: adopt-a-street-secrets
key: COUCHDB_USER
- name: COUCHDB_PASSWORD
valueFrom:
secretKeyRef:
name: adopt-a-street-secrets
key: COUCHDB_PASSWORD
- name: ADMIN_EMAIL
valueFrom:
secretKeyRef:
name: adopt-a-street-secrets
key: ADMIN_EMAIL
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: adopt-a-street-secrets
key: ADMIN_PASSWORD
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
restartPolicy: Never

View File

@@ -1,5 +1,7 @@
apiVersion: v1
data:
ADMIN_EMAIL: d2lsbEB3aWxscy1wb3J0YWwuY29t
ADMIN_PASSWORD: ZnJhY2s2NjY=
CLOUDINARY_API_KEY: ""
CLOUDINARY_API_SECRET: ""
CLOUDINARY_CLOUD_NAME: ""

View File

@@ -22,6 +22,10 @@ stringData:
# OpenAI Configuration (optional - for AI features)
OPENAI_API_KEY: "your-openai-api-key"
# Admin User Configuration - CHANGE THESE IN PRODUCTION!
ADMIN_EMAIL: "admin@example.com" # Default admin user email
ADMIN_PASSWORD: "change-this-password" # Default admin user password
---
# IMPORTANT:
# 1. Copy this file to secrets.yaml
@@ -31,3 +35,4 @@ stringData:
# 5. Generate strong passwords for CouchDB using: openssl rand -base64 32
# 6. Non-sensitive config values (CLOUDINARY_CLOUD_NAME, STRIPE_PUBLISHABLE_KEY, OPENAI_MODEL)
# are in configmap.yaml
# 7. Set ADMIN_EMAIL and ADMIN_PASSWORD to create the default admin user at deployment