GraphQL: Create dedicated top-level filter for sidebar categories (#20353)
We add the excludeTeam switch to allow user to get all sidebar categories from other teams excluding a given team. ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
ade2271442
Коммит
bd6acf04a9
@@ -23,7 +23,7 @@ func getCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
categories, err := c.App.GetSidebarCategories(c.Params.UserId, c.Params.TeamId)
|
||||
categories, err := c.App.GetSidebarCategoriesForTeamForUser(c.Params.UserId, c.Params.TeamId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
|
||||
@@ -309,8 +309,9 @@ func (*resolver) ChannelMembers(ctx context.Context, args struct {
|
||||
|
||||
// match with api4.getCategoriesForTeamForUser
|
||||
func (*resolver) SidebarCategories(ctx context.Context, args struct {
|
||||
UserID string
|
||||
TeamID string
|
||||
UserID string
|
||||
TeamID string
|
||||
ExcludeTeam bool
|
||||
}) ([]*model.SidebarCategoryWithChannels, error) {
|
||||
c, err := getCtx(ctx)
|
||||
if err != nil {
|
||||
@@ -335,7 +336,44 @@ func (*resolver) SidebarCategories(ctx context.Context, args struct {
|
||||
args.UserID = c.AppContext.Session().UserId
|
||||
}
|
||||
|
||||
return getSidebarCategories(c, args.UserID, args.TeamID)
|
||||
if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), args.UserID) {
|
||||
c.SetPermissionError(model.PermissionEditOtherUsers)
|
||||
return nil, c.Err
|
||||
}
|
||||
|
||||
// If it's only for a single team.
|
||||
var categories *model.OrderedSidebarCategories
|
||||
var appErr *model.AppError
|
||||
if !args.ExcludeTeam {
|
||||
categories, appErr = c.App.GetSidebarCategoriesForTeamForUser(args.UserID, args.TeamID)
|
||||
if appErr != nil {
|
||||
return nil, appErr
|
||||
}
|
||||
} else {
|
||||
opts := &store.SidebarCategorySearchOpts{
|
||||
TeamID: args.TeamID,
|
||||
ExcludeTeam: args.ExcludeTeam,
|
||||
}
|
||||
categories, appErr = c.App.GetSidebarCategories(args.UserID, opts)
|
||||
if appErr != nil {
|
||||
return nil, appErr
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: look into optimizing this.
|
||||
// create map
|
||||
orderMap := make(map[string]*model.SidebarCategoryWithChannels, len(categories.Categories))
|
||||
for _, category := range categories.Categories {
|
||||
orderMap[category.Id] = category
|
||||
}
|
||||
|
||||
// create a new slice based on the order
|
||||
res := make([]*model.SidebarCategoryWithChannels, 0, len(categories.Categories))
|
||||
for _, categoryId := range categories.Order {
|
||||
res = append(res, orderMap[categoryId])
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// getCtx extracts web.Context out of the usual request context.
|
||||
|
||||
@@ -26,14 +26,15 @@ func TestGraphQLSidebarCategories(t *testing.T) {
|
||||
DisplayName string `json:"displayName"`
|
||||
Sorting model.SidebarCategorySorting `json:"sorting"`
|
||||
ChannelIDs []string `json:"channelIds"`
|
||||
TeamID string `json:"teamId"`
|
||||
} `json:"sidebarCategories"`
|
||||
}
|
||||
|
||||
input := graphQLInput{
|
||||
OperationName: "sidebarCategories",
|
||||
Query: `
|
||||
query sidebarCategories($userId: String = "", $teamId: String = "") {
|
||||
sidebarCategories(userId: $userId, teamId: $teamId) {
|
||||
query sidebarCategories($userId: String = "", $teamId: String = "", $excludeTeam: Boolean = false) {
|
||||
sidebarCategories(userId: $userId, teamId: $teamId, excludeTeam: $excludeTeam) {
|
||||
id
|
||||
displayName
|
||||
sorting
|
||||
@@ -69,4 +70,66 @@ func TestGraphQLSidebarCategories(t *testing.T) {
|
||||
assert.Equal(t, categories.Categories[i].Sorting, q.SidebarCategories[i].Sorting)
|
||||
assert.Equal(t, categories.Categories[i].ChannelIds(), q.SidebarCategories[i].ChannelIDs)
|
||||
}
|
||||
|
||||
input = graphQLInput{
|
||||
OperationName: "sidebarCategories",
|
||||
Query: `
|
||||
query sidebarCategories($userId: String = "", $teamId: String = "", $excludeTeam: Boolean = false) {
|
||||
sidebarCategories(userId: $userId, teamId: $teamId, excludeTeam: $excludeTeam) {
|
||||
id
|
||||
displayName
|
||||
sorting
|
||||
channelIds
|
||||
}
|
||||
}
|
||||
`,
|
||||
Variables: map[string]interface{}{
|
||||
"userId": "me",
|
||||
"teamId": th.BasicTeam.Id,
|
||||
"excludeTeam": true,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err = th.MakeGraphQLRequest(&input)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resp.Errors, 0)
|
||||
require.NoError(t, json.Unmarshal(resp.Data, &q))
|
||||
assert.Len(t, q.SidebarCategories, 0)
|
||||
|
||||
// Adding a new team
|
||||
myTeam := th.CreateTeam()
|
||||
ch1 := th.CreateChannelWithClientAndTeam(th.Client, model.ChannelTypeOpen, myTeam.Id)
|
||||
ch2 := th.CreateChannelWithClientAndTeam(th.Client, model.ChannelTypePrivate, myTeam.Id)
|
||||
th.LinkUserToTeam(th.BasicUser, myTeam)
|
||||
th.App.AddUserToChannel(th.BasicUser, ch1, false)
|
||||
th.App.AddUserToChannel(th.BasicUser, ch2, false)
|
||||
|
||||
input = graphQLInput{
|
||||
OperationName: "sidebarCategories",
|
||||
Query: `
|
||||
query sidebarCategories($userId: String = "", $teamId: String = "", $excludeTeam: Boolean = false) {
|
||||
sidebarCategories(userId: $userId, teamId: $teamId, excludeTeam: $excludeTeam) {
|
||||
id
|
||||
displayName
|
||||
sorting
|
||||
channelIds
|
||||
teamId
|
||||
}
|
||||
}
|
||||
`,
|
||||
Variables: map[string]interface{}{
|
||||
"userId": "me",
|
||||
"teamId": th.BasicTeam.Id,
|
||||
"excludeTeam": true,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err = th.MakeGraphQLRequest(&input)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resp.Errors, 0)
|
||||
require.NoError(t, json.Unmarshal(resp.Data, &q))
|
||||
assert.Len(t, q.SidebarCategories, 3)
|
||||
for _, cat := range q.SidebarCategories {
|
||||
assert.Equal(t, myTeam.Id, cat.TeamID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/graph-gophers/dataloader/v6"
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/web"
|
||||
)
|
||||
|
||||
// teamMember is an internal graphQL wrapper struct to add resolver methods.
|
||||
@@ -27,43 +26,6 @@ func (tm *teamMember) User(ctx context.Context) (*user, error) {
|
||||
return getGraphQLUser(ctx, tm.UserId)
|
||||
}
|
||||
|
||||
// match with api4.getCategoriesForTeamForUser
|
||||
func (tm *teamMember) SidebarCategories(ctx context.Context) ([]*model.SidebarCategoryWithChannels, error) {
|
||||
c, err := getCtx(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getSidebarCategories(c, tm.UserId, tm.TeamId)
|
||||
}
|
||||
|
||||
func getSidebarCategories(c *web.Context, userID, teamID string) ([]*model.SidebarCategoryWithChannels, error) {
|
||||
if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), userID) {
|
||||
c.SetPermissionError(model.PermissionEditOtherUsers)
|
||||
return nil, c.Err
|
||||
}
|
||||
|
||||
categories, appErr := c.App.GetSidebarCategories(userID, teamID)
|
||||
if appErr != nil {
|
||||
return nil, appErr
|
||||
}
|
||||
|
||||
// TODO: look into optimizing this.
|
||||
// create map
|
||||
orderMap := make(map[string]*model.SidebarCategoryWithChannels, len(categories.Categories))
|
||||
for _, category := range categories.Categories {
|
||||
orderMap[category.Id] = category
|
||||
}
|
||||
|
||||
// create a new slice based on the order
|
||||
res := make([]*model.SidebarCategoryWithChannels, 0, len(categories.Categories))
|
||||
for _, categoryId := range categories.Order {
|
||||
res = append(res, orderMap[categoryId])
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// match with api4.getRolesByNames
|
||||
func (tm *teamMember) Roles_(ctx context.Context) ([]*model.Role, error) {
|
||||
loader, err := getRolesLoader(ctx)
|
||||
|
||||
@@ -41,16 +41,10 @@ func TestGraphQLTeamMembers(t *testing.T) {
|
||||
SchemeManaged bool `json:"schemeManaged"`
|
||||
BuiltIn bool `json:"builtIn"`
|
||||
} `json:"roles"`
|
||||
DeleteAt float64 `json:"deleteAt"`
|
||||
SchemeGuest bool `json:"schemeGuest"`
|
||||
SchemeUser bool `json:"schemeUser"`
|
||||
SchemeAdmin bool `json:"schemeAdmin"`
|
||||
SidebarCategories []struct {
|
||||
ID string `json:"id"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Sorting model.SidebarCategorySorting `json:"sorting"`
|
||||
ChannelIDs []string `json:"channelIds"`
|
||||
} `json:"sidebarCategories"`
|
||||
DeleteAt float64 `json:"deleteAt"`
|
||||
SchemeGuest bool `json:"schemeGuest"`
|
||||
SchemeUser bool `json:"schemeUser"`
|
||||
SchemeAdmin bool `json:"schemeAdmin"`
|
||||
} `json:"teamMembers"`
|
||||
}
|
||||
|
||||
@@ -78,12 +72,6 @@ func TestGraphQLTeamMembers(t *testing.T) {
|
||||
schemeGuest
|
||||
schemeUser
|
||||
schemeAdmin
|
||||
sidebarCategories {
|
||||
id
|
||||
displayName
|
||||
sorting
|
||||
channelIds
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
@@ -114,23 +102,6 @@ func TestGraphQLTeamMembers(t *testing.T) {
|
||||
assert.False(t, tm.SchemeGuest)
|
||||
assert.True(t, tm.SchemeUser)
|
||||
assert.False(t, tm.SchemeAdmin)
|
||||
|
||||
categories, _, err := th.Client.GetSidebarCategoriesForTeamForUser(th.BasicUser.Id, th.BasicTeam.Id, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
sort.Slice(tm.SidebarCategories, func(i, j int) bool {
|
||||
return tm.SidebarCategories[i].ID < tm.SidebarCategories[j].ID
|
||||
})
|
||||
sort.Slice(categories.Categories, func(i, j int) bool {
|
||||
return categories.Categories[i].Id < categories.Categories[j].Id
|
||||
})
|
||||
|
||||
for i := range categories.Categories {
|
||||
assert.Equal(t, categories.Categories[i].Id, tm.SidebarCategories[i].ID)
|
||||
assert.Equal(t, categories.Categories[i].DisplayName, tm.SidebarCategories[i].DisplayName)
|
||||
assert.Equal(t, categories.Categories[i].Sorting, tm.SidebarCategories[i].Sorting)
|
||||
assert.Equal(t, categories.Categories[i].ChannelIds(), tm.SidebarCategories[i].ChannelIDs)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("User+Team", func(t *testing.T) {
|
||||
|
||||
@@ -26,7 +26,8 @@ type Query {
|
||||
after: String = "",
|
||||
lastUpdateAt: Float = 0): [ChannelMember]!
|
||||
sidebarCategories(userId: String!,
|
||||
teamId: String!): [SidebarCategory]!
|
||||
teamId: String!,
|
||||
excludeTeam: Boolean = false): [SidebarCategory]!
|
||||
}
|
||||
|
||||
scalar ChannelType
|
||||
@@ -158,7 +159,6 @@ type TeamMember {
|
||||
schemeGuest: Boolean!
|
||||
schemeUser: Boolean!
|
||||
schemeAdmin: Boolean!
|
||||
sidebarCategories: [SidebarCategory]!
|
||||
}
|
||||
|
||||
type SidebarCategory {
|
||||
@@ -168,6 +168,7 @@ type SidebarCategory {
|
||||
displayName: String!
|
||||
muted: Boolean!
|
||||
collapsed: Boolean!
|
||||
teamId: String!
|
||||
channelIds: [String!]!
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user