Skip to content

Instantly share code, notes, and snippets.

@hoorayimhelping
Created March 25, 2016 22:01
Show Gist options
  • Select an option

  • Save hoorayimhelping/4e4bb2ee56ae80b3f154 to your computer and use it in GitHub Desktop.

Select an option

Save hoorayimhelping/4e4bb2ee56ae80b3f154 to your computer and use it in GitHub Desktop.
commit 53127abe61c94ae35e22ab79b28320ddb351abd5
Author: Bucky Schwarz <d.w.schwarz@gmail.com>
Date: Fri Mar 25 17:59:06 2016 -0400
Common Auth
diff --git a/package.json b/package.json
index 38942af..6714d4c 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,8 @@
"body-parser": "^1.15.0",
"classnames": "^2.2.0",
"console-polyfill": "^0.2.1",
- "cookie-parser": "^1.3.5",
+ "cookie-parser": "^1.4.1",
+ "cookie-session": "^2.0.0-alpha.1",
"debug": "^2.2.0",
"deepcopy": "^0.5.0",
"deepmerge": "^0.2.10",
@@ -39,8 +40,8 @@
"less": "^1.7.5",
"lodash": "^3.9.3",
"moment": "^2.10.3",
- "qh-common": "git+ssh://git@github.com:quartethealth/qh-common.git#v2.4.7",
"node-sass": "^3.4.2",
+ "qh-common": "git+ssh://git@github.com:quartethealth/qh-common.git#v2.5.1",
"react": "^0.13.3",
"react-redux": "3.1.0",
"react-router": "^0.13.3",
@@ -51,9 +52,6 @@
"reselect": "^2.0.1",
"sass-loader": "^3.1.2",
"serialize-javascript": "^1.0.0",
- "superagent": "^1.3.0",
- "superagent-promise": "^1.0.3",
- "url-join": "0.0.1",
"zipcodes": "^2.0.0"
},
"devDependencies": {
diff --git a/server.js b/server.js
index 3b15462..2fa111c 100644
--- a/server.js
+++ b/server.js
@@ -1,14 +1,20 @@
// Express and server libs
import express from 'express';
import path from 'path';
+import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
-import fs from 'fs';
+import cookieSession from 'cookie-session';
+import { API_ENDPOINT, COOKIE_SECRET } from 'qh-common/server/settings';
import proxy from 'qh-common/server/middleware/proxy';
-import { COLLAB_API_ENDPOINT } from './src/settings';
-
-// common
import { buildLogger, buildLogExpressMiddleware } from 'qh-common/server/utils';
+import {
+ apiLogin,
+ apiRegister,
+ apiLogout,
+ apiResetPassword,
+ apiRequestResetPassword
+} from 'qh-common/server/middleware';
const ANONYMOUS_ROUTE_REGEX = /login|reset-password|registration|forgot-password|match/i;
@@ -16,61 +22,52 @@ function isAnonymousPath (newPath) {
return ANONYMOUS_ROUTE_REGEX.test(newPath);
}
+const app = express();
+app.set('state namespace', 'App');
-const server = express();
-
-server.set('state namespace', 'App');
+app.use(cookieSession({ secret: COOKIE_SECRET }));
+app.use(cookieParser());
+app.use(bodyParser.urlencoded({ extended: true }));
+app.use(bodyParser.json({ extended: true }));
-server.use(cookieParser());
-server.use('/public', express.static(path.join(__dirname, '/public')));
-server.use(require('cookie-parser')());
-server.use(require('body-parser').urlencoded({ extended: true }));
-server.use(require('body-parser').json({ extended: true }));
+app.use('/public', express.static(path.join(__dirname, '/public')));
+app.get('/status', (req, res) => res.sendStatus(200));
-server.get('/status', (req, res) => res.sendStatus(200));
+export const isUserLoggedIn = (req) => req.session.userId ? true : false;
-//This function exists because the bff has access to the sessionid cookie
-//that the client does not. The only way to give the client access is by sending over http...
-//In general, it's probably benecifical to force the client to confirm validation with the server
-//instead of assuming.
-let isAuthenticated = req => (req.cookies && req.cookies.sessionid);
-server.get('/api/authenticated', (req, res) => {
- if (isAuthenticated(req)) {
- res.sendStatus(200);
- } else {
- res.sendStatus(401);
- }
+app.get('/authenticated', (req, res) => {
+ isUserLoggedIn(req) ? res.sendStatus(200) : res.sendStatus(401);
});
-//This proxies all api calls from the client to collab.
-server.use('/api/*', proxy(COLLAB_API_ENDPOINT));
+// Handle auth endpoints using common middleware
+app.post('/api/login', apiLogin);
+app.post('/api/register', apiRegister);
+app.delete('/api/logout', apiLogout);
+app.post('/api/reset-password', apiResetPassword);
+app.post('/api/request-reset-password', apiRequestResetPassword);
-const logger = buildLogger({
- appName: 'bhp-client'
-});
+// Handle all other requests using common proxy
+app.use('/api/*', proxy(API_ENDPOINT));
+const logger = buildLogger({appName: 'bhp-client'});
const logExpressMiddleware = buildLogExpressMiddleware(logger);
+app.post('/log', logExpressMiddleware);
-server.post('/log', logExpressMiddleware);
-
-server.get(/^(?!\/api)/, (req, res, next) => {
- if (!isAuthenticated(req) && !isAnonymousPath(req.path)) {
+app.use((req, res, next) => {
+ if (!isUserLoggedIn(req) && !isAnonymousPath(req.path)) {
res.redirect('/login?location=' + encodeURIComponent(req.url));
+ return;
+ }
- return next();
- } else {
- const INDEXFILE = path.join(__dirname, '/public/html/index.html');
- fs.readFile(INDEXFILE, (err, data) => {
- res.setHeader('Content-Type', 'text/html; charset=UTF-8');
- res.send(data);
+ next();
+});
- next();
- });
- }
-} );
+app.get('*', (req, res) => {
+ res.sendFile(path.join(__dirname, '/public/html/index.html'));
+});
const port = process.env.PORT || 3000;
-server.listen(port);
-console.log('Listening on port ' + port);
+app.listen(port);
+logger.info('Listening on port ' + port);
-export default server;
+export default app;
diff --git a/src/action_creators/auth.js b/src/action_creators/auth.js
index 5d1498a..d68769c 100644
--- a/src/action_creators/auth.js
+++ b/src/action_creators/auth.js
@@ -1,5 +1,4 @@
-import { COLLAB_API_URL } from '../settings';
-import { clientRequest } from 'qh-common/utils';
+import { clientRequest, Automaton } from 'qh-common/utils';
export const AUTH_REGISTER_REQUEST = 'AUTH_REGISTER_REQUEST';
export const AUTH_REGISTER_SUCCESS = 'AUTH_REGISTER_SUCCESS';
@@ -32,7 +31,7 @@ function validateAuthentication () {
});
let response = await clientRequest
- .get(`/api/authenticated`)
+ .get('/authenticated')
.end();
if (response && response.ok) {
@@ -42,6 +41,7 @@ function validateAuthentication () {
});
}
} catch (err) {
+ Automaton.logErrorObject(err);
dispatch({
type: AUTH_VALIDATE_AUTHENTICATION_SUCCESS,
isAuthenticated: false
@@ -50,18 +50,19 @@ function validateAuthentication () {
};
}
-
function register ({ name, password, email, phone, pt_id, pt_h }) {
return async (dispatch) => {
dispatch({
type: AUTH_REGISTER_REQUEST
});
let response = await clientRequest
- .post(`${COLLAB_API_URL}api/register`)
+ .post(`/api/register`)
.withCredentials()
.send({ name, password, email, phone, pt_id, pt_h, requesting_app: 'bhp' }) //eslint-disable-line camelcase
.end()
- .catch(() => {
+ .catch(err => {
+ Automaton.logErrorObject(err);
+
dispatch({
type: AUTH_REGISTER_ERROR,
message: 'Sorry, we were unable to register.'
@@ -83,10 +84,11 @@ function login ({ username, password }) {
});
let response = await clientRequest
- .post(`${COLLAB_API_URL}api/login`)
+ .post(`/api/login`)
.send({ username, password })
.end()
- .catch(() => {
+ .catch(err => {
+ Automaton.logErrorObject(err);
dispatch({
type: AUTH_LOGIN_ERROR,
message: 'Sorry, those credentials don\'t work.'
@@ -104,7 +106,7 @@ function login ({ username, password }) {
function logout () {
return async (dispatch) => {
let response = await clientRequest
- .del(`${COLLAB_API_URL}api/logout`)
+ .del(`/api/logout`)
.end();
if (response && response.ok) {
@@ -138,14 +140,16 @@ function resetPassword ({ password, confirmPassword, passwordResetToken, usernam
});
let response = await clientRequest
- .post(`${COLLAB_API_URL}api/reset-password`)
+ .post(`/api/reset-password`)
.send({
password,
password_reset_token:passwordResetToken,
username
})
.end()
- .catch(() => {
+ .catch(err => {
+ Automaton.logErrorObject(err);
+
dispatch({
type: AUTH_RESET_PASSWORD_ERROR,
message: 'Sorry, there was a problem. Please try again.'
@@ -167,12 +171,13 @@ function forgotPassword ({ email }) {
});
let response = await clientRequest
- .post(`${COLLAB_API_URL}api/request-reset-password`)
+ .post(`/api/request-reset-password`)
.send({
username: email
})
.end()
- .catch(() => {
+ .catch(err => {
+ Automaton.logErrorObject(err);
dispatch({
type: AUTH_FORGOT_PASSWORD_ERROR,
message: 'Sorry, there was a problem. Please try again.'
@@ -191,7 +196,7 @@ function createSession () {
return async (dispatch) => {
try {
let response = await clientRequest
- .get(`${COLLAB_API_URL}api/get-user-info`)
+ .get(`/api/get-user-info`)
.end();
if (response && response.ok) {
@@ -217,8 +222,7 @@ function createSession () {
});
}
} catch (err) {
- console.error(err);
- //There was an error with authentication. Transit to login.
+ Automaton.logErrorObject(err);
dispatch({ type: AUTH_LOGOUT_SUCCESS });
}
};
diff --git a/src/action_creators/consultNote.js b/src/action_creators/consultNote.js
index 427b1e4..815e23e 100644
--- a/src/action_creators/consultNote.js
+++ b/src/action_creators/consultNote.js
@@ -4,8 +4,7 @@ export const RECEIVE_APPT = 'RECEIVE_APPT';
export const ERROR_APPT = 'ERROR_APPT';
export const SUBMIT_APPT = 'SUBMIT_APPT';
export const FINISH_SUBMIT_APPT = 'FINISH_SUBMIT_APPT';
-import { COLLAB_API_URL } from '../settings';
-const FETCH_URL = COLLAB_API_URL + 'api/appointment/';
+const FETCH_URL = '/api/appointment/';
// Consult note Form submission
function requestSubmitAppointment(appointment) {
diff --git a/src/action_creators/register.js b/src/action_creators/register.js
index d27e672..50dc08f 100644
--- a/src/action_creators/register.js
+++ b/src/action_creators/register.js
@@ -1,4 +1,3 @@
-import { COLLAB_API_URL } from '../settings';
import { clientRequest } from 'qh-common/utils';
@@ -32,10 +31,10 @@ function submitRegistration ({ formValues, userId, providerId }) {
if (providerId) {
httpMethod = clientRequest.put;
- requestUrl = `${COLLAB_API_URL}api/provider/${providerId}`;
+ requestUrl = `/api/provider/${providerId}`;
} else {
httpMethod = clientRequest.post;
- requestUrl = `${COLLAB_API_URL}api/provider`;
+ requestUrl = `/api/provider`;
// When creating a provider for the first time, specify user to link to
requestData.user = userId;
@@ -69,7 +68,7 @@ function updateSlideIndex (slideIndex) {
function fetchRegData () {
return async (dispatch) => {
let response = await clientRequest
- .get(`${COLLAB_API_URL}api/get-user-info`)
+ .get(`/api/get-user-info`)
.end()
.catch((err) => {
console.error(err);
@@ -93,7 +92,7 @@ function fetchRegData () {
function fetchTreatmentApproaches () {
return async (dispatch) => {
let response = await clientRequest
- .get(`${COLLAB_API_URL}api/treatment-approaches`)
+ .get(`/api/treatment-approaches`)
.end();
if (response && response.ok) {
@@ -108,7 +107,7 @@ function fetchTreatmentApproaches () {
function fetchSpecialties () {
return async (dispatch) => {
let response = await clientRequest
- .get(`${COLLAB_API_URL}api/specialty?selectable=True`)
+ .get(`/api/specialty?selectable=True`)
.end();
if (response && response.ok) {
@@ -123,7 +122,7 @@ function fetchSpecialties () {
function fetchInsurancePlans () {
return async (dispatch) => {
let response = await clientRequest
- .get(`${COLLAB_API_URL}api/insuranceplan`)
+ .get(`/api/insuranceplan`)
.end();
if (response && response.ok) {
diff --git a/src/actions/ApplicationActions.js b/src/actions/ApplicationActions.js
index 57355bc..f06226a 100644
--- a/src/actions/ApplicationActions.js
+++ b/src/actions/ApplicationActions.js
@@ -1,7 +1,5 @@
'use strict';
import { clientRequest } from 'qh-common/utils';
-import urljoin from 'url-join';
-import { COLLAB_API_URL } from '../settings';
export default {
setCalendarDate(context, dateRange) {
@@ -10,7 +8,7 @@ export default {
createSession(context) {
clientRequest
- .get(urljoin(COLLAB_API_URL, 'api/get-user-info/'))
+ .get('/api/get-user-info/')
.set('Accept', 'application/json')
.end(function(err, res) {
if (err) {
diff --git a/src/actions/AppointmentActions.js b/src/actions/AppointmentActions.js
index bf76296..218f871 100644
--- a/src/actions/AppointmentActions.js
+++ b/src/actions/AppointmentActions.js
@@ -1,14 +1,13 @@
'use strict';
import { clientRequest } from 'qh-common/utils';
-import { COLLAB_API_URL } from '../settings';
-import urljoin from 'url-join'
+
export default {
setAppointmentAttendance(context, payload) {
let appointment = payload.appointment;
appointment.patient_attended = payload.attended;
clientRequest
- .patch(urljoin(COLLAB_API_URL, 'api/appointment/', appointment.id))
+ .patch(`/api/appointment/${appointment.id}`)
.set('Accept', 'application/json')
.send({ patient_attended: payload.attended })
.end(function(err, res){
@@ -26,7 +25,7 @@ export default {
loadAppointments(context) {
clientRequest
- .get(urljoin(COLLAB_API_URL, 'api/appointment/'))
+ .get('/api/appointment/')
.set('Accept', 'application/json')
.send()
.end(function(err, res){
@@ -45,7 +44,7 @@ export default {
addNewAppointment(context, payload, done) {
context.dispatch('CLOSE_RIGHT');
clientRequest
- .post(urljoin(COLLAB_API_URL, 'api/new-appointment/'))
+ .post('/api/new-appointment/')
.send(payload)
.end(function(err, res){
if (err) {
diff --git a/src/actions/ReferralActions.js b/src/actions/ReferralActions.js
index 105f270..c41c9c3 100644
--- a/src/actions/ReferralActions.js
+++ b/src/actions/ReferralActions.js
@@ -1,12 +1,10 @@
-import { COLLAB_API_URL } from '../settings';
-import urljoin from 'url-join';
import { clientRequest } from 'qh-common/utils';
import AppointmentActions from './AppointmentActions';
import { REFERRAL_STATUS_ACCEPT } from '../constants';
const loadReferrals = (context) => {
clientRequest
- .get(urljoin(COLLAB_API_URL) + 'api/referral')
+ .get('/api/referral')
.set('Accept', 'application/json')
.send()
.end(function (err, res) {
@@ -27,7 +25,7 @@ const updateReferralStatus = (context, referralData) => {
const referral_decline_feedback = referralData.declineReason;
const id = referralData.referral.id;
clientRequest
- .patch(urljoin(COLLAB_API_URL, 'api/referral/' + id))
+ .patch(`/api/referral/${id}`)
.set('Accept', 'application/json')
.send({ status, referral_decline_feedback })
.end(function (err) {
@@ -45,7 +43,7 @@ const updateReferralStatus = (context, referralData) => {
return;
}
clientRequest
- .post(urljoin(COLLAB_API_URL, 'api/new-appointment/'))
+ .post('/api/new-appointment/')
.set('Accept', 'application/json')
.send({
'source_referral_id': id,
diff --git a/src/app.js b/src/app.js
index cc817e0..3d1abd9 100644
--- a/src/app.js
+++ b/src/app.js
@@ -1,10 +1,8 @@
import Fluxible from 'fluxible';
-import { createStore } from 'redux';
import { combineReducers } from 'redux-immutablejs';
import reducers from './reducers';
import Routes from './components/Routes';
-import Application from './components/Application';
import ApplicationStore from './stores/ApplicationStore';
import AppointmentStore from './stores/AppointmentStore';
import InboxStore from './stores/InboxStore';
diff --git a/src/components/Application.jsx b/src/components/Application.jsx
index 2373334..3ba925c 100644
--- a/src/components/Application.jsx
+++ b/src/components/Application.jsx
@@ -68,7 +68,6 @@ export default class Application extends React.Component {
this.props.createSession();
ThemeManager.setTheme(QuartetTheme);
- //if we're not entering the application via login, validate our authentication
if (!this.props.isMakingRequest) {
this.props.validateAuthentication();
}
diff --git a/src/components/PatientNameTypeahead.jsx b/src/components/PatientNameTypeahead.jsx
index 760f223..c929040 100644
--- a/src/components/PatientNameTypeahead.jsx
+++ b/src/components/PatientNameTypeahead.jsx
@@ -2,8 +2,6 @@ import React from 'react';
import Typeahead from '../legacy-frontend-common/Typeahead';
import ApplicationActions from '../actions/ApplicationActions';
import ApplicationStore from '../stores/ApplicationStore';
-import { COLLAB_API_URL } from '../settings';
-import urljoin from 'url-join';
import { clientRequest } from 'qh-common/utils';
@@ -38,7 +36,7 @@ export default class PatientNameTypeahead extends React.Component {
_searchPatients(value) {
console.debug("executing action searchPatients", value);
clientRequest
- .get(urljoin(COLLAB_API_URL, 'api/search-provider-patients/'))
+ .get('/api/search-provider-patients/')
.set('Accept', 'application/json')
.query({ value: value })
.send(value)
diff --git a/src/components/RegisterApp.jsx b/src/components/RegisterApp.jsx
index 4aa80eb..b7129ef 100644
--- a/src/components/RegisterApp.jsx
+++ b/src/components/RegisterApp.jsx
@@ -75,10 +75,11 @@ export default class RegisterApp extends React.Component {
register: PropTypes.func.isRequired,
isMakingRequest: PropTypes.bool,
registerErrorMessage: PropTypes.string,
+ isAuthenticated: React.PropTypes.bool.isRequired,
query: React.PropTypes.shape({
pt_id: React.PropTypes.string,
pt_h: React.PropTypes.string
- }),
+ })
};
componentDidMount () {
diff --git a/src/components/SidePanel/ExistingAppointment.jsx b/src/components/SidePanel/ExistingAppointment.jsx
index 89ab6fd..68f431a 100644
--- a/src/components/SidePanel/ExistingAppointment.jsx
+++ b/src/components/SidePanel/ExistingAppointment.jsx
@@ -1,13 +1,11 @@
import React from 'react';
import { clientRequest } from 'qh-common/utils';
import Moment from 'moment';
-import { COLLAB_API_URL } from '../../settings';
import AppointmentStore from '../../stores/AppointmentStore';
import InboxActions from '../../actions/InboxActions';
import MenuActions from '../../actions/MenuActions';
import AppointmentActions from '../../actions/AppointmentActions';
import { connectToStores } from 'fluxible-addons-react';
-import urljoin from 'url-join';
import {
PROVIDEROPTION_DA_COUNSELOR,
@@ -188,7 +186,7 @@ export default class ExistingAppointment extends React.Component {
/* load provider info */
const component = this;
clientRequest
- .get(urljoin(COLLAB_API_URL, 'api/medical-provider/', appointment.source_referral.referring_provider))
+ .get(`/api/medical-provider/${appointment.source_referral.referring_provider}`)
.set('Accept', 'application/json')
.send()
.end(function (err, res) {
@@ -214,7 +212,7 @@ export default class ExistingAppointment extends React.Component {
/* load provider info */
clientRequest
- .get(urljoin(COLLAB_API_URL, 'api/medical-provider/', appointment.source_referral.referring_provider))
+ .get(`/api/medical-provider/${appointment.source_referral.referring_provider}`)
.set('Accept', 'application/json')
.send()
.end(function (err, res) {
diff --git a/src/settings.js b/src/settings.js
index 375fdd6..a798051 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -3,13 +3,8 @@
let domain = process.env.DOMAIN || 'quartethealth.local';
let subdomain_prefix = process.env.SUBDOMAIN_PREFIX || '';
-export const COLLAB_ID = process.env.COLLAB_ID || 'BHP_CLIENT';
-export const COLLAB_KEY = process.env.COLLAB_KEY || 'ZzI1MZ2117';
export const INTERCOM_APP_ID = process.env.INTERCOM_APP_ID || 'vpei6msd';
-export const COLLAB_API_URL = '/';
-export const IDENTITY_SERVER = '/';
-export const COLLAB_API_ENDPOINT = `https://${subdomain_prefix}bh.${domain}`;
export const TERMS_AND_CONDITIONS = 'https://' + subdomain_prefix + 'bh.' + domain + '/terms#terms';
export const PRIVACY_POLICY = 'https://' + subdomain_prefix + 'bh.' + domain + '/terms#privacy';
export const ANALYTICS_SERVER = '//analytics.quartethealth.com';
diff --git a/src/stores/ApplicationStore.js b/src/stores/ApplicationStore.js
index fcfb4ea..c8b0e98 100644
--- a/src/stores/ApplicationStore.js
+++ b/src/stores/ApplicationStore.js
@@ -1,5 +1,5 @@
import BaseStore from 'fluxible/addons/BaseStore'
-import urljoin from 'url-join'
+
class ApplicationStore extends BaseStore {
constructor(dispatcher) {
diff --git a/webpack.config.js b/webpack.config.js
index 96e766e..40fe9d9 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -19,9 +19,7 @@ module.exports = {
'deepcopy',
'deepmerge',
'lodash',
- 'serialize-javascript',
- 'superagent',
- 'url-join'
+ 'serialize-javascript'
],
main: './src/client.jsx'
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment