@lastbrain/app 0.1.39 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -903,7 +903,7 @@ async function createConfigFiles(
903
903
  ) {
904
904
  console.log(chalk.yellow("\n⚙️ Création des fichiers de configuration..."));
905
905
 
906
- // middleware.ts - Protection des routes /auth/* et /admin/*
906
+ // middleware.ts - Protection des routes /auth/*, /admin/* et /api/admin/*
907
907
  const middlewarePath = path.join(targetDir, "middleware.ts");
908
908
  if (!fs.existsSync(middlewarePath) || force) {
909
909
  const middleware = `import { type NextRequest, NextResponse } from "next/server";
@@ -911,6 +911,7 @@ import { createMiddlewareClient } from "@lastbrain/core/server";
911
911
 
912
912
  export async function middleware(request: NextRequest) {
913
913
  const { pathname } = request.nextUrl;
914
+ const isApi = pathname.startsWith("/api/");
914
915
 
915
916
  // Protéger les routes /auth/* (espace membre)
916
917
  if (pathname.startsWith("/auth")) {
@@ -920,33 +921,56 @@ export async function middleware(request: NextRequest) {
920
921
  data: { session },
921
922
  } = await supabase.auth.getSession();
922
923
 
923
- // Pas de session → redirection vers /signin
924
+ // Pas de session → nettoyage des cookies + redirection vers /auth/signin
924
925
  if (!session) {
925
- const redirectUrl = new URL("/signin", request.url);
926
+ const redirectUrl = new URL("/auth/signin", request.url);
926
927
  redirectUrl.searchParams.set("redirect", pathname);
927
- return NextResponse.redirect(redirectUrl);
928
+ const res = NextResponse.redirect(redirectUrl);
929
+ res.cookies.delete("sb-access-token");
930
+ res.cookies.delete("sb-refresh-token");
931
+ res.cookies.delete("sb:token");
932
+ res.cookies.delete("sb:refresh-token");
933
+ return res;
928
934
  }
929
935
 
930
936
  return response;
931
937
  } catch (error) {
932
938
  console.error("Middleware auth error:", error);
933
- return NextResponse.redirect(new URL("/signin", request.url));
939
+ const res = NextResponse.redirect(new URL("/auth/signin", request.url));
940
+ res.cookies.delete("sb-access-token");
941
+ res.cookies.delete("sb-refresh-token");
942
+ res.cookies.delete("sb:token");
943
+ res.cookies.delete("sb:refresh-token");
944
+ return res;
934
945
  }
935
946
  }
936
947
 
937
- // Protéger les routes /admin/* (superadmin uniquement)
938
- if (pathname.startsWith("/admin")) {
948
+ // Protéger les routes /admin/* et /api/admin/* (superadmin uniquement)
949
+ if (pathname.startsWith("/admin") || pathname.startsWith("/api/admin")) {
939
950
  try {
940
951
  const { supabase, response } = createMiddlewareClient(request);
941
952
  const {
942
953
  data: { session },
943
954
  } = await supabase.auth.getSession();
944
955
 
945
- // Pas de session → redirection vers /signin
956
+ // Pas de session → 401 JSON pour API, sinon redirection vers /auth/signin avec nettoyage cookies
946
957
  if (!session) {
947
- const redirectUrl = new URL("/signin", request.url);
958
+ if (isApi) {
959
+ const res = NextResponse.json({ error: "Non authentifié" }, { status: 401 });
960
+ res.cookies.delete("sb-access-token");
961
+ res.cookies.delete("sb-refresh-token");
962
+ res.cookies.delete("sb:token");
963
+ res.cookies.delete("sb:refresh-token");
964
+ return res;
965
+ }
966
+ const redirectUrl = new URL("/auth/signin", request.url);
948
967
  redirectUrl.searchParams.set("redirect", pathname);
949
- return NextResponse.redirect(redirectUrl);
968
+ const res = NextResponse.redirect(redirectUrl);
969
+ res.cookies.delete("sb-access-token");
970
+ res.cookies.delete("sb-refresh-token");
971
+ res.cookies.delete("sb:token");
972
+ res.cookies.delete("sb:refresh-token");
973
+ return res;
950
974
  }
951
975
 
952
976
  // Vérifier si l'utilisateur est superadmin
@@ -957,13 +981,24 @@ export async function middleware(request: NextRequest) {
957
981
 
958
982
  if (error || !isSuperAdmin) {
959
983
  console.error("Access denied: not a superadmin", error);
984
+ if (isApi) {
985
+ return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
986
+ }
960
987
  return NextResponse.redirect(new URL("/", request.url));
961
988
  }
962
989
 
963
990
  return response;
964
991
  } catch (error) {
965
992
  console.error("Middleware admin error:", error);
966
- return NextResponse.redirect(new URL("/", request.url));
993
+ if (isApi) {
994
+ return NextResponse.json({ error: "Erreur middleware" }, { status: 500 });
995
+ }
996
+ const res = NextResponse.redirect(new URL("/", request.url));
997
+ res.cookies.delete("sb-access-token");
998
+ res.cookies.delete("sb-refresh-token");
999
+ res.cookies.delete("sb:token");
1000
+ res.cookies.delete("sb:refresh-token");
1001
+ return res;
967
1002
  }
968
1003
  }
969
1004
 
@@ -985,7 +1020,9 @@ export const config = {
985
1020
  `;
986
1021
  await fs.writeFile(middlewarePath, middleware);
987
1022
  console.log(
988
- chalk.green("✓ middleware.ts créé (protection /auth/* et /admin/*)"),
1023
+ chalk.green(
1024
+ "✓ middleware.ts créé (protection /auth/*, /admin/* et /api/admin/*)",
1025
+ ),
989
1026
  );
990
1027
  }
991
1028
 
@@ -1561,6 +1598,13 @@ export const BUCKET_CONFIGS: Record<string, BucketConfig> = {
1561
1598
  return filePath.startsWith(\`\${userId}/\`);
1562
1599
  },
1563
1600
  },
1601
+ recipes: {
1602
+ name: "recipes",
1603
+ isPublic: true,
1604
+ description: "Public recipe images accessible by slug",
1605
+ allowedFileTypes: ["image/jpeg", "image/png", "image/webp", "image/gif"],
1606
+ maxFileSize: 50 * 1024 * 1024, // 50MB
1607
+ },
1564
1608
  // Example for future buckets:
1565
1609
  // public: {
1566
1610
  // name: "public",
@@ -204,16 +204,49 @@ export async function addModule(moduleName: string, targetDir: string) {
204
204
  console.log(
205
205
  chalk.yellow("\n⬆️ Application des nouvelles migrations..."),
206
206
  );
207
- try {
208
- execSync("supabase migration up", {
209
- cwd: targetDir,
210
- stdio: "inherit",
211
- });
212
- console.log(chalk.green("✓ Migrations appliquées"));
213
- } catch {
214
- console.error(
215
- chalk.red("❌ Erreur lors de l'application des migrations"),
207
+
208
+ // Appliquer directement avec psql au lieu de supabase migration up
209
+ const migrationsDir = path.join(targetDir, "supabase", "migrations");
210
+ const migrationFiles = fs
211
+ .readdirSync(migrationsDir)
212
+ .filter((f) => f.endsWith(".sql"))
213
+ .filter((f) => copiedMigrationFiles.includes(f))
214
+ .sort();
215
+
216
+ if (migrationFiles.length === 0) {
217
+ console.log(
218
+ chalk.yellow("⚠️ Aucune nouvelle migration à appliquer"),
216
219
  );
220
+ } else {
221
+ try {
222
+ const dbUrl =
223
+ "postgresql://postgres:postgres@127.0.0.1:54322/postgres";
224
+
225
+ for (const file of migrationFiles) {
226
+ const filePath = path.join(migrationsDir, file);
227
+ console.log(chalk.gray(` Exécution de ${file}...`));
228
+
229
+ execSync(`psql "${dbUrl}" -f "${filePath}"`, {
230
+ cwd: targetDir,
231
+ stdio: "pipe",
232
+ });
233
+ }
234
+
235
+ console.log(
236
+ chalk.green(
237
+ `✓ ${migrationFiles.length} migration(s) appliquée(s)`,
238
+ ),
239
+ );
240
+ } catch (error: any) {
241
+ console.error(
242
+ chalk.red("❌ Erreur lors de l'application des migrations"),
243
+ );
244
+ console.log(
245
+ chalk.gray(
246
+ "\nVous pouvez essayer manuellement:\n supabase db reset\n",
247
+ ),
248
+ );
249
+ }
217
250
  }
218
251
  } else {
219
252
  console.log(
@@ -287,13 +320,13 @@ export async function addModule(moduleName: string, targetDir: string) {
287
320
  // 7. Générer automatiquement les routes du module
288
321
  console.log(chalk.yellow("🔧 Génération des routes du module..."));
289
322
  try {
290
- execSync("pnpm build:modules", { cwd: targetDir, stdio: "inherit" });
323
+ execSync("pnpm run build:modules", { cwd: targetDir, stdio: "inherit" });
291
324
  console.log(chalk.green("✓ Routes du module générées"));
292
325
  } catch {
293
326
  console.error(chalk.red("❌ Erreur lors de la génération des routes"));
294
327
  console.error(
295
328
  chalk.gray(
296
- "Vous pouvez les générer manuellement avec: pnpm build:modules",
329
+ "Vous pouvez les générer manuellement avec: cd apps/<votre-app> && pnpm run build:modules",
297
330
  ),
298
331
  );
299
332
  }