Adding new "VIEW_MEMBERS" permissions restrict the scope of users visibility (#10487)

* MM-14138: Adding new "VIEW_MEMBERS" permissions restrict the scope of users visibility

* Fixing gofmt

* Fixing broken tests

* Addressing PR review comments from Miguel de la Cruz

* Removed hack

* A bit nicer and cleaner code in the UserBelongsToChannels function

* Adding cluster cache invalidation for user team ids

* Checking in the correct order permissions to not leek existency information

* Adding restrictions to TeamMembers and User status requests

* Fixing tests

* Fixing status endpoint permissions checks

* Adding more tests

* Fixing tests

* More tests and making the restrictions query based only on joins

* Adding more tests

* Adding more tests

* fixing merge problems

* Reverting status changes to avoid performance issues

* Adding more tests

* Fixing test

* i18n extract

* Adding extra method for get restrictions for a team

* Add the new elasticsearch functions to search users with restrictions

* Add missing translation string

* Rename restrictedChannelIds to restrictedToChannels

* Remove ToDo

* Adding the permission to the SystemAdmin role during permissions migrations
Этот коммит содержится в:
Jesús Espino
2019-04-29 16:56:56 +02:00
коммит произвёл GitHub
родитель 5b70962f71
Коммит c8920588a0
41 изменённых файлов: 2785 добавлений и 259 удалений

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

@@ -295,6 +295,17 @@ func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, c.Params.UserId)
if err != nil {
c.Err = err
return
}
if !canSee {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
team, err := c.App.GetTeamMember(c.Params.TeamId, c.Params.UserId) team, err := c.App.GetTeamMember(c.Params.TeamId, c.Params.UserId)
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -315,7 +326,13 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
members, err := c.App.GetTeamMembers(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage) restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err != nil {
c.Err = err
return
}
members, err := c.App.GetTeamMembers(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage, restrictions)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -335,6 +352,17 @@ func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, c.Params.UserId)
if err != nil {
c.Err = err
return
}
if !canSee {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
members, err := c.App.GetTeamMembersForUser(c.Params.UserId) members, err := c.App.GetTeamMembersForUser(c.Params.UserId)
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -362,7 +390,13 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
members, err := c.App.GetTeamMembersByIds(c.Params.TeamId, userIds) restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err != nil {
c.Err = err
return
}
members, err := c.App.GetTeamMembersByIds(c.Params.TeamId, userIds, restrictions)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

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

@@ -111,7 +111,16 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
// No permission check required canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, c.Params.UserId)
if err != nil {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
if !canSee {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
user, err := c.App.GetUser(c.Params.UserId) user, err := c.App.GetUser(c.Params.UserId)
if err != nil { if err != nil {
@@ -154,14 +163,32 @@ func getUserByUsername(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
// No permission check required
user, err := c.App.GetUserByUsername(c.Params.Username) user, err := c.App.GetUserByUsername(c.Params.Username)
if err != nil { if err != nil {
restrictions, err2 := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err2 != nil {
c.Err = err2
return
}
if restrictions != nil {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
c.Err = err c.Err = err
return return
} }
canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, user.Id)
if err != nil {
c.Err = err
return
}
if !canSee {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
if c.IsSystemAdmin() || c.App.Session.UserId == user.Id { if c.IsSystemAdmin() || c.App.Session.UserId == user.Id {
userTermsOfService, err := c.App.GetUserTermsOfService(user.Id) userTermsOfService, err := c.App.GetUserTermsOfService(user.Id)
if err != nil && err.StatusCode != http.StatusNotFound { if err != nil && err.StatusCode != http.StatusNotFound {
@@ -196,8 +223,6 @@ func getUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
// No permission check required, but still prevent users who can't see another user's email address from using this
sanitizeOptions := c.App.GetSanitizeOptions(c.IsSystemAdmin()) sanitizeOptions := c.App.GetSanitizeOptions(c.IsSystemAdmin())
if !sanitizeOptions["email"] { if !sanitizeOptions["email"] {
c.Err = model.NewAppError("getUserByEmail", "api.user.get_user_by_email.permissions.app_error", nil, "userId="+c.App.Session.UserId, http.StatusForbidden) c.Err = model.NewAppError("getUserByEmail", "api.user.get_user_by_email.permissions.app_error", nil, "userId="+c.App.Session.UserId, http.StatusForbidden)
@@ -206,10 +231,30 @@ func getUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) {
user, err := c.App.GetUserByEmail(c.Params.Email) user, err := c.App.GetUserByEmail(c.Params.Email)
if err != nil { if err != nil {
restrictions, err2 := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err2 != nil {
c.Err = err2
return
}
if restrictions != nil {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
c.Err = err c.Err = err
return return
} }
canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, user.Id)
if err != nil {
c.Err = err
return
}
if !canSee {
c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
etag := user.Etag(*c.App.Config().PrivacySettings.ShowFullName, *c.App.Config().PrivacySettings.ShowEmailAddress) etag := user.Etag(*c.App.Config().PrivacySettings.ShowFullName, *c.App.Config().PrivacySettings.ShowEmailAddress)
if c.HandleEtag(etag, "Get User", w, r) { if c.HandleEtag(etag, "Get User", w, r) {
@@ -227,18 +272,23 @@ func getDefaultProfileImage(c *Context, w http.ResponseWriter, r *http.Request)
return return
} }
users, err := c.App.GetUsersByIds([]string{c.Params.UserId}, c.IsSystemAdmin()) canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, c.Params.UserId)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
} }
if len(users) == 0 { if !canSee {
c.Err = model.NewAppError("getProfileImage", "api.user.get_profile_image.not_found.app_error", nil, "", http.StatusNotFound) c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
user, err := c.App.GetUser(c.Params.UserId)
if err != nil {
c.Err = err
return return
} }
user := users[0]
img, err := c.App.GetDefaultProfileImage(user) img, err := c.App.GetDefaultProfileImage(user)
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -256,18 +306,23 @@ func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
users, err := c.App.GetUsersByIds([]string{c.Params.UserId}, c.IsSystemAdmin()) canSee, err := c.App.UserCanSeeOtherUser(c.App.Session.UserId, c.Params.UserId)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
} }
if len(users) == 0 { if !canSee {
c.Err = model.NewAppError("getProfileImage", "api.user.get_profile_image.not_found.app_error", nil, "", http.StatusNotFound) c.SetPermissionError(model.PERMISSION_VIEW_MEMBERS)
return
}
user, err := c.App.GetUser(c.Params.UserId)
if err != nil {
c.Err = err
return return
} }
user := users[0]
etag := strconv.FormatInt(user.LastPictureUpdate, 10) etag := strconv.FormatInt(user.LastPictureUpdate, 10)
if c.HandleEtag(etag, "Get Profile Image", w, r) { if c.HandleEtag(etag, "Get Profile Image", w, r) {
return return
@@ -376,7 +431,13 @@ func getTotalUsersStats(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
stats, err := c.App.GetTotalUsersStats() restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err != nil {
c.Err = err
return
}
stats, err := c.App.GetTotalUsersStats(restrictions)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -419,21 +480,27 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
withoutTeamBool, _ := strconv.ParseBool(withoutTeam) withoutTeamBool, _ := strconv.ParseBool(withoutTeam)
inactiveBool, _ := strconv.ParseBool(inactive) inactiveBool, _ := strconv.ParseBool(inactive)
restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err != nil {
c.Err = err
return
}
userGetOptions := &model.UserGetOptions{ userGetOptions := &model.UserGetOptions{
InTeamId: inTeamId, InTeamId: inTeamId,
InChannelId: inChannelId, InChannelId: inChannelId,
NotInTeamId: notInTeamId, NotInTeamId: notInTeamId,
NotInChannelId: notInChannelId, NotInChannelId: notInChannelId,
WithoutTeam: withoutTeamBool, WithoutTeam: withoutTeamBool,
Inactive: inactiveBool, Inactive: inactiveBool,
Role: role, Role: role,
Sort: sort, Sort: sort,
Page: c.Params.Page, Page: c.Params.Page,
PerPage: c.Params.PerPage, PerPage: c.Params.PerPage,
ViewRestrictions: restrictions,
} }
var profiles []*model.User var profiles []*model.User
var err *model.AppError
etag := "" etag := ""
if withoutTeamBool, _ := strconv.ParseBool(withoutTeam); withoutTeamBool { if withoutTeamBool, _ := strconv.ParseBool(withoutTeam); withoutTeamBool {
@@ -443,26 +510,26 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
profiles, err = c.App.GetUsersWithoutTeamPage(c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) profiles, err = c.App.GetUsersWithoutTeamPage(c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
} else if len(notInChannelId) > 0 { } else if len(notInChannelId) > 0 {
if !c.App.SessionHasPermissionToChannel(c.App.Session, notInChannelId, model.PERMISSION_READ_CHANNEL) { if !c.App.SessionHasPermissionToChannel(c.App.Session, notInChannelId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL) c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
return return
} }
profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, 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)
return return
} }
etag = c.App.GetUsersNotInTeamEtag(inTeamId) etag = c.App.GetUsersNotInTeamEtag(inTeamId, restrictions.Hash())
if c.HandleEtag(etag, "Get Users Not in Team", w, r) { if c.HandleEtag(etag, "Get Users Not in Team", w, r) {
return return
} }
profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, 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)
@@ -470,11 +537,11 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
} }
if sort == "last_activity_at" { if sort == "last_activity_at" {
profiles, err = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) profiles, err = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
} else if sort == "create_at" { } else if sort == "create_at" {
profiles, err = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) profiles, err = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions)
} else { } else {
etag = c.App.GetUsersInTeamEtag(inTeamId) etag = c.App.GetUsersInTeamEtag(inTeamId, restrictions.Hash())
if c.HandleEtag(etag, "Get Users in Team", w, r) { if c.HandleEtag(etag, "Get Users in Team", w, r) {
return return
} }
@@ -491,12 +558,16 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
} }
} else { } else {
// No permission check required etag = c.App.GetUsersEtag(restrictions.Hash())
etag = c.App.GetUsersEtag()
if c.HandleEtag(etag, "Get Users", w, r) { if c.HandleEtag(etag, "Get Users", w, r) {
return return
} }
userGetOptions, err = c.App.RestrictUsersGetByPermissions(c.App.Session.UserId, userGetOptions)
if err != nil {
c.Err = err
return
}
profiles, err = c.App.GetUsersPage(userGetOptions, c.IsSystemAdmin()) profiles, err = c.App.GetUsersPage(userGetOptions, c.IsSystemAdmin())
} }
@@ -520,9 +591,13 @@ func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
// No permission check required restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err != nil {
c.Err = err
return
}
users, err := c.App.GetUsersByIds(userIds, c.IsSystemAdmin()) users, err := c.App.GetUsersByIds(userIds, c.IsSystemAdmin(), restrictions)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -539,9 +614,13 @@ func getUsersByNames(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
// No permission check required restrictions, err := c.App.GetViewUsersRestrictions(c.App.Session.UserId)
if err != nil {
c.Err = err
return
}
users, err := c.App.GetUsersByUsernames(usernames, c.IsSystemAdmin()) users, err := c.App.GetUsersByUsernames(usernames, c.IsSystemAdmin(), restrictions)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -607,6 +686,12 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
options.AllowFullNames = *c.App.Config().PrivacySettings.ShowFullName options.AllowFullNames = *c.App.Config().PrivacySettings.ShowFullName
} }
options, err := c.App.RestrictUsersSearchByPermissions(c.App.Session.UserId, options)
if err != nil {
c.Err = err
return
}
profiles, err := c.App.SearchUsers(props, options) profiles, err := c.App.SearchUsers(props, options)
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -670,6 +755,13 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
autocomplete.Users = result.InChannel autocomplete.Users = result.InChannel
autocomplete.OutOfChannel = result.OutOfChannel autocomplete.OutOfChannel = result.OutOfChannel
} else if len(teamId) > 0 { } else if len(teamId) > 0 {
var err *model.AppError
options, err = c.App.RestrictUsersSearchByPermissions(c.App.Session.UserId, options)
if err != nil {
c.Err = err
return
}
result, err := c.App.AutocompleteUsersInTeam(teamId, name, options) result, err := c.App.AutocompleteUsersInTeam(teamId, name, options)
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -678,7 +770,13 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
autocomplete.Users = result.InTeam autocomplete.Users = result.InTeam
} else { } else {
// No permission check required var err *model.AppError
options, err = c.App.RestrictUsersSearchByPermissions(c.App.Session.UserId, options)
if err != nil {
c.Err = err
return
}
result, err := c.App.SearchUsersInTeam("", name, options) result, err := c.App.SearchUsersInTeam("", name, options)
if err != nil { if err != nil {
c.Err = err c.Err = err

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

@@ -525,7 +525,7 @@ func TestGetBotUser(t *testing.T) {
defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions()) defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID) th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false) th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.TEAM_USER_ROLE_ID, false)
bot := &model.Bot{ bot := &model.Bot{
Username: GenerateTestUsername(), Username: GenerateTestUsername(),
@@ -538,6 +538,7 @@ func TestGetBotUser(t *testing.T) {
defer th.App.PermanentDeleteBot(createdBot.UserId) defer th.App.PermanentDeleteBot(createdBot.UserId)
botUser, resp := th.Client.GetUser(createdBot.UserId, "") botUser, resp := th.Client.GetUser(createdBot.UserId, "")
CheckNoError(t, resp)
require.Equal(t, bot.Username, botUser.Username) require.Equal(t, bot.Username, botUser.Username)
require.True(t, botUser.IsBot) require.True(t, botUser.IsBot)
} }

471
api4/user_viewmembers_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,471 @@
package api4
import (
"testing"
"github.com/mattermost/mattermost-server/model"
"github.com/stretchr/testify/require"
)
func TestApiResctrictedViewMembers(t *testing.T) {
th := Setup()
defer th.TearDown()
// Create first account for system admin
_, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user0", Password: "test-password-0", Username: "test-user-0", Roles: model.SYSTEM_USER_ROLE_ID})
require.Nil(t, err)
user1, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user1", Password: "test-password-1", Username: "test-user-1", Roles: model.SYSTEM_USER_ROLE_ID})
require.Nil(t, err)
user2, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user2", Password: "test-password-2", Username: "test-user-2", Roles: model.SYSTEM_USER_ROLE_ID})
require.Nil(t, err)
user3, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user3", Password: "test-password-3", Username: "test-user-3", Roles: model.SYSTEM_USER_ROLE_ID})
require.Nil(t, err)
user4, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user4", Password: "test-password-4", Username: "test-user-4", Roles: model.SYSTEM_USER_ROLE_ID})
require.Nil(t, err)
user5, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user5", Password: "test-password-5", Username: "test-user-5", Roles: model.SYSTEM_USER_ROLE_ID})
require.Nil(t, err)
team1, err := th.App.CreateTeam(&model.Team{DisplayName: "dn_" + model.NewId(), Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN})
require.Nil(t, err)
team2, err := th.App.CreateTeam(&model.Team{DisplayName: "dn_" + model.NewId(), Name: GenerateTestTeamName(), Email: th.GenerateTestEmail(), Type: model.TEAM_OPEN})
require.Nil(t, err)
channel1, err := th.App.CreateChannel(&model.Channel{DisplayName: "dn_" + model.NewId(), Name: "name_" + model.NewId(), Type: model.CHANNEL_OPEN, TeamId: team1.Id, CreatorId: model.NewId()}, false)
require.Nil(t, err)
channel2, err := th.App.CreateChannel(&model.Channel{DisplayName: "dn_" + model.NewId(), Name: "name_" + model.NewId(), Type: model.CHANNEL_OPEN, TeamId: team1.Id, CreatorId: model.NewId()}, false)
require.Nil(t, err)
channel3, err := th.App.CreateChannel(&model.Channel{DisplayName: "dn_" + model.NewId(), Name: "name_" + model.NewId(), Type: model.CHANNEL_OPEN, TeamId: team2.Id, CreatorId: model.NewId()}, false)
require.Nil(t, err)
th.LinkUserToTeam(user1, team1)
th.LinkUserToTeam(user2, team1)
th.LinkUserToTeam(user3, team2)
th.LinkUserToTeam(user4, team1)
th.LinkUserToTeam(user4, team2)
th.AddUserToChannel(user1, channel1)
th.AddUserToChannel(user2, channel2)
th.AddUserToChannel(user3, channel3)
th.AddUserToChannel(user4, channel1)
th.AddUserToChannel(user4, channel3)
th.App.SetStatusOnline(user1.Id, true)
th.App.SetStatusOnline(user2.Id, true)
th.App.SetStatusOnline(user3.Id, true)
th.App.SetStatusOnline(user4.Id, true)
th.App.SetStatusOnline(user5.Id, true)
_, resp := th.Client.Login(user1.Username, "test-password-1")
CheckNoError(t, resp)
t.Run("getUser", func(t *testing.T) {
testCases := []struct {
Name string
RestrictedTo string
UserId string
ExpectedError string
}{
{
"Get visible user without restrictions",
"",
user5.Id,
"",
},
{
"Get not existing user without restrictions",
"",
model.NewId(),
"store.sql_user.missing_account.const",
},
{
"Get not existing user with restrictions to teams",
"teams",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to teams",
"teams",
user2.Id,
"",
},
{
"Get not visible user with restrictions to teams",
"teams",
user5.Id,
"api.context.permissions.app_error",
},
{
"Get not existing user with restrictions to channels",
"channels",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to channels",
"channels",
user4.Id,
"",
},
{
"Get not visible user with restrictions to channels",
"channels",
user3.Id,
"api.context.permissions.app_error",
},
}
defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
if tc.RestrictedTo == "channels" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else if tc.RestrictedTo == "teams" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
}
_, resp := th.Client.GetUser(tc.UserId, "")
require.Nil(t, err)
if tc.ExpectedError != "" {
CheckErrorMessage(t, resp, tc.ExpectedError)
} else {
CheckNoError(t, resp)
}
})
}
})
t.Run("getUserByUsername", func(t *testing.T) {
testCases := []struct {
Name string
RestrictedTo string
Username string
ExpectedError string
}{
{
"Get visible user without restrictions",
"",
user5.Username,
"",
},
{
"Get not existing user without restrictions",
"",
model.NewId(),
"store.sql_user.get_by_username.app_error",
},
{
"Get not existing user with restrictions to teams",
"teams",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to teams",
"teams",
user2.Username,
"",
},
{
"Get not visible user with restrictions to teams",
"teams",
user5.Username,
"api.context.permissions.app_error",
},
{
"Get not existing user with restrictions to channels",
"channels",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to channels",
"channels",
user4.Username,
"",
},
{
"Get not visible user with restrictions to channels",
"channels",
user3.Username,
"api.context.permissions.app_error",
},
}
defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
if tc.RestrictedTo == "channels" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else if tc.RestrictedTo == "teams" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
}
_, resp := th.Client.GetUserByUsername(tc.Username, "")
require.Nil(t, err)
if tc.ExpectedError != "" {
CheckErrorMessage(t, resp, tc.ExpectedError)
} else {
CheckNoError(t, resp)
}
})
}
})
t.Run("getUserByEmail", func(t *testing.T) {
testCases := []struct {
Name string
RestrictedTo string
Email string
ExpectedError string
}{
{
"Get visible user without restrictions",
"",
user5.Email,
"",
},
{
"Get not existing user without restrictions",
"",
th.GenerateTestEmail(),
"store.sql_user.missing_account.const",
},
{
"Get not existing user with restrictions to teams",
"teams",
th.GenerateTestEmail(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to teams",
"teams",
user2.Email,
"",
},
{
"Get not visible user with restrictions to teams",
"teams",
user5.Email,
"api.context.permissions.app_error",
},
{
"Get not existing user with restrictions to channels",
"channels",
th.GenerateTestEmail(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to channels",
"channels",
user4.Email,
"",
},
{
"Get not visible user with restrictions to channels",
"channels",
user3.Email,
"api.context.permissions.app_error",
},
}
defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
if tc.RestrictedTo == "channels" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else if tc.RestrictedTo == "teams" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
}
_, resp := th.Client.GetUserByEmail(tc.Email, "")
require.Nil(t, err)
if tc.ExpectedError != "" {
CheckErrorMessage(t, resp, tc.ExpectedError)
} else {
CheckNoError(t, resp)
}
})
}
})
t.Run("getDefaultProfileImage", func(t *testing.T) {
testCases := []struct {
Name string
RestrictedTo string
UserId string
ExpectedError string
}{
{
"Get visible user without restrictions",
"",
user5.Id,
"",
},
{
"Get not existing user without restrictions",
"",
model.NewId(),
"store.sql_user.missing_account.const",
},
{
"Get not existing user with restrictions to teams",
"teams",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to teams",
"teams",
user2.Id,
"",
},
{
"Get not visible user with restrictions to teams",
"teams",
user5.Id,
"api.context.permissions.app_error",
},
{
"Get not existing user with restrictions to channels",
"channels",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to channels",
"channels",
user4.Id,
"",
},
{
"Get not visible user with restrictions to channels",
"channels",
user3.Id,
"api.context.permissions.app_error",
},
}
defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
if tc.RestrictedTo == "channels" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else if tc.RestrictedTo == "teams" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
}
_, resp := th.Client.GetDefaultProfileImage(tc.UserId)
require.Nil(t, err)
if tc.ExpectedError != "" {
CheckErrorMessage(t, resp, tc.ExpectedError)
} else {
CheckNoError(t, resp)
}
})
}
})
t.Run("getProfileImage", func(t *testing.T) {
testCases := []struct {
Name string
RestrictedTo string
UserId string
ExpectedError string
}{
{
"Get visible user without restrictions",
"",
user5.Id,
"",
},
{
"Get not existing user without restrictions",
"",
model.NewId(),
"store.sql_user.missing_account.const",
},
{
"Get not existing user with restrictions to teams",
"teams",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to teams",
"teams",
user2.Id,
"",
},
{
"Get not visible user with restrictions to teams",
"teams",
user5.Id,
"api.context.permissions.app_error",
},
{
"Get not existing user with restrictions to channels",
"channels",
model.NewId(),
"api.context.permissions.app_error",
},
{
"Get visible user with restrictions to channels",
"channels",
user4.Id,
"",
},
{
"Get not visible user with restrictions to channels",
"channels",
user3.Id,
"api.context.permissions.app_error",
},
}
defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
if tc.RestrictedTo == "channels" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else if tc.RestrictedTo == "teams" {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
} else {
th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
}
_, resp := th.Client.GetProfileImage(tc.UserId, "")
require.Nil(t, err)
if tc.ExpectedError != "" {
CheckErrorMessage(t, resp, tc.ExpectedError)
} else {
CheckNoError(t, resp)
}
})
}
})
}

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

