Adds the endpoints and store logic to get groups by team and by channel (#10502)

* Adds the endpoints and store logic to get groups by team and by channel

* Remove TODO comments

* Fix unit tests
Этот коммит содержится в:
Miguel de la Cruz
2019-04-02 21:02:51 +01:00
коммит произвёл GitHub
родитель 25fd962016
Коммит 2ce48aa6d1
15 изменённых файлов: 777 добавлений и 38 удалений

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

@@ -55,6 +55,14 @@ func (api *API) InitGroup() {
// GET /api/v4/groups/:group_id/members?page=0&per_page=100 // GET /api/v4/groups/:group_id/members?page=0&per_page=100
api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members", api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members",
api.ApiSessionRequired(getGroupMembers)).Methods("GET") api.ApiSessionRequired(getGroupMembers)).Methods("GET")
// GET /api/v4/channels/:channel_id/groups?page=0&per_page=100
api.BaseRoutes.Channels.Handle("/{channel_id:[A-Za-z0-9]+}/groups",
api.ApiSessionRequired(getGroupsByChannel)).Methods("GET")
// GET /api/v4/teams/:team_id/groups?page=0&per_page=100
api.BaseRoutes.Teams.Handle("/{team_id:[A-Za-z0-9]+}/groups",
api.ApiSessionRequired(getGroupsByTeam)).Methods("GET")
} }
func getGroup(c *Context, w http.ResponseWriter, r *http.Request) { func getGroup(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -431,3 +439,65 @@ func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write(b) w.Write(b)
} }
func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireChannelId()
if c.Err != nil {
return
}
if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
return
}
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
}
groups, err := c.App.GetGroupsByChannel(c.Params.ChannelId, c.Params.Page, c.Params.PerPage)
if err != nil {
c.Err = err
return
}
b, marshalErr := json.Marshal(groups)
if marshalErr != nil {
c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
return
}
w.Write(b)
}
func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId()
if c.Err != nil {
return
}
if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
return
}
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
}
groups, err := c.App.GetGroupsByTeam(c.Params.TeamId, c.Params.Page, c.Params.PerPage)
if err != nil {
c.Err = err
return
}
b, marshalErr := json.Marshal(groups)
if marshalErr != nil {
c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
return
}
w.Write(b)
}

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

@@ -594,3 +594,91 @@ func TestPatchGroupChannel(t *testing.T) {
_, response = th.SystemAdminClient.PatchGroupSyncable(g.Id, th.BasicChannel.Id, model.GroupSyncableTypeChannel, patch) _, response = th.SystemAdminClient.PatchGroupSyncable(g.Id, th.BasicChannel.Id, model.GroupSyncableTypeChannel, patch)
CheckUnauthorizedStatus(t, response) CheckUnauthorizedStatus(t, response)
} }
func TestGetGroupsByChannel(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
id := model.NewId()
group, err := th.App.CreateGroup(&model.Group{
DisplayName: "dn_" + id,
Name: "name" + id,
Source: model.GroupSourceLdap,
Description: "description_" + id,
RemoteId: model.NewId(),
})
assert.Nil(t, err)
_, err = th.App.CreateGroupSyncable(&model.GroupSyncable{
AutoAdd: true,
SyncableId: th.BasicChannel.Id,
Type: model.GroupSyncableTypeChannel,
GroupId: group.Id,
})
assert.Nil(t, err)
_, response := th.SystemAdminClient.GetGroupsByChannel("asdfasdf", 0, 60)
CheckBadRequestStatus(t, response)
th.App.SetLicense(nil)
_, response = th.SystemAdminClient.GetGroupsByChannel(th.BasicChannel.Id, 0, 60)
CheckNotImplementedStatus(t, response)
th.App.SetLicense(model.NewTestLicense("ldap"))
_, response = th.Client.GetGroupsByChannel(th.BasicChannel.Id, 0, 60)
CheckForbiddenStatus(t, response)
groups, response := th.SystemAdminClient.GetGroupsByChannel(th.BasicChannel.Id, 0, 60)
assert.Nil(t, response.Error)
assert.ElementsMatch(t, []*model.Group{group}, groups)
groups, response = th.SystemAdminClient.GetGroupsByChannel(model.NewId(), 0, 60)
assert.Nil(t, response.Error)
assert.Empty(t, groups)
}
func TestGetGroupsByTeam(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
id := model.NewId()
group, err := th.App.CreateGroup(&model.Group{
DisplayName: "dn_" + id,
Name: "name" + id,
Source: model.GroupSourceLdap,
Description: "description_" + id,
RemoteId: model.NewId(),
})
assert.Nil(t, err)
_, err = th.App.CreateGroupSyncable(&model.GroupSyncable{
AutoAdd: true,
SyncableId: th.BasicTeam.Id,
Type: model.GroupSyncableTypeTeam,
GroupId: group.Id,
})
assert.Nil(t, err)
_, response := th.SystemAdminClient.GetGroupsByTeam("asdfasdf", 0, 60)
CheckBadRequestStatus(t, response)
th.App.SetLicense(nil)
_, response = th.SystemAdminClient.GetGroupsByTeam(th.BasicTeam.Id, 0, 60)
CheckNotImplementedStatus(t, response)
th.App.SetLicense(model.NewTestLicense("ldap"))
_, response = th.Client.GetGroupsByTeam(th.BasicTeam.Id, 0, 60)
CheckForbiddenStatus(t, response)
groups, response := th.SystemAdminClient.GetGroupsByTeam(th.BasicTeam.Id, 0, 60)
assert.Nil(t, response.Error)
assert.ElementsMatch(t, []*model.Group{group}, groups)
groups, response = th.SystemAdminClient.GetGroupsByTeam(model.NewId(), 0, 60)
assert.Nil(t, response.Error)
assert.Empty(t, groups)
}

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

