Skip to content

Commit

Permalink
Merge pull request #1183 from The-Commit-Company/mobile-auth
Browse files Browse the repository at this point in the history
chore(mobile): consolidated all auth utils
  • Loading branch information
nikkothari22 authored Dec 18, 2024
2 parents 8fcd49a + f2376c3 commit 20bd00b
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 52 deletions.
16 changes: 14 additions & 2 deletions apps/mobile/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,20 @@
"favicon": "./assets/favicon.png"
},
"plugins": [
"expo-router",
"expo-secure-store"
[
"expo-router"
],
[
"expo-secure-store"
],
[
"expo-font",
{
"fonts": [
"./assets/fonts/CalSans-SemiBold.otf"
]
}
]
],
"extra": {
"router": {
Expand Down
7 changes: 4 additions & 3 deletions apps/mobile/app/[site_id]/(tabs)/profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { revokeAsync } from 'expo-auth-session';
import { useContext } from 'react';
import { SiteContext } from '../../_layout';
import * as SecureStore from 'expo-secure-store';
import { clearDefaultSite, DEFAULT_SITE_KEY, deleteAccessToken, getAccessTokenKey, getRevocationEndpoint } from '@lib/auth';

const SCREEN_OPTIONS = {
title: 'Profile',
Expand Down Expand Up @@ -117,11 +118,11 @@ function ListFooterComponent() {
clientId: siteInformation?.client_id || '',
token: tokenParams?.token?.() || ''
}, {
revocationEndpoint: siteInformation?.url + '/api/method/frappe.integrations.oauth2.revoke_token'
revocationEndpoint: getRevocationEndpoint(siteInformation?.url || '')
}).then(result => {
return SecureStore.deleteItemAsync(`${siteInformation?.sitename}-access-token`)
return deleteAccessToken(siteInformation?.sitename || '')
}).then((result) => {
return AsyncStorage.removeItem('default-site')
return clearDefaultSite()
}).then(() => {
router.replace('/landing')
}).catch((error) => {
Expand Down
39 changes: 11 additions & 28 deletions apps/mobile/app/[site_id]/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Text } from "@components/nativewindui/Text";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { createContext, useEffect, useState } from "react";
import { View } from "react-native";
import { SiteInformation } from "../../types/SiteInformation";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from 'expo-secure-store';
import { TokenResponse } from "expo-auth-session";
import { FrappeProvider } from "frappe-react-sdk";
import FullPageLoader from "@components/layout/FullPageLoader";
import { getAccessToken, getSiteFromStorage, getTokenEndpoint, storeAccessToken } from "@lib/auth";

export default function SiteLayout() {

Expand All @@ -26,27 +24,15 @@ export default function SiteLayout() {

let site_info: SiteInformation | null = null

AsyncStorage.getItem('sites')
.then(sites => {
if (!sites) {
router.replace('/landing')

// TODO: Show the user a toast saying that the site is not found

return null
}

const parsedSites: { [key: string]: SiteInformation } = JSON.parse(sites)
const siteInfo = parsedSites[site_id]

getSiteFromStorage(site_id)
.then(siteInfo => {
if (!siteInfo) {
router.replace('/landing')

// TODO: Show the user a toast saying that the site is not found

return null
}

setSiteInfo(siteInfo)
site_info = siteInfo

Expand All @@ -55,7 +41,7 @@ export default function SiteLayout() {
.then((siteInfo: SiteInformation | null) => {
if (!siteInfo) return null

return SecureStore.getItemAsync(`${site_id}-access-token`)
return getAccessToken(siteInfo.sitename)
})
.then(accessToken => {
if (!accessToken) {
Expand All @@ -65,16 +51,18 @@ export default function SiteLayout() {

return null
}
const tokenConfig: TokenResponse = JSON.parse(accessToken)

let tokenResponse = new TokenResponse(tokenConfig)
let tokenResponse = new TokenResponse(accessToken)

if (tokenResponse.shouldRefresh()) {
console.log("Refreshing token")
return tokenResponse.refreshAsync({
clientId: site_info?.client_id || '',
}, {
tokenEndpoint: site_info?.url + '/api/method/frappe.integrations.oauth2.get_token',
tokenEndpoint: getTokenEndpoint(site_info?.url || ''),
}).then(async (tokenResponse) => {
await storeAccessToken(site_info?.sitename || '', tokenResponse)
return tokenResponse
})
} else {
return tokenResponse
Expand All @@ -92,12 +80,7 @@ export default function SiteLayout() {

return <>
<Stack.Screen options={{ headerShown: false }} />
{loading ? <View className="flex-1 justify-center items-center gap-2">

{/* TODO: Change this UI */}
<Text className="text-4xl font-bold">raven</Text>
<Text>Setting up your workspace...</Text>
</View> :
{loading ? <FullPageLoader /> :
<SiteContext.Provider value={siteInfo}>
<FrappeProvider
url={siteInfo?.url}
Expand Down
3 changes: 2 additions & 1 deletion apps/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { useAsyncStorage } from '@react-native-async-storage/async-storage';
export default function RootLayout() {

const path = usePathname()
console.log(path)

const { getItem } = useAsyncStorage(`default-site`)
console.log(path)

// On load, check if the user has a site set

Expand Down Expand Up @@ -46,6 +46,7 @@ export default function RootLayout() {
<KeyboardProvider statusBarTranslucent navigationBarTranslucent>
<ThemeProvider value={NAV_THEME[colorScheme]}>
<Stack>
<Stack.Screen name="index" />
<Stack.Screen name="landing" />
<Stack.Screen name="[site_id]" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
Expand Down
12 changes: 12 additions & 0 deletions apps/mobile/app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Stack } from 'expo-router';
import FullPageLoader from '@components/layout/FullPageLoader';

export default function InitialScreen() {

return (
<>
<Stack.Screen options={{ title: 'Raven' }} />
<FullPageLoader />
</>
);
}
8 changes: 4 additions & 4 deletions apps/mobile/app/landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { View } from 'react-native';
import { Text } from '@components/nativewindui/Text';
import AddSite from '@components/features/auth/AddSite';

export default function NotFoundScreen() {
export default function LandingScreen() {
return (
<>
<Stack.Screen options={{ title: 'Sites', headerTitle: 'Sites' }} />
<View className='flex-1 py-8 px-4 gap-3'>
<Text className='text-3xl font-bold'>raven</Text>
<Stack.Screen options={{ title: 'Sites', headerShown: false }} />
<View className='flex-1 justify-center pt-48 px-6 gap-3'>
<Text className='text-5xl font-bold font-cal-sans'>raven</Text>
<View className='h-2' />
<AddSite />
</View>
Expand Down
17 changes: 3 additions & 14 deletions apps/mobile/components/features/auth/AddSite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import { BottomSheetView } from '@gorhom/bottom-sheet'
import { useCallback, useState } from 'react'
import { Alert, View } from 'react-native'
import * as WebBrowser from 'expo-web-browser'
import * as SecureStore from 'expo-secure-store';
import { CodeChallengeMethod, exchangeCodeAsync, makeRedirectUri, ResponseType, TokenResponse, useAuthRequest } from 'expo-auth-session';
import AsyncStorage from '@react-native-async-storage/async-storage'
import { router } from 'expo-router'
import { SiteInformation } from '../../../types/SiteInformation'
import { addSiteToStorage, discovery, setDefaultSite, storeAccessToken } from '@lib/auth'

WebBrowser.maybeCompleteAuthSession();

Expand Down Expand Up @@ -87,12 +86,6 @@ const AddSite = (props: Props) => {
)
}

const discovery = {
authorizationEndpoint: '/api/method/frappe.integrations.oauth2.authorize',
tokenEndpoint: '/api/method/frappe.integrations.oauth2.get_token',
revocationEndpoint: '/api/method/frappe.integrations.oauth2.revoke_token',
}

const SiteAuthFlowSheet = ({ siteInformation, onDismiss }: { siteInformation: SiteInformation, onDismiss: () => void }) => {

const discoveryWithURL = {
Expand Down Expand Up @@ -141,8 +134,8 @@ const SiteAuthFlowSheet = ({ siteInformation, onDismiss }: { siteInformation: Si
// 3. Redirect the user to the /[sitename] route

storeAccessToken(siteInformation.sitename, token)
.then(() => AsyncStorage.mergeItem('sites', JSON.stringify({ [siteInformation.sitename]: siteInformation })))
.then(() => AsyncStorage.setItem(`default-site`, siteInformation.sitename))
.then(() => addSiteToStorage(siteInformation.sitename, siteInformation))
.then(() => setDefaultSite(siteInformation.sitename))
.then(() => router.replace(`/${siteInformation.sitename}`))
.then(() => onDismiss())
}
Expand All @@ -163,8 +156,4 @@ const SiteAuthFlowSheet = ({ siteInformation, onDismiss }: { siteInformation: Si
</View>
}

const storeAccessToken = (siteName: string, token: TokenResponse) => {
return SecureStore.setItemAsync(`${siteName}-access-token`, JSON.stringify(token))
}

export default AddSite
19 changes: 19 additions & 0 deletions apps/mobile/components/layout/FullPageLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Text } from '@components/nativewindui/Text'
import React from 'react'
import { View } from 'react-native'

type Props = {
title?: string
description?: string
}

const FullPageLoader = ({ title = 'raven', description = 'Setting up your workspace...' }: Props) => {
return (
<View className="flex-1 justify-center items-center gap-2">
<Text className="text-4xl font-bold font-cal-sans">{title}</Text>
<Text className='text-muted-foreground'>{description}</Text>
</View>
)
}

export default FullPageLoader
Loading

0 comments on commit 20bd00b

Please sign in to comment.