All 3 auth methods work & update public profile table as well
This commit is contained in:
parent
07bf94d393
commit
f9fd5dafc5
2
app.json
2
app.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "Tech Tracker",
|
"name": "Tech Tracker",
|
||||||
"slug": "tech-tracker",
|
"slug": "tech-tracker-expo",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/images/icon.png",
|
"icon": "./assets/images/icon.png",
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { supabase } from '@/lib/supabase';
|
import { supabase } from '@/lib/supabase';
|
||||||
import * as AppleAuthentication from 'expo-apple-authentication'
|
import * as AppleAuthentication from 'expo-apple-authentication';
|
||||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||||
import { ThemedView } from '@/components/theme';
|
import { ThemedView } from '@/components/theme';
|
||||||
import { StyleSheet, Platform } from 'react-native';
|
import { StyleSheet, Platform } from 'react-native';
|
||||||
import Constants from 'expo-constants';
|
import Constants from 'expo-constants';
|
||||||
import * as Notifications from 'expo-notifications';
|
import * as Notifications from 'expo-notifications';
|
||||||
|
import type { updateUser } from '@/constants/Types';
|
||||||
|
|
||||||
const AppleSignInButton = () => {
|
const AppleSignInButton = () => {
|
||||||
const scheme = useColorScheme() ?? 'dark';
|
const scheme = useColorScheme() ?? 'dark';
|
||||||
@ -25,14 +26,10 @@ const AppleSignInButton = () => {
|
|||||||
//});
|
//});
|
||||||
if (credential.identityToken) {
|
if (credential.identityToken) {
|
||||||
const email = credential.email;
|
const email = credential.email;
|
||||||
const full_name = (
|
const full_name =
|
||||||
credential.fullName &&
|
credential.fullName && credential.fullName.givenName && credential.fullName.familyName
|
||||||
credential.fullName.givenName &&
|
|
||||||
credential.fullName.familyName
|
|
||||||
)
|
|
||||||
? `${credential.fullName.givenName} ${credential.fullName.familyName}`
|
? `${credential.fullName.givenName} ${credential.fullName.familyName}`
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
error,
|
error,
|
||||||
data: { user, session },
|
data: { user, session },
|
||||||
@ -40,32 +37,32 @@ const AppleSignInButton = () => {
|
|||||||
provider: 'apple',
|
provider: 'apple',
|
||||||
token: credential.identityToken,
|
token: credential.identityToken,
|
||||||
});
|
});
|
||||||
console.log(JSON.stringify({ error, user }, null, 2))
|
console.log(JSON.stringify({ error, user }, null, 2));
|
||||||
if (!error) {
|
if (!error && session) {
|
||||||
if (user && session) {
|
if (email) {
|
||||||
const data: any = {};
|
const data: updateUser = {
|
||||||
if (email) data.email = email;
|
email,
|
||||||
if (full_name) data.full_name = full_name;
|
full_name: full_name ?? '',
|
||||||
const { error: updateError } = await supabase.auth.updateUser({
|
};
|
||||||
|
const { error: authUpdateError } = await supabase.auth.updateUser({
|
||||||
data,
|
data,
|
||||||
|
})
|
||||||
|
const { error: updateError } = await supabase
|
||||||
|
.from('profiles')
|
||||||
|
.upsert({
|
||||||
|
id: session.user.id,
|
||||||
|
full_name,
|
||||||
|
email,
|
||||||
|
provider: 'apple',
|
||||||
|
updated_at: new Date(),
|
||||||
});
|
});
|
||||||
if (updateError) {
|
if (updateError) {
|
||||||
console.error('Error updating user metadata:', updateError);
|
console.error('Error updating user metadata:', updateError);
|
||||||
}
|
}
|
||||||
const { error: updateProfileError } =
|
|
||||||
await supabase.from('profiles').upsert({
|
|
||||||
id: session.user.id,
|
|
||||||
username: data?.email.split('@')[0],
|
|
||||||
full_name: data?.full_name,
|
|
||||||
updated_at: new Date(),
|
|
||||||
});
|
|
||||||
if (updateProfileError) {
|
|
||||||
console.error('Error updating profile:', updateProfileError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No identityToken.')
|
throw new Error('No identityToken.');
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e.code === 'ERR_REQUEST_CANCELED') {
|
if (e.code === 'ERR_REQUEST_CANCELED') {
|
||||||
@ -76,11 +73,11 @@ const AppleSignInButton = () => {
|
|||||||
console.log('Error signing in with Apple:', e);
|
console.log('Error signing in with Apple:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if (Platform.OS !== 'ios') return <ThemedView />;
|
if (Platform.OS !== 'ios') return <ThemedView />;
|
||||||
else return (
|
else
|
||||||
|
return (
|
||||||
<ThemedView style={styles.verticallySpaced}>
|
<ThemedView style={styles.verticallySpaced}>
|
||||||
<AppleAuthentication.AppleAuthenticationButton
|
<AppleAuthentication.AppleAuthenticationButton
|
||||||
buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
|
buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
|
||||||
@ -95,7 +92,7 @@ const AppleSignInButton = () => {
|
|||||||
/>
|
/>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
export default AppleSignInButton;
|
export default AppleSignInButton;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -4,6 +4,7 @@ import { supabase } from '@/lib/supabase';
|
|||||||
import { ThemedView, ThemedText, ThemedTextButton, ThemedTextInput } from '@/components/theme';
|
import { ThemedView, ThemedText, ThemedTextButton, ThemedTextInput } from '@/components/theme';
|
||||||
import AppleSignInButton from '@/components/auth/AppleSignIniOS';
|
import AppleSignInButton from '@/components/auth/AppleSignIniOS';
|
||||||
import AzureSignIn from './AzureSignIn';
|
import AzureSignIn from './AzureSignIn';
|
||||||
|
import type { updateUser } from '@/constants/Types';
|
||||||
|
|
||||||
// Tells Supabase Auth to continuously refresh the session automatically if
|
// Tells Supabase Auth to continuously refresh the session automatically if
|
||||||
// the app is in the foreground. When this is added, you will continue to receive
|
// the app is in the foreground. When this is added, you will continue to receive
|
||||||
@ -20,6 +21,7 @@ if (Platform.OS !== 'web') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Auth = () => {
|
const Auth = () => {
|
||||||
|
const [full_name, setFullName] = useState('');
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -50,11 +52,26 @@ const Auth = () => {
|
|||||||
data: { session },
|
data: { session },
|
||||||
error,
|
error,
|
||||||
} = await supabase.auth.signUp({
|
} = await supabase.auth.signUp({
|
||||||
email: email,
|
email,
|
||||||
password: password,
|
password,
|
||||||
});
|
});
|
||||||
if (error) Alert.alert(error.message);
|
if (error) Alert.alert(error.message);
|
||||||
else if (!session) Alert.alert('Please check your inbox for email verification!');
|
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);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,6 +84,15 @@ const Auth = () => {
|
|||||||
</ThemedText>
|
</ThemedText>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
|
|
||||||
|
<ThemedView style={styles.verticallySpaced}>
|
||||||
|
<ThemedTextInput
|
||||||
|
fontSize={24}
|
||||||
|
onChangeText={(text) => setFullName(text)}
|
||||||
|
value={full_name}
|
||||||
|
placeholder='Full Name'
|
||||||
|
/>
|
||||||
|
</ThemedView>
|
||||||
|
|
||||||
<ThemedView style={[styles.verticallySpaced]}>
|
<ThemedView style={[styles.verticallySpaced]}>
|
||||||
<ThemedTextInput
|
<ThemedTextInput
|
||||||
fontSize={24}
|
fontSize={24}
|
||||||
|
@ -7,6 +7,7 @@ import * as QueryParams from 'expo-auth-session/build/QueryParams';
|
|||||||
import { supabase } from '@/lib/supabase';
|
import { supabase } from '@/lib/supabase';
|
||||||
import { ThemedView, ThemedButton, ThemedText } from '@/components/theme';
|
import { ThemedView, ThemedButton, ThemedText } from '@/components/theme';
|
||||||
import { Colors } from '@/constants/Colors';
|
import { Colors } from '@/constants/Colors';
|
||||||
|
import type { updateUser } from '@/constants/Types';
|
||||||
|
|
||||||
WebBrowser.maybeCompleteAuthSession();
|
WebBrowser.maybeCompleteAuthSession();
|
||||||
|
|
||||||
@ -27,8 +28,6 @@ const AzureSignIn = () => {
|
|||||||
const signInWithAzure = async () => {
|
const signInWithAzure = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
console.log('Starting Azure sign-in with tenant-specific endpoint');
|
|
||||||
console.log('Redirect URI:', redirectUri);
|
|
||||||
|
|
||||||
// Create the MSAL auth request
|
// Create the MSAL auth request
|
||||||
const request = new AuthSession.AuthRequest({
|
const request = new AuthSession.AuthRequest({
|
||||||
@ -44,13 +43,9 @@ const AzureSignIn = () => {
|
|||||||
console.log('Generated auth URL:', authUrl);
|
console.log('Generated auth URL:', authUrl);
|
||||||
|
|
||||||
// Open the auth URL in a browser
|
// Open the auth URL in a browser
|
||||||
const result = await WebBrowser.openAuthSessionAsync(
|
const result = await WebBrowser.openAuthSessionAsync(authUrl, redirectUri, {
|
||||||
authUrl,
|
|
||||||
redirectUri,
|
|
||||||
{
|
|
||||||
showInRecents: true,
|
showInRecents: true,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Auth session result type:', result.type);
|
console.log('Auth session result type:', result.type);
|
||||||
|
|
||||||
@ -79,7 +74,7 @@ const AzureSignIn = () => {
|
|||||||
code_verifier: request.codeVerifier || '',
|
code_verifier: request.codeVerifier || '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
discovery
|
discovery,
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Token exchange successful');
|
console.log('Token exchange successful');
|
||||||
@ -94,6 +89,34 @@ const AzureSignIn = () => {
|
|||||||
token: tokenResult.idToken,
|
token: tokenResult.idToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check if profies table already has info (User is signing in, not signing up)
|
||||||
|
const { data: profileData, 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);
|
||||||
|
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)
|
||||||
|
Alert.alert('Error updating profile:', updateProfileError.message);
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('Supabase sign-in error:', error);
|
console.error('Supabase sign-in error:', error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -114,16 +137,13 @@ const AzureSignIn = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemedView style={styles.verticallySpaced}>
|
<ThemedView style={styles.verticallySpaced}>
|
||||||
<ThemedButton
|
<ThemedButton disabled={loading} onPress={signInWithAzure}>
|
||||||
disabled={loading}
|
|
||||||
onPress={signInWithAzure}
|
|
||||||
>
|
|
||||||
<ThemedText
|
<ThemedText
|
||||||
lightColor={Colors.dark.text}
|
lightColor={Colors.dark.text}
|
||||||
darkColor={Colors.light.text}
|
darkColor={Colors.light.text}
|
||||||
type="defaultSemiBold"
|
type='defaultSemiBold'
|
||||||
>
|
>
|
||||||
{loading ? "Signing in..." : "Sign in with Microsoft"}
|
{loading ? 'Signing in...' : 'Sign in with Microsoft'}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</ThemedButton>
|
</ThemedButton>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
export type updateUser = {
|
||||||
|
id?: string;
|
||||||
|
updated_at?: Date;
|
||||||
|
email?: string;
|
||||||
|
full_name?: string;
|
||||||
|
avatar_url?: string;
|
||||||
|
provider?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type NotificationMessage = {
|
export type NotificationMessage = {
|
||||||
sound?: string;
|
sound?: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -13,7 +13,10 @@ Notifications.setNotificationHandler({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const sendPushNotification = async(expoPushToken: string | null, notification: NotificationMessage) => {
|
export const sendPushNotification = async (
|
||||||
|
expoPushToken: string | null,
|
||||||
|
notification: NotificationMessage,
|
||||||
|
) => {
|
||||||
if (!expoPushToken) {
|
if (!expoPushToken) {
|
||||||
Alert.alert('Error', 'No push token found.');
|
Alert.alert('Error', 'No push token found.');
|
||||||
return;
|
return;
|
||||||
@ -86,18 +89,20 @@ async function registerForPushNotificationsAsync() {
|
|||||||
|
|
||||||
const PushNotificationManager = ({ children }: { children: React.ReactNode }) => {
|
const PushNotificationManager = ({ children }: { children: React.ReactNode }) => {
|
||||||
const [expoPushToken, setExpoPushToken] = useState<string | undefined>('');
|
const [expoPushToken, setExpoPushToken] = useState<string | undefined>('');
|
||||||
const [notification, setNotification] = useState<Notifications.Notification | undefined>(undefined);
|
const [notification, setNotification] = useState<Notifications.Notification | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
const notificationListener = useRef<Notifications.Subscription>();
|
const notificationListener = useRef<Notifications.Subscription>();
|
||||||
const responseListener = useRef<Notifications.Subscription>();
|
const responseListener = useRef<Notifications.Subscription>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
registerForPushNotificationsAsync().then(token => setExpoPushToken(token));
|
registerForPushNotificationsAsync().then((token) => setExpoPushToken(token));
|
||||||
|
|
||||||
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
|
notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
|
||||||
setNotification(notification);
|
setNotification(notification);
|
||||||
});
|
});
|
||||||
|
|
||||||
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
|
responseListener.current = Notifications.addNotificationResponseReceivedListener((response) => {
|
||||||
console.log(response);
|
console.log(response);
|
||||||
// Handle notification response here
|
// Handle notification response here
|
||||||
});
|
});
|
||||||
@ -109,5 +114,5 @@ const PushNotificationManager = ({ children }: { children: React.ReactNode }) =>
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
};
|
||||||
export default PushNotificationManager;
|
export default PushNotificationManager;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user