diff --git a/server/services/openapi/integration.service.ts b/server/services/openapi/integration.service.ts index ef843827..5dc7dbd0 100644 --- a/server/services/openapi/integration.service.ts +++ b/server/services/openapi/integration.service.ts @@ -1,4 +1,10 @@ -import { call, DataNotFoundError, TcContext } from 'tailchat-server-sdk'; +import { + call, + DataNotFoundError, + NoPermissionError, + PERMISSION, + TcContext, +} from 'tailchat-server-sdk'; import { TcService, config } from 'tailchat-server-sdk'; import { isValidStr } from '../../lib/utils'; import type { OpenApp } from '../../models/openapi/app'; @@ -37,6 +43,15 @@ class OpenAppIntegrationService extends TcService { const groupId = ctx.params.groupId; const t = ctx.meta.t; + const [hasPermission] = await call(ctx).checkUserPermissions( + groupId, + ctx.meta.userId, + [PERMISSION.core.manageUser] + ); + if (!hasPermission) { + throw new NoPermissionError(t('没有操作权限')); + } + const openapp: OpenApp = await ctx.call('openapi.app.get', { appId, }); diff --git a/server/test/integration/openapi/integration.spec.ts b/server/test/integration/openapi/integration.spec.ts new file mode 100644 index 00000000..2701ca1f --- /dev/null +++ b/server/test/integration/openapi/integration.spec.ts @@ -0,0 +1,72 @@ +import { createTestServiceBroker } from '../../utils'; +import OpenAppIntegrationService from '../../../services/openapi/integration.service'; +import { Types } from 'mongoose'; +import { PERMISSION } from 'tailchat-server-sdk'; + +describe('Test "openapi.integration" service', () => { + let userPermissions: string[] = []; + const botUserId = String(new Types.ObjectId()); + + const { broker, contextCallMock } = + createTestServiceBroker( + OpenAppIntegrationService, + { + contextCallMockFn(actionName) { + if (actionName === 'group.getUserAllPermissions') { + return userPermissions; + } + if (actionName === 'openapi.app.get') { + return { appId: 'tc_test', capability: ['bot'] }; + } + if (actionName === 'openapi.bot.getOrCreateBotAccount') { + return { userId: botUserId, nickname: 'test-bot' }; + } + }, + } + ); + + function addBotUser(userId: string) { + return broker.call( + 'openapi.integration.addBotUser', + { + appId: 'tc_test', + groupId: String(new Types.ObjectId()), + }, + { + meta: { + userId, + user: { nickname: 'operator' }, + }, + } + ); + } + + beforeEach(() => { + contextCallMock.mockClear(); + }); + + test('rejects member without manageUser permission', async () => { + userPermissions = []; + + await expect(addBotUser(String(new Types.ObjectId()))).rejects.toThrow( + '没有操作权限' + ); + + const joinCalls = contextCallMock.mock.calls.filter( + ([actionName]) => actionName === 'group.joinGroup' + ); + expect(joinCalls).toHaveLength(0); + }); + + test('adds bot when member has manageUser permission', async () => { + userPermissions = [PERMISSION.core.manageUser]; + + await addBotUser(String(new Types.ObjectId())); + + const joinCalls = contextCallMock.mock.calls.filter( + ([actionName]) => actionName === 'group.joinGroup' + ); + expect(joinCalls).toHaveLength(1); + expect(joinCalls[0][2]).toMatchObject({ meta: { userId: botUserId } }); + }); +});