0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-20 22:52:46 -05:00

auth refactoring: part 2

auth plugins
This commit is contained in:
Alex Kocharin 2014-09-02 04:27:04 +04:00
parent 86394b25ee
commit 430a479113
3 changed files with 124 additions and 56 deletions

View file

@ -1,53 +1,126 @@
var Path = require('path')
, crypto = require('crypto')
, UError = require('./error').UError
, UError = require('./error').UserError
, Logger = require('./logger')
, assert = require('assert')
module.exports = Auth
function Auth(config) {
if (!(this instanceof Auth)) return new Auth(config)
this.config = config
this.logger = Logger.logger.child({sub: 'auth'})
var stuff = {
config: config,
logger: this.logger,
}
if (config.users_file) {
this.HTPasswd = require('./htpasswd')(
Path.resolve(
Path.dirname(config.self_path),
config.users_file
)
)
}
}
Auth.prototype.authenticate = function(user, password, cb) {
if (this.config.users != null && this.config.users[user] != null) {
// if user exists in this.users, verify password against it no matter what is in htpasswd
return cb(null, crypto.createHash('sha1').update(password).digest('hex') === this.config.users[user].password ? [user] : null)
}
if (!this.HTPasswd) return cb(null, false)
this.HTPasswd.reload(function() {
cb(null, this.HTPasswd.verify(user, password) ? [user] : null)
}.bind(this))
}
Auth.prototype.add_user = function(user, password, cb) {
if (this.config.users && this.config.users[user]) return cb(new UError({
status: 403,
message: 'this user already exists',
}))
if (this.HTPasswd) {
if (this.max_users || this.max_users == null) {
var max_users = Number(this.max_users || Infinity)
this.HTPasswd.add_user(user, password, max_users, cb)
return
if (!config.auth || !config.auth.htpasswd) {
// b/w compat
config.auth = config.auth || {}
config.auth.htpasswd = {file: config.users_file}
}
}
return cb(new UError({
status: 409,
message: 'registration is disabled',
}))
this.plugins = Object.keys(config.auth || {}).map(function(p) {
var plugin, name
try {
name = 'sinopia-' + p
plugin = require(name)
} catch(x) {
try {
name = p
plugin = require(name)
} catch(x) {}
}
if (plugin == null) {
throw Error('"' + p + '" auth plugin not found\n'
+ 'try "npm install sinopia-' + p + '"')
}
if (typeof(plugin) !== 'function')
throw Error('"' + name + '" doesn\'t look like a valid auth plugin')
plugin = plugin(config.auth[p], stuff)
if (plugin == null || typeof(plugin.authenticate) !== 'function')
throw Error('"' + name + '" doesn\'t look like a valid auth plugin')
return plugin
})
this.plugins.unshift({
authenticate: function(user, password, cb) {
if (config.users != null
&& config.users[user] != null
&& (crypto.createHash('sha1').update(password).digest('hex')
=== config.users[user].password)
) {
return cb(null, [ user ])
}
return cb()
},
adduser: function(user, password, cb) {
if (config.users && config.users[user]) return cb(new UError({
status: 403,
message: 'this user already exists',
}))
return cb()
},
})
this.plugins.push({
authenticate: function(user, password, cb) {
return cb(new UError({
status: 403,
message: 'bad username/password, access denied',
}))
},
adduser: function(user, password, cb) {
return cb(new UError({
status: 409,
message: 'registration is disabled',
}))
},
})
}
Auth.prototype.authenticate = function(user, password, cb) {
var plugins = this.plugins.slice(0)
!function next() {
var p = plugins.shift()
p.authenticate(user, password, function(err, groups) {
if (err || groups) return cb(err, groups)
next()
})
}()
}
Auth.prototype.add_user = function(user, password, cb) {
var plugins = this.plugins.slice(0)
!function next() {
var p = plugins.shift()
var n = 'adduser'
if (typeof(p[n]) !== 'function') {
n = 'add_user'
}
if (typeof(p[n]) !== 'function') {
next()
} else {
p[n](user, password, function(err, ok) {
if (err || ok) return cb(err, ok)
next()
})
}
}()
}
Auth.prototype.middleware = function() {
@ -90,17 +163,14 @@ Auth.prototype.middleware = function() {
var user = credentials.slice(0, index)
, pass = credentials.slice(index + 1)
debugger
self.authenticate(user, pass, function(err, groups) {
if (err) return next(err)
if (groups != null && groups != false) {
if (!err && groups != null && groups != false) {
req.remote_user = AuthenticatedUser(user, groups)
next()
} else {
req.remote_user = AnonymousUser()
next({
status: 403,
message: 'bad username/password, access denied',
})
next(err)
}
})
}

View file

@ -75,11 +75,6 @@ function Config(config) {
Array.isArray(hash[action])
, 'CONFIG: bad "'+i+'" package '+action+' description (array or string expected)')
hash[action] = flatten(hash[action])
hash[action].forEach(function(user) {
assert(
users[user] != null
, 'CONFIG: "'+i+'" package: user "'+user+'" doesn\'t exist')
})
}
for (var i in this.packages) {

View file

@ -12,11 +12,12 @@ users:
title: Sinopia
# logo: logo.png
users_file: ./htpasswd
# Maximum amount of users allowed to register, defaults to "+inf".
# You can set this to 0 to disable registration.
#max_users: 1000
auth:
htpasswd:
users_file: ./htpasswd
# Maximum amount of users allowed to register, defaults to "+inf".
# You can set this to 0 to disable registration.
#max_users: 1000
# a list of other known repositories we can talk to
uplinks:
@ -51,9 +52,11 @@ packages:
# storage: 'local_storage'
'*':
# allow all users to read packages ('all' is a keyword)
# this includes non-authenticated users
allow_access: all
# allow all users to read packages (including non-authenticated users)
#
# you can specify usernames/groupnames (depending on your auth plugin)
# and three keywords: "@all", "@anonymous", "@authenticated"
allow_access: @all
# allow 'admin' to publish packages
allow_publish: admin