@@ -164,3 +164,19 @@ func (a *App) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError)
} }
return result.Data.([]*model.ChannelMember), nil return result.Data.([]*model.ChannelMember), nil
} }
func (a *App) GetGroupsByChannel(channelId string, page, perPage int) ([]*model.Group, *model.AppError) {
result := <-a.Srv.Store.Group().GetGroupsByChannel(channelId, page, perPage)
if result.Err != nil {
return nil, result.Err
}
return result.Data.([]*model.Group), nil
}
func (a *App) GetGroupsByTeam(teamId string, page, perPage int) ([]*model.Group, *model.AppError) {
result := <-a.Srv.Store.Group().GetGroupsByTeam(teamId, page, perPage)
if result.Err != nil {
return nil, result.Err
}
return result.Data.([]*model.Group), nil
}

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

@@ -197,3 +197,55 @@ func TestDeleteGroupSyncable(t *testing.T) {
require.NotNil(t, err) require.NotNil(t, err)
require.Nil(t, gs) require.Nil(t, gs)
} }
func TestGetGroupsByChannel(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
group := th.CreateGroup()
// Create a group channel
groupSyncable := &model.GroupSyncable{
GroupId: group.Id,
AutoAdd: false,
SyncableId: th.BasicChannel.Id,
Type: model.GroupSyncableTypeChannel,
}
gs, err := th.App.CreateGroupSyncable(groupSyncable)
require.Nil(t, err)
require.NotNil(t, gs)
groups, err := th.App.GetGroupsByChannel(th.BasicChannel.Id, 0, 60)
require.Nil(t, err)
require.ElementsMatch(t, []*model.Group{group}, groups)
groups, err = th.App.GetGroupsByChannel(model.NewId(), 0, 60)
require.Nil(t, err)
require.Empty(t, groups)
}
func TestGetGroupsByTeam(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
group := th.CreateGroup()
// Create a group team
groupSyncable := &model.GroupSyncable{
GroupId: group.Id,
AutoAdd: false,
SyncableId: th.BasicTeam.Id,
Type: model.GroupSyncableTypeTeam,
}
gs, err := th.App.CreateGroupSyncable(groupSyncable)
require.Nil(t, err)
require.NotNil(t, gs)
groups, err := th.App.GetGroupsByTeam(th.BasicTeam.Id, 0, 60)
require.Nil(t, err)
require.ElementsMatch(t, []*model.Group{group}, groups)
groups, err = th.App.GetGroupsByTeam(model.NewId(), 0, 60)
require.Nil(t, err)
require.Empty(t, groups)
}

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

