MM-14748: Allow to invalidate email invites (#10509)

Этот коммит содержится в:
Jesús Espino
2019-03-26 19:30:49 +01:00
коммит произвёл GitHub
родитель 3c8975780d
Коммит c370d30041
8 изменённых файлов: 87 добавлений и 15 удалений

Просмотреть файл

@@ -55,6 +55,7 @@ func (api *API) InitTeam() {
api.BaseRoutes.TeamMember.Handle("/schemeRoles", api.ApiSessionRequired(updateTeamMemberSchemeRoles)).Methods("PUT")
api.BaseRoutes.Team.Handle("/import", api.ApiSessionRequired(importTeam)).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")
}
@@ -789,6 +790,20 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
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) {
c.RequireTeamId()
if c.Err != nil {

Просмотреть файл

@@ -1256,3 +1256,10 @@ func (a *App) RemoveTeamIcon(teamId string) *model.AppError {
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",
"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",
"translation": "Email invitations are disabled."
@@ -6022,6 +6026,10 @@
"id": "store.sql_recover.delete.app_error",
"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",
"translation": "Unable to get a token with this code"

Просмотреть файл

@@ -75,3 +75,12 @@ func (s SqlTokenStore) Cleanup() {
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
GetByToken(token string) StoreChannel
Cleanup()
RemoveAllTokensByType(tokenType string) StoreChannel
}
type EmojiStore interface {

Просмотреть файл

@@ -98,6 +98,22 @@ func (_m *PostStore) Get(id string) store.StoreChannel {
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
func (_m *PostStore) GetEtag(channelId string, allowFromCache bool) store.StoreChannel {
ret := _m.Called(channelId, allowFromCache)
@@ -470,18 +486,3 @@ func (_m *PostStore) Update(newPost *model.Post, oldPost *model.Post) store.Stor
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 mock "github.com/stretchr/testify/mock"
import squirrel "github.com/Masterminds/squirrel"
import store "github.com/mattermost/mattermost-server/store"
// SqlStore is an autogenerated mock type for the SqlStore type
@@ -855,3 +856,17 @@ func (_m *SqlStore) Webhook() store.WebhookStore {
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
}
// 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
func (_m *TokenStore) Save(recovery *model.Token) store.StoreChannel {
ret := _m.Called(recovery)