Merge pull request #5124 from overleaf/jk-de-ng-set-password-page

[web] de-ng set password form

GitOrigin-RevId: d8ebf9f794454d5772e13ab783892d2bba6eed87
This commit is contained in:
Jakob Ackermann 2021-09-23 11:47:36 +02:00 committed by Copybot
parent 9e5dae3443
commit 891947770c
4 changed files with 118 additions and 42 deletions

View file

@ -12,7 +12,11 @@ async function setNewUserPassword(req, res, next) {
let user
let { passwordResetToken, password } = req.body
if (!passwordResetToken || !password) {
return res.sendStatus(400)
return res.status(400).json({
message: {
key: 'invalid-password',
},
})
}
passwordResetToken = passwordResetToken.trim()
delete req.session.resetToken
@ -31,8 +35,18 @@ async function setNewUserPassword(req, res, next) {
auditLog
)
const { found, reset, userId } = result
if (!found) return res.sendStatus(404)
if (!reset) return res.sendStatus(500)
if (!found) {
return res.status(404).json({
message: {
key: 'token-expired',
},
})
}
if (!reset) {
return res.status(500).json({
message: req.i18n.translate('error_performing_request'),
})
}
await UserSessionsManager.promises.revokeAllUserSessions(
{ _id: userId },
[]
@ -44,11 +58,21 @@ async function setNewUserPassword(req, res, next) {
user = await UserGetter.promises.getUser(userId)
} catch (error) {
if (error.name === 'NotFoundError') {
return res.sendStatus(404)
return res.status(404).json({
message: {
key: 'token-expired',
},
})
} else if (error.name === 'InvalidPasswordError') {
return res.sendStatus(400)
return res.status(400).json({
message: {
key: 'invalid-password',
},
})
} else {
return res.sendStatus(500)
return res.status(500).json({
message: req.i18n.translate('error_performing_request'),
})
}
}

View file

@ -1,7 +1,4 @@
extends ../layout
block append meta
meta(name="ol-passwordStrengthOptions" data-type="json" content=settings.passwordStrengthOptions)
extends ../layout-marketing
block content
main.content.content-alt#main-content
@ -12,52 +9,68 @@ block content
.page-header
h1 #{translate("reset_your_password")}
form(
async-form="password-reset",
data-ol-async-form,
name="passwordResetForm",
action="/user/password/set",
method="POST",
ng-cloak
)
input(type="hidden", name="_csrf", value=csrfToken)
.alert.alert-success(ng-show="passwordResetForm.response.success")
| #{translate("password_has_been_reset")}.
br
a(href='/login') #{translate("login_here")}
div(ng-show="passwordResetForm.response.error == true")
div(ng-switch="passwordResetForm.response.status")
.alert.alert-danger(ng-switch-when="404")
div(data-ol-not-sent)
div(data-ol-form-messages)
div.alert.alert-danger(
hidden
role="alert"
aria-live="assertive"
data-ol-custom-form-message='token-expired'
)
| #{translate('password_reset_token_expired')}
br
a(href="/user/password/reset")
| Request a new password reset email
.alert.alert-danger(ng-switch-when="400")
| #{translate('invalid_password')}
.alert.alert-danger(ng-switch-when="429")
| #{translate('rate_limit_hit_wait')}
.alert.alert-danger(ng-switch-default)
| #{translate('error_performing_request')}
| #{translate('request_new_password_reset_email')}
div.alert.alert-danger(
hidden
role="alert"
aria-live="assertive"
data-ol-custom-form-message='invalid-password'
)
| #{translate('invalid_password')}
div.alert.alert-success(
hidden
role="alert"
aria-live="assertive"
data-ol-sent
)
| #{translate("password_has_been_reset")}.
br
a(href='/login') #{translate("login_here")}
input(type="hidden", name="_csrf", value=csrfToken)
.form-group
input.form-control#passwordField(
type='password',
name='password',
placeholder='new password',
required,
autocomplete="new-password",
ng-model="password",
autofocus,
complex-password
required,
minlength=settings.passwordStrengthOptions.length.min,
maxlength=settings.passwordStrengthOptions.length.max
)
span.small.text-primary(ng-show="passwordResetForm.password.$error.complexPassword", ng-bind-html="complexPasswordErrorMessage")
input(
type="hidden",
name="passwordResetToken",
value=passwordResetToken
ng-non-bindable
)
.actions
button.btn.btn-primary(
type='submit',
ng-disabled="passwordResetForm.$invalid"
) #{translate("set_new_password")}
data-ol-disabled-inflight
aria-label=translate('set_new_password')
)
span(data-ol-inflight="idle")
| #{translate('set_new_password')}
span(hidden data-ol-inflight="pending")
| #{translate('set_new_password')}…

