Restrict user management operations to administrators

Enhance user management routes (`/api/users`) to enforce admin-only access for viewing and patching user data, and modify `upsertUser` in `DatabaseStorage` to handle existing users by email.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 99f0fce6-9386-489a-9632-1d81223cab44
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/99f0fce6-9386-489a-9632-1d81223cab44/TRdpk3a
This commit is contained in:
marco370 2025-10-11 15:26:17 +00:00
parent 4443773040
commit 0332eb5481
3 changed files with 47 additions and 16 deletions

View File

@ -18,10 +18,6 @@ externalPort = 80
localPort = 33035
externalPort = 3001
[[ports]]
localPort = 38973
externalPort = 3002
[[ports]]
localPort = 41343
externalPort = 3000

View File

@ -24,8 +24,16 @@ export async function registerRoutes(app: Express): Promise<Server> {
});
// ============= USER MANAGEMENT ROUTES =============
app.get("/api/users", isAuthenticated, async (req, res) => {
app.get("/api/users", isAuthenticated, async (req: any, res) => {
try {
const currentUserId = req.user.claims.sub;
const currentUser = await storage.getUser(currentUserId);
// Only admins can view all users
if (currentUser?.role !== "admin") {
return res.status(403).json({ message: "Forbidden: Admin access required" });
}
const allUsers = await storage.getAllUsers();
res.json(allUsers);
} catch (error) {
@ -34,8 +42,21 @@ export async function registerRoutes(app: Express): Promise<Server> {
}
});
app.patch("/api/users/:id", isAuthenticated, async (req, res) => {
app.patch("/api/users/:id", isAuthenticated, async (req: any, res) => {
try {
const currentUserId = req.user.claims.sub;
const currentUser = await storage.getUser(currentUserId);
// Only admins can update user roles
if (currentUser?.role !== "admin") {
return res.status(403).json({ message: "Forbidden: Admin access required" });
}
// Prevent admins from changing their own role
if (req.params.id === currentUserId) {
return res.status(403).json({ message: "Cannot change your own role" });
}
const { role } = req.body;
if (!role || !["admin", "coordinator", "guard", "client"].includes(role)) {
return res.status(400).json({ message: "Invalid role" });

View File

@ -74,19 +74,33 @@ export class DatabaseStorage implements IStorage {
}
async upsertUser(userData: UpsertUser): Promise<User> {
// Check if user already exists by email (unique constraint)
const existingUser = await db
.select()
.from(users)
.where(eq(users.email, userData.email || ''))
.limit(1);
if (existingUser.length > 0) {
// Update existing user
const [updated] = await db
.update(users)
.set({
...userData,
updatedAt: new Date(),
})
.where(eq(users.email, userData.email || ''))
.returning();
return updated;
} else {
// Insert new user
const [user] = await db
.insert(users)
.values(userData)
.onConflictDoUpdate({
target: users.id,
set: {
...userData,
updatedAt: new Date(),
},
})
.returning();
return user;
}
}
async getAllUsers(): Promise<User[]> {
return await db.select().from(users).orderBy(desc(users.createdAt));