Initial commit: WaMarket MVP
Marketplace inversée (Next.js 16 App Router + Supabase Cloud) : auth, schéma + RLS, publication de besoins avec upload d'images, feed avec filtres, offres, acceptation via RPC, messagerie temps réel, dashboards, et Dockerfile pour déploiement Coolify.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import "server-only";
|
||||
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "@/lib/database.types";
|
||||
|
||||
// Uses the service role key — bypasses RLS entirely. Only import this from
|
||||
// trusted server-only code (e.g. the signup trigger fallback, admin tooling).
|
||||
// Never expose this client or its key to the browser.
|
||||
export function createAdminClient() {
|
||||
return createSupabaseClient<Database>(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.SUPABASE_SERVICE_ROLE_KEY!,
|
||||
{
|
||||
auth: {
|
||||
autoRefreshToken: false,
|
||||
persistSession: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { createBrowserClient } from "@supabase/ssr";
|
||||
import type { Database } from "@/lib/database.types";
|
||||
|
||||
export function createClient() {
|
||||
return createBrowserClient<Database>(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { createServerClient } from "@supabase/ssr";
|
||||
import { NextResponse, type NextRequest } from "next/server";
|
||||
|
||||
const PROTECTED_PREFIXES = ["/dashboard", "/messages", "/needs/new"];
|
||||
|
||||
function isProtectedPath(pathname: string) {
|
||||
if (PROTECTED_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {
|
||||
return true;
|
||||
}
|
||||
// /needs/[id]/edit
|
||||
return /^\/needs\/[^/]+\/edit(\/|$)/.test(pathname);
|
||||
}
|
||||
|
||||
export async function updateSession(request: NextRequest) {
|
||||
let supabaseResponse = NextResponse.next({ request });
|
||||
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
getAll() {
|
||||
return request.cookies.getAll();
|
||||
},
|
||||
setAll(cookiesToSet, headers) {
|
||||
cookiesToSet.forEach(({ name, value }) =>
|
||||
request.cookies.set(name, value)
|
||||
);
|
||||
supabaseResponse = NextResponse.next({ request });
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
);
|
||||
Object.entries(headers).forEach(([key, value]) =>
|
||||
supabaseResponse.headers.set(key, value)
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Do not run code between createServerClient and getClaims() — this
|
||||
// refreshes the session token on every request, which is what keeps
|
||||
// users from being randomly logged out.
|
||||
const { data } = await supabase.auth.getClaims();
|
||||
const user = data?.claims;
|
||||
|
||||
if (!user && isProtectedPath(request.nextUrl.pathname)) {
|
||||
const url = request.nextUrl.clone();
|
||||
url.pathname = "/auth/login";
|
||||
url.searchParams.set("redirect_to", request.nextUrl.pathname);
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
|
||||
return supabaseResponse;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { createServerClient } from "@supabase/ssr";
|
||||
import { cookies } from "next/headers";
|
||||
import type { Database } from "@/lib/database.types";
|
||||
|
||||
export async function createClient() {
|
||||
const cookieStore = await cookies();
|
||||
|
||||
return createServerClient<Database>(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
getAll() {
|
||||
return cookieStore.getAll();
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
);
|
||||
} catch {
|
||||
// Called from a Server Component — safe to ignore since the
|
||||
// proxy already refreshes the session on every request.
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user