Files
adopt-a-street/frontend/src/components/Navbar.js
T
William Valentin fc23f4d098 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>
2025-12-06 13:36:15 -08:00

74 lines
2.5 KiB
JavaScript

import React, { useContext } from 'react';
import { Link } from 'react-router-dom';
import { AuthContext } from '../context/AuthContext';
const Navbar = () => {
const { auth, logout } = useContext(AuthContext);
const authLinks = (
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link className="nav-link" to="/map" data-testid="nav-map">Map</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/tasks" data-testid="nav-tasks">Tasks</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/feed" data-testid="nav-feed">Feed</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/events" data-testid="nav-events">Events</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/rewards" data-testid="nav-rewards">Rewards</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/leaderboard" data-testid="nav-leaderboard">Leaderboard</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/analytics" data-testid="nav-analytics">Analytics</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/profile" data-testid="nav-profile">Profile</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/premium" data-testid="nav-premium">Premium</Link>
</li>
{auth.user?.isAdmin && (
<li className="nav-item">
<Link className="nav-link text-danger" to="/admin" data-testid="nav-admin">
Admin
</Link>
</li>
)}
<li className="nav-item">
<a onClick={logout} href="#!" className="nav-link" data-testid="logout-button">Logout</a>
</li>
</ul>
);
const guestLinks = (
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link className="nav-link" to="/register" data-testid="nav-register">Register</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/login" data-testid="nav-login">Login</Link>
</li>
</ul>
);
return (
<nav className="navbar navbar-expand-sm navbar-dark bg-dark mb-4" data-testid="navbar">
<div className="container">
<Link className="navbar-brand" to="/" data-testid="navbar-brand">Adopt-a-Street</Link>
<div className="collapse navbar-collapse">
{auth.isAuthenticated ? authLinks : guestLinks}
</div>
</div>
</nav>
);
};
export default Navbar;