@@ -150,6 +150,7 @@ func (a *App) InvalidateAllCachesSkipSend() {
mlog.Info("Purging all caches") mlog.Info("Purging all caches")
a.Srv.sessionCache.Purge() a.Srv.sessionCache.Purge()
ClearStatusCache() ClearStatusCache()
a.Srv.Store.Team().ClearCaches()
a.Srv.Store.Channel().ClearCaches() a.Srv.Store.Channel().ClearCaches()
a.Srv.Store.User().ClearCaches() a.Srv.Store.User().ClearCaches()
a.Srv.Store.Post().ClearCaches() a.Srv.Store.Post().ClearCaches()

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

@@ -254,7 +254,7 @@ func (a *App) GetAnalytics(name string, teamId string) (model.AnalyticsRows, *mo
} }
func (a *App) GetRecentlyActiveUsersForTeam(teamId string) (map[string]*model.User, *model.AppError) { func (a *App) GetRecentlyActiveUsersForTeam(teamId string) (map[string]*model.User, *model.AppError) {
result := <-a.Srv.Store.User().GetRecentlyActiveUsersForTeam(teamId, 0, 100) result := <-a.Srv.Store.User().GetRecentlyActiveUsersForTeam(teamId, 0, 100, nil)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -269,9 +269,9 @@ func (a *App) GetRecentlyActiveUsersForTeam(teamId string) (map[string]*model.Us
return userMap, nil return userMap, nil
} }
func (a *App) GetRecentlyActiveUsersForTeamPage(teamId string, page, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetRecentlyActiveUsersForTeamPage(teamId string, page, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
var users []*model.User var users []*model.User
result := <-a.Srv.Store.User().GetRecentlyActiveUsersForTeam(teamId, page*perPage, perPage) result := <-a.Srv.Store.User().GetRecentlyActiveUsersForTeam(teamId, page*perPage, perPage, viewRestrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -280,9 +280,9 @@ func (a *App) GetRecentlyActiveUsersForTeamPage(teamId string, page, perPage int
return a.sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetNewUsersForTeamPage(teamId string, page, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetNewUsersForTeamPage(teamId string, page, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
var users []*model.User var users []*model.User
result := <-a.Srv.Store.User().GetNewUsersForTeam(teamId, page*perPage, perPage) result := <-a.Srv.Store.User().GetNewUsersForTeam(teamId, page*perPage, perPage, viewRestrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }

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

@@ -125,6 +125,7 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_JOIN_PUBLIC_TEAMS.Id, model.PERMISSION_JOIN_PUBLIC_TEAMS.Id,
model.PERMISSION_CREATE_DIRECT_CHANNEL.Id, model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
model.PERMISSION_CREATE_GROUP_CHANNEL.Id, model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
model.PERMISSION_VIEW_MEMBERS.Id,
model.PERMISSION_CREATE_TEAM.Id, model.PERMISSION_CREATE_TEAM.Id,
}, },
"system_post_all": []string{ "system_post_all": []string{
@@ -176,6 +177,7 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id,
model.PERMISSION_LIST_PRIVATE_TEAMS.Id, model.PERMISSION_LIST_PRIVATE_TEAMS.Id,
model.PERMISSION_JOIN_PRIVATE_TEAMS.Id, model.PERMISSION_JOIN_PRIVATE_TEAMS.Id,
model.PERMISSION_VIEW_MEMBERS.Id,
model.PERMISSION_LIST_TEAM_CHANNELS.Id, model.PERMISSION_LIST_TEAM_CHANNELS.Id,
model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id, model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
model.PERMISSION_READ_PUBLIC_CHANNEL.Id, model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
@@ -305,6 +307,7 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_JOIN_PUBLIC_TEAMS.Id, model.PERMISSION_JOIN_PUBLIC_TEAMS.Id,
model.PERMISSION_CREATE_DIRECT_CHANNEL.Id, model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
model.PERMISSION_CREATE_GROUP_CHANNEL.Id, model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
model.PERMISSION_VIEW_MEMBERS.Id,
model.PERMISSION_CREATE_TEAM.Id, model.PERMISSION_CREATE_TEAM.Id,
}, },
"system_post_all": []string{ "system_post_all": []string{
@@ -356,6 +359,7 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id,
model.PERMISSION_LIST_PRIVATE_TEAMS.Id, model.PERMISSION_LIST_PRIVATE_TEAMS.Id,
model.PERMISSION_JOIN_PRIVATE_TEAMS.Id, model.PERMISSION_JOIN_PRIVATE_TEAMS.Id,
model.PERMISSION_VIEW_MEMBERS.Id,
model.PERMISSION_LIST_TEAM_CHANNELS.Id, model.PERMISSION_LIST_TEAM_CHANNELS.Id,
model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id, model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
model.PERMISSION_READ_PUBLIC_CHANNEL.Id, model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
@@ -523,6 +527,7 @@ func TestDoEmojisPermissionsMigration(t *testing.T) {
model.PERMISSION_CREATE_EMOJIS.Id, model.PERMISSION_CREATE_EMOJIS.Id,
model.PERMISSION_DELETE_EMOJIS.Id, model.PERMISSION_DELETE_EMOJIS.Id,
model.PERMISSION_DELETE_OTHERS_EMOJIS.Id, model.PERMISSION_DELETE_OTHERS_EMOJIS.Id,
model.PERMISSION_VIEW_MEMBERS.Id,
} }
sort.Strings(expectedSystemAdmin) sort.Strings(expectedSystemAdmin)
@@ -583,6 +588,7 @@ func TestDoEmojisPermissionsMigration(t *testing.T) {
model.PERMISSION_CREATE_TEAM.Id, model.PERMISSION_CREATE_TEAM.Id,
model.PERMISSION_CREATE_EMOJIS.Id, model.PERMISSION_CREATE_EMOJIS.Id,
model.PERMISSION_DELETE_EMOJIS.Id, model.PERMISSION_DELETE_EMOJIS.Id,
model.PERMISSION_VIEW_MEMBERS.Id,
} }
sort.Strings(expected3) sort.Strings(expected3)
sort.Strings(role3.Permissions) sort.Strings(role3.Permissions)

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

@@ -420,7 +420,7 @@ func (a *App) createGroupChannel(userIds []string, creatorId string) (*model.Cha
return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest) return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest)
} }
result := <-a.Srv.Store.User().GetProfileByIds(userIds, true) result := <-a.Srv.Store.User().GetProfileByIds(userIds, true, nil)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -469,7 +469,7 @@ func (a *App) GetGroupChannel(userIds []string) (*model.Channel, *model.AppError
return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest) return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest)
} }
result := <-a.Srv.Store.User().GetProfileByIds(userIds, true) result := <-a.Srv.Store.User().GetProfileByIds(userIds, true, nil)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -1907,7 +1907,7 @@ func (a *App) MoveChannel(team *model.Team, channel *model.Channel, user *model.
} }
if len(channelMemberIds) > 0 { if len(channelMemberIds) > 0 {
teamMembers, err2 := a.GetTeamMembersByIds(team.Id, channelMemberIds) teamMembers, err2 := a.GetTeamMembersByIds(team.Id, channelMemberIds, nil)
if err2 != nil { if err2 != nil {
return err2 return err2
} }

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

@@ -20,6 +20,7 @@ func (a *App) RegisterAllClusterMessageHandlers() {
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME, a.ClusterInvalidateCacheForChannelByNameHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME, a.ClusterInvalidateCacheForChannelByNameHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL, a.ClusterInvalidateCacheForChannelHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL, a.ClusterInvalidateCacheForChannelHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER, a.ClusterInvalidateCacheForUserHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER, a.ClusterInvalidateCacheForUserHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER_TEAMS, a.ClusterInvalidateCacheForUserTeamsHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER, a.ClusterClearSessionCacheForUserHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER, a.ClusterClearSessionCacheForUserHandler)
} }
@@ -65,6 +66,10 @@ func (a *App) ClusterInvalidateCacheForUserHandler(msg *model.ClusterMessage) {
a.InvalidateCacheForUserSkipClusterSend(msg.Data) a.InvalidateCacheForUserSkipClusterSend(msg.Data)
} }
func (a *App) ClusterInvalidateCacheForUserTeamsHandler(msg *model.ClusterMessage) {
a.InvalidateCacheForUserTeamsSkipClusterSend(msg.Data)
}
func (a *App) ClusterClearSessionCacheForUserHandler(msg *model.ClusterMessage) { func (a *App) ClusterClearSessionCacheForUserHandler(msg *model.ClusterMessage) {
a.ClearSessionCacheForUserSkipClusterSend(msg.Data) a.ClearSessionCacheForUserSkipClusterSend(msg.Data)
} }

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

@@ -802,7 +802,7 @@ func TestImportImportUser(t *testing.T) {
Position: ptrStr(model.NewId()), Position: ptrStr(model.NewId()),
} }
teamMembers, err := th.App.GetTeamMembers(team.Id, 0, 1000) teamMembers, err := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to get team member count") t.Fatalf("Failed to get team member count")
} }
@@ -884,7 +884,7 @@ func TestImportImportUser(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
// Check no new member objects were created because dry run mode. // Check no new member objects were created because dry run mode.
tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000) tmc, err := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
require.Nil(t, err, "Failed to get Team Member Count") require.Nil(t, err, "Failed to get Team Member Count")
require.Len(t, tmc, teamMemberCount, "Number of team members not as expected") require.Len(t, tmc, teamMemberCount, "Number of team members not as expected")
@@ -935,7 +935,7 @@ func TestImportImportUser(t *testing.T) {
assert.NotNil(t, err) assert.NotNil(t, err)
// Check no new member objects were created because all tests should have failed so far. // Check no new member objects were created because all tests should have failed so far.
tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000) tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000, nil)
require.Nil(t, err, "Failed to get Team Member Count") require.Nil(t, err, "Failed to get Team Member Count")
require.Len(t, tmc, teamMemberCount) require.Len(t, tmc, teamMemberCount)
@@ -958,7 +958,7 @@ func TestImportImportUser(t *testing.T) {
assert.NotNil(t, err) assert.NotNil(t, err)
// Check only new team member object created because dry run mode. // Check only new team member object created because dry run mode.
tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000) tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000, nil)
require.Nil(t, err, "Failed to get Team Member Count") require.Nil(t, err, "Failed to get Team Member Count")
require.Len(t, tmc, teamMemberCount+1) require.Len(t, tmc, teamMemberCount+1)
@@ -991,7 +991,7 @@ func TestImportImportUser(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
// Check only new channel member object created because dry run mode. // Check only new channel member object created because dry run mode.
tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000) tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000, nil)
require.Nil(t, err, "Failed to get Team Member Count") require.Nil(t, err, "Failed to get Team Member Count")
require.Len(t, tmc, teamMemberCount+1, "Number of team members not as expected") require.Len(t, tmc, teamMemberCount+1, "Number of team members not as expected")
@@ -1046,7 +1046,7 @@ func TestImportImportUser(t *testing.T) {
checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, team.Id, *(*data.Teams)[0].Theme) checkPreference(t, th.App, user.Id, model.PREFERENCE_CATEGORY_THEME, team.Id, *(*data.Teams)[0].Theme)
// No more new member objects. // No more new member objects.
tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000) tmc, err = th.App.GetTeamMembers(team.Id, 0, 1000, nil)
require.Nil(t, err, "Failed to get Team Member Count") require.Nil(t, err, "Failed to get Team Member Count")
require.Len(t, tmc, teamMemberCount+1, "Number of team members not as expected") require.Len(t, tmc, teamMemberCount+1, "Number of team members not as expected")

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

