Skip to content

Commit

Permalink
fix: fix syncing issue on login
Browse files Browse the repository at this point in the history
  • Loading branch information
jbcl-io committed Apr 15, 2021
1 parent efa4f63 commit 40da5d4
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 290 deletions.
36 changes: 11 additions & 25 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { createMuiTheme, LinearProgress, ThemeProvider } from '@material-ui/core';
import { createStore, StoreProvider } from 'easy-peasy';
import { lazy, Suspense, useEffect } from 'react';
import { lazy, memo, Suspense, useEffect } from 'react';
import ApplicationStore from './store';
import { Route, Switch, useLocation, useRoute } from 'wouter';
import { useStoreActions, useStoreState } from './store/typedHooks';
import { useStoreActions } from './store/typedHooks';
import { THEME } from './config/theme';
import loadAppSettings from './services/loadAppSettings';
import useLoading from './hooks/useLoading';

const Login = lazy(() => import('./pages/Login'));
const Signup = lazy(() => import('./pages/Signup'));
Expand All @@ -15,39 +14,26 @@ const MainApp = lazy(() => import('./pages/MainApp'));
const store = createStore(ApplicationStore);
const theme = createMuiTheme(THEME);

export const AppStarter = ({ children }: any) => {
const [isLoading, , , setIsLoading] = useLoading(true);
export const AppStarter = memo(({ children }: any) => {
const [, setLocation] = useLocation();

const [isRoot] = useRoute('/');

const appSettings = useStoreState((s) => s.appSettings);
const setAppSettings = useStoreActions((a) => a.setAppSettings);

useEffect(() => {}, []);

useEffect(() => {
if (!appSettings) {
(async () => {
setAppSettings(await loadAppSettings());
(async () => {
setAppSettings(await loadAppSettings());
})();

if (isRoot) {
setLocation('/login');
}

setIsLoading(false);
})();
if (isRoot) {
setLocation('/login');
return;
}

// eslint-disable-next-line
}, []);

if (isLoading) {
return <LinearProgress />;
} else {
return children;
}
};
return children;
});

const App = () => {
return (
Expand Down
112 changes: 112 additions & 0 deletions src/hooks/useCloudSyncLogin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import useLoading, { ErrorOrNull } from './useLoading';
import generateTokenFromPassword from '../utils/generateTokenFromPassword';
import getNewSessionFromCloudSync from '../api/cloudSync/getNewSession';
import getAccountFromCloudSync from '../api/cloudSync/getAccount';
import decryptAndSaveUserFromBase64 from '../services/decryptAndSaveUserFromBase64';
import saveFileCollectionFromBase64 from '../services/saveFileCollectionFromBase64';
import { useStoreActions } from '../store/typedHooks';
import loadUserFromDisk from '../services/loadUserFromDisk';
import syncAccountAndNotesToCloudSync from '../services/syncAccountAndNotesToCloudSync';

type LoginPayload = {
username: string;
password: string;
};

const useCloudSyncLogin = (): {
start: (payload: LoginPayload) => Promise<void>;
isLoading: boolean;
error: ErrorOrNull;
isComplete: boolean;
reset: () => void;
} => {
const [isLoading, error, isComplete, setIsLoading, setError, setIsComplete, reset] = useLoading();

const setUser = useStoreActions((a) => a.setUser);
const setPasswordKey = useStoreActions((a) => a.setPasswordKey);
const setCloudSyncPasswordKey = useStoreActions((a) => a.setCloudSyncPasswordKey);
const setFileCollection = useStoreActions((a) => a.setFileCollection);

const startLogin = async ({ username, password }: LoginPayload) => {
setIsLoading(true);

// Verify account and get sessionToken
const token = await generateTokenFromPassword(password, username);

const session = await getNewSessionFromCloudSync({
username,
token,
});

if ('error' in session) {
switch (session.error) {
case 'user does not exist':
setError({ ...session, errorCode: 'no_user' });
break;
case 'token does not match':
setError({ ...session, errorCode: 'wrong_password' });
break;
default:
setError(session);
}

return;
}

const sessionToken = session.sessionToken;

// Fetch account, then save user and fileCollection to disk
const fetchAccount = await getAccountFromCloudSync({
username,
sessionToken,
});

if ('error' in fetchAccount) {
setError(fetchAccount);
return;
}

const saveUser = await decryptAndSaveUserFromBase64(username, password, fetchAccount.userItem);

if ('error' in saveUser) {
setError(saveUser);
return;
}

await saveFileCollectionFromBase64(saveUser.userItem, fetchAccount.fileCollection);

// Load user from disk
const loadUser = await loadUserFromDisk({ username, password });

if ('error' in loadUser) {
setError(loadUser);
return;
}

// Start full sync
const sync = await syncAccountAndNotesToCloudSync({
sessionToken,
user: loadUser.user,
fileCollection: loadUser.fileCollection,
fileCollectionNonce: loadUser.user.fileCollectionNonce,
passwordKey: loadUser.passwordKey,
cloudSyncPasswordKey: loadUser.cloudSyncPasswordKey,
});

if ('error' in sync) {
setError(sync);
return;
}

setUser(loadUser.user);
setPasswordKey(loadUser.passwordKey);
setCloudSyncPasswordKey(loadUser.cloudSyncPasswordKey);
setFileCollection(loadUser.fileCollection);

setIsComplete(true);
};

return { start: startLogin, isLoading, error, isComplete, reset };
};

export default useCloudSyncLogin;
4 changes: 2 additions & 2 deletions src/hooks/useFullSync.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import moment from 'moment';
import checkSessionFromCloudSync from '../api/cloudSync/checkSession';
import { runSyncAccountAndNotesToCloudSyncInWorker } from '../services/syncAccountAndNotesToCloudSync';
import syncAccountAndNotesToCloudSync from '../services/syncAccountAndNotesToCloudSync';
import { useStoreActions, useStoreState } from '../store/typedHooks';
import useLoading, { ErrorOrNull } from './useLoading';

Expand Down Expand Up @@ -56,7 +56,7 @@ const useFullSync = (): [() => Promise<void>, boolean, ErrorOrNull, boolean, ()
}

// start full sync
const sync = await runSyncAccountAndNotesToCloudSyncInWorker({
const sync = await syncAccountAndNotesToCloudSync({
sessionToken: cloudSyncSessionToken,
user,
fileCollection,
Expand Down
6 changes: 5 additions & 1 deletion src/hooks/useLoading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ const useLoading = (

const doSetIsComplete = (isComplete: boolean) => {
setIsComplete(isComplete);
if (isComplete) setIsLoading(false);

if (isComplete) {
setError(null);
setIsLoading(false);
}
};

const reset = () => {
Expand Down
Loading

0 comments on commit 40da5d4

Please sign in to comment.