Skip to content
This repository has been archived by the owner on Aug 3, 2018. It is now read-only.

Commit

Permalink
refactor: Restructure Meeting logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian committed Mar 13, 2018
1 parent ff3ac90 commit 95007df
Show file tree
Hide file tree
Showing 32 changed files with 3,834 additions and 1,430 deletions.
7 changes: 6 additions & 1 deletion .nsprc
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"exceptions": ["https://nodesecurity.io/advisories/130", "https://nodesecurity.io/advisories/525", "https://nodesecurity.io/advisories/534"]
"exceptions": [
"https://nodesecurity.io/advisories/130",
"https://nodesecurity.io/advisories/525",
"https://nodesecurity.io/advisories/534",
"https://nodesecurity.io/advisories/566"
]
}
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ language: node_js
services:
- mongodb
node_js:
- '7'
- '8'
before_install:
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then openssl aes-256-cbc -K $encrypted_649f128e279d_key -iv $encrypted_649f128e279d_iv -in deploy_key.enc -out deploy_key -d; fi'
script:
- cp src/config/config.json.travis src/config/config.json
- yarn lint && yarn test && yarn docs && yarn build
- cp -R src/app/helper/mail-templates dist/app/helper/mail-templates
- cp src/app/helper/reserved-usernames.json dist/app/helper/reserved-usernames.json
- yarn lint && yarn test && yarn docs && yarn build && cp -R src/app/helper/mail-templates dist/app/helper/mail-templates; cp src/app/helper/reserved-usernames.json dist/app/helper/reserved-usernames.json
after_success:
- sh deploy.sh
122 changes: 63 additions & 59 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,99 +10,103 @@
"start": "nodemon src/server.js --exec babel-node",
"build": "babel src -d dist",
"lint": "eslint src",
"test": "NODE_ENV=test mocha --compilers js:babel-core/register src/**/*.spec.js",
"test": "NODE_ENV=test mocha --compilers js:babel-core/register src/**/_meeting.spec.js",
"serve": "node src/server.js"
},
"dependencies": {
"bcrypt-nodejs": "0.0.3",
"body-parser": "^1.17.1",
"body-parser": "^1.18.2",
"cookie-parser": "^1.4.3",
"core-js": "^2.4.1",
"express": "^4.15.2",
"express-jwt": "^5.1.0",
"express-session": "^1.15.1",
"core-js": "^2.5.3",
"express": "^4.16.2",
"express-jwt": "^5.3.0",
"express-session": "^1.15.6",
"http": "0.0.0",
"jsonwebtoken": "^7.3.0",
"lodash": "^4.17.4",
"jsonwebtoken": "^8.1.1",
"lodash": "^4.17.5",
"md5": "^2.2.1",
"method-override": "^2.3.10",
"moment-timezone": "^0.5.13",
"mongoose": "^4.9.1",
"morgan": "^1.8.1",
"node-fetch": "^1.6.3",
"nodemailer": "^4.0.1",
"passport": "^0.3.2",
"moment-timezone": "^0.5.14",
"mongoose": "^5.0.7",
"morgan": "^1.9.0",
"node-fetch": "^2.0.0",
"nodemailer": "^4.6.0",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
"randomstring": "^1.1.5",
"socket.io": "^2.0.4",
"socketio-jwt": "^4.5.0",
"timezones.json": "^1.2.0",
"web-push": "^3.2.2",
"winston": "^2.3.1",
"youtube-api": "^2.0.8"
"timezones.json": "^1.3.3",
"web-push": "^3.3.0",
"winston": "^2.4.0",
"youtube-api": "^2.0.9"
},
"devDependencies": {
"apidoc": "^0.17.5",
"babel-cli": "^6.24.0",
"babel-core": "^6.24.0",
"babel-eslint": "^7.2.1",
"babel-loader": "^7.1.1",
"apidoc": "^0.17.6",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-loader": "^7.1.3",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-transform-regenerator": "^6.22.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.24.0",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-0": "^6.22.0",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.24.0",
"babel-runtime": "^6.23.0",
"chai": "^4.1.0",
"cors": "^2.8.1",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.26.0",
"babel-runtime": "^6.26.0",
"chai": "^4.1.2",
"cors": "^2.8.4",
"del": "^3.0.0",
"es6-promise": "^4.1.0",
"es6-promise": "^4.2.4",
"es6-promise-loader": "^1.0.2",
"es6-shim": "^0.35.3",
"es7-reflect-metadata": "^1.6.0",
"eslint": "^4.2.0",
"exports-loader": "^0.6.4",
"expose-loader": "^0.7.3",
"file-loader": "^0.11.2",
"eslint": "^4.18.1",
"exports-loader": "^0.7.0",
"expose-loader": "^0.7.4",
"file-loader": "^1.1.10",
"gulp": "^3.9.1",
"gulp-docco": "0.0.4",
"gulp-nodemon": "^2.2.1",
"gulp-rename": "^1.2.2",
"gulp-scss-lint": "^0.4.0",
"gulp-scss-lint": "^0.6.1",
"gulp-util": "^3.0.8",
"http-server": "^0.10.0",
"imports-loader": "^0.7.1",
"istanbul-instrumenter-loader": "^2.0.0",
"json-loader": "^0.5.4",
"karma": "^1.5.0",
"karma-chrome-launcher": "^2.0.0",
"http-server": "^0.11.1",
"imports-loader": "^0.8.0",
"istanbul-instrumenter-loader": "^3.0.0",
"json-loader": "^0.5.7",
"karma": "^2.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage": "^1.1.1",
"karma-jasmine": "^1.1.0",
"karma-mocha-reporter": "^2.2.3",
"karma-jasmine": "^1.1.1",
"karma-mocha-reporter": "^2.2.5",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.4",
"mocha": "^3.2.0",
"morgan": "^1.8.1",
"parse5": "^3.0.2",
"karma-webpack": "^2.0.12",
"mocha": "^5.0.4",
"morgan": "^1.9.0",
"parse5": "^4.0.0",
"phantomjs-polyfill": "0.0.2",
"phantomjs-prebuilt": "^2.1.14",
"protractor": "^5.1.1",
"q-io": "^1.13.4",
"phantomjs-prebuilt": "^2.1.16",
"protractor": "^5.3.0",
"q-io": "^1.13.5",
"raw-loader": "^0.5.1",
"remap-istanbul": "^0.9.5",
"rimraf": "^2.6.1",
"should": "^11.2.1",
"source-map-loader": "^0.2.0",
"remap-istanbul": "^0.10.1",
"rimraf": "^2.6.2",
"should": "^13.2.1",
"source-map-loader": "^0.2.3",
"supertest": "^3.0.0",
"url-loader": "^0.5.8"
"timekeeper": "^2.0.0",
"url-loader": "^0.6.2"
},
"engines": {
"node": ">= 4.2.1",
"npm": ">= 3"
},
"resolutions": {
"**/hoek": "5.0.3"
}
}
114 changes: 29 additions & 85 deletions src/app/helper/appointment.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ import User from '../models/user.model.js';
import moment from 'moment-timezone';
import webpush from 'web-push';

