Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance(backend): refine system account #15530

Open
wants to merge 30 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/test-federation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,18 @@ jobs:
bash ./setup.sh
sudo chmod 644 ./certificates/*.test.key
- name: Start servers
id: start_servers
continue-on-error: true
# https://github.com/docker/compose/issues/1294#issuecomment-374847206
run: |
cd packages/backend/test-federation
docker compose up -d --scale tester=0
- name: Print start_servers error
if: ${{ steps.start_servers.outcome == 'failure' }}
run: |
cd packages/backend/test-federation
docker compose logs | tail -n 300
exit 1
- name: Test
run: |
cd packages/backend/test-federation
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/basic.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ describe('After user setup', () => {
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
cy.get('[data-cy-open-post-form-submit]').click();

cy.contains('Hello, Misskey!');
cy.contains('Hello, Misskey!', { timeout: 15000 });
});

it('open note form with hotkey', () => {
Expand Down
4 changes: 4 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10058,6 +10058,10 @@ export interface Locale extends ILocale {
* ギャラリーの投稿を削除
*/
"deleteGalleryPost": string;
/**
* プロキシアカウントの説明を更新
*/
"updateProxyAccountDescription": string;
};
"_fileViewer": {
/**
Expand Down
1 change: 1 addition & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2664,6 +2664,7 @@ _moderationLogTypes:
deletePage: "ページを削除"
deleteFlash: "Playを削除"
deleteGalleryPost: "ギャラリーの投稿を削除"
updateProxyAccountDescription: "プロキシアカウントの説明を更新"

_fileViewer:
title: "ファイルの詳細"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"build-storybook": "pnpm --filter frontend build-storybook",
"build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json --no-build && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
"start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js",
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
"start:test": "ncp ./.github/misskey/test.yml ./.config/test.yml && cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
"init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate",
"revert": "cd packages/backend && pnpm revert",
Expand All @@ -37,7 +37,7 @@
"cy:open": "pnpm cypress open --browser --e2e --config-file=cypress.config.ts",
"cy:run": "pnpm cypress run",
"e2e": "pnpm start-server-and-test start:test http://localhost:61812 cy:run",
"e2e-dev-container": "cp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 cy:run",
"e2e-dev-container": "ncp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 cy:run",
"jest": "cd packages/backend && pnpm jest",
"jest-and-coverage": "cd packages/backend && pnpm jest-and-coverage",
"test": "pnpm -r test",
Expand Down
37 changes: 37 additions & 0 deletions packages/backend/migration/1740121393164-system-accounts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class SystemAccounts1740121393164 {
name = 'SystemAccounts1740121393164'

async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "system_account" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "type" character varying(256) NOT NULL, CONSTRAINT "PK_edb56f4aaf9ddd50ee556da97ba" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_41a3c87a37aea616ee459369e1" ON "system_account" ("userId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c362033aee0ea51011386a5a7e" ON "system_account" ("type") `);
await queryRunner.query(`ALTER TABLE "system_account" ADD CONSTRAINT "FK_41a3c87a37aea616ee459369e12" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);

const instanceActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'instance.actor'`);
if (instanceActor.length > 0) {
await queryRunner.query(`INSERT INTO "system_account" ("id", "userId", "type") VALUES ('${instanceActor[0].id}', '${instanceActor[0].id}', 'actor')`);
}

const relayActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'relay.actor'`);
if (relayActor.length > 0) {
await queryRunner.query(`INSERT INTO "system_account" ("id", "userId", "type") VALUES ('${relayActor[0].id}', '${relayActor[0].id}', 'relay')`);
}

const meta = await queryRunner.query(`SELECT "proxyAccountId" FROM "meta" ORDER BY "id" DESC LIMIT 1`);
if (!meta && meta.length >= 1 && meta[0].proxyAccountId) {
await queryRunner.query(`INSERT INTO "system_account" ("id", "userId", "type") VALUES ('${meta[0].proxyAccountId}', '${meta[0].proxyAccountId}', 'proxy')`);
}
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "system_account" DROP CONSTRAINT "FK_41a3c87a37aea616ee459369e12"`);
await queryRunner.query(`DROP INDEX "public"."IDX_c362033aee0ea51011386a5a7e"`);
await queryRunner.query(`DROP INDEX "public"."IDX_41a3c87a37aea616ee459369e1"`);
await queryRunner.query(`DROP TABLE "system_account"`);
}
}
18 changes: 18 additions & 0 deletions packages/backend/migration/1740129169650-system-accounts-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class SystemAccounts21740129169650 {
name = 'SystemAccounts21740129169650'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP CONSTRAINT "FK_ab1bc0c1e209daa77b8e8d212ad"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "proxyAccountId"`);
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "proxyAccountId" character varying(32)`);
await queryRunner.query(`ALTER TABLE "meta" ADD CONSTRAINT "FK_ab1bc0c1e209daa77b8e8d212ad" FOREIGN KEY ("proxyAccountId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
Comment on lines +15 to +16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

system_accountテーブルからmeta.proxyAccountIdを復元するクエリがあったほうが良いように思えます。

}
}
23 changes: 23 additions & 0 deletions packages/backend/migration/1740133121105-system-accounts-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class SystemAccounts31740133121105 {
name = 'SystemAccounts31740133121105'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "rootUserId" character varying(32)`);
await queryRunner.query(`ALTER TABLE "meta" ADD CONSTRAINT "FK_c80e4079d632f95eac06a9d28cc" FOREIGN KEY ("rootUserId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);

const users = await queryRunner.query(`SELECT "id" FROM "user" WHERE "isRoot" = true LIMIT 1`);
if (users.length > 0) {
await queryRunner.query(`UPDATE "meta" SET "rootUserId" = $1`, [users[0].id]);
}
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP CONSTRAINT "FK_c80e4079d632f95eac06a9d28cc"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "rootUserId"`);
}
}
2 changes: 1 addition & 1 deletion packages/backend/src/GlobalModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 3 additions & 3 deletions packages/backend/src/core/AbuseReportService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { bindThis } from '@/decorators.js';
import type { AbuseUserReportsRepository, MiAbuseUserReport, MiUser, UsersRepository } from '@/models/_.js';
import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
import { QueueService } from '@/core/QueueService.js';
import { InstanceActorService } from '@/core/InstanceActorService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { IdService } from './IdService.js';

@Injectable()
Expand All @@ -27,7 +27,7 @@ export class AbuseReportService {
private idService: IdService,
private abuseReportNotificationService: AbuseReportNotificationService,
private queueService: QueueService,
private instanceActorService: InstanceActorService,
private systemAccountService: SystemAccountService,
private apRendererService: ApRendererService,
private moderationLogService: ModerationLogService,
) {
Expand Down Expand Up @@ -136,7 +136,7 @@ export class AbuseReportService {
forwarded: true,
});

const actor = await this.instanceActorService.getInstanceActor();
const actor = await this.systemAccountService.fetch('actor');
const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId });

const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment);
Expand Down
14 changes: 6 additions & 8 deletions packages/backend/src/core/AccountMoveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
) {
}

Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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 } }]);
}
}

Expand Down
24 changes: 6 additions & 18 deletions packages/backend/src/core/CoreModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { AppLockService } from './AppLockService.js';
import { AchievementService } from './AchievementService.js';
import { AvatarDecorationService } from './AvatarDecorationService.js';
import { CaptchaService } from './CaptchaService.js';
import { CreateSystemUserService } from './CreateSystemUserService.js';
import { CustomEmojiService } from './CustomEmojiService.js';
import { DeleteAccountService } from './DeleteAccountService.js';
import { DownloadService } from './DownloadService.js';
Expand All @@ -37,7 +36,7 @@ import { HashtagService } from './HashtagService.js';
import { HttpRequestService } from './HttpRequestService.js';
import { IdService } from './IdService.js';
import { ImageProcessingService } from './ImageProcessingService.js';
import { InstanceActorService } from './InstanceActorService.js';
import { SystemAccountService } from './SystemAccountService.js';
import { InternalStorageService } from './InternalStorageService.js';
import { MetaService } from './MetaService.js';
import { MfmService } from './MfmService.js';
Expand Down Expand Up @@ -69,7 +68,6 @@ import { UserSuspendService } from './UserSuspendService.js';
import { UserAuthService } from './UserAuthService.js';
import { VideoProcessingService } from './VideoProcessingService.js';
import { UserWebhookService } from './UserWebhookService.js';
import { ProxyAccountService } from './ProxyAccountService.js';
import { UtilityService } from './UtilityService.js';
import { FileInfoService } from './FileInfoService.js';
import { SearchService } from './SearchService.js';
Expand Down Expand Up @@ -167,7 +165,6 @@ const $AppLockService: Provider = { provide: 'AppLockService', useExisting: AppL
const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService };
const $AvatarDecorationService: Provider = { provide: 'AvatarDecorationService', useExisting: AvatarDecorationService };
const $CaptchaService: Provider = { provide: 'CaptchaService', useExisting: CaptchaService };
const $CreateSystemUserService: Provider = { provide: 'CreateSystemUserService', useExisting: CreateSystemUserService };
const $CustomEmojiService: Provider = { provide: 'CustomEmojiService', useExisting: CustomEmojiService };
const $DeleteAccountService: Provider = { provide: 'DeleteAccountService', useExisting: DeleteAccountService };
const $DownloadService: Provider = { provide: 'DownloadService', useExisting: DownloadService };
Expand All @@ -180,7 +177,6 @@ const $HashtagService: Provider = { provide: 'HashtagService', useExisting: Hash
const $HttpRequestService: Provider = { provide: 'HttpRequestService', useExisting: HttpRequestService };
const $IdService: Provider = { provide: 'IdService', useExisting: IdService };
const $ImageProcessingService: Provider = { provide: 'ImageProcessingService', useExisting: ImageProcessingService };
const $InstanceActorService: Provider = { provide: 'InstanceActorService', useExisting: InstanceActorService };
const $InternalStorageService: Provider = { provide: 'InternalStorageService', useExisting: InternalStorageService };
const $MetaService: Provider = { provide: 'MetaService', useExisting: MetaService };
const $MfmService: Provider = { provide: 'MfmService', useExisting: MfmService };
Expand All @@ -191,7 +187,7 @@ const $NotePiningService: Provider = { provide: 'NotePiningService', useExisting
const $NoteReadService: Provider = { provide: 'NoteReadService', useExisting: NoteReadService };
const $NotificationService: Provider = { provide: 'NotificationService', useExisting: NotificationService };
const $PollService: Provider = { provide: 'PollService', useExisting: PollService };
const $ProxyAccountService: Provider = { provide: 'ProxyAccountService', useExisting: ProxyAccountService };
const $SystemAccountService: Provider = { provide: 'SystemAccountService', useExisting: SystemAccountService };
const $PushNotificationService: Provider = { provide: 'PushNotificationService', useExisting: PushNotificationService };
const $QueryService: Provider = { provide: 'QueryService', useExisting: QueryService };
const $ReactionService: Provider = { provide: 'ReactionService', useExisting: ReactionService };
Expand Down Expand Up @@ -318,7 +314,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
AchievementService,
AvatarDecorationService,
CaptchaService,
CreateSystemUserService,
CustomEmojiService,
DeleteAccountService,
DownloadService,
Expand All @@ -331,7 +326,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
HttpRequestService,
IdService,
ImageProcessingService,
InstanceActorService,
InternalStorageService,
MetaService,
MfmService,
Expand All @@ -342,7 +336,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
NoteReadService,
NotificationService,
PollService,
ProxyAccountService,
SystemAccountService,
PushNotificationService,
QueryService,
ReactionService,
Expand Down Expand Up @@ -465,7 +459,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$AchievementService,
$AvatarDecorationService,
$CaptchaService,
$CreateSystemUserService,
$CustomEmojiService,
$DeleteAccountService,
$DownloadService,
Expand All @@ -478,7 +471,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$HttpRequestService,
$IdService,
$ImageProcessingService,
$InstanceActorService,
$InternalStorageService,
$MetaService,
$MfmService,
Expand All @@ -489,7 +481,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$NoteReadService,
$NotificationService,
$PollService,
$ProxyAccountService,
$SystemAccountService,
$PushNotificationService,
$QueryService,
$ReactionService,
Expand Down Expand Up @@ -613,7 +605,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
AchievementService,
AvatarDecorationService,
CaptchaService,
CreateSystemUserService,
CustomEmojiService,
DeleteAccountService,
DownloadService,
Expand All @@ -626,7 +617,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
HttpRequestService,
IdService,
ImageProcessingService,
InstanceActorService,
InternalStorageService,
MetaService,
MfmService,
Expand All @@ -637,7 +627,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
NoteReadService,
NotificationService,
PollService,
ProxyAccountService,
SystemAccountService,
PushNotificationService,
QueryService,
ReactionService,
Expand Down Expand Up @@ -759,7 +749,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$AchievementService,
$AvatarDecorationService,
$CaptchaService,
$CreateSystemUserService,
$CustomEmojiService,
$DeleteAccountService,
$DownloadService,
Expand All @@ -772,7 +761,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$HttpRequestService,
$IdService,
$ImageProcessingService,
$InstanceActorService,
$InternalStorageService,
$MetaService,
$MfmService,
Expand All @@ -783,7 +771,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$NoteReadService,
$NotificationService,
$PollService,
$ProxyAccountService,
$SystemAccountService,
$PushNotificationService,
$QueryService,
$ReactionService,
Expand Down
Loading
Loading