@@ -125,7 +125,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
} }
if len(m.OtherPotentialMentions) > 0 && !post.IsSystemMessage() { if len(m.OtherPotentialMentions) > 0 && !post.IsSystemMessage() {
if result := <-a.Srv.Store.User().GetProfilesByUsernames(m.OtherPotentialMentions, team.Id); result.Err == nil { if result := <-a.Srv.Store.User().GetProfilesByUsernames(m.OtherPotentialMentions, &model.ViewUsersRestrictions{Teams: []string{team.Id}}); result.Err == nil {
channelMentions := model.UserSlice(result.Data.([]*model.User)).FilterByActive(true) channelMentions := model.UserSlice(result.Data.([]*model.User)).FilterByActive(true)
var outOfChannelMentions model.UserSlice var outOfChannelMentions model.UserSlice

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

@@ -22,6 +22,7 @@ const (
MIGRATION_KEY_ADD_BOT_PERMISSIONS = "add_bot_permissions" MIGRATION_KEY_ADD_BOT_PERMISSIONS = "add_bot_permissions"
MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER = "apply_channel_manage_delete_to_channel_user" MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER = "apply_channel_manage_delete_to_channel_user"
MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER = "remove_channel_manage_delete_from_team_user" MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER = "remove_channel_manage_delete_from_team_user"
MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION = "view_members_new_permission"
PERMISSION_MANAGE_SYSTEM = "manage_system" PERMISSION_MANAGE_SYSTEM = "manage_system"
PERMISSION_MANAGE_EMOJIS = "manage_emojis" PERMISSION_MANAGE_EMOJIS = "manage_emojis"
@@ -49,6 +50,7 @@ const (
PERMISSION_DELETE_PRIVATE_CHANNEL = "delete_private_channel" PERMISSION_DELETE_PRIVATE_CHANNEL = "delete_private_channel"
PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = "manage_public_channel_properties" PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = "manage_public_channel_properties"
PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = "manage_private_channel_properties" PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = "manage_private_channel_properties"
PERMISSION_VIEW_MEMBERS = "view_members"
) )
func isRole(role string) func(string, map[string]map[string]bool) bool { func isRole(role string) func(string, map[string]map[string]bool) bool {
@@ -258,6 +260,19 @@ func removeChannelManageDeleteFromTeamUser() permissionsMap {
} }
} }
func getViewMembersPermissionMigration() permissionsMap {
return permissionsMap{
permissionTransformation{
On: isRole(model.SYSTEM_USER_ROLE_ID),
Add: []string{PERMISSION_VIEW_MEMBERS},
},
permissionTransformation{
On: isRole(model.SYSTEM_ADMIN_ROLE_ID),
Add: []string{PERMISSION_VIEW_MEMBERS},
},
}
}
// DoPermissionsMigrations execute all the permissions migrations need by the current version. // DoPermissionsMigrations execute all the permissions migrations need by the current version.
func (a *App) DoPermissionsMigrations() *model.AppError { func (a *App) DoPermissionsMigrations() *model.AppError {
PermissionsMigrations := []struct { PermissionsMigrations := []struct {
@@ -271,6 +286,7 @@ func (a *App) DoPermissionsMigrations() *model.AppError {
{Key: MIGRATION_KEY_ADD_BOT_PERMISSIONS, Migration: getAddBotPermissionsMigration}, {Key: MIGRATION_KEY_ADD_BOT_PERMISSIONS, Migration: getAddBotPermissionsMigration},
{Key: MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER, Migration: applyChannelManageDeleteToChannelUser}, {Key: MIGRATION_KEY_APPLY_CHANNEL_MANAGE_DELETE_TO_CHANNEL_USER, Migration: applyChannelManageDeleteToChannelUser},
{Key: MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER, Migration: removeChannelManageDeleteFromTeamUser}, {Key: MIGRATION_KEY_REMOVE_CHANNEL_MANAGE_DELETE_FROM_TEAM_USER, Migration: removeChannelManageDeleteFromTeamUser},
{Key: MIGRATION_KEY_VIEW_MEMBERS_NEW_PERMISSION, Migration: getViewMembersPermissionMigration},
} }
for _, migration := range PermissionsMigrations { for _, migration := range PermissionsMigrations {

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

@@ -173,7 +173,7 @@ func (api *PluginAPI) DeleteTeamMember(teamId, userId, requestorId string) *mode
} }
func (api *PluginAPI) GetTeamMembers(teamId string, page, perPage int) ([]*model.TeamMember, *model.AppError) { func (api *PluginAPI) GetTeamMembers(teamId string, page, perPage int) ([]*model.TeamMember, *model.AppError) {
return api.app.GetTeamMembers(teamId, page*perPage, perPage) return api.app.GetTeamMembers(teamId, page*perPage, perPage, nil)
} }
func (api *PluginAPI) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { func (api *PluginAPI) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
@@ -222,7 +222,7 @@ func (api *PluginAPI) GetUserByUsername(name string) (*model.User, *model.AppErr
} }
func (api *PluginAPI) GetUsersByUsernames(usernames []string) ([]*model.User, *model.AppError) { func (api *PluginAPI) GetUsersByUsernames(usernames []string) ([]*model.User, *model.AppError) {
return api.app.GetUsersByUsernames(usernames, true) return api.app.GetUsersByUsernames(usernames, true, nil)
} }
func (api *PluginAPI) GetUsersInTeam(teamId string, page int, perPage int) ([]*model.User, *model.AppError) { func (api *PluginAPI) GetUsersInTeam(teamId string, page int, perPage int) ([]*model.User, *model.AppError) {

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

@@ -780,7 +780,7 @@ func (a *App) DeletePostFiles(post *model.Post) {
func (a *App) parseAndFetchChannelIdByNameFromInFilter(channelName, userId, teamId string, includeDeleted bool) (*model.Channel, error) { func (a *App) parseAndFetchChannelIdByNameFromInFilter(channelName, userId, teamId string, includeDeleted bool) (*model.Channel, error) {
if strings.HasPrefix(channelName, "@") && strings.Contains(channelName, ",") { if strings.HasPrefix(channelName, "@") && strings.Contains(channelName, ",") {
var userIds []string var userIds []string
users, err := a.GetUsersByUsernames(strings.Split(channelName[1:], ","), false) users, err := a.GetUsersByUsernames(strings.Split(channelName[1:], ","), false, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

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

@@ -66,7 +66,7 @@ func replaceUserIds(userStore store.UserStore, text string) string {
userIds = append(userIds, match[1]) userIds = append(userIds, match[1])
} }
if res := <-userStore.GetProfileByIds(userIds, true); res.Err == nil { if res := <-userStore.GetProfileByIds(userIds, true, nil); res.Err == nil {
for _, user := range res.Data.([]*model.User) { for _, user := range res.Data.([]*model.User) {
text = strings.Replace(text, "<@"+user.Id+">", "@"+user.Username, -1) text = strings.Replace(text, "<@"+user.Id+">", "@"+user.Username, -1)
} }

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

@@ -114,7 +114,7 @@ func TestCreateDefaultMemberships(t *testing.T) {
t.Errorf("error retrieving channel member: %s", err.Error()) t.Errorf("error retrieving channel member: %s", err.Error())
} }
tMembers, err := th.App.GetTeamMembers(singersTeam.Id, 0, 999) tMembers, err := th.App.GetTeamMembers(singersTeam.Id, 0, 999, nil)
if err != nil { if err != nil {
t.Errorf("error retrieving team members: %s", err.Error()) t.Errorf("error retrieving team members: %s", err.Error())
} }
@@ -143,7 +143,7 @@ func TestCreateDefaultMemberships(t *testing.T) {
t.Errorf("wrong error: %s", err.Id) t.Errorf("wrong error: %s", err.Id)
} }
tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999) tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999, nil)
if err != nil { if err != nil {
t.Errorf("error retrieving team members: %s", err.Error()) t.Errorf("error retrieving team members: %s", err.Error())
} }
@@ -185,7 +185,7 @@ func TestCreateDefaultMemberships(t *testing.T) {
t.Errorf("wrong error: %s", err.Id) t.Errorf("wrong error: %s", err.Id)
} }
tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999) tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999, nil)
if err != nil { if err != nil {
t.Errorf("error retrieving team members: %s", err.Error()) t.Errorf("error retrieving team members: %s", err.Error())
} }
@@ -366,7 +366,7 @@ func TestDeleteGroupMemberships(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
// verify the member count // verify the member count
tmembers, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100) tmembers, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100, nil)
require.Nil(t, err) require.Nil(t, err)
require.Len(t, tmembers, 3) require.Len(t, tmembers, 3)
@@ -383,7 +383,7 @@ func TestDeleteGroupMemberships(t *testing.T) {
require.Nil(t, appErr) require.Nil(t, appErr)
// verify the new member counts // verify the new member counts
tmembers, err = th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100) tmembers, err = th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100, nil)
require.Nil(t, err) require.Nil(t, err)
require.Len(t, tmembers, 1) require.Len(t, tmembers, 1)
require.Equal(t, th.SystemAdminUser.Id, tmembers[0].UserId) require.Equal(t, th.SystemAdminUser.Id, tmembers[0].UserId)

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

@@ -559,6 +559,7 @@ func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId
a.ClearSessionCacheForUser(user.Id) a.ClearSessionCacheForUser(user.Id)
a.InvalidateCacheForUser(user.Id) a.InvalidateCacheForUser(user.Id)
a.InvalidateCacheForUserTeams(user.Id)
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil) message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil)
message.Add("team_id", team.Id) message.Add("team_id", team.Id)
@@ -693,16 +694,16 @@ func (a *App) GetTeamMembersForUserWithPagination(userId string, page, perPage i
return result.Data.([]*model.TeamMember), nil return result.Data.([]*model.TeamMember), nil
} }
func (a *App) GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError) { func (a *App) GetTeamMembers(teamId string, offset int, limit int, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError) {
result := <-a.Srv.Store.Team().GetMembers(teamId, offset, limit) result := <-a.Srv.Store.Team().GetMembers(teamId, offset, limit, restrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
return result.Data.([]*model.TeamMember), nil return result.Data.([]*model.TeamMember), nil
} }
func (a *App) GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError) { func (a *App) GetTeamMembersByIds(teamId string, userIds []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError) {
result := <-a.Srv.Store.Team().GetMembersByIds(teamId, userIds) result := <-a.Srv.Store.Team().GetMembersByIds(teamId, userIds, restrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -932,6 +933,7 @@ func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string)
a.ClearSessionCacheForUser(user.Id) a.ClearSessionCacheForUser(user.Id)
a.InvalidateCacheForUser(user.Id) a.InvalidateCacheForUser(user.Id)
a.InvalidateCacheForUserTeams(user.Id)
return nil return nil
} }

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

@@ -756,10 +756,10 @@ func TestGetTeamMembers(t *testing.T) {
sort.Sort(userIDs) sort.Sort(userIDs)
// Fetch team members multipile times // Fetch team members multipile times
members, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 5) members, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 5, nil)
require.Nil(t, err) require.Nil(t, err)
// This should return 5 members // This should return 5 members
members2, err := th.App.GetTeamMembers(th.BasicTeam.Id, 5, 6) members2, err := th.App.GetTeamMembers(th.BasicTeam.Id, 5, 6, nil)
require.Nil(t, err) require.Nil(t, err)
members = append(members, members2...) members = append(members, members2...)
@@ -776,7 +776,7 @@ func TestGetTeamStats(t *testing.T) {
teamStats, err := th.App.GetTeamStats(th.BasicTeam.Id) teamStats, err := th.App.GetTeamStats(th.BasicTeam.Id)
require.Nil(t, err) require.Nil(t, err)
require.NotNil(t, teamStats) require.NotNil(t, teamStats)
members, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 5) members, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 5, nil)
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, int64(len(members)), teamStats.TotalMemberCount) assert.Equal(t, int64(len(members)), teamStats.TotalMemberCount)
} }

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