@@ -3290,6 +3290,30 @@ func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response) {
return GroupFromJson(r.Body), BuildResponse(r) return GroupFromJson(r.Body), BuildResponse(r)
} }
// GetLdapGroupsByChannel retrieves the Mattermost Groups associated with a given channel
func (c *Client4) GetGroupsByChannel(channelId string, page, perPage int) ([]*Group, *Response) {
path := fmt.Sprintf("%s/groups?page=%v&per_page=%v", c.GetChannelRoute(channelId), page, perPage)
r, appErr := c.DoApiGet(path, "")
if appErr != nil {
return nil, BuildErrorResponse(r, appErr)
}
defer closeBody(r)
return GroupsFromJson(r.Body), BuildResponse(r)
}
// GetLdapGroupsByTeam retrieves the Mattermost Groups associated with a given team
func (c *Client4) GetGroupsByTeam(teamId string, page, perPage int) ([]*Group, *Response) {
path := fmt.Sprintf("%s/groups?page=%v&per_page=%v", c.GetTeamRoute(teamId), page, perPage)
r, appErr := c.DoApiGet(path, "")
if appErr != nil {
return nil, BuildErrorResponse(r, appErr)
}
defer closeBody(r)
return GroupsFromJson(r.Body), BuildResponse(r)
}
// Audits Section // Audits Section
// GetAudits returns a list of audits for the whole system. // GetAudits returns a list of audits for the whole system.

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

@@ -477,3 +477,15 @@ func (s *LayeredGroupStore) ChannelMembersToRemove() StoreChannel {
return supplier.ChannelMembersToRemove(s.TmpContext) return supplier.ChannelMembersToRemove(s.TmpContext)
}) })
} }
func (s *LayeredGroupStore) GetGroupsByChannel(channelId string, page, perPage int) StoreChannel {
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
return supplier.GetGroupsByChannel(s.TmpContext, channelId, page, perPage)
})
}
func (s *LayeredGroupStore) GetGroupsByTeam(teamId string, page, perPage int) StoreChannel {
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
return supplier.GetGroupsByTeam(s.TmpContext, teamId, page, perPage)
})
}

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

@@ -73,4 +73,7 @@ type LayeredStoreSupplier interface {
TeamMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult TeamMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
GetGroupsByChannel(ctx context.Context, channelId string, page, perPage int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
GetGroupsByTeam(ctx context.Context, teamId string, page, perPage int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
} }

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

@@ -108,3 +108,11 @@ func (s *LocalCacheSupplier) TeamMembersToRemove(ctx context.Context, hints ...L
func (s *LocalCacheSupplier) ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult { func (s *LocalCacheSupplier) ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
return s.Next().ChannelMembersToRemove(ctx, hints...) return s.Next().ChannelMembersToRemove(ctx, hints...)
} }
func (s *LocalCacheSupplier) GetGroupsByChannel(ctx context.Context, channelId string, page, perPage int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
return s.Next().GetGroupsByChannel(ctx, channelId, page, perPage, hints...)
}
func (s *LocalCacheSupplier) GetGroupsByTeam(ctx context.Context, teamId string, page, perPage int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
return s.Next().GetGroupsByTeam(ctx, teamId, page, perPage, hints...)
}

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

@@ -108,3 +108,13 @@ func (s *RedisSupplier) ChannelMembersToRemove(ctx context.Context, hints ...Lay
// TODO: Redis caching. // TODO: Redis caching.
return s.Next().ChannelMembersToRemove(ctx, hints...) return s.Next().ChannelMembersToRemove(ctx, hints...)
} }
func (s *RedisSupplier) GetGroupsByChannel(ctx context.Context, channelId string, page, perPage int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
// TODO: Redis caching.
return s.Next().GetGroupsByChannel(ctx, channelId, page, perPage, hints...)
}
func (s *RedisSupplier) GetGroupsByTeam(ctx context.Context, teamId string, page, perPage int, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
// TODO: Redis caching.
return s.Next().GetGroupsByTeam(ctx, teamId, page, perPage, hints...)
}

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

