summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints/admin
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/server/api/endpoints/admin')
-rw-r--r--packages/backend/src/server/api/endpoints/admin/delete-account.ts31
-rw-r--r--packages/backend/src/server/api/endpoints/admin/drive-capacity-override.ts47
-rw-r--r--packages/backend/src/server/api/endpoints/admin/drive/files.ts23
-rw-r--r--packages/backend/src/server/api/endpoints/admin/drive/show-file.ts7
-rw-r--r--packages/backend/src/server/api/endpoints/admin/get-user-ips.ts31
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts28
-rw-r--r--packages/backend/src/server/api/endpoints/admin/server-info.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-user.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-users.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts27
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-user-note.ts31
11 files changed, 223 insertions, 17 deletions
diff --git a/packages/backend/src/server/api/endpoints/admin/delete-account.ts b/packages/backend/src/server/api/endpoints/admin/delete-account.ts
new file mode 100644
index 0000000000..2d7ef2f236
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/delete-account.ts
@@ -0,0 +1,31 @@
+import { Users } from '@/models/index.js';
+import { deleteAccount } from '@/services/delete-account.js';
+import define from '../../define.js';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireAdmin: true,
+
+ res: {
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['userId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+export default define(meta, paramDef, async (ps) => {
+ const user = await Users.findOneByOrFail({ id: ps.userId });
+ if (user.isDeleted) {
+ return;
+ }
+
+ await deleteAccount(user);
+});
diff --git a/packages/backend/src/server/api/endpoints/admin/drive-capacity-override.ts b/packages/backend/src/server/api/endpoints/admin/drive-capacity-override.ts
new file mode 100644
index 0000000000..a4b29770e1
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/drive-capacity-override.ts
@@ -0,0 +1,47 @@
+import define from '../../define.js';
+import { Users } from '@/models/index.js';
+import { User } from '@/models/entities/user.js';
+import { insertModerationLog } from '@/services/insert-moderation-log.js';
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireModerator: true,
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id' },
+ overrideMb: { type: 'number', nullable: true },
+ },
+ required: ['userId', 'overrideMb'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+export default define(meta, paramDef, async (ps, me) => {
+ const user = await Users.findOneBy({ id: ps.userId });
+
+ if (user == null) {
+ throw new Error('user not found');
+ }
+
+ if (!Users.isLocalUser(user)) {
+ throw new Error('user is not local user');
+ }
+
+ /*if (user.isAdmin) {
+ throw new Error('cannot suspend admin');
+ }
+ if (user.isModerator) {
+ throw new Error('cannot suspend moderator');
+ }*/
+
+ await Users.update(user.id, {
+ driveCapacityOverrideMb: ps.overrideMb,
+ });
+
+ insertModerationLog(me, 'change-drive-capacity-override', {
+ targetId: user.id,
+ });
+});
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts
index 119c4db19b..ba32aac431 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts
@@ -1,5 +1,5 @@
-import define from '../../../define.js';
import { DriveFiles } from '@/models/index.js';
+import define from '../../../define.js';
import { makePaginationQuery } from '../../../common/make-pagination-query.js';
export const meta = {
@@ -25,8 +25,9 @@ export const paramDef = {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
+ userId: { type: 'string', format: 'misskey:id', nullable: true },
type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) },
- origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" },
+ origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'local' },
hostname: {
type: 'string',
nullable: true,
@@ -41,14 +42,18 @@ export const paramDef = {
export default define(meta, paramDef, 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.userId) {
+ query.andWhere('file.userId = :userId', { userId: ps.userId });
+ } else {
+ 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.hostname) {
+ query.andWhere('file.userHost = :hostname', { hostname: ps.hostname });
+ }
}
if (ps.type) {
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
index 039df74f1b..e9117a23c8 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
@@ -1,6 +1,6 @@
+import { DriveFiles } from '@/models/index.js';
import define from '../../../define.js';
import { ApiError } from '../../../error.js';
-import { DriveFiles } from '@/models/index.js';
export const meta = {
tags: ['admin'],
@@ -184,5 +184,10 @@ export default define(meta, paramDef, async (ps, me) => {
throw new ApiError(meta.errors.noSuchFile);
}
+ if (!me.isAdmin) {
+ delete file.requestIp;
+ delete file.requestHeaders;
+ }
+
return file;
});
diff --git a/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts b/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts
new file mode 100644
index 0000000000..e8b9cb3b09
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts
@@ -0,0 +1,31 @@
+import { UserIps } from '@/models/index.js';
+import define from '../../define.js';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireAdmin: true,
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['userId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+export default define(meta, paramDef, async (ps, me) => {
+ const ips = await UserIps.find({
+ where: { userId: ps.userId },
+ order: { createdAt: 'DESC' },
+ take: 30,
+ });
+
+ return ips.map(x => ({
+ ip: x.ip,
+ createdAt: x.createdAt.toISOString(),
+ }));
+});
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index 8d50486ef6..cb50e128af 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -1,7 +1,7 @@
import config from '@/config/index.js';
-import define from '../../define.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
+import define from '../../define.js';
export const meta = {
tags: ['meta'],
@@ -195,6 +195,22 @@ export const meta = {
type: 'string',
optional: true, nullable: true,
},
+ sensitiveMediaDetection: {
+ type: 'string',
+ optional: true, nullable: false,
+ },
+ sensitiveMediaDetectionSensitivity: {
+ type: 'string',
+ optional: true, nullable: false,
+ },
+ setSensitiveFlagAutomatically: {
+ type: 'boolean',
+ optional: true, nullable: false,
+ },
+ enableSensitiveMediaDetectionForVideos: {
+ type: 'boolean',
+ optional: true, nullable: false,
+ },
proxyAccountId: {
type: 'string',
optional: true, nullable: true,
@@ -304,6 +320,10 @@ export const meta = {
type: 'boolean',
optional: true, nullable: false,
},
+ enableIpLogging: {
+ type: 'boolean',
+ optional: true, nullable: false,
+ },
},
},
} as const;
@@ -360,13 +380,16 @@ export default define(meta, paramDef, async (ps, me) => {
pinnedPages: instance.pinnedPages,
pinnedClipId: instance.pinnedClipId,
cacheRemoteFiles: instance.cacheRemoteFiles,
-
useStarForReactionFallback: instance.useStarForReactionFallback,
pinnedUsers: instance.pinnedUsers,
hiddenTags: instance.hiddenTags,
blockedHosts: instance.blockedHosts,
hcaptchaSecretKey: instance.hcaptchaSecretKey,
recaptchaSecretKey: instance.recaptchaSecretKey,
+ sensitiveMediaDetection: instance.sensitiveMediaDetection,
+ sensitiveMediaDetectionSensitivity: instance.sensitiveMediaDetectionSensitivity,
+ setSensitiveFlagAutomatically: instance.setSensitiveFlagAutomatically,
+ enableSensitiveMediaDetectionForVideos: instance.enableSensitiveMediaDetectionForVideos,
proxyAccountId: instance.proxyAccountId,
twitterConsumerKey: instance.twitterConsumerKey,
twitterConsumerSecret: instance.twitterConsumerSecret,
@@ -397,5 +420,6 @@ export default define(meta, paramDef, async (ps, me) => {
objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle,
deeplAuthKey: instance.deeplAuthKey,
deeplIsPro: instance.deeplIsPro,
+ enableIpLogging: instance.enableIpLogging,
};
});
diff --git a/packages/backend/src/server/api/endpoints/admin/server-info.ts b/packages/backend/src/server/api/endpoints/admin/server-info.ts
index 9c150420b1..85c6fb82e7 100644
--- a/packages/backend/src/server/api/endpoints/admin/server-info.ts
+++ b/packages/backend/src/server/api/endpoints/admin/server-info.ts
@@ -99,12 +99,16 @@ export default define(meta, paramDef, async () => {
const fsStats = await si.fsSize();
const netInterface = await si.networkInterfaceDefault();
+ const redisServerInfo = await redisClient.info('Server');
+ const m = redisServerInfo.match(new RegExp('^redis_version:(.*)', 'm'));
+ const redis_version = m?.[1];
+
return {
machine: os.hostname(),
os: os.platform(),
node: process.version,
psql: await db.query('SHOW server_version').then(x => x[0].server_version),
- redis: redisClient.server_info.redis_version,
+ redis: redis_version,
cpu: {
model: os.cpus()[0].model,
cores: os.cpus().length,
diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts
index 78033aed58..0d866b3113 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts
@@ -25,7 +25,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, me) => {
const [user, profile] = await Promise.all([
Users.findOneBy({ id: ps.userId }),
- UserProfiles.findOneBy({ userId: ps.userId })
+ UserProfiles.findOneBy({ userId: ps.userId }),
]);
if (user == null || profile == null) {
@@ -58,6 +58,7 @@ export default define(meta, paramDef, async (ps, me) => {
autoAcceptFollowed: profile.autoAcceptFollowed,
noCrawle: profile.noCrawle,
alwaysMarkNsfw: profile.alwaysMarkNsfw,
+ autoSensitive: profile.autoSensitive,
carefulBot: profile.carefulBot,
injectFeaturedNote: profile.injectFeaturedNote,
receiveAnnouncementEmail: profile.receiveAnnouncementEmail,
@@ -68,6 +69,8 @@ export default define(meta, paramDef, async (ps, me) => {
isModerator: user.isModerator,
isSilenced: user.isSilenced,
isSuspended: user.isSuspended,
+ lastActiveDate: user.lastActiveDate,
+ moderationNote: profile.moderationNote,
signins,
};
});
diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts
index 1575d81d5d..8e09e72d5b 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts
@@ -25,7 +25,7 @@ export const paramDef = {
offset: { type: 'integer', default: 0 },
sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] },
state: { type: 'string', enum: ['all', 'alive', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: 'all' },
- origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'local' },
+ origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'combined' },
username: { type: 'string', nullable: true, default: null },
hostname: {
type: 'string',
@@ -61,7 +61,7 @@ export default define(meta, paramDef, async (ps, me) => {
}
if (ps.hostname) {
- query.andWhere('user.host like :hostname', { hostname: '%' + ps.hostname.toLowerCase() + '%' });
+ query.andWhere('user.host = :hostname', { hostname: ps.hostname.toLowerCase() });
}
switch (ps.sort) {
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index 09e43301b7..cc32e73c53 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -1,8 +1,8 @@
-import define from '../../define.js';
import { Meta } from '@/models/entities/meta.js';
import { insertModerationLog } from '@/services/insert-moderation-log.js';
import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits.js';
import { db } from '@/db/postgre.js';
+import define from '../../define.js';
export const meta = {
tags: ['admin'],
@@ -48,6 +48,10 @@ export const paramDef = {
enableRecaptcha: { type: 'boolean' },
recaptchaSiteKey: { type: 'string', nullable: true },
recaptchaSecretKey: { type: 'string', nullable: true },
+ sensitiveMediaDetection: { type: 'string', enum: ['none', 'all', 'local', 'remote'] },
+ sensitiveMediaDetectionSensitivity: { type: 'string', enum: ['medium', 'low', 'high', 'veryLow', 'veryHigh'] },
+ setSensitiveFlagAutomatically: { type: 'boolean' },
+ enableSensitiveMediaDetectionForVideos: { type: 'boolean' },
proxyAccountId: { type: 'string', format: 'misskey:id', nullable: true },
maintainerName: { type: 'string', nullable: true },
maintainerEmail: { type: 'string', nullable: true },
@@ -96,6 +100,7 @@ export const paramDef = {
objectStorageUseProxy: { type: 'boolean' },
objectStorageSetPublicRead: { type: 'boolean' },
objectStorageS3ForcePathStyle: { type: 'boolean' },
+ enableIpLogging: { type: 'boolean' },
},
required: [],
} as const;
@@ -212,6 +217,22 @@ export default define(meta, paramDef, async (ps, me) => {
set.recaptchaSecretKey = ps.recaptchaSecretKey;
}
+ if (ps.sensitiveMediaDetection !== undefined) {
+ set.sensitiveMediaDetection = ps.sensitiveMediaDetection;
+ }
+
+ if (ps.sensitiveMediaDetectionSensitivity !== undefined) {
+ set.sensitiveMediaDetectionSensitivity = ps.sensitiveMediaDetectionSensitivity;
+ }
+
+ if (ps.setSensitiveFlagAutomatically !== undefined) {
+ set.setSensitiveFlagAutomatically = ps.setSensitiveFlagAutomatically;
+ }
+
+ if (ps.enableSensitiveMediaDetectionForVideos !== undefined) {
+ set.enableSensitiveMediaDetectionForVideos = ps.enableSensitiveMediaDetectionForVideos;
+ }
+
if (ps.proxyAccountId !== undefined) {
set.proxyAccountId = ps.proxyAccountId;
}
@@ -396,6 +417,10 @@ export default define(meta, paramDef, async (ps, me) => {
set.deeplIsPro = ps.deeplIsPro;
}
+ if (ps.enableIpLogging !== undefined) {
+ set.enableIpLogging = ps.enableIpLogging;
+ }
+
await db.transaction(async transactionalEntityManager => {
const metas = await transactionalEntityManager.find(Meta, {
order: {
diff --git a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
new file mode 100644
index 0000000000..fa21ab7833
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
@@ -0,0 +1,31 @@
+import { UserProfiles, Users } from '@/models/index.js';
+import define from '../../define.js';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireModerator: true,
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id' },
+ text: { type: 'string' },
+ },
+ required: ['userId', 'text'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+export default define(meta, paramDef, async (ps, me) => {
+ const user = await Users.findOneBy({ id: ps.userId });
+
+ if (user == null) {
+ throw new Error('user not found');
+ }
+
+ await UserProfiles.update({ userId: user.id }, {
+ moderationNote: ps.text,
+ });
+});