diff --git a/lib/auth/authStore.js b/lib/auth/authStore.js index f7743cc..c96d7a0 100644 --- a/lib/auth/authStore.js +++ b/lib/auth/authStore.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _bcrypt=_interopRequireDefault(require("bcrypt")),_v=_interopRequireDefault(require("uuid/v4")),_authStoreInitializer=_interopRequireDefault(require("./authStoreInitializer"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _slicedToArray(e,r){return _arrayWithHoles(e)||_iterableToArrayLimit(e,r)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function _iterableToArrayLimit(e,r){var t=[],n=!0,a=!1,s=void 0;try{for(var u,o=e[Symbol.iterator]();!(n=(u=o.next()).done)&&(t.push(u.value),!r||t.length!==r);n=!0);}catch(e){a=!0,s=e}finally{try{n||null==o.return||o.return()}finally{if(a)throw s}}return t}function _arrayWithHoles(e){if(Array.isArray(e))return e}function _objectSpread(r){for(var e=1;e","suspended").query();case 3:if(a=e.sent,s=a.length&&a[0],e.t0=s,e.t0)return e.next=9,_bcrypt.default.compare(n,s.password);e.next=10;break;case 9:e.t0=e.sent;case 10:if(e.t0)return e.abrupt("return",_objectSpread({},l.getIdentity(s),{status:s.status}));e.next=12;break;case 12:case"end":return e.stop()}},e,this)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"changePassword",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t,n,a,s,u;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,n=r.password,a=r.status,e.next=3,_bcrypt.default.hash(n,saltRounds);case 3:return s=e.sent,e.next=6,l.Login.where({userId:t}).fetch();case 6:return u=e.sent,e.next=9,u.save({password:s,version:(0,_v.default)(),status:a||"active"},{patch:!0});case 9:case"end":return e.stop()}},e,this)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"enableUser",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,e.abrupt("return",l._setUserStatus({userId:t,status:"active"}));case 2:case"end":return e.stop()}},e,this)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"suspendUser",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,e.abrupt("return",l._setUserStatus({userId:t,status:"suspended"}));case 2:case"end":return e.stop()}},e,this)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"_setUserStatus",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t,n,a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,n=r.status,e.prev=1,e.next=4,l.Login.where({userId:t}).fetch();case 4:return a=e.sent,e.next=7,a.save({status:n,version:(0,_v.default)()},{patch:!0});case 7:e.next=13;break;case 9:throw e.prev=9,e.t0=e.catch(1),console.log("Error setting user status",e.t0),e.t0;case 13:case"end":return e.stop()}},e,this,[[1,9]])}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"count",function(){return l.Login.count()})};function merge(){var e=0","suspended").query();case 3:if(a=e.sent,s=a.length&&a[0],e.t0=s,e.t0)return e.next=9,_bcrypt.default.compare(n,s.password);e.next=10;break;case 9:e.t0=e.sent;case 10:if(e.t0)return e.abrupt("return",_objectSpread({},p.getIdentity(s),{status:s.status}));e.next=12;break;case 12:case"end":return e.stop()}},e)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"changePassword",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t,n,a,s,u;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,n=r.password,a=r.status,e.next=3,_bcrypt.default.hash(n,saltRounds);case 3:return s=e.sent,e.next=6,p.Login.where({userId:t}).fetch();case 6:return u=e.sent,e.next=9,u.save({password:s,version:(0,_v.default)(),status:a||"active"},{patch:!0});case 9:case"end":return e.stop()}},e)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"enableUser",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,e.abrupt("return",p._setUserStatus({userId:t,status:"active"}));case 2:case"end":return e.stop()}},e)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"suspendUser",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,e.abrupt("return",p._setUserStatus({userId:t,status:"suspended"}));case 2:case"end":return e.stop()}},e)}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"_setUserStatus",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(r){var t,n,a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t=r.userId,n=r.status,e.prev=1,e.next=4,p.Login.where({userId:t}).fetch();case 4:return a=e.sent,e.next=7,a.save({status:n,version:(0,_v.default)()},{patch:!0});case 7:e.next=13;break;case 9:throw e.prev=9,e.t0=e.catch(1),console.log("Error setting user status",e.t0),e.t0;case 13:case"end":return e.stop()}},e,null,[[1,9]])}));return function(e){return r.apply(this,arguments)}}()),_defineProperty(this,"count",function(){return p.Login.count()})};function merge(){var e=0",a.version)),e.next=18,s.orderBy("sequenceNumber","asc").query();case 18:return e.t3=function(e){return i.mapper.fromStoredEvent(e)},e.t4=e.sent.map(e.t3),e.t5=a&&{version:a.version,body:JSON.parse(a.body)},e.abrupt("return",{events:e.t4,snapshot:e.t5});case 24:throw e.prev=24,e.t6=e.catch(1),console.log("Error loading events: Aggregate ".concat(r," ").concat(n),e.t6),e.t6;case 28:case"end":return e.stop()}},e,this,[[1,24]])}));return function(e){return t.apply(this,arguments)}}()),_defineProperty(this,"record",function(){var t=_asyncToGenerator(regeneratorRuntime.mark(function e(t){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,(0,_eachSeries.default)(t,function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(t,r){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,i.recordEvent(t);case 2:r();case 3:case"end":return e.stop()}},e,this)}));return function(e,t){return r.apply(this,arguments)}}());case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e,this)}));return function(e){return t.apply(this,arguments)}}()),_defineProperty(this,"recordEvent",function(){var t=_asyncToGenerator(regeneratorRuntime.mark(function e(t){var r;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return r=i.mapper.toStoredEvent(t),e.prev=1,e.t0=i.mapper,e.next=5,new i.Event(r).save();case 5:return e.t1=e.sent.toJSON(),e.abrupt("return",e.t0.fromStoredEvent.call(e.t0,e.t1));case 9:throw e.prev=9,e.t2=e.catch(1),console.log("Failed to save event",e.t2),e.t2;case 13:case"end":return e.stop()}},e,this,[[1,9]])}));return function(e){return t.apply(this,arguments)}}()),_defineProperty(this,"count",function(){return i.Event.count()}),_defineProperty(this,"saveSnapshot",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(t,r){var n,o,a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return n=r.id,o=r.version,a=_objectWithoutProperties(r,["id","version"]),e.next=3,new i.Snapshot({aggregate:t,aggregateId:n,version:o,body:JSON.stringify(a)}).save();case 3:case"end":return e.stop()}},e,this)}));return function(e,t){return r.apply(this,arguments)}}()),this.mapper=r,this.Event=(0,_bookshelf.default)(n.knex("eventstore")).Model.extend({tableName:"events"}),this.Snapshot=(0,_bookshelf.default)(n.knex("eventstore")).Model.extend({tableName:"snapshots"})};exports.default=EventStore; +"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _eachSeries=_interopRequireDefault(require("async/eachSeries")),_bookshelf=_interopRequireDefault(require("bookshelf"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _objectWithoutProperties(e,t){if(null==e)return{};var r,n,o=_objectWithoutPropertiesLoose(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n",a.version)),e.next=18,s.orderBy("sequenceNumber","asc").query();case 18:return e.t3=function(e){return u.mapper.fromStoredEvent(e)},e.t4=e.sent.map(e.t3),e.t5=a&&{version:a.version,body:JSON.parse(a.body)},e.abrupt("return",{events:e.t4,snapshot:e.t5});case 24:throw e.prev=24,e.t6=e.catch(1),console.log("Error loading events: Aggregate ".concat(r," ").concat(n),e.t6),e.t6;case 28:case"end":return e.stop()}},e,null,[[1,24]])}));return function(e){return t.apply(this,arguments)}}()),_defineProperty(this,"record",function(){var t=_asyncToGenerator(regeneratorRuntime.mark(function e(t){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,(0,_eachSeries.default)(t,function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(t,r){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u.recordEvent(t);case 2:r();case 3:case"end":return e.stop()}},e)}));return function(e,t){return r.apply(this,arguments)}}());case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e)}));return function(e){return t.apply(this,arguments)}}()),_defineProperty(this,"recordEvent",function(){var t=_asyncToGenerator(regeneratorRuntime.mark(function e(t){var r;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return r=u.mapper.toStoredEvent(t),e.prev=1,e.t0=u.mapper,e.next=5,new u.Event(r).save();case 5:return e.t1=e.sent.toJSON(),e.abrupt("return",e.t0.fromStoredEvent.call(e.t0,e.t1));case 9:throw e.prev=9,e.t2=e.catch(1),console.log("Failed to save event",e.t2),e.t2;case 13:case"end":return e.stop()}},e,null,[[1,9]])}));return function(e){return t.apply(this,arguments)}}()),_defineProperty(this,"count",function(){return u.Event.count()}),_defineProperty(this,"saveSnapshot",function(){var r=_asyncToGenerator(regeneratorRuntime.mark(function e(t,r){var n,o,a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return n=r.id,o=r.version,a=_objectWithoutProperties(r,["id","version"]),e.next=3,new u.Snapshot({aggregate:t,aggregateId:n,version:o,body:JSON.stringify(a)}).save();case 3:case"end":return e.stop()}},e)}));return function(e,t){return r.apply(this,arguments)}}()),this.mapper=r,this.Event=(0,_bookshelf.default)(n.knex("eventstore")).Model.extend({tableName:"events"}),this.Snapshot=(0,_bookshelf.default)(n.knex("eventstore")).Model.extend({tableName:"snapshots"})};exports.default=EventStore; //# sourceMappingURL=../maps/eventing/eventStore.js.map diff --git a/lib/eventing/eventStoreInitializer.js b/lib/eventing/eventStoreInitializer.js index 454132b..3d76ca9 100644 --- a/lib/eventing/eventStoreInitializer.js +++ b/lib/eventing/eventStoreInitializer.js @@ -1,2 +1,2 @@ -"use strict";function asyncGeneratorStep(e,t,n,r,a,o,s){try{var i=e[o](s),l=i.value}catch(e){return void n(e)}i.done?t(l):Promise.resolve(l).then(r,a)}function _asyncToGenerator(i){return function(){var e=this,s=arguments;return new Promise(function(t,n){var r=i.apply(e,s);function a(e){asyncGeneratorStep(r,t,n,a,o,"next",e)}function o(e){asyncGeneratorStep(r,t,n,a,o,"throw",e)}a(void 0)})}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var EventStoreInitializer=function e(){_classCallCheck(this,e)};_defineProperty(exports.default=EventStoreInitializer,"assureEventsTable",function(){var t=_asyncToGenerator(regeneratorRuntime.mark(function e(t){var n;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t.knex().raw("CREATE DATABASE IF NOT EXISTS `eventstore`");case 2:return n=t.knex("eventstore"),e.next=5,n.schema.hasTable("events");case 5:if(e.sent){e.next=8;break}return e.next=8,n.schema.createTable("events",function(e){e.bigIncrements("id").primary().notNullable(),e.string("aggregate",255).notNullable(),e.string("aggregateId",36).notNullable(),e.string("type",255).notNullable(),e.integer("sequenceNumber").notNullable(),e.dateTime("timestamp").defaultTo(n.raw("now()")),e.string("actor",255).notNullable(),e.text("position"),e.text("body").notNullable(),e.unique(["aggregateId","aggregate","sequenceNumber"])});case 8:return e.next=10,n.schema.hasTable("snapshots");case 10:if(e.sent){e.next=13;break}return e.next=13,n.schema.createTable("snapshots",function(e){e.bigIncrements("id").primary().notNullable(),e.string("aggregate",255).notNullable(),e.string("aggregateId",36).notNullable(),e.integer("version").notNullable(),e.dateTime("timestamp").defaultTo(n.raw("now()")),e.text("body","longtext").notNullable(),e.unique(["aggregateId","aggregate","version"])});case 13:case"end":return e.stop()}},e,this)}));return function(e){return t.apply(this,arguments)}}()); +"use strict";function asyncGeneratorStep(e,t,n,r,a,o,s){try{var i=e[o](s),l=i.value}catch(e){return void n(e)}i.done?t(l):Promise.resolve(l).then(r,a)}function _asyncToGenerator(i){return function(){var e=this,s=arguments;return new Promise(function(t,n){var r=i.apply(e,s);function a(e){asyncGeneratorStep(r,t,n,a,o,"next",e)}function o(e){asyncGeneratorStep(r,t,n,a,o,"throw",e)}a(void 0)})}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var EventStoreInitializer=function e(){_classCallCheck(this,e)};_defineProperty(exports.default=EventStoreInitializer,"assureEventsTable",function(){var t=_asyncToGenerator(regeneratorRuntime.mark(function e(t){var n;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t.knex().raw("CREATE DATABASE IF NOT EXISTS `eventstore`");case 2:return n=t.knex("eventstore"),e.next=5,n.schema.hasTable("events");case 5:if(e.sent){e.next=8;break}return e.next=8,n.schema.createTable("events",function(e){e.bigIncrements("id").primary().notNullable(),e.string("aggregate",255).notNullable(),e.string("aggregateId",36).notNullable(),e.string("type",255).notNullable(),e.integer("sequenceNumber").notNullable(),e.dateTime("timestamp").defaultTo(n.raw("now()")),e.string("actor",255).notNullable(),e.text("position"),e.text("body").notNullable(),e.unique(["aggregateId","aggregate","sequenceNumber"])});case 8:return e.next=10,n.schema.hasTable("snapshots");case 10:if(e.sent){e.next=13;break}return e.next=13,n.schema.createTable("snapshots",function(e){e.bigIncrements("id").primary().notNullable(),e.string("aggregate",255).notNullable(),e.string("aggregateId",36).notNullable(),e.integer("version").notNullable(),e.dateTime("timestamp").defaultTo(n.raw("now()")),e.text("body","longtext").notNullable(),e.unique(["aggregateId","aggregate","version"])});case 13:case"end":return e.stop()}},e)}));return function(e){return t.apply(this,arguments)}}()); //# sourceMappingURL=../maps/eventing/eventStoreInitializer.js.map diff --git a/lib/initialize.js b/lib/initialize.js index 5bd1cf0..59585e1 100644 --- a/lib/initialize.js +++ b/lib/initialize.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _awsSdk=_interopRequireDefault(require("aws-sdk")),_koaPassport=_interopRequireDefault(require("koa-passport")),_amqplib=_interopRequireDefault(require("amqplib")),_authenticationRouter=_interopRequireDefault(require("./routing/authenticationRouter")),_commandRouter=_interopRequireDefault(require("./routing/commandRouter")),_injectEventRouter=_interopRequireDefault(require("./routing/injectEventRouter")),_identityMiddleware=_interopRequireDefault(require("./routing/identityMiddleware")),_commandExecutor=_interopRequireDefault(require("./commandHandling/commandExecutor")),_webCommandHandler=_interopRequireDefault(require("./commandHandling/webCommandHandler")),_passwordCommandHandler=_interopRequireDefault(require("./commandHandling/passwordCommandHandler")),_domainCommandDeliverer=_interopRequireDefault(require("./commandHandling/domainCommandDeliverer")),_eventing=require("./eventing"),_services=require("./services"),_authTokenMapper=_interopRequireDefault(require("./auth/authTokenMapper")),_authStore=_interopRequireDefault(require("./auth/authStore")),_nodeCqrsLib=require("@facetdev/node-cqrs-lib"),_domainServices=_interopRequireDefault(require("./scheduling/domainServices"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _objectSpread(r){for(var e=1;e claims, status = 'active' }) => { + addUser = async ({ userId, username, password, claims, updateClaims = claims => claims }) => { try { let hashedPassword = await bcrypt.hash(password, saltRounds); - let user = (await this.Login.where({ username }).fetch({ columns: ['id', 'userId', 'username', 'claims'] })); + // Determine if user already exists for update or creation. + let user = await this.Login.where({ username }).fetch({ columns: ['id', 'userId', 'username', 'claims', 'status'] }); + let status; if (!user) { - console.log('adding new user', username); + // No records, create new user + status = 'onboard'; await new this.Login().save({ userId, username, password: hashedPassword, claims: JSON.stringify({ ...claims, ...updateClaims({}) }), version: uuidV4(), status }); } else { - console.log('updating user', username); + // User exists, so set their status back to active from a suspension. + // Or, we are inviting user to a second organization. + + // Get users current status to determine if coming off a suspension or being re-invited to new organization. + status = user.attributes.status; await user.save({ userId, claims: JSON.stringify({ ...user.get('claims'), ...claims, ...updateClaims(user.get('claims') || {}) } || {}), + status: 'active', version: uuidV4() }, { patch: true }); } + return { status }; } catch (e) { console.log('Failed to add login', e); @@ -58,7 +67,11 @@ export default class AuthStore { } removeUser = async ({ userId }) => { - let user = await this.Login.where({ userId }).fetch({ columns: ['id', 'userId', 'claims'] }); + let user = await this.Login.where({ userId }).fetch({ columns: ['id', 'userId', 'claims', 'status'] }); + // NOTE: If removing a user that hasn't yet accepted their invite, just remove from db all together as they will never be able to login because initial random password is lost. + if (user.attributes.status === 'onboard') { + return this.Login.where({ userId: user.attributes.userId }).destroy(); + } await user.save({ userId, status: 'suspended', @@ -67,7 +80,11 @@ export default class AuthStore { } removeUserFromOrg = async ({ organizationId, userId }) => { - let user = await this.Login.where({ userId }).fetch({ columns: ['id', 'userId', 'claims'] }); + let user = await this.Login.where({ userId }).fetch({ columns: ['id', 'userId', 'claims', 'status'] }); + // NOTE: If removing a user that hasn't yet accepted their invite, just remove from db all together as they will never be able to login because initial random password is lost. + if (user.attributes.status === 'onboard') { + return this.Login.where({ userId: user.attributes.userId }).destroy(); + } const organizations = { ...user.get('claims').organizations };