Skip to content
This repository was archived by the owner on Jan 7, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions email_app/app/actions/actionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const ACTION_TYPES = {
REFRESH_EMAIL: 'REFRESH_EMAIL',
SET_INITIALIZER_TASK: 'SET_INITIALIZER_TASK',
STORE_NEW_ACCOUNT: 'STORE_NEW_ACCOUNT',
NET_STATUS_CHANGED: 'NET_STATUS_CHANGED',
RECONNECT_APP: 'RECONNECT_APP',

// Create Account
CREATE_ACCOUNT: 'CREATE_ACCOUNT',
Expand Down
25 changes: 22 additions & 3 deletions email_app/app/actions/initializer_actions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ACTION_TYPES from './actionTypes';
import { authApp, connect, readConfig, writeConfig,
import { authApp, connect, reconnect, readConfig, writeConfig,
readInboxEmails, readArchivedEmails } from '../safenet_comm';

export const setInitializerTask = (task) => ({
Expand All @@ -14,11 +14,20 @@ export const onAuthFailure = (err) => {
};
};

const newNetStatusCallback = (dispatch) => {
return function (state) {
dispatch({
type: ACTION_TYPES.NET_STATUS_CHANGED,
payload: state
});
}
};

export const receiveResponse = (uri) => {
return function (dispatch) {
return dispatch({
type: ACTION_TYPES.AUTHORISE_APP,
payload: connect(uri)
payload: connect(uri, newNetStatusCallback(dispatch))
});
};
};
Expand All @@ -28,7 +37,7 @@ export const authoriseApplication = () => {
return dispatch({
type: ACTION_TYPES.AUTHORISE_APP,
payload: new Promise((resolve, reject) => {
authApp()
authApp(newNetStatusCallback(dispatch))
.then(resolve)
.catch(reject);
})
Expand All @@ -37,6 +46,16 @@ export const authoriseApplication = () => {
};
};

export const reconnectApplication = () => {
return function (dispatch, getState) {
let app = getState().initializer.app;
return dispatch({
type: ACTION_TYPES.RECONNECT_APP,
payload: reconnect(app)
});
};
};

export const refreshConfig = () => {
return function (dispatch, getState) {
let app = getState().initializer.app;
Expand Down
4 changes: 2 additions & 2 deletions email_app/app/components/create_account.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { MESSAGES, CONSTANTS } from '../constants';
import { MESSAGES, CONSTANTS, SAFE_APP_ERROR_CODES } from '../constants';

export default class CreateAccount extends Component {
constructor() {
Expand Down Expand Up @@ -32,7 +32,7 @@ export default class CreateAccount extends Component {
return createAccount(emailId)
.then(this.storeCreatedAccount)
.catch((err) => {
if (err.code === -104) {
if (err.code === SAFE_APP_ERROR_CODES.ERR_DATA_EXISTS) {
return createAccountError(new Error(MESSAGES.EMAIL_ALREADY_TAKEN));
}
return createAccountError(err);
Expand Down
46 changes: 45 additions & 1 deletion email_app/app/components/home.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,59 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link, IndexLink } from 'react-router';
import Modal from 'react-modal';
import className from 'classnames';
import pkg from '../../package.json';
import { CONSTANTS } from '../constants';

const modalStyles = {
content : {
top : '50%',
left : '50%',
right : 'auto',
bottom : 'auto',
marginRight : '-50%',
transform : 'translate(-50%, -50%)'
}
};

export default class Home extends Component {
constructor() {
super();
this.state = {
reconnecting: false
};

this.reconnect = this.reconnect.bind(this);
}

reconnect() {
this.setState({reconnecting: true});
return this.props.reconnectApplication()
.then(() => this.setState({reconnecting: false}));
}

render() {
const { router } = this.context;
const { coreData, inboxSize, savedSize } = this.props;
const { coreData, inboxSize, savedSize, network_status } = this.props;

const isNetworkDisconnected = (network_status !== CONSTANTS.NET_STATUS_CONNECTED);

return (
<div className="home">
<Modal
isOpen={isNetworkDisconnected}
shouldCloseOnOverlayClick={false}
style={modalStyles}
contentLabel="Network connection lost"
>
<div className="text-center">
<div>The application hast lost network connection.</div><br />
<div>Make sure the network link is up before trying to reconnect.</div><br />
<button disabled={this.state.reconnecting} className="mdl-button mdl-js-button bg-primary" onClick={this.reconnect}>Reconnect</button>
</div>
</Modal>

<div className="home-b">
<div className={className('float-btn', { hide: router.isActive('/compose_mail') })}>
<button className="mdl-button mdl-js-button mdl-button--fab mdl-button--primary">
Expand Down
15 changes: 10 additions & 5 deletions email_app/app/components/initializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import { remote } from 'electron';
import { showError } from '../utils/app_utils';
import { MESSAGES, APP_STATUS } from '../constants';

const showAuthError = _ => showError('Authorisation failed',
MESSAGES.AUTHORISATION_ERROR,
_ => { remote.getCurrentWindow().close(); });
const showAuthError = (app_status) => {
let message = MESSAGES.AUTHORISATION_ERROR;
if (app_status === APP_STATUS.AUTHORISATION_DENIED) {
message = MESSAGES.AUTHORISATION_DENIED;
}
showError('Authorisation failed', message, _ => { remote.getCurrentWindow().close(); });
};

export default class Initializer extends Component {
constructor() {
Expand Down Expand Up @@ -40,8 +44,9 @@ export default class Initializer extends Component {
componentDidUpdate(prevProps, prevState) {
const { app_status, app } = this.props;
if (prevProps.app_status === APP_STATUS.AUTHORISING
&& app_status === APP_STATUS.AUTHORISATION_FAILED) {
showAuthError();
&& (app_status === APP_STATUS.AUTHORISATION_DENIED
|| app_status === APP_STATUS.AUTHORISATION_FAILED) ) {
showAuthError(app_status);
} else if (app && app_status === APP_STATUS.AUTHORISED) {
return this.refreshConfig();
}
Expand Down
12 changes: 11 additions & 1 deletion email_app/app/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,26 @@ export const CONSTANTS = {
SAVED: 'SAVED'
},
MAIL_CONTENT_LIMIT: 150,
DATE_FORMAT: 'h:MM-mmm dd'
DATE_FORMAT: 'h:MM-mmm dd',
NET_STATUS_CONNECTED: 'Connected'
};

export const APP_STATUS = {
AUTHORISING: 'AUTHORISING',
AUTHORISATION_FAILED: 'AUTHORISATION_FAILED',
AUTHORISATION_DENIED: 'AUTHORISATION_DENIED',
AUTHORISED: 'AUTHORISED',
READING_CONFIG: 'READING_CONFIG',
READY: 'READY'
}

export const SAFE_APP_ERROR_CODES = {
ERR_AUTH_DENIED: -200,
ERR_NO_SUCH_ENTRY: -106,
ERR_DATA_EXISTS: -104,
ERR_OPERATION_ABORTED: -14
}

export const MESSAGES = {
INITIALIZE: {
AUTHORISE_APP: 'Authorising Application',
Expand All @@ -39,5 +48,6 @@ export const MESSAGES = {
EMAIL_ID_TOO_LONG: 'Email ID is too long',
EMAIL_ID_NOT_FOUND: 'Email ID not found on the network',
AUTHORISATION_ERROR: 'Failed to authorise',
AUTHORISATION_DENIED: 'The authorisation request was denied',
CHECK_CONFIGURATION_ERROR: 'Failed to retrieve configuration'
};
5 changes: 4 additions & 1 deletion email_app/app/containers/home_container.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { connect } from 'react-redux';
import Home from '../components/home';
import { reconnectApplication } from '../actions/initializer_actions';

const mapStateToProps = state => {
return {
coreData: state.initializer.coreData,
inboxSize: state.initializer.inboxSize,
savedSize: state.initializer.savedSize
savedSize: state.initializer.savedSize,
network_status: state.initializer.network_status
};
};

const mapDispatchToProps = dispatch => {
return {
reconnectApplication: () => (dispatch(reconnectApplication())),
};
};

Expand Down
21 changes: 18 additions & 3 deletions email_app/app/reducers/initialiser.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import ACTION_TYPES from '../actions/actionTypes';
import { MESSAGES, APP_STATUS } from '../constants';
import { MESSAGES, APP_STATUS, CONSTANTS, SAFE_APP_ERROR_CODES } from '../constants';

const initialState = {
app_status: null,
network_status: null,
app: null,
tasks: [],
accounts: [],
Expand All @@ -27,10 +28,24 @@ const initializer = (state = initialState, action) => {
return { ...state, app: null, app_status: APP_STATUS.AUTHORISING };
break;
case `${ACTION_TYPES.AUTHORISE_APP}_SUCCESS`:
return { ...state, app: action.payload, app_status: APP_STATUS.AUTHORISED };
return { ...state,
app: action.payload,
app_status: APP_STATUS.AUTHORISED,
network_status: CONSTANTS.NET_STATUS_CONNECTED
};
break;
case `${ACTION_TYPES.AUTHORISE_APP}_ERROR`:
return { ...state, app_status: APP_STATUS.AUTHORISATION_FAILED };
status = APP_STATUS.AUTHORISATION_FAILED;
if (action.payload.code === SAFE_APP_ERROR_CODES.ERR_AUTH_DENIED) {
status = APP_STATUS.AUTHORISATION_DENIED;
}
return { ...state, app_status: status };
break;
case ACTION_TYPES.NET_STATUS_CHANGED:
return { ...state, network_status: action.payload };
break;
case `${ACTION_TYPES.RECONNECT_APP}_SUCCESS`:
return { ...state, network_status: CONSTANTS.NET_STATUS_CONNECTED };
break;
case `${ACTION_TYPES.GET_CONFIG}_LOADING`:
return { ...state, app_status: APP_STATUS.READING_CONFIG };
Expand Down
16 changes: 10 additions & 6 deletions email_app/app/safenet_comm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { shell } from 'electron';
import { CONSTANTS, MESSAGES } from './constants';
import { CONSTANTS, MESSAGES, SAFE_APP_ERROR_CODES } from './constants';
import { initializeApp, fromAuthURI } from 'safe-app';
import { getAuthData, saveAuthData, clearAuthData, hashPublicId, genRandomEntryKey,
genKeyPair, encrypt, decrypt, genServiceInfo, deserialiseArray, parseUrl } from './utils/app_utils';
Expand Down Expand Up @@ -33,15 +33,15 @@ const requestAuth = () => {
);
}

export const authApp = () => {
export const authApp = (netStatusCallback) => {
if (process.env.SAFE_FAKE_AUTH) {
return initializeApp(APP_INFO.info)
.then((app) => app.auth.loginForTest(APP_INFO.permissions));
}

let uri = getAuthData();
if (uri) {
return fromAuthURI(APP_INFO.info, uri)
return fromAuthURI(APP_INFO.info, uri, netStatusCallback)
.then((registered_app) => registered_app.auth.refreshContainersPermissions()
.then(() => registered_app)
)
Expand All @@ -55,15 +55,19 @@ export const authApp = () => {
return requestAuth();
}

export const connect = (uri) => {
export const connect = (uri, netStatusCallback) => {
let registered_app;
return fromAuthURI(APP_INFO.info, uri)
return fromAuthURI(APP_INFO.info, uri, netStatusCallback)
.then((app) => registered_app = app)
.then(() => saveAuthData(uri))
.then(() => registered_app.auth.refreshContainersPermissions())
.then(() => registered_app);
}

export const reconnect = (app) => {
return app.reconnect();
}

export const readConfig = (app) => {
let account = {};
return app.auth.getHomeContainer()
Expand Down Expand Up @@ -195,7 +199,7 @@ export const setupAccount = (app, emailId) => {
.then((pub_names_md) => pub_names_md.encryptKey(serviceInfo.publicId).then((key) => pub_names_md.get(key))
.then((services) => addEmailService(app, serviceInfo, inbox_serialised)
, (err) => {
if (err.code === -106) {
if (err.code === SAFE_APP_ERROR_CODES.ERR_NO_SUCH_ENTRY) {
return createPublicIdAndEmailService(app, pub_names_md,
serviceInfo, inbox_serialised);
}
Expand Down
1 change: 1 addition & 0 deletions email_app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-hot-loader": "^3.0.0-beta.6",
"react-modal": "^2.1.0",
"react-redux": "^5.0.3",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
Expand Down