[MM-14751] Adds group_constrained filter to user list and search endpoints (#10678)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
beb7592c93
Коммит
098dbc84cc
16
api4/user.go
16
api4/user.go
@@ -452,6 +452,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
notInTeamId := r.URL.Query().Get("not_in_team")
|
notInTeamId := r.URL.Query().Get("not_in_team")
|
||||||
inChannelId := r.URL.Query().Get("in_channel")
|
inChannelId := r.URL.Query().Get("in_channel")
|
||||||
notInChannelId := r.URL.Query().Get("not_in_channel")
|
notInChannelId := r.URL.Query().Get("not_in_channel")
|
||||||
|
groupConstrained := r.URL.Query().Get("group_constrained")
|
||||||
withoutTeam := r.URL.Query().Get("without_team")
|
withoutTeam := r.URL.Query().Get("without_team")
|
||||||
inactive := r.URL.Query().Get("inactive")
|
inactive := r.URL.Query().Get("inactive")
|
||||||
role := r.URL.Query().Get("role")
|
role := r.URL.Query().Get("role")
|
||||||
@@ -479,6 +480,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
withoutTeamBool, _ := strconv.ParseBool(withoutTeam)
|
withoutTeamBool, _ := strconv.ParseBool(withoutTeam)
|
||||||
|
groupConstrainedBool, _ := strconv.ParseBool(groupConstrained)
|
||||||
inactiveBool, _ := strconv.ParseBool(inactive)
|
inactiveBool, _ := strconv.ParseBool(inactive)
|
||||||
|
|
||||||
restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
|
restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
|
||||||
@@ -492,6 +494,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
InChannelId: inChannelId,
|
InChannelId: inChannelId,
|
||||||
NotInTeamId: notInTeamId,
|
NotInTeamId: notInTeamId,
|
||||||
NotInChannelId: notInChannelId,
|
NotInChannelId: notInChannelId,
|
||||||
|
GroupConstrained: groupConstrainedBool,
|
||||||
WithoutTeam: withoutTeamBool,
|
WithoutTeam: withoutTeamBool,
|
||||||
Inactive: inactiveBool,
|
Inactive: inactiveBool,
|
||||||
Role: role,
|
Role: role,
|
||||||
@@ -518,7 +521,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
|
profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
|
||||||
} else if len(notInTeamId) > 0 {
|
} else if len(notInTeamId) > 0 {
|
||||||
if !c.App.SessionHasPermissionToTeam(c.App.Session, notInTeamId, model.PERMISSION_VIEW_TEAM) {
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, notInTeamId, model.PERMISSION_VIEW_TEAM) {
|
||||||
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
||||||
@@ -530,7 +533,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
|
profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
|
||||||
} else if len(inTeamId) > 0 {
|
} else if len(inTeamId) > 0 {
|
||||||
if !c.App.SessionHasPermissionToTeam(c.App.Session, inTeamId, model.PERMISSION_VIEW_TEAM) {
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, inTeamId, model.PERMISSION_VIEW_TEAM) {
|
||||||
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
||||||
@@ -673,10 +676,11 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
options := &model.UserSearchOptions{
|
options := &model.UserSearchOptions{
|
||||||
IsAdmin: c.IsSystemAdmin(),
|
IsAdmin: c.IsSystemAdmin(),
|
||||||
AllowInactive: props.AllowInactive,
|
AllowInactive: props.AllowInactive,
|
||||||
Limit: props.Limit,
|
GroupConstrained: props.GroupConstrained,
|
||||||
Role: props.Role,
|
Limit: props.Limit,
|
||||||
|
Role: props.Role,
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
if c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
||||||
|
|||||||
20
app/user.go
20
app/user.go
@@ -472,8 +472,8 @@ func (a *App) GetUsersInTeam(options *model.UserGetOptions) ([]*model.User, *mod
|
|||||||
return result.Data.([]*model.User), nil
|
return result.Data.([]*model.User), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetUsersNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
func (a *App) GetUsersNotInTeam(teamId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
||||||
result := <-a.Srv.Store.User().GetProfilesNotInTeam(teamId, offset, limit, viewRestrictions)
|
result := <-a.Srv.Store.User().GetProfilesNotInTeam(teamId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
if result.Err != nil {
|
if result.Err != nil {
|
||||||
return nil, result.Err
|
return nil, result.Err
|
||||||
}
|
}
|
||||||
@@ -489,8 +489,8 @@ func (a *App) GetUsersInTeamPage(options *model.UserGetOptions, asAdmin bool) ([
|
|||||||
return a.sanitizeProfiles(users, asAdmin), nil
|
return a.sanitizeProfiles(users, asAdmin), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetUsersNotInTeamPage(teamId string, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
func (a *App) GetUsersNotInTeamPage(teamId string, groupConstrained bool, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
||||||
users, err := a.GetUsersNotInTeam(teamId, page*perPage, perPage, viewRestrictions)
|
users, err := a.GetUsersNotInTeam(teamId, groupConstrained, page*perPage, perPage, viewRestrictions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -554,16 +554,16 @@ func (a *App) GetUsersInChannelPageByStatus(channelId string, page int, perPage
|
|||||||
return a.sanitizeProfiles(users, asAdmin), nil
|
return a.sanitizeProfiles(users, asAdmin), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetUsersNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
func (a *App) GetUsersNotInChannel(teamId string, channelId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
||||||
result := <-a.Srv.Store.User().GetProfilesNotInChannel(teamId, channelId, offset, limit, viewRestrictions)
|
result := <-a.Srv.Store.User().GetProfilesNotInChannel(teamId, channelId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
if result.Err != nil {
|
if result.Err != nil {
|
||||||
return nil, result.Err
|
return nil, result.Err
|
||||||
}
|
}
|
||||||
return result.Data.([]*model.User), nil
|
return result.Data.([]*model.User), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetUsersNotInChannelMap(teamId string, channelId string, offset int, limit int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) (map[string]*model.User, *model.AppError) {
|
func (a *App) GetUsersNotInChannelMap(teamId string, channelId string, groupConstrained bool, offset int, limit int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) (map[string]*model.User, *model.AppError) {
|
||||||
users, err := a.GetUsersNotInChannel(teamId, channelId, offset, limit, viewRestrictions)
|
users, err := a.GetUsersNotInChannel(teamId, channelId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -578,8 +578,8 @@ func (a *App) GetUsersNotInChannelMap(teamId string, channelId string, offset in
|
|||||||
return userMap, nil
|
return userMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetUsersNotInChannelPage(teamId string, channelId string, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
func (a *App) GetUsersNotInChannelPage(teamId string, channelId string, groupConstrained bool, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
|
||||||
users, err := a.GetUsersNotInChannel(teamId, channelId, page*perPage, perPage, viewRestrictions)
|
users, err := a.GetUsersNotInChannel(teamId, channelId, groupConstrained, page*perPage, perPage, viewRestrictions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ func TestResctrictedViewMembers(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.Name, func(t *testing.T) {
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
results, err := th.App.GetUsersNotInTeam(tc.TeamId, 0, 100, tc.Restrictions)
|
results, err := th.App.GetUsersNotInTeam(tc.TeamId, false, 0, 100, tc.Restrictions)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
ids := []string{}
|
ids := []string{}
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
@@ -775,7 +775,7 @@ func TestResctrictedViewMembers(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.Name, func(t *testing.T) {
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
results, err := th.App.GetUsersNotInChannel(tc.TeamId, tc.ChannelId, 0, 100, tc.Restrictions)
|
results, err := th.App.GetUsersNotInChannel(tc.TeamId, tc.ChannelId, false, 0, 100, tc.Restrictions)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
ids := []string{}
|
ids := []string{}
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ type UserGetOptions struct {
|
|||||||
InChannelId string
|
InChannelId string
|
||||||
// Filters the users not in the channel
|
// Filters the users not in the channel
|
||||||
NotInChannelId string
|
NotInChannelId string
|
||||||
|
// Filters the users group constrained
|
||||||
|
GroupConstrained bool
|
||||||
// Filters the users without a team
|
// Filters the users without a team
|
||||||
WithoutTeam bool
|
WithoutTeam bool
|
||||||
// Filters the inactive users
|
// Filters the inactive users
|
||||||
|
|||||||
@@ -13,15 +13,16 @@ const USER_SEARCH_DEFAULT_LIMIT = 100
|
|||||||
|
|
||||||
// UserSearch captures the parameters provided by a client for initiating a user search.
|
// UserSearch captures the parameters provided by a client for initiating a user search.
|
||||||
type UserSearch struct {
|
type UserSearch struct {
|
||||||
Term string `json:"term"`
|
Term string `json:"term"`
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
NotInTeamId string `json:"not_in_team_id"`
|
NotInTeamId string `json:"not_in_team_id"`
|
||||||
InChannelId string `json:"in_channel_id"`
|
InChannelId string `json:"in_channel_id"`
|
||||||
NotInChannelId string `json:"not_in_channel_id"`
|
NotInChannelId string `json:"not_in_channel_id"`
|
||||||
AllowInactive bool `json:"allow_inactive"`
|
GroupConstrained bool `json:"group_constrained"`
|
||||||
WithoutTeam bool `json:"without_team"`
|
AllowInactive bool `json:"allow_inactive"`
|
||||||
Limit int `json:"limit"`
|
WithoutTeam bool `json:"without_team"`
|
||||||
Role string `json:"role"`
|
Limit int `json:"limit"`
|
||||||
|
Role string `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJson convert a User to a json string
|
// ToJson convert a User to a json string
|
||||||
@@ -53,6 +54,8 @@ type UserSearchOptions struct {
|
|||||||
AllowFullNames bool
|
AllowFullNames bool
|
||||||
// AllowInactive configures whether or not to return inactive users in the search results.
|
// AllowInactive configures whether or not to return inactive users in the search results.
|
||||||
AllowInactive bool
|
AllowInactive bool
|
||||||
|
// Narrows the search to the group constrained users
|
||||||
|
GroupConstrained bool
|
||||||
// Limit limits the total number of results returned.
|
// Limit limits the total number of results returned.
|
||||||
Limit int
|
Limit int
|
||||||
// Filters for the given role
|
// Filters for the given role
|
||||||
|
|||||||
@@ -448,6 +448,54 @@ func applyRoleFilter(query sq.SelectBuilder, role string, isPostgreSQL bool) sq.
|
|||||||
return query.Where("u.Roles LIKE ? ESCAPE '*'", roleParam)
|
return query.Where("u.Roles LIKE ? ESCAPE '*'", roleParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyChannelGroupConstrainedFilter(query sq.SelectBuilder, channelId string) sq.SelectBuilder {
|
||||||
|
if channelId == "" {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.
|
||||||
|
Where(`u.Id IN (
|
||||||
|
SELECT
|
||||||
|
GroupMembers.UserId
|
||||||
|
FROM
|
||||||
|
Channels
|
||||||
|
JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id
|
||||||
|
JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId
|
||||||
|
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
||||||
|
WHERE
|
||||||
|
Channels.Id = ?
|
||||||
|
AND GroupChannels.DeleteAt = 0
|
||||||
|
AND UserGroups.DeleteAt = 0
|
||||||
|
AND GroupMembers.DeleteAt = 0
|
||||||
|
GROUP BY
|
||||||
|
GroupMembers.UserId
|
||||||
|
)`, channelId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyTeamGroupConstrainedFilter(query sq.SelectBuilder, teamId string) sq.SelectBuilder {
|
||||||
|
if teamId == "" {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.
|
||||||
|
Where(`u.Id IN (
|
||||||
|
SELECT
|
||||||
|
GroupMembers.UserId
|
||||||
|
FROM
|
||||||
|
Teams
|
||||||
|
JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id
|
||||||
|
JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId
|
||||||
|
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
||||||
|
WHERE
|
||||||
|
Teams.Id = ?
|
||||||
|
AND GroupTeams.DeleteAt = 0
|
||||||
|
AND UserGroups.DeleteAt = 0
|
||||||
|
AND GroupMembers.DeleteAt = 0
|
||||||
|
GROUP BY
|
||||||
|
GroupMembers.UserId
|
||||||
|
)`, teamId)
|
||||||
|
}
|
||||||
|
|
||||||
func (s SqlUserStore) GetEtagForProfiles(teamId string) store.StoreChannel {
|
func (s SqlUserStore) GetEtagForProfiles(teamId string) store.StoreChannel {
|
||||||
return store.Do(func(result *store.StoreResult) {
|
return store.Do(func(result *store.StoreResult) {
|
||||||
updateAt, err := s.GetReplica().SelectInt("SELECT UpdateAt FROM Users, TeamMembers WHERE TeamMembers.TeamId = :TeamId AND Users.Id = TeamMembers.UserId ORDER BY UpdateAt DESC LIMIT 1", map[string]interface{}{"TeamId": teamId})
|
updateAt, err := s.GetReplica().SelectInt("SELECT UpdateAt FROM Users, TeamMembers WHERE TeamMembers.TeamId = :TeamId AND Users.Id = TeamMembers.UserId ORDER BY UpdateAt DESC LIMIT 1", map[string]interface{}{"TeamId": teamId})
|
||||||
@@ -636,7 +684,7 @@ func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
||||||
return store.Do(func(result *store.StoreResult) {
|
return store.Do(func(result *store.StoreResult) {
|
||||||
query := us.usersQuery.
|
query := us.usersQuery.
|
||||||
Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
|
Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
|
||||||
@@ -647,6 +695,10 @@ func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string,
|
|||||||
|
|
||||||
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
|
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
|
||||||
|
|
||||||
|
if groupConstrained {
|
||||||
|
query = applyChannelGroupConstrainedFilter(query, channelId)
|
||||||
|
}
|
||||||
|
|
||||||
queryString, args, err := query.ToSql()
|
queryString, args, err := query.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInChannel", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInChannel", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
@@ -1185,6 +1237,10 @@ func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options
|
|||||||
OrderBy("u.Username ASC").
|
OrderBy("u.Username ASC").
|
||||||
Limit(uint64(options.Limit))
|
Limit(uint64(options.Limit))
|
||||||
|
|
||||||
|
if options.GroupConstrained {
|
||||||
|
query = applyTeamGroupConstrainedFilter(query, notInTeamId)
|
||||||
|
}
|
||||||
|
|
||||||
*result = us.performSearch(query, term, options)
|
*result = us.performSearch(query, term, options)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1201,6 +1257,10 @@ func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term
|
|||||||
query = query.Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId)
|
query = query.Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.GroupConstrained {
|
||||||
|
query = applyChannelGroupConstrainedFilter(query, channelId)
|
||||||
|
}
|
||||||
|
|
||||||
*result = us.performSearch(query, term, options)
|
*result = us.performSearch(query, term, options)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1341,7 +1401,7 @@ func (us SqlUserStore) AnalyticsGetSystemAdminCount() store.StoreChannel {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us SqlUserStore) GetProfilesNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
func (us SqlUserStore) GetProfilesNotInTeam(teamId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
||||||
return store.Do(func(result *store.StoreResult) {
|
return store.Do(func(result *store.StoreResult) {
|
||||||
query := us.usersQuery.
|
query := us.usersQuery.
|
||||||
LeftJoin("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
|
LeftJoin("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
|
||||||
@@ -1351,6 +1411,10 @@ func (us SqlUserStore) GetProfilesNotInTeam(teamId string, offset int, limit int
|
|||||||
|
|
||||||
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
|
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
|
||||||
|
|
||||||
|
if groupConstrained {
|
||||||
|
query = applyTeamGroupConstrainedFilter(query, teamId)
|
||||||
|
}
|
||||||
|
|
||||||
queryString, args, err := query.ToSql()
|
queryString, args, err := query.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
@@ -1551,23 +1615,7 @@ func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit
|
|||||||
|
|
||||||
func (us SqlUserStore) GetTeamGroupUsers(teamID string) store.StoreChannel {
|
func (us SqlUserStore) GetTeamGroupUsers(teamID string) store.StoreChannel {
|
||||||
return store.Do(func(result *store.StoreResult) {
|
return store.Do(func(result *store.StoreResult) {
|
||||||
query := us.usersQuery.
|
query := applyTeamGroupConstrainedFilter(us.usersQuery, teamID)
|
||||||
Where(`Id IN (
|
|
||||||
SELECT
|
|
||||||
GroupMembers.UserId
|
|
||||||
FROM
|
|
||||||
Teams
|
|
||||||
JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id
|
|
||||||
JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId
|
|
||||||
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
|
||||||
WHERE
|
|
||||||
Teams.Id = ?
|
|
||||||
AND GroupTeams.DeleteAt = 0
|
|
||||||
AND UserGroups.DeleteAt = 0
|
|
||||||
AND GroupMembers.DeleteAt = 0
|
|
||||||
GROUP BY
|
|
||||||
GroupMembers.UserId
|
|
||||||
)`, teamID)
|
|
||||||
|
|
||||||
queryString, args, err := query.ToSql()
|
queryString, args, err := query.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1591,23 +1639,7 @@ func (us SqlUserStore) GetTeamGroupUsers(teamID string) store.StoreChannel {
|
|||||||
|
|
||||||
func (us SqlUserStore) GetChannelGroupUsers(channelID string) store.StoreChannel {
|
func (us SqlUserStore) GetChannelGroupUsers(channelID string) store.StoreChannel {
|
||||||
return store.Do(func(result *store.StoreResult) {
|
return store.Do(func(result *store.StoreResult) {
|
||||||
query := us.usersQuery.
|
query := applyChannelGroupConstrainedFilter(us.usersQuery, channelID)
|
||||||
Where(`Id IN (
|
|
||||||
SELECT
|
|
||||||
GroupMembers.UserId
|
|
||||||
FROM
|
|
||||||
Channels
|
|
||||||
JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id
|
|
||||||
JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId
|
|
||||||
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
|
||||||
WHERE
|
|
||||||
Channels.Id = ?
|
|
||||||
AND GroupChannels.DeleteAt = 0
|
|
||||||
AND UserGroups.DeleteAt = 0
|
|
||||||
AND GroupMembers.DeleteAt = 0
|
|
||||||
GROUP BY
|
|
||||||
GroupMembers.UserId
|
|
||||||
)`, channelID)
|
|
||||||
|
|
||||||
queryString, args, err := query.ToSql()
|
queryString, args, err := query.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ type UserStore interface {
|
|||||||
GetProfilesInChannel(channelId string, offset int, limit int) StoreChannel
|
GetProfilesInChannel(channelId string, offset int, limit int) StoreChannel
|
||||||
GetProfilesInChannelByStatus(channelId string, offset int, limit int) StoreChannel
|
GetProfilesInChannelByStatus(channelId string, offset int, limit int) StoreChannel
|
||||||
GetAllProfilesInChannel(channelId string, allowFromCache bool) StoreChannel
|
GetAllProfilesInChannel(channelId string, allowFromCache bool) StoreChannel
|
||||||
GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
GetProfilesNotInChannel(teamId string, channelId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
||||||
GetProfilesWithoutTeam(offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
GetProfilesWithoutTeam(offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
||||||
GetProfilesByUsernames(usernames []string, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
GetProfilesByUsernames(usernames []string, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
||||||
GetAllProfiles(options *model.UserGetOptions) StoreChannel
|
GetAllProfiles(options *model.UserGetOptions) StoreChannel
|
||||||
@@ -292,7 +292,7 @@ type UserStore interface {
|
|||||||
SearchWithoutTeam(term string, options *model.UserSearchOptions) StoreChannel
|
SearchWithoutTeam(term string, options *model.UserSearchOptions) StoreChannel
|
||||||
AnalyticsGetInactiveUsersCount() StoreChannel
|
AnalyticsGetInactiveUsersCount() StoreChannel
|
||||||
AnalyticsGetSystemAdminCount() StoreChannel
|
AnalyticsGetSystemAdminCount() StoreChannel
|
||||||
GetProfilesNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
GetProfilesNotInTeam(teamId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
|
||||||
GetEtagForProfilesNotInTeam(teamId string) StoreChannel
|
GetEtagForProfilesNotInTeam(teamId string) StoreChannel
|
||||||
ClearAllCustomRoleAssignments() StoreChannel
|
ClearAllCustomRoleAssignments() StoreChannel
|
||||||
InferSystemInstallDate() StoreChannel
|
InferSystemInstallDate() StoreChannel
|
||||||
|
|||||||
@@ -443,13 +443,13 @@ func (_m *UserStore) GetProfilesInChannelByStatus(channelId string, offset int,
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProfilesNotInChannel provides a mock function with given fields: teamId, channelId, offset, limit, viewRestrictions
|
// GetProfilesNotInChannel provides a mock function with given fields: teamId, channelId, groupConstrained, offset, limit, viewRestrictions
|
||||||
func (_m *UserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
func (_m *UserStore) GetProfilesNotInChannel(teamId string, channelId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
||||||
ret := _m.Called(teamId, channelId, offset, limit, viewRestrictions)
|
ret := _m.Called(teamId, channelId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
|
|
||||||
var r0 store.StoreChannel
|
var r0 store.StoreChannel
|
||||||
if rf, ok := ret.Get(0).(func(string, string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
|
if rf, ok := ret.Get(0).(func(string, string, bool, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
|
||||||
r0 = rf(teamId, channelId, offset, limit, viewRestrictions)
|
r0 = rf(teamId, channelId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(store.StoreChannel)
|
r0 = ret.Get(0).(store.StoreChannel)
|
||||||
@@ -459,13 +459,13 @@ func (_m *UserStore) GetProfilesNotInChannel(teamId string, channelId string, of
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProfilesNotInTeam provides a mock function with given fields: teamId, offset, limit, viewRestrictions
|
// GetProfilesNotInTeam provides a mock function with given fields: teamId, groupConstrained, offset, limit, viewRestrictions
|
||||||
func (_m *UserStore) GetProfilesNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
func (_m *UserStore) GetProfilesNotInTeam(teamId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
|
||||||
ret := _m.Called(teamId, offset, limit, viewRestrictions)
|
ret := _m.Called(teamId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
|
|
||||||
var r0 store.StoreChannel
|
var r0 store.StoreChannel
|
||||||
if rf, ok := ret.Get(0).(func(string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
|
if rf, ok := ret.Get(0).(func(string, bool, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
|
||||||
r0 = rf(teamId, offset, limit, viewRestrictions)
|
r0 = rf(teamId, groupConstrained, offset, limit, viewRestrictions)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(store.StoreChannel)
|
r0 = ret.Get(0).(store.StoreChannel)
|
||||||
|
|||||||
@@ -1031,7 +1031,7 @@ func testUserStoreGetProfilesNotInChannel(t *testing.T, ss store.Store) {
|
|||||||
}, -1)).(*model.Channel)
|
}, -1)).(*model.Channel)
|
||||||
|
|
||||||
t.Run("get team 1, channel 1, offset 0, limit 100", func(t *testing.T) {
|
t.Run("get team 1, channel 1, offset 0, limit 100", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100, nil)
|
result := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, false, 0, 100, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u1),
|
sanitized(u1),
|
||||||
@@ -1041,7 +1041,7 @@ func testUserStoreGetProfilesNotInChannel(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get team 1, channel 2, offset 0, limit 100", func(t *testing.T) {
|
t.Run("get team 1, channel 2, offset 0, limit 100", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100, nil)
|
result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, false, 0, 100, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u1),
|
sanitized(u1),
|
||||||
@@ -1075,19 +1075,55 @@ func testUserStoreGetProfilesNotInChannel(t *testing.T, ss store.Store) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
t.Run("get team 1, channel 1, offset 0, limit 100, after update", func(t *testing.T) {
|
t.Run("get team 1, channel 1, offset 0, limit 100, after update", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100, nil)
|
result := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, false, 0, 100, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{}, result.Data.([]*model.User))
|
assert.Equal(t, []*model.User{}, result.Data.([]*model.User))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get team 1, channel 2, offset 0, limit 100, after update", func(t *testing.T) {
|
t.Run("get team 1, channel 2, offset 0, limit 100, after update", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100, nil)
|
result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, false, 0, 100, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u2),
|
sanitized(u2),
|
||||||
sanitized(u3),
|
sanitized(u3),
|
||||||
}, result.Data.([]*model.User))
|
}, result.Data.([]*model.User))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("get team 1, channel 2, offset 0, limit 0, setting group constrained when it's not", func(t *testing.T) {
|
||||||
|
result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, true, 0, 100, nil)
|
||||||
|
require.Nil(t, result.Err)
|
||||||
|
assert.Empty(t, result.Data.([]*model.User))
|
||||||
|
})
|
||||||
|
|
||||||
|
// create a group
|
||||||
|
group := store.Must(ss.Group().Create(&model.Group{
|
||||||
|
Name: "n_" + model.NewId(),
|
||||||
|
DisplayName: "dn_" + model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
RemoteId: "ri_" + model.NewId(),
|
||||||
|
})).(*model.Group)
|
||||||
|
|
||||||
|
// add two members to the group
|
||||||
|
for _, u := range []*model.User{u1, u2} {
|
||||||
|
res := <-ss.Group().CreateOrRestoreMember(group.Id, u.Id)
|
||||||
|
require.Nil(t, res.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// associate the group with the channel
|
||||||
|
res := <-ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
GroupId: group.Id,
|
||||||
|
SyncableId: c2.Id,
|
||||||
|
Type: model.GroupSyncableTypeChannel,
|
||||||
|
})
|
||||||
|
require.Nil(t, res.Err)
|
||||||
|
|
||||||
|
t.Run("get team 1, channel 2, offset 0, limit 0, setting group constrained", func(t *testing.T) {
|
||||||
|
result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, true, 0, 100, nil)
|
||||||
|
require.Nil(t, result.Err)
|
||||||
|
assert.Equal(t, []*model.User{
|
||||||
|
sanitized(u2),
|
||||||
|
}, result.Data.([]*model.User))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserStoreGetProfilesByIds(t *testing.T, ss store.Store) {
|
func testUserStoreGetProfilesByIds(t *testing.T, ss store.Store) {
|
||||||
@@ -3069,7 +3105,14 @@ func testUserStoreAnalyticsGetSystemAdminCount(t *testing.T, ss store.Store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
||||||
teamId := model.NewId()
|
team, err := ss.Team().Save(&model.Team{
|
||||||
|
DisplayName: "Team",
|
||||||
|
Name: model.NewId(),
|
||||||
|
Type: model.TEAM_OPEN,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
teamId := team.Id
|
||||||
teamId2 := model.NewId()
|
teamId2 := model.NewId()
|
||||||
|
|
||||||
u1 := store.Must(ss.User().Save(&model.User{
|
u1 := store.Must(ss.User().Save(&model.User{
|
||||||
@@ -3114,7 +3157,7 @@ func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get not in team 1, offset 0, limit 100000", func(t *testing.T) {
|
t.Run("get not in team 1, offset 0, limit 100000", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000, nil)
|
result := <-ss.User().GetProfilesNotInTeam(teamId, false, 0, 100000, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u2),
|
sanitized(u2),
|
||||||
@@ -3123,7 +3166,7 @@ func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get not in team 1, offset 1, limit 1", func(t *testing.T) {
|
t.Run("get not in team 1, offset 1, limit 1", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInTeam(teamId, 1, 1, nil)
|
result := <-ss.User().GetProfilesNotInTeam(teamId, false, 1, 1, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u3),
|
sanitized(u3),
|
||||||
@@ -3131,7 +3174,7 @@ func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get not in team 2, offset 0, limit 100", func(t *testing.T) {
|
t.Run("get not in team 2, offset 0, limit 100", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInTeam(teamId2, 0, 100, nil)
|
result := <-ss.User().GetProfilesNotInTeam(teamId2, false, 0, 100, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u1),
|
sanitized(u1),
|
||||||
@@ -3154,7 +3197,7 @@ func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get not in team 1, offset 0, limit 100000 after update", func(t *testing.T) {
|
t.Run("get not in team 1, offset 0, limit 100000 after update", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000, nil)
|
result := <-ss.User().GetProfilesNotInTeam(teamId, false, 0, 100000, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u3),
|
sanitized(u3),
|
||||||
@@ -3178,7 +3221,7 @@ func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get not in team 1, offset 0, limit 100000 after second update", func(t *testing.T) {
|
t.Run("get not in team 1, offset 0, limit 100000 after second update", func(t *testing.T) {
|
||||||
result := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000, nil)
|
result := <-ss.User().GetProfilesNotInTeam(teamId, false, 0, 100000, nil)
|
||||||
require.Nil(t, result.Err)
|
require.Nil(t, result.Err)
|
||||||
assert.Equal(t, []*model.User{
|
assert.Equal(t, []*model.User{
|
||||||
sanitized(u1),
|
sanitized(u1),
|
||||||
@@ -3220,6 +3263,43 @@ func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
|||||||
etag4 := result.Data.(string)
|
etag4 := result.Data.(string)
|
||||||
require.Equal(t, etag3, etag4, "etag should not have changed")
|
require.Equal(t, etag3, etag4, "etag should not have changed")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("get not in team 1, offset 0, limit 100000 after second update, setting group constrained when it's not", func(t *testing.T) {
|
||||||
|
result := <-ss.User().GetProfilesNotInTeam(teamId, true, 0, 100000, nil)
|
||||||
|
require.Nil(t, result.Err)
|
||||||
|
assert.Empty(t, result.Data.([]*model.User))
|
||||||
|
})
|
||||||
|
|
||||||
|
// create a group
|
||||||
|
group := store.Must(ss.Group().Create(&model.Group{
|
||||||
|
Name: "n_" + model.NewId(),
|
||||||
|
DisplayName: "dn_" + model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
RemoteId: "ri_" + model.NewId(),
|
||||||
|
})).(*model.Group)
|
||||||
|
|
||||||
|
// add two members to the group
|
||||||
|
for _, u := range []*model.User{u1, u2} {
|
||||||
|
res := <-ss.Group().CreateOrRestoreMember(group.Id, u.Id)
|
||||||
|
require.Nil(t, res.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// associate the group with the team
|
||||||
|
res := <-ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
GroupId: group.Id,
|
||||||
|
SyncableId: teamId,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
})
|
||||||
|
require.Nil(t, res.Err)
|
||||||
|
|
||||||
|
t.Run("get not in team 1, offset 0, limit 100000 after second update, setting group constrained", func(t *testing.T) {
|
||||||
|
result := <-ss.User().GetProfilesNotInTeam(teamId, true, 0, 100000, nil)
|
||||||
|
require.Nil(t, result.Err)
|
||||||
|
assert.Equal(t, []*model.User{
|
||||||
|
sanitized(u1),
|
||||||
|
sanitized(u2),
|
||||||
|
}, result.Data.([]*model.User))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserStoreClearAllCustomRoleAssignments(t *testing.T, ss store.Store) {
|
func testUserStoreClearAllCustomRoleAssignments(t *testing.T, ss store.Store) {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user