diff --git a/src/backend/app.js b/src/backend/app.js index 40ead9c2..59f00e6b 100644 --- a/src/backend/app.js +++ b/src/backend/app.js @@ -84,7 +84,11 @@ app.use(function (err, req, res, next) { // Not every error is worth logging - but this is good for now until it gets annoying. if (typeof err.stack !== 'undefined' && err.stack) { - log.warn(err.stack); + if (process.env.NODE_ENV === 'development') { + log.warn(err.stack); + } else { + log.warn(err.message); + } } res diff --git a/src/backend/internal/user.js b/src/backend/internal/user.js index 75fe8973..9d6abb85 100644 --- a/src/backend/internal/user.js +++ b/src/backend/internal/user.js @@ -19,7 +19,7 @@ const internalUser = { * @returns {Promise} */ create: (access, data) => { - let auth = data.auth; + let auth = data.auth || null; delete data.auth; data.avatar = data.avatar || ''; @@ -38,21 +38,25 @@ const internalUser = { .omit(omissions()) .insertAndFetch(data); }) + .then(user => { + if (auth) { + return authModel + .query() + .insert({ + user_id: user.id, + type: auth.type, + secret: auth.secret, + meta: {} + }) + .then(() => { + return user; + }); + } else { + return user; + } + }) .then(user => { return internalUser.get(access, {id: user.id}); - /* - return authModel - .query() - .insert({ - user_id: user.id, - type: auth.type, - secret: auth.secret, - meta: {} - }) - .then(() => { - return internalUser.get(access, {id: user.id}); - }); - */ }); }, @@ -60,6 +64,7 @@ const internalUser = { * @param {Access} access * @param {Object} data * @param {Integer} data.id + * @param {String} [data.email] * @param {String} [data.name] * @return {Promise} */ @@ -337,17 +342,38 @@ const internalUser = { return user; }) .then(user => { + // Get auth, patch if it exists return authModel .query() .where('user_id', user.id) .andWhere('type', data.type) - .patch({ - type: data.type, - secret: data.secret - }) - .then(() => { - return true; + .first() + .then(existing_auth => { + if (existing_auth) { + // patch + return authModel + .query() + .where('user_id', user.id) + .andWhere('type', data.type) + .patch({ + type: data.type, // This is required for the model to encrypt on save + secret: data.secret + }); + } else { + // insert + return authModel + .query() + .insert({ + user_id: user.id, + type: data.type, + secret: data.secret, + meta: {} + }); + } }); + }) + .then(() => { + return true; }); }, diff --git a/src/frontend/js/app/controller.js b/src/frontend/js/app/controller.js index 2802d596..19738f23 100644 --- a/src/frontend/js/app/controller.js +++ b/src/frontend/js/app/controller.js @@ -52,6 +52,19 @@ module.exports = { } }, + /** + * User Password Form + * + * @param model + */ + showUserPasswordForm: function (model) { + if (Cache.User.isAdmin() || model.get('id') === Cache.User.get('id')) { + require(['./main', './user/password'], function (App, View) { + App.UI.showModalDialog(new View({model: model})); + }); + } + }, + /** * Error * diff --git a/src/frontend/js/app/ui/menu/main.ejs b/src/frontend/js/app/ui/menu/main.ejs index bdb065fe..0cd83c39 100644 --- a/src/frontend/js/app/ui/menu/main.ejs +++ b/src/frontend/js/app/ui/menu/main.ejs @@ -2,59 +2,23 @@
diff --git a/src/frontend/js/app/user/password.ejs b/src/frontend/js/app/user/password.ejs new file mode 100644 index 00000000..3a9c69c2 --- /dev/null +++ b/src/frontend/js/app/user/password.ejs @@ -0,0 +1,30 @@ + diff --git a/src/frontend/js/app/user/password.js b/src/frontend/js/app/user/password.js new file mode 100644 index 00000000..b98e0219 --- /dev/null +++ b/src/frontend/js/app/user/password.js @@ -0,0 +1,63 @@ +'use strict'; + +const Mn = require('backbone.marionette'); +const template = require('./password.ejs'); +const Controller = require('../controller'); +const Api = require('../api'); +const App = require('../main'); +const Cache = require('../cache'); + +require('jquery-serializejson'); + +module.exports = Mn.View.extend({ + template: template, + className: 'modal-dialog', + + ui: { + form: 'form', + buttons: '.modal-footer button', + cancel: 'button.cancel', + save: 'button.save', + error: '.secret-error' + }, + + events: { + 'click @ui.save': function (e) { + e.preventDefault(); + this.ui.error.hide(); + let form = this.ui.form.serializeJSON(); + + if (form.new_password1 !== form.new_password2) { + this.ui.error.text('Passwords do not match!').show(); + return; + } + + let data = { + type: 'password', + current: form.current_password, + secret: form.new_password1 + }; + + this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); + Api.Users.setPassword(this.model.get('id'), data) + .then(() => { + App.UI.closeModal(); + Controller.showUsers(); + }) + .catch(err => { + this.ui.error.text(err.message).show(); + this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); + }); + } + }, + + isSelf: function () { + return Cache.User.get('id') === this.model.get('id'); + }, + + templateContext: function () { + return { + isSelf: this.isSelf.bind(this) + }; + } +}); diff --git a/src/frontend/js/app/users/list/item.ejs b/src/frontend/js/app/users/list/item.ejs index b83f03dc..2b1e3dd0 100644 --- a/src/frontend/js/app/users/list/item.ejs +++ b/src/frontend/js/app/users/list/item.ejs @@ -6,7 +6,7 @@
<%- name %>
- Created: Mar 19, 2018 + Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
diff --git a/src/frontend/js/app/users/list/item.js b/src/frontend/js/app/users/list/item.js index a74bbde2..8b0994b4 100644 --- a/src/frontend/js/app/users/list/item.js +++ b/src/frontend/js/app/users/list/item.js @@ -26,7 +26,7 @@ module.exports = Mn.View.extend({ 'click @ui.password': function (e) { e.preventDefault(); - //Controller.showUserPasswordForm(this.model); + Controller.showUserPasswordForm(this.model); }, 'click @ui.delete': function (e) { diff --git a/src/frontend/js/lib/marionette.js b/src/frontend/js/lib/marionette.js index 810defe4..bdb84f11 100644 --- a/src/frontend/js/lib/marionette.js +++ b/src/frontend/js/lib/marionette.js @@ -39,15 +39,21 @@ Mn.Renderer.render = function (template, data, view) { * @param {String} date * @returns {String} */ - data.shortDate = function (date) { - let shortdate = ''; - + data.formatDbDate = function (date, format) { if (typeof date === 'number') { - shortdate = moment.unix(date).format('YYYY-MM-DD'); - } else { - shortdate = moment(date).format('YYYY-MM-DD'); + return moment.unix(date).format(format); } + return moment(date).format(format); + }; + + /** + * @param {String} date + * @returns {String} + */ + data.shortDate = function (date) { + let shortdate = data.formatDbDate(date, 'YYYY-MM-DD'); + return moment().format('YYYY-MM-DD') === shortdate ? 'Today' : shortdate; }; @@ -56,15 +62,7 @@ Mn.Renderer.render = function (template, data, view) { * @returns {String} */ data.shortTime = function (date) { - let shorttime = ''; - - if (typeof date === 'number') { - shorttime = moment.unix(date).format('H:mm A'); - } else { - shorttime = moment(date).format('H:mm A'); - } - - return shorttime; + return data.formatDbDate(date, 'H:mm A'); }; /** diff --git a/src/frontend/js/login/ui/login.ejs b/src/frontend/js/login/ui/login.ejs index 991d42f2..da584687 100644 --- a/src/frontend/js/login/ui/login.ejs +++ b/src/frontend/js/login/ui/login.ejs @@ -9,9 +9,7 @@
- +