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'
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'
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_-]+}'
ChannelsForTeam *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/channels'
ChannelMembers *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/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'
Channels *mux.Router // 'api/v4/channels'
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_-]+}'
ChannelByNameForTeamName *mux.Router // 'api/v4/teams/name/{team_name:[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'
ChannelMembers *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/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'
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.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.ChannelMembers = BaseRoutes.Channel.PathPrefix("/members").Subrouter()
BaseRoutes.ChannelMember = BaseRoutes.ChannelMembers.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()

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

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

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

@@ -18,6 +18,10 @@ func InitChannel() {
BaseRoutes.Channels.Handle("", ApiSessionRequired(createChannel)).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.ChannelMembersForUser.Handle("", ApiSessionRequired(getChannelMembersForUser)).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) {
c.RequireChannelId()
if c.Err != nil {

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

@@ -221,6 +221,84 @@ func TestCreateDirectChannel(t *testing.T) {
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) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
@@ -255,7 +333,7 @@ func TestGetChannelMembers(t *testing.T) {
}
_, resp = Client.GetChannelMembers("", 0, 60, "")
CheckNotFoundStatus(t, resp)
CheckUnauthorizedStatus(t, resp)
_, resp = Client.GetChannelMembers("junk", 0, 60, "")
CheckBadRequestStatus(t, resp)

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

@@ -364,12 +364,8 @@ func (c *Context) RequireUsername() *Context {
return c
}
if len(c.Params.Username) < 3 {
c.SetInvalidUrlParam("username")
}
if len(c.Params.Username) > 22 {
c.SetInvalidUrlParam("username")
if !model.IsValidUsername(c.Params.Username) {
c.SetInvalidParam("username")
}
return c
@@ -386,16 +382,40 @@ func (c *Context) RequirePostId() *Context {
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 {
if c.Err != nil {
return c
}
pos := strings.Index(c.Params.Email, "@")
if pos < 0 {
if !model.IsValidEmail(c.Params.Email) {
c.SetInvalidUrlParam("email")
}
return c
}

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

@@ -17,18 +17,20 @@ const (
)
type ApiParams struct {
UserId string
TeamId string
ChannelId string
PostId string
FileId string
CommandId string
HookId string
EmojiId string
Email string
Username string
Page int
PerPage int
UserId string
TeamId string
ChannelId string
PostId string
FileId string
CommandId string
HookId string
EmojiId string
Email string
Username string
TeamName string
ChannelName string
Page int
PerPage int
}
func ApiParamsFromRequest(r *http.Request) *ApiParams {
@@ -76,6 +78,14 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams {
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 {
params.Page = PAGE_DEFAULT
} else {

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

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

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

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