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:
@@ -367,14 +367,87 @@ class CouchDBSetup {
|
||||
}
|
||||
}
|
||||
|
||||
async run() {
|
||||
try {
|
||||
await this.initialize();
|
||||
await this.createDatabase();
|
||||
await this.createIndexes();
|
||||
await this.createSecurityDocument();
|
||||
await this.seedBadges();
|
||||
await this.verifySetup();
|
||||
async seedAdminUser() {
|
||||
console.log('👤 Seeding admin user...');
|
||||
|
||||
const ADMIN_EMAIL = process.env.ADMIN_EMAIL;
|
||||
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD;
|
||||
|
||||
if (!ADMIN_EMAIL || !ADMIN_PASSWORD) {
|
||||
console.log('⚠️ ADMIN_EMAIL or ADMIN_PASSWORD not set, skipping admin user creation');
|
||||
return;
|
||||
}
|
||||
|
||||
const db = this.nano.use(COUCHDB_DB_NAME);
|
||||
|
||||
// Check if admin user already exists
|
||||
try {
|
||||
const existing = await db.find({
|
||||
selector: { type: 'user', email: ADMIN_EMAIL },
|
||||
limit: 1
|
||||
});
|
||||
|
||||
if (existing.docs.length > 0) {
|
||||
const user = existing.docs[0];
|
||||
if (!user.isAdmin) {
|
||||
user.isAdmin = true;
|
||||
user.updatedAt = new Date().toISOString();
|
||||
await db.insert(user);
|
||||
console.log('✅ Existing user promoted to admin');
|
||||
} else {
|
||||
console.log('ℹ️ Admin user already exists');
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
// Continue with creation
|
||||
}
|
||||
|
||||
// Create new admin user with hashed password
|
||||
const bcrypt = require('bcryptjs');
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
const hashedPassword = await bcrypt.hash(ADMIN_PASSWORD, salt);
|
||||
|
||||
const adminUser = {
|
||||
_id: `user_admin_${Date.now()}`,
|
||||
type: 'user',
|
||||
name: 'Administrator',
|
||||
email: ADMIN_EMAIL,
|
||||
password: hashedPassword,
|
||||
isAdmin: true,
|
||||
isPremium: true,
|
||||
points: 0,
|
||||
avatar: null,
|
||||
profilePicture: null,
|
||||
bio: 'System Administrator',
|
||||
location: '',
|
||||
website: '',
|
||||
social: { twitter: '', github: '', linkedin: '' },
|
||||
privacySettings: { profileVisibility: 'private' },
|
||||
preferences: { emailNotifications: true, pushNotifications: true, theme: 'light' },
|
||||
adoptedStreets: [],
|
||||
completedTasks: [],
|
||||
posts: [],
|
||||
events: [],
|
||||
earnedBadges: [],
|
||||
stats: { streetsAdopted: 0, tasksCompleted: 0, postsCreated: 0, eventsParticipated: 0, badgesEarned: 0 },
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString()
|
||||
};
|
||||
|
||||
await db.insert(adminUser);
|
||||
console.log(`✅ Admin user created: ${ADMIN_EMAIL}`);
|
||||
}
|
||||
|
||||
async run() {
|
||||
try {
|
||||
await this.initialize();
|
||||
await this.createDatabase();
|
||||
await this.createIndexes();
|
||||
await this.createSecurityDocument();
|
||||
await this.seedBadges();
|
||||
await this.seedAdminUser();
|
||||
await this.verifySetup();
|
||||
|
||||
console.log('\n🎉 CouchDB setup completed successfully!');
|
||||
console.log(`\n📋 Connection Details:`);
|
||||
|
||||
Reference in New Issue
Block a user