diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 415fbf08dd..c19e861a5a 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -271,6 +271,17 @@ export class ApiCallService implements OnApplicationShutdown { } } + if (ep.meta.requireRoleOption != null && !user!.isRoot) { + const myRole = await this.roleService.getUserRoleOptions(user!.id); + if (!myRole[ep.meta.requireRoleOption]) { + throw new ApiError({ + message: 'You are not assigned to a required role.', + code: 'ROLE_PERMISSION_DENIED', + id: '7f86f06f-7e15-4057-8561-f4b6d4ac755a', + }); + } + } + if (token && ep.meta.kind && !token.permission.some(p => p === ep.meta.kind)) { throw new ApiError({ message: 'Your app does not have the necessary permissions to use this endpoint.', diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 0a26094c44..f50a3b5dd2 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -695,6 +695,8 @@ export interface IEndpointMeta { */ readonly requireAdmin?: boolean; + readonly requireRoleOption?: string; + /** * エンドポイントのリミテーションに関するやつ * 省略した場合はリミテーションは無いものとして解釈されます。 diff --git a/packages/backend/src/server/api/endpoints/invite.ts b/packages/backend/src/server/api/endpoints/invite.ts index d22946e04a..9b03cf4bb6 100644 --- a/packages/backend/src/server/api/endpoints/invite.ts +++ b/packages/backend/src/server/api/endpoints/invite.ts @@ -4,12 +4,12 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import type { RegistrationTicketsRepository } from '@/models/index.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; -import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['meta'], requireCredential: true, + requireRoleOption: 'canInvite', res: { type: 'object', @@ -39,15 +39,9 @@ export default class extends Endpoint { @Inject(DI.registrationTicketsRepository) private registrationTicketsRepository: RegistrationTicketsRepository, - private roleService: RoleService, private idService: IdService, ) { super(meta, paramDef, async (ps, me) => { - const role = await this.roleService.getUserRoleOptions(me.id); - if (!me.isRoot && !role.canInvite) { - throw new Error('access denied'); - } - const code = rndstr({ length: 8, chars: '2-9A-HJ-NP-Z', // [0-9A-Z] w/o [01IO] (32 patterns)