From bfe90c370423e2c3afad5137cdf7a04f9f27f455 Mon Sep 17 00:00:00 2001 From: Ben Cooke Date: Wed, 21 May 2025 19:44:34 +0100 Subject: [PATCH] New pluginapi method for syncables (#30790) * new pluginapi method for syncables --------- Co-authored-by: Mattermost Build --- server/channels/app/plugin_api.go | 26 +++++++++ server/i18n/en.json | 8 +++ server/public/plugin/api.go | 12 ++++ .../plugin/api_timer_layer_generated.go | 14 +++++ server/public/plugin/client_rpc_generated.go | 55 +++++++++++++++++++ server/public/plugin/plugintest/api.go | 40 ++++++++++++++ server/public/pluginapi/group.go | 16 ++++++ 7 files changed, 171 insertions(+) diff --git a/server/channels/app/plugin_api.go b/server/channels/app/plugin_api.go index ec6385cfcd..2bc6020c40 100644 --- a/server/channels/app/plugin_api.go +++ b/server/channels/app/plugin_api.go @@ -1460,3 +1460,29 @@ func (api *PluginAPI) GetGroups(page, perPage int, opts model.GroupSearchOpts, v } return api.app.GetGroups(page, perPage, opts, viewRestrictions) } + +func (api *PluginAPI) CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) *model.AppError { + if err := api.checkLDAPLicense(); err != nil { + return model.NewAppError("CreateDefaultSyncableMemberships", "app.group.license_error", nil, "", http.StatusForbidden).Wrap(err) + } + + err := api.app.CreateDefaultMemberships(api.ctx, params) + if err != nil { + return model.NewAppError("CreateDefaultSyncableMemberships", "app.group.create_syncable_memberships.error", nil, "", http.StatusInternalServerError).Wrap(err) + } + + return nil +} + +func (api *PluginAPI) DeleteGroupConstrainedMemberships() *model.AppError { + if err := api.checkLDAPLicense(); err != nil { + return model.NewAppError("DeleteGroupConstrainedMemberships", "app.group.license_error", nil, "", http.StatusForbidden).Wrap(err) + } + + err := api.app.DeleteGroupConstrainedMemberships(api.ctx) + if err != nil { + return model.NewAppError("DeleteGroupConstrainedMemberships", "app.group.delete_invalid_syncable_memberships.error", nil, "", http.StatusInternalServerError).Wrap(err) + } + + return nil +} diff --git a/server/i18n/en.json b/server/i18n/en.json index c93a0ab738..0852408f8a 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -5358,10 +5358,18 @@ "id": "app.get_user_team_scheduled_posts.error", "translation": "Error occurred fetching scheduled posts." }, + { + "id": "app.group.create_syncable_memberships.error", + "translation": "Unable to create group syncable memberships." + }, { "id": "app.group.crud_permission", "translation": "Unable to perform operation for that source type." }, + { + "id": "app.group.delete_invalid_syncable_memberships.error", + "translation": "Unable to delete invalid group syncable memberships." + }, { "id": "app.group.group_syncable_already_deleted", "translation": "group syncable was already deleted" diff --git a/server/public/plugin/api.go b/server/public/plugin/api.go index 1782da9869..f40bab9ba1 100644 --- a/server/public/plugin/api.go +++ b/server/public/plugin/api.go @@ -1399,6 +1399,18 @@ type API interface { // @tag Group // Minimum server version: 10.7 GetGroups(page, perPage int, opts model.GroupSearchOpts, viewRestrictions *model.ViewUsersRestrictions) ([]*model.Group, *model.AppError) + + // CreateDefaultSyncableMemberships creates default syncable memberships based off the provided parameters. + // + // @tag Group + // Minimum server version: 10.9 + CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) *model.AppError + + // DeleteGroupConstrainedMemberships deletes team and channel memberships of users who aren't members of the allowed groups of all group-constrained teams and channels. + // + // @tag Group + // Minimum server version: 10.9 + DeleteGroupConstrainedMemberships() *model.AppError } var handshake = plugin.HandshakeConfig{ diff --git a/server/public/plugin/api_timer_layer_generated.go b/server/public/plugin/api_timer_layer_generated.go index 6c52b629bd..22166d2f26 100644 --- a/server/public/plugin/api_timer_layer_generated.go +++ b/server/public/plugin/api_timer_layer_generated.go @@ -1483,3 +1483,17 @@ func (api *apiTimerLayer) GetGroups(page, perPage int, opts model.GroupSearchOpt api.recordTime(startTime, "GetGroups", _returnsB == nil) return _returnsA, _returnsB } + +func (api *apiTimerLayer) CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) *model.AppError { + startTime := timePkg.Now() + _returnsA := api.apiImpl.CreateDefaultSyncableMemberships(params) + api.recordTime(startTime, "CreateDefaultSyncableMemberships", _returnsA == nil) + return _returnsA +} + +func (api *apiTimerLayer) DeleteGroupConstrainedMemberships() *model.AppError { + startTime := timePkg.Now() + _returnsA := api.apiImpl.DeleteGroupConstrainedMemberships() + api.recordTime(startTime, "DeleteGroupConstrainedMemberships", _returnsA == nil) + return _returnsA +} diff --git a/server/public/plugin/client_rpc_generated.go b/server/public/plugin/client_rpc_generated.go index 8ca15ac11d..388c2acd17 100644 --- a/server/public/plugin/client_rpc_generated.go +++ b/server/public/plugin/client_rpc_generated.go @@ -7113,3 +7113,58 @@ func (s *apiRPCServer) GetGroups(args *Z_GetGroupsArgs, returns *Z_GetGroupsRetu } return nil } + +type Z_CreateDefaultSyncableMembershipsArgs struct { + A model.CreateDefaultMembershipParams +} + +type Z_CreateDefaultSyncableMembershipsReturns struct { + A *model.AppError +} + +func (g *apiRPCClient) CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) *model.AppError { + _args := &Z_CreateDefaultSyncableMembershipsArgs{params} + _returns := &Z_CreateDefaultSyncableMembershipsReturns{} + if err := g.client.Call("Plugin.CreateDefaultSyncableMemberships", _args, _returns); err != nil { + log.Printf("RPC call to CreateDefaultSyncableMemberships API failed: %s", err.Error()) + } + return _returns.A +} + +func (s *apiRPCServer) CreateDefaultSyncableMemberships(args *Z_CreateDefaultSyncableMembershipsArgs, returns *Z_CreateDefaultSyncableMembershipsReturns) error { + if hook, ok := s.impl.(interface { + CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) *model.AppError + }); ok { + returns.A = hook.CreateDefaultSyncableMemberships(args.A) + } else { + return encodableError(fmt.Errorf("API CreateDefaultSyncableMemberships called but not implemented.")) + } + return nil +} + +type Z_DeleteGroupConstrainedMembershipsArgs struct { +} + +type Z_DeleteGroupConstrainedMembershipsReturns struct { + A *model.AppError +} + +func (g *apiRPCClient) DeleteGroupConstrainedMemberships() *model.AppError { + _args := &Z_DeleteGroupConstrainedMembershipsArgs{} + _returns := &Z_DeleteGroupConstrainedMembershipsReturns{} + if err := g.client.Call("Plugin.DeleteGroupConstrainedMemberships", _args, _returns); err != nil { + log.Printf("RPC call to DeleteGroupConstrainedMemberships API failed: %s", err.Error()) + } + return _returns.A +} + +func (s *apiRPCServer) DeleteGroupConstrainedMemberships(args *Z_DeleteGroupConstrainedMembershipsArgs, returns *Z_DeleteGroupConstrainedMembershipsReturns) error { + if hook, ok := s.impl.(interface { + DeleteGroupConstrainedMemberships() *model.AppError + }); ok { + returns.A = hook.DeleteGroupConstrainedMemberships() + } else { + return encodableError(fmt.Errorf("API DeleteGroupConstrainedMemberships called but not implemented.")) + } + return nil +} diff --git a/server/public/plugin/plugintest/api.go b/server/public/plugin/plugintest/api.go index c4b7029edd..6c9753b980 100644 --- a/server/public/plugin/plugintest/api.go +++ b/server/public/plugin/plugintest/api.go @@ -272,6 +272,26 @@ func (_m *API) CreateCommand(cmd *model.Command) (*model.Command, error) { return r0, r1 } +// CreateDefaultSyncableMemberships provides a mock function with given fields: params +func (_m *API) CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) *model.AppError { + ret := _m.Called(params) + + if len(ret) == 0 { + panic("no return value specified for CreateDefaultSyncableMemberships") + } + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(model.CreateDefaultMembershipParams) *model.AppError); ok { + r0 = rf(params) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + // CreateGroup provides a mock function with given fields: group func (_m *API) CreateGroup(group *model.Group) (*model.Group, *model.AppError) { ret := _m.Called(group) @@ -717,6 +737,26 @@ func (_m *API) DeleteGroup(groupID string) (*model.Group, *model.AppError) { return r0, r1 } +// DeleteGroupConstrainedMemberships provides a mock function with given fields: +func (_m *API) DeleteGroupConstrainedMemberships() *model.AppError { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for DeleteGroupConstrainedMemberships") + } + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func() *model.AppError); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + // DeleteGroupMember provides a mock function with given fields: groupID, userID func (_m *API) DeleteGroupMember(groupID string, userID string) (*model.GroupMember, *model.AppError) { ret := _m.Called(groupID, userID) diff --git a/server/public/pluginapi/group.go b/server/public/pluginapi/group.go index 8acd89ad8d..284644f634 100644 --- a/server/public/pluginapi/group.go +++ b/server/public/pluginapi/group.go @@ -167,3 +167,19 @@ func (g *GroupService) GetGroups(page, perPage int, opts model.GroupSearchOpts, groups, appErr := g.api.GetGroups(page, perPage, opts, viewRestrictions) return groups, normalizeAppErr(appErr) } + +// CreateDefaultSyncableMemberships creates default syncable memberships based off the provided parameters. +// +// Minimum server version: 10.9 +func (g *GroupService) CreateDefaultSyncableMemberships(params model.CreateDefaultMembershipParams) error { + appErr := g.api.CreateDefaultSyncableMemberships(params) + return normalizeAppErr(appErr) +} + +// DeleteGroupConstrainedMemberships deletes team and channel memberships of users who aren't members of the allowed groups of all group-constrained teams and channels. +// +// Minimum server version: 10.9 +func (g *GroupService) DeleteGroupConstrainedMemberships() error { + appErr := g.api.DeleteGroupConstrainedMemberships() + return normalizeAppErr(appErr) +}