diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 85a39548a..e37e95c1d 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -11,6 +11,8 @@ import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-repor import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js'; +import * as ep___admin_accounts_pending_list from './endpoints/admin/accounts/pending/list.js'; +import * as ep___admin_accounts_pending_revoke from './endpoints/admin/accounts/pending/revoke.js'; import * as ep___admin_ad_create from './endpoints/admin/ad/create.js'; import * as ep___admin_ad_delete from './endpoints/admin/ad/delete.js'; import * as ep___admin_ad_list from './endpoints/admin/ad/list.js'; @@ -398,6 +400,8 @@ const $admin_abuseUserReports: Provider = { provide: 'ep:admin/abuse-user-report const $admin_accounts_create: Provider = { provide: 'ep:admin/accounts/create', useClass: ep___admin_accounts_create.default }; const $admin_accounts_delete: Provider = { provide: 'ep:admin/accounts/delete', useClass: ep___admin_accounts_delete.default }; const $admin_accounts_findByEmail: Provider = { provide: 'ep:admin/accounts/find-by-email', useClass: ep___admin_accounts_findByEmail.default }; +const $admin_accounts_pending_list: Provider = { provide: 'ep:admin/accounts/pending/list', useClass: ep___admin_accounts_pending_list.default }; +const $admin_accounts_pending_revoke: Provider = { provide: 'ep:admin/accounts/pending/revoke', useClass: ep___admin_accounts_pending_revoke.default }; const $admin_ad_create: Provider = { provide: 'ep:admin/ad/create', useClass: ep___admin_ad_create.default }; const $admin_ad_delete: Provider = { provide: 'ep:admin/ad/delete', useClass: ep___admin_ad_delete.default }; const $admin_ad_list: Provider = { provide: 'ep:admin/ad/list', useClass: ep___admin_ad_list.default }; @@ -789,6 +793,8 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_accounts_create, $admin_accounts_delete, $admin_accounts_findByEmail, + $admin_accounts_pending_list, + $admin_accounts_pending_revoke, $admin_ad_create, $admin_ad_delete, $admin_ad_list, @@ -1174,6 +1180,8 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_accounts_create, $admin_accounts_delete, $admin_accounts_findByEmail, + $admin_accounts_pending_list, + $admin_accounts_pending_revoke, $admin_ad_create, $admin_ad_delete, $admin_ad_list, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 368ffdca7..862d1d162 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -11,6 +11,8 @@ import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-repor import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js'; +import * as ep___admin_accounts_pending_list from './endpoints/admin/accounts/pending/list.js'; +import * as ep___admin_accounts_pending_revoke from './endpoints/admin/accounts/pending/revoke.js'; import * as ep___admin_ad_create from './endpoints/admin/ad/create.js'; import * as ep___admin_ad_delete from './endpoints/admin/ad/delete.js'; import * as ep___admin_ad_list from './endpoints/admin/ad/list.js'; @@ -396,6 +398,8 @@ const eps = [ ['admin/accounts/create', ep___admin_accounts_create], ['admin/accounts/delete', ep___admin_accounts_delete], ['admin/accounts/find-by-email', ep___admin_accounts_findByEmail], + ['admin/accounts/pending/list', ep___admin_accounts_pending_list], + ['admin/accounts/pending/revoke', ep___admin_accounts_pending_revoke], ['admin/ad/create', ep___admin_ad_create], ['admin/ad/delete', ep___admin_ad_delete], ['admin/ad/list', ep___admin_ad_list], diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/pending/list.ts b/packages/backend/src/server/api/endpoints/admin/accounts/pending/list.ts new file mode 100644 index 000000000..9d85bc7a9 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/accounts/pending/list.ts @@ -0,0 +1,102 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { UserPendingsRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireAdmin: true, + kind: 'read:admin:account', + + res: { + type: 'array', + nullable: false, optional: false, + items: { + type: 'object', + nullable: false, optional: false, + properties: { + id: { + type: 'string', + nullable: false, optional: false, + format: 'id', + example: 'xxxxxxxxxx', + }, + createdAt: { + type: 'string', + nullable: false, optional: false, + format: 'date-time', + }, + code: { + type: 'string', + nullable: false, optional: false, + }, + username: { + type: 'string', + nullable: false, optional: false, + example: 'ai', + }, + email: { + type: 'string', + nullable: true, optional: true, + }, + }, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + sort: { type: 'string', enum: ['+createdAt', '-createdAt'] }, + username: { type: 'string', nullable: true, default: null }, + email: { type: 'string', nullable: true, default: null }, + code: { type: 'string', nullable: true, default: null }, + }, + required: [], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.userPendingsRepository) + private userPendingsRepository: UserPendingsRepository, + ) { + super(meta, paramDef, async (ps, me) => { + const query = this.userPendingsRepository.createQueryBuilder('pending'); + + if (ps.username != null) { + query.andWhere('pending.username = :username', { username: ps.username }); + } + + if (ps.email != null) { + query.andWhere('pending.email = :email', { email: ps.email }); + } + + if (ps.code != null) { + query.andWhere('pending.code = :code', { code: ps.code }); + } + + switch (ps.sort) { + case '+createdAt': query.orderBy('pending.id', 'DESC'); break; + case '-createdAt': query.orderBy('pending.id', 'ASC'); break; + default: query.orderBy('pending.id', 'DESC'); break; + } + + query.limit(ps.limit); + query.offset(ps.offset); + + const pendings = await query.getMany(); + return pendings.map(pending => ({ + id: pending.id, + createdAt: pending.createdAt.toISOString(), + code: pending.code, + username: pending.username, + email: pending.email, + })); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/pending/revoke.ts b/packages/backend/src/server/api/endpoints/admin/accounts/pending/revoke.ts new file mode 100644 index 000000000..c1cc3fed7 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/accounts/pending/revoke.ts @@ -0,0 +1,49 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import type { UserPendingsRepository } from '@/models/_.js'; +import { ApiError } from '@/server/api/error.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireAdmin: true, + kind: 'write:admin:account', + + errors: { + pendingUserNotFound: { + message: 'Pending User not found.', + code: 'PENDING_USER_NOT_FOUND', + id: 'a04d6118-65e6-4508-9144-9900a331bbf3', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + code: { type: 'string' }, + }, + anyOf: [ + { required: ['id'] }, + { required: ['code'] }, + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.userPendingsRepository) + private userPendingsRepository: UserPendingsRepository, + ) { + super(meta, paramDef, async (ps, me) => { + const pendingUser = await this.userPendingsRepository.findOneBy({ id: ps.id, code: ps.code }); + + if (pendingUser == null) throw new ApiError(meta.errors.pendingUserNotFound); + + await this.userPendingsRepository.delete(pendingUser.id); + }); + } +} diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index e5f23163c..e1c388f5f 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -70,6 +70,15 @@ type AdminAccountsFindByEmailRequest = operations['admin___accounts___find-by-em // @public (undocumented) type AdminAccountsFindByEmailResponse = operations['admin___accounts___find-by-email']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAccountsPendingListRequest = operations['admin___accounts___pending___list']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminAccountsPendingListResponse = operations['admin___accounts___pending___list']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminAccountsPendingRevokeRequest = operations['admin___accounts___pending___revoke']['requestBody']['content']['application/json']; + // @public (undocumented) type AdminAdCreateRequest = operations['admin___ad___create']['requestBody']['content']['application/json']; @@ -1189,6 +1198,9 @@ declare namespace entities { AdminAccountsDeleteRequest, AdminAccountsFindByEmailRequest, AdminAccountsFindByEmailResponse, + AdminAccountsPendingListRequest, + AdminAccountsPendingListResponse, + AdminAccountsPendingRevokeRequest, AdminAdCreateRequest, AdminAdCreateResponse, AdminAdDeleteRequest, diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index f25943a4f..008251bbc 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -58,6 +58,28 @@ declare module '../api.js' { credential?: string | null, ): Promise>; + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:admin:account* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:admin:account* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + /** * No description provided. * diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 6ddc534ea..7c5205bc4 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -9,6 +9,9 @@ import type { AdminAccountsDeleteRequest, AdminAccountsFindByEmailRequest, AdminAccountsFindByEmailResponse, + AdminAccountsPendingListRequest, + AdminAccountsPendingListResponse, + AdminAccountsPendingRevokeRequest, AdminAdCreateRequest, AdminAdCreateResponse, AdminAdDeleteRequest, @@ -583,6 +586,8 @@ export type Endpoints = { 'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse }; 'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse }; 'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse }; + 'admin/accounts/pending/list': { req: AdminAccountsPendingListRequest; res: AdminAccountsPendingListResponse }; + 'admin/accounts/pending/revoke': { req: AdminAccountsPendingRevokeRequest; res: EmptyResponse }; 'admin/ad/create': { req: AdminAdCreateRequest; res: AdminAdCreateResponse }; 'admin/ad/delete': { req: AdminAdDeleteRequest; res: EmptyResponse }; 'admin/ad/list': { req: AdminAdListRequest; res: AdminAdListResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index bc5b420a4..5239627f0 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -12,6 +12,9 @@ export type AdminAccountsCreateResponse = operations['admin___accounts___create' export type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json']; export type AdminAccountsFindByEmailRequest = operations['admin___accounts___find-by-email']['requestBody']['content']['application/json']; export type AdminAccountsFindByEmailResponse = operations['admin___accounts___find-by-email']['responses']['200']['content']['application/json']; +export type AdminAccountsPendingListRequest = operations['admin___accounts___pending___list']['requestBody']['content']['application/json']; +export type AdminAccountsPendingListResponse = operations['admin___accounts___pending___list']['responses']['200']['content']['application/json']; +export type AdminAccountsPendingRevokeRequest = operations['admin___accounts___pending___revoke']['requestBody']['content']['application/json']; export type AdminAdCreateRequest = operations['admin___ad___create']['requestBody']['content']['application/json']; export type AdminAdCreateResponse = operations['admin___ad___create']['responses']['200']['content']['application/json']; export type AdminAdDeleteRequest = operations['admin___ad___delete']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index b2bca962f..a893d9cca 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -57,6 +57,24 @@ export type paths = { */ post: operations['admin___accounts___find-by-email']; }; + '/admin/accounts/pending/list': { + /** + * admin/accounts/pending/list + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:admin:account* + */ + post: operations['admin___accounts___pending___list']; + }; + '/admin/accounts/pending/revoke': { + /** + * admin/accounts/pending/revoke + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:admin:account* + */ + post: operations['admin___accounts___pending___revoke']; + }; '/admin/ad/create': { /** * admin/ad/create @@ -5538,6 +5556,135 @@ export type operations = { }; }; }; + /** + * admin/accounts/pending/list + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:admin:account* + */ + admin___accounts___pending___list: { + requestBody: { + content: { + 'application/json': { + /** @default 10 */ + limit?: number; + /** @default 0 */ + offset?: number; + /** @enum {string} */ + sort?: '+createdAt' | '-createdAt'; + /** @default null */ + username?: string | null; + /** @default null */ + email?: string | null; + /** @default null */ + code?: string | null; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': ({ + /** + * Format: id + * @example xxxxxxxxxx + */ + id: string; + /** Format: date-time */ + createdAt: string; + code: string; + /** @example ai */ + username: string; + email?: string | null; + })[]; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/accounts/pending/revoke + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:admin:account* + */ + admin___accounts___pending___revoke: { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id?: string; + code?: string; + }; + }; + }; + responses: { + /** @description OK (without any results) */ + 204: { + content: never; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; /** * admin/ad/create * @description No description provided.