0

Caleb: first version of supabase proxy to make db authentication optional

This commit is contained in:
Caleb Peffer 2024-04-21 09:31:22 -07:00
parent ad7951a679
commit be75aaa195
4 changed files with 83 additions and 22 deletions

View File

@ -3,6 +3,7 @@ import { getRateLimiter } from "../../src/services/rate-limiter";
import { RateLimiterMode } from "../../src/types"; import { RateLimiterMode } from "../../src/types";
import { supabase_service } from "../../src/services/supabase"; import { supabase_service } from "../../src/services/supabase";
export async function authenticateUser( export async function authenticateUser(
req, req,
res, res,
@ -13,6 +14,16 @@ export async function authenticateUser(
error?: string; error?: string;
status?: number; status?: number;
}> { }> {
console.log(process.env)
if(process.env.USE_DB_AUTHENTICATION === "false"){
console.log("WARNING - YOU'RE bypassing Authentication");
return { success: true};
}
console.log("USING SUPABASE AUTH");
const authHeader = req.headers.authorization; const authHeader = req.headers.authorization;
if (!authHeader) { if (!authHeader) {
return { success: false, error: "Unauthorized", status: 401 }; return { success: false, error: "Unauthorized", status: 401 };

View File

@ -8,6 +8,8 @@ import { addWebScraperJob } from "../../src/services/queue-jobs";
export async function crawlController(req: Request, res: Response) { export async function crawlController(req: Request, res: Response) {
try { try {
console.log("hello")
const { success, team_id, error, status } = await authenticateUser( const { success, team_id, error, status } = await authenticateUser(
req, req,
res, res,
@ -17,13 +19,14 @@ export async function crawlController(req: Request, res: Response) {
return res.status(status).json({ error }); return res.status(status).json({ error });
} }
const { success: creditsCheckSuccess, message: creditsCheckMessage } = if (process.env.USE_DB_AUTHENTICATION === "true") {
await checkTeamCredits(team_id, 1); const { success: creditsCheckSuccess, message: creditsCheckMessage } =
if (!creditsCheckSuccess) { await checkTeamCredits(team_id, 1);
return res.status(402).json({ error: "Insufficient credits" }); if (!creditsCheckSuccess) {
return res.status(402).json({ error: "Insufficient credits" });
}
} }
// authenticate on supabase
const url = req.body.url; const url = req.body.url;
if (!url) { if (!url) {
return res.status(400).json({ error: "Url is required" }); return res.status(400).json({ error: "Url is required" });

View File

@ -40,18 +40,22 @@ export async function scrapeHelper(
if (filteredDocs.length === 0) { if (filteredDocs.length === 0) {
return { success: true, error: "No page found", returnCode: 200 }; return { success: true, error: "No page found", returnCode: 200 };
} }
const { success, credit_usage } = await billTeam(
team_id, if (process.env.USE_DB_AUTHENTICATION === "true") {
filteredDocs.length const { success, credit_usage } = await billTeam(
); team_id,
if (!success) { filteredDocs.length
return { );
success: false, if (!success) {
error: return {
"Failed to bill team. Insufficient credits or subscription not found.", success: false,
returnCode: 402, error:
}; "Failed to bill team. Insufficient credits or subscription not found.",
returnCode: 402,
};
}
} }
return { return {
success: true, success: true,
data: filteredDocs[0], data: filteredDocs[0],

View File

@ -1,6 +1,49 @@
import { createClient } from "@supabase/supabase-js"; import { createClient, SupabaseClient } from '@supabase/supabase-js';
export const supabase_service = createClient<any>( // SupabaseService class initializes the Supabase client conditionally based on environment variables.
process.env.SUPABASE_URL, class SupabaseService {
process.env.SUPABASE_SERVICE_TOKEN, private client: SupabaseClient | null = null;
);
constructor() {
const supabaseUrl = process.env.SUPABASE_URL;
const supabaseServiceToken = process.env.SUPABASE_SERVICE_TOKEN;
// Only initialize the Supabase client if both URL and Service Token are provided.
if (process.env.USE_DB_AUTHENTICATION === "false") {
// Warn the user that Authentication is disabled by setting the client to null
console.warn("\x1b[33mAuthentication is disabled. Supabase client will not be initialized.\x1b[0m");
this.client = null;
} else if (!supabaseUrl || !supabaseServiceToken) {
console.error("\x1b[31mSupabase environment variables aren't configured correctly. Supabase client will not be initialized. Fix ENV configuration or disable DB authentication with USE_DB_AUTHENTICATION env variable\x1b[0m");
} else {
this.client = createClient(supabaseUrl, supabaseServiceToken);
}
}
// Provides access to the initialized Supabase client, if available.
getClient(): SupabaseClient | null {
return this.client;
}
}
// Using a Proxy to handle dynamic access to the Supabase client or service methods.
// This approach ensures that if Supabase is not configured, any attempt to use it will result in a clear error.
export const supabase_service: SupabaseClient = new Proxy(new SupabaseService(), {
get: function (target, prop, receiver) {
const client = target.getClient();
// If the Supabase client is not initialized, intercept property access to provide meaningful error feedback.
if (client === null) {
console.error("Attempted to access Supabase client when it's not configured.");
return () => {
throw new Error("Supabase client is not configured.");
};
}
// Direct access to SupabaseService properties takes precedence.
if (prop in target) {
return Reflect.get(target, prop, receiver);
}
// Otherwise, delegate access to the Supabase client.
return Reflect.get(client, prop, receiver);
}
}) as unknown as SupabaseClient;