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:
parent
4443773040
commit
0332eb5481
4
.replit
4
.replit
@ -18,10 +18,6 @@ externalPort = 80
|
|||||||
localPort = 33035
|
localPort = 33035
|
||||||
externalPort = 3001
|
externalPort = 3001
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 38973
|
|
||||||
externalPort = 3002
|
|
||||||
|
|
||||||
[[ports]]
|
[[ports]]
|
||||||
localPort = 41343
|
localPort = 41343
|
||||||
externalPort = 3000
|
externalPort = 3000
|
||||||
|
|||||||
@ -24,8 +24,16 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ============= USER MANAGEMENT ROUTES =============
|
// ============= USER MANAGEMENT ROUTES =============
|
||||||
app.get("/api/users", isAuthenticated, async (req, res) => {
|
app.get("/api/users", isAuthenticated, async (req: any, res) => {
|
||||||
try {
|
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();
|
const allUsers = await storage.getAllUsers();
|
||||||
res.json(allUsers);
|
res.json(allUsers);
|
||||||
} catch (error) {
|
} 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 {
|
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;
|
const { role } = req.body;
|
||||||
if (!role || !["admin", "coordinator", "guard", "client"].includes(role)) {
|
if (!role || !["admin", "coordinator", "guard", "client"].includes(role)) {
|
||||||
return res.status(400).json({ message: "Invalid role" });
|
return res.status(400).json({ message: "Invalid role" });
|
||||||
|
|||||||
@ -74,18 +74,32 @@ export class DatabaseStorage implements IStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async upsertUser(userData: UpsertUser): Promise<User> {
|
async upsertUser(userData: UpsertUser): Promise<User> {
|
||||||
const [user] = await db
|
// Check if user already exists by email (unique constraint)
|
||||||
.insert(users)
|
const existingUser = await db
|
||||||
.values(userData)
|
.select()
|
||||||
.onConflictDoUpdate({
|
.from(users)
|
||||||
target: users.id,
|
.where(eq(users.email, userData.email || ''))
|
||||||
set: {
|
.limit(1);
|
||||||
|
|
||||||
|
if (existingUser.length > 0) {
|
||||||
|
// Update existing user
|
||||||
|
const [updated] = await db
|
||||||
|
.update(users)
|
||||||
|
.set({
|
||||||
...userData,
|
...userData,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
},
|
})
|
||||||
})
|
.where(eq(users.email, userData.email || ''))
|
||||||
.returning();
|
.returning();
|
||||||
return user;
|
return updated;
|
||||||
|
} else {
|
||||||
|
// Insert new user
|
||||||
|
const [user] = await db
|
||||||
|
.insert(users)
|
||||||
|
.values(userData)
|
||||||
|
.returning();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllUsers(): Promise<User[]> {
|
async getAllUsers(): Promise<User[]> {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user