mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-15 11:18:54 +02:00
Add user management features for administrators to control accounts
Implement CRUD operations for users, including listing, creating, editing, and deleting users, along with updates to authentication and UI components. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/HPCBgsr
This commit is contained in:
1 parent
ebc581e015
commit
f6d82f67ba
6 files changed
+507
-102
No files matched your search
+114
-1
@@ -8,7 +8,7 @@ import { z } from "zod";
|
||||
import { openRouterService } from "./services/openrouter";
|
||||
import { cloudinaryService } from "./services/cloudinary";
|
||||
import { insertPostSchema, insertScheduledPostSchema, insertSocialPageSchema, insertAiGenerationSchema, insertCloudinaryConfigSchema, insertOpenrouterConfigSchema, insertUserSchema } from "@shared/schema";
|
||||
import type { User } from "@shared/schema";
|
||||
import type { User, InsertUser } from "@shared/schema";
|
||||
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
||||
@@ -78,6 +78,25 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour obtenir la liste de tous les utilisateurs (réservée aux admins)
|
||||
app.get("/api/users", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const allUsers = await storage.getAllUsers();
|
||||
|
||||
// Ne pas envoyer les mots de passe
|
||||
const safeUsers = allUsers.map(user => ({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
role: user.role,
|
||||
}));
|
||||
|
||||
res.json(safeUsers);
|
||||
} catch (error) {
|
||||
console.error("Error fetching users:", error);
|
||||
res.status(500).json({ error: "Erreur lors de la récupération des utilisateurs" });
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour créer un nouvel utilisateur (réservée aux admins)
|
||||
app.post("/api/users", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
@@ -118,6 +137,100 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour modifier un utilisateur (réservée aux admins)
|
||||
app.patch("/api/users/:id", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const userId = req.params.id;
|
||||
const { username, password, role } = req.body;
|
||||
|
||||
// Vérifier si l'utilisateur existe
|
||||
const existingUser = await storage.getUser(userId);
|
||||
if (!existingUser) {
|
||||
return res.status(404).json({ error: "Utilisateur non trouvé" });
|
||||
}
|
||||
|
||||
const updateData: Partial<InsertUser> = {};
|
||||
|
||||
if (username && username !== existingUser.username) {
|
||||
// Vérifier si le nouveau username est déjà pris
|
||||
const userWithSameUsername = await storage.getUserByUsername(username);
|
||||
if (userWithSameUsername && userWithSameUsername.id !== userId) {
|
||||
return res.status(409).json({ error: "Ce nom d'utilisateur est déjà utilisé" });
|
||||
}
|
||||
updateData.username = username;
|
||||
}
|
||||
|
||||
if (password) {
|
||||
// Hasher le nouveau mot de passe
|
||||
updateData.password = await bcrypt.hash(password, 10);
|
||||
}
|
||||
|
||||
if (role && (role === "admin" || role === "user")) {
|
||||
updateData.role = role;
|
||||
}
|
||||
|
||||
if (Object.keys(updateData).length === 0) {
|
||||
return res.status(400).json({ error: "Aucune modification fournie" });
|
||||
}
|
||||
|
||||
const updatedUser = await storage.updateUser(userId, updateData);
|
||||
|
||||
res.json({
|
||||
id: updatedUser.id,
|
||||
username: updatedUser.username,
|
||||
role: updatedUser.role,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error("Error updating user:", error);
|
||||
res.status(500).json({ error: "Erreur lors de la modification de l'utilisateur" });
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour supprimer un utilisateur (réservée aux admins)
|
||||
app.delete("/api/users/:id", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const userId = req.params.id;
|
||||
const currentUser = req.user as User;
|
||||
|
||||
// Empêcher l'admin de se supprimer lui-même
|
||||
if (userId === currentUser.id) {
|
||||
return res.status(400).json({ error: "Vous ne pouvez pas supprimer votre propre compte" });
|
||||
}
|
||||
|
||||
// Vérifier si l'utilisateur existe
|
||||
const existingUser = await storage.getUser(userId);
|
||||
if (!existingUser) {
|
||||
return res.status(404).json({ error: "Utilisateur non trouvé" });
|
||||
}
|
||||
|
||||
await storage.deleteUser(userId);
|
||||
|
||||
res.json({ success: true, message: "Utilisateur supprimé avec succès" });
|
||||
} catch (error: any) {
|
||||
console.error("Error deleting user:", error);
|
||||
res.status(500).json({ error: "Erreur lors de la suppression de l'utilisateur" });
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour vérifier si le mot de passe admin par défaut a été changé
|
||||
app.get("/api/auth/default-password-status", async (req, res) => {
|
||||
try {
|
||||
const adminUser = await storage.getUserByUsername("admin");
|
||||
|
||||
if (!adminUser) {
|
||||
return res.json({ isDefault: false });
|
||||
}
|
||||
|
||||
// Vérifier si le mot de passe correspond à "admin"
|
||||
const isDefaultPassword = await bcrypt.compare("admin", adminUser.password);
|
||||
|
||||
res.json({ isDefault: isDefaultPassword });
|
||||
} catch (error) {
|
||||
console.error("Error checking default password:", error);
|
||||
res.status(500).json({ error: "Erreur lors de la vérification" });
|
||||
}
|
||||
});
|
||||
|
||||
// Route SQL (réservée aux admins)
|
||||
app.post("/api/sql/execute", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
|
||||
@@ -31,7 +31,10 @@ export interface IStorage {
|
||||
// Users
|
||||
getUser(id: string): Promise<User | undefined>;
|
||||
getUserByUsername(username: string): Promise<User | undefined>;
|
||||
getAllUsers(): Promise<User[]>;
|
||||
createUser(user: InsertUser): Promise<User>;
|
||||
updateUser(id: string, user: Partial<InsertUser>): Promise<User>;
|
||||
deleteUser(id: string): Promise<void>;
|
||||
|
||||
// Social Pages
|
||||
getSocialPages(userId: string): Promise<SocialPage[]>;
|
||||
@@ -88,11 +91,24 @@ export class DatabaseStorage implements IStorage {
|
||||
return user || undefined;
|
||||
}
|
||||
|
||||
async getAllUsers(): Promise<User[]> {
|
||||
return await db.select().from(users);
|
||||
}
|
||||
|
||||
async createUser(insertUser: InsertUser): Promise<User> {
|
||||
const [user] = await db.insert(users).values(insertUser).returning();
|
||||
return user;
|
||||
}
|
||||
|
||||
async updateUser(id: string, updateData: Partial<InsertUser>): Promise<User> {
|
||||
const [updated] = await db.update(users).set(updateData).where(eq(users.id, id)).returning();
|
||||
return updated;
|
||||
}
|
||||
|
||||
async deleteUser(id: string): Promise<void> {
|
||||
await db.delete(users).where(eq(users.id, id));
|
||||
}
|
||||
|
||||
// Social Pages
|
||||
async getSocialPages(userId: string): Promise<SocialPage[]> {
|
||||
return await db.select().from(socialPages).where(eq(socialPages.userId, userId));
|
||||
|
||||
Reference in new issue
Block a user