@@ -447,8 +447,8 @@ func (a *App) GetUsersPage(options *model.UserGetOptions, asAdmin bool) ([]*mode
return a.sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersEtag() string { func (a *App) GetUsersEtag(restrictionsHash string) string {
return fmt.Sprintf("%v.%v.%v", (<-a.Srv.Store.User().GetEtagForAllProfiles()).Data.(string), a.Config().PrivacySettings.ShowFullName, a.Config().PrivacySettings.ShowEmailAddress) return fmt.Sprintf("%v.%v.%v.%v", (<-a.Srv.Store.User().GetEtagForAllProfiles()).Data.(string), a.Config().PrivacySettings.ShowFullName, a.Config().PrivacySettings.ShowEmailAddress, restrictionsHash)
} }
func (a *App) GetUsersInTeam(options *model.UserGetOptions) ([]*model.User, *model.AppError) { func (a *App) GetUsersInTeam(options *model.UserGetOptions) ([]*model.User, *model.AppError) {
@@ -459,8 +459,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) ([]*model.User, *model.AppError) { func (a *App) GetUsersNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
result := <-a.Srv.Store.User().GetProfilesNotInTeam(teamId, offset, limit) result := <-a.Srv.Store.User().GetProfilesNotInTeam(teamId, offset, limit, viewRestrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -476,8 +476,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) ([]*model.User, *model.AppError) { func (a *App) GetUsersNotInTeamPage(teamId string, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
users, err := a.GetUsersNotInTeam(teamId, page*perPage, perPage) users, err := a.GetUsersNotInTeam(teamId, page*perPage, perPage, viewRestrictions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -485,12 +485,12 @@ func (a *App) GetUsersNotInTeamPage(teamId string, page int, perPage int, asAdmi
return a.sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersInTeamEtag(teamId string) string { func (a *App) GetUsersInTeamEtag(teamId string, restrictionsHash string) string {
return fmt.Sprintf("%v.%v.%v", (<-a.Srv.Store.User().GetEtagForProfiles(teamId)).Data.(string), a.Config().PrivacySettings.ShowFullName, a.Config().PrivacySettings.ShowEmailAddress) return fmt.Sprintf("%v.%v.%v.%v", (<-a.Srv.Store.User().GetEtagForProfiles(teamId)).Data.(string), a.Config().PrivacySettings.ShowFullName, a.Config().PrivacySettings.ShowEmailAddress, restrictionsHash)
} }
func (a *App) GetUsersNotInTeamEtag(teamId string) string { func (a *App) GetUsersNotInTeamEtag(teamId string, restrictionsHash string) string {
return fmt.Sprintf("%v.%v.%v", (<-a.Srv.Store.User().GetEtagForProfilesNotInTeam(teamId)).Data.(string), a.Config().PrivacySettings.ShowFullName, a.Config().PrivacySettings.ShowEmailAddress) return fmt.Sprintf("%v.%v.%v.%v", (<-a.Srv.Store.User().GetEtagForProfilesNotInTeam(teamId)).Data.(string), a.Config().PrivacySettings.ShowFullName, a.Config().PrivacySettings.ShowEmailAddress, restrictionsHash)
} }
func (a *App) GetUsersInChannel(channelId string, offset int, limit int) ([]*model.User, *model.AppError) { func (a *App) GetUsersInChannel(channelId string, offset int, limit int) ([]*model.User, *model.AppError) {
@@ -541,16 +541,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) ([]*model.User, *model.AppError) { func (a *App) GetUsersNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
result := <-a.Srv.Store.User().GetProfilesNotInChannel(teamId, channelId, offset, limit) result := <-a.Srv.Store.User().GetProfilesNotInChannel(teamId, channelId, 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) (map[string]*model.User, *model.AppError) { func (a *App) GetUsersNotInChannelMap(teamId string, channelId string, offset int, limit int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) (map[string]*model.User, *model.AppError) {
users, err := a.GetUsersNotInChannel(teamId, channelId, offset, limit) users, err := a.GetUsersNotInChannel(teamId, channelId, offset, limit, viewRestrictions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -565,8 +565,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) ([]*model.User, *model.AppError) { func (a *App) GetUsersNotInChannelPage(teamId string, channelId string, page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
users, err := a.GetUsersNotInChannel(teamId, channelId, page*perPage, perPage) users, err := a.GetUsersNotInChannel(teamId, channelId, page*perPage, perPage, viewRestrictions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -574,8 +574,8 @@ func (a *App) GetUsersNotInChannelPage(teamId string, channelId string, page int
return a.sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersWithoutTeamPage(page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetUsersWithoutTeamPage(page int, perPage int, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
users, err := a.GetUsersWithoutTeam(page*perPage, perPage) users, err := a.GetUsersWithoutTeam(page*perPage, perPage, viewRestrictions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -583,8 +583,8 @@ func (a *App) GetUsersWithoutTeamPage(page int, perPage int, asAdmin bool) ([]*m
return a.sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersWithoutTeam(offset int, limit int) ([]*model.User, *model.AppError) { func (a *App) GetUsersWithoutTeam(offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
result := <-a.Srv.Store.User().GetProfilesWithoutTeam(offset, limit) result := <-a.Srv.Store.User().GetProfilesWithoutTeam(offset, limit, viewRestrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -609,16 +609,16 @@ func (a *App) GetChannelGroupUsers(channelID string) ([]*model.User, *model.AppE
return result.Data.([]*model.User), nil return result.Data.([]*model.User), nil
} }
func (a *App) GetUsersByIds(userIds []string, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetUsersByIds(userIds []string, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
result := <-a.Srv.Store.User().GetProfileByIds(userIds, true) result := <-a.Srv.Store.User().GetProfileByIds(userIds, viewRestrictions == nil, viewRestrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
return a.sanitizeProfiles(result.Data.([]*model.User), asAdmin), nil return a.sanitizeProfiles(result.Data.([]*model.User), asAdmin), nil
} }
func (a *App) GetUsersByUsernames(usernames []string, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetUsersByUsernames(usernames []string, asAdmin bool, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
result := <-a.Srv.Store.User().GetProfilesByUsernames(usernames, "") result := <-a.Srv.Store.User().GetProfilesByUsernames(usernames, viewRestrictions)
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
} }
@@ -1601,9 +1601,10 @@ func (a *App) GetVerifyEmailToken(token string) (*model.Token, *model.AppError)
} }
// GetTotalUsersStats is used for the DM list total // GetTotalUsersStats is used for the DM list total
func (a *App) GetTotalUsersStats() (*model.UsersStats, *model.AppError) { func (a *App) GetTotalUsersStats(viewRestrictions *model.ViewUsersRestrictions) (*model.UsersStats, *model.AppError) {
result := <-a.Srv.Store.User().Count(model.UserCountOptions{ result := <-a.Srv.Store.User().Count(model.UserCountOptions{
IncludeBotAccounts: true, IncludeBotAccounts: true,
ViewRestrictions: viewRestrictions,
}) })
if result.Err != nil { if result.Err != nil {
return nil, result.Err return nil, result.Err
@@ -1682,12 +1683,20 @@ func (a *App) SearchUsersInTeam(teamId string, term string, options *model.UserS
esInterface := a.Elasticsearch esInterface := a.Elasticsearch
license := a.License() license := a.License()
if esInterface != nil && *a.Config().ElasticsearchSettings.EnableAutocomplete && license != nil && *license.Features.Elasticsearch { if esInterface != nil && *a.Config().ElasticsearchSettings.EnableAutocomplete && license != nil && *license.Features.Elasticsearch {
usersIds, err := a.Elasticsearch.SearchUsersInTeam(teamId, term, options) listOfAllowedChannels, err := a.GetViewUsersRestrictionsForTeam(a.Session.UserId, teamId)
if err != nil {
return nil, err
}
if len(listOfAllowedChannels) == 0 {
return []*model.User{}, nil
}
usersIds, err := a.Elasticsearch.SearchUsersInTeam(teamId, listOfAllowedChannels, term, options)
if err != nil { if err != nil {
return nil, err return nil, err
} }
result = <-a.Srv.Store.User().GetProfileByIds(usersIds, false) result = <-a.Srv.Store.User().GetProfileByIds(usersIds, false, nil)
} else { } else {
result = <-a.Srv.Store.User().Search(teamId, term, options) result = <-a.Srv.Store.User().Search(teamId, term, options)
} }
@@ -1738,12 +1747,25 @@ func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term s
esInterface := a.Elasticsearch esInterface := a.Elasticsearch
license := a.License() license := a.License()
if esInterface != nil && *a.Config().ElasticsearchSettings.EnableAutocomplete && license != nil && *license.Features.Elasticsearch { if esInterface != nil && *a.Config().ElasticsearchSettings.EnableAutocomplete && license != nil && *license.Features.Elasticsearch {
uchanIds, nuchanIds, err := a.Elasticsearch.SearchUsersInChannel(teamId, channelId, term, options) listOfAllowedChannels, err := a.getListOfAllowedChannelsForTeam(teamId, options.ViewRestrictions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
uchan = a.Srv.Store.User().GetProfileByIds(uchanIds, false) if len(listOfAllowedChannels) == 0 {
nuchan = a.Srv.Store.User().GetProfileByIds(nuchanIds, false) return &model.UserAutocompleteInChannel{}, nil
}
uchanIds := []string{}
nuchanIds := []string{}
if !strings.Contains(strings.Join(listOfAllowedChannels, "."), channelId) {
nuchanIds, err = a.Elasticsearch.SearchUsersInTeam(teamId, listOfAllowedChannels, term, options)
} else {
uchanIds, nuchanIds, err = a.Elasticsearch.SearchUsersInChannel(teamId, channelId, listOfAllowedChannels, term, options)
}
if err != nil {
return nil, err
}
uchan = a.Srv.Store.User().GetProfileByIds(uchanIds, false, nil)
nuchan = a.Srv.Store.User().GetProfileByIds(nuchanIds, false, nil)
} else { } else {
uchan = a.Srv.Store.User().SearchInChannel(channelId, term, options) uchan = a.Srv.Store.User().SearchInChannel(channelId, term, options)
nuchan = a.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, options) nuchan = a.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, options)
@@ -1785,12 +1807,20 @@ func (a *App) AutocompleteUsersInTeam(teamId string, term string, options *model
esInterface := a.Elasticsearch esInterface := a.Elasticsearch
license := a.License() license := a.License()
if esInterface != nil && *a.Config().ElasticsearchSettings.EnableAutocomplete && license != nil && *license.Features.Elasticsearch { if esInterface != nil && *a.Config().ElasticsearchSettings.EnableAutocomplete && license != nil && *license.Features.Elasticsearch {
usersIds, err := a.Elasticsearch.SearchUsersInTeam(teamId, term, options) listOfAllowedChannels, err := a.getListOfAllowedChannelsForTeam(teamId, options.ViewRestrictions)
if err != nil {
return nil, err
}
if len(listOfAllowedChannels) == 0 {
return &model.UserAutocompleteInTeam{}, nil
}
usersIds, err := a.Elasticsearch.SearchUsersInTeam(teamId, listOfAllowedChannels, term, options)
if err != nil { if err != nil {
return nil, err return nil, err
} }
result = <-a.Srv.Store.User().GetProfileByIds(usersIds, false) result = <-a.Srv.Store.User().GetProfileByIds(usersIds, false, nil)
} else { } else {
result = <-a.Srv.Store.User().Search(teamId, term, options) result = <-a.Srv.Store.User().Search(teamId, term, options)
} }
@@ -1865,6 +1895,16 @@ func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provide
return nil return nil
} }
func (a *App) RestrictUsersGetByPermissions(userId string, options *model.UserGetOptions) (*model.UserGetOptions, *model.AppError) {
restrictions, err := a.GetViewUsersRestrictions(userId)
if err != nil {
return nil, err
}
options.ViewRestrictions = restrictions
return options, nil
}
// FilterNonGroupTeamMembers returns the subset of the given user IDs of the users who are not members of groups // FilterNonGroupTeamMembers returns the subset of the given user IDs of the users who are not members of groups
// associated to the team. // associated to the team.
func (a *App) FilterNonGroupTeamMembers(userIDs []string, team *model.Team) ([]string, error) { func (a *App) FilterNonGroupTeamMembers(userIDs []string, team *model.Team) ([]string, error) {
@@ -1930,3 +1970,154 @@ func (a *App) FilterNonGroupChannelMembers(userIDs []string, channel *model.Chan
return nonMemberIDs, nil return nonMemberIDs, nil
} }
func (a *App) RestrictUsersSearchByPermissions(userId string, options *model.UserSearchOptions) (*model.UserSearchOptions, *model.AppError) {
restrictions, err := a.GetViewUsersRestrictions(userId)
if err != nil {
return nil, err
}
options.ViewRestrictions = restrictions
return options, nil
}
func (a *App) UserCanSeeOtherUser(userId string, otherUserId string) (bool, *model.AppError) {
if userId == otherUserId {
return true, nil
}
restrictions, err := a.GetViewUsersRestrictions(userId)
if err != nil {
return false, err
}
if restrictions == nil {
return true, nil
}
if len(restrictions.Teams) > 0 {
result, err := a.userBelongsToTeams(otherUserId, restrictions.Teams)
if err != nil {
return false, err
}
if result {
return true, nil
}
}
if len(restrictions.Channels) > 0 {
result, err := a.userBelongsToChannels(otherUserId, restrictions.Channels)
if err != nil {
return false, err
}
if result {
return true, nil
}
}
return false, nil
}
func (a *App) userBelongsToTeams(userId string, teamIds []string) (bool, *model.AppError) {
result := <-a.Srv.Store.Team().UserBelongsToTeams(userId, teamIds)
if result.Err != nil {
return false, result.Err
}
return result.Data.(bool), nil
}
func (a *App) userBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError) {
result := <-a.Srv.Store.Channel().UserBelongsToChannels(userId, channelIds)
if result.Err != nil {
return false, result.Err
}
return result.Data.(bool), nil
}
func (a *App) GetViewUsersRestrictions(userId string) (*model.ViewUsersRestrictions, *model.AppError) {
if a.HasPermissionTo(userId, model.PERMISSION_VIEW_MEMBERS) {
return nil, nil
}
result := <-a.Srv.Store.Team().GetUserTeamIds(userId, true)
if result.Err != nil {
return nil, result.Err
}
teamIds := result.Data.([]string)
teamIdsWithPermission := []string{}
teamIdsWithoutPermission := []string{}
for _, teamId := range teamIds {
if a.HasPermissionToTeam(userId, teamId, model.PERMISSION_VIEW_MEMBERS) {
teamIdsWithPermission = append(teamIdsWithPermission, teamId)
} else {
teamIdsWithoutPermission = append(teamIdsWithoutPermission, teamId)
}
}
if len(teamIdsWithoutPermission) == 0 {
return &model.ViewUsersRestrictions{Teams: teamIdsWithPermission}, nil
}
userChannelMembers := <-a.Srv.Store.Channel().GetAllChannelMembersForUser(userId, true, true)
if userChannelMembers.Err != nil {
return nil, userChannelMembers.Err
}
channelIds := []string{}
for channelId := range userChannelMembers.Data.(map[string]string) {
channelIds = append(channelIds, channelId)
}
return &model.ViewUsersRestrictions{Teams: teamIdsWithPermission, Channels: channelIds}, nil
}
func (a *App) GetViewUsersRestrictionsForTeam(userId string, teamId string) ([]string, *model.AppError) {
if a.HasPermissionTo(userId, model.PERMISSION_VIEW_MEMBERS) {
return nil, nil
}
if a.HasPermissionToTeam(userId, teamId, model.PERMISSION_VIEW_MEMBERS) {
return nil, nil
}
result := <-a.Srv.Store.Channel().GetMembersForUser(teamId, userId)
if result.Err != nil {
return nil, result.Err
}
channelIds := []string{}
for _, membership := range *result.Data.(*model.ChannelMembers) {
channelIds = append(channelIds, membership.ChannelId)
}
return channelIds, nil
}
func (a *App) getListOfAllowedChannelsForTeam(teamId string, viewRestrictions *model.ViewUsersRestrictions) ([]string, *model.AppError) {
var listOfAllowedChannels []string
if viewRestrictions == nil || strings.Contains(strings.Join(viewRestrictions.Teams, "."), teamId) {
result := <-a.Srv.Store.Channel().GetTeamChannels(teamId)
if result.Err != nil {
return nil, result.Err
}
channelIds := []string{}
for _, channel := range *result.Data.(*model.ChannelList) {
channelIds = append(channelIds, channel.Id)
}
return channelIds, nil
}
cresult := <-a.Srv.Store.Channel().GetChannelsByIds(viewRestrictions.Channels)
if cresult.Err != nil {
return nil, cresult.Err
}
for _, c := range cresult.Data.([]*model.Channel) {
if c.TeamId == teamId {
listOfAllowedChannels = append(listOfAllowedChannels, c.Id)
}
}
return listOfAllowedChannels, nil
}

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

@@ -704,3 +704,206 @@ func TestPasswordRecovery(t *testing.T) {
err = th.App.ResetPasswordFromToken(token.Token, "abcdefgh") err = th.App.ResetPasswordFromToken(token.Token, "abcdefgh")
assert.NotNil(t, err) assert.NotNil(t, err)
} }
func TestGetViewUsersRestrictions(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
team1 := th.CreateTeam()
team2 := th.CreateTeam()
th.CreateTeam() // Another team
user1 := th.CreateUser()
th.LinkUserToTeam(user1, team1)
th.LinkUserToTeam(user1, team2)
th.App.UpdateTeamMemberRoles(team1.Id, user1.Id, "team_user team_admin")
team1channel1 := th.CreateChannel(team1)
team1channel2 := th.CreateChannel(team1)
th.CreateChannel(team1) // Another channel
team1offtopic, err := th.App.GetChannelByName("off-topic", team1.Id, false)
require.Nil(t, err)
team1townsquare, err := th.App.GetChannelByName("town-square", team1.Id, false)
require.Nil(t, err)
team2channel1 := th.CreateChannel(team2)
th.CreateChannel(team2) // Another channel
team2offtopic, err := th.App.GetChannelByName("off-topic", team2.Id, false)
require.Nil(t, err)
team2townsquare, err := th.App.GetChannelByName("town-square", team2.Id, false)
require.Nil(t, err)
th.App.AddUserToChannel(user1, team1channel1)
th.App.AddUserToChannel(user1, team1channel2)
th.App.AddUserToChannel(user1, team2channel1)
addPermission := func(role *model.Role, permission string) *model.AppError {
newPermissions := append(role.Permissions, permission)
_, err := th.App.PatchRole(role, &model.RolePatch{Permissions: &newPermissions})
return err
}
removePermission := func(role *model.Role, permission string) *model.AppError {
newPermissions := []string{}
for _, oldPermission := range role.Permissions {
if permission != oldPermission {
newPermissions = append(newPermissions, oldPermission)
}
}
_, err := th.App.PatchRole(role, &model.RolePatch{Permissions: &newPermissions})
return err
}
t.Run("VIEW_MEMBERS permission granted at system level", func(t *testing.T) {
restrictions, err := th.App.GetViewUsersRestrictions(user1.Id)
require.Nil(t, err)
assert.Nil(t, restrictions)
})
t.Run("VIEW_MEMBERS permission granted at team level", func(t *testing.T) {
systemUserRole, err := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID)
require.Nil(t, err)
teamUserRole, err := th.App.GetRoleByName(model.TEAM_USER_ROLE_ID)
require.Nil(t, err)
require.Nil(t, removePermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer addPermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
require.Nil(t, addPermission(teamUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer removePermission(teamUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
restrictions, err := th.App.GetViewUsersRestrictions(user1.Id)
require.Nil(t, err)
assert.NotNil(t, restrictions)
assert.NotNil(t, restrictions.Teams)
assert.Len(t, restrictions.Channels, 0)
assert.ElementsMatch(t, []string{team1.Id, team2.Id}, restrictions.Teams)
})
t.Run("VIEW_MEMBERS permission not granted at any level", func(t *testing.T) {
systemUserRole, err := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID)
require.Nil(t, err)
require.Nil(t, removePermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer addPermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
restrictions, err := th.App.GetViewUsersRestrictions(user1.Id)
require.Nil(t, err)
assert.NotNil(t, restrictions)
assert.Len(t, restrictions.Teams, 0)
assert.NotNil(t, restrictions.Channels)
assert.ElementsMatch(t, []string{team1townsquare.Id, team1offtopic.Id, team1channel1.Id, team1channel2.Id, team2townsquare.Id, team2offtopic.Id, team2channel1.Id}, restrictions.Channels)
})
t.Run("VIEW_MEMBERS permission for some teams but not for others", func(t *testing.T) {
systemUserRole, err := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID)
require.Nil(t, err)
teamAdminRole, err := th.App.GetRoleByName(model.TEAM_ADMIN_ROLE_ID)
require.Nil(t, err)
require.Nil(t, removePermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer addPermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
require.Nil(t, addPermission(teamAdminRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer removePermission(teamAdminRole, model.PERMISSION_VIEW_MEMBERS.Id)
restrictions, err := th.App.GetViewUsersRestrictions(user1.Id)
require.Nil(t, err)
assert.NotNil(t, restrictions)
assert.NotNil(t, restrictions.Teams)
assert.NotNil(t, restrictions.Channels)
assert.ElementsMatch(t, restrictions.Teams, []string{team1.Id})
assert.ElementsMatch(t, []string{team1townsquare.Id, team1offtopic.Id, team1channel1.Id, team1channel2.Id, team2townsquare.Id, team2offtopic.Id, team2channel1.Id}, restrictions.Channels)
})
}
func TestGetViewUsersRestrictionsForTeam(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
team1 := th.CreateTeam()
team2 := th.CreateTeam()
th.CreateTeam() // Another team
user1 := th.CreateUser()
th.LinkUserToTeam(user1, team1)
th.LinkUserToTeam(user1, team2)
th.App.UpdateTeamMemberRoles(team1.Id, user1.Id, "team_user team_admin")
team1channel1 := th.CreateChannel(team1)
team1channel2 := th.CreateChannel(team1)
th.CreateChannel(team1) // Another channel
team1offtopic, err := th.App.GetChannelByName("off-topic", team1.Id, false)
require.Nil(t, err)
team1townsquare, err := th.App.GetChannelByName("town-square", team1.Id, false)
require.Nil(t, err)
team2channel1 := th.CreateChannel(team2)
th.CreateChannel(team2) // Another channel
team2offtopic, err := th.App.GetChannelByName("off-topic", team2.Id, false)
require.Nil(t, err)
team2townsquare, err := th.App.GetChannelByName("town-square", team2.Id, false)
require.Nil(t, err)
th.App.AddUserToChannel(user1, team1channel1)
th.App.AddUserToChannel(user1, team1channel2)
th.App.AddUserToChannel(user1, team2channel1)
addPermission := func(role *model.Role, permission string) *model.AppError {
newPermissions := append(role.Permissions, permission)
_, err := th.App.PatchRole(role, &model.RolePatch{Permissions: &newPermissions})
return err
}
removePermission := func(role *model.Role, permission string) *model.AppError {
newPermissions := []string{}
for _, oldPermission := range role.Permissions {
if permission != oldPermission {
newPermissions = append(newPermissions, oldPermission)
}
}
_, err := th.App.PatchRole(role, &model.RolePatch{Permissions: &newPermissions})
return err
}
t.Run("VIEW_MEMBERS permission granted at system level", func(t *testing.T) {
restrictions, err := th.App.GetViewUsersRestrictionsForTeam(user1.Id, team1.Id)
require.Nil(t, err)
assert.Nil(t, restrictions)
})
t.Run("VIEW_MEMBERS permission granted at team level", func(t *testing.T) {
systemUserRole, err := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID)
require.Nil(t, err)
teamUserRole, err := th.App.GetRoleByName(model.TEAM_USER_ROLE_ID)
require.Nil(t, err)
require.Nil(t, removePermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer addPermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
require.Nil(t, addPermission(teamUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer removePermission(teamUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
restrictions, err := th.App.GetViewUsersRestrictionsForTeam(user1.Id, team1.Id)
require.Nil(t, err)
assert.Nil(t, restrictions)
})
t.Run("VIEW_MEMBERS permission not granted at any level", func(t *testing.T) {
systemUserRole, err := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID)
require.Nil(t, err)
require.Nil(t, removePermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id))
defer addPermission(systemUserRole, model.PERMISSION_VIEW_MEMBERS.Id)
restrictions, err := th.App.GetViewUsersRestrictionsForTeam(user1.Id, team1.Id)
require.Nil(t, err)
assert.NotNil(t, restrictions)
assert.ElementsMatch(t, []string{team1townsquare.Id, team1offtopic.Id, team1channel1.Id, team1channel2.Id, team2townsquare.Id, team2offtopic.Id, team2channel1.Id}, restrictions)
})
}

1088
app/user_viewmembers_test.go Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@@ -303,6 +303,19 @@ func (a *App) InvalidateCacheForUser(userId string) {
} }
} }
func (a *App) InvalidateCacheForUserTeams(userId string) {
a.InvalidateCacheForUserTeamsSkipClusterSend(userId)
if a.Cluster != nil {
msg := &model.ClusterMessage{
Event: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER_TEAMS,
SendType: model.CLUSTER_SEND_BEST_EFFORT,
Data: userId,
}
a.Cluster.SendClusterMessage(msg)
}
}
func (a *App) InvalidateCacheForUserSkipClusterSend(userId string) { func (a *App) InvalidateCacheForUserSkipClusterSend(userId string) {
a.Srv.Store.Channel().InvalidateAllChannelMembersForUser(userId) a.Srv.Store.Channel().InvalidateAllChannelMembersForUser(userId)
a.Srv.Store.User().InvalidateProfilesInChannelCacheByUser(userId) a.Srv.Store.User().InvalidateProfilesInChannelCacheByUser(userId)
@@ -314,6 +327,15 @@ func (a *App) InvalidateCacheForUserSkipClusterSend(userId string) {
} }
} }
func (a *App) InvalidateCacheForUserTeamsSkipClusterSend(userId string) {
a.Srv.Store.Team().InvalidateAllTeamIdsForUser(userId)
hub := a.GetHubForUserId(userId)
if hub != nil {
hub.InvalidateUser(userId)
}
}
func (a *App) InvalidateCacheForWebhook(webhookId string) { func (a *App) InvalidateCacheForWebhook(webhookId string) {
a.InvalidateCacheForWebhookSkipClusterSend(webhookId) a.InvalidateCacheForWebhookSkipClusterSend(webhookId)

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

@@ -19,8 +19,8 @@ type ElasticsearchInterface interface {
SearchChannels(teamId, term string) ([]string, *model.AppError) SearchChannels(teamId, term string) ([]string, *model.AppError)
DeleteChannel(channel *model.Channel) *model.AppError DeleteChannel(channel *model.Channel) *model.AppError
IndexUser(user *model.User, teamsIds, channelsIds []string) *model.AppError IndexUser(user *model.User, teamsIds, channelsIds []string) *model.AppError
SearchUsersInChannel(teamId, channelId, term string, options *model.UserSearchOptions) ([]string, []string, *model.AppError) SearchUsersInChannel(teamId, channelId string, restrictedToChannels []string, term string, options *model.UserSearchOptions) ([]string, []string, *model.AppError)
SearchUsersInTeam(teamId, term string, options *model.UserSearchOptions) ([]string, *model.AppError) SearchUsersInTeam(teamId string, restrictedToChannels []string, term string, options *model.UserSearchOptions) ([]string, *model.AppError)
DeleteUser(user *model.User) *model.AppError DeleteUser(user *model.User) *model.AppError
TestConfig(cfg *model.Config) *model.AppError TestConfig(cfg *model.Config) *model.AppError
PurgeIndexes() *model.AppError PurgeIndexes() *model.AppError

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

@@ -2298,10 +2298,6 @@
"id": "api.user.get_authorization_code.unsupported.app_error", "id": "api.user.get_authorization_code.unsupported.app_error",
"translation": "Unsupported OAuth service provider" "translation": "Unsupported OAuth service provider"
}, },
{
"id": "api.user.get_profile_image.not_found.app_error",
"translation": "Unable to get profile image, user not found."
},
{ {
"id": "api.user.get_user_by_email.permissions.app_error", "id": "api.user.get_user_by_email.permissions.app_error",
"translation": "Unable to get user by email." "translation": "Unable to get user by email."
@@ -5586,6 +5582,10 @@
"id": "store.sql_channel.update_member.app_error", "id": "store.sql_channel.update_member.app_error",
"translation": "We encountered an error updating the channel member" "translation": "We encountered an error updating the channel member"
}, },
{
"id": "store.sql_channel.user_belongs_to_channels.app_error",
"translation": "Unable to determine if the user belongs to a list of channels"
},
{ {
"id": "store.sql_channel_member_history.get_users_in_channel_during.app_error", "id": "store.sql_channel_member_history.get_users_in_channel_during.app_error",
"translation": "Failed to get users in channel during specified time period" "translation": "Failed to get users in channel during specified time period"
@@ -6450,6 +6450,10 @@
"id": "store.sql_team.get_unread.app_error", "id": "store.sql_team.get_unread.app_error",
"translation": "Unable to get the teams unread messages" "translation": "Unable to get the teams unread messages"
}, },
{
"id": "store.sql_team.get_user_team_ids.app_error",
"translation": "Unable to get the list of teams of a user"
},
{ {
"id": "store.sql_team.migrate_team_members.commit_transaction.app_error", "id": "store.sql_team.migrate_team_members.commit_transaction.app_error",
"translation": "Failed to commit the database transaction" "translation": "Failed to commit the database transaction"
@@ -6534,6 +6538,10 @@
"id": "store.sql_team.update_last_team_icon_update.app_error", "id": "store.sql_team.update_last_team_icon_update.app_error",
"translation": "Unable to update the date of the last team icon update" "translation": "Unable to update the date of the last team icon update"
}, },
{
"id": "store.sql_team.user_belongs_to_teams.app_error",
"translation": "Unable to determine if the user belongs to a list of teams"
},
{ {
"id": "store.sql_terms_of_service.save.app_error", "id": "store.sql_terms_of_service.save.app_error",
"translation": "Unable to save terms of service." "translation": "Unable to save terms of service."

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

@@ -20,6 +20,7 @@ const (
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME = "inv_channel_name" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME = "inv_channel_name"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL = "inv_channel" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL = "inv_channel"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER = "inv_user" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER = "inv_user"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER_TEAMS = "inv_user_teams"
CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER = "clear_session_user" CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER = "clear_session_user"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES = "inv_roles" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES = "inv_roles"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES = "inv_schemes" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES = "inv_schemes"

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

@@ -85,6 +85,7 @@ var PERMISSION_READ_BOTS *Permission
var PERMISSION_READ_OTHERS_BOTS *Permission var PERMISSION_READ_OTHERS_BOTS *Permission
var PERMISSION_MANAGE_BOTS *Permission var PERMISSION_MANAGE_BOTS *Permission
var PERMISSION_MANAGE_OTHERS_BOTS *Permission var PERMISSION_MANAGE_OTHERS_BOTS *Permission
var PERMISSION_VIEW_MEMBERS *Permission
// General permission that encompasses all system admin functions // General permission that encompasses all system admin functions
// in the future this could be broken up to allow access to some // in the future this could be broken up to allow access to some
@@ -519,6 +520,12 @@ func initializePermissions() {
"authentication.permisssions.manage_jobs.description", "authentication.permisssions.manage_jobs.description",
PERMISSION_SCOPE_SYSTEM, PERMISSION_SCOPE_SYSTEM,
} }
PERMISSION_VIEW_MEMBERS = &Permission{
"view_members",
"authentication.permisssions.view_members.name",
"authentication.permisssions.view_members.description",
PERMISSION_SCOPE_TEAM,
}
ALL_PERMISSIONS = []*Permission{ ALL_PERMISSIONS = []*Permission{
PERMISSION_INVITE_USER, PERMISSION_INVITE_USER,
@@ -591,6 +598,7 @@ func initializePermissions() {
PERMISSION_MANAGE_BOTS, PERMISSION_MANAGE_BOTS,
PERMISSION_MANAGE_OTHERS_BOTS, PERMISSION_MANAGE_OTHERS_BOTS,
PERMISSION_MANAGE_SYSTEM, PERMISSION_MANAGE_SYSTEM,
PERMISSION_VIEW_MEMBERS,
} }
} }

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

@@ -268,6 +268,7 @@ func MakeDefaultRoles() map[string]*Role {
PERMISSION_JOIN_PUBLIC_TEAMS.Id, PERMISSION_JOIN_PUBLIC_TEAMS.Id,
PERMISSION_CREATE_DIRECT_CHANNEL.Id, PERMISSION_CREATE_DIRECT_CHANNEL.Id,
PERMISSION_CREATE_GROUP_CHANNEL.Id, PERMISSION_CREATE_GROUP_CHANNEL.Id,
PERMISSION_VIEW_MEMBERS.Id,
}, },
SchemeManaged: true, SchemeManaged: true,
BuiltIn: true, BuiltIn: true,
@@ -357,6 +358,7 @@ func MakeDefaultRoles() map[string]*Role {
PERMISSION_REMOVE_OTHERS_REACTIONS.Id, PERMISSION_REMOVE_OTHERS_REACTIONS.Id,
PERMISSION_LIST_PRIVATE_TEAMS.Id, PERMISSION_LIST_PRIVATE_TEAMS.Id,
PERMISSION_JOIN_PRIVATE_TEAMS.Id, PERMISSION_JOIN_PRIVATE_TEAMS.Id,
PERMISSION_VIEW_MEMBERS.Id,
}, },
roles[TEAM_USER_ROLE_ID].Permissions..., roles[TEAM_USER_ROLE_ID].Permissions...,
), ),

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

@@ -4,6 +4,7 @@
package model package model
import ( import (
"crypto/sha256"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@@ -118,6 +119,22 @@ type UserForIndexing struct {
ChannelsIds []string `json:"channel_id"` ChannelsIds []string `json:"channel_id"`
} }
type ViewUsersRestrictions struct {
Teams []string
Channels []string
}
func (r *ViewUsersRestrictions) Hash() string {
if r == nil {
return ""
}
ids := append(r.Teams, r.Channels...)
sort.Strings(ids)
hash := sha256.New()
hash.Write([]byte(strings.Join(ids, "")))
return fmt.Sprintf("%x", hash.Sum(nil))
}
type UserSlice []*User type UserSlice []*User
func (u UserSlice) Usernames() []string { func (u UserSlice) Usernames() []string {

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

@@ -13,4 +13,6 @@ type UserCountOptions struct {
ExcludeRegularUsers bool ExcludeRegularUsers bool
// Only include users on a specific team. "" for any team. // Only include users on a specific team. "" for any team.
TeamId string TeamId string
// Restrict to search in a list of teams and channels
ViewRestrictions *ViewUsersRestrictions
} }

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

@@ -20,6 +20,8 @@ type UserGetOptions struct {
Role string Role string
// Sorting option // Sorting option
Sort string Sort string
// Restrict to search in a list of teams and channels
ViewRestrictions *ViewUsersRestrictions
// Page // Page
Page int Page int
// Page size // Page size

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

@@ -57,4 +57,6 @@ type UserSearchOptions struct {
Limit int Limit int
// Filters for the given role // Filters for the given role
Role string Role string
// Restrict to search in a list of teams and channels
ViewRestrictions *ViewUsersRestrictions
} }

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

@@ -2604,3 +2604,27 @@ func (s SqlChannelStore) GetChannelsBatchForIndexing(startTime, endTime int64, l
result.Data = channels result.Data = channels
}) })
} }
func (s SqlChannelStore) UserBelongsToChannels(userId string, channelIds []string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
query := s.getQueryBuilder().
Select("Count(*)").
From("ChannelMembers").
Where(sq.And{
sq.Eq{"UserId": userId},
sq.Eq{"ChannelId": channelIds},
})
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.UserBelongsToChannels", "store.sql_channel.user_belongs_to_channels.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
c, err := s.GetReplica().SelectInt(queryString, args...)
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.UserBelongsToChannels", "store.sql_channel.user_belongs_to_channels.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
result.Data = c > 0
})
}

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

@@ -124,7 +124,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
supplier.initConnection() supplier.initConnection()
supplier.oldStores.team = NewSqlTeamStore(supplier) supplier.oldStores.team = NewSqlTeamStore(supplier, metrics)
supplier.oldStores.channel = NewSqlChannelStore(supplier, metrics) supplier.oldStores.channel = NewSqlChannelStore(supplier, metrics)
supplier.oldStores.post = NewSqlPostStore(supplier, metrics) supplier.oldStores.post = NewSqlPostStore(supplier, metrics)
supplier.oldStores.user = NewSqlUserStore(supplier, metrics) supplier.oldStores.user = NewSqlUserStore(supplier, metrics)

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

@@ -5,21 +5,28 @@ package sqlstore
import ( import (
"database/sql" "database/sql"
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
sq "github.com/Masterminds/squirrel"
"github.com/mattermost/gorp" "github.com/mattermost/gorp"
"github.com/mattermost/mattermost-server/einterfaces"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store" "github.com/mattermost/mattermost-server/store"
"github.com/mattermost/mattermost-server/utils"
) )
const ( const (
TEAM_MEMBER_EXISTS_ERROR = "store.sql_team.save_member.exists.app_error" TEAM_MEMBER_EXISTS_ERROR = "store.sql_team.save_member.exists.app_error"
ALL_TEAM_IDS_FOR_USER_CACHE_SIZE = model.SESSION_CACHE_SIZE
ALL_TEAM_IDS_FOR_USER_CACHE_SEC = 1800 // 30 mins
) )
type SqlTeamStore struct { type SqlTeamStore struct {
SqlStore SqlStore
metrics einterfaces.MetricsInterface
} }
type teamMember struct { type teamMember struct {
@@ -132,8 +139,11 @@ func (db teamMemberWithSchemeRolesList) ToModel() []*model.TeamMember {
return tms return tms
} }
func NewSqlTeamStore(sqlStore SqlStore) store.TeamStore { func NewSqlTeamStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.TeamStore {
s := &SqlTeamStore{sqlStore} s := &SqlTeamStore{
sqlStore,
metrics,
}
for _, db := range sqlStore.GetAllConns() { for _, db := range sqlStore.GetAllConns() {
table := db.AddTableWithName(model.Team{}, "Teams").SetKeys(false, "Id") table := db.AddTableWithName(model.Team{}, "Teams").SetKeys(false, "Id")
@@ -224,6 +234,11 @@ func (s SqlTeamStore) Update(team *model.Team) (*model.Team, *model.AppError) {
return nil, model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.app_error", nil, "id="+team.Id, http.StatusInternalServerError) return nil, model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.app_error", nil, "id="+team.Id, http.StatusInternalServerError)
} }
if oldTeam.DeleteAt == 0 && team.DeleteAt != 0 {
// Invalidate this cache after any team deletion
allTeamIdsForUserCache.Purge()
}
return team, nil return team, nil
} }
@@ -461,21 +476,21 @@ func (s SqlTeamStore) AnalyticsTeamCount() store.StoreChannel {
}) })
} }
var TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY = ` func (s SqlTeamStore) getTeamMembersWithSchemeSelectQuery() sq.SelectBuilder {
SELECT return s.getQueryBuilder().
TeamMembers.*, Select(
TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole, "TeamMembers.*",
TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole "TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole",
FROM "TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole",
TeamMembers ).
LEFT JOIN From("TeamMembers").
Teams ON TeamMembers.TeamId = Teams.Id LeftJoin("Teams ON TeamMembers.TeamId = Teams.Id").
LEFT JOIN LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id")
Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id }
`
func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) store.StoreChannel { func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
defer s.InvalidateAllTeamIdsForUser(member.UserId)
if result.Err = member.IsValid(); result.Err != nil { if result.Err = member.IsValid(); result.Err != nil {
return return
} }
@@ -517,8 +532,18 @@ func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int)
return return
} }
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": dbMember.TeamId}).
Where(sq.Eq{"TeamMembers.UserId": dbMember.UserId})
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var retrievedMember teamMemberWithSchemeRoles var retrievedMember teamMemberWithSchemeRoles
if err := s.GetMaster().SelectOne(&retrievedMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": dbMember.TeamId, "UserId": dbMember.UserId}); err != nil { if err := s.GetMaster().SelectOne(&retrievedMember, queryString, args...); err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound) result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound)
return return
@@ -543,8 +568,18 @@ func (s SqlTeamStore) UpdateMember(member *model.TeamMember) store.StoreChannel
return return
} }
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": member.TeamId}).
Where(sq.Eq{"TeamMembers.UserId": member.UserId})
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var retrievedMember teamMemberWithSchemeRoles var retrievedMember teamMemberWithSchemeRoles
if err := s.GetMaster().SelectOne(&retrievedMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": member.TeamId, "UserId": member.UserId}); err != nil { if err := s.GetMaster().SelectOne(&retrievedMember, queryString, args...); err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound) result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
return return
@@ -559,8 +594,18 @@ func (s SqlTeamStore) UpdateMember(member *model.TeamMember) store.StoreChannel
func (s SqlTeamStore) GetMember(teamId string, userId string) store.StoreChannel { func (s SqlTeamStore) GetMember(teamId string, userId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": teamId}).
Where(sq.Eq{"TeamMembers.UserId": userId})
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var dbMember teamMemberWithSchemeRoles var dbMember teamMemberWithSchemeRoles
err := s.GetReplica().SelectOne(&dbMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId}) err = s.GetReplica().SelectOne(&dbMember, queryString, args...)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.missing.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusNotFound) result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.missing.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusNotFound)
@@ -573,10 +618,24 @@ func (s SqlTeamStore) GetMember(teamId string, userId string) store.StoreChannel
}) })
} }
func (s SqlTeamStore) GetMembers(teamId string, offset int, limit int) store.StoreChannel { func (s SqlTeamStore) GetMembers(teamId string, offset int, limit int, restrictions *model.ViewUsersRestrictions) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": teamId}).
Where(sq.Eq{"TeamMembers.DeleteAt": 0}).
Limit(uint64(limit)).
Offset(uint64(offset))
query = applyTeamMemberViewRestrictionsFilter(query, teamId, restrictions)
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var dbMembers teamMemberWithSchemeRolesList var dbMembers teamMemberWithSchemeRolesList
_, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.DeleteAt = 0 LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}) _, err = s.GetReplica().Select(&dbMembers, queryString, args...)
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
return return
@@ -629,24 +688,27 @@ func (s SqlTeamStore) GetActiveMemberCount(teamId string) store.StoreChannel {
}) })
} }
func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string) store.StoreChannel { func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string, restrictions *model.ViewUsersRestrictions) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
var dbMembers teamMemberWithSchemeRolesList if len(userIds) == 0 {
props := make(map[string]interface{}) result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, "Invalid list of user ids", http.StatusInternalServerError)
idQuery := ""
for index, userId := range userIds {
if len(idQuery) > 0 {
idQuery += ", "
}
props["userId"+strconv.Itoa(index)] = userId
idQuery += ":userId" + strconv.Itoa(index)
} }
props["TeamId"] = teamId query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": teamId}).
Where(sq.Eq{"TeamMembers.UserId": userIds}).
Where(sq.Eq{"TeamMembers.DeleteAt": 0})
if _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId IN ("+idQuery+") AND TeamMembers.DeleteAt = 0", props); err != nil { query = applyTeamMemberViewRestrictionsFilter(query, teamId, restrictions)
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var dbMembers teamMemberWithSchemeRolesList
if _, err := s.GetReplica().Select(&dbMembers, queryString, args...); err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
return return
} }
@@ -656,8 +718,17 @@ func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string) store.Sto
func (s SqlTeamStore) GetTeamsForUser(userId string) store.StoreChannel { func (s SqlTeamStore) GetTeamsForUser(userId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.UserId": userId})
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var dbMembers teamMemberWithSchemeRolesList var dbMembers teamMemberWithSchemeRolesList
_, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId", map[string]interface{}{"UserId": userId}) _, err = s.GetReplica().Select(&dbMembers, queryString, args...)
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
return return
@@ -669,9 +740,19 @@ func (s SqlTeamStore) GetTeamsForUser(userId string) store.StoreChannel {
func (s SqlTeamStore) GetTeamsForUserWithPagination(userId string, page, perPage int) store.StoreChannel { func (s SqlTeamStore) GetTeamsForUserWithPagination(userId string, page, perPage int) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.UserId": userId}).
Limit(uint64(perPage)).
Offset(uint64(page * perPage))
queryString, args, err := query.ToSql()
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetTeamsForUserWithPagination", "store.sql_team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
var dbMembers teamMemberWithSchemeRolesList var dbMembers teamMemberWithSchemeRolesList
offset := page * perPage _, err = s.GetReplica().Select(&dbMembers, queryString, args...)
_, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId Limit :Limit Offset :Offset", map[string]interface{}{"UserId": userId, "Limit": perPage, "Offset": offset})
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetTeamsForUserWithPagination", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.GetTeamsForUserWithPagination", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
return return
@@ -731,7 +812,7 @@ func (s SqlTeamStore) RemoveMember(teamId string, userId string) store.StoreChan
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId AND UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId}) _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId AND UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId})
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
} }
}) })
} }
@@ -740,7 +821,7 @@ func (s SqlTeamStore) RemoveAllMembersByTeam(teamId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}) _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId})
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
} }
}) })
} }
@@ -749,7 +830,7 @@ func (s SqlTeamStore) RemoveAllMembersByUser(userId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}) _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlTeamStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
} }
}) })
} }
@@ -849,6 +930,22 @@ func (s SqlTeamStore) ResetAllTeamSchemes() store.StoreChannel {
}) })
} }
var allTeamIdsForUserCache = utils.NewLru(ALL_TEAM_IDS_FOR_USER_CACHE_SIZE)
func (s SqlTeamStore) ClearCaches() {
allTeamIdsForUserCache.Purge()
if s.metrics != nil {
s.metrics.IncrementMemCacheInvalidationCounter("All Team Ids for User - Purge")
}
}
func (s SqlTeamStore) InvalidateAllTeamIdsForUser(userId string) {
allTeamIdsForUserCache.Remove(userId)
if s.metrics != nil {
s.metrics.IncrementMemCacheInvalidationCounter("All Team Ids for User - Remove by UserId")
}
}
func (s SqlTeamStore) ClearAllCustomRoleAssignments() store.StoreChannel { func (s SqlTeamStore) ClearAllCustomRoleAssignments() store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
builtInRoles := model.MakeDefaultRoles() builtInRoles := model.MakeDefaultRoles()
@@ -944,6 +1041,48 @@ func (s SqlTeamStore) GetAllForExportAfter(limit int, afterId string) store.Stor
}) })
} }
func (s SqlTeamStore) GetUserTeamIds(userId string, allowFromCache bool) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
if allowFromCache {
if cacheItem, ok := allTeamIdsForUserCache.Get(userId); ok {
if s.metrics != nil {
s.metrics.IncrementMemCacheHitCounter("All Team Ids for User")
}
result.Data = cacheItem.([]string)
return
}
}
if s.metrics != nil {
s.metrics.IncrementMemCacheMissCounter("All Team Ids for User")
}
var teamIds []string
_, err := s.GetReplica().Select(&teamIds, `
SELECT
TeamId
FROM
TeamMembers
INNER JOIN
Teams ON TeamMembers.TeamId = Teams.Id
WHERE
TeamMembers.UserId = :UserId
AND TeamMembers.DeleteAt = 0
AND Teams.DeleteAt = 0`,
map[string]interface{}{"UserId": userId})
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.GetUserTeamIds", "store.sql_team.get_user_team_ids.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
return
}
result.Data = teamIds
if allowFromCache {
allTeamIdsForUserCache.AddWithExpiresInSecs(userId, teamIds, ALL_TEAM_IDS_FOR_USER_CACHE_SEC)
}
})
}
func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel { func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
var members []*model.TeamMemberForExport var members []*model.TeamMemberForExport
@@ -967,3 +1106,56 @@ func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel
result.Data = members result.Data = members
}) })
} }
func (s SqlTeamStore) UserBelongsToTeams(userId string, teamIds []string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
props := make(map[string]interface{})
props["UserId"] = userId
idQuery := ""
for index, teamId := range teamIds {
if len(idQuery) > 0 {
idQuery += ", "
}
props["teamId"+strconv.Itoa(index)] = teamId
idQuery += ":teamId" + strconv.Itoa(index)
}
c, err := s.GetReplica().SelectInt("SELECT Count(*) FROM TeamMembers WHERE UserId = :UserId AND TeamId IN ("+idQuery+") AND DeleteAt = 0", props)
if err != nil {
result.Err = model.NewAppError("SqlTeamStore.UserBelongsToTeams", "store.sql_team.user_belongs_to_teams.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
result.Data = c > 0
})
}
func applyTeamMemberViewRestrictionsFilter(query sq.SelectBuilder, teamId string, restrictions *model.ViewUsersRestrictions) sq.SelectBuilder {
if restrictions == nil {
return query
}
// If you have no access to teams or channels, return and empty result.
if restrictions.Teams != nil && len(restrictions.Teams) == 0 && restrictions.Channels != nil && len(restrictions.Channels) == 0 {
return query.Where("1 = 0")
}
teams := make([]interface{}, len(restrictions.Teams))
for i, v := range restrictions.Teams {
teams[i] = v
}
channels := make([]interface{}, len(restrictions.Channels))
for i, v := range restrictions.Channels {
channels[i] = v
}
resultQuery := query.Join("Users ru ON (TeamMembers.UserId = ru.Id)")
if restrictions.Teams != nil && len(restrictions.Teams) > 0 {
resultQuery = resultQuery.Join(fmt.Sprintf("TeamMembers rtm ON ( rtm.UserId = ru.Id AND rtm.DeleteAt = 0 AND rtm.TeamId IN (%s))", sq.Placeholders(len(teams))), teams...)
}
if restrictions.Channels != nil && len(restrictions.Channels) > 0 {
resultQuery = resultQuery.Join(fmt.Sprintf("ChannelMembers rcm ON ( rcm.UserId = ru.Id AND rcm.ChannelId IN (%s))", sq.Placeholders(len(channels))), channels...)
}
return resultQuery.Distinct()
}

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

