From 5b08024859836667544ec61ea62e72cb6029a5bc Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 13 May 2014 14:01:22 -0700 Subject: [PATCH] Enhance the docs and fix the model type checking --- lib/models/application-credential.js | 37 ++++++----------- lib/models/user-identity.js | 60 ++++++++++++++++++---------- lib/models/utils.js | 38 ++++++++++++++++++ 3 files changed, 89 insertions(+), 46 deletions(-) create mode 100644 lib/models/utils.js diff --git a/lib/models/application-credential.js b/lib/models/application-credential.js index 3c7084fe..7e76f7a0 100644 --- a/lib/models/application-credential.js +++ b/lib/models/application-credential.js @@ -1,35 +1,14 @@ var DataModel = require('./data-model'); +var utils = require('./utils'); /*! * Default ApplicationCredential properties. */ - var properties = { provider: {type: String, required: true}, // facebook, google, twitter, linkedIn authScheme: {type: String}, // oAuth, oAuth 2.0, OpenID, OpenID Connect - /* - * oAuth: token, tokenSecret - * oAuth 2.0: accessToken, refreshToken - * OpenID: openId - * OpenID Connect: accessToken, refreshToken, profile - */ credentials: Object, - /* - openId: { - returnURL: String, - realm: String - }, - oAuth2: { - clientID: String, - clientSecret: String, - callbackURL: String - }, - oAuth: { - consumerKey: String, - consumerSecret: String, - callbackURL: String - }, - */ + // appId: String, // To be injected by belongsTo relation created: Date, modified: Date }; @@ -47,12 +26,22 @@ var options = { /** * Credentials associated with the LoopBack client application, such as oAuth 2.0 * client id/secret, or SSL keys + * + * **Properties** + * - {String} provider: The auth provider name, such as facebook, google, twitter, linkedin + * - {String} authScheme: The auth scheme, such as oAuth, oAuth 2.0, OpenID, OpenID Connect + * - {Object} credentials: The provider specific credentials + * - openId: {returnURL: String, realm: String} + * - oAuth2: {clientID: String, clientSecret: String, callbackURL: String} + * - oAuth: {consumerKey: String, consumerSecret: String, callbackURL: String} + * - {Date} created: The created date + * - {Date} modified: The last modified date */ var ApplicationCredential = DataModel.extend('ApplicationCredential', properties, options); module.exports = ApplicationCredential; ApplicationCredential.link = function (appId, provider, authScheme, credentials, cb) { - var appCredentialModel = (this instanceof ApplicationCredential) ? this : ApplicationCredential; + var appCredentialModel = utils.getModel(this, ApplicationCredential); appCredentialModel.findOne({where: { appId: appId, provider: provider diff --git a/lib/models/user-identity.js b/lib/models/user-identity.js index ee5666b7..0e7a9f3e 100644 --- a/lib/models/user-identity.js +++ b/lib/models/user-identity.js @@ -2,6 +2,7 @@ var loopback = require('../loopback'); var DataModel = require('./data-model'); var Role = require('./role').Role; var ACL = require('./acl').ACL; +var utils = require('./utils'); /*! * Default UserIdentity properties. @@ -12,12 +13,6 @@ var properties = { authScheme: {type: String}, // oAuth, oAuth 2.0, OpenID, OpenID Connect externalId: {type: String}, // The provider specific id profile: {type: Object}, - /* - * oAuth: token, tokenSecret - * oAuth 2.0: accessToken, refreshToken - * OpenID: openId - * OpenID Connect: accessToken, refreshToken, profile - */ credentials: {type: Object}, // userId: {type: String}, // Allow LoopBack to inject it based on the relation created: Date, @@ -48,22 +43,26 @@ var options = { /** * UserIdentity model keeps track of 3rd party logins/profiles + * + * **Properties** + * - {String} provider: The auth provider name, such as facebook, google, twitter, linkedin + * - {String} authScheme: The auth scheme, such as oAuth, oAuth 2.0, OpenID, OpenID Connect + * - {String} externalId: The provider specific user id + * - {Object} profile: The user profile, see http://passportjs.org/guide/profile + * - {Object} credentials + * - oAuth: token, tokenSecret + * - oAuth 2.0: accessToken, refreshToken + * - OpenID: openId + * - OpenID Connect: accessToken, refreshToken, profile + * - {*} userId: The LoopBack user id + * - {Date} created: The created date + * - {Date} modified: The last modified date + * + * @class + * @inherits {DataModel} */ var UserIdentity = DataModel.extend('UserIdentity', properties, options); -var crypto = require('crypto'); - -function generateKey(hmacKey, algorithm, encoding) { - hmacKey = hmacKey || 'loopback'; - algorithm = algorithm || 'sha1'; - encoding = encoding || 'hex'; - var hmac = crypto.createHmac(algorithm, hmacKey); - var buf = crypto.randomBytes(32); - hmac.update(buf); - var key = hmac.digest(encoding); - return key; -} - /** * Log in with a third party provider such as facebook or google * @param {String} provider The provider name @@ -76,7 +75,7 @@ function generateKey(hmacKey, algorithm, encoding) { * @param {Object} [identity] The user identity object */ UserIdentity.login = function (provider, authScheme, profile, credentials, cb) { - var userIdentityModel = (this instanceof UserIdentity) ? this : UserIdentity; + var userIdentityModel = utils.getModel(this, UserIdentity); userIdentityModel.findOne({where: { provider: provider, externalId: profile.id @@ -102,7 +101,7 @@ UserIdentity.login = function (provider, authScheme, profile, credentials, cb) { var email = profile.emails && profile.emails[0] && profile.emails[0].value; userModel.create({ username: provider + '.' + (profile.username || profile.id), - password: generateKey('password'), + password: utils.generateKey('password'), email: email }, function (err, user) { if (err) { @@ -127,6 +126,23 @@ UserIdentity.login = function (provider, authScheme, profile, credentials, cb) { /** * UserCredential model keeps track of 3rd party credentials for linked accounts + * + * **Properties** + * - {String} provider: The auth provider name, such as facebook, google, twitter, linkedin + * - {String} authScheme: The auth scheme, such as oAuth, oAuth 2.0, OpenID, OpenID Connect + * - {String} externalId: The provider specific user id + * - {Object} profile: The user profile, see http://passportjs.org/guide/profile + * - {Object} credentials + * - oAuth: token, tokenSecret + * - oAuth 2.0: accessToken, refreshToken + * - OpenID: openId + * - OpenID Connect: accessToken, refreshToken, profile + * - {*} userId: The LoopBack user id + * - {Date} created: The created date + * - {Date} modified: The last modified date + * + * @class + * @inherits {DataModel} */ var UserCredential = DataModel.extend('UserCredential', properties, options); @@ -141,7 +157,7 @@ var UserCredential = DataModel.extend('UserCredential', properties, options); * @param {Object} [credential] The user credential object */ UserCredential.link = function (userId, provider, authScheme, profile, credentials, cb) { - var userCredentialModel = (this instanceof UserCredential) ? this : UserCredential; + var userCredentialModel = utils.getModel(this, UserCredential); userCredentialModel.findOne({where: { userId: userId, provider: provider, diff --git a/lib/models/utils.js b/lib/models/utils.js new file mode 100644 index 00000000..bf1c729b --- /dev/null +++ b/lib/models/utils.js @@ -0,0 +1,38 @@ +/* + * Internal utilities for models + */ +var crypto = require('crypto'); + +/** + * Get the model class + * @param {Function} cls The sub class + * @param {Function} base The base class + * @returns {Function} The resolved class + */ +function getModel(cls, base) { + if (!cls) { + return base; + } + return (cls.prototype instanceof base)? cls: base; +} + +/** + * Generate a key + * @param {String} hmacKey The hmac key, default to 'loopback' + * @param {String} algorithm The algorithm, default to 'sha1' + * @param {String} encoding The string encoding, default to 'hex' + * @returns {String} The generated key + */ +function generateKey(hmacKey, algorithm, encoding) { + hmacKey = hmacKey || 'loopback'; + algorithm = algorithm || 'sha1'; + encoding = encoding || 'hex'; + var hmac = crypto.createHmac(algorithm, hmacKey); + var buf = crypto.randomBytes(32); + hmac.update(buf); + var key = hmac.digest(encoding); + return key; +} + +exports.getModel = getModel; +exports.generateKey = generateKey; \ No newline at end of file