feat: enhance Navbar with user profile and configuration links

- Updated Navbar component to include a link to the configuration page.
- Added a new Settings icon and link for user configuration.
- Improved user session handling and UI updates based on authentication state.

feat: implement OnboardingDialog for user setup

- Created OnboardingDialog component to guide users through initial setup.
- Added functionality to collect additional email addresses during onboarding.
- Integrated toast notifications for error handling during email addition.

feat: extend Supabase admin functions for user management

- Added functions to retrieve user IDs and full user information by email.
- Implemented error handling and logging for database operations.

feat: update Supabase schema with new user features

- Created new tables: user_profiles, additional_emails, and email_processing_usage.
- Enabled Row Level Security (RLS) on new tables with appropriate policies.
- Added triggers and functions for automatic user profile creation and email usage tracking.

feat: create public users table for simplified access

- Established a public.users table to mirror relevant auth.users data.
- Implemented triggers to automatically populate public.users upon user creation.
- Set up RLS policies to restrict access to user data.

chore: add configuration files for Supabase local development

- Included .gitignore and config.toml for local Supabase setup.
- Configured email testing server and other development settings.

feat: add configuration page for user settings

- Created configuration.astro page to manage user settings.
- Integrated AuthGuard to protect the configuration route.
This commit is contained in:
2025-06-07 04:37:03 -03:00
parent d37509338e
commit 0d2ab87519
17 changed files with 1584 additions and 101 deletions

View File

@@ -1,4 +1,5 @@
import { createClient } from "@supabase/supabase-js";
import type { SupabaseClient } from "@supabase/supabase-js";
/**
* Creates a Supabase client with service role key for server-side operations
@@ -49,3 +50,104 @@ export function handleDatabaseError(error: any) {
originalError: process.env.NODE_ENV === "development" ? error : undefined,
};
}
/**
* Find user ID by email address (primary or additional email)
* First checks public.users table, then additional_emails if needed
*/
export async function getUserIdByEmail(
email: string,
supabaseAdmin?: SupabaseClient
): Promise<string | null> {
const client = supabaseAdmin || createSupabaseAdmin();
try {
// First try to find user by primary email in public.users table
const { data: primaryUser, error: primaryError } = await client
.from("users")
.select("id")
.eq("email", email.toLowerCase())
.maybeSingle();
if (primaryError) {
console.error("Error finding user by primary email:", primaryError);
}
if (primaryUser) {
return primaryUser.id;
}
// If not found, check additional emails
const { data: additionalEmail, error: additionalError } = await client
.from("additional_emails")
.select("user_id")
.eq("email_address", email.toLowerCase())
// TODO: START REQUIRING VERIFIED ADDITIONAL EMAILS
// .eq("verified", true)
.eq("verified", false)
.maybeSingle();
if (additionalError) {
console.error("Error finding user by additional email:", additionalError);
return null;
}
return additionalEmail?.user_id || null;
} catch (error) {
console.error("Error in getUserIdByEmail:", error);
return null;
}
}
/**
* Get full user information by email address (primary or additional email)
* First checks public.users table, then additional_emails if needed
*/
export async function getUserByEmail(
email: string,
supabaseAdmin?: SupabaseClient
) {
const client = supabaseAdmin || createSupabaseAdmin();
try {
// First try to find user by primary email in public.users table
const { data: primaryUser, error: primaryError } = await client
.from("users")
.select("*")
.eq("email", email.toLowerCase())
.maybeSingle();
if (primaryError) {
console.error("Error finding user by primary email:", primaryError);
}
if (primaryUser) {
return primaryUser;
}
// If not found, check additional emails and join with users table
const { data: userViaAdditionalEmail, error: additionalError } = await client
.from("additional_emails")
.select(`
user_id,
users!inner (
id,
email,
created_at
)
`)
.eq("email_address", email.toLowerCase())
.eq("verified", true)
.maybeSingle();
if (additionalError) {
console.error("Error finding user by additional email:", additionalError);
return null;
}
return userViaAdditionalEmail?.users || null;
} catch (error) {
console.error("Error in getUserByEmail:", error);
return null;
}
}