Add version files and update imports for trip model; enhance error handling
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
|
||||
import { handleOptions, json } from "../_shared/http.ts";
|
||||
|
||||
const supabaseUrl = Deno.env.get("SUPABASE_URL");
|
||||
const supabaseAnonKey = Deno.env.get("SUPABASE_ANON_KEY");
|
||||
|
||||
if (!supabaseUrl || !supabaseAnonKey) {
|
||||
throw new Error("SUPABASE_URL and SUPABASE_ANON_KEY are required");
|
||||
}
|
||||
|
||||
type JwtClaims = {
|
||||
sub?: string;
|
||||
aud?: string | string[];
|
||||
role?: string;
|
||||
email?: string;
|
||||
exp?: number;
|
||||
iat?: number;
|
||||
nbf?: number;
|
||||
iss?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
function parseJwtClaims(token: string): {
|
||||
claims: JwtClaims | null;
|
||||
decodeError: string | null;
|
||||
partsCount: number;
|
||||
} {
|
||||
const parts = token.split(".");
|
||||
if (parts.length !== 3) {
|
||||
return {
|
||||
claims: null,
|
||||
decodeError: `JWT must have 3 parts, got ${parts.length}`,
|
||||
partsCount: parts.length,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
||||
const padLen = (4 - (b64.length % 4)) % 4;
|
||||
const padded = b64 + "=".repeat(padLen);
|
||||
const decoded = atob(padded);
|
||||
const claims = JSON.parse(decoded) as JwtClaims;
|
||||
return { claims, decodeError: null, partsCount: parts.length };
|
||||
} catch (error) {
|
||||
return {
|
||||
claims: null,
|
||||
decodeError: error instanceof Error ? error.message : "Unknown decode error",
|
||||
partsCount: parts.length,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function unixNow() {
|
||||
return Math.floor(Date.now() / 1000);
|
||||
}
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
const preflight = handleOptions(req);
|
||||
if (preflight) return preflight;
|
||||
|
||||
if (req.method !== "GET" && req.method !== "POST") {
|
||||
return json({ error: "Method not allowed" }, 405);
|
||||
}
|
||||
|
||||
const authHeader = req.headers.get("Authorization");
|
||||
const bearerPrefixOk = authHeader?.startsWith("Bearer ") ?? false;
|
||||
const token = bearerPrefixOk ? authHeader!.slice(7).trim() : "";
|
||||
const tokenPresent = token.length > 0;
|
||||
|
||||
const jwtParse = tokenPresent
|
||||
? parseJwtClaims(token)
|
||||
: { claims: null, decodeError: "Missing bearer token", partsCount: 0 };
|
||||
|
||||
const claims = jwtParse.claims;
|
||||
const now = unixNow();
|
||||
|
||||
const authClient = createClient(supabaseUrl, supabaseAnonKey, {
|
||||
global: { headers: { Authorization: authHeader ?? "" } },
|
||||
});
|
||||
const { data: userData, error: userError } = await authClient.auth.getUser();
|
||||
|
||||
const checks = {
|
||||
authorizationHeaderPresent: authHeader != null,
|
||||
bearerPrefixOk,
|
||||
tokenPresent,
|
||||
tokenLength: token.length,
|
||||
tokenPreview: tokenPresent ? `${token.slice(0, 16)}...` : null,
|
||||
jwtPartsCount: jwtParse.partsCount,
|
||||
jwtDecodeError: jwtParse.decodeError,
|
||||
claimSub: claims?.sub ?? null,
|
||||
claimRole: claims?.role ?? null,
|
||||
claimAud: claims?.aud ?? null,
|
||||
claimEmail: claims?.email ?? null,
|
||||
claimIssuer: claims?.iss ?? null,
|
||||
claimExp: claims?.exp ?? null,
|
||||
claimIat: claims?.iat ?? null,
|
||||
claimNbf: claims?.nbf ?? null,
|
||||
nowUnix: now,
|
||||
isExpired:
|
||||
typeof claims?.exp === "number" ? claims.exp <= now : null,
|
||||
notYetValid:
|
||||
typeof claims?.nbf === "number" ? claims.nbf > now : null,
|
||||
authGetUserOk: !!userData.user && !userError,
|
||||
authGetUserError: userError?.message ?? null,
|
||||
authGetUserUserId: userData.user?.id ?? null,
|
||||
authGetUserEmail: userData.user?.email ?? null,
|
||||
};
|
||||
|
||||
return json({
|
||||
function: "auth-debug",
|
||||
verifyJwtDisabled: true,
|
||||
checks,
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user