MM-52477 - remove recovery tokens when creating a new one (#23171)
* remove recovery tokens when creating a new one * add app layers, unit test, i18 extract * lint fixes * fix unit test
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e4075dae18
Коммит
355bc6502c
@@ -887,6 +887,7 @@ type AppIface interface {
|
|||||||
InvalidateAllEmailInvites() *model.AppError
|
InvalidateAllEmailInvites() *model.AppError
|
||||||
InvalidateAllResendInviteEmailJobs() *model.AppError
|
InvalidateAllResendInviteEmailJobs() *model.AppError
|
||||||
InvalidateCacheForUser(userID string)
|
InvalidateCacheForUser(userID string)
|
||||||
|
InvalidatePasswordRecoveryTokensForUser(userID string) *model.AppError
|
||||||
InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError
|
InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError
|
||||||
InviteGuestsToChannelsGracefully(teamID string, guestsInvite *model.GuestsInvite, senderId string) ([]*model.EmailInviteWithError, *model.AppError)
|
InviteGuestsToChannelsGracefully(teamID string, guestsInvite *model.GuestsInvite, senderId string) ([]*model.EmailInviteWithError, *model.AppError)
|
||||||
InviteNewUsersToTeam(emailList []string, teamID, senderId string) *model.AppError
|
InviteNewUsersToTeam(emailList []string, teamID, senderId string) *model.AppError
|
||||||
|
|||||||
@@ -11904,6 +11904,28 @@ func (a *OpenTracingAppLayer) InvalidateCacheForUser(userID string) {
|
|||||||
a.app.InvalidateCacheForUser(userID)
|
a.app.InvalidateCacheForUser(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *OpenTracingAppLayer) InvalidatePasswordRecoveryTokensForUser(userID string) *model.AppError {
|
||||||
|
origCtx := a.ctx
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InvalidatePasswordRecoveryTokensForUser")
|
||||||
|
|
||||||
|
a.ctx = newCtx
|
||||||
|
a.app.Srv().Store().SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
a.app.Srv().Store().SetContext(origCtx)
|
||||||
|
a.ctx = origCtx
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0 := a.app.InvalidatePasswordRecoveryTokensForUser(userID)
|
||||||
|
|
||||||
|
if resultVar0 != nil {
|
||||||
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultVar0
|
||||||
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError {
|
func (a *OpenTracingAppLayer) InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InviteGuestsToChannels")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InviteGuestsToChannels")
|
||||||
|
|||||||
@@ -1487,8 +1487,13 @@ func (a *App) CreatePasswordRecoveryToken(userID, email string) (*model.Token, *
|
|||||||
return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError).Wrap(err)
|
return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
token := model.NewToken(TokenTypePasswordRecovery, string(jsonData))
|
// remove any previously created tokens for user
|
||||||
|
appErr := a.InvalidatePasswordRecoveryTokensForUser(userID)
|
||||||
|
if appErr != nil {
|
||||||
|
mlog.Warn("Error while deleting additional user tokens.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
token := model.NewToken(TokenTypePasswordRecovery, string(jsonData))
|
||||||
if err := a.Srv().Store().Token().Save(token); err != nil {
|
if err := a.Srv().Store().Token().Save(token); err != nil {
|
||||||
var appErr *model.AppError
|
var appErr *model.AppError
|
||||||
switch {
|
switch {
|
||||||
@@ -1502,6 +1507,34 @@ func (a *App) CreatePasswordRecoveryToken(userID, email string) (*model.Token, *
|
|||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) InvalidatePasswordRecoveryTokensForUser(userID string) *model.AppError {
|
||||||
|
tokens, err := a.Srv().Store().Token().GetAllTokensByType(TokenTypePasswordRecovery)
|
||||||
|
if err != nil {
|
||||||
|
return model.NewAppError("InvalidatePasswordRecoveryTokensForUser", "api.user.invalidate_password_recovery_tokens.error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var appErr *model.AppError = nil
|
||||||
|
for _, token := range tokens {
|
||||||
|
tokenExtra := struct {
|
||||||
|
UserId string
|
||||||
|
Email string
|
||||||
|
}{}
|
||||||
|
if err := json.Unmarshal([]byte(token.Extra), &tokenExtra); err != nil {
|
||||||
|
appErr = model.NewAppError("InvalidatePasswordRecoveryTokensForUser", "api.user.invalidate_password_recovery_tokens_parse.error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokenExtra.UserId != userID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.Srv().Store().Token().Delete(token.Token); err != nil {
|
||||||
|
appErr = model.NewAppError("InvalidatePasswordRecoveryTokensForUser", "api.user.invalidate_password_recovery_tokens_delete.error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appErr
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) GetPasswordRecoveryToken(token string) (*model.Token, *model.AppError) {
|
func (a *App) GetPasswordRecoveryToken(token string) (*model.Token, *model.AppError) {
|
||||||
rtoken, err := a.Srv().Store().Token().GetByToken(token)
|
rtoken, err := a.Srv().Store().Token().GetByToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1173,6 +1173,44 @@ func TestPasswordRecovery(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInvalidatePasswordRecoveryTokens(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
t.Run("remove manually added tokens", func(t *testing.T) {
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
token := model.NewToken(
|
||||||
|
TokenTypePasswordRecovery,
|
||||||
|
model.MapToJSON(map[string]string{"UserId": th.BasicUser.Id, "email": th.BasicUser.Email}),
|
||||||
|
)
|
||||||
|
require.NoError(t, th.App.Srv().Store().Token().Save(token))
|
||||||
|
}
|
||||||
|
tokens, err := th.App.Srv().Store().Token().GetAllTokensByType(TokenTypePasswordRecovery)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 5, len(tokens))
|
||||||
|
|
||||||
|
appErr := th.App.InvalidatePasswordRecoveryTokensForUser(th.BasicUser.Id)
|
||||||
|
assert.Nil(t, appErr)
|
||||||
|
|
||||||
|
tokens, err = th.App.Srv().Store().Token().GetAllTokensByType(TokenTypePasswordRecovery)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 0, len(tokens))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("add multiple tokens, should only be one valid", func(t *testing.T) {
|
||||||
|
_, appErr := th.App.CreatePasswordRecoveryToken(th.BasicUser.Id, th.BasicUser.Email)
|
||||||
|
assert.Nil(t, appErr)
|
||||||
|
|
||||||
|
token, appErr := th.App.CreatePasswordRecoveryToken(th.BasicUser.Id, th.BasicUser.Email)
|
||||||
|
assert.Nil(t, appErr)
|
||||||
|
|
||||||
|
tokens, err := th.App.Srv().Store().Token().GetAllTokensByType(TokenTypePasswordRecovery)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 1, len(tokens))
|
||||||
|
assert.Equal(t, token.Token, tokens[0].Token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetViewUsersRestrictions(t *testing.T) {
|
func TestGetViewUsersRestrictions(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|||||||
@@ -4163,6 +4163,18 @@
|
|||||||
"id": "api.user.get_users.validation.app_error",
|
"id": "api.user.get_users.validation.app_error",
|
||||||
"translation": "Error fetching roles during validation."
|
"translation": "Error fetching roles during validation."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.user.invalidate_password_recovery_tokens.error",
|
||||||
|
"translation": "Unable to get tokens by type when invalidating password recovery tokens"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api.user.invalidate_password_recovery_tokens_delete.error",
|
||||||
|
"translation": "Unable to remove token when invalidating password recovery tokens"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api.user.invalidate_password_recovery_tokens_parse.error",
|
||||||
|
"translation": "Unable to parse token when invalidating password recovery tokens"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.user.invalidate_verify_email_tokens.error",
|
"id": "api.user.invalidate_verify_email_tokens.error",
|
||||||
"translation": "Unable to get tokens by type when invalidating email verification tokens"
|
"translation": "Unable to get tokens by type when invalidating email verification tokens"
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user