From 86d1df35581365cf01116cb1a0d13c17534106d4 Mon Sep 17 00:00:00 2001
From: gibbyb <gib@gibbyb.com>
Date: Tue, 11 Mar 2025 10:05:31 -0500
Subject: [PATCH] Cleaned up auth. Ensured everything is necessary

---
 assets/fonts/SpaceMono-Regular.ttf | Bin
 components/auth/AppleSignIniOS.tsx |  28 +++++++-------
 components/auth/Auth.tsx           |  21 +++-------
 components/auth/AzureSignIn.tsx    |  53 ++++++++++----------------
 scripts/files_to_clipboard         |   0
 scripts/supabase_schema.sql        |  59 +++++++++++++++++++++++++++++
 6 files changed, 99 insertions(+), 62 deletions(-)
 mode change 100644 => 100755 assets/fonts/SpaceMono-Regular.ttf
 mode change 100644 => 100755 scripts/files_to_clipboard
 create mode 100644 scripts/supabase_schema.sql

diff --git a/assets/fonts/SpaceMono-Regular.ttf b/assets/fonts/SpaceMono-Regular.ttf
old mode 100644
new mode 100755
diff --git a/components/auth/AppleSignIniOS.tsx b/components/auth/AppleSignIniOS.tsx
index 55688c8..7dbe563 100644
--- a/components/auth/AppleSignIniOS.tsx
+++ b/components/auth/AppleSignIniOS.tsx
@@ -30,6 +30,7 @@ const AppleSignInButton = () => {
           credential.fullName && credential.fullName.givenName && credential.fullName.familyName
             ? `${credential.fullName.givenName} ${credential.fullName.familyName}`
             : null;
+
         const {
           error,
           data: { user, session },
@@ -41,26 +42,25 @@ const AppleSignInButton = () => {
         if (!error && session) {
           if (email) {
             const data: updateUser = {
+              id: session?.user.id,
+              updated_at: new Date(),
               email,
               full_name: full_name ?? '',
+              provider: 'apple',
             };
-            const { error: authUpdateError } = await supabase.auth.updateUser({
-              data,
-            });
-            if (authUpdateError)
-              Alert.alert('Error updating auth info:', authUpdateError.message);
-            const { error: updateError } = await supabase
+            const { error: updateError } = await supabase.auth.updateUser({ data });
+            if (updateError) Alert.alert('Error updating auth info:', updateError.message);
+            const { error: updateProfileError } = await supabase
               .from('profiles')
               .upsert({
-                id: session.user.id,
-                full_name,
-                email,
-                provider: 'apple',
+                id: session?.user.id ?? '',
                 updated_at: new Date(),
-            });
-            if (updateError) {
-              console.error('Error updating user metadata:', updateError);
-            }
+                email: email ?? '',
+                full_name: full_name ?? '',
+                provider: 'apple',
+              });
+            if (updateProfileError)
+              Alert.alert('Error updating profile:', updateProfileError.message);
           }
         }
       } else {
diff --git a/components/auth/Auth.tsx b/components/auth/Auth.tsx
index 5708325..b1f5d75 100644
--- a/components/auth/Auth.tsx
+++ b/components/auth/Auth.tsx
@@ -58,24 +58,15 @@ const Auth = () => {
     } = await supabase.auth.signUp({
       email,
       password,
+      options: {
+        data: {
+          full_name,
+          provider: 'email',
+        }
+      }
     });
     if (error) Alert.alert(error.message);
     else if (!session) Alert.alert('Please check your inbox for email verification!');
-    else {
-      const { error: updateProfileError } = await supabase
-        .from('profiles')
-        .upsert({
-          id: session.user.id,
-          full_name,
-          email,
-          provider: 'email',
-          updated_at: new Date(),
-      });
-      if (updateProfileError) {
-        Alert.alert('Error updating profile:', updateProfileError.message);
-        console.error('Error updating profile:', updateProfileError.message);
-      }
-    }
     setLoading(false);
   };
 
