diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
| commit | 0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch) | |
| tree | 40874799472fa07416f17b50a398ac33b7771905 /src/server/api/endpoints/admin | |
| parent | update deps (diff) | |
| download | sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2 sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip | |
refactoring
Resolve #7779
Diffstat (limited to 'src/server/api/endpoints/admin')
55 files changed, 0 insertions, 3635 deletions
diff --git a/src/server/api/endpoints/admin/abuse-user-reports.ts b/src/server/api/endpoints/admin/abuse-user-reports.ts deleted file mode 100644 index 403eb24191..0000000000 --- a/src/server/api/endpoints/admin/abuse-user-reports.ts +++ /dev/null @@ -1,134 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { AbuseUserReports } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - state: { - validator: $.optional.nullable.str, - default: null, - }, - - reporterOrigin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'combined' - }, - - targetUserOrigin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'combined' - }, - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - nullable: false as const, optional: false as const, - format: 'id', - example: 'xxxxxxxxxx', - }, - createdAt: { - type: 'string' as const, - nullable: false as const, optional: false as const, - format: 'date-time', - }, - comment: { - type: 'string' as const, - nullable: false as const, optional: false as const, - }, - resolved: { - type: 'boolean' as const, - nullable: false as const, optional: false as const, - example: false - }, - reporterId: { - type: 'string' as const, - nullable: false as const, optional: false as const, - format: 'id', - }, - targetUserId: { - type: 'string' as const, - nullable: false as const, optional: false as const, - format: 'id', - }, - assigneeId: { - type: 'string' as const, - nullable: true as const, optional: false as const, - format: 'id', - }, - reporter: { - type: 'object' as const, - nullable: false as const, optional: false as const, - ref: 'User' - }, - targetUser: { - type: 'object' as const, - nullable: false as const, optional: false as const, - ref: 'User' - }, - assignee: { - type: 'object' as const, - nullable: true as const, optional: true as const, - ref: 'User' - } - } - } - } -}; - -export default define(meta, async (ps) => { - const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId); - - switch (ps.state) { - case 'resolved': query.andWhere('report.resolved = TRUE'); break; - case 'unresolved': query.andWhere('report.resolved = FALSE'); break; - } - - switch (ps.reporterOrigin) { - case 'local': query.andWhere('report.reporterHost IS NULL'); break; - case 'remote': query.andWhere('report.reporterHost IS NOT NULL'); break; - } - - switch (ps.targetUserOrigin) { - case 'local': query.andWhere('report.targetUserHost IS NULL'); break; - case 'remote': query.andWhere('report.targetUserHost IS NOT NULL'); break; - } - - const reports = await query.take(ps.limit!).getMany(); - - return await AbuseUserReports.packMany(reports); -}); diff --git a/src/server/api/endpoints/admin/accounts/create.ts b/src/server/api/endpoints/admin/accounts/create.ts deleted file mode 100644 index fa15e84f77..0000000000 --- a/src/server/api/endpoints/admin/accounts/create.ts +++ /dev/null @@ -1,51 +0,0 @@ -import define from '../../../define'; -import { Users } from '@/models/index'; -import { signup } from '../../../common/signup'; - -export const meta = { - tags: ['admin'], - - params: { - username: { - validator: Users.validateLocalUsername, - }, - - password: { - validator: Users.validatePassword, - } - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - ref: 'User', - properties: { - token: { - type: 'string' as const, - optional: false as const, nullable: false as const, - } - } - } -}; - -export default define(meta, async (ps, _me) => { - const me = _me ? await Users.findOneOrFail(_me.id) : null; - const noUsers = (await Users.count({ - host: null, - })) === 0; - if (!noUsers && !me?.isAdmin) throw new Error('access denied'); - - const { account, secret } = await signup({ - username: ps.username, - password: ps.password, - }); - - const res = await Users.pack(account, account, { - detail: true, - includeSecrets: true - }); - - (res as any).token = secret; - - return res; -}); diff --git a/src/server/api/endpoints/admin/accounts/delete.ts b/src/server/api/endpoints/admin/accounts/delete.ts deleted file mode 100644 index 4e8a559805..0000000000 --- a/src/server/api/endpoints/admin/accounts/delete.ts +++ /dev/null @@ -1,58 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Users } from '@/models/index'; -import { doPostSuspend } from '@/services/suspend-user'; -import { publishUserEvent } from '@/services/stream'; -import { createDeleteAccountJob } from '@/queue'; -import { ID } from '@/misc/cafy-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const user = await Users.findOne(ps.userId); - - if (user == null) { - throw new Error('user not found'); - } - - if (user.isAdmin) { - throw new Error('cannot suspend admin'); - } - - if (user.isModerator) { - throw new Error('cannot suspend moderator'); - } - - if (Users.isLocalUser(user)) { - // 物理削除する前にDelete activityを送信する - await doPostSuspend(user).catch(e => {}); - - createDeleteAccountJob(user, { - soft: false - }); - } else { - createDeleteAccountJob(user, { - soft: true // リモートユーザーの削除は、完全にDBから物理削除してしまうと再度連合してきてアカウントが復活する可能性があるため、soft指定する - }); - } - - await Users.update(user.id, { - isDeleted: true, - }); - - if (Users.isLocalUser(user)) { - // Terminate streaming - publishUserEvent(user.id, 'terminate', {}); - } -}); diff --git a/src/server/api/endpoints/admin/ad/create.ts b/src/server/api/endpoints/admin/ad/create.ts deleted file mode 100644 index 27c7b5d318..0000000000 --- a/src/server/api/endpoints/admin/ad/create.ts +++ /dev/null @@ -1,49 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Ads } from '@/models/index'; -import { genId } from '@/misc/gen-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - url: { - validator: $.str.min(1) - }, - memo: { - validator: $.str - }, - place: { - validator: $.str - }, - priority: { - validator: $.str - }, - ratio: { - validator: $.num.int().min(0) - }, - expiresAt: { - validator: $.num.int() - }, - imageUrl: { - validator: $.str.min(1) - } - }, -}; - -export default define(meta, async (ps) => { - await Ads.insert({ - id: genId(), - createdAt: new Date(), - expiresAt: new Date(ps.expiresAt), - url: ps.url, - imageUrl: ps.imageUrl, - priority: ps.priority, - ratio: ps.ratio, - place: ps.place, - memo: ps.memo, - }); -}); diff --git a/src/server/api/endpoints/admin/ad/delete.ts b/src/server/api/endpoints/admin/ad/delete.ts deleted file mode 100644 index 91934e1aab..0000000000 --- a/src/server/api/endpoints/admin/ad/delete.ts +++ /dev/null @@ -1,34 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Ads } from '@/models/index'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - id: { - validator: $.type(ID) - } - }, - - errors: { - noSuchAd: { - message: 'No such ad.', - code: 'NO_SUCH_AD', - id: 'ccac9863-3a03-416e-b899-8a64041118b1' - } - } -}; - -export default define(meta, async (ps, me) => { - const ad = await Ads.findOne(ps.id); - - if (ad == null) throw new ApiError(meta.errors.noSuchAd); - - await Ads.delete(ad.id); -}); diff --git a/src/server/api/endpoints/admin/ad/list.ts b/src/server/api/endpoints/admin/ad/list.ts deleted file mode 100644 index 000aaaba9d..0000000000 --- a/src/server/api/endpoints/admin/ad/list.ts +++ /dev/null @@ -1,36 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Ads } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, -}; - -export default define(meta, async (ps) => { - const query = makePaginationQuery(Ads.createQueryBuilder('ad'), ps.sinceId, ps.untilId) - .andWhere('ad.expiresAt > :now', { now: new Date() }); - - const ads = await query.take(ps.limit!).getMany(); - - return ads; -}); diff --git a/src/server/api/endpoints/admin/ad/update.ts b/src/server/api/endpoints/admin/ad/update.ts deleted file mode 100644 index 36c87895c2..0000000000 --- a/src/server/api/endpoints/admin/ad/update.ts +++ /dev/null @@ -1,63 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Ads } from '@/models/index'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - id: { - validator: $.type(ID) - }, - memo: { - validator: $.str - }, - url: { - validator: $.str.min(1) - }, - imageUrl: { - validator: $.str.min(1) - }, - place: { - validator: $.str - }, - priority: { - validator: $.str - }, - ratio: { - validator: $.num.int().min(0) - }, - expiresAt: { - validator: $.num.int() - }, - }, - - errors: { - noSuchAd: { - message: 'No such ad.', - code: 'NO_SUCH_AD', - id: 'b7aa1727-1354-47bc-a182-3a9c3973d300' - } - } -}; - -export default define(meta, async (ps, me) => { - const ad = await Ads.findOne(ps.id); - - if (ad == null) throw new ApiError(meta.errors.noSuchAd); - - await Ads.update(ad.id, { - url: ps.url, - place: ps.place, - priority: ps.priority, - ratio: ps.ratio, - memo: ps.memo, - imageUrl: ps.imageUrl, - expiresAt: new Date(ps.expiresAt), - }); -}); diff --git a/src/server/api/endpoints/admin/announcements/create.ts b/src/server/api/endpoints/admin/announcements/create.ts deleted file mode 100644 index f1c07745f9..0000000000 --- a/src/server/api/endpoints/admin/announcements/create.ts +++ /dev/null @@ -1,71 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Announcements } from '@/models/index'; -import { genId } from '@/misc/gen-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - title: { - validator: $.str.min(1) - }, - text: { - validator: $.str.min(1) - }, - imageUrl: { - validator: $.nullable.str.min(1) - } - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id', - example: 'xxxxxxxxxx', - }, - createdAt: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'date-time', - }, - updatedAt: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'date-time', - }, - title: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - text: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - imageUrl: { - type: 'string' as const, - optional: false as const, nullable: true as const, - } - } - } -}; - -export default define(meta, async (ps) => { - const announcement = await Announcements.save({ - id: genId(), - createdAt: new Date(), - updatedAt: null, - title: ps.title, - text: ps.text, - imageUrl: ps.imageUrl, - }); - - return announcement; -}); diff --git a/src/server/api/endpoints/admin/announcements/delete.ts b/src/server/api/endpoints/admin/announcements/delete.ts deleted file mode 100644 index 7dbc05b4c9..0000000000 --- a/src/server/api/endpoints/admin/announcements/delete.ts +++ /dev/null @@ -1,34 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Announcements } from '@/models/index'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - id: { - validator: $.type(ID) - } - }, - - errors: { - noSuchAnnouncement: { - message: 'No such announcement.', - code: 'NO_SUCH_ANNOUNCEMENT', - id: 'ecad8040-a276-4e85-bda9-015a708d291e' - } - } -}; - -export default define(meta, async (ps, me) => { - const announcement = await Announcements.findOne(ps.id); - - if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); - - await Announcements.delete(announcement.id); -}); diff --git a/src/server/api/endpoints/admin/announcements/list.ts b/src/server/api/endpoints/admin/announcements/list.ts deleted file mode 100644 index 4039bcd88f..0000000000 --- a/src/server/api/endpoints/admin/announcements/list.ts +++ /dev/null @@ -1,84 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Announcements, AnnouncementReads } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id', - example: 'xxxxxxxxxx', - }, - createdAt: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'date-time', - }, - updatedAt: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'date-time', - }, - text: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - title: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - imageUrl: { - type: 'string' as const, - optional: false as const, nullable: true as const, - }, - reads: { - type: 'number' as const, - optional: false as const, nullable: false as const, - } - } - } - } -}; - -export default define(meta, async (ps) => { - const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); - - const announcements = await query.take(ps.limit!).getMany(); - - for (const announcement of announcements) { - (announcement as any).reads = await AnnouncementReads.count({ - announcementId: announcement.id - }); - } - - return announcements; -}); diff --git a/src/server/api/endpoints/admin/announcements/update.ts b/src/server/api/endpoints/admin/announcements/update.ts deleted file mode 100644 index 343f37d626..0000000000 --- a/src/server/api/endpoints/admin/announcements/update.ts +++ /dev/null @@ -1,48 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Announcements } from '@/models/index'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - id: { - validator: $.type(ID) - }, - title: { - validator: $.str.min(1) - }, - text: { - validator: $.str.min(1) - }, - imageUrl: { - validator: $.nullable.str.min(1) - } - }, - - errors: { - noSuchAnnouncement: { - message: 'No such announcement.', - code: 'NO_SUCH_ANNOUNCEMENT', - id: 'd3aae5a7-6372-4cb4-b61c-f511ffc2d7cc' - } - } -}; - -export default define(meta, async (ps, me) => { - const announcement = await Announcements.findOne(ps.id); - - if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); - - await Announcements.update(announcement.id, { - updatedAt: new Date(), - title: ps.title, - text: ps.text, - imageUrl: ps.imageUrl, - }); -}); diff --git a/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts b/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts deleted file mode 100644 index 988ab29558..0000000000 --- a/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts +++ /dev/null @@ -1,28 +0,0 @@ -import $ from 'cafy'; -import define from '../../define'; -import { deleteFile } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const files = await DriveFiles.find({ - userId: ps.userId - }); - - for (const file of files) { - deleteFile(file); - } -}); diff --git a/src/server/api/endpoints/admin/delete-logs.ts b/src/server/api/endpoints/admin/delete-logs.ts deleted file mode 100644 index 9d37ceb434..0000000000 --- a/src/server/api/endpoints/admin/delete-logs.ts +++ /dev/null @@ -1,13 +0,0 @@ -import define from '../../define'; -import { Logs } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, -}; - -export default define(meta, async (ps) => { - await Logs.clear(); // TRUNCATE -}); diff --git a/src/server/api/endpoints/admin/drive/clean-remote-files.ts b/src/server/api/endpoints/admin/drive/clean-remote-files.ts deleted file mode 100644 index 76a6acff59..0000000000 --- a/src/server/api/endpoints/admin/drive/clean-remote-files.ts +++ /dev/null @@ -1,13 +0,0 @@ -import define from '../../../define'; -import { createCleanRemoteFilesJob } from '@/queue/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, -}; - -export default define(meta, async (ps, me) => { - createCleanRemoteFilesJob(); -}); diff --git a/src/server/api/endpoints/admin/drive/cleanup.ts b/src/server/api/endpoints/admin/drive/cleanup.ts deleted file mode 100644 index 8497478da9..0000000000 --- a/src/server/api/endpoints/admin/drive/cleanup.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IsNull } from 'typeorm'; -import define from '../../../define'; -import { deleteFile } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, -}; - -export default define(meta, async (ps, me) => { - const files = await DriveFiles.find({ - userId: IsNull() - }); - - for (const file of files) { - deleteFile(file); - } -}); diff --git a/src/server/api/endpoints/admin/drive/files.ts b/src/server/api/endpoints/admin/drive/files.ts deleted file mode 100644 index fe1c799805..0000000000 --- a/src/server/api/endpoints/admin/drive/files.ts +++ /dev/null @@ -1,81 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { DriveFiles } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; -import { ID } from '@/misc/cafy-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: false as const, - requireModerator: true, - - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - type: { - validator: $.optional.nullable.str.match(/^[a-zA-Z0-9\/\-*]+$/) - }, - - origin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'local' - }, - - hostname: { - validator: $.optional.nullable.str, - default: null - }, - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - ref: 'DriveFile' - } - } -}; - -export default define(meta, async (ps, me) => { - const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId); - - if (ps.origin === 'local') { - query.andWhere('file.userHost IS NULL'); - } else if (ps.origin === 'remote') { - query.andWhere('file.userHost IS NOT NULL'); - } - - if (ps.hostname) { - query.andWhere('file.userHost = :hostname', { hostname: ps.hostname }); - } - - if (ps.type) { - if (ps.type.endsWith('/*')) { - query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' }); - } else { - query.andWhere('file.type = :type', { type: ps.type }); - } - } - - const files = await query.take(ps.limit!).getMany(); - - return await DriveFiles.packMany(files, { detail: true, withUser: true, self: true }); -}); diff --git a/src/server/api/endpoints/admin/drive/show-file.ts b/src/server/api/endpoints/admin/drive/show-file.ts deleted file mode 100644 index 270b89c4fa..0000000000 --- a/src/server/api/endpoints/admin/drive/show-file.ts +++ /dev/null @@ -1,180 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFiles } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - fileId: { - validator: $.optional.type(ID), - }, - - url: { - validator: $.optional.str, - }, - }, - - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'caf3ca38-c6e5-472e-a30c-b05377dcc240' - } - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id', - example: 'xxxxxxxxxx', - }, - createdAt: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'date-time', - }, - userId: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'id', - example: 'xxxxxxxxxx', - }, - userHost: { - type: 'string' as const, - optional: false as const, nullable: true as const - }, - md5: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'md5', - example: '15eca7fba0480996e2245f5185bf39f2' - }, - name: { - type: 'string' as const, - optional: false as const, nullable: false as const, - example: 'lenna.jpg' - }, - type: { - type: 'string' as const, - optional: false as const, nullable: false as const, - example: 'image/jpeg' - }, - size: { - type: 'number' as const, - optional: false as const, nullable: false as const, - example: 51469 - }, - comment: { - type: 'string' as const, - optional: false as const, nullable: true as const - }, - blurhash: { - type: 'string' as const, - optional: false as const, nullable: true as const - }, - properties: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - width: { - type: 'number' as const, - optional: false as const, nullable: false as const, - example: 1280 - }, - height: { - type: 'number' as const, - optional: false as const, nullable: false as const, - example: 720 - }, - avgColor: { - type: 'string' as const, - optional: true as const, nullable: false as const, - example: 'rgb(40,65,87)' - } - } - }, - storedInternal: { - type: 'boolean' as const, - optional: false as const, nullable: true as const, - example: true - }, - url: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'url', - }, - thumbnailUrl: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'url', - }, - webpublicUrl: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'url', - }, - accessKey: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - thumbnailAccessKey: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - webpublicAccessKey: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - uri: { - type: 'string' as const, - optional: false as const, nullable: true as const - }, - src: { - type: 'string' as const, - optional: false as const, nullable: true as const - }, - folderId: { - type: 'string' as const, - optional: false as const, nullable: true as const, - format: 'id', - example: 'xxxxxxxxxx', - }, - isSensitive: { - type: 'boolean' as const, - optional: false as const, nullable: false as const, - }, - isLink: { - type: 'boolean' as const, - optional: false as const, nullable: false as const - } - } - } -}; - -export default define(meta, async (ps, me) => { - const file = ps.fileId ? await DriveFiles.findOne(ps.fileId) : await DriveFiles.findOne({ - where: [{ - url: ps.url - }, { - thumbnailUrl: ps.url - }, { - webpublicUrl: ps.url - }] - }); - - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } - - return file; -}); diff --git a/src/server/api/endpoints/admin/emoji/add.ts b/src/server/api/endpoints/admin/emoji/add.ts deleted file mode 100644 index 1af81fe46d..0000000000 --- a/src/server/api/endpoints/admin/emoji/add.ts +++ /dev/null @@ -1,64 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis, DriveFiles } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { getConnection } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { ApiError } from '../../../error'; -import { ID } from '@/misc/cafy-id'; -import rndstr from 'rndstr'; -import { publishBroadcastStream } from '@/services/stream'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - fileId: { - validator: $.type(ID) - }, - }, - - errors: { - noSuchFile: { - message: 'No such file.', - code: 'MO_SUCH_FILE', - id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf' - } - } -}; - -export default define(meta, async (ps, me) => { - const file = await DriveFiles.findOne(ps.fileId); - - if (file == null) throw new ApiError(meta.errors.noSuchFile); - - const name = file.name.split('.')[0].match(/^[a-z0-9_]+$/) ? file.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`; - - const emoji = await Emojis.save({ - id: genId(), - updatedAt: new Date(), - name: name, - category: null, - host: null, - aliases: [], - url: file.url, - type: file.type, - }); - - await getConnection().queryResultCache!.remove(['meta_emojis']); - - publishBroadcastStream('emojiAdded', { - emoji: await Emojis.pack(emoji.id) - }); - - insertModerationLog(me, 'addEmoji', { - emojiId: emoji.id - }); - - return { - id: emoji.id - }; -}); diff --git a/src/server/api/endpoints/admin/emoji/copy.ts b/src/server/api/endpoints/admin/emoji/copy.ts deleted file mode 100644 index 4c8ab99f7c..0000000000 --- a/src/server/api/endpoints/admin/emoji/copy.ts +++ /dev/null @@ -1,81 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { getConnection } from 'typeorm'; -import { ApiError } from '../../../error'; -import { DriveFile } from '@/models/entities/drive-file'; -import { ID } from '@/misc/cafy-id'; -import uploadFromUrl from '@/services/drive/upload-from-url'; -import { publishBroadcastStream } from '@/services/stream'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - emojiId: { - validator: $.type(ID) - }, - }, - - errors: { - noSuchEmoji: { - message: 'No such emoji.', - code: 'NO_SUCH_EMOJI', - id: 'e2785b66-dca3-4087-9cac-b93c541cc425' - } - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id', - } - } - } -}; - -export default define(meta, async (ps, me) => { - const emoji = await Emojis.findOne(ps.emojiId); - - if (emoji == null) { - throw new ApiError(meta.errors.noSuchEmoji); - } - - let driveFile: DriveFile; - - try { - // Create file - driveFile = await uploadFromUrl(emoji.url, null, null, null, false, true); - } catch (e) { - throw new ApiError(); - } - - const copied = await Emojis.insert({ - id: genId(), - updatedAt: new Date(), - name: emoji.name, - host: null, - aliases: [], - url: driveFile.url, - type: driveFile.type, - fileId: driveFile.id, - }).then(x => Emojis.findOneOrFail(x.identifiers[0])); - - await getConnection().queryResultCache!.remove(['meta_emojis']); - - publishBroadcastStream('emojiAdded', { - emoji: await Emojis.pack(copied.id) - }); - - return { - id: copied.id - }; -}); diff --git a/src/server/api/endpoints/admin/emoji/list-remote.ts b/src/server/api/endpoints/admin/emoji/list-remote.ts deleted file mode 100644 index 3c8ca22170..0000000000 --- a/src/server/api/endpoints/admin/emoji/list-remote.ts +++ /dev/null @@ -1,99 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; -import { ID } from '@/misc/cafy-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - query: { - validator: $.optional.nullable.str, - default: null - }, - - host: { - validator: $.optional.nullable.str, - default: null - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - } - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id', - }, - aliases: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'string' as const, - optional: false as const, nullable: false as const - } - }, - name: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - category: { - type: 'string' as const, - optional: false as const, nullable: true as const, - }, - host: { - type: 'string' as const, - optional: false as const, nullable: true as const, - }, - url: { - type: 'string' as const, - optional: false as const, nullable: false as const, - } - } - } - } -}; - -export default define(meta, async (ps) => { - const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId); - - if (ps.host == null) { - q.andWhere(`emoji.host IS NOT NULL`); - } else { - q.andWhere(`emoji.host = :host`, { host: toPuny(ps.host) }); - } - - if (ps.query) { - q.andWhere('emoji.name like :query', { query: '%' + ps.query + '%' }); - } - - const emojis = await q - .orderBy('emoji.id', 'DESC') - .take(ps.limit!) - .getMany(); - - return Emojis.packMany(emojis); -}); diff --git a/src/server/api/endpoints/admin/emoji/list.ts b/src/server/api/endpoints/admin/emoji/list.ts deleted file mode 100644 index cb1e79e0fe..0000000000 --- a/src/server/api/endpoints/admin/emoji/list.ts +++ /dev/null @@ -1,98 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; -import { ID } from '@/misc/cafy-id'; -import { Emoji } from '@/models/entities/emoji'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - query: { - validator: $.optional.nullable.str, - default: null - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - } - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id', - }, - aliases: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'string' as const, - optional: false as const, nullable: false as const - } - }, - name: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - category: { - type: 'string' as const, - optional: false as const, nullable: true as const, - }, - host: { - type: 'string' as const, - optional: false as const, nullable: true as const, - }, - url: { - type: 'string' as const, - optional: false as const, nullable: false as const, - } - } - } - } -}; - -export default define(meta, async (ps) => { - const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId) - .andWhere(`emoji.host IS NULL`); - - let emojis: Emoji[]; - - if (ps.query) { - //q.andWhere('emoji.name ILIKE :q', { q: `%${ps.query}%` }); - //const emojis = await q.take(ps.limit!).getMany(); - - emojis = await q.getMany(); - - emojis = emojis.filter(emoji => - emoji.name.includes(ps.query!) || - emoji.aliases.some(a => a.includes(ps.query!)) || - emoji.category?.includes(ps.query!)); - - emojis.splice(ps.limit! + 1); - } else { - emojis = await q.take(ps.limit!).getMany(); - } - - return Emojis.packMany(emojis); -}); diff --git a/src/server/api/endpoints/admin/emoji/remove.ts b/src/server/api/endpoints/admin/emoji/remove.ts deleted file mode 100644 index 259950e362..0000000000 --- a/src/server/api/endpoints/admin/emoji/remove.ts +++ /dev/null @@ -1,42 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; -import { getConnection } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - id: { - validator: $.type(ID) - } - }, - - errors: { - noSuchEmoji: { - message: 'No such emoji.', - code: 'NO_SUCH_EMOJI', - id: 'be83669b-773a-44b7-b1f8-e5e5170ac3c2' - } - } -}; - -export default define(meta, async (ps, me) => { - const emoji = await Emojis.findOne(ps.id); - - if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); - - await Emojis.delete(emoji.id); - - await getConnection().queryResultCache!.remove(['meta_emojis']); - - insertModerationLog(me, 'removeEmoji', { - emoji: emoji - }); -}); diff --git a/src/server/api/endpoints/admin/emoji/update.ts b/src/server/api/endpoints/admin/emoji/update.ts deleted file mode 100644 index 3fd547d7e5..0000000000 --- a/src/server/api/endpoints/admin/emoji/update.ts +++ /dev/null @@ -1,54 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; -import { getConnection } from 'typeorm'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - id: { - validator: $.type(ID) - }, - - name: { - validator: $.str - }, - - category: { - validator: $.optional.nullable.str - }, - - aliases: { - validator: $.arr($.str) - } - }, - - errors: { - noSuchEmoji: { - message: 'No such emoji.', - code: 'NO_SUCH_EMOJI', - id: '684dec9d-a8c2-4364-9aa8-456c49cb1dc8' - } - } -}; - -export default define(meta, async (ps) => { - const emoji = await Emojis.findOne(ps.id); - - if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); - - await Emojis.update(emoji.id, { - updatedAt: new Date(), - name: ps.name, - category: ps.category, - aliases: ps.aliases, - }); - - await getConnection().queryResultCache!.remove(['meta_emojis']); -}); diff --git a/src/server/api/endpoints/admin/federation/delete-all-files.ts b/src/server/api/endpoints/admin/federation/delete-all-files.ts deleted file mode 100644 index 82540c5447..0000000000 --- a/src/server/api/endpoints/admin/federation/delete-all-files.ts +++ /dev/null @@ -1,27 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { deleteFile } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - host: { - validator: $.str - } - } -}; - -export default define(meta, async (ps, me) => { - const files = await DriveFiles.find({ - userHost: ps.host - }); - - for (const file of files) { - deleteFile(file); - } -}); diff --git a/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts b/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts deleted file mode 100644 index 65a6947ba0..0000000000 --- a/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts +++ /dev/null @@ -1,28 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Instances } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; -import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - host: { - validator: $.str - }, - } -}; - -export default define(meta, async (ps, me) => { - const instance = await Instances.findOne({ host: toPuny(ps.host) }); - - if (instance == null) { - throw new Error('instance not found'); - } - - fetchInstanceMetadata(instance, true); -}); diff --git a/src/server/api/endpoints/admin/federation/remove-all-following.ts b/src/server/api/endpoints/admin/federation/remove-all-following.ts deleted file mode 100644 index 7935eaa631..0000000000 --- a/src/server/api/endpoints/admin/federation/remove-all-following.ts +++ /dev/null @@ -1,32 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import deleteFollowing from '@/services/following/delete'; -import { Followings, Users } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - host: { - validator: $.str - } - } -}; - -export default define(meta, async (ps, me) => { - const followings = await Followings.find({ - followerHost: ps.host - }); - - const pairs = await Promise.all(followings.map(f => Promise.all([ - Users.findOneOrFail(f.followerId), - Users.findOneOrFail(f.followeeId) - ]))); - - for (const pair of pairs) { - deleteFollowing(pair[0], pair[1]); - } -}); diff --git a/src/server/api/endpoints/admin/federation/update-instance.ts b/src/server/api/endpoints/admin/federation/update-instance.ts deleted file mode 100644 index 34eab27c78..0000000000 --- a/src/server/api/endpoints/admin/federation/update-instance.ts +++ /dev/null @@ -1,33 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Instances } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - host: { - validator: $.str - }, - - isSuspended: { - validator: $.bool - }, - } -}; - -export default define(meta, async (ps, me) => { - const instance = await Instances.findOne({ host: toPuny(ps.host) }); - - if (instance == null) { - throw new Error('instance not found'); - } - - Instances.update({ host: toPuny(ps.host) }, { - isSuspended: ps.isSuspended - }); -}); diff --git a/src/server/api/endpoints/admin/get-index-stats.ts b/src/server/api/endpoints/admin/get-index-stats.ts deleted file mode 100644 index f2b06d0ef2..0000000000 --- a/src/server/api/endpoints/admin/get-index-stats.ts +++ /dev/null @@ -1,26 +0,0 @@ -import define from '../../define'; -import { getConnection } from 'typeorm'; - -export const meta = { - requireCredential: true as const, - requireModerator: true, - - tags: ['admin'], - - params: { - }, -}; - -export default define(meta, async () => { - const stats = await - getConnection().query(`SELECT * FROM pg_indexes;`) - .then(recs => { - const res = [] as { tablename: string; indexname: string; }[]; - for (const rec of recs) { - res.push(rec); - } - return res; - }); - - return stats; -}); diff --git a/src/server/api/endpoints/admin/get-table-stats.ts b/src/server/api/endpoints/admin/get-table-stats.ts deleted file mode 100644 index bce813232b..0000000000 --- a/src/server/api/endpoints/admin/get-table-stats.ts +++ /dev/null @@ -1,45 +0,0 @@ -import define from '../../define'; -import { getConnection } from 'typeorm'; - -export const meta = { - requireCredential: true as const, - requireModerator: true, - - tags: ['admin'], - - params: { - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - example: { - migrations: { - count: 66, - size: 32768 - }, - } - } -}; - -export default define(meta, async () => { - const sizes = await - getConnection().query(` - SELECT relname AS "table", reltuples as "count", pg_total_relation_size(C.oid) AS "size" - FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) - WHERE nspname NOT IN ('pg_catalog', 'information_schema') - AND C.relkind <> 'i' - AND nspname !~ '^pg_toast';`) - .then(recs => { - const res = {} as Record<string, { count: number; size: number; }>; - for (const rec of recs) { - res[rec.table] = { - count: parseInt(rec.count, 10), - size: parseInt(rec.size, 10), - }; - } - return res; - }); - - return sizes; -}); diff --git a/src/server/api/endpoints/admin/invite.ts b/src/server/api/endpoints/admin/invite.ts deleted file mode 100644 index 2c69eec535..0000000000 --- a/src/server/api/endpoints/admin/invite.ts +++ /dev/null @@ -1,44 +0,0 @@ -import rndstr from 'rndstr'; -import define from '../../define'; -import { RegistrationTickets } from '@/models/index'; -import { genId } from '@/misc/gen-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: {}, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - code: { - type: 'string' as const, - optional: false as const, nullable: false as const, - example: '2ERUA5VR', - maxLength: 8, - minLength: 8 - } - } - } -}; - -export default define(meta, async () => { - const code = rndstr({ - length: 8, - chars: '2-9A-HJ-NP-Z', // [0-9A-Z] w/o [01IO] (32 patterns) - }); - - await RegistrationTickets.insert({ - id: genId(), - createdAt: new Date(), - code, - }); - - return { - code, - }; -}); diff --git a/src/server/api/endpoints/admin/moderators/add.ts b/src/server/api/endpoints/admin/moderators/add.ts deleted file mode 100644 index 2b87fc217f..0000000000 --- a/src/server/api/endpoints/admin/moderators/add.ts +++ /dev/null @@ -1,33 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Users } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireAdmin: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - if (user.isAdmin) { - throw new Error('cannot mark as moderator if admin user'); - } - - await Users.update(user.id, { - isModerator: true - }); -}); diff --git a/src/server/api/endpoints/admin/moderators/remove.ts b/src/server/api/endpoints/admin/moderators/remove.ts deleted file mode 100644 index cbb0625224..0000000000 --- a/src/server/api/endpoints/admin/moderators/remove.ts +++ /dev/null @@ -1,29 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Users } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireAdmin: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - await Users.update(user.id, { - isModerator: false - }); -}); diff --git a/src/server/api/endpoints/admin/promo/create.ts b/src/server/api/endpoints/admin/promo/create.ts deleted file mode 100644 index 3bdaaad4d9..0000000000 --- a/src/server/api/endpoints/admin/promo/create.ts +++ /dev/null @@ -1,57 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getNote } from '../../../common/getters'; -import { PromoNotes } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - noteId: { - validator: $.type(ID), - }, - - expiresAt: { - validator: $.num.int() - }, - }, - - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'ee449fbe-af2a-453b-9cae-cf2fe7c895fc' - }, - - alreadyPromoted: { - message: 'The note has already promoted.', - code: 'ALREADY_PROMOTED', - id: 'ae427aa2-7a41-484f-a18c-2c1104051604' - }, - } -}; - -export default define(meta, async (ps, user) => { - const note = await getNote(ps.noteId).catch(e => { - if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw e; - }); - - const exist = await PromoNotes.findOne(note.id); - - if (exist != null) { - throw new ApiError(meta.errors.alreadyPromoted); - } - - await PromoNotes.insert({ - noteId: note.id, - createdAt: new Date(), - expiresAt: new Date(ps.expiresAt), - userId: note.userId, - }); -}); diff --git a/src/server/api/endpoints/admin/queue/clear.ts b/src/server/api/endpoints/admin/queue/clear.ts deleted file mode 100644 index fedb7065ab..0000000000 --- a/src/server/api/endpoints/admin/queue/clear.ts +++ /dev/null @@ -1,18 +0,0 @@ -import define from '../../../define'; -import { destroy } from '@/queue/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: {} -}; - -export default define(meta, async (ps, me) => { - destroy(); - - insertModerationLog(me, 'clearQueue'); -}); diff --git a/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/src/server/api/endpoints/admin/queue/deliver-delayed.ts deleted file mode 100644 index cd7b640983..0000000000 --- a/src/server/api/endpoints/admin/queue/deliver-delayed.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { deliverQueue } from '@/queue/queues'; -import { URL } from 'url'; -import define from '../../../define'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - anyOf: [ - { - type: 'string' as const, - }, - { - type: 'number' as const, - } - ] - } - }, - example: [[ - 'example.com', - 12 - ]] - } -}; - -export default define(meta, async (ps) => { - const jobs = await deliverQueue.getJobs(['delayed']); - - const res = [] as [string, number][]; - - for (const job of jobs) { - const host = new URL(job.data.to).host; - if (res.find(x => x[0] === host)) { - res.find(x => x[0] === host)![1]++; - } else { - res.push([host, 1]); - } - } - - res.sort((a, b) => b[1] - a[1]); - - return res; -}); diff --git a/src/server/api/endpoints/admin/queue/inbox-delayed.ts b/src/server/api/endpoints/admin/queue/inbox-delayed.ts deleted file mode 100644 index 1925906c28..0000000000 --- a/src/server/api/endpoints/admin/queue/inbox-delayed.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { URL } from 'url'; -import define from '../../../define'; -import { inboxQueue } from '@/queue/queues'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - anyOf: [ - { - type: 'string' as const, - }, - { - type: 'number' as const, - } - ] - } - }, - example: [[ - 'example.com', - 12 - ]] - } -}; - -export default define(meta, async (ps) => { - const jobs = await inboxQueue.getJobs(['delayed']); - - const res = [] as [string, number][]; - - for (const job of jobs) { - const host = new URL(job.data.signature.keyId).host; - if (res.find(x => x[0] === host)) { - res.find(x => x[0] === host)![1]++; - } else { - res.push([host, 1]); - } - } - - res.sort((a, b) => b[1] - a[1]); - - return res; -}); diff --git a/src/server/api/endpoints/admin/queue/jobs.ts b/src/server/api/endpoints/admin/queue/jobs.ts deleted file mode 100644 index c426e5f39b..0000000000 --- a/src/server/api/endpoints/admin/queue/jobs.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues'; -import $ from 'cafy'; -import define from '../../../define'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - domain: { - validator: $.str.or(['deliver', 'inbox', 'db', 'objectStorage']), - }, - - state: { - validator: $.str.or(['active', 'waiting', 'delayed']), - }, - - limit: { - validator: $.optional.num, - default: 50 - }, - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id' - }, - data: { - type: 'object' as const, - optional: false as const, nullable: false as const - }, - attempts: { - type: 'number' as const, - optional: false as const, nullable: false as const - }, - maxAttempts: { - type: 'number' as const, - optional: false as const, nullable: false as const - }, - timestamp: { - type: 'number' as const, - optional: false as const, nullable: false as const - } - } - } - } -}; - -export default define(meta, async (ps) => { - const queue = - ps.domain === 'deliver' ? deliverQueue : - ps.domain === 'inbox' ? inboxQueue : - ps.domain === 'db' ? dbQueue : - ps.domain === 'objectStorage' ? objectStorageQueue : - null as never; - - const jobs = await queue.getJobs([ps.state], 0, ps.limit!); - - return jobs.map(job => { - const data = job.data; - delete data.content; - delete data.user; - return { - id: job.id, - data, - attempts: job.attemptsMade, - maxAttempts: job.opts ? job.opts.attempts : 0, - timestamp: job.timestamp, - }; - }); -}); diff --git a/src/server/api/endpoints/admin/queue/stats.ts b/src/server/api/endpoints/admin/queue/stats.ts deleted file mode 100644 index 38f18459dd..0000000000 --- a/src/server/api/endpoints/admin/queue/stats.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues'; -import define from '../../../define'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: {}, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - deliver: { - ref: 'QueueCount' - }, - inbox: { - ref: 'QueueCount' - }, - db: { - ref: 'QueueCount' - }, - objectStorage: { - ref: 'QueueCount' - } - } - } -}; - -export default define(meta, async (ps) => { - const deliverJobCounts = await deliverQueue.getJobCounts(); - const inboxJobCounts = await inboxQueue.getJobCounts(); - const dbJobCounts = await dbQueue.getJobCounts(); - const objectStorageJobCounts = await objectStorageQueue.getJobCounts(); - - return { - deliver: deliverJobCounts, - inbox: inboxJobCounts, - db: dbJobCounts, - objectStorage: objectStorageJobCounts, - }; -}); diff --git a/src/server/api/endpoints/admin/relays/add.ts b/src/server/api/endpoints/admin/relays/add.ts deleted file mode 100644 index 567035fd3a..0000000000 --- a/src/server/api/endpoints/admin/relays/add.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { URL } from 'url'; -import $ from 'cafy'; -import define from '../../../define'; -import { addRelay } from '@/services/relay'; -import { ApiError } from '../../../error'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true as const, - - params: { - inbox: { - validator: $.str - }, - }, - - errors: { - invalidUrl: { - message: 'Invalid URL', - code: 'INVALID_URL', - id: 'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c' - }, - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id' - }, - inbox: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'url' - }, - status: { - type: 'string' as const, - optional: false as const, nullable: false as const, - default: 'requesting', - enum: [ - 'requesting', - 'accepted', - 'rejected' - ] - } - } - } -}; - -export default define(meta, async (ps, user) => { - try { - if (new URL(ps.inbox).protocol !== 'https:') throw 'https only'; - } catch { - throw new ApiError(meta.errors.invalidUrl); - } - - return await addRelay(ps.inbox); -}); diff --git a/src/server/api/endpoints/admin/relays/list.ts b/src/server/api/endpoints/admin/relays/list.ts deleted file mode 100644 index 031ebe85d0..0000000000 --- a/src/server/api/endpoints/admin/relays/list.ts +++ /dev/null @@ -1,47 +0,0 @@ -import define from '../../../define'; -import { listRelay } from '@/services/relay'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true as const, - - params: { - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id' - }, - inbox: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'url' - }, - status: { - type: 'string' as const, - optional: false as const, nullable: false as const, - default: 'requesting', - enum: [ - 'requesting', - 'accepted', - 'rejected' - ] - } - } - } - } -}; - -export default define(meta, async (ps, user) => { - return await listRelay(); -}); diff --git a/src/server/api/endpoints/admin/relays/remove.ts b/src/server/api/endpoints/admin/relays/remove.ts deleted file mode 100644 index c1c50f5dc0..0000000000 --- a/src/server/api/endpoints/admin/relays/remove.ts +++ /dev/null @@ -1,20 +0,0 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { removeRelay } from '@/services/relay'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true as const, - - params: { - inbox: { - validator: $.str - }, - }, -}; - -export default define(meta, async (ps, user) => { - return await removeRelay(ps.inbox); -}); diff --git a/src/server/api/endpoints/admin/reset-password.ts b/src/server/api/endpoints/admin/reset-password.ts deleted file mode 100644 index 0fc2c6a868..0000000000 --- a/src/server/api/endpoints/admin/reset-password.ts +++ /dev/null @@ -1,59 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import * as bcrypt from 'bcryptjs'; -import rndstr from 'rndstr'; -import { Users, UserProfiles } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - password: { - type: 'string' as const, - optional: false as const, nullable: false as const, - minLength: 8, - maxLength: 8 - } - } - } -}; - -export default define(meta, async (ps) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - if (user.isAdmin) { - throw new Error('cannot reset password of admin'); - } - - const passwd = rndstr('a-zA-Z0-9', 8); - - // Generate hash of password - const hash = bcrypt.hashSync(passwd); - - await UserProfiles.update({ - userId: user.id - }, { - password: hash - }); - - return { - password: passwd - }; -}); diff --git a/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/src/server/api/endpoints/admin/resolve-abuse-user-report.ts deleted file mode 100644 index 7b71f8e000..0000000000 --- a/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ /dev/null @@ -1,30 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { AbuseUserReports } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - reportId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const report = await AbuseUserReports.findOne(ps.reportId); - - if (report == null) { - throw new Error('report not found'); - } - - await AbuseUserReports.update(report.id, { - resolved: true, - assigneeId: me.id, - }); -}); diff --git a/src/server/api/endpoints/admin/resync-chart.ts b/src/server/api/endpoints/admin/resync-chart.ts deleted file mode 100644 index e01dfce1b6..0000000000 --- a/src/server/api/endpoints/admin/resync-chart.ts +++ /dev/null @@ -1,21 +0,0 @@ -import define from '../../define'; -import { driveChart, notesChart, usersChart } from '@/services/chart/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, -}; - -export default define(meta, async (ps, me) => { - insertModerationLog(me, 'chartResync'); - - driveChart.resync(); - notesChart.resync(); - usersChart.resync(); - - // TODO: ユーザーごとのチャートもキューに入れて更新する - // TODO: インスタンスごとのチャートもキューに入れて更新する -}); diff --git a/src/server/api/endpoints/admin/send-email.ts b/src/server/api/endpoints/admin/send-email.ts deleted file mode 100644 index 6f67b78542..0000000000 --- a/src/server/api/endpoints/admin/send-email.ts +++ /dev/null @@ -1,26 +0,0 @@ -import $ from 'cafy'; -import define from '../../define'; -import { sendEmail } from '@/services/send-email'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - to: { - validator: $.str, - }, - subject: { - validator: $.str, - }, - text: { - validator: $.str, - }, - } -}; - -export default define(meta, async (ps) => { - await sendEmail(ps.to, ps.subject, ps.text, ps.text); -}); diff --git a/src/server/api/endpoints/admin/server-info.ts b/src/server/api/endpoints/admin/server-info.ts deleted file mode 100644 index bb2d35e397..0000000000 --- a/src/server/api/endpoints/admin/server-info.ts +++ /dev/null @@ -1,119 +0,0 @@ -import * as os from 'os'; -import * as si from 'systeminformation'; -import { getConnection } from 'typeorm'; -import define from '../../define'; -import { redisClient } from '../../../../db/redis'; - -export const meta = { - requireCredential: true as const, - requireModerator: true, - - tags: ['admin', 'meta'], - - params: { - }, - - res: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - machine: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - os: { - type: 'string' as const, - optional: false as const, nullable: false as const, - example: 'linux' - }, - node: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - psql: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - cpu: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - model: { - type: 'string' as const, - optional: false as const, nullable: false as const, - }, - cores: { - type: 'number' as const, - optional: false as const, nullable: false as const, - } - } - }, - mem: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - total: { - type: 'number' as const, - optional: false as const, nullable: false as const, - format: 'bytes', - } - } - }, - fs: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - total: { - type: 'number' as const, - optional: false as const, nullable: false as const, - format: 'bytes', - }, - used: { - type: 'number' as const, - optional: false as const, nullable: false as const, - format: 'bytes', - } - } - }, - net: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - interface: { - type: 'string' as const, - optional: false as const, nullable: false as const, - example: 'eth0' - } - } - } - } - } -}; - -export default define(meta, async () => { - const memStats = await si.mem(); - const fsStats = await si.fsSize(); - const netInterface = await si.networkInterfaceDefault(); - - return { - machine: os.hostname(), - os: os.platform(), - node: process.version, - psql: await getConnection().query('SHOW server_version').then(x => x[0].server_version), - redis: redisClient.server_info.redis_version, - cpu: { - model: os.cpus()[0].model, - cores: os.cpus().length - }, - mem: { - total: memStats.total - }, - fs: { - total: fsStats[0].size, - used: fsStats[0].used, - }, - net: { - interface: netInterface - } - }; -}); diff --git a/src/server/api/endpoints/admin/show-moderation-logs.ts b/src/server/api/endpoints/admin/show-moderation-logs.ts deleted file mode 100644 index e9509568d0..0000000000 --- a/src/server/api/endpoints/admin/show-moderation-logs.ts +++ /dev/null @@ -1,74 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ModerationLogs } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - - res: { - type: 'array' as const, - optional: false as const, nullable: false as const, - items: { - type: 'object' as const, - optional: false as const, nullable: false as const, - properties: { - id: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id' - }, - createdAt: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'date-time' - }, - type: { - type: 'string' as const, - optional: false as const, nullable: false as const - }, - info: { - type: 'object' as const, - optional: false as const, nullable: false as const - }, - userId: { - type: 'string' as const, - optional: false as const, nullable: false as const, - format: 'id' - }, - user: { - type: 'object' as const, - optional: false as const, nullable: false as const, - ref: 'User' - } - } - } - } -}; - -export default define(meta, async (ps) => { - const query = makePaginationQuery(ModerationLogs.createQueryBuilder('report'), ps.sinceId, ps.untilId); - - const reports = await query.take(ps.limit!).getMany(); - - return await ModerationLogs.packMany(reports); -}); diff --git a/src/server/api/endpoints/admin/show-user.ts b/src/server/api/endpoints/admin/show-user.ts deleted file mode 100644 index 963c123255..0000000000 --- a/src/server/api/endpoints/admin/show-user.ts +++ /dev/null @@ -1,177 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - }, - - res: { - type: 'object' as const, - nullable: false as const, optional: false as const, - properties: { - id: { - type: 'string' as const, - nullable: false as const, optional: false as const, - format: 'id' - }, - createdAt: { - type: 'string' as const, - nullable: false as const, optional: false as const, - format: 'date-time' - }, - updatedAt: { - type: 'string' as const, - nullable: true as const, optional: false as const, - format: 'date-time' - }, - lastFetchedAt: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - username: { - type: 'string' as const, - nullable: false as const, optional: false as const - }, - name: { - type: 'string' as const, - nullable: false as const, optional: false as const - }, - folowersCount: { - type: 'number' as const, - nullable: false as const, optional: false as const - }, - followingCount: { - type: 'number' as const, - nullable: false as const, optional: false as const - }, - notesCount: { - type: 'number' as const, - nullable: false as const, optional: false as const - }, - avatarId: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - bannerId: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - tags: { - type: 'array' as const, - nullable: false as const, optional: false as const, - items: { - type: 'string' as const, - nullable: false as const, optional: false as const - } - }, - avatarUrl: { - type: 'string' as const, - nullable: true as const, optional: false as const, - format: 'url' - }, - bannerUrl: { - type: 'string' as const, - nullable: true as const, optional: false as const, - format: 'url' - }, - avatarBlurhash: { - type: 'any' as const, - nullable: true as const, optional: false as const, - default: null - }, - bannerBlurhash: { - type: 'any' as const, - nullable: true as const, optional: false as const, - default: null - }, - isSuspended: { - type: 'boolean' as const, - nullable: false as const, optional: false as const - }, - isSilenced: { - type: 'boolean' as const, - nullable: false as const, optional: false as const - }, - isLocked: { - type: 'boolean' as const, - nullable: false as const, optional: false as const, - }, - isBot: { - type: 'boolean' as const, - nullable: false as const, optional: false as const - }, - isCat: { - type: 'boolean' as const, - nullable: false as const, optional: false as const - }, - isAdmin: { - type: 'boolean' as const, - nullable: false as const, optional: false as const - }, - isModerator: { - type: 'boolean' as const, - nullable: false as const, optional: false as const - }, - emojis: { - type: 'array' as const, - nullable: false as const, optional: false as const, - items: { - type: 'string' as const, - nullable: false as const, optional: false as const - } - }, - host: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - inbox: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - sharedInbox: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - featured: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - uri: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, - token: { - type: 'string' as const, - nullable: false as const, optional: false as const, - default: '<MASKED>' - } - } - } -}; - -export default define(meta, async (ps, me) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - if ((me.isModerator && !me.isAdmin) && user.isAdmin) { - throw new Error('cannot show info of admin'); - } - - return { - ...user, - token: user.token != null ? '<MASKED>' : user.token, - }; -}); diff --git a/src/server/api/endpoints/admin/show-users.ts b/src/server/api/endpoints/admin/show-users.ts deleted file mode 100644 index 20b63e7be6..0000000000 --- a/src/server/api/endpoints/admin/show-users.ts +++ /dev/null @@ -1,119 +0,0 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Users } from '@/models/index'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10 - }, - - offset: { - validator: $.optional.num.min(0), - default: 0 - }, - - sort: { - validator: $.optional.str.or([ - '+follower', - '-follower', - '+createdAt', - '-createdAt', - '+updatedAt', - '-updatedAt', - ]), - }, - - state: { - validator: $.optional.str.or([ - 'all', - 'available', - 'admin', - 'moderator', - 'adminOrModerator', - 'silenced', - 'suspended', - ]), - default: 'all' - }, - - origin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'local' - }, - - username: { - validator: $.optional.str, - default: null - }, - - hostname: { - validator: $.optional.str, - default: null - } - }, - - res: { - type: 'array' as const, - nullable: false as const, optional: false as const, - items: { - type: 'object' as const, - nullable: false as const, optional: false as const, - ref: 'User' - } - } -}; - -export default define(meta, async (ps, me) => { - const query = Users.createQueryBuilder('user'); - - switch (ps.state) { - case 'available': query.where('user.isSuspended = FALSE'); break; - case 'admin': query.where('user.isAdmin = TRUE'); break; - case 'moderator': query.where('user.isModerator = TRUE'); break; - case 'adminOrModerator': query.where('user.isAdmin = TRUE OR user.isModerator = TRUE'); break; - case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break; - case 'silenced': query.where('user.isSilenced = TRUE'); break; - case 'suspended': query.where('user.isSuspended = TRUE'); break; - } - - switch (ps.origin) { - case 'local': query.andWhere('user.host IS NULL'); break; - case 'remote': query.andWhere('user.host IS NOT NULL'); break; - } - - if (ps.username) { - query.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' }); - } - - if (ps.hostname) { - query.andWhere('user.host like :hostname', { hostname: '%' + ps.hostname.toLowerCase() + '%' }); - } - - switch (ps.sort) { - case '+follower': query.orderBy('user.followersCount', 'DESC'); break; - case '-follower': query.orderBy('user.followersCount', 'ASC'); break; - case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break; - case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break; - case '+updatedAt': query.orderBy('user.updatedAt', 'DESC', 'NULLS LAST'); break; - case '-updatedAt': query.orderBy('user.updatedAt', 'ASC', 'NULLS FIRST'); break; - default: query.orderBy('user.id', 'ASC'); break; - } - - query.take(ps.limit!); - query.skip(ps.offset); - - const users = await query.getMany(); - - return await Users.packMany(users, me, { detail: true }); -}); diff --git a/src/server/api/endpoints/admin/silence-user.ts b/src/server/api/endpoints/admin/silence-user.ts deleted file mode 100644 index 9bfed2310a..0000000000 --- a/src/server/api/endpoints/admin/silence-user.ts +++ /dev/null @@ -1,38 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - if (user.isAdmin) { - throw new Error('cannot silence admin'); - } - - await Users.update(user.id, { - isSilenced: true - }); - - insertModerationLog(me, 'silence', { - targetId: user.id, - }); -}); diff --git a/src/server/api/endpoints/admin/suspend-user.ts b/src/server/api/endpoints/admin/suspend-user.ts deleted file mode 100644 index 364f258ce8..0000000000 --- a/src/server/api/endpoints/admin/suspend-user.ts +++ /dev/null @@ -1,84 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import deleteFollowing from '@/services/following/delete'; -import { Users, Followings, Notifications } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { doPostSuspend } from '@/services/suspend-user'; -import { publishUserEvent } from '@/services/stream'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - if (user.isAdmin) { - throw new Error('cannot suspend admin'); - } - - if (user.isModerator) { - throw new Error('cannot suspend moderator'); - } - - await Users.update(user.id, { - isSuspended: true - }); - - insertModerationLog(me, 'suspend', { - targetId: user.id, - }); - - // Terminate streaming - if (Users.isLocalUser(user)) { - publishUserEvent(user.id, 'terminate', {}); - } - - (async () => { - await doPostSuspend(user).catch(e => {}); - await unFollowAll(user).catch(e => {}); - await readAllNotify(user).catch(e => {}); - })(); -}); - -async function unFollowAll(follower: User) { - const followings = await Followings.find({ - followerId: follower.id - }); - - for (const following of followings) { - const followee = await Users.findOne({ - id: following.followeeId - }); - - if (followee == null) { - throw `Cant find followee ${following.followeeId}`; - } - - await deleteFollowing(follower, followee, true); - } -} - -async function readAllNotify(notifier: User) { - await Notifications.update({ - notifierId: notifier.id, - isRead: false, - }, { - isRead: true - }); -} diff --git a/src/server/api/endpoints/admin/unsilence-user.ts b/src/server/api/endpoints/admin/unsilence-user.ts deleted file mode 100644 index 9994fbf462..0000000000 --- a/src/server/api/endpoints/admin/unsilence-user.ts +++ /dev/null @@ -1,34 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - await Users.update(user.id, { - isSilenced: false - }); - - insertModerationLog(me, 'unsilence', { - targetId: user.id, - }); -}); diff --git a/src/server/api/endpoints/admin/unsuspend-user.ts b/src/server/api/endpoints/admin/unsuspend-user.ts deleted file mode 100644 index ab4c2d3dfe..0000000000 --- a/src/server/api/endpoints/admin/unsuspend-user.ts +++ /dev/null @@ -1,37 +0,0 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { doPostUnsuspend } from '@/services/unsuspend-user'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - userId: { - validator: $.type(ID), - }, - } -}; - -export default define(meta, async (ps, me) => { - const user = await Users.findOne(ps.userId as string); - - if (user == null) { - throw new Error('user not found'); - } - - await Users.update(user.id, { - isSuspended: false - }); - - insertModerationLog(me, 'unsuspend', { - targetId: user.id, - }); - - doPostUnsuspend(user); -}); diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts deleted file mode 100644 index 55447098dc..0000000000 --- a/src/server/api/endpoints/admin/update-meta.ts +++ /dev/null @@ -1,608 +0,0 @@ -import $ from 'cafy'; -import define from '../../define'; -import { getConnection } from 'typeorm'; -import { Meta } from '@/models/entities/meta'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits'; -import { ID } from '@/misc/cafy-id'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireAdmin: true, - - params: { - disableRegistration: { - validator: $.optional.nullable.bool, - }, - - disableLocalTimeline: { - validator: $.optional.nullable.bool, - }, - - disableGlobalTimeline: { - validator: $.optional.nullable.bool, - }, - - useStarForReactionFallback: { - validator: $.optional.nullable.bool, - }, - - pinnedUsers: { - validator: $.optional.nullable.arr($.str), - }, - - hiddenTags: { - validator: $.optional.nullable.arr($.str), - }, - - blockedHosts: { - validator: $.optional.nullable.arr($.str), - }, - - mascotImageUrl: { - validator: $.optional.nullable.str, - }, - - bannerUrl: { - validator: $.optional.nullable.str, - }, - - errorImageUrl: { - validator: $.optional.nullable.str, - }, - - iconUrl: { - validator: $.optional.nullable.str, - }, - - backgroundImageUrl: { - validator: $.optional.nullable.str, - }, - - logoImageUrl: { - validator: $.optional.nullable.str, - }, - - name: { - validator: $.optional.nullable.str, - }, - - description: { - validator: $.optional.nullable.str, - }, - - maxNoteTextLength: { - validator: $.optional.num.min(0).max(DB_MAX_NOTE_TEXT_LENGTH), - }, - - localDriveCapacityMb: { - validator: $.optional.num.min(0), - }, - - remoteDriveCapacityMb: { - validator: $.optional.num.min(0), - }, - - cacheRemoteFiles: { - validator: $.optional.bool, - }, - - proxyRemoteFiles: { - validator: $.optional.bool, - }, - - emailRequiredForSignup: { - validator: $.optional.bool, - }, - - enableHcaptcha: { - validator: $.optional.bool, - }, - - hcaptchaSiteKey: { - validator: $.optional.nullable.str, - }, - - hcaptchaSecretKey: { - validator: $.optional.nullable.str, - }, - - enableRecaptcha: { - validator: $.optional.bool, - }, - - recaptchaSiteKey: { - validator: $.optional.nullable.str, - }, - - recaptchaSecretKey: { - validator: $.optional.nullable.str, - }, - - proxyAccountId: { - validator: $.optional.nullable.type(ID), - }, - - maintainerName: { - validator: $.optional.nullable.str, - }, - - maintainerEmail: { - validator: $.optional.nullable.str, - }, - - pinnedPages: { - validator: $.optional.arr($.str), - }, - - pinnedClipId: { - validator: $.optional.nullable.type(ID), - }, - - langs: { - validator: $.optional.arr($.str), - }, - - summalyProxy: { - validator: $.optional.nullable.str, - }, - - deeplAuthKey: { - validator: $.optional.nullable.str, - }, - - deeplIsPro: { - validator: $.optional.bool, - }, - - enableTwitterIntegration: { - validator: $.optional.bool, - }, - - twitterConsumerKey: { - validator: $.optional.nullable.str, - }, - - twitterConsumerSecret: { - validator: $.optional.nullable.str, - }, - - enableGithubIntegration: { - validator: $.optional.bool, - }, - - githubClientId: { - validator: $.optional.nullable.str, - }, - - githubClientSecret: { - validator: $.optional.nullable.str, - }, - - enableDiscordIntegration: { - validator: $.optional.bool, - }, - - discordClientId: { - validator: $.optional.nullable.str, - }, - - discordClientSecret: { - validator: $.optional.nullable.str, - }, - - enableEmail: { - validator: $.optional.bool, - }, - - email: { - validator: $.optional.nullable.str, - }, - - smtpSecure: { - validator: $.optional.bool, - }, - - smtpHost: { - validator: $.optional.nullable.str, - }, - - smtpPort: { - validator: $.optional.nullable.num, - }, - - smtpUser: { - validator: $.optional.nullable.str, - }, - - smtpPass: { - validator: $.optional.nullable.str, - }, - - enableServiceWorker: { - validator: $.optional.bool, - }, - - swPublicKey: { - validator: $.optional.nullable.str, - }, - - swPrivateKey: { - validator: $.optional.nullable.str, - }, - - tosUrl: { - validator: $.optional.nullable.str, - }, - - repositoryUrl: { - validator: $.optional.str, - }, - - feedbackUrl: { - validator: $.optional.str, - }, - - useObjectStorage: { - validator: $.optional.bool - }, - - objectStorageBaseUrl: { - validator: $.optional.nullable.str - }, - - objectStorageBucket: { - validator: $.optional.nullable.str - }, - - objectStoragePrefix: { - validator: $.optional.nullable.str - }, - - objectStorageEndpoint: { - validator: $.optional.nullable.str - }, - - objectStorageRegion: { - validator: $.optional.nullable.str - }, - - objectStoragePort: { - validator: $.optional.nullable.num - }, - - objectStorageAccessKey: { - validator: $.optional.nullable.str - }, - - objectStorageSecretKey: { - validator: $.optional.nullable.str - }, - - objectStorageUseSSL: { - validator: $.optional.bool - }, - - objectStorageUseProxy: { - validator: $.optional.bool - }, - - objectStorageSetPublicRead: { - validator: $.optional.bool - }, - - objectStorageS3ForcePathStyle: { - validator: $.optional.bool - }, - } -}; - -export default define(meta, async (ps, me) => { - const set = {} as Partial<Meta>; - - if (typeof ps.disableRegistration === 'boolean') { - set.disableRegistration = ps.disableRegistration; - } - - if (typeof ps.disableLocalTimeline === 'boolean') { - set.disableLocalTimeline = ps.disableLocalTimeline; - } - - if (typeof ps.disableGlobalTimeline === 'boolean') { - set.disableGlobalTimeline = ps.disableGlobalTimeline; - } - - if (typeof ps.useStarForReactionFallback === 'boolean') { - set.useStarForReactionFallback = ps.useStarForReactionFallback; - } - - if (Array.isArray(ps.pinnedUsers)) { - set.pinnedUsers = ps.pinnedUsers.filter(Boolean); - } - - if (Array.isArray(ps.hiddenTags)) { - set.hiddenTags = ps.hiddenTags.filter(Boolean); - } - - if (Array.isArray(ps.blockedHosts)) { - set.blockedHosts = ps.blockedHosts.filter(Boolean); - } - - if (ps.mascotImageUrl !== undefined) { - set.mascotImageUrl = ps.mascotImageUrl; - } - - if (ps.bannerUrl !== undefined) { - set.bannerUrl = ps.bannerUrl; - } - - if (ps.iconUrl !== undefined) { - set.iconUrl = ps.iconUrl; - } - - if (ps.backgroundImageUrl !== undefined) { - set.backgroundImageUrl = ps.backgroundImageUrl; - } - - if (ps.logoImageUrl !== undefined) { - set.logoImageUrl = ps.logoImageUrl; - } - - if (ps.name !== undefined) { - set.name = ps.name; - } - - if (ps.description !== undefined) { - set.description = ps.description; - } - - if (ps.maxNoteTextLength) { - set.maxNoteTextLength = ps.maxNoteTextLength; - } - - if (ps.localDriveCapacityMb !== undefined) { - set.localDriveCapacityMb = ps.localDriveCapacityMb; - } - - if (ps.remoteDriveCapacityMb !== undefined) { - set.remoteDriveCapacityMb = ps.remoteDriveCapacityMb; - } - - if (ps.cacheRemoteFiles !== undefined) { - set.cacheRemoteFiles = ps.cacheRemoteFiles; - } - - if (ps.proxyRemoteFiles !== undefined) { - set.proxyRemoteFiles = ps.proxyRemoteFiles; - } - - if (ps.emailRequiredForSignup !== undefined) { - set.emailRequiredForSignup = ps.emailRequiredForSignup; - } - - if (ps.enableHcaptcha !== undefined) { - set.enableHcaptcha = ps.enableHcaptcha; - } - - if (ps.hcaptchaSiteKey !== undefined) { - set.hcaptchaSiteKey = ps.hcaptchaSiteKey; - } - - if (ps.hcaptchaSecretKey !== undefined) { - set.hcaptchaSecretKey = ps.hcaptchaSecretKey; - } - - if (ps.enableRecaptcha !== undefined) { - set.enableRecaptcha = ps.enableRecaptcha; - } - - if (ps.recaptchaSiteKey !== undefined) { - set.recaptchaSiteKey = ps.recaptchaSiteKey; - } - - if (ps.recaptchaSecretKey !== undefined) { - set.recaptchaSecretKey = ps.recaptchaSecretKey; - } - - if (ps.proxyAccountId !== undefined) { - set.proxyAccountId = ps.proxyAccountId; - } - - if (ps.maintainerName !== undefined) { - set.maintainerName = ps.maintainerName; - } - - if (ps.maintainerEmail !== undefined) { - set.maintainerEmail = ps.maintainerEmail; - } - - if (Array.isArray(ps.langs)) { - set.langs = ps.langs.filter(Boolean); - } - - if (Array.isArray(ps.pinnedPages)) { - set.pinnedPages = ps.pinnedPages.filter(Boolean); - } - - if (ps.pinnedClipId !== undefined) { - set.pinnedClipId = ps.pinnedClipId; - } - - if (ps.summalyProxy !== undefined) { - set.summalyProxy = ps.summalyProxy; - } - - if (ps.enableTwitterIntegration !== undefined) { - set.enableTwitterIntegration = ps.enableTwitterIntegration; - } - - if (ps.twitterConsumerKey !== undefined) { - set.twitterConsumerKey = ps.twitterConsumerKey; - } - - if (ps.twitterConsumerSecret !== undefined) { - set.twitterConsumerSecret = ps.twitterConsumerSecret; - } - - if (ps.enableGithubIntegration !== undefined) { - set.enableGithubIntegration = ps.enableGithubIntegration; - } - - if (ps.githubClientId !== undefined) { - set.githubClientId = ps.githubClientId; - } - - if (ps.githubClientSecret !== undefined) { - set.githubClientSecret = ps.githubClientSecret; - } - - if (ps.enableDiscordIntegration !== undefined) { - set.enableDiscordIntegration = ps.enableDiscordIntegration; - } - - if (ps.discordClientId !== undefined) { - set.discordClientId = ps.discordClientId; - } - - if (ps.discordClientSecret !== undefined) { - set.discordClientSecret = ps.discordClientSecret; - } - - if (ps.enableEmail !== undefined) { - set.enableEmail = ps.enableEmail; - } - - if (ps.email !== undefined) { - set.email = ps.email; - } - - if (ps.smtpSecure !== undefined) { - set.smtpSecure = ps.smtpSecure; - } - - if (ps.smtpHost !== undefined) { - set.smtpHost = ps.smtpHost; - } - - if (ps.smtpPort !== undefined) { - set.smtpPort = ps.smtpPort; - } - - if (ps.smtpUser !== undefined) { - set.smtpUser = ps.smtpUser; - } - - if (ps.smtpPass !== undefined) { - set.smtpPass = ps.smtpPass; - } - - if (ps.errorImageUrl !== undefined) { - set.errorImageUrl = ps.errorImageUrl; - } - - if (ps.enableServiceWorker !== undefined) { - set.enableServiceWorker = ps.enableServiceWorker; - } - - if (ps.swPublicKey !== undefined) { - set.swPublicKey = ps.swPublicKey; - } - - if (ps.swPrivateKey !== undefined) { - set.swPrivateKey = ps.swPrivateKey; - } - - if (ps.tosUrl !== undefined) { - set.ToSUrl = ps.tosUrl; - } - - if (ps.repositoryUrl !== undefined) { - set.repositoryUrl = ps.repositoryUrl; - } - - if (ps.feedbackUrl !== undefined) { - set.feedbackUrl = ps.feedbackUrl; - } - - if (ps.useObjectStorage !== undefined) { - set.useObjectStorage = ps.useObjectStorage; - } - - if (ps.objectStorageBaseUrl !== undefined) { - set.objectStorageBaseUrl = ps.objectStorageBaseUrl; - } - - if (ps.objectStorageBucket !== undefined) { - set.objectStorageBucket = ps.objectStorageBucket; - } - - if (ps.objectStoragePrefix !== undefined) { - set.objectStoragePrefix = ps.objectStoragePrefix; - } - - if (ps.objectStorageEndpoint !== undefined) { - set.objectStorageEndpoint = ps.objectStorageEndpoint; - } - - if (ps.objectStorageRegion !== undefined) { - set.objectStorageRegion = ps.objectStorageRegion; - } - - if (ps.objectStoragePort !== undefined) { - set.objectStoragePort = ps.objectStoragePort; - } - - if (ps.objectStorageAccessKey !== undefined) { - set.objectStorageAccessKey = ps.objectStorageAccessKey; - } - - if (ps.objectStorageSecretKey !== undefined) { - set.objectStorageSecretKey = ps.objectStorageSecretKey; - } - - if (ps.objectStorageUseSSL !== undefined) { - set.objectStorageUseSSL = ps.objectStorageUseSSL; - } - - if (ps.objectStorageUseProxy !== undefined) { - set.objectStorageUseProxy = ps.objectStorageUseProxy; - } - - if (ps.objectStorageSetPublicRead !== undefined) { - set.objectStorageSetPublicRead = ps.objectStorageSetPublicRead; - } - - if (ps.objectStorageS3ForcePathStyle !== undefined) { - set.objectStorageS3ForcePathStyle = ps.objectStorageS3ForcePathStyle; - } - - if (ps.deeplAuthKey !== undefined) { - if (ps.deeplAuthKey === '') { - set.deeplAuthKey = null; - } else { - set.deeplAuthKey = ps.deeplAuthKey; - } - } - - if (ps.deeplIsPro !== undefined) { - set.deeplIsPro = ps.deeplIsPro; - } - - await getConnection().transaction(async transactionalEntityManager => { - const meta = await transactionalEntityManager.findOne(Meta, { - order: { - id: 'DESC' - } - }); - - if (meta) { - await transactionalEntityManager.update(Meta, meta.id, set); - } else { - await transactionalEntityManager.save(Meta, set); - } - }); - - insertModerationLog(me, 'updateMeta'); -}); diff --git a/src/server/api/endpoints/admin/vacuum.ts b/src/server/api/endpoints/admin/vacuum.ts deleted file mode 100644 index 9a80d88c44..0000000000 --- a/src/server/api/endpoints/admin/vacuum.ts +++ /dev/null @@ -1,36 +0,0 @@ -import $ from 'cafy'; -import define from '../../define'; -import { getConnection } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; - -export const meta = { - tags: ['admin'], - - requireCredential: true as const, - requireModerator: true, - - params: { - full: { - validator: $.bool, - }, - analyze: { - validator: $.bool, - }, - } -}; - -export default define(meta, async (ps, me) => { - const params: string[] = []; - - if (ps.full) { - params.push('FULL'); - } - - if (ps.analyze) { - params.push('ANALYZE'); - } - - getConnection().query('VACUUM ' + params.join(' ')); - - insertModerationLog(me, 'vacuum', ps); -}); |