MM-14748: Allow to invalidate email invites (#10509)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3c8975780d
Коммит
c370d30041
15
api4/team.go
15
api4/team.go
@@ -55,6 +55,7 @@ func (api *API) InitTeam() {
|
|||||||
api.BaseRoutes.TeamMember.Handle("/schemeRoles", api.ApiSessionRequired(updateTeamMemberSchemeRoles)).Methods("PUT")
|
api.BaseRoutes.TeamMember.Handle("/schemeRoles", api.ApiSessionRequired(updateTeamMemberSchemeRoles)).Methods("PUT")
|
||||||
api.BaseRoutes.Team.Handle("/import", api.ApiSessionRequired(importTeam)).Methods("POST")
|
api.BaseRoutes.Team.Handle("/import", api.ApiSessionRequired(importTeam)).Methods("POST")
|
||||||
api.BaseRoutes.Team.Handle("/invite/email", api.ApiSessionRequired(inviteUsersToTeam)).Methods("POST")
|
api.BaseRoutes.Team.Handle("/invite/email", api.ApiSessionRequired(inviteUsersToTeam)).Methods("POST")
|
||||||
|
api.BaseRoutes.Teams.Handle("/invites/email", api.ApiSessionRequired(invalidateAllEmailInvites)).Methods("DELETE")
|
||||||
api.BaseRoutes.Teams.Handle("/invite/{invite_id:[A-Za-z0-9]+}", api.ApiHandler(getInviteInfo)).Methods("GET")
|
api.BaseRoutes.Teams.Handle("/invite/{invite_id:[A-Za-z0-9]+}", api.ApiHandler(getInviteInfo)).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,6 +790,20 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write([]byte(model.MapToJson(result)))
|
w.Write([]byte(model.MapToJson(result)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func invalidateAllEmailInvites(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
||||||
|
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.App.InvalidateAllEmailInvites(); err != nil {
|
||||||
|
c.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnStatusOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
func getTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireTeamId()
|
c.RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
|
|||||||
@@ -1256,3 +1256,10 @@ func (a *App) RemoveTeamIcon(teamId string) *model.AppError {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) InvalidateAllEmailInvites() *model.AppError {
|
||||||
|
if result := <-a.Srv.Store.Token().RemoveAllTokensByType(TOKEN_TYPE_TEAM_INVITATION); result.Err != nil {
|
||||||
|
return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, result.Err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1778,6 +1778,10 @@
|
|||||||
"id": "api.team.import_team.unavailable.app_error",
|
"id": "api.team.import_team.unavailable.app_error",
|
||||||
"translation": "Malformed request: filesize field is not present."
|
"translation": "Malformed request: filesize field is not present."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.team.invalidate_all_email_invites.app_error",
|
||||||
|
"translation": "Error invalidating email invites."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.team.invite_members.disabled.app_error",
|
"id": "api.team.invite_members.disabled.app_error",
|
||||||
"translation": "Email invitations are disabled."
|
"translation": "Email invitations are disabled."
|
||||||
@@ -6022,6 +6026,10 @@
|
|||||||
"id": "store.sql_recover.delete.app_error",
|
"id": "store.sql_recover.delete.app_error",
|
||||||
"translation": "Unable to delete token"
|
"translation": "Unable to delete token"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "store.sql_recover.remove_all_tokens_by_type.app_error",
|
||||||
|
"translation": "Unable to remove all the tokens of a type"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "store.sql_recover.get_by_code.app_error",
|
"id": "store.sql_recover.get_by_code.app_error",
|
||||||
"translation": "Unable to get a token with this code"
|
"translation": "Unable to get a token with this code"
|
||||||
|
|||||||
@@ -75,3 +75,12 @@ func (s SqlTokenStore) Cleanup() {
|
|||||||
mlog.Error("Unable to cleanup token store.")
|
mlog.Error("Unable to cleanup token store.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlTokenStore) RemoveAllTokensByType(tokenType string) store.StoreChannel {
|
||||||
|
return store.Do(func(result *store.StoreResult) {
|
||||||
|
if _, err := s.GetMaster().Exec("DELETE FROM Tokens WHERE Type = :TokenType", map[string]interface{}{"TokenType": tokenType}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlTokenStore.RemoveAllTokensByType", "store.sql_recover.remove_all_tokens_by_type.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -443,6 +443,7 @@ type TokenStore interface {
|
|||||||
Delete(token string) StoreChannel
|
Delete(token string) StoreChannel
|
||||||
GetByToken(token string) StoreChannel
|
GetByToken(token string) StoreChannel
|
||||||
Cleanup()
|
Cleanup()
|
||||||
|
RemoveAllTokensByType(tokenType string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
type EmojiStore interface {
|
type EmojiStore interface {
|
||||||
|
|||||||
@@ -98,6 +98,22 @@ func (_m *PostStore) Get(id string) store.StoreChannel {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDirectPostParentsForExportAfter provides a mock function with given fields: limit, afterId
|
||||||
|
func (_m *PostStore) GetDirectPostParentsForExportAfter(limit int, afterId string) store.StoreChannel {
|
||||||
|
ret := _m.Called(limit, afterId)
|
||||||
|
|
||||||
|
var r0 store.StoreChannel
|
||||||
|
if rf, ok := ret.Get(0).(func(int, string) store.StoreChannel); ok {
|
||||||
|
r0 = rf(limit, afterId)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(store.StoreChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// GetEtag provides a mock function with given fields: channelId, allowFromCache
|
// GetEtag provides a mock function with given fields: channelId, allowFromCache
|
||||||
func (_m *PostStore) GetEtag(channelId string, allowFromCache bool) store.StoreChannel {
|
func (_m *PostStore) GetEtag(channelId string, allowFromCache bool) store.StoreChannel {
|
||||||
ret := _m.Called(channelId, allowFromCache)
|
ret := _m.Called(channelId, allowFromCache)
|
||||||
@@ -470,18 +486,3 @@ func (_m *PostStore) Update(newPost *model.Post, oldPost *model.Post) store.Stor
|
|||||||
|
|
||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_m *PostStore) GetDirectPostParentsForExportAfter(limit int, afterId string) store.StoreChannel {
|
|
||||||
ret := _m.Called(limit, afterId)
|
|
||||||
|
|
||||||
var r0 store.StoreChannel
|
|
||||||
if rf, ok := ret.Get(0).(func(int, string) store.StoreChannel); ok {
|
|
||||||
r0 = rf(limit, afterId)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(store.StoreChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package mocks
|
|||||||
import gorp "github.com/mattermost/gorp"
|
import gorp "github.com/mattermost/gorp"
|
||||||
import mock "github.com/stretchr/testify/mock"
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
import squirrel "github.com/Masterminds/squirrel"
|
||||||
import store "github.com/mattermost/mattermost-server/store"
|
import store "github.com/mattermost/mattermost-server/store"
|
||||||
|
|
||||||
// SqlStore is an autogenerated mock type for the SqlStore type
|
// SqlStore is an autogenerated mock type for the SqlStore type
|
||||||
@@ -855,3 +856,17 @@ func (_m *SqlStore) Webhook() store.WebhookStore {
|
|||||||
|
|
||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getQueryBuilder provides a mock function with given fields:
|
||||||
|
func (_m *SqlStore) getQueryBuilder() squirrel.StatementBuilderType {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 squirrel.StatementBuilderType
|
||||||
|
if rf, ok := ret.Get(0).(func() squirrel.StatementBuilderType); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(squirrel.StatementBuilderType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,6 +50,22 @@ func (_m *TokenStore) GetByToken(token string) store.StoreChannel {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveAllTokensByType provides a mock function with given fields: tokenType
|
||||||
|
func (_m *TokenStore) RemoveAllTokensByType(tokenType string) store.StoreChannel {
|
||||||
|
ret := _m.Called(tokenType)
|
||||||
|
|
||||||
|
var r0 store.StoreChannel
|
||||||
|
if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
|
||||||
|
r0 = rf(tokenType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(store.StoreChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// Save provides a mock function with given fields: recovery
|
// Save provides a mock function with given fields: recovery
|
||||||
func (_m *TokenStore) Save(recovery *model.Token) store.StoreChannel {
|
func (_m *TokenStore) Save(recovery *model.Token) store.StoreChannel {
|
||||||
ret := _m.Called(recovery)
|
ret := _m.Called(recovery)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user