Implement GET channels endpoints for APIv4 (#5363)

* implement get channels endpoints and updated drivers and unittests

* removed channel deletion on tear down, removed manage permission on get channels endpoints, and updated utils to add constant channel length

* added constants for user, team and channel length, updated context to use the model functions

* make sure team name length should be less than the minimum length and revert underscore to team name validity

* changed post test condition from notfound to unauthorized
Этот коммит содержится в:
Ruzette Tanyag
2017-02-14 10:28:08 -05:00
коммит произвёл Harrison Healey
родитель 9dabd10da9
Коммит 28aa7cdbf2
14 изменённых файлов: 293 добавлений и 42 удалений

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

@@ -32,13 +32,14 @@ type Routes struct {
TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members' TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members'
TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members/{user_id:[A-Za-z0-9_-]+}' TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members/{user_id:[A-Za-z0-9_-]+}'
Channels *mux.Router // 'api/v4/channels' Channels *mux.Router // 'api/v4/channels'
Channel *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}' Channel *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}'
ChannelByName *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/channels/name/{channel_name:[A-Za-z0-9_-]+}' ChannelByName *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/channels/name/{channel_name:[A-Za-z0-9_-]+}'
ChannelsForTeam *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/channels' ChannelByNameForTeamName *mux.Router // 'api/v4/teams/name/{team_name:[A-Za-z0-9_-]+}/channels/name/{channel_name:[A-Za-z0-9_-]+}'
ChannelMembers *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/members' ChannelsForTeam *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/channels'
ChannelMember *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/members/{user_id:[A-Za-z0-9]+}' ChannelMembers *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/members'
ChannelMembersForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}/channels/members' ChannelMember *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/members/{user_id:[A-Za-z0-9]+}'
ChannelMembersForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}/channels/members'
Posts *mux.Router // 'api/v4/posts' Posts *mux.Router // 'api/v4/posts'
Post *mux.Router // 'api/v4/posts/{post_id:[A-Za-z0-9]+}' Post *mux.Router // 'api/v4/posts/{post_id:[A-Za-z0-9]+}'
@@ -102,7 +103,8 @@ func InitApi(full bool) {
BaseRoutes.Channels = BaseRoutes.ApiRoot.PathPrefix("/channels").Subrouter() BaseRoutes.Channels = BaseRoutes.ApiRoot.PathPrefix("/channels").Subrouter()
BaseRoutes.Channel = BaseRoutes.Channels.PathPrefix("/{channel_id:[A-Za-z0-9]+}").Subrouter() BaseRoutes.Channel = BaseRoutes.Channels.PathPrefix("/{channel_id:[A-Za-z0-9]+}").Subrouter()
BaseRoutes.ChannelByName = BaseRoutes.Team.PathPrefix("/name/{channel_name:[A-Za-z0-9_-]+}").Subrouter() BaseRoutes.ChannelByName = BaseRoutes.Team.PathPrefix("/channels/name/{channel_name:[A-Za-z0-9_-]+}").Subrouter()
BaseRoutes.ChannelByNameForTeamName = BaseRoutes.TeamByName.PathPrefix("/channels/name/{channel_name:[A-Za-z0-9_-]+}").Subrouter()
BaseRoutes.ChannelsForTeam = BaseRoutes.Team.PathPrefix("/channels").Subrouter() BaseRoutes.ChannelsForTeam = BaseRoutes.Team.PathPrefix("/channels").Subrouter()
BaseRoutes.ChannelMembers = BaseRoutes.Channel.PathPrefix("/members").Subrouter() BaseRoutes.ChannelMembers = BaseRoutes.Channel.PathPrefix("/members").Subrouter()
BaseRoutes.ChannelMember = BaseRoutes.ChannelMembers.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter() BaseRoutes.ChannelMember = BaseRoutes.ChannelMembers.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()

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

@@ -278,11 +278,11 @@ func GenerateTestUsername() string {
} }
func GenerateTestTeamName() string { func GenerateTestTeamName() string {
return "faketeam" + model.NewId() return "faketeam" + model.NewRandomString(6)
} }
func GenerateTestChannelName() string { func GenerateTestChannelName() string {
return "fakechannel" + model.NewId() return "fakechannel" + model.NewRandomString(10)
} }
func VerifyUserEmail(userId string) { func VerifyUserEmail(userId string) {

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

@@ -18,6 +18,10 @@ func InitChannel() {
BaseRoutes.Channels.Handle("", ApiSessionRequired(createChannel)).Methods("POST") BaseRoutes.Channels.Handle("", ApiSessionRequired(createChannel)).Methods("POST")
BaseRoutes.Channels.Handle("/direct", ApiSessionRequired(createDirectChannel)).Methods("POST") BaseRoutes.Channels.Handle("/direct", ApiSessionRequired(createDirectChannel)).Methods("POST")
BaseRoutes.Channel.Handle("", ApiSessionRequired(getChannel)).Methods("GET")
BaseRoutes.ChannelByName.Handle("", ApiSessionRequired(getChannelByName)).Methods("GET")
BaseRoutes.ChannelByNameForTeamName.Handle("", ApiSessionRequired(getChannelByNameForTeamName)).Methods("GET")
BaseRoutes.ChannelMembers.Handle("", ApiSessionRequired(getChannelMembers)).Methods("GET") BaseRoutes.ChannelMembers.Handle("", ApiSessionRequired(getChannelMembers)).Methods("GET")
BaseRoutes.ChannelMembersForUser.Handle("", ApiSessionRequired(getChannelMembersForUser)).Methods("GET") BaseRoutes.ChannelMembersForUser.Handle("", ApiSessionRequired(getChannelMembersForUser)).Methods("GET")
BaseRoutes.ChannelMember.Handle("", ApiSessionRequired(getChannelMember)).Methods("GET") BaseRoutes.ChannelMember.Handle("", ApiSessionRequired(getChannelMember)).Methods("GET")
@@ -88,6 +92,72 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireChannelId()
if c.Err != nil {
return
}
if !app.SessionHasPermissionToChannel(c.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
return
}
if channel, err := app.GetChannel(c.Params.ChannelId); err != nil {
c.Err = err
return
} else {
w.Write([]byte(channel.ToJson()))
return
}
}
func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId().RequireChannelName()
if c.Err != nil {
return
}
var channel *model.Channel
var err *model.AppError
if channel, err = app.GetChannelByName(c.Params.ChannelName, c.Params.TeamId); err != nil {
c.Err = err
return
}
if !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
return
}
w.Write([]byte(channel.ToJson()))
return
}
func getChannelByNameForTeamName(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamName().RequireChannelName()
if c.Err != nil {
return
}
var channel *model.Channel
var err *model.AppError
if channel, err = app.GetChannelByNameForTeamName(c.Params.ChannelName, c.Params.TeamName); err != nil {
c.Err = err
return
}
if !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
return
}
w.Write([]byte(channel.ToJson()))
return
}
func getChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) { func getChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireChannelId() c.RequireChannelId()
if c.Err != nil { if c.Err != nil {

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

@@ -221,6 +221,84 @@ func TestCreateDirectChannel(t *testing.T) {
CheckNoError(t, resp) CheckNoError(t, resp)
} }
func TestGetChannel(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
_, resp := Client.GetChannel(th.BasicChannel.Id, "")
CheckNoError(t, resp)
_, resp = Client.GetChannel(model.NewId(), "")
CheckForbiddenStatus(t, resp)
Client.Logout()
_, resp = Client.GetChannel(th.BasicChannel.Id, "")
CheckUnauthorizedStatus(t, resp)
user := th.CreateUser()
Client.Login(user.Email, user.Password)
_, resp = Client.GetChannel(th.BasicChannel.Id, "")
CheckForbiddenStatus(t, resp)
_, resp = th.SystemAdminClient.GetChannel(th.BasicChannel.Id, "")
CheckNoError(t, resp)
_, resp = th.SystemAdminClient.GetChannel(th.BasicUser.Id, "")
CheckNotFoundStatus(t, resp)
}
func TestGetChannelByName(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
_, resp := Client.GetChannelByName(th.BasicChannel.Name, th.BasicTeam.Id, "")
CheckNoError(t, resp)
_, resp = Client.GetChannelByName(GenerateTestChannelName(), th.BasicTeam.Id, "")
CheckNotFoundStatus(t, resp)
Client.Logout()
_, resp = Client.GetChannelByName(th.BasicChannel.Name, th.BasicTeam.Id, "")
CheckUnauthorizedStatus(t, resp)
user := th.CreateUser()
Client.Login(user.Email, user.Password)
_, resp = Client.GetChannelByName(th.BasicChannel.Name, th.BasicTeam.Id, "")
CheckForbiddenStatus(t, resp)
_, resp = th.SystemAdminClient.GetChannelByName(th.BasicChannel.Name, th.BasicTeam.Id, "")
CheckNoError(t, resp)
}
func TestGetChannelByNameForTeamName(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
_, resp := th.SystemAdminClient.GetChannelByNameForTeamName(th.BasicChannel.Name, th.BasicTeam.Name, "")
CheckNoError(t, resp)
_, resp = Client.GetChannelByNameForTeamName(th.BasicChannel.Name, th.BasicTeam.Name, "")
CheckNoError(t, resp)
_, resp = Client.GetChannelByNameForTeamName(th.BasicChannel.Name, model.NewRandomString(15), "")
CheckNotFoundStatus(t, resp)
_, resp = Client.GetChannelByNameForTeamName(GenerateTestChannelName(), th.BasicTeam.Name, "")
CheckNotFoundStatus(t, resp)
Client.Logout()
_, resp = Client.GetChannelByNameForTeamName(th.BasicChannel.Name, th.BasicTeam.Name, "")
CheckUnauthorizedStatus(t, resp)
user := th.CreateUser()
Client.Login(user.Email, user.Password)
_, resp = Client.GetChannelByNameForTeamName(th.BasicChannel.Name, th.BasicTeam.Name, "")
CheckForbiddenStatus(t, resp)
}
func TestGetChannelMembers(t *testing.T) { func TestGetChannelMembers(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin() th := Setup().InitBasic().InitSystemAdmin()
defer TearDown() defer TearDown()
@@ -255,7 +333,7 @@ func TestGetChannelMembers(t *testing.T) {
} }
_, resp = Client.GetChannelMembers("", 0, 60, "") _, resp = Client.GetChannelMembers("", 0, 60, "")
CheckNotFoundStatus(t, resp) CheckUnauthorizedStatus(t, resp)
_, resp = Client.GetChannelMembers("junk", 0, 60, "") _, resp = Client.GetChannelMembers("junk", 0, 60, "")
CheckBadRequestStatus(t, resp) CheckBadRequestStatus(t, resp)

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

@@ -364,12 +364,8 @@ func (c *Context) RequireUsername() *Context {
return c return c
} }
if len(c.Params.Username) < 3 { if !model.IsValidUsername(c.Params.Username) {
c.SetInvalidUrlParam("username") c.SetInvalidParam("username")
}
if len(c.Params.Username) > 22 {
c.SetInvalidUrlParam("username")
} }
return c return c
@@ -386,16 +382,40 @@ func (c *Context) RequirePostId() *Context {
return c return c
} }
func (c *Context) RequireTeamName() *Context {
if c.Err != nil {
return c
}
if !model.IsValidTeamName(c.Params.TeamName){
c.SetInvalidUrlParam("team_name")
}
return c
}
func (c *Context) RequireChannelName() *Context {
if c.Err != nil {
return c
}
if !model.IsValidChannelIdentifier(c.Params.ChannelName) {
c.SetInvalidUrlParam("channel_name")
}
return c
}
func (c *Context) RequireEmail() *Context { func (c *Context) RequireEmail() *Context {
if c.Err != nil { if c.Err != nil {
return c return c
} }
pos := strings.Index(c.Params.Email, "@") if !model.IsValidEmail(c.Params.Email) {
if pos < 0 {
c.SetInvalidUrlParam("email") c.SetInvalidUrlParam("email")
} }
return c return c
} }

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

@@ -17,18 +17,20 @@ const (
) )
type ApiParams struct { type ApiParams struct {
UserId string UserId string
TeamId string TeamId string
ChannelId string ChannelId string
PostId string PostId string
FileId string FileId string
CommandId string CommandId string
HookId string HookId string
EmojiId string EmojiId string
Email string Email string
Username string Username string
Page int TeamName string
PerPage int ChannelName string
Page int
PerPage int
} }
func ApiParamsFromRequest(r *http.Request) *ApiParams { func ApiParamsFromRequest(r *http.Request) *ApiParams {
@@ -76,6 +78,14 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams {
params.Username = val params.Username = val
} }
if val, ok := props["team_name"]; ok {
params.TeamName = val
}
if val, ok := props["channel_name"]; ok {
params.ChannelName = val
}
if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil { if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil {
params.Page = PAGE_DEFAULT params.Page = PAGE_DEFAULT
} else { } else {

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

@@ -159,7 +159,7 @@ func TestGetPostsForChannel(t *testing.T) {
} }
_, resp = Client.GetPostsForChannel("", 0, 60, "") _, resp = Client.GetPostsForChannel("", 0, 60, "")
CheckNotFoundStatus(t, resp) CheckUnauthorizedStatus(t, resp)
_, resp = Client.GetPostsForChannel("junk", 0, 60, "") _, resp = Client.GetPostsForChannel("junk", 0, 60, "")
CheckBadRequestStatus(t, resp) CheckBadRequestStatus(t, resp)

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

@@ -154,7 +154,7 @@ func TestGetUserByUsername(t *testing.T) {
_, resp = Client.GetUserByUsername(GenerateTestUsername(), "") _, resp = Client.GetUserByUsername(GenerateTestUsername(), "")
CheckNotFoundStatus(t, resp) CheckNotFoundStatus(t, resp)
_, resp = Client.GetUserByUsername(model.NewRandomString(25), "") _, resp = Client.GetUserByUsername(model.NewRandomString(1), "")
CheckBadRequestStatus(t, resp) CheckBadRequestStatus(t, resp)
// Check against privacy config settings // Check against privacy config settings

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

@@ -543,7 +543,11 @@ func PostUpdateChannelDisplayNameMessage(userId string, channelId string, teamId
} }
func GetChannel(channelId string) (*model.Channel, *model.AppError) { func GetChannel(channelId string) (*model.Channel, *model.AppError) {
if result := <-Srv.Store.Channel().Get(channelId, true); result.Err != nil { if result := <-Srv.Store.Channel().Get(channelId, true); result.Err != nil && result.Err.Id == "store.sql_channel.get.existing.app_error" {
result.Err.StatusCode = http.StatusNotFound
return nil, result.Err
} else if result.Err != nil {
result.Err.StatusCode = http.StatusBadRequest
return nil, result.Err return nil, result.Err
} else { } else {
return result.Data.(*model.Channel), nil return result.Data.(*model.Channel), nil
@@ -551,7 +555,32 @@ func GetChannel(channelId string) (*model.Channel, *model.AppError) {
} }
func GetChannelByName(channelName, teamId string) (*model.Channel, *model.AppError) { func GetChannelByName(channelName, teamId string) (*model.Channel, *model.AppError) {
if result := <-Srv.Store.Channel().GetByName(teamId, channelName, true); result.Err != nil { if result := <-Srv.Store.Channel().GetByName(teamId, channelName, true); result.Err != nil && result.Err.Id == "store.sql_channel.get_by_name.missing.app_error" {
result.Err.StatusCode = http.StatusNotFound
return nil, result.Err
} else if result.Err != nil {
result.Err.StatusCode = http.StatusBadRequest
return nil, result.Err
} else {
return result.Data.(*model.Channel), nil
}
}
func GetChannelByNameForTeamName(channelName, teamName string) (*model.Channel, *model.AppError) {
var team *model.Team
if result := <-Srv.Store.Team().GetByName(teamName); result.Err != nil {
result.Err.StatusCode = http.StatusNotFound
return nil, result.Err
} else {
team = result.Data.(*model.Team)
}
if result := <-Srv.Store.Channel().GetByName(team.Id, channelName, true); result.Err != nil && result.Err.Id == "store.sql_channel.get_by_name.missing.app_error" {
result.Err.StatusCode = http.StatusNotFound
return nil, result.Err
} else if result.Err != nil {
result.Err.StatusCode = http.StatusBadRequest
return nil, result.Err return nil, result.Err
} else { } else {
return result.Data.(*model.Channel), nil return result.Data.(*model.Channel), nil

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

@@ -15,6 +15,7 @@ const (
CHANNEL_DIRECT = "D" CHANNEL_DIRECT = "D"
DEFAULT_CHANNEL = "town-square" DEFAULT_CHANNEL = "town-square"
CHANNEL_DISPLAY_NAME_MAX_RUNES = 64 CHANNEL_DISPLAY_NAME_MAX_RUNES = 64
CHANNEL_NAME_MIN_LENGTH = 3
CHANNEL_NAME_MAX_LENGTH = 64 CHANNEL_NAME_MAX_LENGTH = 64
CHANNEL_HEADER_MAX_RUNES = 1024 CHANNEL_HEADER_MAX_RUNES = 1024
CHANNEL_PURPOSE_MAX_RUNES = 250 CHANNEL_PURPOSE_MAX_RUNES = 250
@@ -83,10 +84,6 @@ func (o *Channel) IsValid() *AppError {
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.display_name.app_error", nil, "id="+o.Id) return NewLocAppError("Channel.IsValid", "model.channel.is_valid.display_name.app_error", nil, "id="+o.Id)
} }
if len(o.Name) > CHANNEL_NAME_MAX_LENGTH {
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.name.app_error", nil, "id="+o.Id)
}
if !IsValidChannelIdentifier(o.Name) { if !IsValidChannelIdentifier(o.Name) {
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.2_or_more.app_error", nil, "id="+o.Id) return NewLocAppError("Channel.IsValid", "model.channel.is_valid.2_or_more.app_error", nil, "id="+o.Id)
} }

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

@@ -72,6 +72,10 @@ func (c *Client4) GetTeamRoute(teamId string) string {
return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId) return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId)
} }
func (c *Client4) GetTeamByNameRoute(teamName string) string {
return fmt.Sprintf(c.GetTeamsRoute()+"/name/%v", teamName)
}
func (c *Client4) GetTeamMemberRoute(teamId, userId string) string { func (c *Client4) GetTeamMemberRoute(teamId, userId string) string {
return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId) return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId)
} }
@@ -84,6 +88,14 @@ func (c *Client4) GetChannelRoute(channelId string) string {
return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId) return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId)
} }
func (c *Client4) GetChannelByNameRoute(channelName, teamId string) string {
return fmt.Sprintf(c.GetTeamRoute(teamId)+"/channels/name/%v", channelName)
}
func (c *Client4) GetChannelByNameForTeamNameRoute(channelName, teamName string) string {
return fmt.Sprintf(c.GetTeamByNameRoute(teamName)+"/channels/name/%v", channelName)
}
func (c *Client4) GetChannelMembersRoute(channelId string) string { func (c *Client4) GetChannelMembersRoute(channelId string) string {
return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members") return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members")
} }
@@ -444,6 +456,36 @@ func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Respo
} }
} }
// GetChannel returns a channel based on the provided channel id string.
func (c *Client4) GetChannel(channelId, etag string) (*User, *Response) {
if r, err := c.DoApiGet(c.GetChannelRoute(channelId), etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserFromJson(r.Body), BuildResponse(r)
}
}
// GetChannelByName returns a channel based on the provided channel name and team id strings.
func (c *Client4) GetChannelByName(channelName, teamId string, etag string) (*User, *Response) {
if r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId), etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserFromJson(r.Body), BuildResponse(r)
}
}
// GetChannelByNameForTeamName returns a channel based on the provided channel name and team name strings.
func (c *Client4) GetChannelByNameForTeamName(channelName, teamName string, etag string) (*User, *Response) {
if r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName), etag); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return UserFromJson(r.Body), BuildResponse(r)
}
}
// GetChannelMembers gets a page of channel members. // GetChannelMembers gets a page of channel members.
func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag string) (*ChannelMembers, *Response) { func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag string) (*ChannelMembers, *Response) {
query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)

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