@@ -407,6 +407,8 @@ func (us SqlUserStore) GetAllProfiles(options *model.UserGetOptions) store.Store
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage)) Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
query = applyRoleFilter(query, options.Role, isPostgreSQL) query = applyRoleFilter(query, options.Role, isPostgreSQL)
if options.Inactive { if options.Inactive {
@@ -466,6 +468,8 @@ func (us SqlUserStore) GetProfiles(options *model.UserGetOptions) store.StoreCha
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage)) Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
query = applyRoleFilter(query, options.Role, isPostgreSQL) query = applyRoleFilter(query, options.Role, isPostgreSQL)
if options.Inactive { if options.Inactive {
@@ -632,7 +636,7 @@ func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache
}) })
} }
func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int) store.StoreChannel { func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, 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).
@@ -641,6 +645,8 @@ func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string,
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(offset)).Limit(uint64(limit)) Offset(uint64(offset)).Limit(uint64(limit))
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
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)
@@ -661,7 +667,7 @@ func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string,
}) })
} }
func (us SqlUserStore) GetProfilesWithoutTeam(offset int, limit int) store.StoreChannel { func (us SqlUserStore) GetProfilesWithoutTeam(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.
Where(`( Where(`(
@@ -676,6 +682,8 @@ func (us SqlUserStore) GetProfilesWithoutTeam(offset int, limit int) store.Store
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(offset)).Limit(uint64(limit)) Offset(uint64(offset)).Limit(uint64(limit))
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
queryString, args, err := query.ToSql() queryString, args, err := query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlUserStore.GetProfilesWithoutTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlUserStore.GetProfilesWithoutTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -696,13 +704,11 @@ func (us SqlUserStore) GetProfilesWithoutTeam(offset int, limit int) store.Store
}) })
} }
func (us SqlUserStore) GetProfilesByUsernames(usernames []string, teamId string) store.StoreChannel { func (us SqlUserStore) GetProfilesByUsernames(usernames []string, 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
if teamId != "" { query = applyViewRestrictionsFilter(query, viewRestrictions, true)
query = query.Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId)
}
query = query. query = query.
Where(map[string]interface{}{ Where(map[string]interface{}{
@@ -731,7 +737,7 @@ type UserWithLastActivityAt struct {
LastActivityAt int64 LastActivityAt int64
} }
func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) store.StoreChannel { func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, 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.
Column("s.LastActivityAt"). Column("s.LastActivityAt").
@@ -741,6 +747,8 @@ func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, limi
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(offset)).Limit(uint64(limit)) Offset(uint64(offset)).Limit(uint64(limit))
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
queryString, args, err := query.ToSql() queryString, args, err := query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlUserStore.GetRecentlyActiveUsers", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlUserStore.GetRecentlyActiveUsers", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -766,7 +774,7 @@ func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, limi
}) })
} }
func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, limit int) store.StoreChannel { func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, 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.TeamId = ?)", teamId). Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId).
@@ -774,6 +782,8 @@ func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, limit int) stor
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(offset)).Limit(uint64(limit)) Offset(uint64(offset)).Limit(uint64(limit))
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
queryString, args, err := query.ToSql() queryString, args, err := query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlUserStore.GetNewUsersForTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlUserStore.GetNewUsersForTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -794,7 +804,7 @@ func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, limit int) stor
}) })
} }
func (us SqlUserStore) GetProfileByIds(userIds []string, allowFromCache bool) store.StoreChannel { func (us SqlUserStore) GetProfileByIds(userIds []string, allowFromCache bool, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
users := []*model.User{} users := []*model.User{}
remainingUserIds := make([]string, 0) remainingUserIds := make([]string, 0)
@@ -832,6 +842,8 @@ func (us SqlUserStore) GetProfileByIds(userIds []string, allowFromCache bool) st
}). }).
OrderBy("u.Username ASC") OrderBy("u.Username ASC")
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
queryString, args, err := query.ToSql() queryString, args, err := query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlUserStore.GetProfileByIds", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlUserStore.GetProfileByIds", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -1039,18 +1051,18 @@ func (us SqlUserStore) PermanentDelete(userId string) store.StoreChannel {
func (us SqlUserStore) Count(options model.UserCountOptions) store.StoreChannel { func (us SqlUserStore) Count(options model.UserCountOptions) store.StoreChannel {
return store.Do(func(result *store.StoreResult) { return store.Do(func(result *store.StoreResult) {
query := sq.Select("COUNT(Users.Id)").From("Users") query := sq.Select("COUNT(DISTINCT u.Id)").From("Users AS u")
if !options.IncludeDeleted { if !options.IncludeDeleted {
query = query.Where("Users.DeleteAt = 0") query = query.Where("u.DeleteAt = 0")
} }
if options.IncludeBotAccounts { if options.IncludeBotAccounts {
if options.ExcludeRegularUsers { if options.ExcludeRegularUsers {
query = query.Join("Bots ON Users.Id = Bots.UserId") query = query.Join("Bots ON u.Id = Bots.UserId")
} }
} else { } else {
query = query.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL") query = query.LeftJoin("Bots ON u.Id = Bots.UserId").Where("Bots.UserId IS NULL")
if options.ExcludeRegularUsers { if options.ExcludeRegularUsers {
// Currenty this doesn't make sense because it will always return 0 // Currenty this doesn't make sense because it will always return 0
result.Err = model.NewAppError("SqlUserStore.Count", "store.sql_user.count.app_error", nil, "", http.StatusInternalServerError) result.Err = model.NewAppError("SqlUserStore.Count", "store.sql_user.count.app_error", nil, "", http.StatusInternalServerError)
@@ -1059,8 +1071,9 @@ func (us SqlUserStore) Count(options model.UserCountOptions) store.StoreChannel
} }
if options.TeamId != "" { if options.TeamId != "" {
query = query.LeftJoin("TeamMembers ON Users.Id = TeamMembers.UserId").Where("TeamMembers.TeamId = ? AND TeamMembers.DeleteAt = 0", options.TeamId) query = query.LeftJoin("TeamMembers AS tm ON u.Id = tm.UserId").Where("tm.TeamId = ? AND tm.DeleteAt = 0", options.TeamId)
} }
query = applyViewRestrictionsFilter(query, options.ViewRestrictions, false)
if us.DriverName() == model.DATABASE_DRIVER_POSTGRES { if us.DriverName() == model.DATABASE_DRIVER_POSTGRES {
query = query.PlaceholderFormat(sq.Dollar) query = query.PlaceholderFormat(sq.Dollar)
@@ -1285,6 +1298,8 @@ func (us SqlUserStore) performSearch(query sq.SelectBuilder, term string, option
query = generateSearchQuery(query, strings.Fields(term), searchType, isPostgreSQL) query = generateSearchQuery(query, strings.Fields(term), searchType, isPostgreSQL)
} }
query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
queryString, args, err := query.ToSql() queryString, args, err := query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError) result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -1326,7 +1341,7 @@ func (us SqlUserStore) AnalyticsGetSystemAdminCount() store.StoreChannel {
}) })
} }
func (us SqlUserStore) GetProfilesNotInTeam(teamId string, offset int, limit int) store.StoreChannel { func (us SqlUserStore) GetProfilesNotInTeam(teamId string, 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).
@@ -1334,6 +1349,8 @@ func (us SqlUserStore) GetProfilesNotInTeam(teamId string, offset int, limit int
OrderBy("u.Username ASC"). OrderBy("u.Username ASC").
Offset(uint64(offset)).Limit(uint64(limit)) Offset(uint64(offset)).Limit(uint64(limit))
query = applyViewRestrictionsFilter(query, viewRestrictions, true)
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)
@@ -1611,3 +1628,36 @@ func (us SqlUserStore) GetChannelGroupUsers(channelID string) store.StoreChannel
result.Data = users result.Data = users
}) })
} }
func applyViewRestrictionsFilter(query sq.SelectBuilder, restrictions *model.ViewUsersRestrictions, distinct bool) sq.SelectBuilder {
if restrictions == nil {
return query
}
// If you have no access to teams or channels, return and empty result.
if restrictions.Teams != nil && len(restrictions.Teams) == 0 && restrictions.Channels != nil && len(restrictions.Channels) == 0 {
return query.Where("1 = 0")
}
teams := make([]interface{}, len(restrictions.Teams))
for i, v := range restrictions.Teams {
teams[i] = v
}
channels := make([]interface{}, len(restrictions.Channels))
for i, v := range restrictions.Channels {
channels[i] = v
}
resultQuery := query
if restrictions.Teams != nil && len(restrictions.Teams) > 0 {
resultQuery = resultQuery.Join(fmt.Sprintf("TeamMembers rtm ON ( rtm.UserId = u.Id AND rtm.DeleteAt = 0 AND rtm.TeamId IN (%s))", sq.Placeholders(len(teams))), teams...)
}
if restrictions.Channels != nil && len(restrictions.Channels) > 0 {
resultQuery = resultQuery.Join(fmt.Sprintf("ChannelMembers rcm ON ( rcm.UserId = u.Id AND rcm.ChannelId IN (%s))", sq.Placeholders(len(channels))), channels...)
}
if distinct {
return resultQuery.Distinct()
}
return resultQuery
}

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

