From 6592864bc42ce9d2084bb43bca6f952b0baa10dc Mon Sep 17 00:00:00 2001 From: Jakob Stornig Date: Fri, 8 Dec 2023 14:51:05 +0100 Subject: [PATCH] feat: introduced Authentification Context --- app/(tabs)/_layout.tsx | 16 +++- app/(tabs)/home/index.tsx | 9 ++- app/_layout.tsx | 12 +++ app/contexts/AuthContext.tsx | 137 +++++++++++++++++++++++++++++++++++ app/index.jsx | 9 --- app/index.tsx | 14 ++++ app/login.tsx | 22 ++++++ package-lock.json | 9 +++ package.json | 3 +- 9 files changed, 215 insertions(+), 16 deletions(-) create mode 100644 app/_layout.tsx create mode 100644 app/contexts/AuthContext.tsx delete mode 100644 app/index.jsx create mode 100644 app/index.tsx create mode 100644 app/login.tsx diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index fb022e3..2987b71 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -1,15 +1,22 @@ import { Tabs } from "expo-router/tabs"; -import {StyleSheet, View} from "react-native" +import {StyleSheet, View, Text} from "react-native" import { FontAwesome } from "@expo/vector-icons"; import {useThemeColor} from "../../hooks/hooks"; -import React from "react"; +import React, { useEffect } from "react"; +import { Redirect } from "expo-router"; +import { useAuth } from "../contexts/AuthContext"; export default function Layout() { // const selectedColor: string = useThemeColor( "tabIconSelected"); // const defaultColor: string = useThemeColor("tabIconDefault"); // const backgroundColor: string = useThemeColor("backgroundColor"); // const tabBarColor: string = useThemeColor("tabBarColor"); + const {authState} = useAuth() + useEffect(()=>{ + console.log(authState, "in root Layout") + },[authState]) + const styles = StyleSheet.create({ sceneContainer: { @@ -27,6 +34,11 @@ export default function Layout() { tabBarStyle: styles.tabBar, } + if(!authState?.authenticated){ + return ( + ) + } + return ( + {plusShow && { router.push("/(tabs)/home/addItem") }}/>} @@ -61,7 +62,7 @@ export default function Page() { data={data} ListHeaderComponent={ <> - console.log("hello")}> + } @@ -72,7 +73,7 @@ export default function Page() { scrollEventThrottle={20} > - + ); } \ No newline at end of file diff --git a/app/_layout.tsx b/app/_layout.tsx new file mode 100644 index 0000000..42cdecd --- /dev/null +++ b/app/_layout.tsx @@ -0,0 +1,12 @@ +import { Slot } from 'expo-router' +import React from 'react' +import { AuthProvider } from './contexts/AuthContext' + +export default function _layout() { + console.log("layout called") + return ( + + + + ) +} \ No newline at end of file diff --git a/app/contexts/AuthContext.tsx b/app/contexts/AuthContext.tsx new file mode 100644 index 0000000..236c962 --- /dev/null +++ b/app/contexts/AuthContext.tsx @@ -0,0 +1,137 @@ +import { createContext, useContext, useEffect, useState } from "react"; +import { Platform } from "react-native"; +import * as SecureStore from 'expo-secure-store' + +interface AuthProps { + authState?: {email: string | null; authenticated: boolean | null; session: string | null}; + onRegister?: (email: string, password: string) => Promise; + onLogin?: (email: string, password: string) => Promise + onLogout?: () => void +} + +const SESSION_KEY = 'my_session' +const USER_KEY = "email" +const AuthContext = createContext({}) + +export const useAuth = ()=>{ + return useContext(AuthContext) +} + +async function setStorageItemAsync(key: string, value: string | null){ + if (Platform.OS === 'web') { + try { + if (value === null) { + localStorage.removeItem(key); + } else { + localStorage.setItem(key, value); + } + } catch (e) { + console.error('Local storage is unavailable:', e); + } + } else { + if (value == null) { + await SecureStore.deleteItemAsync(key); + } else { + await SecureStore.setItemAsync(key, value); + } + } +} + +async function getStorageItemAsync(key: string) : Promise { + if(Platform.OS === 'web'){ + return localStorage.getItem(key) + }else{ + return SecureStore.getItemAsync(key) + } +} + +export const AuthProvider = ({children}: any) => { + const [authState, setAuthState] = useState<{ + email: string | null; + authenticated: boolean | null; + session : string | null; + isLoading: boolean; + }>({ + email: null, authenticated: null, session: null, isLoading: false + }); + + useEffect(() => { + const loadSession = async () => { + setAuthState((prev) => { + return { + ...prev, + isLoading: true + } + }) + + + const session = await getStorageItemAsync(SESSION_KEY) + const email = await getStorageItemAsync(USER_KEY) + + if(session && email){ + setAuthState({ + email: email, + authenticated: true, + session: session, + isLoading: false + }) + } + setAuthState((prev) => { + return { + ...prev, + isLoading: false + } + }) + } + loadSession() + },[]) + + + const register = async (email: string, password: string) => { + //registration Logic goes here + } + + const login = async (email: string, password: string) => { + + //login functionality goes here + console.log("login called") + setAuthState((prev) => { + return{ + ...prev, + isLoading: true + } + }) + + setAuthState({ + email: email, + authenticated: true, + session: "super duper session token das wir vlt mal brauchen", + isLoading: false + + }) + + await setStorageItemAsync(SESSION_KEY, "super duper session token das wir vlt mal brauchen") + await setStorageItemAsync(USER_KEY, email) + } + + const logout = async () => { + await setStorageItemAsync(SESSION_KEY, null) + await setStorageItemAsync(USER_KEY, null) + + setAuthState({ + email: null, + authenticated: false, + session: null, + isLoading: false + }); + }; + + + const value = { + onRegister: register, + onLogin: login, + onLogout: logout, + authState + } + return {children} +} \ No newline at end of file diff --git a/app/index.jsx b/app/index.jsx deleted file mode 100644 index 05e453f..0000000 --- a/app/index.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View, Text } from 'react-native' -import React from 'react' -import { Redirect } from 'expo-router' - -export default function index() { - return ( - - ) -} \ No newline at end of file diff --git a/app/index.tsx b/app/index.tsx new file mode 100644 index 0000000..094049b --- /dev/null +++ b/app/index.tsx @@ -0,0 +1,14 @@ + +import React, { useEffect } from 'react' +import { Redirect } from 'expo-router' +import { useAuth } from './contexts/AuthContext' + +export default function index() { + const {authState} = useAuth() + + + return ( + + + ) +} \ No newline at end of file diff --git a/app/login.tsx b/app/login.tsx new file mode 100644 index 0000000..cb8113c --- /dev/null +++ b/app/login.tsx @@ -0,0 +1,22 @@ +import { View, Text } from 'react-native' +import React, { useEffect } from 'react' +import { useAuth } from './contexts/AuthContext' +import { Redirect } from 'expo-router'; + +export default function login() { + const {authState, onLogin} = useAuth(); + useEffect(() => { + login() + }, []) + + + const login = async() => { + onLogin!("test", "test"); + } + return ( + + login + + + ) +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a72517a..6e8bf8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "expo-font": "~11.4.0", "expo-linking": "~5.0.2", "expo-router": "^2.0.0", + "expo-secure-store": "~12.3.1", "expo-splash-screen": "~0.20.5", "expo-status-bar": "~1.6.0", "expo-system-ui": "~2.4.0", @@ -9008,6 +9009,14 @@ } } }, + "node_modules/expo-secure-store": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-12.3.1.tgz", + "integrity": "sha512-XLIgWDiIuiR0c+AA4NCWWibAMHCZUyRcy+lQBU49U6rvG+xmd3YrBJfQjfqAPyLroEqnLPGTWUX57GyRsfDOQw==", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-splash-screen": { "version": "0.20.5", "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.20.5.tgz", diff --git a/package.json b/package.json index 4a2fb5a..914e2df 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "react-native-gesture-handler": "~2.12.0", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", - "react-native-web": "~0.19.6" + "react-native-web": "~0.19.6", + "expo-secure-store": "~12.3.1" }, "devDependencies": { "@babel/core": "^7.20.0",