enhance(backend): refine system account (#15530)

* wip

* wip

* wip

* Update SystemAccountService.ts

* Update 1740121393164-system-accounts.js

* Update DeleteAccountService.ts

* wip

* wip

* wip

* wip

* Update 1740121393164-system-accounts.js

* Update RepositoryModule.ts

* wip

* wip

* wip

* Update ApRendererService.ts

* wip

* wip

* Update SystemAccountService.ts

* fix tests

* fix tests

* fix tests

* fix tests

* fix tests

* fix tests

* add print logs

* ログが長すぎて出てないかもしれない

* fix migration

* refactor

* fix fed-tests

* Update RelayService.ts

* merge

* Update user.test.ts

* chore: emit log

* fix: tweak sleep duration

* fix: exit 1

* fix: wait for misskey processes to become healthy

* fix: longer sleep for user deletion

* fix: make sleep longer again

* デッドロック解消の試み

https://github.com/misskey-dev/misskey/issues/15005

* Revert "デッドロック解消の試み"

This reverts commit 266141f66f.

* wip

* Update SystemAccountService.ts

---------

Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com>
This commit is contained in:
syuilo
2025-03-02 20:06:20 +09:00
committed by GitHub
parent 7114523d84
commit 616cccf251
71 changed files with 783 additions and 439 deletions

View File

@@ -7,14 +7,10 @@ import type { Config } from '@/config.js';
import type { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js';
import type { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import type { ApRequestService } from '@/core/activitypub/ApRequestService.js';
import { Resolver } from '@/core/activitypub/ApResolverService.js';
import type { IObject } from '@/core/activitypub/type.js';
import type { HttpRequestService } from '@/core/HttpRequestService.js';
import type { InstanceActorService } from '@/core/InstanceActorService.js';
import type { LoggerService } from '@/core/LoggerService.js';
import type { MetaService } from '@/core/MetaService.js';
import type { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import type {
FollowRequestsRepository,
MiMeta,
@@ -23,6 +19,9 @@ import type {
PollsRepository,
UsersRepository,
} from '@/models/_.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { bindThis } from '@/decorators.js';
import { Resolver } from '@/core/activitypub/ApResolverService.js';
type MockResponse = {
type: string;
@@ -43,7 +42,7 @@ export class MockResolver extends Resolver {
{} as NoteReactionsRepository,
{} as FollowRequestsRepository,
{} as UtilityService,
{} as InstanceActorService,
{} as SystemAccountService,
{} as ApRequestService,
{} as HttpRequestService,
{} as ApRendererService,

View File

@@ -149,9 +149,9 @@ describe('AbuseReportNotificationService', () => {
});
beforeEach(async () => {
root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true });
alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false });
bob = await createUser({ username: 'bob', usernameLower: 'bob', isRoot: false });
root = await createUser({ username: 'root', usernameLower: 'root' });
alice = await createUser({ username: 'alice', usernameLower: 'alice' });
bob = await createUser({ username: 'bob', usernameLower: 'bob' });
systemWebhook1 = await createWebhook();
systemWebhook2 = await createWebhook();

View File

@@ -79,9 +79,9 @@ describe('FlashService', () => {
userProfilesRepository = app.get(DI.userProfilesRepository);
idService = app.get(IdService);
root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true });
alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false });
bob = await createUser({ username: 'bob', usernameLower: 'bob', isRoot: false });
root = await createUser({ username: 'root', usernameLower: 'root' });
alice = await createUser({ username: 'alice', usernameLower: 'alice' });
bob = await createUser({ username: 'bob', usernameLower: 'bob' });
});
afterEach(async () => {

View File

@@ -3,24 +3,21 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { UtilityService } from '@/core/UtilityService.js';
process.env.NODE_ENV = 'test';
import { jest } from '@jest/globals';
import { ModuleMocker } from 'jest-mock';
import { Test } from '@nestjs/testing';
import { GlobalModule } from '@/GlobalModule.js';
import { RelayService } from '@/core/RelayService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { CreateSystemUserService } from '@/core/CreateSystemUserService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { QueueService } from '@/core/QueueService.js';
import { IdService } from '@/core/IdService.js';
import type { RelaysRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { ModuleMocker } from 'jest-mock';
import type { TestingModule } from '@nestjs/testing';
import type { MockFunctionMetadata } from 'jest-mock';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { IdService } from '@/core/IdService.js';
import { QueueService } from '@/core/QueueService.js';
import { RelayService } from '@/core/RelayService.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { GlobalModule } from '@/GlobalModule.js';
import { UtilityService } from '@/core/UtilityService.js';
const moduleMocker = new ModuleMocker(global);
@@ -28,8 +25,6 @@ describe('RelayService', () => {
let app: TestingModule;
let relayService: RelayService;
let queueService: jest.Mocked<QueueService>;
let relaysRepository: RelaysRepository;
let userEntityService: UserEntityService;
beforeAll(async () => {
app = await Test.createTestingModule({
@@ -38,10 +33,10 @@ describe('RelayService', () => {
],
providers: [
IdService,
CreateSystemUserService,
ApRendererService,
RelayService,
UserEntityService,
SystemAccountService,
UtilityService,
],
})
@@ -61,8 +56,6 @@ describe('RelayService', () => {
relayService = app.get<RelayService>(RelayService);
queueService = app.get<QueueService>(QueueService) as jest.Mocked<QueueService>;
relaysRepository = app.get<RelaysRepository>(DI.relaysRepository);
userEntityService = app.get<UserEntityService>(UserEntityService);
});
afterAll(async () => {

View File

@@ -57,6 +57,12 @@ describe('RoleService', () => {
return await usersRepository.findOneByOrFail(x.identifiers[0]);
}
async function createRoot(data: Partial<MiUser> = {}) {
const user = await createUser(data);
meta.rootUserId = user.id;
return user;
}
async function createRole(data: Partial<MiRole> = {}) {
const x = await rolesRepository.insert({
id: genAidx(Date.now()),
@@ -279,7 +285,7 @@ describe('RoleService', () => {
describe('getModeratorIds', () => {
test('includeAdmins = false, includeRoot = false, excludeExpire = false', async () => {
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -305,7 +311,7 @@ describe('RoleService', () => {
test('includeAdmins = false, includeRoot = false, excludeExpire = true', async () => {
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -331,7 +337,7 @@ describe('RoleService', () => {
test('includeAdmins = true, includeRoot = false, excludeExpire = false', async () => {
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -357,7 +363,7 @@ describe('RoleService', () => {
test('includeAdmins = true, includeRoot = false, excludeExpire = true', async () => {
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -383,7 +389,7 @@ describe('RoleService', () => {
test('includeAdmins = false, includeRoot = true, excludeExpire = false', async () => {
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -409,7 +415,7 @@ describe('RoleService', () => {
test('root has moderator role', async () => {
const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -433,7 +439,7 @@ describe('RoleService', () => {
test('root has administrator role', async () => {
const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });
@@ -457,7 +463,7 @@ describe('RoleService', () => {
test('root has moderator role(expire)', async () => {
const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([
createUser(), createUser(), createUser(), createUser({ isRoot: true }),
createUser(), createUser(), createUser(), createRoot(),
]);
const role1 = await createRole({ name: 'admin', isAdministrator: true });

View File

@@ -97,7 +97,7 @@ describe('SystemWebhookService', () => {
}
async function beforeEachImpl() {
root = await createUser({ isRoot: true, username: 'root', usernameLower: 'root' });
root = await createUser({ username: 'root', usernameLower: 'root' });
}
async function afterEachImpl() {

View File

@@ -113,7 +113,7 @@ describe('UserSearchService', () => {
});
beforeEach(async () => {
root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true });
root = await createUser({ username: 'root', usernameLower: 'root' });
alice = await createUser({ username: 'Alice', usernameLower: 'alice' });
alyce = await createUser({ username: 'Alyce', usernameLower: 'alyce' });
alycia = await createUser({ username: 'Alycia', usernameLower: 'alycia' });

View File

@@ -91,7 +91,7 @@ describe('UserWebhookService', () => {
}
async function beforeEachImpl() {
root = await createUser({ isRoot: true, username: 'root', usernameLower: 'root' });
root = await createUser({ username: 'root', usernameLower: 'root' });
}
async function afterEachImpl() {

View File

@@ -88,8 +88,8 @@ describe('WebhookTestService', () => {
});
beforeEach(async () => {
root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true });
alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false });
root = await createUser({ username: 'root', usernameLower: 'root' });
alice = await createUser({ username: 'alice', usernameLower: 'alice' });
userWebhookService.fetchWebhooks.mockReturnValue(Promise.resolve([
{ id: 'dummy-webhook', active: true, userId: alice.id } as MiWebhook,

View File

@@ -316,7 +316,7 @@ describe('CheckModeratorsActivityProcessorService', () => {
createUser({}, { email: 'user2@example.com', emailVerified: false }),
createUser({}, { email: null, emailVerified: false }),
createUser({}, { email: 'user4@example.com', emailVerified: true }),
createUser({ isRoot: true }, { email: 'root@example.com', emailVerified: true }),
createUser({}, { email: 'root@example.com', emailVerified: true }),
]);
mockModeratorRole([user1, user2, user3, root]);
@@ -349,7 +349,7 @@ describe('CheckModeratorsActivityProcessorService', () => {
createUser({}, { email: 'user2@example.com', emailVerified: false }),
createUser({}, { email: null, emailVerified: false }),
createUser({}, { email: 'user4@example.com', emailVerified: true }),
createUser({ isRoot: true }, { email: 'root@example.com', emailVerified: true }),
createUser({}, { email: 'root@example.com', emailVerified: true }),
]);
mockModeratorRole([user1, user2, user3, root]);