@@ -103,8 +103,8 @@ type TeamStore interface {
SaveMember(member *model.TeamMember, maxUsersPerTeam int) StoreChannel SaveMember(member *model.TeamMember, maxUsersPerTeam int) StoreChannel
UpdateMember(member *model.TeamMember) StoreChannel UpdateMember(member *model.TeamMember) StoreChannel
GetMember(teamId string, userId string) StoreChannel GetMember(teamId string, userId string) StoreChannel
GetMembers(teamId string, offset int, limit int) StoreChannel GetMembers(teamId string, offset int, limit int, restrictions *model.ViewUsersRestrictions) StoreChannel
GetMembersByIds(teamId string, userIds []string) StoreChannel GetMembersByIds(teamId string, userIds []string, restrictions *model.ViewUsersRestrictions) StoreChannel
GetTotalMemberCount(teamId string) StoreChannel GetTotalMemberCount(teamId string) StoreChannel
GetActiveMemberCount(teamId string) StoreChannel GetActiveMemberCount(teamId string) StoreChannel
GetTeamsForUser(userId string) StoreChannel GetTeamsForUser(userId string) StoreChannel
@@ -122,6 +122,10 @@ type TeamStore interface {
AnalyticsGetTeamCountForScheme(schemeId string) StoreChannel AnalyticsGetTeamCountForScheme(schemeId string) StoreChannel
GetAllForExportAfter(limit int, afterId string) StoreChannel GetAllForExportAfter(limit int, afterId string) StoreChannel
GetTeamMembersForExport(userId string) StoreChannel GetTeamMembersForExport(userId string) StoreChannel
UserBelongsToTeams(userId string, teamIds []string) StoreChannel
GetUserTeamIds(userId string, allowFromCache bool) StoreChannel
InvalidateAllTeamIdsForUser(userId string)
ClearCaches()
} }
type ChannelStore interface { type ChannelStore interface {
@@ -195,6 +199,7 @@ type ChannelStore interface {
GetChannelMembersForExport(userId string, teamId string) StoreChannel GetChannelMembersForExport(userId string, teamId string) StoreChannel
RemoveAllDeactivatedMembers(channelId string) StoreChannel RemoveAllDeactivatedMembers(channelId string) StoreChannel
GetChannelsBatchForIndexing(startTime, endTime int64, limit int) StoreChannel GetChannelsBatchForIndexing(startTime, endTime int64, limit int) StoreChannel
UserBelongsToChannels(userId string, channelIds []string) StoreChannel
} }
type ChannelMemberHistoryStore interface { type ChannelMemberHistoryStore interface {
@@ -256,12 +261,12 @@ 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) StoreChannel GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
GetProfilesWithoutTeam(offset int, limit int) StoreChannel GetProfilesWithoutTeam(offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
GetProfilesByUsernames(usernames []string, teamId string) StoreChannel GetProfilesByUsernames(usernames []string, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
GetAllProfiles(options *model.UserGetOptions) StoreChannel GetAllProfiles(options *model.UserGetOptions) StoreChannel
GetProfiles(options *model.UserGetOptions) StoreChannel GetProfiles(options *model.UserGetOptions) StoreChannel
GetProfileByIds(userId []string, allowFromCache bool) StoreChannel GetProfileByIds(userId []string, allowFromCache bool, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
InvalidatProfileCacheForUser(userId string) InvalidatProfileCacheForUser(userId string)
GetByEmail(email string) StoreChannel GetByEmail(email string) StoreChannel
GetByAuth(authData *string, authService string) StoreChannel GetByAuth(authData *string, authService string) StoreChannel
@@ -278,8 +283,8 @@ type UserStore interface {
GetUnreadCount(userId string) StoreChannel GetUnreadCount(userId string) StoreChannel
GetUnreadCountForChannel(userId string, channelId string) StoreChannel GetUnreadCountForChannel(userId string, channelId string) StoreChannel
GetAnyUnreadPostCountForChannel(userId string, channelId string) StoreChannel GetAnyUnreadPostCountForChannel(userId string, channelId string) StoreChannel
GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) StoreChannel GetRecentlyActiveUsersForTeam(teamId string, offset, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
GetNewUsersForTeam(teamId string, offset, limit int) StoreChannel GetNewUsersForTeam(teamId string, offset, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
Search(teamId string, term string, options *model.UserSearchOptions) StoreChannel Search(teamId string, term string, options *model.UserSearchOptions) StoreChannel
SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) StoreChannel SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) StoreChannel
SearchInChannel(channelId string, term string, options *model.UserSearchOptions) StoreChannel SearchInChannel(channelId string, term string, options *model.UserSearchOptions) StoreChannel
@@ -287,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) StoreChannel GetProfilesNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) StoreChannel
GetEtagForProfilesNotInTeam(teamId string) StoreChannel GetEtagForProfilesNotInTeam(teamId string) StoreChannel
ClearAllCustomRoleAssignments() StoreChannel ClearAllCustomRoleAssignments() StoreChannel
InferSystemInstallDate() StoreChannel InferSystemInstallDate() StoreChannel

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

@@ -1087,3 +1087,19 @@ func (_m *ChannelStore) UpdateMember(member *model.ChannelMember) store.StoreCha
return r0 return r0
} }
// UserBelongsToChannels provides a mock function with given fields: userId, channelIds
func (_m *ChannelStore) UserBelongsToChannels(userId string, channelIds []string) store.StoreChannel {
ret := _m.Called(userId, channelIds)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, []string) store.StoreChannel); ok {
r0 = rf(userId, channelIds)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}

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

@@ -61,6 +61,11 @@ func (_m *TeamStore) ClearAllCustomRoleAssignments() store.StoreChannel {
return r0 return r0
} }
// ClearCaches provides a mock function with given fields:
func (_m *TeamStore) ClearCaches() {
_m.Called()
}
// Get provides a mock function with given fields: id // Get provides a mock function with given fields: id
func (_m *TeamStore) Get(id string) (*model.Team, *model.AppError) { func (_m *TeamStore) Get(id string) (*model.Team, *model.AppError) {
ret := _m.Called(id) ret := _m.Called(id)
@@ -294,13 +299,13 @@ func (_m *TeamStore) GetMember(teamId string, userId string) store.StoreChannel
return r0 return r0
} }
// GetMembers provides a mock function with given fields: teamId, offset, limit // GetMembers provides a mock function with given fields: teamId, offset, limit, restrictions
func (_m *TeamStore) GetMembers(teamId string, offset int, limit int) store.StoreChannel { func (_m *TeamStore) GetMembers(teamId string, offset int, limit int, restrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(teamId, offset, limit) ret := _m.Called(teamId, offset, limit, restrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(teamId, offset, limit) r0 = rf(teamId, offset, limit, restrictions)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).(store.StoreChannel)
@@ -310,13 +315,13 @@ func (_m *TeamStore) GetMembers(teamId string, offset int, limit int) store.Stor
return r0 return r0
} }
// GetMembersByIds provides a mock function with given fields: teamId, userIds // GetMembersByIds provides a mock function with given fields: teamId, userIds, restrictions
func (_m *TeamStore) GetMembersByIds(teamId string, userIds []string) store.StoreChannel { func (_m *TeamStore) GetMembersByIds(teamId string, userIds []string, restrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(teamId, userIds) ret := _m.Called(teamId, userIds, restrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, []string) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, []string, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(teamId, userIds) r0 = rf(teamId, userIds, restrictions)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).(store.StoreChannel)
@@ -422,6 +427,27 @@ func (_m *TeamStore) GetTotalMemberCount(teamId string) store.StoreChannel {
return r0 return r0
} }
// GetUserTeamIds provides a mock function with given fields: userId, allowFromCache
func (_m *TeamStore) GetUserTeamIds(userId string, allowFromCache bool) store.StoreChannel {
ret := _m.Called(userId, allowFromCache)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, bool) store.StoreChannel); ok {
r0 = rf(userId, allowFromCache)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}
// InvalidateAllTeamIdsForUser provides a mock function with given fields: userId
func (_m *TeamStore) InvalidateAllTeamIdsForUser(userId string) {
_m.Called(userId)
}
// MigrateTeamMembers provides a mock function with given fields: fromTeamId, fromUserId // MigrateTeamMembers provides a mock function with given fields: fromTeamId, fromUserId
func (_m *TeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) store.StoreChannel { func (_m *TeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) store.StoreChannel {
ret := _m.Called(fromTeamId, fromUserId) ret := _m.Called(fromTeamId, fromUserId)
@@ -686,3 +712,19 @@ func (_m *TeamStore) UpdateMember(member *model.TeamMember) store.StoreChannel {
return r0 return r0
} }
// UserBelongsToTeams provides a mock function with given fields: userId, teamIds
func (_m *TeamStore) UserBelongsToTeams(userId string, teamIds []string) store.StoreChannel {
ret := _m.Called(userId, teamIds)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, []string) store.StoreChannel); ok {
r0 = rf(userId, teamIds)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}

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

