diff options
-rw-r--r-- | api4/apitestlib.go | 4 | ||||
-rw-r--r-- | api4/channel.go | 46 | ||||
-rw-r--r-- | api4/channel_test.go | 88 | ||||
-rw-r--r-- | app/channel.go | 25 | ||||
-rw-r--r-- | model/client4.go | 11 |
5 files changed, 172 insertions, 2 deletions
diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 64d3f22b2..b3007ebfe 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -498,14 +498,14 @@ func CheckErrorMessage(t *testing.T, resp *model.Response, errorId string) { func CheckInternalErrorStatus(t *testing.T, resp *model.Response) { if resp.Error == nil { debug.PrintStack() - t.Fatal("should have errored with status:" + strconv.Itoa(http.StatusNotImplemented)) + t.Fatal("should have errored with status:" + strconv.Itoa(http.StatusInternalServerError)) return } if resp.StatusCode != http.StatusInternalServerError { debug.PrintStack() t.Log("actual: " + strconv.Itoa(resp.StatusCode)) - t.Log("expected: " + strconv.Itoa(http.StatusNotImplemented)) + t.Log("expected: " + strconv.Itoa(http.StatusInternalServerError)) t.Fatal("wrong status code") } } diff --git a/api4/channel.go b/api4/channel.go index bd1710975..61d9e6f53 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -33,6 +33,7 @@ func InitChannel() { BaseRoutes.ChannelMembers.Handle("", ApiSessionRequired(getChannelMembers)).Methods("GET") BaseRoutes.ChannelMembers.Handle("/ids", ApiSessionRequired(getChannelMembersByIds)).Methods("POST") + BaseRoutes.ChannelMembers.Handle("", ApiSessionRequired(addChannelMember)).Methods("POST") BaseRoutes.ChannelMembersForUser.Handle("", ApiSessionRequired(getChannelMembersForUser)).Methods("GET") BaseRoutes.ChannelMember.Handle("", ApiSessionRequired(getChannelMember)).Methods("GET") BaseRoutes.ChannelMember.Handle("", ApiSessionRequired(removeChannelMember)).Methods("DELETE") @@ -498,6 +499,51 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request ReturnStatusOK(w) } +func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireChannelId() + if c.Err != nil { + return + } + + member := model.ChannelMemberFromJson(r.Body) + if member == nil { + c.SetInvalidParam("channel_member") + return + } + + if len(member.UserId) != 26 { + c.SetInvalidParam("user_id") + return + } + + member.ChannelId = c.Params.ChannelId + + var channel *model.Channel + var err *model.AppError + if channel, err = app.GetChannel(member.ChannelId); err != nil { + c.Err = err + return + } + + if channel.Type == model.CHANNEL_OPEN && !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) { + c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) + return + } + + if channel.Type == model.CHANNEL_PRIVATE && !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) { + c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) + return + } + + if cm, err := app.AddChannelMember(member.UserId, channel, c.Session.UserId); err != nil { + c.Err = err + return + } else { + c.LogAudit("name=" + channel.Name + " user_id=" + cm.UserId) + w.Write([]byte(cm.ToJson())) + } +} + func removeChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireChannelId().RequireUserId() if c.Err != nil { diff --git a/api4/channel_test.go b/api4/channel_test.go index 6d5b5cef3..fd72a8ba7 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -1118,6 +1118,94 @@ func TestUpdateChannelRoles(t *testing.T) { CheckForbiddenStatus(t, resp) } +func TestAddChannelMember(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + user := th.BasicUser + user2 := th.BasicUser2 + publicChannel := th.CreatePublicChannel() + privateChannel := th.CreatePrivateChannel() + + cm, resp := Client.AddChannelMember(publicChannel.Id, user2.Id) + CheckNoError(t, resp) + + if cm.ChannelId != publicChannel.Id { + t.Fatal("should have returned exact channel") + } + + if cm.UserId != user2.Id { + t.Fatal("should have returned exact user added to public channel") + } + + cm, resp = Client.AddChannelMember(privateChannel.Id, user2.Id) + CheckNoError(t, resp) + + if cm.ChannelId != privateChannel.Id { + t.Fatal("should have returned exact channel") + } + + if cm.UserId != user2.Id { + t.Fatal("should have returned exact user added to private channel") + } + + cm, resp = Client.AddChannelMember(publicChannel.Id, "junk") + CheckBadRequestStatus(t, resp) + + if cm != nil { + t.Fatal("should return nothing") + } + + _, resp = Client.AddChannelMember(publicChannel.Id, GenerateTestId()) + CheckNotFoundStatus(t, resp) + + _, resp = Client.AddChannelMember("junk", user2.Id) + CheckBadRequestStatus(t, resp) + + _, resp = Client.AddChannelMember(GenerateTestId(), user2.Id) + CheckNotFoundStatus(t, resp) + + otherUser := th.CreateUser() + otherChannel := th.CreatePublicChannel() + Client.Logout() + Client.Login(user2.Id, user2.Password) + + _, resp = Client.AddChannelMember(publicChannel.Id, otherUser.Id) + CheckUnauthorizedStatus(t, resp) + + _, resp = Client.AddChannelMember(privateChannel.Id, otherUser.Id) + CheckUnauthorizedStatus(t, resp) + + _, resp = Client.AddChannelMember(otherChannel.Id, otherUser.Id) + CheckUnauthorizedStatus(t, resp) + + Client.Logout() + Client.Login(user.Id, user.Password) + + // should fail adding user who is not a member of the team + _, resp = Client.AddChannelMember(otherChannel.Id, otherUser.Id) + CheckUnauthorizedStatus(t, resp) + + Client.DeleteChannel(otherChannel.Id) + + // should fail adding user to a deleted channel + _, resp = Client.AddChannelMember(otherChannel.Id, user2.Id) + CheckUnauthorizedStatus(t, resp) + + Client.Logout() + _, resp = Client.AddChannelMember(publicChannel.Id, user2.Id) + CheckUnauthorizedStatus(t, resp) + + _, resp = Client.AddChannelMember(privateChannel.Id, user2.Id) + CheckUnauthorizedStatus(t, resp) + + _, resp = th.SystemAdminClient.AddChannelMember(publicChannel.Id, user2.Id) + CheckNoError(t, resp) + + _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user2.Id) + CheckNoError(t, resp) +} + func TestRemoveChannelMember(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer TearDown() diff --git a/app/channel.go b/app/channel.go index af7596ae1..a55805303 100644 --- a/app/channel.go +++ b/app/channel.go @@ -446,6 +446,31 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM return newMember, nil } +func AddChannelMember(userId string, channel *model.Channel, userRequestorId string) (*model.ChannelMember, *model.AppError) { + var user *model.User + var err *model.AppError + + if user, err = GetUser(userId); err != nil { + return nil, err + } + + var userRequestor *model.User + if userRequestor, err = GetUser(userRequestorId); err != nil { + return nil, err + } + + cm, err := AddUserToChannel(user, channel) + if err != nil { + return nil, err + } + + go PostAddToChannelMessage(userRequestor, user, channel) + + UpdateChannelLastViewedAt([]string{channel.Id}, userRequestor.Id) + + return cm, nil +} + func AddDirectChannels(teamId string, user *model.User) *model.AppError { var profiles []*model.User if result := <-Srv.Store.User().GetProfiles(teamId, 0, 100); result.Err != nil { diff --git a/model/client4.go b/model/client4.go index 307d52c55..bcefe90a4 100644 --- a/model/client4.go +++ b/model/client4.go @@ -968,6 +968,17 @@ func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (bool, *Re } } +// AddChannelMember adds user to channel and return a channel member. +func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *Response) { + requestBody := map[string]string{"user_id": userId} + if r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody)); err != nil { + return nil, &Response{StatusCode: r.StatusCode, Error: err} + } else { + defer closeBody(r) + return ChannelMemberFromJson(r.Body), BuildResponse(r) + } +} + // RemoveUserFromChannel will delete the channel member object for a user, effectively removing the user from a channel. func (c *Client4) RemoveUserFromChannel(channelId, userId string) (bool, *Response) { if r, err := c.DoApiDelete(c.GetChannelMemberRoute(channelId, userId)); err != nil { |