MM-8678: add CUD support for channel members via plugins (#8565)

* add CUD support for channel members via plugins

This effectively exposes AddChannelMember, UpdateChannelMemberRoles,
UpdateChannelMemberNotifyProps and LeaveChannel via the plugin API.

It also modifies the semantics of AddChannelMember to explicitly allow
for an empty user requestor, left as such for now via the plugin API.

* change the signature of AddChannelMember to accept a channel id instead of a channel
This commit is contained in:
Jesse Hallam
2018-04-06 17:08:57 -04:00
committed by Joram Wilander
parent ff077c6761
commit 116849842b
7 changed files with 251 additions and 6 deletions

View File

@@ -77,9 +77,21 @@ type API interface {
// UpdateChannel updates a channel.
UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError)
// AddChannelMember creates a channel membership for a user.
AddChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError)
// GetChannelMember gets a channel membership for a user.
GetChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError)
// UpdateChannelMemberRoles updates a user's roles for a channel.
UpdateChannelMemberRoles(channelId, userId, newRoles string) (*model.ChannelMember, *model.AppError)
// UpdateChannelMemberNotifications updates a user's notification properties for a channel.
UpdateChannelMemberNotifications(channelId, userId string, notifications map[string]string) (*model.ChannelMember, *model.AppError)
// DeleteChannelMember deletes a channel membership for a user.
DeleteChannelMember(channelId, userId string) *model.AppError
// CreatePost creates a post.
CreatePost(post *model.Post) (*model.Post, *model.AppError)

View File

