diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2020-01-30 04:37:25 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-30 04:37:25 +0900 |
| commit | f6154dc0af1a0d65819e87240f4385f9573095cb (patch) | |
| tree | 699a5ca07d6727b7f8497d4769f25d6d62f94b5a /src/server/api/endpoints/admin | |
| parent | Add Event activity-type support (#5785) (diff) | |
| download | sharkey-f6154dc0af1a0d65819e87240f4385f9573095cb.tar.gz sharkey-f6154dc0af1a0d65819e87240f4385f9573095cb.tar.bz2 sharkey-f6154dc0af1a0d65819e87240f4385f9573095cb.zip | |
v12 (#5712)
Co-authored-by: MeiMei <30769358+mei23@users.noreply.github.com>
Co-authored-by: Satsuki Yanagi <17376330+u1-liquid@users.noreply.github.com>
Diffstat (limited to 'src/server/api/endpoints/admin')
| -rw-r--r-- | src/server/api/endpoints/admin/accounts/create.ts | 33 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/announcements/create.ts | 36 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/announcements/delete.ts | 34 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/announcements/list.ts | 41 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/announcements/update.ts | 48 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/emoji/list-remote.ts | 62 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/emoji/list.ts | 32 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/queue/deliver-delayed.ts | 31 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/queue/inbox-delayed.ts | 31 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/server-info.ts | 45 | ||||
| -rw-r--r-- | src/server/api/endpoints/admin/update-meta.ts | 30 |
11 files changed, 384 insertions, 39 deletions
diff --git a/src/server/api/endpoints/admin/accounts/create.ts b/src/server/api/endpoints/admin/accounts/create.ts new file mode 100644 index 0000000000..ac80b579b7 --- /dev/null +++ b/src/server/api/endpoints/admin/accounts/create.ts @@ -0,0 +1,33 @@ +import define from '../../../define'; +import { Users } from '../../../../../models'; +import { signup } from '../../../common/signup'; + +export const meta = { + tags: ['admin'], + + params: { + username: { + validator: Users.validateLocalUsername, + }, + + password: { + validator: Users.validatePassword, + } + } +}; + +export default define(meta, async (ps, me) => { + const noUsers = (await Users.count({})) === 0; + if (!noUsers && me == null) throw new Error('access denied'); + + const { account, secret } = await signup(ps.username, 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/announcements/create.ts b/src/server/api/endpoints/admin/announcements/create.ts new file mode 100644 index 0000000000..c1d48a7d38 --- /dev/null +++ b/src/server/api/endpoints/admin/announcements/create.ts @@ -0,0 +1,36 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { Announcements } from '../../../../../models'; +import { genId } from '../../../../../misc/gen-id'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + + params: { + title: { + validator: $.str.min(1) + }, + text: { + validator: $.str.min(1) + }, + imageUrl: { + validator: $.nullable.str.min(1) + } + } +}; + +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 new file mode 100644 index 0000000000..284b4bf549 --- /dev/null +++ b/src/server/api/endpoints/admin/announcements/delete.ts @@ -0,0 +1,34 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { ID } from '../../../../../misc/cafy-id'; +import { Announcements } from '../../../../../models'; +import { ApiError } from '../../../error'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + 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 new file mode 100644 index 0000000000..f4e622144e --- /dev/null +++ b/src/server/api/endpoints/admin/announcements/list.ts @@ -0,0 +1,41 @@ +import $ from 'cafy'; +import { ID } from '../../../../../misc/cafy-id'; +import define from '../../../define'; +import { Announcements, AnnouncementReads } from '../../../../../models'; +import { makePaginationQuery } from '../../../common/make-pagination-query'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + 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(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 new file mode 100644 index 0000000000..b65c3a4f93 --- /dev/null +++ b/src/server/api/endpoints/admin/announcements/update.ts @@ -0,0 +1,48 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { ID } from '../../../../../misc/cafy-id'; +import { Announcements } from '../../../../../models'; +import { ApiError } from '../../../error'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + 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/emoji/list-remote.ts b/src/server/api/endpoints/admin/emoji/list-remote.ts new file mode 100644 index 0000000000..0a3e74c333 --- /dev/null +++ b/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -0,0 +1,62 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { Emojis } from '../../../../../models'; +import { toPuny } from '../../../../../misc/convert-host'; +import { makePaginationQuery } from '../../../common/make-pagination-query'; +import { ID } from '../../../../../misc/cafy-id'; + +export const meta = { + desc: { + 'ja-JP': 'カスタム絵文字を取得します。' + }, + + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + + params: { + host: { + validator: $.optional.nullable.str, + default: null as any + }, + + 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 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) }); + } + + const emojis = await q + .orderBy('emoji.category', 'ASC') + .orderBy('emoji.name', 'ASC') + .take(ps.limit!) + .getMany(); + + return emojis.map(e => ({ + id: e.id, + name: e.name, + category: e.category, + aliases: e.aliases, + host: e.host, + url: e.url + })); +}); diff --git a/src/server/api/endpoints/admin/emoji/list.ts b/src/server/api/endpoints/admin/emoji/list.ts index d2a5e7df0d..d525a659c0 100644 --- a/src/server/api/endpoints/admin/emoji/list.ts +++ b/src/server/api/endpoints/admin/emoji/list.ts @@ -1,7 +1,8 @@ import $ from 'cafy'; import define from '../../../define'; import { Emojis } from '../../../../../models'; -import { toPunyNullable } from '../../../../../misc/convert-host'; +import { makePaginationQuery } from '../../../common/make-pagination-query'; +import { ID } from '../../../../../misc/cafy-id'; export const meta = { desc: { @@ -14,23 +15,28 @@ export const meta = { requireModerator: true, params: { - host: { - validator: $.optional.nullable.str, - default: null as any + 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 emojis = await Emojis.find({ - where: { - host: toPunyNullable(ps.host) - }, - order: { - category: 'ASC', - name: 'ASC' - } - }); + const emojis = await makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId) + .andWhere(`emoji.host IS NULL`) + .orderBy('emoji.category', 'ASC') + .orderBy('emoji.name', 'ASC') + .take(ps.limit!) + .getMany(); return emojis.map(e => ({ id: e.id, diff --git a/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/src/server/api/endpoints/admin/queue/deliver-delayed.ts new file mode 100644 index 0000000000..d33837c099 --- /dev/null +++ b/src/server/api/endpoints/admin/queue/deliver-delayed.ts @@ -0,0 +1,31 @@ +import define from '../../../define'; +import { deliverQueue } from '../../../../../queue'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + + params: { + } +}; + +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 new file mode 100644 index 0000000000..643e22f10d --- /dev/null +++ b/src/server/api/endpoints/admin/queue/inbox-delayed.ts @@ -0,0 +1,31 @@ +import define from '../../../define'; +import { inboxQueue } from '../../../../../queue'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + + params: { + } +}; + +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/server-info.ts b/src/server/api/endpoints/admin/server-info.ts new file mode 100644 index 0000000000..f51040a2c8 --- /dev/null +++ b/src/server/api/endpoints/admin/server-info.ts @@ -0,0 +1,45 @@ +import * as os from 'os'; +import * as si from 'systeminformation'; +import { getConnection } from 'typeorm'; +import define from '../../define'; +import redis from '../../../../db/redis'; + +export const meta = { + requireCredential: false, + + desc: { + }, + + tags: ['meta'], + + params: { + }, +}; + +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: redis.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/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts index bc37228d0a..65650f1295 100644 --- a/src/server/api/endpoints/admin/update-meta.ts +++ b/src/server/api/endpoints/admin/update-meta.ts @@ -13,16 +13,9 @@ export const meta = { tags: ['admin'], requireCredential: true, - requireModerator: true, + requireAdmin: true, params: { - announcements: { - validator: $.optional.nullable.arr($.obj()), - desc: { - 'ja-JP': 'お知らせ' - } - }, - disableRegistration: { validator: $.optional.nullable.bool, desc: { @@ -44,13 +37,6 @@ export const meta = { } }, - enableEmojiReaction: { - validator: $.optional.nullable.bool, - desc: { - 'ja-JP': '絵文字リアクションを有効にするか否か' - } - }, - useStarForReactionFallback: { validator: $.optional.nullable.bool, desc: { @@ -347,7 +333,7 @@ export const meta = { } }, - ToSUrl: { + tosUrl: { validator: $.optional.nullable.str, desc: { 'ja-JP': '利用規約のURL' @@ -413,10 +399,6 @@ export const meta = { export default define(meta, async (ps, me) => { const set = {} as Partial<Meta>; - if (ps.announcements) { - set.announcements = ps.announcements; - } - if (typeof ps.disableRegistration === 'boolean') { set.disableRegistration = ps.disableRegistration; } @@ -429,10 +411,6 @@ export default define(meta, async (ps, me) => { set.disableGlobalTimeline = ps.disableGlobalTimeline; } - if (typeof ps.enableEmojiReaction === 'boolean') { - set.enableEmojiReaction = ps.enableEmojiReaction; - } - if (typeof ps.useStarForReactionFallback === 'boolean') { set.useStarForReactionFallback = ps.useStarForReactionFallback; } @@ -601,8 +579,8 @@ export default define(meta, async (ps, me) => { set.swPrivateKey = ps.swPrivateKey; } - if (ps.ToSUrl !== undefined) { - set.ToSUrl = ps.ToSUrl; + if (ps.tosUrl !== undefined) { + set.ToSUrl = ps.tosUrl; } if (ps.repositoryUrl !== undefined) { |