Implement GET /users endpoint for APIv4 (#5277)

Этот коммит содержится в:
Joram Wilander
2017-02-03 15:17:34 -05:00
коммит произвёл GitHub
родитель 948b557453
Коммит 7ff2aef7fa
15 изменённых файлов: 603 добавлений и 87 удалений

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

@@ -291,7 +291,7 @@ func (me *LoadTestProvider) PostsCommand(c *Context, channelId string, message s
var usernames []string
if result := <-app.Srv.Store.User().GetProfiles(c.TeamId, 0, 1000); result.Err == nil {
profileUsers := result.Data.(map[string]*model.User)
profileUsers := result.Data.([]*model.User)
usernames = make([]string, len(profileUsers))
i := 0
for _, userprof := range profileUsers {

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

@@ -442,14 +442,10 @@ func getProfiles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if profiles, err := app.GetUsers(offset, limit); err != nil {
if profiles, err := app.GetUsersMap(offset, limit, c.IsSystemAdmin()); err != nil {
c.Err = err
return
} else {
for k, p := range profiles {
profiles[k] = sanitizeProfile(c, p)
}
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
w.Write([]byte(model.UserMapToJson(profiles)))
}
@@ -482,14 +478,10 @@ func getProfilesInTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if profiles, err := app.GetUsersInTeam(teamId, offset, limit); err != nil {
if profiles, err := app.GetUsersInTeamMap(teamId, offset, limit, c.IsSystemAdmin()); err != nil {
c.Err = err
return
} else {
for k, p := range profiles {
profiles[k] = sanitizeProfile(c, p)
}
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
w.Write([]byte(model.UserMapToJson(profiles)))
}
@@ -523,17 +515,10 @@ func getProfilesInChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
var profiles map[string]*model.User
var profileErr *model.AppError
if profiles, err = app.GetUsersInChannel(channelId, offset, limit); profileErr != nil {
c.Err = profileErr
if profiles, err := app.GetUsersInChannelMap(channelId, offset, limit, c.IsSystemAdmin()); err != nil {
c.Err = err
return
} else {
for k, p := range profiles {
profiles[k] = sanitizeProfile(c, p)
}
w.Write([]byte(model.UserMapToJson(profiles)))
}
}
@@ -566,14 +551,10 @@ func getProfilesNotInChannel(c *Context, w http.ResponseWriter, r *http.Request)
return
}
if profiles, err := app.GetUsersNotInChannel(c.TeamId, channelId, offset, limit); err != nil {
if profiles, err := app.GetUsersNotInChannelMap(c.TeamId, channelId, offset, limit, c.IsSystemAdmin()); err != nil {
c.Err = err
return
} else {
for k, p := range profiles {
profiles[k] = sanitizeProfile(c, p)
}
w.Write([]byte(model.UserMapToJson(profiles)))
}
}

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

@@ -97,6 +97,8 @@ func (me *TestHelper) InitBasic() *TestHelper {
LinkUserToTeam(me.BasicUser, me.BasicTeam)
me.BasicUser2 = me.CreateUser()
LinkUserToTeam(me.BasicUser2, me.BasicTeam)
app.AddUserToChannel(me.BasicUser, me.BasicChannel)
app.AddUserToChannel(me.BasicUser2, me.BasicChannel)
app.UpdateUserRoles(me.BasicUser.Id, model.ROLE_SYSTEM_USER.Id)
me.LoginBasic()

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

@@ -77,17 +77,17 @@ func TestCreateChannel(t *testing.T) {
// Check permissions with policy config changes
isLicensed := utils.IsLicensed
license := utils.License
restrictPublicChannel := *utils.Cfg.TeamSettings.RestrictPublicChannelManagement
restrictPrivateChannel := *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement
restrictPublicChannel := *utils.Cfg.TeamSettings.RestrictPublicChannelCreation
restrictPrivateChannel := *utils.Cfg.TeamSettings.RestrictPrivateChannelCreation
defer func() {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
*utils.Cfg.TeamSettings.RestrictPublicChannelCreation = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelCreation = restrictPrivateChannel
utils.IsLicensed = isLicensed
utils.License = license
utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_ALL
utils.SetDefaultRolesBasedOnConfig()
utils.IsLicensed = true
utils.License = &model.License{Features: &model.Features{}}

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

@@ -5,10 +5,17 @@ package api4
import (
"net/http"
"strconv"
"github.com/gorilla/mux"
)
const (
PAGE_DEFAULT = 0
PER_PAGE_DEFAULT = 60
PER_PAGE_MAXIMUM = 200
)
type ApiParams struct {
UserId string
TeamId string
@@ -18,6 +25,8 @@ type ApiParams struct {
CommandId string
HookId string
EmojiId string
Page int
PerPage int
}
func ApiParamsFromRequest(r *http.Request) *ApiParams {
@@ -57,5 +66,19 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams {
params.EmojiId = val
}
if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil {
params.Page = PAGE_DEFAULT
} else {
params.Page = val
}
if val, err := strconv.Atoi(r.URL.Query().Get("per_page")); err != nil {
params.PerPage = PER_PAGE_DEFAULT
} else if val > PER_PAGE_MAXIMUM {
params.PerPage = PER_PAGE_MAXIMUM
} else {
params.PerPage = val
}
return params
}

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

@@ -16,6 +16,7 @@ func InitUser() {
l4g.Debug(utils.T("api.user.init.debug"))
BaseRoutes.Users.Handle("", ApiHandler(createUser)).Methods("POST")
BaseRoutes.Users.Handle("", ApiSessionRequired(getUsers)).Methods("GET")
BaseRoutes.Users.Handle("/ids", ApiSessionRequired(getUsersByIds)).Methods("POST")
BaseRoutes.User.Handle("", ApiSessionRequired(getUser)).Methods("GET")
@@ -86,6 +87,67 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
inTeamId := r.URL.Query().Get("in_team")
inChannelId := r.URL.Query().Get("in_channel")
notInChannelId := r.URL.Query().Get("not_in_channel")
if len(notInChannelId) > 0 && len(inTeamId) == 0 {
c.SetInvalidParam("team_id")
return
}
var profiles []*model.User
var err *model.AppError
etag := ""
if len(notInChannelId) > 0 {
if !app.SessionHasPermissionToChannel(c.Session, notInChannelId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
return
}
profiles, err = app.GetUsersNotInChannelPage(inTeamId, notInChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
} else if len(inTeamId) > 0 {
if !app.SessionHasPermissionToTeam(c.Session, inTeamId, model.PERMISSION_VIEW_TEAM) {
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
return
}
etag = app.GetUsersInTeamEtag(inTeamId)
if HandleEtag(etag, "Get Users in Team", w, r) {
return
}
profiles, err = app.GetUsersInTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
} else if len(inChannelId) > 0 {
if !app.SessionHasPermissionToChannel(c.Session, inChannelId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
return
}
profiles, err = app.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
} else {
// No permission check required
etag = app.GetUsersEtag()
if HandleEtag(etag, "Get Users", w, r) {
return
}
profiles, err = app.GetUsersPage(c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
}
if err != nil {
c.Err = err
return
} else {
if len(etag) > 0 {
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
}
w.Write([]byte(model.UserListToJson(profiles)))
}
}
func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
userIds := model.ArrayFromJson(r.Body)

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

@@ -242,3 +242,175 @@ func TestUpdateUserRoles(t *testing.T) {
_, resp = SystemAdminClient.UpdateUserRoles(model.NewId(), model.ROLE_SYSTEM_USER.Id)
CheckBadRequestStatus(t, resp)
}
func TestGetUsers(t *testing.T) {
th := Setup().InitBasic()
defer TearDown()
Client := th.Client
rusers, resp := Client.GetUsers(0, 60, "")
CheckNoError(t, resp)
for _, u := range rusers {
CheckUserSanitization(t, u)
}
rusers, resp = Client.GetUsers(0, 60, resp.Etag)
CheckEtag(t, rusers, resp)
rusers, resp = Client.GetUsers(0, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsers(1, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsers(10000, 100, "")
CheckNoError(t, resp)
if len(rusers) != 0 {
t.Fatal("should be no users")
}
// Check default params for page and per_page
if _, err := Client.DoApiGet("/users", ""); err != nil {
t.Fatal("should not have errored")
}
Client.Logout()
_, resp = Client.GetUsers(0, 60, "")
CheckUnauthorizedStatus(t, resp)
}
func TestGetUsersInTeam(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
teamId := th.BasicTeam.Id
rusers, resp := Client.GetUsersInTeam(teamId, 0, 60, "")
CheckNoError(t, resp)
for _, u := range rusers {
CheckUserSanitization(t, u)
}
rusers, resp = Client.GetUsersInTeam(teamId, 0, 60, resp.Etag)
CheckEtag(t, rusers, resp)
rusers, resp = Client.GetUsersInTeam(teamId, 0, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsersInTeam(teamId, 1, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsersInTeam(teamId, 10000, 100, "")
CheckNoError(t, resp)
if len(rusers) != 0 {
t.Fatal("should be no users")
}
Client.Logout()
_, resp = Client.GetUsersInTeam(teamId, 0, 60, "")
CheckUnauthorizedStatus(t, resp)
user := th.CreateUser()
Client.Login(user.Email, user.Password)
_, resp = Client.GetUsersInTeam(teamId, 0, 60, "")
CheckForbiddenStatus(t, resp)
_, resp = th.SystemAdminClient.GetUsersInTeam(teamId, 0, 60, "")
CheckNoError(t, resp)
}
func TestGetUsersInChannel(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
channelId := th.BasicChannel.Id
rusers, resp := Client.GetUsersInChannel(channelId, 0, 60, "")
CheckNoError(t, resp)
for _, u := range rusers {
CheckUserSanitization(t, u)
}
rusers, resp = Client.GetUsersInChannel(channelId, 0, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsersInChannel(channelId, 1, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsersInChannel(channelId, 10000, 100, "")
CheckNoError(t, resp)
if len(rusers) != 0 {
t.Fatal("should be no users")
}
Client.Logout()
_, resp = Client.GetUsersInChannel(channelId, 0, 60, "")
CheckUnauthorizedStatus(t, resp)
user := th.CreateUser()
Client.Login(user.Email, user.Password)
_, resp = Client.GetUsersInChannel(channelId, 0, 60, "")
CheckForbiddenStatus(t, resp)
_, resp = th.SystemAdminClient.GetUsersInChannel(channelId, 0, 60, "")
CheckNoError(t, resp)
}
func TestGetUsersNotInChannel(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
teamId := th.BasicTeam.Id
channelId := th.BasicChannel.Id
user := th.CreateUser()
LinkUserToTeam(user, th.BasicTeam)
rusers, resp := Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
CheckNoError(t, resp)
for _, u := range rusers {
CheckUserSanitization(t, u)
}
rusers, resp = Client.GetUsersNotInChannel(teamId, channelId, 0, 1, "")
CheckNoError(t, resp)
if len(rusers) != 1 {
t.Log(len(rusers))
t.Fatal("should be 1 per page")
}
rusers, resp = Client.GetUsersNotInChannel(teamId, channelId, 10000, 100, "")
CheckNoError(t, resp)
if len(rusers) != 0 {
t.Fatal("should be no users")
}
Client.Logout()
_, resp = Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
CheckUnauthorizedStatus(t, resp)
Client.Login(user.Email, user.Password)
_, resp = Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
CheckForbiddenStatus(t, resp)
_, resp = th.SystemAdminClient.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
CheckNoError(t, resp)
}

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

@@ -404,22 +404,20 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
}
func AddDirectChannels(teamId string, user *model.User) *model.AppError {
var profiles map[string]*model.User
var profiles []*model.User
if result := <-Srv.Store.User().GetProfiles(teamId, 0, 100); result.Err != nil {
return model.NewLocAppError("AddDirectChannels", "api.user.add_direct_channels_and_forget.failed.error", map[string]interface{}{"UserId": user.Id, "TeamId": teamId, "Error": result.Err.Error()}, "")
} else {
profiles = result.Data.(map[string]*model.User)
profiles = result.Data.([]*model.User)
}
var preferences model.Preferences
for id := range profiles {
if id == user.Id {
for _, profile := range profiles {
if profile.Id == user.Id {
continue
}
profile := profiles[id]
preference := model.Preference{
UserId: user.Id,
Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,

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

@@ -25,7 +25,7 @@ import (
)
func SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User) ([]string, *model.AppError) {
pchan := Srv.Store.User().GetProfilesInChannel(channel.Id, -1, -1, true)
pchan := Srv.Store.User().GetAllProfilesInChannel(channel.Id, true)
fchan := Srv.Store.FileInfo().GetForPost(post.Id)
var profileMap map[string]*model.User

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

@@ -377,46 +377,162 @@ func GetUserForLogin(loginId string, onlyLdap bool) (*model.User, *model.AppErro
}
}
func GetUsers(offset int, limit int) (map[string]*model.User, *model.AppError) {
func GetUsers(offset int, limit int) ([]*model.User, *model.AppError) {
if result := <-Srv.Store.User().GetAllProfiles(offset, limit); result.Err != nil {
return nil, result.Err
} else {
return result.Data.(map[string]*model.User), nil
return result.Data.([]*model.User), nil
}
}
func GetUsersMap(page int, perPage int, asAdmin bool) (map[string]*model.User, *model.AppError) {
users, err := GetUsers(page*perPage, perPage)
if err != nil {
return nil, err
}
userMap := make(map[string]*model.User, len(users))
for _, user := range users {
SanitizeProfile(user, asAdmin)
userMap[user.Id] = user
}
return userMap, nil
}
func GetUsersPage(page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
users, err := GetUsers(page*perPage, perPage)
if err != nil {
return nil, err
}
for _, user := range users {
SanitizeProfile(user, asAdmin)
}
return users, nil
}
func GetUsersEtag() string {
return (<-Srv.Store.User().GetEtagForAllProfiles()).Data.(string)
}
func GetUsersInTeam(teamId string, offset int, limit int) (map[string]*model.User, *model.AppError) {
func GetUsersInTeam(teamId string, offset int, limit int) ([]*model.User, *model.AppError) {
if result := <-Srv.Store.User().GetProfiles(teamId, offset, limit); result.Err != nil {
return nil, result.Err
} else {
return result.Data.(map[string]*model.User), nil
return result.Data.([]*model.User), nil
}
}
func GetUsersInTeamMap(teamId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError) {
users, err := GetUsersInTeam(teamId, offset, limit)
if err != nil {
return nil, err
}
userMap := make(map[string]*model.User, len(users))
for _, user := range users {
SanitizeProfile(user, asAdmin)
userMap[user.Id] = user
}
return userMap, nil
}
func GetUsersInTeamPage(teamId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
users, err := GetUsersInTeam(teamId, page*perPage, perPage)
if err != nil {
return nil, err
}
for _, user := range users {
SanitizeProfile(user, asAdmin)
}
return users, nil
}
func GetUsersInTeamEtag(teamId string) string {
return (<-Srv.Store.User().GetEtagForProfiles(teamId)).Data.(string)
}
func GetUsersInChannel(channelId string, offset int, limit int) (map[string]*model.User, *model.AppError) {
if result := <-Srv.Store.User().GetProfilesInChannel(channelId, offset, limit, false); result.Err != nil {
func GetUsersInChannel(channelId string, offset int, limit int) ([]*model.User, *model.AppError) {
if result := <-Srv.Store.User().GetProfilesInChannel(channelId, offset, limit); result.Err != nil {
return nil, result.Err
} else {
return result.Data.(map[string]*model.User), nil
return result.Data.([]*model.User), nil
}
}
func GetUsersNotInChannel(teamId string, channelId string, offset int, limit int) (map[string]*model.User, *model.AppError) {
func GetUsersInChannelMap(channelId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError) {
users, err := GetUsersInChannel(channelId, offset, limit)
if err != nil {
return nil, err
}
userMap := make(map[string]*model.User, len(users))
for _, user := range users {
SanitizeProfile(user, asAdmin)
userMap[user.Id] = user
}
return userMap, nil
}
func GetUsersInChannelPage(channelId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
users, err := GetUsersInChannel(channelId, page*perPage, perPage)
if err != nil {
return nil, err
}
for _, user := range users {
SanitizeProfile(user, asAdmin)
}
return users, nil
}
func GetUsersNotInChannel(teamId string, channelId string, offset int, limit int) ([]*model.User, *model.AppError) {
if result := <-Srv.Store.User().GetProfilesNotInChannel(teamId, channelId, offset, limit); result.Err != nil {
return nil, result.Err
} else {
return result.Data.(map[string]*model.User), nil
return result.Data.([]*model.User), nil
}
}
func GetUsersNotInChannelMap(teamId string, channelId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError) {
users, err := GetUsersNotInChannel(teamId, channelId, offset, limit)
if err != nil {
return nil, err
}
userMap := make(map[string]*model.User, len(users))
for _, user := range users {
SanitizeProfile(user, asAdmin)
userMap[user.Id] = user
}
return userMap, nil
}
func GetUsersNotInChannelPage(teamId string, channelId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
users, err := GetUsersNotInChannel(teamId, channelId, page*perPage, perPage)
if err != nil {
return nil, err
}
for _, user := range users {
SanitizeProfile(user, asAdmin)
}
return users, nil
}
func GetUsersByIds(userIds []string, asAdmin bool) ([]*model.User, *model.AppError) {
if result := <-Srv.Store.User().GetProfileByIds(userIds, true); result.Err != nil {
return nil, result.Err

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

@@ -54,6 +54,7 @@ var PERMISSION_REMOVE_USER_FROM_TEAM *Permission
var PERMISSION_CREATE_TEAM *Permission
var PERMISSION_MANAGE_TEAM *Permission
var PERMISSION_IMPORT_TEAM *Permission
var PERMISSION_VIEW_TEAM *Permission
// General permission that encompases all system admin functions
// in the future this could be broken up to allow access to some
@@ -268,6 +269,11 @@ func InitalizePermissions() {
"authentication.permissions.import_team.name",
"authentication.permissions.import_team.description",
}
PERMISSION_VIEW_TEAM = &Permission{
"view_team",
"authentication.permissions.view_team.name",
"authentication.permissions.view_team.description",
}
}
func InitalizeRoles() {
@@ -314,6 +320,7 @@ func InitalizeRoles() {
[]string{
PERMISSION_LIST_TEAM_CHANNELS.Id,
PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
PERMISSION_VIEW_TEAM.Id,
},
}
BuiltInRoles[ROLE_TEAM_USER.Id] = ROLE_TEAM_USER

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

@@ -210,6 +210,50 @@ func (c *Client4) GetUser(userId, etag string) (*User, *Response) {
}
}
// GetUsers returns a page of users on the system. Page counting starts at 0.
func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Response) {
query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserListFromJson(r.Body), BuildResponse(r)
}
}
// GetUsersInTeam returns a page of users on a team. Page counting starts at 0.
func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
query := fmt.Sprintf("?in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserListFromJson(r.Body), BuildResponse(r)
}
}
// GetUsersInChannel returns a page of users on a team. Page counting starts at 0.
func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, etag string) ([]*User, *Response) {
query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v", channelId, page, perPage)
if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserListFromJson(r.Body), BuildResponse(r)
}
}
// GetUsersNotInChannel returns a page of users on a team. Page counting starts at 0.
func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPage int, etag string) ([]*User, *Response) {
query := fmt.Sprintf("?in_team=%v&not_in_channel=%v&page=%v&per_page=%v", teamId, channelId, page, perPage)
if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserListFromJson(r.Body), BuildResponse(r)
}
}
// GetUsersByIds returns a list of users based on the provided user ids.
func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) {
if r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds)); err != nil {

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

@@ -510,16 +510,13 @@ func (us SqlUserStore) GetAllProfiles(offset int, limit int) StoreChannel {
result.Err = model.NewLocAppError("SqlUserStore.GetAllProfiles", "store.sql_user.get_profiles.app_error", nil, err.Error())
} else {
userMap := make(map[string]*model.User)
for _, u := range users {
u.Password = ""
u.AuthData = new(string)
*u.AuthData = ""
userMap[u.Id] = u
}
result.Data = userMap
result.Data = users
}
storeChannel <- result
@@ -562,16 +559,13 @@ func (us SqlUserStore) GetProfiles(teamId string, offset int, limit int) StoreCh
result.Err = model.NewLocAppError("SqlUserStore.GetProfiles", "store.sql_user.get_profiles.app_error", nil, err.Error())
} else {
userMap := make(map[string]*model.User)
for _, u := range users {
u.Password = ""
u.AuthData = new(string)
*u.AuthData = ""
userMap[u.Id] = u
}
result.Data = userMap
result.Data = users
}
storeChannel <- result
@@ -598,7 +592,38 @@ func (us SqlUserStore) InvalidateProfilesInChannelCache(channelId string) {
profilesInChannelCache.Remove(channelId)
}
func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit int, allowFromCache bool) StoreChannel {
func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit int) StoreChannel {
storeChannel := make(StoreChannel)
go func() {
result := StoreResult{}
var users []*model.User
query := "SELECT Users.* FROM Users, ChannelMembers WHERE ChannelMembers.ChannelId = :ChannelId AND Users.Id = ChannelMembers.UserId AND Users.DeleteAt = 0 ORDER BY Users.Username ASC LIMIT :Limit OFFSET :Offset"
if _, err := us.GetReplica().Select(&users, query, map[string]interface{}{"ChannelId": channelId, "Offset": offset, "Limit": limit}); err != nil {
result.Err = model.NewLocAppError("SqlUserStore.GetProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error())
} else {
for _, u := range users {
u.Password = ""
u.AuthData = new(string)
*u.AuthData = ""
}
result.Data = users
}
storeChannel <- result
close(storeChannel)
}()
return storeChannel
}
func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) StoreChannel {
storeChannel := make(StoreChannel)
@@ -606,7 +631,7 @@ func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit
result := StoreResult{}
metrics := einterfaces.GetMetricsInterface()
if allowFromCache && offset == -1 && limit == -1 {
if allowFromCache {
if cacheItem, ok := profilesInChannelCache.Get(channelId); ok {
if metrics != nil {
metrics.IncrementMemCacheHitCounter("Profiles in Channel")
@@ -630,12 +655,8 @@ func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit
query := "SELECT Users.* FROM Users, ChannelMembers WHERE ChannelMembers.ChannelId = :ChannelId AND Users.Id = ChannelMembers.UserId AND Users.DeleteAt = 0"
if limit >= 0 && offset >= 0 {
query += " ORDER BY Users.Username ASC LIMIT :Limit OFFSET :Offset"
}
if _, err := us.GetReplica().Select(&users, query, map[string]interface{}{"ChannelId": channelId, "Offset": offset, "Limit": limit}); err != nil {
result.Err = model.NewLocAppError("SqlUserStore.GetProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error())
if _, err := us.GetReplica().Select(&users, query, map[string]interface{}{"ChannelId": channelId}); err != nil {
result.Err = model.NewLocAppError("SqlUserStore.GetAllProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error())
} else {
userMap := make(map[string]*model.User)
@@ -649,7 +670,7 @@ func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit
result.Data = userMap
if allowFromCache && offset == -1 && limit == -1 {
if allowFromCache {
profilesInChannelCache.AddWithExpiresInSecs(channelId, userMap, PROFILES_IN_CHANNEL_CACHE_SEC)
}
}
@@ -688,16 +709,13 @@ func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string,
result.Err = model.NewLocAppError("SqlUserStore.GetProfilesNotInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error())
} else {
userMap := make(map[string]*model.User)
for _, u := range users {
u.Password = ""
u.AuthData = new(string)
*u.AuthData = ""
userMap[u.Id] = u
}
result.Data = userMap
result.Data = users
}
storeChannel <- result

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

@@ -208,7 +208,7 @@ func TestUserStoreGetAllProfiles(t *testing.T) {
if r1 := <-store.User().GetAllProfiles(0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
users := r1.Data.(map[string]*model.User)
users := r1.Data.([]*model.User)
if len(users) < 2 {
t.Fatal("invalid returned users")
}
@@ -217,7 +217,7 @@ func TestUserStoreGetAllProfiles(t *testing.T) {
if r2 := <-store.User().GetAllProfiles(0, 1); r2.Err != nil {
t.Fatal(r2.Err)
} else {
users := r2.Data.(map[string]*model.User)
users := r2.Data.([]*model.User)
if len(users) != 1 {
t.Fatal("invalid returned users, limit did not work")
}
@@ -242,20 +242,27 @@ func TestUserStoreGetProfiles(t *testing.T) {
if r1 := <-store.User().GetProfiles(teamId, 0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
users := r1.Data.(map[string]*model.User)
users := r1.Data.([]*model.User)
if len(users) != 2 {
t.Fatal("invalid returned users")
}
if users[u1.Id].Id != u1.Id {
t.Fatal("invalid returned user")
found := false
for _, u := range users {
if u.Id == u1.Id {
found = true
}
}
if !found {
t.Fatal("missing user")
}
}
if r2 := <-store.User().GetProfiles("123", 0, 100); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 0 {
if len(r2.Data.([]*model.User)) != 0 {
t.Fatal("should have returned empty map")
}
}
@@ -310,7 +317,85 @@ func TestUserStoreGetProfilesInChannel(t *testing.T) {
Must(store.Channel().SaveMember(&m2))
Must(store.Channel().SaveMember(&m3))
if r1 := <-store.User().GetProfilesInChannel(c1.Id, -1, -1, false); r1.Err != nil {
if r1 := <-store.User().GetProfilesInChannel(c1.Id, 0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
users := r1.Data.([]*model.User)
if len(users) != 2 {
t.Fatal("invalid returned users")
}
found := false
for _, u := range users {
if u.Id == u1.Id {
found = true
}
}
if !found {
t.Fatal("missing user")
}
}
if r2 := <-store.User().GetProfilesInChannel(c2.Id, 0, 1); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.([]*model.User)) != 1 {
t.Fatal("should have returned only 1 user")
}
}
}
func TestUserStoreGetAllProfilesInChannel(t *testing.T) {
Setup()
teamId := model.NewId()
u1 := &model.User{}
u1.Email = model.NewId()
Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id}))
u2 := &model.User{}
u2.Email = model.NewId()
Must(store.User().Save(u2))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id}))
c1 := model.Channel{}
c1.TeamId = teamId
c1.DisplayName = "Profiles in channel"
c1.Name = "profiles-" + model.NewId()
c1.Type = model.CHANNEL_OPEN
c2 := model.Channel{}
c2.TeamId = teamId
c2.DisplayName = "Profiles in private"
c2.Name = "profiles-" + model.NewId()
c2.Type = model.CHANNEL_PRIVATE
Must(store.Channel().Save(&c1))
Must(store.Channel().Save(&c2))
m1 := model.ChannelMember{}
m1.ChannelId = c1.Id
m1.UserId = u1.Id
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
m2 := model.ChannelMember{}
m2.ChannelId = c1.Id
m2.UserId = u2.Id
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
m3 := model.ChannelMember{}
m3.ChannelId = c2.Id
m3.UserId = u1.Id
m3.NotifyProps = model.GetDefaultChannelNotifyProps()
Must(store.Channel().SaveMember(&m1))
Must(store.Channel().SaveMember(&m2))
Must(store.Channel().SaveMember(&m3))
if r1 := <-store.User().GetAllProfilesInChannel(c1.Id, false); r1.Err != nil {
t.Fatal(r1.Err)
} else {
users := r1.Data.(map[string]*model.User)
@@ -323,7 +408,7 @@ func TestUserStoreGetProfilesInChannel(t *testing.T) {
}
}
if r2 := <-store.User().GetProfilesInChannel(c2.Id, -1, -1, false); r2.Err != nil {
if r2 := <-store.User().GetAllProfilesInChannel(c2.Id, false); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 1 {
@@ -331,7 +416,7 @@ func TestUserStoreGetProfilesInChannel(t *testing.T) {
}
}
if r2 := <-store.User().GetProfilesInChannel(c2.Id, -1, -1, true); r2.Err != nil {
if r2 := <-store.User().GetAllProfilesInChannel(c2.Id, true); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 1 {
@@ -339,7 +424,7 @@ func TestUserStoreGetProfilesInChannel(t *testing.T) {
}
}
if r2 := <-store.User().GetProfilesInChannel(c2.Id, -1, -1, true); r2.Err != nil {
if r2 := <-store.User().GetAllProfilesInChannel(c2.Id, true); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 1 {
@@ -383,20 +468,27 @@ func TestUserStoreGetProfilesNotInChannel(t *testing.T) {
if r1 := <-store.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
users := r1.Data.(map[string]*model.User)
users := r1.Data.([]*model.User)
if len(users) != 2 {
t.Fatal("invalid returned users")
}
if users[u1.Id].Id != u1.Id {
t.Fatal("invalid returned user")
found := false
for _, u := range users {
if u.Id == u1.Id {
found = true
}
}
if !found {
t.Fatal("missing user")
}
}
if r2 := <-store.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 2 {
if len(r2.Data.([]*model.User)) != 2 {
t.Fatal("invalid returned users")
}
}
@@ -423,7 +515,7 @@ func TestUserStoreGetProfilesNotInChannel(t *testing.T) {
if r1 := <-store.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
users := r1.Data.(map[string]*model.User)
users := r1.Data.([]*model.User)
if len(users) != 0 {
t.Fatal("invalid returned users")
}
@@ -432,7 +524,7 @@ func TestUserStoreGetProfilesNotInChannel(t *testing.T) {
if r2 := <-store.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 1 {
if len(r2.Data.([]*model.User)) != 1 {
t.Fatal("should have had 1 user not in channel")
}
}
@@ -576,8 +668,8 @@ func TestUserStoreGetProfilesByIds(t *testing.T) {
if r2 := <-store.User().GetProfiles("123", 0, 100); r2.Err != nil {
t.Fatal(r2.Err)
} else {
if len(r2.Data.(map[string]*model.User)) != 0 {
t.Fatal("should have returned empty map")
if len(r2.Data.([]*model.User)) != 0 {
t.Fatal("should have returned empty array")
}
}
}

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

@@ -162,7 +162,8 @@ type UserStore interface {
GetAll() StoreChannel
InvalidateProfilesInChannelCacheByUser(userId string)
InvalidateProfilesInChannelCache(channelId string)
GetProfilesInChannel(channelId string, offset int, limit int, allowFromCache bool) StoreChannel
GetProfilesInChannel(channelId string, offset int, limit int) StoreChannel
GetAllProfilesInChannel(channelId string, allowFromCache bool) StoreChannel
GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int) StoreChannel
GetProfilesByUsernames(usernames []string, teamId string) StoreChannel
GetAllProfiles(offset int, limit int) StoreChannel