@@ -222,13 +222,13 @@ func (s *SqlSupplier) GroupGetMemberUsers(stc context.Context, groupID string, h
var groupMembers []*model.User var groupMembers []*model.User
query := ` query := `
SELECT SELECT
Users.* Users.*
FROM FROM
GroupMembers GroupMembers
JOIN Users ON Users.Id = GroupMembers.UserId JOIN Users ON Users.Id = GroupMembers.UserId
WHERE WHERE
GroupMembers.DeleteAt = 0 GroupMembers.DeleteAt = 0
AND Users.DeleteAt = 0 AND Users.DeleteAt = 0
AND GroupId = :GroupId` AND GroupId = :GroupId`
@@ -248,13 +248,13 @@ func (s *SqlSupplier) GroupGetMemberUsersPage(stc context.Context, groupID strin
var groupMembers []*model.User var groupMembers []*model.User
query := ` query := `
SELECT SELECT
Users.* Users.*
FROM FROM
GroupMembers GroupMembers
JOIN Users ON Users.Id = GroupMembers.UserId JOIN Users ON Users.Id = GroupMembers.UserId
WHERE WHERE
GroupMembers.DeleteAt = 0 GroupMembers.DeleteAt = 0
AND Users.DeleteAt = 0 AND Users.DeleteAt = 0
AND GroupId = :GroupId AND GroupId = :GroupId
ORDER BY ORDER BY
@@ -281,11 +281,11 @@ func (s *SqlSupplier) GroupGetMemberCount(stc context.Context, groupID string, h
var err error var err error
query := ` query := `
SELECT SELECT
count(*) count(*)
FROM FROM
GroupMembers GroupMembers
WHERE WHERE
GroupMembers.GroupId = :GroupId` GroupMembers.GroupId = :GroupId`
if count, err = s.GetReplica().SelectInt(query, map[string]interface{}{"GroupId": groupID}); err != nil { if count, err = s.GetReplica().SelectInt(query, map[string]interface{}{"GroupId": groupID}); err != nil {
@@ -506,13 +506,13 @@ func (s *SqlSupplier) GroupGetAllGroupSyncablesByGroup(ctx context.Context, grou
case model.GroupSyncableTypeTeam: case model.GroupSyncableTypeTeam:
sqlQuery := ` sqlQuery := `
SELECT SELECT
GroupTeams.*, GroupTeams.*,
Teams.DisplayName AS TeamDisplayName, Teams.DisplayName AS TeamDisplayName,
Teams.Type AS TeamType Teams.Type AS TeamType
FROM FROM
GroupTeams GroupTeams
JOIN Teams ON Teams.Id = GroupTeams.TeamId JOIN Teams ON Teams.Id = GroupTeams.TeamId
WHERE WHERE
GroupId = :GroupId AND GroupTeams.DeleteAt = 0` GroupId = :GroupId AND GroupTeams.DeleteAt = 0`
results := []*groupTeamJoin{} results := []*groupTeamJoin{}
@@ -538,17 +538,17 @@ func (s *SqlSupplier) GroupGetAllGroupSyncablesByGroup(ctx context.Context, grou
case model.GroupSyncableTypeChannel: case model.GroupSyncableTypeChannel:
sqlQuery := ` sqlQuery := `
SELECT SELECT
GroupChannels.*, GroupChannels.*,
Channels.DisplayName AS ChannelDisplayName, Channels.DisplayName AS ChannelDisplayName,
Teams.DisplayName AS TeamDisplayName, Teams.DisplayName AS TeamDisplayName,
Channels.Type As ChannelType, Channels.Type As ChannelType,
Teams.Type As TeamType, Teams.Type As TeamType,
Teams.Id AS TeamId Teams.Id AS TeamId
FROM FROM
GroupChannels GroupChannels
JOIN Channels ON Channels.Id = GroupChannels.ChannelId JOIN Channels ON Channels.Id = GroupChannels.ChannelId
JOIN Teams ON Teams.Id = Channels.TeamId JOIN Teams ON Teams.Id = Channels.TeamId
WHERE WHERE
GroupId = :GroupId AND GroupChannels.DeleteAt = 0` GroupId = :GroupId AND GroupChannels.DeleteAt = 0`
results := []*groupChannelJoin{} results := []*groupChannelJoin{}
@@ -676,19 +676,19 @@ func (s *SqlSupplier) TeamMembersToAdd(ctx context.Context, since int64, hints .
result := store.NewSupplierResult() result := store.NewSupplierResult()
sql := ` sql := `
SELECT SELECT
GroupMembers.UserId, GroupTeams.TeamId GroupMembers.UserId, GroupTeams.TeamId
FROM FROM
GroupMembers GroupMembers
JOIN GroupTeams JOIN GroupTeams
ON GroupTeams.GroupId = GroupMembers.GroupId ON GroupTeams.GroupId = GroupMembers.GroupId
JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId
JOIN Teams ON Teams.Id = GroupTeams.TeamId JOIN Teams ON Teams.Id = GroupTeams.TeamId
LEFT OUTER JOIN TeamMembers LEFT OUTER JOIN TeamMembers
ON ON
TeamMembers.TeamId = GroupTeams.TeamId TeamMembers.TeamId = GroupTeams.TeamId
AND TeamMembers.UserId = GroupMembers.UserId AND TeamMembers.UserId = GroupMembers.UserId
WHERE WHERE
TeamMembers.UserId IS NULL TeamMembers.UserId IS NULL
AND UserGroups.DeleteAt = 0 AND UserGroups.DeleteAt = 0
AND GroupTeams.DeleteAt = 0 AND GroupTeams.DeleteAt = 0
@@ -718,16 +718,16 @@ func (s *SqlSupplier) ChannelMembersToAdd(ctx context.Context, since int64, hint
result := store.NewSupplierResult() result := store.NewSupplierResult()
sql := ` sql := `
SELECT SELECT
GroupMembers.UserId, GroupChannels.ChannelId GroupMembers.UserId, GroupChannels.ChannelId
FROM FROM
GroupMembers GroupMembers
JOIN GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId JOIN GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId
JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId
JOIN Channels ON Channels.Id = GroupChannels.ChannelId JOIN Channels ON Channels.Id = GroupChannels.ChannelId
LEFT OUTER JOIN ChannelMemberHistory LEFT OUTER JOIN ChannelMemberHistory
ON ON
ChannelMemberHistory.ChannelId = GroupChannels.ChannelId ChannelMemberHistory.ChannelId = GroupChannels.ChannelId
AND ChannelMemberHistory.UserId = GroupMembers.UserId AND ChannelMemberHistory.UserId = GroupMembers.UserId
WHERE WHERE
ChannelMemberHistory.UserId IS NULL ChannelMemberHistory.UserId IS NULL
@@ -811,6 +811,40 @@ func (s *SqlSupplier) TeamMembersToRemove(ctx context.Context, hints ...store.La
return result return result
} }
func (s *SqlSupplier) GetGroupsByChannel(ctx context.Context, channelId string, page, perPage int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
result := store.NewSupplierResult()
var groups []*model.Group
offset := page * perPage
_, err := s.GetReplica().Select(&groups, `
SELECT
ug.*
FROM
GroupChannels gc
LEFT JOIN
UserGroups ug
ON
gc.GroupId = ug.Id
WHERE
ug.DeleteAt = 0
AND
gc.ChannelId = :ChannelId
ORDER BY
ug.DisplayName
LIMIT :Limit
OFFSET :Offset`,
map[string]interface{}{"ChannelId": channelId, "Limit": perPage, "Offset": offset})
if err != nil {
result.Err = model.NewAppError("SqlGroupStore.GetGroupsByChannel", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
return result
}
result.Data = groups
return result
}
// ChannelMembersToRemove returns all channel members that should be removed based on group constraints. // ChannelMembersToRemove returns all channel members that should be removed based on group constraints.
func (s *SqlSupplier) ChannelMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult { func (s *SqlSupplier) ChannelMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
result := store.NewSupplierResult() result := store.NewSupplierResult()
@@ -854,3 +888,37 @@ func (s *SqlSupplier) ChannelMembersToRemove(ctx context.Context, hints ...store
return result return result
} }
func (s *SqlSupplier) GetGroupsByTeam(ctx context.Context, teamId string, page, perPage int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
result := store.NewSupplierResult()
var groups []*model.Group
offset := page * perPage
_, err := s.GetReplica().Select(&groups, `
SELECT
ug.*
FROM
GroupTeams gt
LEFT JOIN
UserGroups ug
ON
gt.GroupId = ug.Id
WHERE
ug.DeleteAt = 0
AND
gt.TeamId = :TeamId
ORDER BY
ug.DisplayName
LIMIT :Limit
OFFSET :Offset`,
map[string]interface{}{"TeamId": teamId, "Limit": perPage, "Offset": offset})
if err != nil {
result.Err = model.NewAppError("SqlGroupStore.GetGroupsByTeam", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
return result
}
result.Data = groups
return result
}

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

@@ -585,6 +585,9 @@ type GroupStore interface {
TeamMembersToRemove() StoreChannel TeamMembersToRemove() StoreChannel
ChannelMembersToRemove() StoreChannel ChannelMembersToRemove() StoreChannel
GetGroupsByChannel(channelId string, page, perPage int) StoreChannel
GetGroupsByTeam(teamId string, page, perPage int) StoreChannel
} }
type LinkMetadataStore interface { type LinkMetadataStore interface {

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

@@ -36,6 +36,9 @@ func TestGroupStore(t *testing.T, ss store.Store) {
t.Run("TeamMembersToRemove", func(t *testing.T) { testPendingTeamMemberRemovals(t, ss) }) t.Run("TeamMembersToRemove", func(t *testing.T) { testPendingTeamMemberRemovals(t, ss) })
t.Run("ChannelMembersToRemove", func(t *testing.T) { testPendingChannelMemberRemovals(t, ss) }) t.Run("ChannelMembersToRemove", func(t *testing.T) { testPendingChannelMemberRemovals(t, ss) })
t.Run("GetGroupsByChannel", func(t *testing.T) { testGetGroupsByChannel(t, ss) })
t.Run("GetGroupsByTeam", func(t *testing.T) { testGetGroupsByTeam(t, ss) })
} }
func testGroupStoreCreate(t *testing.T, ss store.Store) { func testGroupStoreCreate(t *testing.T, ss store.Store) {
@@ -1507,3 +1510,261 @@ func pendingMemberRemovalsDataSetup(t *testing.T, ss store.Store) *removalsData
Group: group, Group: group,
} }
} }
func testGetGroupsByChannel(t *testing.T, ss store.Store) {
// Create Channel1
channel1 := &model.Channel{
TeamId: model.NewId(),
DisplayName: "Channel1",
Name: model.NewId(),
Type: model.CHANNEL_OPEN,
}
res := <-ss.Channel().Save(channel1, 9999)
require.Nil(t, res.Err)
channel1 = res.Data.(*model.Channel)
// Create Groups 1 and 2
res = <-ss.Group().Create(&model.Group{
Name: model.NewId(),
DisplayName: "group-1",
RemoteId: model.NewId(),
Source: model.GroupSourceLdap,
})
require.Nil(t, res.Err)
group1 := res.Data.(*model.Group)
res = <-ss.Group().Create(&model.Group{
Name: model.NewId(),
DisplayName: "group-2",
RemoteId: model.NewId(),
Source: model.GroupSourceLdap,
})
require.Nil(t, res.Err)
group2 := res.Data.(*model.Group)
// And associate them with Channel1
for _, g := range []*model.Group{group1, group2} {
res = <-ss.Group().CreateGroupSyncable(&model.GroupSyncable{
AutoAdd: true,
SyncableId: channel1.Id,
Type: model.GroupSyncableTypeChannel,
GroupId: g.Id,
})
require.Nil(t, res.Err)
}
// Create Channel2
channel2 := &model.Channel{
TeamId: model.NewId(),
DisplayName: "Channel2",
Name: model.NewId(),
Type: model.CHANNEL_OPEN,
}
res = <-ss.Channel().Save(channel2, 9999)
require.Nil(t, res.Err)
channel2 = res.Data.(*model.Channel)
// Create Group3
res = <-ss.Group().Create(&model.Group{
Name: model.NewId(),
DisplayName: "group-3",
RemoteId: model.NewId(),
Source: model.GroupSourceLdap,
})
require.Nil(t, res.Err)
group3 := res.Data.(*model.Group)
// And associate it to Channel2
res = <-ss.Group().CreateGroupSyncable(&model.GroupSyncable{
AutoAdd: true,
SyncableId: channel2.Id,
Type: model.GroupSyncableTypeChannel,
GroupId: group3.Id,
})
require.Nil(t, res.Err)
testCases := []struct {
Name string
ChannelId string
Page int
PerPage int
Result []*model.Group
}{
{
Name: "Get the two Groups for Channel1",
ChannelId: channel1.Id,
Page: 0,
PerPage: 60,
Result: []*model.Group{group1, group2},
},
{
Name: "Get first Group for Channel1 with page 0 with 1 element",
ChannelId: channel1.Id,
Page: 0,
PerPage: 1,
Result: []*model.Group{group1},
},
{
Name: "Get second Group for Channel1 with page 1 with 1 element",
ChannelId: channel1.Id,
Page: 1,
PerPage: 1,
Result: []*model.Group{group2},
},
{
Name: "Get third Group for Channel2",
ChannelId: channel2.Id,
Page: 0,
PerPage: 60,
Result: []*model.Group{group3},
},
{
Name: "Get empty Groups for a fake id",
ChannelId: model.NewId(),
Page: 0,
PerPage: 60,
Result: []*model.Group{},
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
res := <-ss.Group().GetGroupsByChannel(tc.ChannelId, tc.Page, tc.PerPage)
require.Nil(t, res.Err)
require.ElementsMatch(t, tc.Result, res.Data.([]*model.Group))
})
}
}
func testGetGroupsByTeam(t *testing.T, ss store.Store) {
// Create Team1
team1 := &model.Team{
DisplayName: "Team1",
Description: model.NewId(),
CompanyName: model.NewId(),
AllowOpenInvite: false,
InviteId: model.NewId(),
Name: model.NewId(),
Email: "success+" + model.NewId() + "@simulator.amazonses.com",
Type: model.TEAM_OPEN,
}
res := <-ss.Team().Save(team1)
require.Nil(t, res.Err)
team1 = res.Data.(*model.Team)
// Create Groups 1 and 2
res = <-ss.Group().Create(&model.Group{
Name: model.NewId(),
DisplayName: "group-1",
RemoteId: model.NewId(),
Source: model.GroupSourceLdap,
})
require.Nil(t, res.Err)
group1 := res.Data.(*model.Group)
res = <-ss.Group().Create(&model.Group{
Name: model.NewId(),
DisplayName: "group-2",
RemoteId: model.NewId(),
Source: model.GroupSourceLdap,
})
require.Nil(t, res.Err)
group2 := res.Data.(*model.Group)
// And associate them with Team1
for _, g := range []*model.Group{group1, group2} {
res = <-ss.Group().CreateGroupSyncable(&model.GroupSyncable{
AutoAdd: true,
SyncableId: team1.Id,
Type: model.GroupSyncableTypeTeam,
GroupId: g.Id,
})
require.Nil(t, res.Err)
}
// Create Team2
team2 := &model.Team{
DisplayName: "Team2",
Description: model.NewId(),
CompanyName: model.NewId(),
AllowOpenInvite: false,
InviteId: model.NewId(),
Name: model.NewId(),
Email: "success+" + model.NewId() + "@simulator.amazonses.com",
Type: model.TEAM_INVITE,
}
res = <-ss.Team().Save(team2)
require.Nil(t, res.Err)
team2 = res.Data.(*model.Team)
// Create Group3
res = <-ss.Group().Create(&model.Group{
Name: model.NewId(),
DisplayName: "group-3",
RemoteId: model.NewId(),
Source: model.GroupSourceLdap,
})
require.Nil(t, res.Err)
group3 := res.Data.(*model.Group)
// And associate it to Team2
res = <-ss.Group().CreateGroupSyncable(&model.GroupSyncable{
AutoAdd: true,
SyncableId: team2.Id,
Type: model.GroupSyncableTypeTeam,
GroupId: group3.Id,
})
require.Nil(t, res.Err)
testCases := []struct {
Name string
TeamId string
Page int
PerPage int
Result []*model.Group
}{
{
Name: "Get the two Groups for Team1",
TeamId: team1.Id,
Page: 0,
PerPage: 60,
Result: []*model.Group{group1, group2},
},
{
Name: "Get first Group for Team1 with page 0 with 1 element",
TeamId: team1.Id,
Page: 0,
PerPage: 1,
Result: []*model.Group{group1},
},
{
Name: "Get second Group for Team1 with page 1 with 1 element",
TeamId: team1.Id,
Page: 1,
PerPage: 1,
Result: []*model.Group{group2},
},
{
Name: "Get third Group for Team2",
TeamId: team2.Id,
Page: 0,
PerPage: 60,
Result: []*model.Group{group3},
},
{
Name: "Get empty Groups for a fake id",
TeamId: model.NewId(),
Page: 0,
PerPage: 60,
Result: []*model.Group{},
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
res := <-ss.Group().GetGroupsByTeam(tc.TeamId, tc.Page, tc.PerPage)
require.Nil(t, res.Err)
require.ElementsMatch(t, tc.Result, res.Data.([]*model.Group))
})
}
}

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

@@ -189,6 +189,38 @@ func (_m *GroupStore) GetGroupSyncable(groupID string, syncableID string, syncab
return r0 return r0
} }
// GetGroupsByChannel provides a mock function with given fields: channelId, page, perPage
func (_m *GroupStore) GetGroupsByChannel(channelId string, page int, perPage int) store.StoreChannel {
ret := _m.Called(channelId, page, perPage)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok {
r0 = rf(channelId, page, perPage)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}
// GetGroupsByTeam provides a mock function with given fields: teamId, page, perPage
func (_m *GroupStore) GetGroupsByTeam(teamId string, page int, perPage int) store.StoreChannel {
ret := _m.Called(teamId, page, perPage)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok {
r0 = rf(teamId, page, perPage)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}
// GetMemberCount provides a mock function with given fields: groupID // GetMemberCount provides a mock function with given fields: groupID
func (_m *GroupStore) GetMemberCount(groupID string) store.StoreChannel { func (_m *GroupStore) GetMemberCount(groupID string) store.StoreChannel {
ret := _m.Called(groupID) ret := _m.Called(groupID)

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

@@ -184,6 +184,52 @@ func (_m *LayeredStoreDatabaseLayer) FileInfo() store.FileInfoStore {
return r0 return r0
} }
// GetGroupsByChannel provides a mock function with given fields: ctx, channelId, page, perPage, hints
func (_m *LayeredStoreDatabaseLayer) GetGroupsByChannel(ctx context.Context, channelId string, page int, perPage int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))
for _i := range hints {
_va[_i] = hints[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, channelId, page, perPage)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *store.LayeredStoreSupplierResult
if rf, ok := ret.Get(0).(func(context.Context, string, int, int, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
r0 = rf(ctx, channelId, page, perPage, hints...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
}
}
return r0
}
// GetGroupsByTeam provides a mock function with given fields: ctx, teamId, page, perPage, hints
func (_m *LayeredStoreDatabaseLayer) GetGroupsByTeam(ctx context.Context, teamId string, page int, perPage int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))
for _i := range hints {
_va[_i] = hints[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, teamId, page, perPage)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *store.LayeredStoreSupplierResult
if rf, ok := ret.Get(0).(func(context.Context, string, int, int, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
r0 = rf(ctx, teamId, page, perPage, hints...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
}
}
return r0
}
// Group provides a mock function with given fields: // Group provides a mock function with given fields:
func (_m *LayeredStoreDatabaseLayer) Group() store.GroupStore { func (_m *LayeredStoreDatabaseLayer) Group() store.GroupStore {
ret := _m.Called() ret := _m.Called()

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

@@ -14,6 +14,52 @@ type LayeredStoreSupplier struct {
mock.Mock mock.Mock
} }
// GetGroupsByChannel provides a mock function with given fields: ctx, channelId, page, perPage, hints
func (_m *LayeredStoreSupplier) GetGroupsByChannel(ctx context.Context, channelId string, page int, perPage int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))
for _i := range hints {
_va[_i] = hints[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, channelId, page, perPage)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *store.LayeredStoreSupplierResult
if rf, ok := ret.Get(0).(func(context.Context, string, int, int, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
r0 = rf(ctx, channelId, page, perPage, hints...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
}
}
return r0
}
// GetGroupsByTeam provides a mock function with given fields: ctx, teamId, page, perPage, hints
func (_m *LayeredStoreSupplier) GetGroupsByTeam(ctx context.Context, teamId string, page int, perPage int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints))
for _i := range hints {
_va[_i] = hints[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, teamId, page, perPage)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *store.LayeredStoreSupplierResult
if rf, ok := ret.Get(0).(func(context.Context, string, int, int, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
r0 = rf(ctx, teamId, page, perPage, hints...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
}
}
return r0
}
// GroupCreate provides a mock function with given fields: ctx, group, hints // GroupCreate provides a mock function with given fields: ctx, group, hints
func (_m *LayeredStoreSupplier) GroupCreate(ctx context.Context, group *model.Group, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult { func (_m *LayeredStoreSupplier) GroupCreate(ctx context.Context, group *model.Group, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
_va := make([]interface{}, len(hints)) _va := make([]interface{}, len(hints))