Merge pull request #322 from sharelatex/ho-password-limits

Ho password limits
This commit is contained in:
Henry Oswald 2016-10-05 10:03:54 +01:00 committed by GitHub
commit 3141f91b59
6 changed files with 65 additions and 29 deletions

View file

@ -29,6 +29,9 @@ module.exports = AuthenticationManager =
callback null, null
setUserPassword: (user_id, password, callback = (error) ->) ->
if Settings.passwordStrengthOptions?.length?.max? and Settings.passwordStrengthOptions?.length?.max < password.length
return callback("password is too long")
bcrypt.genSalt BCRYPT_ROUNDS, (error, salt) ->
return callback(error) if error?
bcrypt.hash password, salt, (error, hash) ->

View file

@ -3,7 +3,7 @@ extends ../layout
block content
- locals.supressDefaultJs = true
script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath)
script(src=buildJsPath('libs/recurly.min.js'))
script(src=buildJsPath('libs/recurly.min.js', {fingerprint:false}))
.content.content-alt
.container

View file

@ -79,7 +79,7 @@ block content
required,
complex-password
)
span.small.text-primary(ng-show="changePasswordForm.newPassword1.$error.complexPassword && changePasswordForm.currentPassword.$dirty", ng-bind-html="complexPasswordErrorMessage")
span.small.text-primary(ng-show="changePasswordForm.newPassword1.$error.complexPassword && changePasswordForm.newPassword1.$dirty", ng-bind-html="complexPasswordErrorMessage")
.form-group
label(for='newPassword2') #{translate("confirm_new_password")}
input.form-control(
@ -88,9 +88,11 @@ block content
placeholder='*********',
ng-model="newPassword2",
equals="passwordField"
)
span.small.text-primary(ng-show="changePasswordForm.newPassword2.$invalid && changePasswordForm.newPassword2.$dirty")
| #{translate("doesnt_match")}
)
span.small.text-primary(ng-show="changePasswordForm.newPassword2.$error.areEqual && changePasswordForm.newPassword2.$dirty")
| #{translate("doesnt_match")}
span.small.text-primary(ng-show="!changePasswordForm.newPassword2.$error.areEqual && changePasswordForm.newPassword2.$invalid && changePasswordForm.newPassword2.$dirty")
| #{translate("Invalid Password")}
.actions
button.btn.btn-primary(
type='submit',

View file

@ -193,8 +193,8 @@ module.exports = settings =
# passwordStrengthOptions:
# pattern: "aA$3"
# length:
# min: 8
# max: 50
# min: 1
# max: 10
# Email support
# -------------

View file

@ -112,6 +112,8 @@ define [
[asyncFormCtrl, ngModelCtrl] = ctrl
ngModelCtrl.$parsers.unshift (modelValue) ->
isValid = passField.validatePass()
email = asyncFormCtrl.getEmail() || window.usersEmail
if !isValid
@ -121,5 +123,8 @@ define [
if modelValue.indexOf(email) != -1 or modelValue.indexOf(startOfEmail) != -1
isValid = false
scope.complexPasswordErrorMessage = "Password can not contain email address"
if opts.length.max? and modelValue.length == opts.length.max
isValid = false
scope.complexPasswordErrorMessage = "Maximum password length #{opts.length.max} reached"
ngModelCtrl.$setValidity('complexPassword', isValid)
return modelValue

View file

@ -9,6 +9,7 @@ ObjectId = require("mongojs").ObjectId
describe "AuthenticationManager", ->
beforeEach ->
@settings = { security: { bcryptRounds: 12 } }
@AuthenticationManager = SandboxedModule.require modulePath, requires:
"../../models/User": User: @User = {}
"../../infrastructure/mongojs":
@ -16,7 +17,7 @@ describe "AuthenticationManager", ->
users: {}
ObjectId: ObjectId
"bcrypt": @bcrypt = {}
"settings-sharelatex": { security: { bcryptRounds: 12 } }
"settings-sharelatex": @settings
@callback = sinon.stub()
describe "authenticate", ->
@ -102,27 +103,52 @@ describe "AuthenticationManager", ->
@bcrypt.genSalt = sinon.stub().callsArgWith(1, null, @salt)
@bcrypt.hash = sinon.stub().callsArgWith(2, null, @hashedPassword)
@db.users.update = sinon.stub().callsArg(2)
@AuthenticationManager.setUserPassword(@user_id, @password, @callback)
it "should update the user's password in the database", ->
@db.users.update
.calledWith({
_id: ObjectId(@user_id.toString())
}, {
$set: {
"hashedPassword": @hashedPassword
}
$unset: password: true
})
.should.equal true
describe "too long", ->
beforeEach ->
@settings.passwordStrengthOptions =
length:
max:10
@password = "dsdsadsadsadsadsadkjsadjsadjsadljs"
it "should return and error", (done)->
@AuthenticationManager.setUserPassword @user_id, @password, (err)->
expect(err).to.exist
done()
it "should not start the bcrypt process", (done)->
@AuthenticationManager.setUserPassword @user_id, @password, (err)=>
@bcrypt.genSalt.called.should.equal false
@bcrypt.hash.called.should.equal false
done()
describe "successful set", ->
beforeEach ->
@AuthenticationManager.setUserPassword(@user_id, @password, @callback)
it "should update the user's password in the database", ->
@db.users.update
.calledWith({
_id: ObjectId(@user_id.toString())
}, {
$set: {
"hashedPassword": @hashedPassword
}
$unset: password: true
})
.should.equal true
it "should hash the password", ->
@bcrypt.genSalt
.calledWith(12)
.should.equal true
@bcrypt.hash
.calledWith(@password, @salt)
.should.equal true
it "should call the callback", ->
@callback.called.should.equal true
it "should hash the password", ->
@bcrypt.genSalt
.calledWith(12)
.should.equal true
@bcrypt.hash
.calledWith(@password, @salt)
.should.equal true
it "should call the callback", ->
@callback.called.should.equal true