mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-01-27 22:59:51 -05:00
add user registration
This commit is contained in:
parent
9a14a6e022
commit
ff8a5e99ec
3 changed files with 112 additions and 7 deletions
|
@ -2,6 +2,7 @@ var assert = require('assert')
|
||||||
, crypto = require('crypto')
|
, crypto = require('crypto')
|
||||||
, Path = require('path')
|
, Path = require('path')
|
||||||
, minimatch = require('minimatch')
|
, minimatch = require('minimatch')
|
||||||
|
, UError = require('./error').UserError
|
||||||
, utils = require('./utils')
|
, utils = require('./utils')
|
||||||
|
|
||||||
// [[a, [b, c]], d] -> [a, b, c, d]
|
// [[a, [b, c]], d] -> [a, b, c, d]
|
||||||
|
@ -168,6 +169,21 @@ Config.prototype.authenticate = function(user, password, cb) {
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Config.prototype.add_user = function(user, password, cb) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(new UError({
|
||||||
|
status: 409,
|
||||||
|
message: 'registration is disabled',
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = Config
|
module.exports = Config
|
||||||
|
|
||||||
var parse_interval_table = {
|
var parse_interval_table = {
|
||||||
|
|
|
@ -31,12 +31,85 @@ function verify_password(user, passwd, hash) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function add_user_to_htpasswd(body, user, passwd) {
|
||||||
|
if (user != encodeURIComponent(user)) {
|
||||||
|
throw new UError({
|
||||||
|
status: 409,
|
||||||
|
message: "username shouldn't contain non-uri-safe characters",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
passwd = crypt3(passwd)
|
||||||
|
if (!passwd) {
|
||||||
|
passwd = '{SHA}' + crypto.createHash('sha1').update(passwd, 'binary').digest('base64')
|
||||||
|
}
|
||||||
|
var comment = 'autocreated ' + (new Date()).toJSON()
|
||||||
|
|
||||||
|
var newline = user + ':' + passwd + ':' + comment + '\n'
|
||||||
|
if (body.length && body[body.length-1] != '\n') newline = '\n' + newline
|
||||||
|
return body + newline
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function(path) {
|
module.exports = function(path) {
|
||||||
var result = {}
|
var result = {}
|
||||||
var users = {}
|
var users = {}
|
||||||
var last_time
|
var last_time
|
||||||
result.add_user = function(user, passwd, cb) {
|
|
||||||
// TODO
|
// hopefully race-condition-free way to add users:
|
||||||
|
// 1. lock file for writing (other processes can still read)
|
||||||
|
// 2. reload .htpasswd
|
||||||
|
// 3. write new data into .htpasswd.tmp
|
||||||
|
// 4. move .htpasswd.tmp to .htpasswd
|
||||||
|
// 5. reload .htpasswd
|
||||||
|
// 6. unlock file
|
||||||
|
result.add_user = function(user, passwd, maxusers, real_cb) {
|
||||||
|
function sanity_check() {
|
||||||
|
if (users[user]) {
|
||||||
|
return new UError({
|
||||||
|
status: 409,
|
||||||
|
message: 'this user already exists',
|
||||||
|
})
|
||||||
|
} else if (Object.keys(users).length >= maxusers) {
|
||||||
|
return new UError({
|
||||||
|
status: 409,
|
||||||
|
message: 'maximum amount of users reached',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// preliminary checks, just to ensure that file won't be reloaded if it's not needed
|
||||||
|
var s_err = sanity_check()
|
||||||
|
if (s_err) return real_cb(s_err)
|
||||||
|
|
||||||
|
fs_storage.lock_and_read(path, function(err, fd, res) {
|
||||||
|
// callback that cleanups fd first
|
||||||
|
function cb(err) {
|
||||||
|
if (!fd) return real_cb(err)
|
||||||
|
fs.close(fd, function() {
|
||||||
|
real_cb(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore ENOENT errors, we'll just create .htpasswd in that case
|
||||||
|
if (err && err.code != 'ENOENT') return cb(err)
|
||||||
|
|
||||||
|
var body = (res || '').toString('utf8')
|
||||||
|
users = parse_htpasswd(body)
|
||||||
|
|
||||||
|
// real checks, to prevent race conditions
|
||||||
|
var s_err = sanity_check()
|
||||||
|
if (s_err) return cb(s_err)
|
||||||
|
|
||||||
|
try {
|
||||||
|
body = add_user_to_htpasswd(body, user, passwd)
|
||||||
|
} catch(err) {
|
||||||
|
return cb(err)
|
||||||
|
}
|
||||||
|
fs_storage.write(path, body, function(err) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
result.reload(cb)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
result.verify = function(user, passwd) {
|
result.verify = function(user, passwd) {
|
||||||
if (!users[user]) return false
|
if (!users[user]) return false
|
||||||
|
@ -45,7 +118,6 @@ module.exports = function(path) {
|
||||||
result.reload = function(callback) {
|
result.reload = function(callback) {
|
||||||
fs.open(path, 'r', function(err, fd) {
|
fs.open(path, 'r', function(err, fd) {
|
||||||
if (err) return callback(err)
|
if (err) return callback(err)
|
||||||
|
|
||||||
fs.fstat(fd, function(err, st) {
|
fs.fstat(fd, function(err, st) {
|
||||||
if (err) return callback(err)
|
if (err) return callback(err)
|
||||||
if (last_time === st.mtime) return callback()
|
if (last_time === st.mtime) return callback()
|
||||||
|
|
19
lib/index.js
19
lib/index.js
|
@ -206,10 +206,27 @@ module.exports = function(config_hash) {
|
||||||
})
|
})
|
||||||
|
|
||||||
app.put('/-/user/:org_couchdb_user', function(req, res, next) {
|
app.put('/-/user/:org_couchdb_user', function(req, res, next) {
|
||||||
|
if (req.remoteUser != null) {
|
||||||
|
res.status(200)
|
||||||
|
return res.send({
|
||||||
|
ok: 'you are authenticated as "' + req.remoteUser + '"',
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if (typeof(req.body.name) !== 'string' || typeof(req.body.password) !== 'string') {
|
||||||
res.status(409)
|
res.status(409)
|
||||||
return res.send({
|
return res.send({
|
||||||
error: 'registration is not implemented',
|
ok: 'user/password is not found in request (npm issue?)',
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
config.add_user(req.body.name, req.body.password, function(err) {
|
||||||
|
if (err) return next(err)
|
||||||
|
|
||||||
|
res.status(201)
|
||||||
|
return res.send({
|
||||||
|
ok: 'user "' + req.remoteUser + '" created',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.put('/-/user/:org_couchdb_user/-rev/*', function(req, res, next) {
|
app.put('/-/user/:org_couchdb_user/-rev/*', function(req, res, next) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue