diff --git a/client/src/pages/settings.tsx b/client/src/pages/settings.tsx index 0a13a7e..b9aa3c4 100644 --- a/client/src/pages/settings.tsx +++ b/client/src/pages/settings.tsx @@ -55,18 +55,28 @@ export default function Settings() { const hasExistingConfig = !!openrouterConfig; const saveCloudinaryMutation = useMutation({ - mutationFn: () => - apiRequest('POST', '/api/cloudinary/config', { + mutationFn: () => { + const payload: any = { cloudName, - apiKey, - apiSecret, - }), + }; + + // N'inclure apiKey et apiSecret que s'ils ne sont pas vides + if (apiKey && apiKey.trim() !== "") { + payload.apiKey = apiKey; + } + if (apiSecret && apiSecret.trim() !== "") { + payload.apiSecret = apiSecret; + } + + return apiRequest('POST', '/api/cloudinary/config', payload); + }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/cloudinary/config'] }); toast({ title: "Configuration sauvegardée", description: "Vos paramètres Cloudinary ont été enregistrés", }); + setApiKey(""); // Clear the API key after saving setApiSecret(""); // Clear the secret after saving }, onError: () => { diff --git a/server/routes.ts b/server/routes.ts index 22afc99..4075ff7 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -8,7 +8,7 @@ import passport from "./auth"; import { z } from "zod"; import { openRouterService } from "./services/openrouter"; import { cloudinaryService } from "./services/cloudinary"; -import { insertPostSchema, insertScheduledPostSchema, insertSocialPageSchema, insertAiGenerationSchema, insertCloudinaryConfigSchema, insertOpenrouterConfigSchema, updateOpenrouterConfigSchema, insertUserSchema, postMedia } from "@shared/schema"; +import { insertPostSchema, insertScheduledPostSchema, insertSocialPageSchema, insertAiGenerationSchema, insertCloudinaryConfigSchema, updateCloudinaryConfigSchema, insertOpenrouterConfigSchema, updateOpenrouterConfigSchema, insertUserSchema, postMedia } from "@shared/schema"; import type { User, InsertUser } from "@shared/schema"; const upload = multer({ storage: multer.memoryStorage() }); @@ -618,18 +618,31 @@ export async function registerRoutes(app: Express): Promise { const user = req.user as User; const userId = user.id; - const configData = insertCloudinaryConfigSchema.parse({ - ...req.body, - userId, - }); - // Check if config already exists const existingConfig = await storage.getCloudinaryConfig(userId); let config; if (existingConfig) { - config = await storage.updateCloudinaryConfig(userId, configData); + // Pour les mises à jour, utiliser le schéma qui rend les secrets optionnels + const updateData = updateCloudinaryConfigSchema.parse({ + ...req.body, + userId, + }); + + // Si apiKey/apiSecret ne sont pas fournis, garder les anciens + const finalData = { + ...updateData, + apiKey: updateData.apiKey || existingConfig.apiKey, + apiSecret: updateData.apiSecret || existingConfig.apiSecret, + }; + + config = await storage.updateCloudinaryConfig(userId, finalData); } else { + // Pour les créations, exiger tous les champs + const configData = insertCloudinaryConfigSchema.parse({ + ...req.body, + userId, + }); config = await storage.createCloudinaryConfig(configData); } diff --git a/shared/schema.ts b/shared/schema.ts index c50590b..c2ea279 100644 --- a/shared/schema.ts +++ b/shared/schema.ts @@ -230,6 +230,11 @@ export const updateOpenrouterConfigSchema = insertOpenrouterConfigSchema.partial apiKey: true, }); +export const updateCloudinaryConfigSchema = insertCloudinaryConfigSchema.partial({ + apiKey: true, + apiSecret: true, +}); + // Types export type User = typeof users.$inferSelect; export type InsertUser = z.infer; @@ -251,8 +256,10 @@ export type InsertAiGeneration = z.infer; export type CloudinaryConfig = typeof cloudinaryConfig.$inferSelect; export type InsertCloudinaryConfig = z.infer; +export type UpdateCloudinaryConfig = z.infer; export type OpenrouterConfig = typeof openrouterConfig.$inferSelect; export type InsertOpenrouterConfig = z.infer; +export type UpdateOpenrouterConfig = z.infer; export type PostMedia = typeof postMedia.$inferSelect;