feat: add password reset for usermanager (#2688)

* feat: add password reset for usermanager
- add a reset_key to account table
- add ?reset_key= GET arguments to index.html and show reset form if provided
- superuser can generate and copy reset url with key to share
future ideas:
- could add send forgot password email if user fill out email address
* feat: simplify reset key
* test: use reset key
* test: add more tests
* test: reset passwords do not match
* test: `reset_password_auth_threshold_expired`

---------

Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
This commit is contained in:
dni ⚡
2024-10-01 10:59:57 +02:00
committed by GitHub
co-authored by Vlad Stan
parent 3a64cf5245
commit a4c000d7dc
12 changed files with 344 additions and 10 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -1
View File
@@ -266,5 +266,7 @@ window.localisation.en = {
hide_empty_wallets: 'Hide empty wallets',
recheck: 'Recheck',
contributors: 'Contributors',
license: 'License'
license: 'License',
reset_key: 'Reset Key',
reset_password: 'Reset Password'
}
+11
View File
@@ -81,6 +81,17 @@ window.LNbits = {
}
})
},
reset: function (reset_key, password, password_repeat) {
return axios({
method: 'PUT',
url: '/api/v1/auth/reset',
data: {
reset_key,
password,
password_repeat
}
})
},
login: function (username, password) {
return axios({
method: 'POST',
+19
View File
@@ -13,6 +13,7 @@ window.app = Vue.createApp({
authMethod: 'username-password',
usr: '',
username: '',
reset_key: '',
email: '',
password: '',
passwordRepeat: '',
@@ -128,6 +129,18 @@ window.app = Vue.createApp({
LNbits.utils.notifyApiError(e)
}
},
reset: async function () {
try {
await LNbits.api.reset(
this.reset_key,
this.password,
this.passwordRepeat
)
window.location.href = '/wallet'
} catch (e) {
LNbits.utils.notifyApiError(e)
}
},
login: async function () {
try {
await LNbits.api.login(this.username, this.password)
@@ -171,5 +184,11 @@ window.app = Vue.createApp({
if (this.isUserAuthorized) {
window.location.href = '/wallet'
}
this.reset_key = new URLSearchParams(window.location.search).get(
'reset_key'
)
if (this.reset_key) {
this.authAction = 'reset'
}
}
})
+16
View File
@@ -218,6 +218,22 @@ window.app = Vue.createApp({
formatSat: function (value) {
return LNbits.utils.formatSat(Math.floor(value / 1000))
},
resetPassword(user_id) {
return LNbits.api
.request('PUT', `/users/api/v1/user/${user_id}/reset_password`)
.then(res => {
this.$q.notify({
type: 'positive',
message: 'generated key for password reset',
icon: null
})
const url = window.location.origin + '?reset_key=' + res.data
this.copyText(url)
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
},
createUser() {
LNbits.api
.request('POST', '/users/api/v1/user', null, this.createUserDialog.data)