@@ -347,13 +347,13 @@ func (_m *UserStore) GetForLogin(loginId string, allowSignInWithUsername bool, a
return r0 return r0
} }
// GetNewUsersForTeam provides a mock function with given fields: teamId, offset, limit // GetNewUsersForTeam provides a mock function with given fields: teamId, offset, limit, viewRestrictions
func (_m *UserStore) GetNewUsersForTeam(teamId string, offset int, limit int) store.StoreChannel { func (_m *UserStore) GetNewUsersForTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(teamId, offset, limit) ret := _m.Called(teamId, offset, limit, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(teamId, offset, limit) r0 = rf(teamId, 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)
@@ -363,13 +363,13 @@ func (_m *UserStore) GetNewUsersForTeam(teamId string, offset int, limit int) st
return r0 return r0
} }
// GetProfileByIds provides a mock function with given fields: userId, allowFromCache // GetProfileByIds provides a mock function with given fields: userId, allowFromCache, viewRestrictions
func (_m *UserStore) GetProfileByIds(userId []string, allowFromCache bool) store.StoreChannel { func (_m *UserStore) GetProfileByIds(userId []string, allowFromCache bool, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(userId, allowFromCache) ret := _m.Called(userId, allowFromCache, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func([]string, bool) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func([]string, bool, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(userId, allowFromCache) r0 = rf(userId, allowFromCache, 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)
@@ -395,13 +395,13 @@ func (_m *UserStore) GetProfiles(options *model.UserGetOptions) store.StoreChann
return r0 return r0
} }
// GetProfilesByUsernames provides a mock function with given fields: usernames, teamId // GetProfilesByUsernames provides a mock function with given fields: usernames, viewRestrictions
func (_m *UserStore) GetProfilesByUsernames(usernames []string, teamId string) store.StoreChannel { func (_m *UserStore) GetProfilesByUsernames(usernames []string, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(usernames, teamId) ret := _m.Called(usernames, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func([]string, string) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func([]string, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(usernames, teamId) r0 = rf(usernames, 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)
@@ -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 // GetProfilesNotInChannel provides a mock function with given fields: teamId, channelId, offset, limit, viewRestrictions
func (_m *UserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int) store.StoreChannel { func (_m *UserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(teamId, channelId, offset, limit) ret := _m.Called(teamId, channelId, offset, limit, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, string, int, int) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(teamId, channelId, offset, limit) r0 = rf(teamId, channelId, 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 // GetProfilesNotInTeam provides a mock function with given fields: teamId, offset, limit, viewRestrictions
func (_m *UserStore) GetProfilesNotInTeam(teamId string, offset int, limit int) store.StoreChannel { func (_m *UserStore) GetProfilesNotInTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(teamId, offset, limit) ret := _m.Called(teamId, offset, limit, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(teamId, offset, limit) r0 = rf(teamId, 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)
@@ -475,13 +475,13 @@ func (_m *UserStore) GetProfilesNotInTeam(teamId string, offset int, limit int)
return r0 return r0
} }
// GetProfilesWithoutTeam provides a mock function with given fields: offset, limit // GetProfilesWithoutTeam provides a mock function with given fields: offset, limit, viewRestrictions
func (_m *UserStore) GetProfilesWithoutTeam(offset int, limit int) store.StoreChannel { func (_m *UserStore) GetProfilesWithoutTeam(offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(offset, limit) ret := _m.Called(offset, limit, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(int, int) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(offset, limit) r0 = rf(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)
@@ -491,13 +491,13 @@ func (_m *UserStore) GetProfilesWithoutTeam(offset int, limit int) store.StoreCh
return r0 return r0
} }
// GetRecentlyActiveUsersForTeam provides a mock function with given fields: teamId, offset, limit // GetRecentlyActiveUsersForTeam provides a mock function with given fields: teamId, offset, limit, viewRestrictions
func (_m *UserStore) GetRecentlyActiveUsersForTeam(teamId string, offset int, limit int) store.StoreChannel { func (_m *UserStore) GetRecentlyActiveUsersForTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) store.StoreChannel {
ret := _m.Called(teamId, offset, limit) ret := _m.Called(teamId, offset, limit, viewRestrictions)
var r0 store.StoreChannel var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func(string, int, int) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, int, int, *model.ViewUsersRestrictions) store.StoreChannel); ok {
r0 = rf(teamId, offset, limit) r0 = rf(teamId, 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)

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

@@ -769,14 +769,14 @@ func testTeamMembers(t *testing.T, ss store.Store) {
store.Must(ss.Team().SaveMember(m2, -1)) store.Must(ss.Team().SaveMember(m2, -1))
store.Must(ss.Team().SaveMember(m3, -1)) store.Must(ss.Team().SaveMember(m3, -1))
if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { if r1 := <-ss.Team().GetMembers(teamId1, 0, 100, nil); r1.Err != nil {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} else { } else {
ms := r1.Data.([]*model.TeamMember) ms := r1.Data.([]*model.TeamMember)
require.Len(t, ms, 2) require.Len(t, ms, 2)
} }
if r1 := <-ss.Team().GetMembers(teamId2, 0, 100); r1.Err != nil { if r1 := <-ss.Team().GetMembers(teamId2, 0, 100, nil); r1.Err != nil {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} else { } else {
ms := r1.Data.([]*model.TeamMember) ms := r1.Data.([]*model.TeamMember)
@@ -798,7 +798,7 @@ func testTeamMembers(t *testing.T, ss store.Store) {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} }
if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { if r1 := <-ss.Team().GetMembers(teamId1, 0, 100, nil); r1.Err != nil {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} else { } else {
ms := r1.Data.([]*model.TeamMember) ms := r1.Data.([]*model.TeamMember)
@@ -813,7 +813,7 @@ func testTeamMembers(t *testing.T, ss store.Store) {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} }
if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { if r1 := <-ss.Team().GetMembers(teamId1, 0, 100, nil); r1.Err != nil {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} else { } else {
ms := r1.Data.([]*model.TeamMember) ms := r1.Data.([]*model.TeamMember)
@@ -872,7 +872,7 @@ func testTeamMembersWithPagination(t *testing.T, ss store.Store) {
r1 = <-ss.Team().RemoveMember(teamId1, m1.UserId) r1 = <-ss.Team().RemoveMember(teamId1, m1.UserId)
require.Nil(t, r1.Err) require.Nil(t, r1.Err)
r1 = <-ss.Team().GetMembers(teamId1, 0, 100) r1 = <-ss.Team().GetMembers(teamId1, 0, 100, nil)
require.Nil(t, r1.Err) require.Nil(t, r1.Err)
ms = r1.Data.([]*model.TeamMember) ms = r1.Data.([]*model.TeamMember)
@@ -1077,7 +1077,7 @@ func testGetTeamMembersByIds(t *testing.T, ss store.Store) {
m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()}
store.Must(ss.Team().SaveMember(m1, -1)) store.Must(ss.Team().SaveMember(m1, -1))
if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId}); r.Err != nil { if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId}, nil); r.Err != nil {
t.Fatal(r.Err) t.Fatal(r.Err)
} else { } else {
rm1 := r.Data.([]*model.TeamMember)[0] rm1 := r.Data.([]*model.TeamMember)[0]
@@ -1094,7 +1094,7 @@ func testGetTeamMembersByIds(t *testing.T, ss store.Store) {
m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()}
store.Must(ss.Team().SaveMember(m2, -1)) store.Must(ss.Team().SaveMember(m2, -1))
if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId, m2.UserId, model.NewId()}); r.Err != nil { if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId, m2.UserId, model.NewId()}, nil); r.Err != nil {
t.Fatal(r.Err) t.Fatal(r.Err)
} else { } else {
rm := r.Data.([]*model.TeamMember) rm := r.Data.([]*model.TeamMember)
@@ -1104,7 +1104,7 @@ func testGetTeamMembersByIds(t *testing.T, ss store.Store) {
} }
} }
if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{}); r.Err == nil { if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{}, nil); r.Err == nil {
t.Fatal("empty user ids - should have failed") t.Fatal("empty user ids - should have failed")
} }
} }

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

@@ -860,19 +860,19 @@ func testUserStoreGetProfilesWithoutTeam(t *testing.T, ss store.Store) {
defer func() { store.Must(ss.Bot().PermanentDelete(u3.Id)) }() defer func() { store.Must(ss.Bot().PermanentDelete(u3.Id)) }()
t.Run("get, offset 0, limit 100", func(t *testing.T) { t.Run("get, offset 0, limit 100", func(t *testing.T) {
result := <-ss.User().GetProfilesWithoutTeam(0, 100) result := <-ss.User().GetProfilesWithoutTeam(0, 100, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{sanitized(u2), sanitized(u3)}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{sanitized(u2), sanitized(u3)}, result.Data.([]*model.User))
}) })
t.Run("get, offset 1, limit 1", func(t *testing.T) { t.Run("get, offset 1, limit 1", func(t *testing.T) {
result := <-ss.User().GetProfilesWithoutTeam(1, 1) result := <-ss.User().GetProfilesWithoutTeam(1, 1, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{sanitized(u3)}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{sanitized(u3)}, result.Data.([]*model.User))
}) })
t.Run("get, offset 2, limit 1", func(t *testing.T) { t.Run("get, offset 2, limit 1", func(t *testing.T) {
result := <-ss.User().GetProfilesWithoutTeam(2, 1) result := <-ss.User().GetProfilesWithoutTeam(2, 1, 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))
}) })
@@ -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) result := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 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) result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 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,13 +1075,13 @@ 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) result := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 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) result := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 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),
@@ -1122,31 +1122,31 @@ func testUserStoreGetProfilesByIds(t *testing.T, ss store.Store) {
defer func() { store.Must(ss.Bot().PermanentDelete(u3.Id)) }() defer func() { store.Must(ss.Bot().PermanentDelete(u3.Id)) }()
t.Run("get u1 by id, no caching", func(t *testing.T) { t.Run("get u1 by id, no caching", func(t *testing.T) {
result := <-ss.User().GetProfileByIds([]string{u1.Id}, false) result := <-ss.User().GetProfileByIds([]string{u1.Id}, false, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{sanitized(u1)}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{sanitized(u1)}, result.Data.([]*model.User))
}) })
t.Run("get u1 by id, caching", func(t *testing.T) { t.Run("get u1 by id, caching", func(t *testing.T) {
result := <-ss.User().GetProfileByIds([]string{u1.Id}, true) result := <-ss.User().GetProfileByIds([]string{u1.Id}, true, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{sanitized(u1)}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{sanitized(u1)}, result.Data.([]*model.User))
}) })
t.Run("get u1, u2, u3 by id, no caching", func(t *testing.T) { t.Run("get u1, u2, u3 by id, no caching", func(t *testing.T) {
result := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id, u3.Id}, false) result := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id, u3.Id}, false, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{sanitized(u1), sanitized(u2), sanitized(u3)}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{sanitized(u1), sanitized(u2), sanitized(u3)}, result.Data.([]*model.User))
}) })
t.Run("get u1, u2, u3 by id, caching", func(t *testing.T) { t.Run("get u1, u2, u3 by id, caching", func(t *testing.T) {
result := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id, u3.Id}, true) result := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id, u3.Id}, true, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{sanitized(u1), sanitized(u2), sanitized(u3)}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{sanitized(u1), sanitized(u2), sanitized(u3)}, result.Data.([]*model.User))
}) })
t.Run("get unknown id, caching", func(t *testing.T) { t.Run("get unknown id, caching", func(t *testing.T) {
result := <-ss.User().GetProfileByIds([]string{"123"}, true) result := <-ss.User().GetProfileByIds([]string{"123"}, true, 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))
}) })
@@ -1185,31 +1185,31 @@ func testUserStoreGetProfilesByUsernames(t *testing.T, ss store.Store) {
defer func() { store.Must(ss.Bot().PermanentDelete(u3.Id)) }() defer func() { store.Must(ss.Bot().PermanentDelete(u3.Id)) }()
t.Run("get by u1 and u2 usernames, team id 1", func(t *testing.T) { t.Run("get by u1 and u2 usernames, team id 1", func(t *testing.T) {
result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u2.Username}, teamId) result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u2.Username}, &model.ViewUsersRestrictions{Teams: []string{teamId}})
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{u1, u2}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{u1, u2}, result.Data.([]*model.User))
}) })
t.Run("get by u1 username, team id 1", func(t *testing.T) { t.Run("get by u1 username, team id 1", func(t *testing.T) {
result := <-ss.User().GetProfilesByUsernames([]string{u1.Username}, teamId) result := <-ss.User().GetProfilesByUsernames([]string{u1.Username}, &model.ViewUsersRestrictions{Teams: []string{teamId}})
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{u1}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{u1}, result.Data.([]*model.User))
}) })
t.Run("get by u1 and u3 usernames, no team id", func(t *testing.T) { t.Run("get by u1 and u3 usernames, no team id", func(t *testing.T) {
result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, "") result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{u1, u3}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{u1, u3}, result.Data.([]*model.User))
}) })
t.Run("get by u1 and u3 usernames, team id 1", func(t *testing.T) { t.Run("get by u1 and u3 usernames, team id 1", func(t *testing.T) {
result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, teamId) result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, &model.ViewUsersRestrictions{Teams: []string{teamId}})
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{u1}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{u1}, result.Data.([]*model.User))
}) })
t.Run("get by u1 and u3 usernames, team id 2", func(t *testing.T) { t.Run("get by u1 and u3 usernames, team id 2", func(t *testing.T) {
result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, team2Id) result := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, &model.ViewUsersRestrictions{Teams: []string{team2Id}})
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{u3}, result.Data.([]*model.User)) assert.Equal(t, []*model.User{u3}, result.Data.([]*model.User))
}) })
@@ -1778,7 +1778,7 @@ func testUserStoreGetRecentlyActiveUsersForTeam(t *testing.T, ss store.Store) {
store.Must(ss.Status().SaveOrUpdate(&model.Status{UserId: u3.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: u3.LastActivityAt, ActiveChannel: ""})) store.Must(ss.Status().SaveOrUpdate(&model.Status{UserId: u3.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: u3.LastActivityAt, ActiveChannel: ""}))
t.Run("get team 1, offset 0, limit 100", func(t *testing.T) { t.Run("get team 1, offset 0, limit 100", func(t *testing.T) {
result := <-ss.User().GetRecentlyActiveUsersForTeam(teamId, 0, 100) result := <-ss.User().GetRecentlyActiveUsersForTeam(teamId, 0, 100, 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),
@@ -1788,7 +1788,7 @@ func testUserStoreGetRecentlyActiveUsersForTeam(t *testing.T, ss store.Store) {
}) })
t.Run("get team 1, offset 0, limit 1", func(t *testing.T) { t.Run("get team 1, offset 0, limit 1", func(t *testing.T) {
result := <-ss.User().GetRecentlyActiveUsersForTeam(teamId, 0, 1) result := <-ss.User().GetRecentlyActiveUsersForTeam(teamId, 0, 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),
@@ -1796,7 +1796,7 @@ func testUserStoreGetRecentlyActiveUsersForTeam(t *testing.T, ss store.Store) {
}) })
t.Run("get team 1, offset 2, limit 1", func(t *testing.T) { t.Run("get team 1, offset 2, limit 1", func(t *testing.T) {
result := <-ss.User().GetRecentlyActiveUsersForTeam(teamId, 2, 1) result := <-ss.User().GetRecentlyActiveUsersForTeam(teamId, 2, 1, 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),
@@ -1844,7 +1844,7 @@ func testUserStoreGetNewUsersForTeam(t *testing.T, ss store.Store) {
store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId2, UserId: u4.Id}, -1)) store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId2, UserId: u4.Id}, -1))
t.Run("get team 1, offset 0, limit 100", func(t *testing.T) { t.Run("get team 1, offset 0, limit 100", func(t *testing.T) {
result := <-ss.User().GetNewUsersForTeam(teamId, 0, 100) result := <-ss.User().GetNewUsersForTeam(teamId, 0, 100, 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),
@@ -1854,7 +1854,7 @@ func testUserStoreGetNewUsersForTeam(t *testing.T, ss store.Store) {
}) })
t.Run("get team 1, offset 0, limit 1", func(t *testing.T) { t.Run("get team 1, offset 0, limit 1", func(t *testing.T) {
result := <-ss.User().GetNewUsersForTeam(teamId, 0, 1) result := <-ss.User().GetNewUsersForTeam(teamId, 0, 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),
@@ -1862,7 +1862,7 @@ func testUserStoreGetNewUsersForTeam(t *testing.T, ss store.Store) {
}) })
t.Run("get team 1, offset 2, limit 1", func(t *testing.T) { t.Run("get team 1, offset 2, limit 1", func(t *testing.T) {
result := <-ss.User().GetNewUsersForTeam(teamId, 2, 1) result := <-ss.User().GetNewUsersForTeam(teamId, 2, 1, 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),
@@ -1870,7 +1870,7 @@ func testUserStoreGetNewUsersForTeam(t *testing.T, ss store.Store) {
}) })
t.Run("get team 2, offset 0, limit 100", func(t *testing.T) { t.Run("get team 2, offset 0, limit 100", func(t *testing.T) {
result := <-ss.User().GetNewUsersForTeam(teamId2, 0, 100) result := <-ss.User().GetNewUsersForTeam(teamId2, 0, 100, nil)
require.Nil(t, result.Err) require.Nil(t, result.Err)
assert.Equal(t, []*model.User{ assert.Equal(t, []*model.User{
sanitized(u4), sanitized(u4),
@@ -2982,6 +2982,23 @@ func testCount(t *testing.T, ss store.Store) {
require.Nil(t, result.Err) require.Nil(t, result.Err)
require.Equal(t, int64(0), result.Data.(int64)) require.Equal(t, int64(0), result.Data.(int64))
result = <-ss.User().Count(model.UserCountOptions{
IncludeBotAccounts: true,
IncludeDeleted: true,
TeamId: teamId,
ViewRestrictions: &model.ViewUsersRestrictions{Teams: []string{teamId}},
})
require.Nil(t, result.Err)
require.Equal(t, int64(1), result.Data.(int64))
result = <-ss.User().Count(model.UserCountOptions{
IncludeBotAccounts: true,
IncludeDeleted: true,
TeamId: teamId,
ViewRestrictions: &model.ViewUsersRestrictions{Teams: []string{model.NewId()}},
})
require.Nil(t, result.Err)
require.Equal(t, int64(0), result.Data.(int64))
} }
func testUserStoreAnalyticsGetInactiveUsersCount(t *testing.T, ss store.Store) { func testUserStoreAnalyticsGetInactiveUsersCount(t *testing.T, ss store.Store) {
@@ -3097,7 +3114,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) result := <-ss.User().GetProfilesNotInTeam(teamId, 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),
@@ -3106,7 +3123,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) result := <-ss.User().GetProfilesNotInTeam(teamId, 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),
@@ -3114,7 +3131,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) result := <-ss.User().GetProfilesNotInTeam(teamId2, 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),
@@ -3137,7 +3154,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) result := <-ss.User().GetProfilesNotInTeam(teamId, 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),
@@ -3161,7 +3178,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) result := <-ss.User().GetProfilesNotInTeam(teamId, 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),