mirror of
https://github.com/atlanticbiomedical/biomedjs.git
synced 2025-07-02 00:47:26 -04:00
More stuff
This commit is contained in:
@ -1,6 +1,43 @@
|
||||
var jwt = require('jwt-simple');
|
||||
var moment = require('moment-timezone');
|
||||
|
||||
var mongoose = require('mongoose');
|
||||
|
||||
exports.profile = function(req, res) {
|
||||
res.json(req.user);
|
||||
};
|
||||
|
||||
module.exports = function(config) {
|
||||
|
||||
function createJWT(user, uid) {
|
||||
var payload = {
|
||||
sub: uid,
|
||||
oid: user.id,
|
||||
iat: moment().unix(),
|
||||
exp: moment().add(14, 'days').unix()
|
||||
};
|
||||
|
||||
return jwt.encode(payload, config.auth.jwtSecret);
|
||||
}
|
||||
|
||||
return {
|
||||
profile: function(req, res) {
|
||||
res.json(req.user);
|
||||
},
|
||||
|
||||
impersonate: function(req, res) {
|
||||
|
||||
var uid = req.body.uid;
|
||||
if (!uid) {
|
||||
return res.json(400);
|
||||
}
|
||||
|
||||
console.log(req.user.name.first + " " + req.user.name.last + " is requesting to impersonate user " + uid);
|
||||
if (req.user.perms.indexOf('system.developer') === -1) {
|
||||
console.log("Access to impersonate user denied");
|
||||
return res.json(403);
|
||||
} else {
|
||||
console.log("User is a developer");
|
||||
}
|
||||
|
||||
console.log("Access token issued to impersonate user.");
|
||||
res.send({ token: createJWT(req.user, uid) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
520
app/controllers/timeclock.js
Normal file
520
app/controllers/timeclock.js
Normal file
@ -0,0 +1,520 @@
|
||||
"use strict";
|
||||
|
||||
var mongoose = require('mongoose');
|
||||
var moment = require('moment-timezone');
|
||||
var _ = require('lodash');
|
||||
var Promise = require('bluebird');
|
||||
var TimeClockSpan = mongoose.model('TimeClockSpan');
|
||||
var Workorder = mongoose.model('Workorder');
|
||||
|
||||
var NON_BILLABLES = ['shop', 'break', 'pto', 'meeting', 'event', 'weather', 'holiday'];
|
||||
var TASK_TYPES = ['workday', 'workorder', 'nonBillable'];
|
||||
|
||||
function MultipleSpansError(spans) {
|
||||
Error.captureStackTrace(this, MultipleSpansError);
|
||||
|
||||
this.name = 'MultipleSpansError';
|
||||
this.message = 'Encountered multiple spans when one was expected';
|
||||
this.spans = spans;
|
||||
}
|
||||
MultipleSpansError.prototype = Object.create(Error.prototype);
|
||||
|
||||
function findUserSpans(user, day) {
|
||||
var startOfDay = day.clone().startOf('day').utc().toDate();
|
||||
var endOfDay = day.clone().endOf('day').utc().toDate();
|
||||
|
||||
var query = {
|
||||
start: {
|
||||
'$gte': startOfDay,
|
||||
'$lte': endOfDay
|
||||
},
|
||||
user: user.id
|
||||
};
|
||||
|
||||
return TimeClockSpan
|
||||
.find(query)
|
||||
.exec();
|
||||
}
|
||||
|
||||
function findUserWorkorders(user, day) {
|
||||
var startOfDay = day.clone().startOf('day').toDate();
|
||||
var endOfDay = day.clone().endOf('day').toDate();
|
||||
|
||||
var query = {
|
||||
deleted: false,
|
||||
techs: user.id,
|
||||
'scheduling.start': {
|
||||
'$lte': endOfDay
|
||||
},
|
||||
'scheduling.end': {
|
||||
'$gte': startOfDay
|
||||
}
|
||||
};
|
||||
|
||||
return Workorder
|
||||
.find(query)
|
||||
.populate('client', 'name identifier')
|
||||
.exec();
|
||||
}
|
||||
|
||||
function findUserWorkorder(id, user) {
|
||||
var query = {
|
||||
_id: id,
|
||||
techs: user.id,
|
||||
deleted: false
|
||||
};
|
||||
|
||||
return Workorder
|
||||
.findOne(query)
|
||||
.populate('client', 'name identifier contacts address')
|
||||
.exec();
|
||||
}
|
||||
|
||||
function filterSpans(spans, filter) {
|
||||
filter = {
|
||||
type: filter.type ? [].concat(filter.type) : undefined,
|
||||
status: filter.status ? String(filter.status) : undefined,
|
||||
workorder: filter.workorder ? String(filter.workorder) : undefined,
|
||||
reason: filter.reason ? String(filter.reason) : undefined
|
||||
};
|
||||
|
||||
return _.chain(spans)
|
||||
.filter(function(span) {
|
||||
|
||||
if (filter.type && filter.type.indexOf(span.type) === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter.status && String(span.status) !== filter.status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter.workorder && String(span.workorder) !== filter.workorder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter.reason && span.reason !== filter.reason) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.sortBy('start')
|
||||
.value();
|
||||
}
|
||||
|
||||
function spansStatus(spans, filter) {
|
||||
if (filter) {
|
||||
spans = filterSpans(spans, filter);
|
||||
}
|
||||
|
||||
var result = 'pending';
|
||||
_.forEach(spans, function(span) {
|
||||
if (span.status === 'open') {
|
||||
result = 'clockedIn';
|
||||
return false;
|
||||
} else {
|
||||
result = 'clockedOut';
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function validateClockRequest(req) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
var params = {};
|
||||
|
||||
var type = req.body.type;
|
||||
if (!type) {
|
||||
return reject("Missing required parameter 'type'");
|
||||
}
|
||||
|
||||
if (TASK_TYPES.indexOf(type) === -1) {
|
||||
return reject("Invalid type: '" + type + "'");
|
||||
}
|
||||
|
||||
params.type = type;
|
||||
|
||||
if (type === 'workorder') {
|
||||
var id = req.body.id;
|
||||
if (!id) {
|
||||
return reject("Missing required parameter 'id'");
|
||||
}
|
||||
|
||||
params.id = id;
|
||||
}
|
||||
|
||||
if (type === 'nonBillable') {
|
||||
var reason = req.body.reason;
|
||||
if (!reason) {
|
||||
return reject("Missing required parameter 'reason'");
|
||||
}
|
||||
|
||||
if (NON_BILLABLES.indexOf(reason) === -1) {
|
||||
return reject("Invalid reason: '" + reason + "'");
|
||||
}
|
||||
|
||||
params.reason = reason;
|
||||
}
|
||||
|
||||
resolve(params);
|
||||
});
|
||||
}
|
||||
|
||||
function validateWorkorderDetailsRequest(req) {
|
||||
var params = {};
|
||||
|
||||
var id = req.param('id');
|
||||
if (!id) {
|
||||
return Promise.reject("Missing required parameter 'id'");
|
||||
}
|
||||
|
||||
params.id = id;
|
||||
|
||||
return Promise.resolve(params);
|
||||
}
|
||||
|
||||
function handleStatusRequest(spans, workorders) {
|
||||
|
||||
var results = {};
|
||||
|
||||
var workdaySpans = _.filter(spans, { type: 'workday' });
|
||||
|
||||
results.tasks = [];
|
||||
|
||||
results.tasks = results.tasks.concat({
|
||||
type: 'workday',
|
||||
status: spansStatus(workdaySpans),
|
||||
spans: _.map(workdaySpans, spanToResponse)
|
||||
});
|
||||
|
||||
results.tasks = results.tasks.concat(_.chain(workorders)
|
||||
.sortBy('scheduling.start')
|
||||
.map(function(workorder) {
|
||||
var workorderSpans = filterSpans(spans, { type: 'workorder', workorder: workorder.id });
|
||||
|
||||
return {
|
||||
type: 'workorder',
|
||||
id: workorder.id,
|
||||
title: workorder.client.name,
|
||||
start: moment(workorder.scheduling.start).utc().toISOString(),
|
||||
end: moment(workorder.scheduling.end).utc().toISOString(),
|
||||
status: spansStatus(workorderSpans),
|
||||
spans: _.map(workorderSpans, spanToResponse)
|
||||
};
|
||||
})
|
||||
.value()
|
||||
);
|
||||
|
||||
results.tasks = results.tasks.concat(_.chain(NON_BILLABLES)
|
||||
.map(function(nonBillable) {
|
||||
var nonBillableSpans = filterSpans(spans, { reason: nonBillable });
|
||||
|
||||
return {
|
||||
type: 'nonBillable',
|
||||
reason: nonBillable,
|
||||
status: spansStatus(nonBillableSpans),
|
||||
spans: _.map(nonBillableSpans, spanToResponse)
|
||||
};
|
||||
})
|
||||
.value()
|
||||
);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function handleClockInRequest(params, user, spans, workorders, now) {
|
||||
var workdayStatus = spansStatus(spans, { type: 'workday' });
|
||||
|
||||
if (params.type === 'workday') {
|
||||
if (workdayStatus === 'clockedIn') {
|
||||
return Promise.reject('Already clocked in');
|
||||
}
|
||||
|
||||
var span = new TimeClockSpan({
|
||||
user: user.id,
|
||||
type: 'workday',
|
||||
status: 'open',
|
||||
start: now.clone().utc().toDate()
|
||||
});
|
||||
|
||||
} else {
|
||||
if (workdayStatus !== 'clockedIn') {
|
||||
return Promise.reject('Not clocked into day');
|
||||
}
|
||||
|
||||
var allTasksStatus = spansStatus(spans, {type: ['workorder', 'nonBillable']});
|
||||
if (allTasksStatus === 'clockedIn') {
|
||||
return Promise.reject('Already clocked in');
|
||||
}
|
||||
|
||||
if (params.type === 'workorder') {
|
||||
var workorder = _.find(workorders, {id: params.id});
|
||||
if (!workorder) {
|
||||
return Promise.reject('Invalid workorder');
|
||||
}
|
||||
|
||||
handleClockInExceptions(user, workorder, spans, now);
|
||||
|
||||
var span = new TimeClockSpan({
|
||||
user: user.id,
|
||||
type: 'workorder',
|
||||
status: 'open',
|
||||
start: now.clone().utc().toDate(),
|
||||
workorder: workorder.id,
|
||||
client: workorder.client.id
|
||||
});
|
||||
}
|
||||
|
||||
if (params.type === 'nonBillable') {
|
||||
var span = new TimeClockSpan({
|
||||
user: user.id,
|
||||
type: 'nonBillable',
|
||||
status: 'open',
|
||||
start: now.clone().utc().toDate(),
|
||||
reason: params.reason
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return span.save().then(spanToResponse);
|
||||
}
|
||||
|
||||
function handleClockInExceptions(user, workorder, spans, now) {
|
||||
|
||||
var closedWorkordersSpans = filterSpans(spans, { type: 'workorder', status: 'closed' });
|
||||
var isFirstWorkorder = closedWorkordersSpans.length == 0;
|
||||
|
||||
if (isFirstWorkorder) {
|
||||
var start = moment(workorder.scheduling.start);
|
||||
var minutes = now.diff(start, 'minutes');
|
||||
|
||||
if (minutes > 15) {
|
||||
reportException({
|
||||
user: user,
|
||||
workorder: workorder,
|
||||
reason: 'User is late to first workorder.'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var previousWorkorderSpan = _.last(closedWorkordersSpans);
|
||||
|
||||
if (previousWorkorderSpan.workorder != workorder.id) {
|
||||
console.log(previousWorkorderSpan);
|
||||
|
||||
var end = moment(previousWorkorderSpan.end);
|
||||
var minutes = now.diff(end, 'minutes');
|
||||
console.log("Time between tasks: ", minutes);
|
||||
|
||||
if (minutes < 5) {
|
||||
reportException({
|
||||
user: user,
|
||||
workorder: workorder,
|
||||
reason: 'User clocked in to next workorder too quickly.'
|
||||
});
|
||||
}
|
||||
|
||||
if (minutes > 75) {
|
||||
reportException({
|
||||
user: user,
|
||||
workorder: workorder,
|
||||
reason: 'Too much travel time detected between jobs.'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function reportException(exception) {
|
||||
// TODO: Actually send emails for exceptions.
|
||||
|
||||
console.log('--- EXCEPTION ---', exception.reason);
|
||||
}
|
||||
|
||||
function handleClockOutRequest(params, user, spans, workorders, now) {
|
||||
var workdaySpans = filterSpans(spans, { type: 'workday' });
|
||||
var workdayStatus = spansStatus(workdaySpans);
|
||||
|
||||
if (workdayStatus !== 'clockedIn') {
|
||||
return Promise.reject('Not clocked in');
|
||||
}
|
||||
|
||||
if (params.type === 'workday') {
|
||||
var allTasksStatus = spansStatus(spans, {type: ['workorder', 'nonBillable']});
|
||||
if (allTasksStatus === 'clockedIn') {
|
||||
return Promise.reject('Cannot clock out while tasks are still open.');
|
||||
}
|
||||
|
||||
var span = ensureSingularSpan(filterSpans(workdaySpans, {status: 'open'}));
|
||||
}
|
||||
|
||||
if (params.type === 'workorder') {
|
||||
var workorder = _.find(workorders, {id: params.id});
|
||||
if (!workorder) {
|
||||
return Promise.reject('Invalid workorder');
|
||||
}
|
||||
|
||||
var workorderSpans = filterSpans(spans, { type: 'workorder', workorder: workorder.id });
|
||||
var workorderStatus = spansStatus(workorderSpans);
|
||||
|
||||
if (workorderStatus !== 'clockedIn') {
|
||||
return Promise.reject('Not clocked in');
|
||||
}
|
||||
|
||||
var span = ensureSingularSpan(filterSpans(workorderSpans, {status: 'open'}));
|
||||
}
|
||||
|
||||
if (params.type === 'nonBillable') {
|
||||
var nonBillableSpans = filterSpans(spans, { type: 'nonBillable', reason: params.reason });
|
||||
var nonBillableStatus = spansStatus(nonBillableSpans);
|
||||
|
||||
if (nonBillableStatus !== 'clockedIn') {
|
||||
return Promise.reject('Not clocked in');
|
||||
}
|
||||
|
||||
var span = ensureSingularSpan(filterSpans(nonBillableSpans, {status: 'open'}));
|
||||
}
|
||||
|
||||
span.status = 'closed';
|
||||
span.end = now.clone().utc().toDate();
|
||||
span.duration = moment(span.end).diff(span.start, 'seconds');
|
||||
|
||||
return span.save().then(spanToResponse);
|
||||
}
|
||||
|
||||
function handleWorkorderDetailsRequest(params, user, spans, workorder, today) {
|
||||
if (!workorder) {
|
||||
return Promise.reject('Invalid workorder');
|
||||
}
|
||||
|
||||
var workorderSpans = filterSpans(spans, { type: 'workorder', workorder: workorder.id });
|
||||
var workorderStatus = spansStatus(workorderSpans);
|
||||
|
||||
workorder = workorder.toObject();
|
||||
workorder.timeclock = {
|
||||
type: 'workorder',
|
||||
id: workorder._id,
|
||||
title: workorder.client.name,
|
||||
start: moment(workorder.scheduling.start).utc().toISOString(),
|
||||
end: moment(workorder.scheduling.end).utc().toISOString(),
|
||||
status: workorderStatus,
|
||||
spans: _.map(workorderSpans, spanToResponse),
|
||||
blocked: false
|
||||
};
|
||||
|
||||
if (workorderStatus != 'clockedIn') {
|
||||
var workdayStatus = spansStatus(spans, { type: 'workday' });
|
||||
var otherSpansStatus = spansStatus(spans, {type: ['workorder', 'nonBillable']});
|
||||
|
||||
if (workdayStatus != 'clockedIn' || otherSpansStatus == 'clockedIn') {
|
||||
workorder.timeclock.blocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
return workorder;
|
||||
}
|
||||
|
||||
function spanToResponse(span) {
|
||||
return {
|
||||
start: span.start,
|
||||
end: span.end,
|
||||
duration: span.duration
|
||||
};
|
||||
}
|
||||
|
||||
function ensureSingularSpan(spans) {
|
||||
if (spans.length != 1) {
|
||||
throw new MultipleSpansError(spans);
|
||||
}
|
||||
|
||||
return spans[0];
|
||||
}
|
||||
|
||||
function responseHandler(res) {
|
||||
return function(data) {
|
||||
res.json(data);
|
||||
};
|
||||
}
|
||||
|
||||
function errorHandler(res) {
|
||||
return function(error) {
|
||||
if (typeof error === 'string') {
|
||||
res.json(400, {
|
||||
error: {
|
||||
message: error
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error(error.stack);
|
||||
res.json(500, 'Internal error');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function() {
|
||||
return {
|
||||
index: function(req, res) {
|
||||
|
||||
//TODO: Check to make sure user has a valid timesheet.
|
||||
|
||||
var today = moment();
|
||||
|
||||
var spans = findUserSpans(req.user, today);
|
||||
var workorders = findUserWorkorders(req.user, today);
|
||||
|
||||
Promise.join(spans, workorders, handleStatusRequest)
|
||||
.then(responseHandler(res))
|
||||
.catch(errorHandler(res));
|
||||
},
|
||||
|
||||
clockIn: function(req, res) {
|
||||
|
||||
//TODO: Check to make sure user has a valid timesheet.
|
||||
|
||||
var today = moment();
|
||||
|
||||
var params = validateClockRequest(req);
|
||||
var spans = findUserSpans(req.user, today);
|
||||
var workorders = findUserWorkorders(req.user, today);
|
||||
|
||||
Promise.join(params, req.user, spans, workorders, today, handleClockInRequest)
|
||||
.then(responseHandler(res))
|
||||
.catch(errorHandler(res));
|
||||
},
|
||||
|
||||
clockOut: function(req, res) {
|
||||
|
||||
//TODO: Check to make sure user has a valid timesheet.
|
||||
|
||||
var today = moment();
|
||||
|
||||
var params = validateClockRequest(req);
|
||||
var spans = findUserSpans(req.user, today);
|
||||
var workorders = findUserWorkorders(req.user, today);
|
||||
|
||||
Promise.join(params, req.user, spans, workorders, today, handleClockOutRequest)
|
||||
.then(responseHandler(res))
|
||||
.catch(errorHandler(res));
|
||||
},
|
||||
|
||||
workorderDetails: function(req, res) {
|
||||
|
||||
var today = moment();
|
||||
|
||||
validateWorkorderDetailsRequest(req)
|
||||
.then(function(params) {
|
||||
var spans = findUserSpans(req.user, today);
|
||||
var workorder = findUserWorkorder(params.id, req.user);
|
||||
|
||||
return Promise.join(params, req.user, spans, workorder, today, handleWorkorderDetailsRequest)
|
||||
})
|
||||
.then(responseHandler(res))
|
||||
.catch(errorHandler(res));
|
||||
|
||||
|
||||
Promise.join
|
||||
}
|
||||
}
|
||||
};
|
58
app/model/timeClockSpan.js
Normal file
58
app/model/timeClockSpan.js
Normal file
@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
|
||||
var mongoose = require('mongoose');
|
||||
var Schema = mongoose.Schema;
|
||||
var ObjectId = Schema.ObjectId;
|
||||
|
||||
var schema = new Schema({
|
||||
|
||||
user: {
|
||||
type: ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
|
||||
client: {
|
||||
type: ObjectId,
|
||||
ref: 'Client'
|
||||
},
|
||||
|
||||
workorder: {
|
||||
type: ObjectId,
|
||||
ref: 'Workorder'
|
||||
},
|
||||
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['open', 'closed']
|
||||
},
|
||||
|
||||
start: {
|
||||
type: Date
|
||||
},
|
||||
|
||||
end: {
|
||||
type: Date
|
||||
},
|
||||
|
||||
duration: {
|
||||
type: Number,
|
||||
min: 0
|
||||
},
|
||||
|
||||
type: {
|
||||
type: String,
|
||||
enum: [ 'workorder', 'workday', 'nonBillable' ]
|
||||
},
|
||||
|
||||
reason: {
|
||||
type: String,
|
||||
enum: ['shop', 'break', 'pto', 'meeting', 'event', 'weather', 'holiday']
|
||||
},
|
||||
|
||||
notes: {
|
||||
type: String,
|
||||
trim: true
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('TimeClockSpan', schema);
|
147
config/auth.js
147
config/auth.js
@ -1,6 +1,85 @@
|
||||
var log = require('log4node');
|
||||
var mongoose = require('mongoose');
|
||||
var User = mongoose.model('User');
|
||||
var request = require('request');
|
||||
var jwt = require('jwt-simple');
|
||||
var moment = require('moment');
|
||||
|
||||
var ACCESS_TOKEN_URL = 'https://accounts.google.com/o/oauth2/token';
|
||||
var PEOPLE_API_URL = 'https://www.googleapis.com/plus/v1/people/me/openIdConnect';
|
||||
|
||||
module.exports = function(app, passport, config) {
|
||||
|
||||
function createJWT(user) {
|
||||
var payload = {
|
||||
sub: user._id,
|
||||
iat: moment().unix(),
|
||||
exp: moment().add(14, 'days').unix()
|
||||
};
|
||||
|
||||
return jwt.encode(payload, config.auth.jwtSecret);
|
||||
}
|
||||
|
||||
app.post('/auth2', function(req, res) {
|
||||
var params = {
|
||||
code: req.body.code,
|
||||
client_id: req.body.clientId,
|
||||
client_secret: config.auth.clientSecret,
|
||||
redirect_uri: req.body.redirectUri,
|
||||
grant_type: 'authorization_code'
|
||||
};
|
||||
|
||||
request.post(ACCESS_TOKEN_URL, { json: true, form: params }, function(err, response, token) {
|
||||
console.log(token);
|
||||
|
||||
var accessToken = token.access_token;
|
||||
var headers = {
|
||||
Authorization: 'Bearer ' + accessToken
|
||||
};
|
||||
|
||||
request.get({ url: PEOPLE_API_URL, headers: headers, json: true }, function(err, response, profile) {
|
||||
if (profile.error) {
|
||||
return res.status(500).send({ message: profile.error.message });
|
||||
}
|
||||
|
||||
User.findOne({ email: profile.email.toLowerCase() }, function(err, user) {
|
||||
if (err) {
|
||||
return res.status(500).send(err);
|
||||
}
|
||||
|
||||
if (!user || !user.hasPermission('system.login')) {
|
||||
return res.status(403).send({ message: "You are not authorized to access this portal."});
|
||||
}
|
||||
|
||||
user.accessToken = token.access_token;
|
||||
|
||||
if (token.refresh_token) {
|
||||
user.refreshToken = token.refresh_token;
|
||||
}
|
||||
|
||||
if (profile.given_name) {
|
||||
user.name.first = profile.given_name;
|
||||
}
|
||||
|
||||
if (profile.family_name) {
|
||||
user.name.last = profile.family_name;
|
||||
}
|
||||
|
||||
if (profile.picture) {
|
||||
user.picture = profile.picture.replace('sz=50', 'sz=200');
|
||||
}
|
||||
|
||||
user.save()
|
||||
.then(function() {
|
||||
res.send({ token: createJWT(user) });
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
module.exports = function(app, passport) {
|
||||
app.get('/auth', function(req, res, next) {
|
||||
console.dir(req.headers);
|
||||
req.session.redirectUrl = req.headers['referer'];
|
||||
@ -52,15 +131,68 @@ module.exports = function(app, passport) {
|
||||
})(req, res, next);
|
||||
});
|
||||
|
||||
function createAuthenticator(error) {
|
||||
return function(req, res, next) {
|
||||
var onError = function() {
|
||||
error(req, res, next);
|
||||
};
|
||||
|
||||
var onSuccess = function(user) {
|
||||
log.setPrefix(function(level) {
|
||||
return '[' + new Date().toUTCString() + '] ' + level.toUpperCase() + ' ' + user.name.first + ' ' + user.name.last + ' | ';
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
if (!req.isAuthenticated()) {
|
||||
if (!req.headers.authorization) {
|
||||
return onError();
|
||||
}
|
||||
|
||||
var token = req.headers.authorization.split(' ')[1];
|
||||
var payload = null;
|
||||
try {
|
||||
payload = jwt.decode(token, config.auth.jwtSecret);
|
||||
} catch (err) {
|
||||
return onError();
|
||||
}
|
||||
|
||||
if (payload.exp <= moment().unix()) {
|
||||
return onError();
|
||||
}
|
||||
|
||||
User.findById(payload.sub, function(err, user) {
|
||||
console.log('Loaded User');
|
||||
req.user = user;
|
||||
|
||||
onSuccess(user);
|
||||
});
|
||||
} else {
|
||||
onSuccess(req.user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
requiresUiLogin: createAuthenticator(function(req, res, next) {
|
||||
res.redirect('/login');
|
||||
}),
|
||||
|
||||
requiresApiAccess: createAuthenticator(function(req, res, next) {
|
||||
res.send(403);
|
||||
})
|
||||
};
|
||||
|
||||
/*
|
||||
return {
|
||||
requiresUiLogin: function(req, res, next) {
|
||||
if (!req.isAuthenticated()) {
|
||||
return res.redirect('/login');
|
||||
}
|
||||
|
||||
log.setPrefix(function(level) {
|
||||
return '[' + new Date().toUTCString() + '] ' + level.toUpperCase() + ' ' + req.user.name.first + ' ' + req.user.name.last + ' | ';
|
||||
});
|
||||
log.setPrefix(function(level) {
|
||||
return '[' + new Date().toUTCString() + '] ' + level.toUpperCase() + ' ' + req.user.name.first + ' ' + req.user.name.last + ' | ';
|
||||
});
|
||||
next();
|
||||
},
|
||||
requiresApiAccess: function(req, res, next) {
|
||||
@ -68,10 +200,11 @@ module.exports = function(app, passport) {
|
||||
return res.send(403);
|
||||
}
|
||||
|
||||
log.setPrefix(function(level) {
|
||||
return '[' + new Date().toUTCString() + '] ' + level.toUpperCase() + ' ' + req.user.name.first + ' ' + req.user.name.last + ' | ';
|
||||
});
|
||||
log.setPrefix(function(level) {
|
||||
return '[' + new Date().toUTCString() + '] ' + level.toUpperCase() + ' ' + req.user.name.first + ' ' + req.user.name.last + ' | ';
|
||||
});
|
||||
next();
|
||||
}
|
||||
};
|
||||
*/
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ module.exports = {
|
||||
clientSecret: '8MRNar9E_pRTOGTQonPzYOW_',
|
||||
callback: 'http://devel.portal.atlanticbiomedical.com/auth/callback',
|
||||
accessToken: 'ya29.AHES6ZR-vUVEh7CZzsEeGFSHqFfXtU1-LHyEAidi0CKhDGQ',
|
||||
refreshToken: '1/exRXjTaGNlWEo-HZZWyn4NTwJ4TY3wKb-_npce21c50',
|
||||
refreshToken: '1/exRXjTaGNlWEo-HZZWyn4NTwJ4TY3wKb-_npce21c50'
|
||||
},
|
||||
email: {
|
||||
user: 'api@atlanticbiomedical.com',
|
||||
@ -18,7 +18,7 @@ module.exports = {
|
||||
host: 'biomed.akira.gs',
|
||||
user: 'biomed_prod',
|
||||
password: 'wUw3RB8rrXX4HwKj',
|
||||
database: 'biomed_prod',
|
||||
database: 'biomed_prod'
|
||||
}
|
||||
},
|
||||
prod: {
|
||||
@ -28,16 +28,17 @@ module.exports = {
|
||||
auth: {
|
||||
clientId: '333768673996-8epedo3je5h59n4l97v4dv8nofs7qnee.apps.googleusercontent.com',
|
||||
clientSecret: 'afu9KhKxckWJ3Tk6uxzp9Pg6',
|
||||
callback: 'http://portal.atlanticbiomedical.com/auth/callback',
|
||||
callback: 'http://localhost:9000/auth/callback',
|
||||
// accessToken: 'ya29.AHES6ZT1Sj1vpgidR2I_ksLdlV_VeZUjkitnZ01cP6VRrknjUEVbuw',
|
||||
// refreshToken: '1/XQW9P9FNYm6jikTsV8HOIuPAo1APYhwTH5CLhq9263g'
|
||||
|
||||
accessToken: 'ya29.1.AADtN_Xjt0PK6YVs8q5csiQFXQg2ZDtrVhsH6P4a5zm0mHqhGx0Nnjx4Jk68Gw',
|
||||
refreshToken: '1/_5SkDLYmsi4XNaQyAzld-W5-GEqEqt5byH6VkI-j5QI',
|
||||
jwtSecret: '97v4dvcsiQFXQg28nofedo3jemsi4XNaQy5h59n4l97m0mHqhGx0Nnjxv4dv8n'
|
||||
},
|
||||
email: {
|
||||
user: 'api@atlanticbiomedical.com',
|
||||
password: 'success4',
|
||||
password: 'success4'
|
||||
},
|
||||
mysql: {
|
||||
host: 'localhost',
|
||||
|
@ -1,4 +1,5 @@
|
||||
var express = require('express');
|
||||
var cors = require('cors');
|
||||
var ClusterStore = require('strong-cluster-connect-store')(express.session);
|
||||
|
||||
module.exports = function(app, config, passport, piler) {
|
||||
@ -23,6 +24,14 @@ module.exports = function(app, config, passport, piler) {
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
// allow cors
|
||||
app.use(cors({
|
||||
origin: function(origin, callback) {
|
||||
callback(null, true);
|
||||
},
|
||||
credentials: true
|
||||
}));
|
||||
|
||||
// use piler for asset management
|
||||
piler.bind();
|
||||
|
||||
|
@ -94,6 +94,12 @@ module.exports = function(app, auth, piler, calendar, directory, config) {
|
||||
app.post('/api/test_runs', testRuns.create);
|
||||
app.post('/api/test_runs/:test_run_id', testRuns.update);
|
||||
|
||||
var timeclock = require('../app/controllers/timeclock')();
|
||||
app.get('/api/timeclock', timeclock.index);
|
||||
app.post('/api/timeclock/clock_in', timeclock.clockIn);
|
||||
app.post('/api/timeclock/clock_out', timeclock.clockOut);
|
||||
app.get('/api/timeclock/workorder/:id', timeclock.workorderDetails);
|
||||
|
||||
var pms = require('../app/controllers/pms');
|
||||
app.get('/api/pms', pms.index);
|
||||
|
||||
@ -107,8 +113,9 @@ module.exports = function(app, auth, piler, calendar, directory, config) {
|
||||
app.post('/api/users/:user_id', users.update);
|
||||
app.get('/api/users/:user_id/clocks', users.clocks);
|
||||
|
||||
var account = require('../app/controllers/account');
|
||||
var account = require('../app/controllers/account')(config);
|
||||
app.get('/api/account', account.profile);
|
||||
app.post('/api/account/impersonate', account.impersonate);
|
||||
|
||||
var messages = require('../app/controllers/messages')(config);
|
||||
app.post('/api/messages/send', messages.send);
|
||||
|
@ -9,10 +9,12 @@ var fs = require('fs');
|
||||
var passport = require('passport');
|
||||
var config = require('./config/config')[env];
|
||||
var mongoose = require('mongoose');
|
||||
var Promise = require('bluebird');
|
||||
var log = require('log4node');
|
||||
|
||||
Promise.promisifyAll(mongoose);
|
||||
mongoose.Promise = require('bluebird');
|
||||
|
||||
var moment = require('moment-timezone');
|
||||
moment.tz.setDefault("America/New_York");
|
||||
|
||||
var pushoverApi = new pushover({
|
||||
user: 'aJmPD4KigO0vLwim76n3WqWKwbKA3k',
|
||||
@ -57,7 +59,7 @@ var piler = require('./config/piler')(app, server, io, config);
|
||||
// Express settings
|
||||
require('./config/express')(app, config, passport, piler);
|
||||
|
||||
var auth = require('./config/auth')(app, passport);
|
||||
var auth = require('./config/auth')(app, passport, config);
|
||||
|
||||
var calendar = require('./config/calendar')(config);
|
||||
|
||||
|
Reference in New Issue
Block a user