enhance: account migration (#10592)

* copy block and mute then create follow and unfollow jobs

* copy block and mute and update lists when detecting an account has moved

* no need to care promise orders

* refactor updating actor and target

* automatically accept if a locked account had accepted an old account

* fix exception format

* prevent the old account from calling some endpoints

* do not unfollow when moving

* adjust following and follower counts

* check movedToUri when receiving a follow request

* skip if no need to adjust

* Revert "disable account migration"

This reverts commit 2321214c98.

* fix translation specifier

* fix checking alsoKnownAs and uri

* fix updating account

* fix refollowing locked account

* decrease followersCount if followed by the old account

* adjust following and followers counts when unfollowing

* fix copying mutings

* prohibit moved account from moving again

* fix move service

* allow app creation after moving

* fix lint

* remove unnecessary field

* fix cache update

* add e2e test

* add e2e test of accepting the new account automatically

* force follow if any error happens

* remove unnecessary joins

* use Array.map instead of for const of

* ユーザーリストの移行は追加のみを行う

* nanka iroiro

* fix misskey-js?

* ✌️

* 移行を行ったアカウントからのフォローリクエストの自動許可を調整

* newUriを外に出す

* newUriを外に出す2

* clean up

* fix newUri

* prevent moving if the destination account has already moved

* set alsoKnownAs via /i/update

* fix database initialization

* add return type

* prohibit updating alsoKnownAs after moving

* skip to add to alsoKnownAs if toUrl is known

* skip adding to the list if it already has

* use Acct.parse instead

* rename error code

* 🎨

* 制限を5から10に緩和

* movedTo(Uri), alsoKnownAsはユーザーidを返すように

* test api res

* fix

* 元アカウントはミュートし続ける

* 🎨

* unfollow

* fix

* getUserUriをUserEntityServiceに

* ?

* job!

* 🎨

* instance => server

* accountMovedShort, forbiddenBecauseYouAreMigrated

* accountMovedShort

* fix test

* import, pin禁止

* 実績を凍結する

* clean up

* ✌️

* change message

* ブロック, フォロー, ミュート, リストのインポートファイルの制限を32MiBに

* Revert "ブロック, フォロー, ミュート, リストのインポートファイルの制限を32MiBに"

This reverts commit 3bd7be35d8aa455cb01ae58f8172a71a50485db1.

* validateAlsoKnownAs

* 移行後2時間以内はインポート可能なファイルサイズを拡大

* clean up

* どうせactorをupdatePersonで更新するならupdatePersonしか移行処理を発行しないことにする

* handle error?

* リモートからの移行処理の条件を是正

* log, port

* fix

* fix

* enhance(dev): non-production環境でhttpサーバー間でもユーザー、ノートの連合が可能なように

* refactor (use checkHttps)

* MISSKEY_WEBFINGER_USE_HTTP

* Environment Variable readme

* NEVER USE IN PRODUCTION

* fix punyHost

* fix indent

* fix

* experimental

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
Namekuji 2023-04-29 11:09:29 -04:00 committed by GitHub
parent 149ddebf16
commit d28866f71a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 1558 additions and 470 deletions

View file

@ -1,63 +1,121 @@
<template>
<div class="_gaps_m">
<FormSection first>
<template #label>{{ i18n.ts._accountMigration.moveTo }}</template>
<MkInput v-model="moveToAccount" manual-save>
<template #prefix><i class="ti ti-plane-departure"></i></template>
<template #label>{{ i18n.ts._accountMigration.moveToLabel }}</template>
</MkInput>
</FormSection>
<FormInfo warn>{{ i18n.ts._accountMigration.moveAccountDescription }}</FormInfo>
<FormSection>
<FormInfo warn>
{{ i18n.ts.ThisIsExperimentalFeature }}
</FormInfo>
<MkFolder :default-open="true">
<template #icon><i class="ti ti-plane-arrival"></i></template>
<template #label>{{ i18n.ts._accountMigration.moveFrom }}</template>
<MkInput v-model="accountAlias" manual-save>
<template #prefix><i class="ti ti-plane-arrival"></i></template>
<template #label>{{ i18n.ts._accountMigration.moveFromLabel }}</template>
</MkInput>
</FormSection>
<FormInfo warn>{{ i18n.ts._accountMigration.moveFromDescription }}</FormInfo>
<template #caption>{{ i18n.ts._accountMigration.moveFromSub }}</template>
<div class="_gaps_m">
<FormInfo warn>
{{ i18n.ts._accountMigration.moveFromDescription }}
</FormInfo>
<div>
<MkButton :disabled="accountAliases.length >= 10" inline style="margin-right: 8px;" @click="add"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
<MkButton inline primary @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</div>
<div class="_gaps">
<MkInput v-for="(_, i) in accountAliases" v-model="accountAliases[i]">
<template #prefix><i class="ti ti-plane-arrival"></i></template>
<template #label>{{ i18n.t('_accountMigration.moveFromLabel', { n: i + 1 }) }}</template>
</MkInput>
</div>
</div>
</MkFolder>
<MkFolder :default-open="!!$i?.movedTo">
<template #icon><i class="ti ti-plane-departure"></i></template>
<template #label>{{ i18n.ts._accountMigration.moveTo }}</template>
<div class="_gaps_m">
<FormInfo>{{ i18n.ts._accountMigration.moveAccountDescription }}</FormInfo>
<template v-if="$i && !$i.movedTo">
<FormInfo>{{ i18n.ts._accountMigration.moveAccountHowTo }}</FormInfo>
<FormInfo warn>{{ i18n.ts._accountMigration.moveCannotBeUndone }}</FormInfo>
<MkInput v-model="moveToAccount">
<template #prefix><i class="ti ti-plane-departure"></i></template>
<template #label>{{ i18n.ts._accountMigration.moveToLabel }}</template>
</MkInput>
<MkButton inline danger :disabled="!moveToAccount" @click="move">
<i class="ti ti-check"></i> {{ i18n.ts._accountMigration.startMigration }}
</MkButton>
</template>
<template v-else-if="$i">
<FormInfo>{{ i18n.ts._accountMigration.postMigrationNote }}</FormInfo>
<FormInfo warn>{{ i18n.ts._accountMigration.movedAndCannotBeUndone }}</FormInfo>
<div>{{ i18n.ts._accountMigration.movedTo }}</div>
<MkUserInfo v-if="movedTo" :user="movedTo" class="_panel _shadow" />
</template>
</div>
</MkFolder>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import FormSection from '@/components/form/section.vue';
import { ref } from 'vue';
import FormInfo from '@/components/MkInfo.vue';
import MkInput from '@/components/MkInput.vue';
import MkButton from '@/components/MkButton.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkUserInfo from '@/components/MkUserInfo.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
import { $i } from '@/account';
import { toString } from 'misskey-js/built/acct';
import { UserDetailed } from 'misskey-js/built/entities';
import { unisonReload } from '@/scripts/unison-reload';
const moveToAccount = ref('');
const accountAlias = ref('');
const movedTo = ref<UserDetailed>();
const accountAliases = ref(['']);
async function init() {
if ($i?.movedTo) {
movedTo.value = await os.api('users/show', { userId: $i.movedTo });
} else {
moveToAccount.value = '';
}
if ($i?.alsoKnownAs && $i.alsoKnownAs.length > 0) {
const alsoKnownAs = await os.api('users/show', { userIds: $i.alsoKnownAs });
accountAliases.value = (alsoKnownAs && alsoKnownAs.length > 0) ? alsoKnownAs.map(user => `@${toString(user)}`) : [''];
} else {
accountAliases.value = [''];
}
}
async function move(): Promise<void> {
const account = moveToAccount.value;
const confirm = await os.confirm({
type: 'warning',
text: i18n.t('migrationConfirm', { account: account.toString() }),
text: i18n.t('_accountMigration.migrationConfirm', { account }),
});
if (confirm.canceled) return;
os.apiWithDialog('i/move', {
await os.apiWithDialog('i/move', {
moveToAccount: account,
});
unisonReload();
}
function add(): void {
accountAliases.value.push('');
}
async function save(): Promise<void> {
const account = accountAlias.value;
os.apiWithDialog('i/known-as', {
alsoKnownAs: account,
const alsoKnownAs = accountAliases.value.map(alias => alias.trim()).filter(alias => alias !== '');
const i = await os.apiWithDialog('i/update', {
alsoKnownAs,
});
$i.alsoKnownAs = i.alsoKnownAs;
init();
}
watch(accountAlias, async () => {
await save();
});
watch(moveToAccount, async () => {
await move();
});
init();
definePageMetadata({
title: i18n.ts.accountMigration,