Copy role on move (#15745)
* feat(backend): copyOnMoveAccount * feat(endpoints): copyOnMoveAccount * feat(frontend): copyOnMoveAccount * docs(changelog): アカウントのマイグレーション時に古いアカウントからロールをコピーできるようになりました。 * fix: spdx header for migration * Update locales/ja-JP.yml * copyOnMoveAccount -> preserveAssignmentOnMoveAccount * fix: check for preserveAssignmentOnMoveAccount --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
parent
440a4a4d8b
commit
cab82452ec
13 changed files with 83 additions and 1 deletions
|
|
@ -24,6 +24,7 @@ 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';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
|
||||
@Injectable()
|
||||
export class AccountMoveService {
|
||||
|
|
@ -61,6 +62,7 @@ export class AccountMoveService {
|
|||
private relayService: RelayService,
|
||||
private queueService: QueueService,
|
||||
private systemAccountService: SystemAccountService,
|
||||
private roleService: RoleService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +121,7 @@ export class AccountMoveService {
|
|||
await Promise.all([
|
||||
this.copyBlocking(src, dst),
|
||||
this.copyMutings(src, dst),
|
||||
this.copyRoles(src, dst),
|
||||
this.updateLists(src, dst),
|
||||
]);
|
||||
} catch {
|
||||
|
|
@ -201,6 +204,32 @@ export class AccountMoveService {
|
|||
await this.mutingsRepository.insert(arrayToInsert);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async copyRoles(src: ThinUser, dst: ThinUser): Promise<void> {
|
||||
// Insert new roles with the same values except userId
|
||||
// role service may have cache for roles so retrieve roles from service
|
||||
const [oldRoleAssignments, roles] = await Promise.all([
|
||||
this.roleService.getUserAssigns(src.id),
|
||||
this.roleService.getRoles(),
|
||||
]);
|
||||
|
||||
if (oldRoleAssignments.length === 0) return;
|
||||
|
||||
// No promise all since the only async operation is writing to the database
|
||||
for (const oldRoleAssignment of oldRoleAssignments) {
|
||||
const role = roles.find(x => x.id === oldRoleAssignment.roleId);
|
||||
if (role == null) continue; // Very unlikely however removing role may cause this case
|
||||
if (!role.preserveAssignmentOnMoveAccount) continue;
|
||||
|
||||
try {
|
||||
await this.roleService.assign(dst.id, role.id, oldRoleAssignment.expiresAt);
|
||||
} catch (e) {
|
||||
if (e instanceof RoleService.AlreadyAssignedError) continue;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update lists while moving accounts.
|
||||
* - No removal of the old account from the lists
|
||||
|
|
|
|||
|
|
@ -630,6 +630,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
|||
isModerator: values.isModerator,
|
||||
isExplorable: values.isExplorable,
|
||||
asBadge: values.asBadge,
|
||||
preserveAssignmentOnMoveAccount: values.preserveAssignmentOnMoveAccount,
|
||||
canEditMembersByModerator: values.canEditMembersByModerator,
|
||||
displayOrder: values.displayOrder,
|
||||
policies: values.policies,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import type { MiRole } from '@/models/Role.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { Packed } from '@/misc/json-schema.js';
|
||||
|
||||
@Injectable()
|
||||
export class RoleEntityService {
|
||||
|
|
@ -31,7 +32,7 @@ export class RoleEntityService {
|
|||
public async pack(
|
||||
src: MiRole['id'] | MiRole,
|
||||
me?: { id: MiUser['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'Role'>> {
|
||||
const role = typeof src === 'object' ? src : await this.rolesRepository.findOneByOrFail({ id: src });
|
||||
|
||||
const assignedCount = await this.roleAssignmentsRepository.createQueryBuilder('assign')
|
||||
|
|
@ -67,6 +68,7 @@ export class RoleEntityService {
|
|||
isModerator: role.isModerator,
|
||||
isExplorable: role.isExplorable,
|
||||
asBadge: role.asBadge,
|
||||
preserveAssignmentOnMoveAccount: role.preserveAssignmentOnMoveAccount,
|
||||
canEditMembersByModerator: role.canEditMembersByModerator,
|
||||
displayOrder: role.displayOrder,
|
||||
policies: policies,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue