Skip to content

Loading…

Added additional status codes #26

Open
wants to merge 2 commits into from

1 participant

@wshager

I needed this for my purposes, but it can't hurt to have them:

I used 406 to determine if the requests from an automated system were acceptable, and 409 to let the same system know an entry already existed (i.e. duplicate). The system would retry otherwise, which led to faulty behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 61 additions and 26 deletions.
  1. +6 −2 jsgi/error.js
  2. +55 −24 security.js
View
8 jsgi/error.js
@@ -5,6 +5,7 @@
var METHOD_HAS_BODY = require("./methods").METHOD_HAS_BODY,
DatabaseError = require("perstore/errors").DatabaseError,
AccessError = require("perstore/errors").AccessError,
+ AcceptError = require("perstore/errors").AcceptError,
MethodNotAllowedError = require("perstore/errors").MethodNotAllowedError,
print = require("promised-io/process").print,
when = require("promised-io/promise").when;
@@ -48,10 +49,13 @@ exports.ErrorHandler = function(nextApp){
}else if(e instanceof DatabaseError){
if(e.code == 2){
status = 404;
- }
- else if(e.code == 3){
+ } else if(e.code == 3){
status = 412;
+ } else if(e.code == 4) {
+ status = 409;
}
+ }else if(e instanceof AcceptError){
+ status = 406;
}else if(e instanceof TypeError){
status = 403;
}else if(e instanceof RangeError){
View
79 security.js
@@ -7,7 +7,8 @@ var AccessError = require("perstore/errors").AccessError,
when = require("promised-io/promise").when,
getCurrentSession = require("./jsgi/session").getCurrentSession,
Restrictive = require("perstore/facet").Restrictive,
- sha1 = require("./util/sha1").b64_sha1,
+ Promise = require("promised-io/promise").Promise,
+ bcrypt = require('bcrypt-nodejs'),
settings = require("perstore/util/settings");
try{
@@ -50,35 +51,65 @@ exports.DefaultSecurity = function(){
var userModel;
var admins = settings.security && settings.security.admins;
var security = {
- encryptPassword: function(username, password){
- return password && sha1(password);
+ encryptPassword: function(password){
+ var d = new Promise();
+ bcrypt.hash(password, null, null, function(err, hash) {
+ if(err) {
+ throw new AccessError("Password encryption error occurred: "+err);
+ d.reject();
+ }
+ d.resolve(hash);
+ });
+ return d;
+ },
+ comparePassword: function(password, userPassword) {
+ var d = new Promise();
+ bcrypt.compare(password, userPassword, function(err, isMatch) {
+ if (err) {
+ throw new AccessError("Password encryption error occurred: "+err);
+ d.reject();
+ }
+ d.resolve(isMatch);
+ });
+ return d;
},
authenticate: function(username, password){
- if(typeof this.encryptPassword === 'function'){
- password = this.encryptPassword(username, password);
- }
+ var comparePassword = this.comparePassword;
return when(security.getUserModel().get(username), function(user){
- if(!user || (user.password !== password)){
- // allow admins to authenticate
- if (!admins || !(user=admins[username]) || user.password !== password)
- throw new AccessError("No user with the provided password");
- user.id = username;
- }
- return user;
+ return when(comparePassword(password, user.password), function(isMatch) {
+ if(!user || !isMatch){
+ // allow admins to authenticate
+ if (!admins || !(user=admins[username]) || !isMatch)
+ throw new AccessError("No user with the provided password");
+ user.id = username;
+ }
+ return user;
+ });
});
},
createUser: function(username, password){
- if(typeof this.encryptPassword === 'function'){
- password = this.encryptPassword(username, password);
- }
- return when(security.getUserModel().get(username), function(user){
- // N.B. disallow overwrite admins
- var admins = settings.security.admins;
- if(user || (admins && admins[username]))
- throw new AccessError("User already exists");
- return security.getUserModel().add({
- password: password
- }, {id: username, overwrite: false});
+ if(!username || !password) throw new Error("No username or password specified.");
+ return when(this.encryptPassword(password), function(password) {
+ return when(security.getUserModel().get(username), function(user){
+ // N.B. disallow overwrite admins
+ var admins = settings.security.admins;
+ if(user || (admins && admins[username]))
+ throw new AccessError("User already exists");
+ return security.getUserModel().add({
+ password: password
+ }, {id: username, overwrite: false});
+ });
+ });
+ },
+ changePassword: function(username, password){
+ if(!username || !password) throw new Error("No username or password specified.");
+ return when(this.encryptPassword(password), function(password) {
+ return when(security.getUserModel().get(username), function(user){
+ // N.B. disallow overwrite admins
+ if(!user) throw new Error("User does not exist");
+ user.password = password;
+ return security.getUserModel().put(user, {id: username, overwrite: true});
+ });
});
},
getUserModel: function(){
Something went wrong with that request. Please try again.