From 919639f8a08a760b5dcaee9f73405181a795bad2 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 10 Oct 2025 08:44:06 +0000 Subject: [PATCH 1/6] Transitioned from Plan to Build mode Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/G1P4XGr From 73fe39bfbd27fc4f5d549cd4ce0b4af630e603e9 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 10 Oct 2025 08:47:23 +0000 Subject: [PATCH 2/6] Allow users to select from assigned pages and manage their posts Modify routes to differentiate admin and user permissions for fetching, deleting, and updating scheduled posts. Admins can access all data, while regular users can only manage posts associated with their assigned pages. 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/G1P4XGr --- server/routes.ts | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/server/routes.ts b/server/routes.ts index 4b4dcc7..e50e9a6 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -758,7 +758,23 @@ export async function registerRoutes(app: Express): Promise { const start = startDate ? new Date(startDate as string) : undefined; const end = endDate ? new Date(endDate as string) : undefined; - const scheduledPosts = await storage.getScheduledPosts(userId, start, end); + let scheduledPosts; + + if (user.role === 'admin') { + // Admin voit tous les posts programmés + const allUsers = await storage.getAllUsers(); + const allPostsPromises = allUsers.map(u => storage.getScheduledPosts(u.id, start, end)); + const allPostsArrays = await Promise.all(allPostsPromises); + scheduledPosts = allPostsArrays.flat(); + } else { + // User voit uniquement les posts des pages qui lui sont attribuées + const accessiblePages = await storage.getUserAccessiblePages(userId); + const accessiblePageIds = accessiblePages.map(p => p.id); + + const userScheduledPosts = await storage.getScheduledPosts(userId, start, end); + scheduledPosts = userScheduledPosts.filter(sp => accessiblePageIds.includes(sp.pageId)); + } + res.json(scheduledPosts); } catch (error) { console.error("Error fetching scheduled posts:", error); @@ -772,14 +788,19 @@ export async function registerRoutes(app: Express): Promise { const userId = user.id; const { id } = req.params; - // Verify the scheduled post belongs to the user before deleting + // Verify the scheduled post exists const scheduledPost = await storage.getScheduledPost(id); if (!scheduledPost) { return res.status(404).json({ error: "Scheduled post not found" }); } const post = await storage.getPost(scheduledPost.postId); - if (!post || post.userId !== userId) { + if (!post) { + return res.status(404).json({ error: "Post not found" }); + } + + // Admin peut tout supprimer, user peut supprimer uniquement ses propres posts + if (user.role !== 'admin' && post.userId !== userId) { return res.status(403).json({ error: "Unauthorized" }); } @@ -797,14 +818,19 @@ export async function registerRoutes(app: Express): Promise { const userId = user.id; const { id } = req.params; - // Verify the scheduled post belongs to the user before updating + // Verify the scheduled post exists const scheduledPost = await storage.getScheduledPost(id); if (!scheduledPost) { return res.status(404).json({ error: "Scheduled post not found" }); } const post = await storage.getPost(scheduledPost.postId); - if (!post || post.userId !== userId) { + if (!post) { + return res.status(404).json({ error: "Post not found" }); + } + + // Admin peut tout modifier, user peut modifier uniquement ses propres posts + if (user.role !== 'admin' && post.userId !== userId) { return res.status(403).json({ error: "Unauthorized" }); } From d32b5ca306604bd8be84619bb0482456254083ad Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 10 Oct 2025 09:11:27 +0000 Subject: [PATCH 3/6] Update post scheduling to synchronize with the posts table Synchronize scheduled post's `scheduledFor` field with the database when updating post schedule in server/routes.ts. 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/1VOBLTw --- .replit | 8 ++++++++ server/routes.ts | 2 ++ 2 files changed, 10 insertions(+) diff --git a/.replit b/.replit index f9a4cd6..164cd5a 100644 --- a/.replit +++ b/.replit @@ -14,6 +14,10 @@ run = ["npm", "run", "start"] localPort = 5000 externalPort = 80 +[[ports]] +localPort = 33821 +externalPort = 8099 + [[ports]] localPort = 34045 externalPort = 3003 @@ -46,6 +50,10 @@ externalPort = 8081 localPort = 40537 externalPort = 3000 +[[ports]] +localPort = 41803 +externalPort = 8008 + [[ports]] localPort = 42161 externalPort = 6000 diff --git a/server/routes.ts b/server/routes.ts index e50e9a6..079bfa0 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -840,6 +840,8 @@ export async function registerRoutes(app: Express): Promise { if (scheduledAt) { updateData.scheduledAt = new Date(scheduledAt); + // Synchroniser avec la table posts + await storage.updatePost(scheduledPost.postId, { scheduledFor: new Date(scheduledAt) }); } if (pageId) { From b1a142e45cc98771157631a5ca7e97620a0275d3 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 10 Oct 2025 09:23:00 +0000 Subject: [PATCH 4/6] Enforce page selection for scheduled posts to prevent errors Add validation to ensure scheduled posts are associated with at least one page, returning a 400 error if not. 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/1VOBLTw --- server/routes.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/routes.ts b/server/routes.ts index 079bfa0..da9b905 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -611,6 +611,11 @@ export async function registerRoutes(app: Express): Promise { // Set status to "scheduled" if scheduledFor is provided, otherwise "draft" if (postFields.scheduledFor) { postFields.status = "scheduled"; + + // Validate that scheduled posts require at least one page + if (!pageIds || !Array.isArray(pageIds) || pageIds.length === 0) { + return res.status(400).json({ error: "Les posts programmés nécessitent au moins une page cible" }); + } } // Create the post From 157c9ae7d8cefdae6a7a3d578eb1d71ab1a00edf Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 10 Oct 2025 09:23:55 +0000 Subject: [PATCH 5/6] Improve calendar permissions and fix scheduled post data synchronization Implement page-based permissions for calendar access and fix data synchronization issues for scheduled posts. 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/1VOBLTw --- replit.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/replit.md b/replit.md index 2c7e2e7..94b0244 100644 --- a/replit.md +++ b/replit.md @@ -11,6 +11,9 @@ Preferred communication style: Simple, everyday language. ## Recent Changes ### October 10, 2025 +- **Calendar Permissions System**: Implemented comprehensive page-based permissions for calendar access. Admin users see all scheduled posts with full edit/delete rights. Standard users see only posts from their assigned pages via `user_page_permissions` table, but can only edit/delete their own posts (ownership check via `post.userId`). GET /api/scheduled-posts filters posts by accessible pages (admin bypass). DELETE and PATCH /api/scheduled-posts enforce ownership validation (admin can modify any post, users limited to own posts). +- **Scheduled Posts Data Sync Fix**: Fixed critical bug where editing scheduled post time via PATCH /api/scheduled-posts/:id updated `scheduled_posts.scheduledAt` but not `posts.scheduledFor`, causing calendar/database inconsistency. Now both tables are synchronized: updating scheduledAt automatically updates scheduledFor via `storage.updatePost()`. +- **Scheduled Posts Validation**: Added validation to POST /api/posts requiring `pageIds` when `scheduledFor` is provided. Prevents orphaned scheduled posts that would be invisible in calendar. Returns 400 error: "Les posts programmés nécessitent au moins une page cible". - **AI Assistant Admin-Only Access**: Restricted access to AI Assistant to administrators only. Route `/ai` now requires admin role with `adminOnly` prop. Sidebar moved "Assistant IA" link to Administration section (visible only to admins). Backend endpoints (`/api/ai/models`, `/api/ai/generate`, `/api/ai/generations`) protected with `requireAdmin` middleware. Standard users attempting to access AI features see "Accès refusé" message and receive 403 responses. ### October 9, 2025 From 344d79f5d9cbf6676838b89544b8fef85520dad9 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 10 Oct 2025 09:24:19 +0000 Subject: [PATCH 6/6] Improve the way product information is processed for content generation Update product data processing logic to enhance AI-driven text generation for social media posts. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/1VOBLTw