diff --git a/locales/index.d.ts b/locales/index.d.ts index 6dfc76546a..2d75a86ca6 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -13512,13 +13512,17 @@ export interface Locale extends ILocale { */ "permissions": string; /** - * Override rank + * Limit rank */ "overrideRank": string; /** - * Overrides the user rank (admin, moderator, or user) for apps using this token. + * Limits the user rank (admin, moderator, or user) for apps using this token. */ "overrideRankDescription": string; + /** + * Rank + */ + "rank": string; "_ranks": { /** * Admin diff --git a/packages/backend/src/server/api/endpoints/i/apps.ts b/packages/backend/src/server/api/endpoints/i/apps.ts index f290ff6844..c33174ed48 100644 --- a/packages/backend/src/server/api/endpoints/i/apps.ts +++ b/packages/backend/src/server/api/endpoints/i/apps.ts @@ -5,9 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AccessTokensRepository } from '@/models/_.js'; +import type { AccessTokensRepository, SharedAccessTokensRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { IdService } from '@/core/IdService.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; export const meta = { requireCredential: true, @@ -46,6 +47,19 @@ export const meta = { type: 'string', }, }, + grantees: { + type: 'array', + optional: false, + items: { + ref: 'UserLite', + }, + }, + rank: { + type: 'string', + optional: false, + nullable: true, + enum: ['admin', 'mod', 'user'], + }, }, }, }, @@ -71,6 +85,10 @@ export default class extends Endpoint { // eslint- @Inject(DI.accessTokensRepository) private accessTokensRepository: AccessTokensRepository, + @Inject(DI.sharedAccessTokensRepository) + private readonly sharedAccessTokenRepository: SharedAccessTokensRepository, + + private readonly userEntityService: UserEntityService, private idService: IdService, ) { super(meta, paramDef, async (ps, me) => { @@ -88,13 +106,26 @@ export default class extends Endpoint { // eslint- const tokens = await query.getMany(); - return await Promise.all(tokens.map(token => ({ - id: token.id, - name: token.name ?? token.app?.name, - createdAt: this.idService.parse(token.id).date.toISOString(), - lastUsedAt: token.lastUsedAt?.toISOString(), - permission: token.app ? token.app.permission : token.permission, - }))); + return await Promise.all(tokens.map(async token => { + // TODO inline this table into a column w/ GIN index + const sharedTokens = await this.sharedAccessTokenRepository.find({ + where: { accessTokenId: token.id }, + relations: { grantee: true }, + }); + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const grantees = await this.userEntityService.packMany(sharedTokens.map(t => t.grantee!), me); + + return { + id: token.id, + name: token.name ?? token.app?.name, + createdAt: this.idService.parse(token.id).date.toISOString(), + lastUsedAt: token.lastUsedAt?.toISOString(), + permission: token.app ? token.app.permission : token.permission, + rank: token.rank, + grantees, + }; + })); }); } } diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue index 33c17e5d7f..8521a35103 100644 --- a/packages/frontend/src/pages/settings/apps.vue +++ b/packages/frontend/src/pages/settings/apps.vue @@ -32,14 +32,31 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + - + - +
    -
  • {{ i18n.ts._permissions[p] }}
  • +
  • {{ i18n.ts._permissions[p] }}
+ + + +
    +
  • {{ i18n.ts._permissions[p] }}
  • +
+
+ + + + + +
@@ -50,7 +67,6 @@ SPDX-License-Identifier: AGPL-3.0-only