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:
parent
86394b25ee
commit
430a479113
3 changed files with 124 additions and 56 deletions
156
lib/auth.js
156
lib/auth.js
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue