From dd3b769bcb156feb4b0c9b65def5039cd1ee5eea Mon Sep 17 00:00:00 2001 From: Antonin Cezard Date: Mon, 17 Jan 2022 17:11:45 +0100 Subject: [PATCH] feat: Implement MVP feature --- package.json | 2 +- src/App.js | 5 +- src/libs/client.js | 2 +- src/libs/services/SessionService.js | 99 ++++++++++++++++++----------- src/screens/connectors/HomeView.js | 37 +++++++---- src/screens/routes/CozyAppView.js | 11 +++- yarn.lock | 18 +++--- 7 files changed, 109 insertions(+), 65 deletions(-) diff --git a/package.json b/package.json index 96df94ba5..368bc5d03 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "base-64": "^1.0.0", "bluebird-retry": "^0.11.0", "cheerio": "^1.0.0-rc.9", - "cozy-client": "^27.8.0", + "cozy-client": "^27.12.0", "cozy-client-js": "^0.20.0", "cozy-intent": "^1.2.0", "cozy-ui": "^52.0.0", diff --git a/src/App.js b/src/App.js index 5ae7fdfa7..d1a61eb3d 100644 --- a/src/App.js +++ b/src/App.js @@ -18,6 +18,7 @@ import {SplashScreenProvider} from './screens/providers/SplashScreenProvider' import {clearClient, getClient} from './libs/client' import {lightTheme} from './theme' import {useSplashScreen} from './hooks/useSplashScreen' +import {SessionProvider} from './libs/services/SessionService.js' const Root = createStackNavigator() const MainStack = createStackNavigator() @@ -80,7 +81,9 @@ const App = () => { return client ? ( - + + + ) : ( diff --git a/src/libs/client.js b/src/libs/client.js index bfaeb73a5..d7b6be98e 100644 --- a/src/libs/client.js +++ b/src/libs/client.js @@ -10,7 +10,7 @@ const COZY_PREFIX = 'cozy://' * Clears the storage key related to client authentication */ export const clearClient = () => { - return AsyncStorage.removeItem(OAUTH_STORAGE_KEY) + return AsyncStorage.multiRemove(OAUTH_STORAGE_KEY, 'FLAG_TOKEN') } /** diff --git a/src/libs/services/SessionService.js b/src/libs/services/SessionService.js index 9d5331785..54782e24a 100644 --- a/src/libs/services/SessionService.js +++ b/src/libs/services/SessionService.js @@ -3,59 +3,84 @@ import AsyncStorage from '@react-native-async-storage/async-storage' import {useClient} from 'cozy-client' class SessionService { - SESSION_CODE = 'sessioncode' + SESSION_CODE = 'session_code' LOGIN = 'login' - DID_CONSUME_TOKEN = 'didconsumetoken' - - state = { - consumedToken: false, - sessionCode: '', - } + FLAG_TOKEN = 'flagtoken' + IS_REDIRECT = '/auth/login' constructor(client) { this.client = client + this.responseToken = this.getFlagToken() } - init = async () => { - const didConsumeToken = await AsyncStorage.getItem(this.DID_CONSUME_TOKEN) + getInitialParams = async () => { + const token = await this.responseToken + const parsedToken = Boolean(token) + + if (parsedToken) { + return + } + + if (!parsedToken) { + await this.getSessionCode() + await this.setFlagToken() - didConsumeToken ? this.initWithoutCode() : await this.initCode() + return [this.SESSION_CODE, this.sessionCode] + } } - initWithoutCode = () => (this.state.consumedToken = true) + getSessionCode = async () => { + if (this.sessionCode) { + return this.sessionCode + } + + const {session_code} = await this.client.stackClient.fetchSessionCode() - initCode = async () => { - const sessionCode = await this.client.getSessionCode() - this.state.sessionCode = sessionCode + this.sessionCode = session_code } - wrapUrl = (url) => { - const {href} = new URL(url).append( - this.SESSION_CODE, - this.state.sessionCode, - ) + wrapUrl = async urlArg => { + const url = new URL(urlArg) + const params = new URLSearchParams(url.search) + const {session_code} = await this.client.stackClient.fetchSessionCode() + + params.append(this.SESSION_CODE, await session_code) + + url.search = params - return href + return url } - interceptLogin = async (request) => { - if (this.state.consumedToken) { + interceptLogin = async (request, setUri) => { + const url = new URL(request.url) + const {pathname, search} = url + + if (pathname !== this.IS_REDIRECT) { return true } - if (request?.url.includes(this.LOGIN)) { - await this.initCode() - // const wrappedUrl = this.wrapUrl(request.url) Do a redirect with the wrappedUrl - await this.consumeToken() + const redirect = new URLSearchParams(search).get('redirect') + const wrappedUrl = await this.wrapUrl(redirect) + + await this.setFlagToken() + + setUri(wrappedUrl) + + return false + } + + getFlagToken = async () => { + try { + const token = await AsyncStorage.getItem(this.FLAG_TOKEN) + return token + } catch (error) { return false } - - return true } - consumeToken = () => AsyncStorage.setItem(this.DID_CONSUME_TOKEN, 'true') + setFlagToken = () => AsyncStorage.setItem(this.FLAG_TOKEN, '1') - onLogout = () => AsyncStorage.removeItem(this.DID_CONSUME_TOKEN) + unsetFlagToken = () => AsyncStorage.setItem(this.FLAG_TOKEN, '') } const SessionContext = React.createContext(undefined) @@ -63,22 +88,20 @@ const SessionContext = React.createContext(undefined) export const useSession = () => useContext(SessionContext) export const SessionProvider = ({children}) => { - const [sessionService, createSessionService] = useState() + const [sessionService, setSessionService] = useState() const client = useClient() useEffect(() => { if (!sessionService) { - createSessionService(new SessionService(client)) - } - - if (sessionService) { - sessionService.init() + setSessionService(new SessionService(client)) } - }, [sessionService, client]) + }, [client, sessionService]) - return ( + return sessionService ? ( {children} + ) : ( + children ) } diff --git a/src/screens/connectors/HomeView.js b/src/screens/connectors/HomeView.js index d6c5392f8..41f3d30d2 100644 --- a/src/screens/connectors/HomeView.js +++ b/src/screens/connectors/HomeView.js @@ -4,6 +4,8 @@ import {useClient, Q, generateWebLink} from 'cozy-client' import {useNativeIntent} from 'cozy-intent' import CozyWebView from '../CozyWebView' +import {useSession} from '../../libs/services/SessionService' +import {URLSearchParams} from 'react-native-url-polyfill' const HomeView = ({route, navigation, setLauncherContext}) => { const client = useClient() @@ -11,23 +13,13 @@ const HomeView = ({route, navigation, setLauncherContext}) => { const [run, setRun] = useState('') const [ref, setRef] = useState('') const nativeIntent = useNativeIntent() + const session = useSession() useEffect(() => { if (ref && route.name === 'home') { nativeIntent.registerWebview(ref) } - const getHomeUri = async () => { - setUri( - generateWebLink({ - cozyUrl: client.getStackClient().uri, - pathname: '/', - slug: 'home', - subDomainType: await getSubDomainType(), - }), - ) - } - const getSubDomainType = async () => { try { const { @@ -66,10 +58,29 @@ const HomeView = ({route, navigation, setLauncherContext}) => { return true; `) - if (!uri) { + const getHomeUri = async () => { + const sessionSearchParams = await session.getInitialParams() + + const baseUri = new URL( + generateWebLink({ + cozyUrl: client.getStackClient().uri, + pathname: '/', + slug: 'home', + subDomainType: await getSubDomainType(), + }), + ) + + const params = new URLSearchParams(baseUri.search) + + params.append(...sessionSearchParams) + + setUri(`${baseUri.toString().replace('#/', '')}?${params.toString()}`) + } + + if (!uri && !run && session) { getHomeUri() } - }, [uri, client, run, route, nativeIntent, ref, navigation]) + }, [uri, client, run, route, nativeIntent, ref, navigation, session]) return uri ? ( { + const session = useSession() + const [uri, setUri] = useState() + const run = ` window.cozy = { isFlagshipApp: true @@ -12,10 +16,13 @@ export const CozyAppView = ({route}) => { return ( { + await session.interceptLogin(request, setUri) + }} /> ) } diff --git a/yarn.lock b/yarn.lock index c3b579441..053314b9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6403,10 +6403,10 @@ cozy-client-js@^0.20.0: pouchdb-browser "7.0.0" pouchdb-find "7.0.0" -cozy-client@^27.8.0: - version "27.8.0" - resolved "https://registry.yarnpkg.com/cozy-client/-/cozy-client-27.8.0.tgz#08cbd8e778a3a721732b6e42b88d10775c0dd067" - integrity sha512-ZzdGJo4Jnjtf3v3mON5JjXpO+Qu+aKy1ePxyP037lktWq7N/eYvv3EMOgSbYztEbtnd9euIggEYgwN+sj2FhGg== +cozy-client@^27.12.0: + version "27.12.0" + resolved "https://registry.yarnpkg.com/cozy-client/-/cozy-client-27.12.0.tgz#b3f5753f267744172c475e81a0fb12b93a149cf0" + integrity sha512-FbxmUSEW9n235VD4MMOaCHG451YDecSXSwviCs8NuHL4h59kYsLxJbP58QCtc0vA9r+CdkyniUcgZohaFtumOA== dependencies: "@cozy/minilog" "1.0.0" "@types/jest" "^26.0.20" @@ -6415,7 +6415,7 @@ cozy-client@^27.8.0: cozy-device-helper "^1.12.0" cozy-flags "2.7.1" cozy-logger "^1.6.0" - cozy-stack-client "^27.6.5" + cozy-stack-client "^27.9.0" json-stable-stringify "^1.0.1" lodash "^4.17.13" microee "^0.0.6" @@ -6472,10 +6472,10 @@ cozy-logger@^1.6.0: chalk "^2.4.2" json-stringify-safe "5.0.1" -cozy-stack-client@^27.6.5: - version "27.6.5" - resolved "https://registry.yarnpkg.com/cozy-stack-client/-/cozy-stack-client-27.6.5.tgz#4b40ad59821b957f161a77132b5346e99be0bc2c" - integrity sha512-aGkchVfvVGfI38qt+R8/BKv8nFN6Ihhx1LFsDYDtV+mW6OxOqVYdd22sIg9iHkusaqJgxgkMYnB9NcnDlC8Ajg== +cozy-stack-client@^27.9.0: + version "27.9.0" + resolved "https://registry.yarnpkg.com/cozy-stack-client/-/cozy-stack-client-27.9.0.tgz#f73f41699218ffbc1eb8116aea2bcb97248d98e3" + integrity sha512-6wuk91Pt7PhmkENgyDAYXYDJlNMuWtsluhoZHQKJplF7tbWfuQPdWZq2OFwOUB7xzhwhmjcsF4JlRUlEqKVtJA== dependencies: cozy-flags "2.7.1" detect-node "^2.0.4"