From 271ca3f5c902da2e01055bc0b3f82b913816c130 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 21 Feb 2025 20:34:20 +0900 Subject: [PATCH] wip --- locales/index.d.ts | 4 ++ locales/ja-JP.yml | 1 + packages/backend/src/GlobalModule.ts | 2 +- .../backend/src/core/AccountMoveService.ts | 14 +++--- packages/backend/src/core/MetaService.ts | 2 +- .../backend/src/core/SystemAccountService.ts | 12 +++-- packages/backend/src/core/UserListService.ts | 10 ++--- .../endpoints/admin/update-proxy-account.ts | 44 ++++--------------- packages/backend/src/types.ts | 29 +++++++----- .../src/pages/admin/modlog.ModLog.vue | 5 +++ packages/misskey-js/src/autogen/types.ts | 4 -- 11 files changed, 55 insertions(+), 72 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index c7996b2ca9..507491dfe9 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -10058,6 +10058,10 @@ export interface Locale extends ILocale { * ギャラリーの投稿を削除 */ "deleteGalleryPost": string; + /** + * プロキシアカウントの説明を更新 + */ + "updateProxyAccountDescription": string; }; "_fileViewer": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1aed7c21ae..eed8a283b9 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2664,6 +2664,7 @@ _moderationLogTypes: deletePage: "ページを削除" deleteFlash: "Playを削除" deleteGalleryPost: "ギャラリーの投稿を削除" + updateProxyAccountDescription: "プロキシアカウントの説明を更新" _fileViewer: title: "ファイルの詳細" diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts index ace7f7841c..5544eeeddd 100644 --- a/packages/backend/src/GlobalModule.ts +++ b/packages/backend/src/GlobalModule.ts @@ -133,7 +133,7 @@ const $meta: Provider = { for (const key in body.after) { (meta as any)[key] = (body.after as any)[key]; } - meta.proxyAccount = null; // joinなカラムは通常取ってこないので + meta.rootUser = null; // joinなカラムは通常取ってこないので break; } default: diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts index 24d11f29ff..0fbb9bcd80 100644 --- a/packages/backend/src/core/AccountMoveService.ts +++ b/packages/backend/src/core/AccountMoveService.ts @@ -20,10 +20,10 @@ import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js'; import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { ProxyAccountService } from '@/core/ProxyAccountService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import InstanceChart from '@/core/chart/charts/instance.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; +import { SystemAccountService } from '@/core/SystemAccountService.js'; @Injectable() export class AccountMoveService { @@ -55,12 +55,12 @@ export class AccountMoveService { private apRendererService: ApRendererService, private apDeliverManagerService: ApDeliverManagerService, private globalEventService: GlobalEventService, - private proxyAccountService: ProxyAccountService, private perUserFollowingChart: PerUserFollowingChart, private federatedInstanceService: FederatedInstanceService, private instanceChart: InstanceChart, private relayService: RelayService, private queueService: QueueService, + private systemAccountService: SystemAccountService, ) { } @@ -126,11 +126,11 @@ export class AccountMoveService { } // follow the new account - const proxy = await this.proxyAccountService.fetch(); + const proxy = await this.systemAccountService.fetch('proxy'); const followings = await this.followingsRepository.findBy({ followeeId: src.id, followerHost: IsNull(), // follower is local - followerId: proxy ? Not(proxy.id) : undefined, + followerId: Not(proxy.id), }); const followJobs = followings.map(following => ({ from: { id: following.followerId }, @@ -250,10 +250,8 @@ export class AccountMoveService { // Have the proxy account follow the new account in the same way as UserListService.push if (this.userEntityService.isRemoteUser(dst)) { - const proxy = await this.proxyAccountService.fetch(); - if (proxy) { - this.queueService.createFollowJob([{ from: { id: proxy.id }, to: { id: dst.id } }]); - } + const proxy = await this.systemAccountService.fetch('proxy'); + this.queueService.createFollowJob([{ from: { id: proxy.id }, to: { id: dst.id } }]); } } diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts index 3d88d0aefe..3a3eaf5063 100644 --- a/packages/backend/src/core/MetaService.ts +++ b/packages/backend/src/core/MetaService.ts @@ -53,7 +53,7 @@ export class MetaService implements OnApplicationShutdown { case 'metaUpdated': { this.cache = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい ...(body.after), - proxyAccount: null, // joinなカラムは通常取ってこないので + rootUser: null, // joinなカラムは通常取ってこないので }; break; } diff --git a/packages/backend/src/core/SystemAccountService.ts b/packages/backend/src/core/SystemAccountService.ts index 3ceb8bc437..cd91355d06 100644 --- a/packages/backend/src/core/SystemAccountService.ts +++ b/packages/backend/src/core/SystemAccountService.ts @@ -9,7 +9,7 @@ import { DataSource, IsNull } from 'typeorm'; import bcrypt from 'bcryptjs'; import { MiLocalUser, MiUser } from '@/models/User.js'; import { MiSystemAccount, MiUsedUsername, MiUserKeypair, MiUserProfile, type UsersRepository, type SystemAccountsRepository } from '@/models/_.js'; -import type { UserProfilesRepository } from '@/models/_.js'; +import type { MiMeta, UserProfilesRepository } from '@/models/_.js'; import { MemoryKVCache } from '@/misc/cache.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; @@ -27,6 +27,9 @@ export class SystemAccountService { @Inject(DI.db) private db: DataSource, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.systemAccountsRepository) private systemAccountsRepository: SystemAccountsRepository, @@ -64,6 +67,7 @@ export class SystemAccountService { } else { const created = await this.createCorrespondingUser(type, { username: `system.${type}`, + name: this.meta.name, }); this.cache.set(type, created); return created; @@ -72,8 +76,8 @@ export class SystemAccountService { @bindThis private async createCorrespondingUser(type: typeof SYSTEM_ACCOUNT_TYPES[number], extra: { - username: string; - name?: string; + username: MiUser['username']; + name?: MiUser['name']; }): Promise { const password = randomUUID(); @@ -139,7 +143,7 @@ export class SystemAccountService { @bindThis public async updateCorrespondingUserProfile(type: typeof SYSTEM_ACCOUNT_TYPES[number], extra: { name?: string; - description?: string; + description?: MiUserProfile['description']; }): Promise { const user = await this.fetch(type); diff --git a/packages/backend/src/core/UserListService.ts b/packages/backend/src/core/UserListService.ts index 6333356fe9..f0a8768c8f 100644 --- a/packages/backend/src/core/UserListService.ts +++ b/packages/backend/src/core/UserListService.ts @@ -15,11 +15,11 @@ import type { GlobalEvents } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { ProxyAccountService } from '@/core/ProxyAccountService.js'; import { bindThis } from '@/decorators.js'; import { QueueService } from '@/core/QueueService.js'; import { RedisKVCache } from '@/misc/cache.js'; import { RoleService } from '@/core/RoleService.js'; +import { SystemAccountService } from '@/core/SystemAccountService.js'; @Injectable() export class UserListService implements OnApplicationShutdown, OnModuleInit { @@ -43,8 +43,8 @@ export class UserListService implements OnApplicationShutdown, OnModuleInit { private userEntityService: UserEntityService, private idService: IdService, private globalEventService: GlobalEventService, - private proxyAccountService: ProxyAccountService, private queueService: QueueService, + private systemAccountService: SystemAccountService, ) { this.membersCache = new RedisKVCache>(this.redisClient, 'userListMembers', { lifetime: 1000 * 60 * 30, // 30m @@ -111,10 +111,8 @@ export class UserListService implements OnApplicationShutdown, OnModuleInit { // このインスタンス内にこのリモートユーザーをフォローしているユーザーがいなくても投稿を受け取るためにダミーのユーザーがフォローしたということにする if (this.userEntityService.isRemoteUser(target)) { - const proxy = await this.proxyAccountService.fetch(); - if (proxy) { - this.queueService.createFollowJob([{ from: { id: proxy.id }, to: { id: target.id } }]); - } + const proxy = await this.systemAccountService.fetch('proxy'); + this.queueService.createFollowJob([{ from: { id: proxy.id }, to: { id: target.id } }]); } } diff --git a/packages/backend/src/server/api/endpoints/admin/update-proxy-account.ts b/packages/backend/src/server/api/endpoints/admin/update-proxy-account.ts index 1322327dd1..6c9612c71a 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-proxy-account.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-proxy-account.ts @@ -3,18 +3,11 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Inject, Injectable } from '@nestjs/common'; -import type { - UsersRepository, -} from '@/models/_.js'; +import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { DI } from '@/di-symbols.js'; -import { RoleService } from '@/core/RoleService.js'; import { descriptionSchema, - nameSchema, } from '@/models/User.js'; -import { ApiError } from '@/server/api/error.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { SystemAccountService } from '@/core/SystemAccountService.js'; @@ -24,52 +17,30 @@ export const meta = { requireCredential: true, requireModerator: true, - kind: 'write:admin:update-proxy-account', - - errors: { - accessDenied: { - message: 'Only administrators can edit members of the role.', - code: 'ACCESS_DENIED', - id: '101f9105-27cb-489c-842a-69b6d2092c03', - }, - }, + kind: 'write:admin:account', res: { type: 'object', nullable: false, optional: false, ref: 'UserDetailed', }, - - required: [], } as const; export const paramDef = { type: 'object', properties: { - name: { ...nameSchema, nullable: true }, description: { ...descriptionSchema, nullable: true }, - avatarId: { type: 'string', format: 'misskey:id', nullable: true }, - bannerId: { type: 'string', format: 'misskey:id', nullable: true }, }, } as const; @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.usersRepository) - private usersRepository: UsersRepository, - - private roleService: RoleService, private userEntityService: UserEntityService, private moderationLogService: ModerationLogService, private systemAccountService: SystemAccountService, ) { super(meta, paramDef, async (ps, me) => { - const _me = await this.usersRepository.findOneByOrFail({ id: me.id }); - if (!await this.roleService.isModerator(_me)) { - throw new ApiError(meta.errors.accessDenied); - } - const proxy = await this.systemAccountService.updateCorrespondingUserProfile('proxy', { description: ps.description, }); @@ -78,11 +49,12 @@ export default class extends Endpoint { // eslint- schema: 'MeDetailed', }); - this.moderationLogService.log(me, 'updateUser', { - userId: proxy.id, - userUsername: proxy.username, - userHost: proxy.host, - }); + if (ps.description !== undefined) { + this.moderationLogService.log(me, 'updateProxyAccountDescription', { + before: null, //TODO + after: ps.description, + }); + } return updated; }); diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index bf409031c8..c6b1035554 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -122,6 +122,7 @@ export const moderationLogTypes = [ 'deletePage', 'deleteFlash', 'deleteGalleryPost', + 'updateProxyAccountDescription', ] as const; export type ModerationLogPayloads = { @@ -374,25 +375,29 @@ export type ModerationLogPayloads = { postUserUsername: string; post: any; }; + updateProxyAccountDescription: { + before: string | null; + after: string | null; + }; }; export type Serialized = { [K in keyof T]: - T[K] extends Date - ? string - : T[K] extends (Date | null) - ? (string | null) - : T[K] extends Record - ? Serialized - : T[K] extends (Record | null) + T[K] extends Date + ? string + : T[K] extends (Date | null) + ? (string | null) + : T[K] extends Record + ? Serialized + : T[K] extends (Record | null) ? (Serialized | null) - : T[K] extends (Record | undefined) + : T[K] extends (Record | undefined) ? (Serialized | undefined) - : T[K]; + : T[K]; }; export type FilterUnionByProperty< - Union, - Property extends string | number | symbol, - Condition + Union, + Property extends string | number | symbol, + Condition, > = Union extends Record ? Union : never; diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 1e144394fb..9bbe5f2e42 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -170,6 +170,11 @@ SPDX-License-Identifier: AGPL-3.0-only +
raw diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index c7485c6c3d..31d05dab6c 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -8282,8 +8282,6 @@ export type operations = { sensitiveMediaDetectionSensitivity: string; setSensitiveFlagAutomatically: boolean; enableSensitiveMediaDetectionForVideos: boolean; - /** Format: id */ - proxyAccountId: string | null; email: string | null; smtpSecure: boolean; smtpHost: string | null; @@ -10623,8 +10621,6 @@ export type operations = { sensitiveMediaDetectionSensitivity?: 'medium' | 'low' | 'high' | 'veryLow' | 'veryHigh'; setSensitiveFlagAutomatically?: boolean; enableSensitiveMediaDetectionForVideos?: boolean; - /** Format: misskey:id */ - proxyAccountId?: string | null; maintainerName?: string | null; maintainerEmail?: string | null; langs?: string[];