View file

@ -1113,6 +1113,7 @@
"support_lots_of_features": "We support almost all LaTeX features, including inserting images, bibliographies, equations, and much more! Read about all the exciting things you can do with __appName__ in our <0>__help_guides_link__</0>",
"latex_guides": "LaTeX guides",
"reset_password": "Reset Password",
"request_new_password_reset_email": "Request a new password reset email",
"set_password": "Set Password",
"updating_site": "Updating Site",
"bonus_please_recommend_us": "Bonus - Please recommend us",

View file

@ -22,7 +22,9 @@ describe('PasswordResetController', function () {
password: this.password,
},
i18n: {
translate() {},
translate() {
return '.'
},
},
session: {},
query: {},
@ -174,8 +176,12 @@ describe('PasswordResetController', function () {
reset: false,
userId: this.user_id,
})
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(404)
return this.res
}
this.res.json = data => {
data.message.key.should.equal('token-expired')
done()
}
this.PasswordResetController.setNewUserPassword(this.req, this.res)
@ -187,8 +193,12 @@ describe('PasswordResetController', function () {
reset: false,
userId: this.user_id,
})
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(500)
return this.res
}
this.res.json = data => {
expect(data.message).to.exist
done()
}
this.PasswordResetController.setNewUserPassword(this.req, this.res)
@ -196,8 +206,12 @@ describe('PasswordResetController', function () {
it('should return 400 (Bad Request) if there is no password', function (done) {
this.req.body.password = ''
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(400)
return this.res
}
this.res.json = data => {
data.message.key.should.equal('invalid-password')
this.PasswordResetHandler.promises.setNewUserPassword.called.should.equal(
false
)
@ -208,8 +222,12 @@ describe('PasswordResetController', function () {
it('should return 400 (Bad Request) if there is no passwordResetToken', function (done) {
this.req.body.passwordResetToken = ''
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(400)
return this.res
}
this.res.json = data => {
data.message.key.should.equal('invalid-password')
this.PasswordResetHandler.promises.setNewUserPassword.called.should.equal(
false
)
@ -223,8 +241,12 @@ describe('PasswordResetController', function () {
const err = new Error('bad')
err.name = 'InvalidPasswordError'
this.PasswordResetHandler.promises.setNewUserPassword.rejects(err)
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(400)
return this.res
}
this.res.json = data => {
data.message.key.should.equal('invalid-password')
this.PasswordResetHandler.promises.setNewUserPassword.called.should.equal(
true
)
@ -265,8 +287,12 @@ describe('PasswordResetController', function () {
const anError = new Error('oops')
anError.name = 'NotFoundError'
this.PasswordResetHandler.promises.setNewUserPassword.rejects(anError)
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(404)
return this.res
}
this.res.json = data => {
data.message.key.should.equal('token-expired')
done()
}
this.PasswordResetController.setNewUserPassword(this.req, this.res)
@ -275,8 +301,12 @@ describe('PasswordResetController', function () {
const anError = new Error('oops')
anError.name = 'InvalidPasswordError'
this.PasswordResetHandler.promises.setNewUserPassword.rejects(anError)
this.res.sendStatus = code => {
this.res.status = code => {
code.should.equal(400)
return this.res
}
this.res.json = data => {
data.message.key.should.equal('invalid-password')
done()
}
this.PasswordResetController.setNewUserPassword(this.req, this.res)
@ -284,6 +314,14 @@ describe('PasswordResetController', function () {
it('should return 500 for other errors', function (done) {
const anError = new Error('oops')
this.PasswordResetHandler.promises.setNewUserPassword.rejects(anError)
this.res.status = code => {
code.should.equal(500)
return this.res
}
this.res.json = data => {
expect(data.message).to.exist
done()
}
this.res.sendStatus = code => {
code.should.equal(500)
done()