diff --git a/components/auth/AzureSignIn.tsx b/components/auth/AzureSignIn.tsx
index e1d8d19..c245a67 100644
--- a/components/auth/AzureSignIn.tsx
+++ b/components/auth/AzureSignIn.tsx
@@ -28,7 +28,7 @@ const AzureSignIn = () => {
   const signInWithAzure = async () => {
     try {
       setLoading(true);
-
+      
       // Create the MSAL auth request
       const request = new AuthSession.AuthRequest({
         clientId: clientId!,
@@ -38,17 +38,12 @@ const AzureSignIn = () => {
         responseType: AuthSession.ResponseType.Code,
       });
 
-      // Generate the auth URL with PKCE
+      // Generate the auth URL with PKCE & open in browser
       const authUrl = await request.makeAuthUrlAsync(discovery);
-      console.log('Generated auth URL:', authUrl);
-
-      // Open the auth URL in a browser
       const result = await WebBrowser.openAuthSessionAsync(authUrl, redirectUri, {
         showInRecents: true,
       });
 
-      console.log('Auth session result type:', result.type);
-
       if (result.type === 'success' && result.url) {
         // Parse the URL to get the authorization code
         const { params, errorCode } = QueryParams.getQueryParams(result.url);
@@ -57,13 +52,10 @@ const AzureSignIn = () => {
           const errorMessage = params.error_description || params.error || errorCode;
           throw new Error(`Error during authentication: ${errorMessage}`);
         }
-
         if (!params.code) {
           throw new Error('No authorization code received');
         }
 
-        console.log('Authorization code received');
-
         // Exchange the code for tokens
         const tokenResult = await AuthSession.exchangeCodeAsync(
           {
@@ -76,9 +68,6 @@ const AzureSignIn = () => {
           },
           discovery,
         );
-
-        console.log('Token exchange successful');
-
         if (!tokenResult.idToken) {
           throw new Error('No ID token received');
         }
@@ -88,40 +77,38 @@ const AzureSignIn = () => {
           provider: 'azure',
           token: tokenResult.idToken,
         });
+        console.log(JSON.stringify({ data, error }, null, 2));
 
-        // Check if profies table already has info (User is signing in, not signing up)
-        const { data: profileData, error: profileError } = await supabase
+        const { data: profile, error: profileError } = await supabase
           .from('profiles')
           .select('*')
           .eq('id', data.user?.id)
           .single();
 
-        if (profileData.email === '' || !profileData.email && data.session?.user.email) {
-          const updateData: updateUser = {
-            email: data.session?.user.email ?? '',
-          };
-          const { error: updateAuthError } = await supabase.auth.updateUser({
-            data: updateData,
-          });
-          if (updateAuthError)
-            Alert.alert('Error updating auth info:', updateAuthError.message);
+        if (profileError) {
+          console.error('Supabase profile error:', profileError);
+          throw profileError;
+        }
+        console.log(JSON.stringify({ profile, error: profileError }, null, 2));
+
+        if (profile?.provider !== 'azure') {
           const { error: updateProfileError } = await supabase
-          .from('profiles')
-          .upsert({
-            id: data.session?.user.id ?? '',
-            email: data.session?.user.email ?? '',
-            provider: 'azure',
-            updated_at: new Date(),
-          });
-          if (updateProfileError)
+            .from('profiles')
+            .upsert({
+              id: data.session?.user.id ?? '',
+              provider: 'azure',
+              updated_at: new Date(),
+            });
+          if (updateProfileError) { 
+            console.error('Supabase profile error:', updateProfileError);
             Alert.alert('Error updating profile:', updateProfileError.message);
+          }
         }
 
         if (error) {
           console.error('Supabase sign-in error:', error);
           throw error;
         }
-
         console.log('Successfully signed in with Azure via Supabase');
         return data;
       } else {
diff --git a/scripts/files_to_clipboard b/scripts/files_to_clipboard
old mode 100644
new mode 100755
diff --git a/scripts/supabase_schema.sql b/scripts/supabase_schema.sql
new file mode 100644
index 0000000..74ada70
--- /dev/null
+++ b/scripts/supabase_schema.sql
@@ -0,0 +1,59 @@
+-- Create a table for public profiles
+create table profiles (
+  id uuid references auth.users on delete cascade not null primary key,
+  updated_at timestamp with time zone,
+  email text,
+  full_name text,
+  avatar_url text,
+  provider text,
+
+  constraint full_name_length check (char_length(full_name) >= 3 and char_length(full_name) <= 50),
+);
+-- Set up Row Level Security (RLS)
+-- See https://supabase.com/docs/guides/auth/row-level-security for more details.
+alter table profiles
+  enable row level security;
+
+create policy "Public profiles are viewable by everyone." on profiles
+  for select using (true);
+
+create policy "Users can insert their own profile." on profiles
+  for insert with check ((select auth.uid()) = id);
+
+create policy "Users can update own profile." on profiles
+  for update using ((select auth.uid()) = id);
+
+-- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth.
+-- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details.
+create function public.handle_new_user()
+returns trigger
+set search_path = ''
+as $$
+begin
+  insert into public.profiles (id, email, full_name, avatar_url, provider, updated_at)
+  values (
+    new.id,
+    new.email,
+    new.raw_user_meta_data->>'full_name',
+    new.raw_user_meta_data->>'avatar_url'
+    new.raw_user_meta_data->>'provider',
+    now()
+  );
+  return new;
+end;
+$$ language plpgsql security definer;
+create trigger on_auth_user_created
+  after insert on auth.users
+  for each row execute procedure public.handle_new_user();
+
+-- Set up Storage!
+insert into storage.buckets (id, name)
+  values ('avatars', 'avatars');
+
+-- Set up access controls for storage.
+-- See https://supabase.com/docs/guides/storage#policy-examples for more details.
+create policy "Avatar images are publicly accessible." on storage.objects
+  for select using (bucket_id = 'avatars');
+
+create policy "Anyone can upload an avatar." on storage.objects
+  for insert with check (bucket_id = 'avatars');