web UI/REST API: add password reset

In order to reset the password from the admin/client user interface,
an SMTP configuration must be added and the user/admin must have an email
address.
You can prohibit the reset functionality on a per-user basis by using a
specific restriction.

Fixes #597
This commit is contained in:
Nicola Murino
2021-11-13 13:25:43 +01:00
parent b331dc5686
commit 78233ff9a3
25 changed files with 1787 additions and 60 deletions

View File

@@ -796,6 +796,34 @@ func TestCreateTokenError(t *testing.T) {
assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
assert.Contains(t, rr.Body.String(), "invalid URL escape")
req, _ = http.NewRequest(http.MethodPost, webAdminForgotPwdPath+"?a=a%C3%A1%GD", bytes.NewBuffer([]byte(form.Encode())))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rr = httptest.NewRecorder()
handleWebAdminForgotPwdPost(rr, req)
assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
assert.Contains(t, rr.Body.String(), "invalid URL escape")
req, _ = http.NewRequest(http.MethodPost, webClientForgotPwdPath+"?a=a%C2%A1%GD", bytes.NewBuffer([]byte(form.Encode())))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rr = httptest.NewRecorder()
handleWebClientForgotPwdPost(rr, req)
assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
assert.Contains(t, rr.Body.String(), "invalid URL escape")
req, _ = http.NewRequest(http.MethodPost, webAdminResetPwdPath+"?a=a%C3%AO%JD", bytes.NewBuffer([]byte(form.Encode())))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rr = httptest.NewRecorder()
server.handleWebAdminPasswordResetPost(rr, req)
assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
assert.Contains(t, rr.Body.String(), "invalid URL escape")
req, _ = http.NewRequest(http.MethodPost, webClientResetPwdPath+"?a=a%C3%AO%JD", bytes.NewBuffer([]byte(form.Encode())))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rr = httptest.NewRecorder()
server.handleWebClientPasswordResetPost(rr, req)
assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
assert.Contains(t, rr.Body.String(), "invalid URL escape")
req, _ = http.NewRequest(http.MethodPost, webChangeClientPwdPath+"?a=a%K3%AO%GA", bytes.NewBuffer([]byte(form.Encode())))
_, err = getShareFromPostFields(req)
@@ -2040,3 +2068,32 @@ func TestLoginLinks(t *testing.T) {
assert.False(t, b.showAdminLoginURL())
assert.True(t, b.showClientLoginURL())
}
func TestResetCodesCleanup(t *testing.T) {
resetCode := newResetCode(util.GenerateUniqueID(), false)
resetCode.ExpiresAt = time.Now().Add(-1 * time.Minute).UTC()
resetCodes.Store(resetCode.Code, resetCode)
cleanupExpiredResetCodes()
_, ok := resetCodes.Load(resetCode.Code)
assert.False(t, ok)
}
func TestUserCanResetPassword(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, webClientLoginPath, nil)
assert.NoError(t, err)
req.RemoteAddr = "172.16.9.2:55080"
u := dataprovider.User{}
assert.True(t, isUserAllowedToResetPassword(req, &u))
u.Filters.DeniedProtocols = []string{common.ProtocolHTTP}
assert.False(t, isUserAllowedToResetPassword(req, &u))
u.Filters.DeniedProtocols = nil
u.Filters.WebClient = []string{sdk.WebClientPasswordResetDisabled}
assert.False(t, isUserAllowedToResetPassword(req, &u))
u.Filters.WebClient = nil
u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
assert.False(t, isUserAllowedToResetPassword(req, &u))
u.Filters.DeniedLoginMethods = nil
u.Filters.AllowedIP = []string{"127.0.0.1/8"}
assert.False(t, isUserAllowedToResetPassword(req, &u))
}