@@ -22,6 +22,7 @@ const (
TEAM_DISPLAY_NAME_MAX_RUNES = 64 TEAM_DISPLAY_NAME_MAX_RUNES = 64
TEAM_EMAIL_MAX_LENGTH = 128 TEAM_EMAIL_MAX_LENGTH = 128
TEAM_NAME_MAX_LENGTH = 64 TEAM_NAME_MAX_LENGTH = 64
TEAM_NAME_MIN_LENGTH = 2
) )
type Team struct { type Team struct {
@@ -228,7 +229,7 @@ func IsValidTeamName(s string) bool {
return false return false
} }
if len(s) <= 1 { if len(s) < TEAM_NAME_MIN_LENGTH {
return false return false
} }

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

@@ -29,6 +29,8 @@ const (
USER_FIRST_NAME_MAX_RUNES = 64 USER_FIRST_NAME_MAX_RUNES = 64
USER_LAST_NAME_MAX_RUNES = 64 USER_LAST_NAME_MAX_RUNES = 64
USER_AUTH_DATA_MAX_LENGTH = 128 USER_AUTH_DATA_MAX_LENGTH = 128
USER_NAME_MAX_LENGTH = 64
USER_NAME_MIN_LENGTH = 3
) )
type User struct { type User struct {
@@ -487,7 +489,7 @@ var restrictedUsernames = []string{
} }
func IsValidUsername(s string) bool { func IsValidUsername(s string) bool {
if len(s) == 0 || len(s) > 64 { if len(s) < USER_NAME_MIN_LENGTH || len(s) > USER_NAME_MAX_LENGTH {
return false return false
} }

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

@@ -280,7 +280,7 @@ func IsValidChannelIdentifier(s string) bool {
return false return false
} }
if len(s) < 2 { if len(s) < CHANNEL_NAME_MIN_LENGTH {
return false return false
} }