/**
* Converts Date or moment object to Integer representing the time.
*
* @param {moment/Date} Date or moment object
* @return {Number} Time as Number
*/
function timeToNumber(time): Number {
return time instanceof Date
let appointmentHelper = {
/**
* Converts Date or moment object to Integer representing the time.
*
* @param {moment/Date} Date or moment object
* @return {Number} Time as Number
*/
timeToNumber: time => time instanceof Date
? time.getHours() * 100 + time.getMinutes()
: (time instanceof moment ? time.hours() * 100 + time.minutes() : 0);
}
: (time instanceof moment ? time.hours() * 100 + time.minutes() : 0),

let appointmentHelper = {
/**
* Parses hour as String.
*
Expand All @@ -27,35 +25,6 @@ let appointmentHelper = {
printHour: hour => {
const hourStr = '0000' + hour.toString();
return hourStr.substr(-4, 2) + ':' + hourStr.substr(-2, 2);
},

/**
* Adds increment of hours to an appointment.
*
* @param {Object} appointment Appointment object
* @param {Number} increment Amount of hours to add
* @return {Object} Modified appointment object
*/
addIncrement: (appointment, increment) => {
if (!appointment) {
return null;
}

// add increment
appointment.hour = (appointment.hour + 100 * increment);

// handle possible overflow
if (appointment.hour < 0) {
// change day to previous day if negative hour
appointment.weekDay = appointment.weekDay === 0 ? 6 : appointment.weekDay - 1;
appointment.hour += 2400;
} else if (appointment.hour >= 2400) {
// change day to next day if positive overflow
appointment.weekDay = (appointment.weekDay + 1) % 7;
appointment.hour %= 2400;
}

return appointment;
}
};

Expand Down Expand Up @@ -110,11 +79,6 @@ appointmentHelper.notify = () => new Promise(async (resolve) => {

nextAppointment = nextAppointment[0];

if (settings.appointmentsIncrement) {
// add global increment
nextAppointment = appointmentHelper.addIncrement(nextAppointment, settings.appointmentsIncrement);
}

// notification object for push message
const notification = {
title: 'Next Appointment',
Expand Down Expand Up @@ -144,51 +108,49 @@ appointmentHelper.notify = () => new Promise(async (resolve) => {
resolve('Notifications were send. Exiting.');
});


/**
* Find an appointment for the given date/time.
*
* @param {'Datable'} datetime The date, moment, date-string or 'now'
* @param {Date/Moment} datetime The date, moment, date-string or 'now'
* @param {number} toleranceBefore The minutes of tolerance before
* @param {number} toleranceAfter The minutes tolerance after
* @return The appointment object
*/
appointmentHelper.getAt = (datetime, toleranceBefore = 0, toleranceAfter = 0) => new Promise(async resolve => {
appointmentHelper.getNow = async (user, toleranceBefore = 5, toleranceAfter = 5) => {
if (!user) {
return null;
}

// load settings entity
const settings = await Settings.findOne();
let at = datetime === 'now'
? moment.tz(settings.appointmentsTimezone)
: moment(datetime);
let now = moment.tz(settings.appointmentsTimezone);

if (!at.isValid()) {
return resolve(null);
if (!now.isValid()) {
return null;
}

// apply increment
const increment = settings && settings.appointmentsIncrement
? settings.appointmentsIncrement
: 0;
at = at.subtract(increment, 'hours');

const minDate = at.clone().subtract(toleranceAfter, 'minutes');
const maxDate = at.clone().add(toleranceBefore, 'minutes');
const minDate = now.clone().subtract(toleranceAfter, 'minutes');
const maxDate = now.clone().add(toleranceBefore, 'minutes');

let doc = null;
if (minDate.weekday() !== maxDate.weekday()) {
// handle the case where the tolerance range
// includes two days
doc = await Appointment
.findOne({
user: user._id,
$or: [
{
weekDay: minDate.weekday(),
hour: {
$gte: timeToNumber(minDate)
$gte: appointmentHelper.timeToNumber(minDate)
}
},
{
weekDay: maxDate.weekday(),
hour: {
$lte: timeToNumber(maxDate)
$lte: appointmentHelper.timeToNumber(maxDate)
}
}
]
Expand All @@ -198,36 +160,18 @@ appointmentHelper.getAt = (datetime, toleranceBefore = 0, toleranceAfter = 0) =>
} else {
doc = await Appointment
.findOne({
user: user._id,
weekDay: minDate.weekday(),
hour: {
$gte: timeToNumber(minDate),
$lte: timeToNumber(maxDate)
$gte: appointmentHelper.timeToNumber(minDate),
$lte: appointmentHelper.timeToNumber(maxDate)
}
})
.populate('user', 'name username gravatarHash')
.exec();
}

resolve(appointmentHelper.addIncrement(doc, increment));
});

/**
* Searches for appointments the user is allowed to
* join right now. For regular users this means at
* the time of their booked appointment (with a 5 minute
* tolerance). For admins marked as teacher, it means
* within the timespan of 5 minutes before any appointment
* starts and 20 minutes after it was scheduled.
*
* @param {Object} user User that needs authorization
* @param {Boolean} reconnect If set to true, the time tolarance
* for regular users is the same as for
* admins.
*
* @return the appointment object
*/
appointmentHelper.getNowAuthorized = (user, reconnect = false) => appointmentHelper.getAt('now', 5,
reconnect || (user && user.role === 'ROLE_ADMIN' && user.appointmentsCallee === true) ? 25 : 8
);
return doc;
};

export default appointmentHelper;
Loading

0 comments on commit 95007df

Please sign in to comment.