Fix admin integrations (#10076)

* Get your own integrations for admin

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Remove admin check

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Clean up

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Allow to add social id by admin

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Use service token for integrations test

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Update version

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Fix tokens

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Update allowed services

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Use workspace service

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Fix service client

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Get rid of admin service name

Signed-off-by: Artem Savchenko <armisav@gmail.com>

---------

Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
Artyom Savchenko
2025-10-14 17:01:10 +07:00
committed by GitHub
parent 152befc628
commit 35cd8a3d86
12 changed files with 27 additions and 24 deletions
+2 -1
View File
@@ -6196,7 +6196,7 @@ packages:
version: 0.0.0
'@rush-temp/tests-sanity@file:projects/tests-sanity.tgz':
resolution: {integrity: sha512-oAaYl2IO0i1GSSbO6rLxbZOnmAxl3tMQ8mLLe5A3lWMu7eXTFnt6arzUxNixChALxKiO9eCbA1KWpvutJ3dDEw==, tarball: file:projects/tests-sanity.tgz}
resolution: {integrity: sha512-6MzoRP9tBpHv4XkiFFo6bGdKNfW9tAmXZxiPTXHunGc/BIgxEiUqvYlBi28EMp1oYsJWg2s6t4up1hin0sqIFA==, tarball: file:projects/tests-sanity.tgz}
version: 0.0.0
'@rush-temp/tests-ws-sanity@file:projects/tests-ws-sanity.tgz':
@@ -34129,6 +34129,7 @@ snapshots:
'@hcengineering/client-resources': 0.7.6
'@hcengineering/core': 0.7.7
'@hcengineering/platform-rig': 0.7.19(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.9.3)))(postcss@8.5.3)(sass@1.93.2)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.9.3))
'@hcengineering/server-token': 0.7.5
'@playwright/test': 1.49.1
'@types/jest': 29.5.12
'@types/node': 22.15.29
+1 -1
View File
@@ -54,7 +54,7 @@ export async function performGithubAccountMigrations (
txes: Tx[],
region: string | null
): Promise<void> {
const token = generateToken(systemAccountUuid, undefined, { service: 'admin', admin: 'true' })
const token = generateToken(systemAccountUuid, undefined, { service: 'tool', admin: 'true' })
const githubToken = generateToken(systemAccountUuid, undefined, { service: 'github' })
const accountClient = getAccountClient(token)
+1 -1
View File
@@ -79,7 +79,7 @@ export async function performGmailAccountMigrations (
txes: Tx[]
): Promise<void> {
console.log('Start Gmail migrations')
const token = generateToken(systemAccountUuid, undefined, { service: 'admin', admin: 'true' })
const token = generateToken(systemAccountUuid, undefined, { service: 'tool', admin: 'true' })
const accountClient = getAccountClient(token)
const allWorkpaces = await accountClient.listWorkspaces(region)
+1 -1
View File
@@ -378,7 +378,7 @@ export async function restoreMarkupRefs (
storageAdapter: StorageAdapter,
region: string | null
): Promise<void> {
const token = generateToken(systemAccountUuid, undefined, { service: 'admin', admin: 'true' })
const token = generateToken(systemAccountUuid, undefined, { service: 'tool', admin: 'true' })
const ctx = new MeasureMetricsContext('restore-markup-ref', {})
const accountClient = getAccountClient(token)
+1 -1
View File
@@ -16,7 +16,7 @@ export async function restoreGithubIntegrations (dbUrl: string, dryrun: boolean)
try {
const pg = getDBClient(dbUrl)
const pgClient = await pg.getClient()
const token = generateToken(systemAccountUuid, undefined, { service: 'admin', admin: 'true' })
const token = generateToken(systemAccountUuid, undefined, { service: 'tool', admin: 'true' })
const accountClient = getAccountClient(token)
const integrationSettings = await pgClient<
@@ -1686,15 +1686,6 @@ describe('account utils', () => {
}).not.toThrow()
})
test('should not throw for admin', () => {
const services = ['service1']
const extra = { service: 'service2', admin: 'true' }
expect(() => {
verifyAllowedServices(services, extra)
}).not.toThrow()
})
test('should throw for unauthorized service', () => {
const services = ['service1']
const extra = { service: 'service2' }
+6 -4
View File
@@ -585,10 +585,12 @@ export async function addSocialIdToPerson (
const { person, type, value, confirmed, displayValue } = params
const { extra } = decodeTokenVerbose(ctx, token)
verifyAllowedServices(
['github', 'telegram-bot', 'gmail', 'tool', 'workspace', 'hulygram', 'google-calendar', 'ai-assistant'],
extra
)
if (extra?.admin !== 'true') {
verifyAllowedServices(
['github', 'telegram-bot', 'gmail', 'tool', 'workspace', 'hulygram', 'google-calendar', 'ai-assistant'],
extra
)
}
if (person == null || person === '' || !Object.values(SocialIdType).includes(type) || value == null || value === '') {
throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))
+3 -2
View File
@@ -1536,7 +1536,7 @@ export async function getWorkspaces (
}
export function verifyAllowedServices (services: string[], extra: any, shouldThrow = true): boolean {
const ok = services.includes(extra?.service) || extra?.admin === 'true'
const ok = services.includes(extra?.service)
if (!ok && shouldThrow) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))
@@ -1811,7 +1811,8 @@ export const integrationServices = [
'gmail',
'google-calendar',
'huly-mail',
'ai-assistant'
'ai-assistant',
'tool'
]
export async function findExistingIntegration (
+2 -1
View File
@@ -52,6 +52,7 @@
"@hcengineering/core": "^0.7.7",
"@hcengineering/client-resources": "^0.7.6",
"@hcengineering/account": "^0.7.0",
"@hcengineering/account-client": "^0.7.5"
"@hcengineering/account-client": "^0.7.5",
"@hcengineering/server-token": "^0.7.5"
}
}
+7
View File
@@ -1,5 +1,7 @@
import { getClient as getClientRaw, type AccountClient } from '@hcengineering/account-client'
import { LocalUrl, PlatformAdmin } from '../utils'
import { systemAccountUuid } from '@hcengineering/core'
import { generateToken } from '@hcengineering/server-token'
let adminAccountClient: AccountClient
@@ -18,3 +20,8 @@ export async function getAdminAccountClient (): Promise<AccountClient> {
adminAccountClient = getClientRaw(LocalUrl, loginInfo.token)
return adminAccountClient
}
export async function getServiceAccountClient (serviceName: string): Promise<AccountClient> {
const token = generateToken(systemAccountUuid, undefined, { service: serviceName }, 'secret')
return getClientRaw(LocalUrl, token)
}
+2 -2
View File
@@ -4,11 +4,11 @@ import { Integration, IntegrationSecret } from '@hcengineering/account'
import { buildSocialIdString, IntegrationKind, SocialIdType } from '@hcengineering/core'
import { PlatformUser } from './utils'
import { getAdminAccountClient } from './API/AccountClient'
import { getServiceAccountClient } from './API/AccountClient'
test.describe('integrations in accounts tests', () => {
test('manage integrations', async () => {
const accountClient = await getAdminAccountClient()
const accountClient = await getServiceAccountClient('github')
const personUuid = await accountClient.findPersonBySocialKey(
buildSocialIdString({ type: SocialIdType.EMAIL, value: PlatformUser })
@@ -75,7 +75,7 @@ describe('rest-api-server', () => {
accountClient = getAccountClient(config.ACCOUNTS_URL, apiWorkspace1.token)
adminAccountClient = getAccountClient(
config.ACCOUNTS_URL,
generateToken(systemAccountUuid, undefined, { admin: 'true' }, 'secret')
generateToken(systemAccountUuid, undefined, { service: 'workspace', admin: 'true' }, 'secret')
)
const person = await accountClient.getPerson()
const socialIds: SocialId[] = await accountClient.getSocialIds(true)