mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
WIP: move all the code
This commit is contained in:
31
packages/node_modules/@node-red/editor/lib/auth/clients.js
generated
vendored
Normal file
31
packages/node_modules/@node-red/editor/lib/auth/clients.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var clients = [
|
||||
{id:"node-red-editor",secret:"not_available"},
|
||||
{id:"node-red-admin",secret:"not_available"}
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
get: function(id) {
|
||||
for (var i=0;i<clients.length;i++) {
|
||||
if (clients[i].id == id) {
|
||||
return Promise.resolve(clients[i]);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
211
packages/node_modules/@node-red/editor/lib/auth/index.js
generated
vendored
Normal file
211
packages/node_modules/@node-red/editor/lib/auth/index.js
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var passport = require("passport");
|
||||
var oauth2orize = require("oauth2orize");
|
||||
|
||||
var strategies = require("./strategies");
|
||||
var Tokens = require("./tokens");
|
||||
var Users = require("./users");
|
||||
var permissions = require("./permissions");
|
||||
|
||||
var theme = require("../editor/theme");
|
||||
|
||||
var settings = null;
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
|
||||
|
||||
passport.use(strategies.bearerStrategy.BearerStrategy);
|
||||
passport.use(strategies.clientPasswordStrategy.ClientPasswordStrategy);
|
||||
passport.use(strategies.anonymousStrategy);
|
||||
|
||||
var server = oauth2orize.createServer();
|
||||
|
||||
server.exchange(oauth2orize.exchange.password(strategies.passwordTokenExchange));
|
||||
|
||||
function init(_settings,storage) {
|
||||
settings = _settings;
|
||||
if (settings.adminAuth) {
|
||||
Users.init(settings.adminAuth);
|
||||
Tokens.init(settings.adminAuth,storage);
|
||||
}
|
||||
}
|
||||
|
||||
function needsPermission(permission) {
|
||||
return function(req,res,next) {
|
||||
if (settings && settings.adminAuth) {
|
||||
return passport.authenticate(['bearer','anon'],{ session: false })(req,res,function() {
|
||||
if (!req.user) {
|
||||
return next();
|
||||
}
|
||||
if (permissions.hasPermission(req.authInfo.scope,permission)) {
|
||||
return next();
|
||||
}
|
||||
log.audit({event: "permission.fail", permissions: permission},req);
|
||||
return res.status(401).end();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ensureClientSecret(req,res,next) {
|
||||
if (!req.body.client_secret) {
|
||||
req.body.client_secret = 'not_available';
|
||||
}
|
||||
next();
|
||||
}
|
||||
function authenticateClient(req,res,next) {
|
||||
return passport.authenticate(['oauth2-client-password'], {session: false})(req,res,next);
|
||||
}
|
||||
function getToken(req,res,next) {
|
||||
return server.token()(req,res,next);
|
||||
}
|
||||
|
||||
function login(req,res) {
|
||||
var response = {};
|
||||
if (settings.adminAuth) {
|
||||
if (settings.adminAuth.type === "credentials") {
|
||||
response = {
|
||||
"type":"credentials",
|
||||
"prompts":[{id:"username",type:"text",label:"user.username"},{id:"password",type:"password",label:"user.password"}]
|
||||
}
|
||||
} else if (settings.adminAuth.type === "strategy") {
|
||||
|
||||
var urlPrefix = (settings.httpAdminRoot==='/')?"":settings.httpAdminRoot;
|
||||
response = {
|
||||
"type":"strategy",
|
||||
"prompts":[{type:"button",label:settings.adminAuth.strategy.label, url: urlPrefix + "auth/strategy"}]
|
||||
}
|
||||
if (settings.adminAuth.strategy.icon) {
|
||||
response.prompts[0].icon = settings.adminAuth.strategy.icon;
|
||||
}
|
||||
if (settings.adminAuth.strategy.image) {
|
||||
response.prompts[0].image = theme.serveFile('/login/',settings.adminAuth.strategy.image);
|
||||
}
|
||||
}
|
||||
if (theme.context().login && theme.context().login.image) {
|
||||
response.image = theme.context().login.image;
|
||||
}
|
||||
}
|
||||
res.json(response);
|
||||
}
|
||||
|
||||
function revoke(req,res) {
|
||||
var token = req.body.token;
|
||||
// TODO: audit log
|
||||
Tokens.revoke(token).then(function() {
|
||||
log.audit({event: "auth.login.revoke"},req);
|
||||
if (settings.editorTheme && settings.editorTheme.logout && settings.editorTheme.logout.redirect) {
|
||||
res.json({redirect:settings.editorTheme.logout.redirect});
|
||||
} else {
|
||||
res.status(200).end();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function completeVerify(profile,done) {
|
||||
Users.authenticate(profile).then(function(user) {
|
||||
if (user) {
|
||||
Tokens.create(user.username,"node-red-editor",user.permissions).then(function(tokens) {
|
||||
log.audit({event: "auth.login",username:user.username,scope:user.permissions});
|
||||
user.tokens = tokens;
|
||||
done(null,user);
|
||||
});
|
||||
} else {
|
||||
log.audit({event: "auth.login.fail.oauth",username:typeof profile === "string"?profile:profile.username});
|
||||
done(null,false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function genericStrategy(adminApp,strategy) {
|
||||
var crypto = require("crypto")
|
||||
var session = require('express-session')
|
||||
var MemoryStore = require('memorystore')(session)
|
||||
|
||||
adminApp.use(session({
|
||||
// As the session is only used across the life-span of an auth
|
||||
// hand-shake, we can use a instance specific random string
|
||||
secret: crypto.randomBytes(20).toString('hex'),
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
store: new MemoryStore({
|
||||
checkPeriod: 86400000 // prune expired entries every 24h
|
||||
})
|
||||
}));
|
||||
//TODO: all passport references ought to be in ./auth
|
||||
adminApp.use(passport.initialize());
|
||||
adminApp.use(passport.session());
|
||||
|
||||
var options = strategy.options;
|
||||
|
||||
passport.use(new strategy.strategy(options,
|
||||
function() {
|
||||
var originalDone = arguments[arguments.length-1];
|
||||
if (options.verify) {
|
||||
var args = Array.from(arguments);
|
||||
args[args.length-1] = function(err,profile) {
|
||||
if (err) {
|
||||
return originalDone(err);
|
||||
} else {
|
||||
return completeVerify(profile,originalDone);
|
||||
}
|
||||
};
|
||||
options.verify.apply(null,args);
|
||||
} else {
|
||||
var profile = arguments[arguments.length - 2];
|
||||
return completeVerify(profile,originalDone);
|
||||
}
|
||||
|
||||
}
|
||||
));
|
||||
|
||||
adminApp.get('/auth/strategy',
|
||||
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
|
||||
completeGenerateStrategyAuth
|
||||
);
|
||||
adminApp.get('/auth/strategy/callback',
|
||||
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
|
||||
completeGenerateStrategyAuth
|
||||
);
|
||||
|
||||
}
|
||||
function completeGenerateStrategyAuth(req,res) {
|
||||
var tokens = req.user.tokens;
|
||||
delete req.user.tokens;
|
||||
// Successful authentication, redirect home.
|
||||
res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
needsPermission: needsPermission,
|
||||
ensureClientSecret: ensureClientSecret,
|
||||
authenticateClient: authenticateClient,
|
||||
getToken: getToken,
|
||||
errorHandler: function(err,req,res,next) {
|
||||
//TODO: audit log statment
|
||||
//console.log(err.stack);
|
||||
//log.log({level:"audit",type:"auth",msg:err.toString()});
|
||||
return server.errorHandler()(err,req,res,next);
|
||||
},
|
||||
login: login,
|
||||
revoke: revoke,
|
||||
genericStrategy: genericStrategy
|
||||
}
|
65
packages/node_modules/@node-red/editor/lib/auth/permissions.js
generated
vendored
Normal file
65
packages/node_modules/@node-red/editor/lib/auth/permissions.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var util = require('util');
|
||||
|
||||
var readRE = /^((.+)\.)?read$/
|
||||
var writeRE = /^((.+)\.)?write$/
|
||||
|
||||
function hasPermission(userScope,permission) {
|
||||
if (permission === "") {
|
||||
return true;
|
||||
}
|
||||
var i;
|
||||
|
||||
if (util.isArray(permission)) {
|
||||
// Multiple permissions requested - check each one
|
||||
for (i=0;i<permission.length;i++) {
|
||||
if (!hasPermission(userScope,permission[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// All permissions check out
|
||||
return true;
|
||||
}
|
||||
|
||||
if (util.isArray(userScope)) {
|
||||
if (userScope.length === 0) {
|
||||
return false;
|
||||
}
|
||||
for (i=0;i<userScope.length;i++) {
|
||||
if (hasPermission(userScope[i],permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (userScope === "*" || userScope === permission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (userScope === "read" || userScope === "*.read") {
|
||||
return readRE.test(permission);
|
||||
} else if (userScope === "write" || userScope === "*.write") {
|
||||
return writeRE.test(permission);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasPermission: hasPermission,
|
||||
}
|
131
packages/node_modules/@node-red/editor/lib/auth/strategies.js
generated
vendored
Normal file
131
packages/node_modules/@node-red/editor/lib/auth/strategies.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var BearerStrategy = require('passport-http-bearer').Strategy;
|
||||
var ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy;
|
||||
|
||||
var passport = require("passport");
|
||||
var crypto = require("crypto");
|
||||
var util = require("util");
|
||||
|
||||
var Tokens = require("./tokens");
|
||||
var Users = require("./users");
|
||||
var Clients = require("./clients");
|
||||
var permissions = require("./permissions");
|
||||
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
|
||||
var bearerStrategy = function (accessToken, done) {
|
||||
// is this a valid token?
|
||||
Tokens.get(accessToken).then(function(token) {
|
||||
if (token) {
|
||||
Users.get(token.user).then(function(user) {
|
||||
if (user) {
|
||||
done(null,user,{scope:token.scope});
|
||||
} else {
|
||||
log.audit({event: "auth.invalid-token"});
|
||||
done(null,false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.audit({event: "auth.invalid-token"});
|
||||
done(null,false);
|
||||
}
|
||||
});
|
||||
}
|
||||
bearerStrategy.BearerStrategy = new BearerStrategy(bearerStrategy);
|
||||
|
||||
var clientPasswordStrategy = function(clientId, clientSecret, done) {
|
||||
Clients.get(clientId).then(function(client) {
|
||||
if (client && client.secret == clientSecret) {
|
||||
done(null,client);
|
||||
} else {
|
||||
log.audit({event: "auth.invalid-client",client:clientId});
|
||||
done(null,false);
|
||||
}
|
||||
});
|
||||
}
|
||||
clientPasswordStrategy.ClientPasswordStrategy = new ClientPasswordStrategy(clientPasswordStrategy);
|
||||
|
||||
var loginAttempts = [];
|
||||
var loginSignInWindow = 600000; // 10 minutes
|
||||
|
||||
|
||||
var passwordTokenExchange = function(client, username, password, scope, done) {
|
||||
var now = Date.now();
|
||||
loginAttempts = loginAttempts.filter(function(logEntry) {
|
||||
return logEntry.time + loginSignInWindow > now;
|
||||
});
|
||||
loginAttempts.push({time:now, user:username});
|
||||
var attemptCount = 0;
|
||||
loginAttempts.forEach(function(logEntry) {
|
||||
/* istanbul ignore else */
|
||||
if (logEntry.user == username) {
|
||||
attemptCount++;
|
||||
}
|
||||
});
|
||||
if (attemptCount > 5) {
|
||||
log.audit({event: "auth.login.fail.too-many-attempts",username:username,client:client.id});
|
||||
done(new Error("Too many login attempts. Wait 10 minutes and try again"),false);
|
||||
return;
|
||||
}
|
||||
|
||||
Users.authenticate(username,password).then(function(user) {
|
||||
if (user) {
|
||||
if (scope === "") {
|
||||
scope = user.permissions;
|
||||
}
|
||||
if (permissions.hasPermission(user.permissions,scope)) {
|
||||
loginAttempts = loginAttempts.filter(function(logEntry) {
|
||||
return logEntry.user !== username;
|
||||
});
|
||||
Tokens.create(username,client.id,scope).then(function(tokens) {
|
||||
log.audit({event: "auth.login",username:username,client:client.id,scope:scope});
|
||||
done(null,tokens.accessToken,null,{expires_in:tokens.expires_in});
|
||||
});
|
||||
} else {
|
||||
log.audit({event: "auth.login.fail.permissions",username:username,client:client.id,scope:scope});
|
||||
done(null,false);
|
||||
}
|
||||
} else {
|
||||
log.audit({event: "auth.login.fail.credentials",username:username,client:client.id,scope:scope});
|
||||
done(null,false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function AnonymousStrategy() {
|
||||
passport.Strategy.call(this);
|
||||
this.name = 'anon';
|
||||
}
|
||||
util.inherits(AnonymousStrategy, passport.Strategy);
|
||||
AnonymousStrategy.prototype.authenticate = function(req) {
|
||||
var self = this;
|
||||
Users.default().then(function(anon) {
|
||||
if (anon) {
|
||||
self.success(anon,{scope:anon.permissions});
|
||||
} else {
|
||||
self.fail(401);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bearerStrategy: bearerStrategy,
|
||||
clientPasswordStrategy: clientPasswordStrategy,
|
||||
passwordTokenExchange: passwordTokenExchange,
|
||||
anonymousStrategy: new AnonymousStrategy()
|
||||
}
|
110
packages/node_modules/@node-red/editor/lib/auth/tokens.js
generated
vendored
Normal file
110
packages/node_modules/@node-red/editor/lib/auth/tokens.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
function generateToken(length) {
|
||||
var c = "ABCDEFGHIJKLMNOPQRSTUZWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||
var token = [];
|
||||
for (var i=0;i<length;i++) {
|
||||
token.push(c[Math.floor(Math.random()*c.length)]);
|
||||
}
|
||||
return token.join("");
|
||||
}
|
||||
|
||||
|
||||
var storage;
|
||||
|
||||
var sessionExpiryTime
|
||||
|
||||
var sessions = {};
|
||||
|
||||
var loadedSessions = null;
|
||||
|
||||
function expireSessions() {
|
||||
var now = Date.now();
|
||||
var modified = false;
|
||||
for (var t in sessions) {
|
||||
if (sessions.hasOwnProperty(t)) {
|
||||
var session = sessions[t];
|
||||
if (!session.hasOwnProperty("expires") || session.expires < now) {
|
||||
delete sessions[t];
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
return storage.saveSessions(sessions);
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
function loadSessions() {
|
||||
if (loadedSessions === null) {
|
||||
loadedSessions = storage.getSessions().then(function(_sessions) {
|
||||
sessions = _sessions||{};
|
||||
return expireSessions();
|
||||
});
|
||||
}
|
||||
return loadedSessions;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(adminAuthSettings, _storage) {
|
||||
storage = _storage;
|
||||
sessionExpiryTime = adminAuthSettings.sessionExpiryTime || 604800; // 1 week in seconds
|
||||
// At this point, storage will not have been initialised, so defer loading
|
||||
// the sessions until there's a request for them.
|
||||
loadedSessions = null;
|
||||
return Promise.resolve();
|
||||
},
|
||||
get: function(token) {
|
||||
return loadSessions().then(function() {
|
||||
if (sessions[token]) {
|
||||
if (sessions[token].expires < Date.now()) {
|
||||
return expireSessions().then(function() { return null });
|
||||
}
|
||||
}
|
||||
return Promise.resolve(sessions[token]);
|
||||
});
|
||||
},
|
||||
create: function(user,client,scope) {
|
||||
return loadSessions().then(function() {
|
||||
var accessToken = generateToken(128);
|
||||
|
||||
var accessTokenExpiresAt = Date.now() + (sessionExpiryTime*1000);
|
||||
|
||||
var session = {
|
||||
user:user,
|
||||
client:client,
|
||||
scope:scope,
|
||||
accessToken: accessToken,
|
||||
expires: accessTokenExpiresAt
|
||||
};
|
||||
sessions[accessToken] = session;
|
||||
return storage.saveSessions(sessions).then(function() {
|
||||
return {
|
||||
accessToken: accessToken,
|
||||
expires_in: sessionExpiryTime
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
revoke: function(token) {
|
||||
return loadSessions().then(function() {
|
||||
delete sessions[token];
|
||||
return storage.saveSessions(sessions);
|
||||
});
|
||||
}
|
||||
}
|
122
packages/node_modules/@node-red/editor/lib/auth/users.js
generated
vendored
Normal file
122
packages/node_modules/@node-red/editor/lib/auth/users.js
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var util = require("util");
|
||||
var clone = require("clone");
|
||||
var bcrypt;
|
||||
try { bcrypt = require('bcrypt'); }
|
||||
catch(e) { bcrypt = require('bcryptjs'); }
|
||||
var users = {};
|
||||
var defaultUser = null;
|
||||
|
||||
function authenticate() {
|
||||
var username = arguments[0];
|
||||
if (typeof username !== 'string') {
|
||||
username = username.username;
|
||||
}
|
||||
const args = Array.from(arguments);
|
||||
return api.get(username).then(function(user) {
|
||||
if (user) {
|
||||
if (args.length === 2) {
|
||||
// Username/password authentication
|
||||
var password = args[1];
|
||||
return new Promise(function(resolve,reject) {
|
||||
bcrypt.compare(password, user.password, function(err, res) {
|
||||
resolve(res?cleanUser(user):null);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Try to extract common profile information
|
||||
if (args[0].hasOwnProperty('photos') && args[0].photos.length > 0) {
|
||||
user.image = args[0].photos[0].value;
|
||||
}
|
||||
return cleanUser(user);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
function get(username) {
|
||||
return Promise.resolve(users[username]);
|
||||
}
|
||||
function getDefaultUser() {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
var api = {
|
||||
get: get,
|
||||
authenticate: authenticate,
|
||||
default: getDefaultUser
|
||||
}
|
||||
|
||||
function init(config) {
|
||||
users = {};
|
||||
defaultUser = null;
|
||||
if (config.type == "credentials" || config.type == "strategy") {
|
||||
if (config.users) {
|
||||
if (typeof config.users === "function") {
|
||||
api.get = config.users;
|
||||
} else {
|
||||
var us = config.users;
|
||||
/* istanbul ignore else */
|
||||
if (!util.isArray(us)) {
|
||||
us = [us];
|
||||
}
|
||||
for (var i=0;i<us.length;i++) {
|
||||
var u = us[i];
|
||||
users[u.username] = clone(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config.authenticate && typeof config.authenticate === "function") {
|
||||
api.authenticate = config.authenticate;
|
||||
} else {
|
||||
api.authenticate = authenticate;
|
||||
}
|
||||
} else {
|
||||
api.get = get;
|
||||
api.authenticate = authenticate;
|
||||
api.default = api.default;
|
||||
}
|
||||
if (config.default) {
|
||||
if (typeof config.default === "function") {
|
||||
api.default = config.default;
|
||||
} else {
|
||||
api.default = function() {
|
||||
return Promise.resolve({
|
||||
"anonymous": true,
|
||||
"permissions":config.default.permissions
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
api.default = getDefaultUser;
|
||||
}
|
||||
}
|
||||
function cleanUser(user) {
|
||||
if (user && user.hasOwnProperty('password')) {
|
||||
user = clone(user);
|
||||
delete user.password;
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
get: function(username) { return api.get(username).then(cleanUser)},
|
||||
authenticate: function() { return api.authenticate.apply(null, arguments) },
|
||||
default: function() { return api.default(); }
|
||||
};
|
Reference in New Issue
Block a user