diff --git a/common/models/user.js b/common/models/user.js index 69b36b1b0b..74285aaba9 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -483,6 +483,12 @@ module.exports = function(User) { } ); + User.prototype.createAuthToken = function createAuthToken({ ttl } = {}) { + return Observable.fromNodeCallback( + this.authTokens.create.bind(this.authTokens) + )({ ttl }); + }; + User.prototype.getEncodedEmail = function getEncodedEmail() { if (!this.email) { return null; @@ -506,7 +512,7 @@ module.exports = function(User) { } // create a temporary access token with ttl for 15 minutes - return this.createAccessToken$({ ttl: 15 * 60 * 1000 }); + return this.createAuthToken({ ttl: 15 * 60 * 1000 }); }) .flatMap(token => { let renderAuthEmail = renderSignInEmail; diff --git a/common/models/user.json b/common/models/user.json index 66b8f5ed8a..9869f06faa 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -288,6 +288,14 @@ "type": "hasOne", "model": "pledge", "foreignKey": "" + }, + "authTokens": { + "type": "hasMany", + "model": "AuthToken", + "foreignKey": "userId", + "options": { + "disableInclude": true + } } }, "acls": [ diff --git a/server/boot/authentication.js b/server/boot/authentication.js index 0b52df3299..abc5846ffe 100644 --- a/server/boot/authentication.js +++ b/server/boot/authentication.js @@ -21,7 +21,7 @@ module.exports = function enableAuthentication(app) { const ifUserRedirect = ifUserRedirectTo(); const router = app.loopback.Router(); const api = app.loopback.Router(); - const { AccessToken, User } = app.models; + const { AuthToken, User } = app.models; router.get('/login', (req, res) => res.redirect(301, '/signin')); router.get('/logout', (req, res) => res.redirect(301, '/signout')); @@ -99,7 +99,7 @@ module.exports = function enableAuthentication(app) { )); } // first find - return AccessToken.findOne$({ where: { id: authTokenId } }) + return AuthToken.findOne$({ where: { id: authTokenId } }) .flatMap(authToken => { if (!authToken) { throw wrapHandledError( @@ -135,7 +135,7 @@ module.exports = function enableAuthentication(app) { } ); } - return authToken.validate$() + return authToken.validate() .map(isValid => { if (!isValid) { throw wrapHandledError( @@ -150,7 +150,7 @@ module.exports = function enableAuthentication(app) { } ); } - return authToken.destroy$(); + return authToken.destroy(); }) .map(() => user); }); diff --git a/server/model-config.json b/server/model-config.json index 4cc2d87ccf..4acea9fdba 100644 --- a/server/model-config.json +++ b/server/model-config.json @@ -78,5 +78,9 @@ "about": { "dataSource": "db", "public": true + }, + "AuthToken": { + "dataSource": "db", + "public": false } } diff --git a/server/models/auth-token.js b/server/models/auth-token.js new file mode 100644 index 0000000000..11200da184 --- /dev/null +++ b/server/models/auth-token.js @@ -0,0 +1,15 @@ +import { Observable } from 'rx'; + +export default function(AuthToken) { + AuthToken.on('dataSourceAttached', () => { + AuthToken.findOne$ = Observable.fromNodeCallback( + AuthToken.findOne.bind(AuthToken) + ); + AuthToken.prototype.validate = Observable.fromNodeCallback( + AuthToken.prototype.validate + ); + AuthToken.prototype.destroy = Observable.fromNodeCallback( + AuthToken.prototype.destroy + ); + }); +} diff --git a/server/models/auth-token.json b/server/models/auth-token.json new file mode 100644 index 0000000000..be263f3932 --- /dev/null +++ b/server/models/auth-token.json @@ -0,0 +1,13 @@ +{ + "name": "AuthToken", + "base": "AccessToken", + "idInjection": true, + "options": { + "validateUpsert": true + }, + "properties": {}, + "validations": [], + "relations": {}, + "acls": [], + "methods": {} +}