@@ -223,6 +223,16 @@ func (m *API) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppE
return channelOut, err
}
func (m *API) AddChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError) {
ret := m.Called(channelId, userId)
if f, ok := ret.Get(0).(func(_, _ string) (*model.ChannelMember, *model.AppError)); ok {
return f(channelId, userId)
}
member, _ := ret.Get(0).(*model.ChannelMember)
err, _ := ret.Get(1).(*model.AppError)
return member, err
}
func (m *API) GetChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError) {
ret := m.Called(channelId, userId)
if f, ok := ret.Get(0).(func(_, _ string) (*model.ChannelMember, *model.AppError)); ok {
@@ -233,6 +243,35 @@ func (m *API) GetChannelMember(channelId, userId string) (*model.ChannelMember,
return member, err
}
func (m *API) UpdateChannelMemberRoles(channelId, userId, newRoles string) (*model.ChannelMember, *model.AppError) {
ret := m.Called(channelId, userId, newRoles)
if f, ok := ret.Get(0).(func(_, _, _ string) (*model.ChannelMember, *model.AppError)); ok {
return f(channelId, userId, newRoles)
}
member, _ := ret.Get(0).(*model.ChannelMember)
err, _ := ret.Get(1).(*model.AppError)
return member, err
}
func (m *API) UpdateChannelMemberNotifications(channelId, userId string, notifications map[string]string) (*model.ChannelMember, *model.AppError) {
ret := m.Called(channelId, userId, notifications)
if f, ok := ret.Get(0).(func(_, _ string, _ map[string]string) (*model.ChannelMember, *model.AppError)); ok {
return f(channelId, userId, notifications)
}
member, _ := ret.Get(0).(*model.ChannelMember)
err, _ := ret.Get(1).(*model.AppError)
return member, err
}
func (m *API) DeleteChannelMember(channelId, userId string) *model.AppError {
ret := m.Called(channelId, userId)
if f, ok := ret.Get(0).(func(_, _ string) *model.AppError); ok {
return f(channelId, userId)
}
err, _ := ret.Get(0).(*model.AppError)
return err
}
func (m *API) CreatePost(post *model.Post) (*model.Post, *model.AppError) {
ret := m.Called(post)
if f, ok := ret.Get(0).(func(*model.Post) (*model.Post, *model.AppError)); ok {

View File

@@ -163,11 +163,33 @@ type APIGetGroupChannelArgs struct {
UserIds []string
}
type APIAddChannelMemberArgs struct {
ChannelId string
UserId string
}
type APIGetChannelMemberArgs struct {
ChannelId string
UserId string
}
type APIUpdateChannelMemberRolesArgs struct {
ChannelId string
UserId string
NewRoles string
}
type APIUpdateChannelMemberNotificationsArgs struct {
ChannelId string
UserId string
Notifications map[string]string
}
type APIDeleteChannelMemberArgs struct {
ChannelId string
UserId string
}
type APIChannelReply struct {
Channel *model.Channel
Error *model.AppError
@@ -239,6 +261,15 @@ func (api *LocalAPI) UpdateChannel(args *model.Channel, reply *APIChannelReply)
return nil
}
func (api *LocalAPI) AddChannelMember(args *APIAddChannelMemberArgs, reply *APIChannelMemberReply) error {
member, err := api.api.AddChannelMember(args.ChannelId, args.UserId)
*reply = APIChannelMemberReply{
ChannelMember: member,
Error: err,
}
return nil
}
func (api *LocalAPI) GetChannelMember(args *APIGetChannelMemberArgs, reply *APIChannelMemberReply) error {
member, err := api.api.GetChannelMember(args.ChannelId, args.UserId)
*reply = APIChannelMemberReply{
@@ -248,6 +279,32 @@ func (api *LocalAPI) GetChannelMember(args *APIGetChannelMemberArgs, reply *APIC
return nil
}
func (api *LocalAPI) UpdateChannelMemberRoles(args *APIUpdateChannelMemberRolesArgs, reply *APIChannelMemberReply) error {
member, err := api.api.UpdateChannelMemberRoles(args.ChannelId, args.UserId, args.NewRoles)
*reply = APIChannelMemberReply{
ChannelMember: member,
Error: err,
}
return nil
}
func (api *LocalAPI) UpdateChannelMemberNotifications(args *APIUpdateChannelMemberNotificationsArgs, reply *APIChannelMemberReply) error {
member, err := api.api.UpdateChannelMemberNotifications(args.ChannelId, args.UserId, args.Notifications)
*reply = APIChannelMemberReply{
ChannelMember: member,
Error: err,
}
return nil
}
func (api *LocalAPI) DeleteChannelMember(args *APIDeleteChannelMemberArgs, reply *APIErrorReply) error {
err := api.api.DeleteChannelMember(args.ChannelId, args.UserId)
*reply = APIErrorReply{
Error: err,
}
return nil
}
type APIPostReply struct {
Post *model.Post
Error *model.AppError
@@ -520,6 +577,17 @@ func (api *RemoteAPI) UpdateChannel(channel *model.Channel) (*model.Channel, *mo
return reply.Channel, reply.Error
}
func (api *RemoteAPI) AddChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError) {
var reply APIChannelMemberReply
if err := api.client.Call("LocalAPI.AddChannelMember", &APIAddChannelMemberArgs{
ChannelId: channelId,
UserId: userId,
}, &reply); err != nil {
return nil, model.NewAppError("RemoteAPI.AddChannelMember", "plugin.rpcplugin.invocation.error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
return reply.ChannelMember, reply.Error
}
func (api *RemoteAPI) GetChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError) {
var reply APIChannelMemberReply
if err := api.client.Call("LocalAPI.GetChannelMember", &APIGetChannelMemberArgs{
@@ -531,6 +599,41 @@ func (api *RemoteAPI) GetChannelMember(channelId, userId string) (*model.Channel
return reply.ChannelMember, reply.Error
}
func (api *RemoteAPI) UpdateChannelMemberRoles(channelId, userId, newRoles string) (*model.ChannelMember, *model.AppError) {
var reply APIChannelMemberReply
if err := api.client.Call("LocalAPI.UpdateChannelMemberRoles", &APIUpdateChannelMemberRolesArgs{
ChannelId: channelId,
UserId: userId,
NewRoles: newRoles,
}, &reply); err != nil {
return nil, model.NewAppError("RemoteAPI.UpdateChannelMemberRoles", "plugin.rpcplugin.invocation.error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
return reply.ChannelMember, reply.Error
}
func (api *RemoteAPI) UpdateChannelMemberNotifications(channelId, userId string, notifications map[string]string) (*model.ChannelMember, *model.AppError) {
var reply APIChannelMemberReply
if err := api.client.Call("LocalAPI.UpdateChannelMemberNotifications", &APIUpdateChannelMemberNotificationsArgs{
ChannelId: channelId,
UserId: userId,
Notifications: notifications,
}, &reply); err != nil {
return nil, model.NewAppError("RemoteAPI.UpdateChannelMemberNotifications", "plugin.rpcplugin.invocation.error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
return reply.ChannelMember, reply.Error
}
func (api *RemoteAPI) DeleteChannelMember(channelId, userId string) *model.AppError {
var reply APIErrorReply
if err := api.client.Call("LocalAPI.DeleteChannelMember", &APIDeleteChannelMemberArgs{
ChannelId: channelId,
UserId: userId,
}, &reply); err != nil {
return model.NewAppError("RemoteAPI.DeleteChannelMember", "plugin.rpcplugin.invocation.error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
return reply.Error
}
func (api *RemoteAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) {
var reply APIPostReply
if err := api.client.Call("LocalAPI.CreatePost", post, &reply); err != nil {

View File

@@ -128,11 +128,32 @@ func TestAPI(t *testing.T) {
assert.Equal(t, testChannel, channel)
assert.Nil(t, err)
api.On("GetChannelMember", "thechannelid", "theuserid").Return(testChannelMember, nil).Once()
member, err := remote.GetChannelMember("thechannelid", "theuserid")
api.On("AddChannelMember", testChannel.Id, "theuserid").Return(testChannelMember, nil).Once()
member, err := remote.AddChannelMember(testChannel.Id, "theuserid")
assert.Equal(t, testChannelMember, member)
assert.Nil(t, err)
api.On("GetChannelMember", "thechannelid", "theuserid").Return(testChannelMember, nil).Once()
member, err = remote.GetChannelMember("thechannelid", "theuserid")
assert.Equal(t, testChannelMember, member)
assert.Nil(t, err)
api.On("UpdateChannelMemberRoles", testChannel.Id, "theuserid", model.CHANNEL_ADMIN_ROLE_ID).Return(testChannelMember, nil).Once()
member, err = remote.UpdateChannelMemberRoles(testChannel.Id, "theuserid", model.CHANNEL_ADMIN_ROLE_ID)
assert.Equal(t, testChannelMember, member)
assert.Nil(t, err)
notifications := map[string]string{}
notifications[model.MARK_UNREAD_NOTIFY_PROP] = model.CHANNEL_MARK_UNREAD_MENTION
api.On("UpdateChannelMemberNotifications", testChannel.Id, "theuserid", notifications).Return(testChannelMember, nil).Once()
member, err = remote.UpdateChannelMemberNotifications(testChannel.Id, "theuserid", notifications)
assert.Equal(t, testChannelMember, member)
assert.Nil(t, err)
api.On("DeleteChannelMember", "thechannelid", "theuserid").Return(nil).Once()
err = remote.DeleteChannelMember("thechannelid", "theuserid")
assert.Nil(t, err)
api.On("CreateUser", mock.AnythingOfType("*model.User")).Return(func(u *model.User) (*model.User, *model.AppError) {
u.Id = "theuserid"
return u, nil