Skip to content

Commit

Permalink
WIP: Refactor auth
Browse files Browse the repository at this point in the history
  • Loading branch information
dmsnell committed May 7, 2020
1 parent 2477939 commit eb92efe
Show file tree
Hide file tree
Showing 24 changed files with 418 additions and 493 deletions.
80 changes: 14 additions & 66 deletions lib/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ import { connect } from 'react-redux';
import 'focus-visible/dist/focus-visible.js';
import appState from './flux/app-state';
import { loadTags } from './state/domain/tags';
import reduxActions from './state/actions';
import selectors from './state/selectors';
import browserShell from './browser-shell';
import NoteInfo from './note-info';
import NavigationBar from './navigation-bar';
import AppLayout from './app-layout';
import Auth from './auth';
import DevBadge from './components/dev-badge';
import DialogRenderer from './dialog-renderer';
import { getIpcRenderer } from './utils/electron';
Expand Down Expand Up @@ -42,11 +39,6 @@ export type OwnProps = {
noteBucket: object;
};

export type StateProps = S.State & {
authIsPending: boolean;
isAuthorized: boolean;
};

export type DispatchProps = {
createNote: () => any;
closeNote: () => any;
Expand All @@ -56,13 +48,9 @@ export type DispatchProps = {
trashNote: (previousIndex: number) => any;
};

export type Props = OwnProps & StateProps & DispatchProps;
export type Props = OwnProps & DispatchProps;

const mapStateToProps: S.MapState<StateProps> = (state) => ({
...state,
authIsPending: selectors.auth.authIsPending(state),
isAuthorized: selectors.auth.isAuthorized(state),
});
const mapStateToProps: S.MapState<S.State> = (state) => state;

const mapDispatchToProps: S.MapDispatch<
DispatchProps,
Expand Down Expand Up @@ -106,9 +94,7 @@ const mapDispatchToProps: S.MapDispatch<
toggleSortTagsAlpha: thenReloadTags(settingsActions.toggleSortTagsAlpha),
createNote: () => dispatch(createNote()),
openTagList: () => dispatch(toggleNavigation()),
resetAuth: () => dispatch(reduxActions.auth.reset()),
selectNote: (note: T.NoteEntity) => dispatch(actions.ui.selectNote(note)),
setAuthorized: () => dispatch(reduxActions.auth.setAuthorized()),
focusSearchField: () => dispatch(actions.ui.focusSearchField()),
setSimperiumConnectionStatus: (connected) =>
dispatch(toggleSimperiumConnectionStatus(connected)),
Expand All @@ -129,31 +115,17 @@ export const App = connect(
static propTypes = {
actions: PropTypes.object.isRequired,
appState: PropTypes.object.isRequired,
authIsPending: PropTypes.bool.isRequired,
authorizeUserWithToken: PropTypes.func.isRequired,
client: PropTypes.object.isRequired,
isAuthorized: PropTypes.bool.isRequired,
isDevConfig: PropTypes.bool.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
loadTags: PropTypes.func.isRequired,
onAuthenticate: PropTypes.func.isRequired,
onCreateUser: PropTypes.func.isRequired,
openTagList: PropTypes.func.isRequired,
onSignOut: PropTypes.func.isRequired,
settings: PropTypes.object.isRequired,
preferencesBucket: PropTypes.object.isRequired,
resetAuth: PropTypes.func.isRequired,
setAuthorized: PropTypes.func.isRequired,
systemTheme: PropTypes.string.isRequired,
tagBucket: PropTypes.object.isRequired,
};

static defaultProps = {
onAuthenticate: () => {},
onCreateUser: () => {},
onSignOut: () => {},
};

UNSAFE_componentWillMount() {
if (isElectron) {
this.initializeElectron();
Expand Down Expand Up @@ -341,21 +313,9 @@ export const App = connect(

onAuthChanged = () => {
const {
actions,
appState: { accountName },
client,
resetAuth,
setAuthorized,
} = this.props;

actions.authChanged();

if (!client.isAuthorized()) {
this.props.closeNote();
return resetAuth();
}

setAuthorized();
analytics.initialize(accountName);
this.onLoadPreferences();

Expand Down Expand Up @@ -487,8 +447,6 @@ export const App = connect(
render() {
const {
appState: state,
authIsPending,
isAuthorized,
isDevConfig,
noteBucket,
preferencesBucket,
Expand All @@ -515,29 +473,19 @@ export const App = connect(
return (
<div className={appClasses}>
{isDevConfig && <DevBadge />}
{isAuthorized ? (
<div className={mainClasses}>
{showNavigation && <NavigationBar />}
<AppLayout
isFocusMode={settings.focusModeEnabled}
isNavigationOpen={showNavigation}
isNoteInfoOpen={showNoteInfo}
isSmallScreen={isSmallScreen}
noteBucket={noteBucket}
onUpdateContent={this.onUpdateContent}
syncNote={this.syncNote}
/>
{showNoteInfo && <NoteInfo noteBucket={noteBucket} />}
</div>
) : (
<Auth
authPending={authIsPending}
isAuthenticated={isAuthorized}
onAuthenticate={this.props.onAuthenticate}
onCreateUser={this.props.onCreateUser}
authorizeUserWithToken={this.props.authorizeUserWithToken}
<div className={mainClasses}>
{showNavigation && <NavigationBar />}
<AppLayout
isFocusMode={settings.focusModeEnabled}
isNavigationOpen={showNavigation}
isNoteInfoOpen={showNoteInfo}
isSmallScreen={isSmallScreen}
noteBucket={noteBucket}
onUpdateContent={this.onUpdateContent}
syncNote={this.syncNote}
/>
)}
{showNoteInfo && <NoteInfo noteBucket={noteBucket} />}
</div>
<DialogRenderer
appProps={this.props}
buckets={{ noteBucket, preferencesBucket, tagBucket }}
Expand Down
51 changes: 15 additions & 36 deletions lib/auth/index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import classNames from 'classnames';
import cryptoRandomString from '../utils/crypto-random-string';
import { get } from 'lodash';
import getConfig from '../../get-config';
import SimplenoteLogo from '../icons/simplenote';
import Spinner from '../components/spinner';

import { hasInvalidCredentials, hasLoginError } from '../state/auth/selectors';
import { isElectron, isMac } from '../utils/platform';
import { reset } from '../state/auth/actions';
import { setWPToken } from '../state/settings/actions';
import { viewExternalUrl } from '../utils/url-utils';

export class Auth extends Component {
static propTypes = {
authorizeUserWithToken: PropTypes.func.isRequired,
authPending: PropTypes.bool,
hasInvalidCredentials: PropTypes.bool,
hasLoginError: PropTypes.bool,
isAuthenticated: PropTypes.bool,
onAuthenticate: PropTypes.func.isRequired,
onCreateUser: PropTypes.func.isRequired,
resetErrors: PropTypes.func.isRequired,
saveWPToken: PropTypes.func.isRequired,
};
type OwnProps = {
authPending: boolean;
hasInvalidCredentials: boolean;
hasLoginError: boolean;
login: (username: string, password: string) => any;
signup: (username: string, password: string) => any;
tokenLogin: (username: string, token: string) => any;
resetErrors: () => any;
};

type Props = OwnProps;

export class Auth extends Component<Props> {
state = {
isCreatingAccount: false,
passwordErrorMessage: null,
Expand Down Expand Up @@ -207,7 +202,7 @@ export class Auth extends Component {
return;
}

this.props.onAuthenticate(username, password);
this.props.login(username, password);
};

onWPLogin = () => {
Expand Down Expand Up @@ -283,11 +278,7 @@ export class Auth extends Component {
return;
}

const { authorizeUserWithToken, saveWPToken } = this.props;
authorizeUserWithToken(userEmail, simpToken);
if (wpccToken) {
saveWPToken(wpccToken);
}
this.props.tokenLogin(userEmail, simpToken);
}
);
};
Expand Down Expand Up @@ -331,7 +322,7 @@ export class Auth extends Component {
return;
}

this.props.onCreateUser(username, password);
this.props.signup(username, password, true);
this.setState({ passwordErrorMessage: null });
};

Expand All @@ -344,15 +335,3 @@ export class Auth extends Component {
this.setState({ isCreatingAccount: !this.state.isCreatingAccount });
};
}

const mapDispatchToProps = (dispatch) => ({
resetErrors: () => dispatch(reset()),
saveWPToken: (token) => dispatch(setWPToken(token)),
});

const mapStateToProps = (state) => ({
hasInvalidCredentials: hasInvalidCredentials(state),
hasLoginError: hasLoginError(state),
});

export default connect(mapStateToProps, mapDispatchToProps)(Auth);
97 changes: 97 additions & 0 deletions lib/boot-with-auth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
if (__TEST__) {
window.testEvents = [];
}

import 'core-js/stable';
import 'regenerator-runtime/runtime';
import 'unorm';

import React from 'react';
import App from './app';
import Modal from 'react-modal';
import Debug from 'debug';
import { initClient } from './client';
import getConfig from '../get-config';
import { makeStore } from './state';
import actions from './state/actions';
import { initSimperium } from './state/simperium/middleware';
import { render } from 'react-dom';
import { Provider } from 'react-redux';

import '../scss/style.scss';

import isDevConfig from './utils/is-dev-config';
import { normalizeForSorting } from './utils/note-utils';

import * as T from './types';

const config = getConfig();
const appID = config.app_id;

export const bootWithToken = (
logout: () => any,
token: string,
username: string | null,
createWelcomeNote: boolean
) => {
const client = initClient({
appID,
token,
bucketConfig: {
note: {
beforeIndex: function (note: T.NoteEntity) {
var content = (note.data && note.data.content) || '';

return {
...note,
contentKey: normalizeForSorting(content),
};
},
configure: function (objectStore) {
objectStore.createIndex('modificationDate', 'data.modificationDate');
objectStore.createIndex('creationDate', 'data.creationDate');
objectStore.createIndex('alphabetical', 'contentKey');
},
},
preferences: function (objectStore) {
console.log('Configure preferences', objectStore); // eslint-disable-line no-console
},
tag: function (objectStore) {
console.log('Configure tag', objectStore); // eslint-disable-line no-console
},
},
database: 'simplenote',
version: 42,
});

const debug = Debug('client');
const l = (msg: string) => (...args: unknown[]) => debug(msg, ...args);

client
.on('connect', l('Connected'))
.on('disconnect', l('Not connected'))
.on('message', l('<='))
.on('send', l('=>'))
.on('unauthorized', l('Not authorized'));

Modal.setAppElement('#root');

const store = makeStore(
initSimperium(logout, token, username, createWelcomeNote, client)
);

store.dispatch(actions.settings.setAccountName(username));

render(
<Provider store={store}>
<App
client={client}
noteBucket={client.bucket('note')}
preferencesBucket={client.bucket('preferences')}
tagBucket={client.bucket('tag')}
isDevConfig={isDevConfig(config?.development)}
/>
</Provider>,
document.getElementById('root')
);
};
Loading

0 comments on commit eb92efe

Please sign in to comment.