From d28866f71a2fd1809f595bf599cc3914834f74e2 Mon Sep 17 00:00:00 2001 From: Namekuji <11836635+nmkj-io@users.noreply.github.com> Date: Sat, 29 Apr 2023 11:09:29 -0400 Subject: enhance: account migration (#10592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 2321214c98591bcfe1385c1ab5bf0ff7b471ae1d. * 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? * :v: * 移行を行ったアカウントからのフォローリクエストの自動許可を調整 * 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 * :art: * 制限を5から10に緩和 * movedTo(Uri), alsoKnownAsはユーザーidを返すように * test api res * fix * 元アカウントはミュートし続ける * :art: * unfollow * fix * getUserUriをUserEntityServiceに * ? * job! * :art: * instance => server * accountMovedShort, forbiddenBecauseYouAreMigrated * accountMovedShort * fix test * import, pin禁止 * 実績を凍結する * clean up * :v: * 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 Co-authored-by: syuilo --- packages/backend/src/server/api/endpoints/notes/create.ts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages/backend/src/server/api/endpoints/notes/create.ts') diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 69fafcb9c7..fa2dc447d8 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -18,6 +18,8 @@ export const meta = { requireCredential: true, + prohibitMoved: true, + limit: { duration: ms('1hour'), max: 300, -- cgit v1.2.3-freya From 5dfbce7571d0ecb70a9be6610f7906b702700d25 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 6 May 2023 08:15:17 +0900 Subject: feat: チャンネルの削除 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve #7171 Resolve #9935 --- CHANGELOG.md | 4 +++- locales/ja-JP.yml | 4 ++++ .../migration/1683328299359-channelArchive.js | 13 +++++++++++++ .../src/core/entities/ChannelEntityService.ts | 1 + packages/backend/src/models/entities/Channel.ts | 6 ++++++ packages/backend/src/models/json-schema/channel.ts | 4 ++++ .../src/server/api/endpoints/channels/featured.ts | 1 + .../src/server/api/endpoints/channels/owned.ts | 1 + .../src/server/api/endpoints/channels/search.ts | 3 ++- .../src/server/api/endpoints/channels/update.ts | 2 ++ .../backend/src/server/api/endpoints/notes/create.ts | 2 +- packages/frontend/src/pages/channel-editor.vue | 20 +++++++++++++++++++- packages/frontend/src/pages/channel.vue | 3 +++ 13 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 packages/backend/migration/1683328299359-channelArchive.js (limited to 'packages/backend/src/server/api/endpoints/notes/create.ts') diff --git a/CHANGELOG.md b/CHANGELOG.md index 900f0992df..b2e80ffba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ * ユーザーメニューから追加できます。 (デスクトップ表示ではusernameの右側のボタンからも追加可能) - チャンネルに色を設定できるようになりました。各ノートに設定した色のインジケーターが表示されます。 +- チャンネルをアーカイブできるようになりました。 + * アーカイブすると、チャンネル一覧や検索結果に表示されなくなり、新たな書き込みもできなくなります。 - ロールタイムラインをロールごとに表示するかどうかの選択できるようになりました。 * デフォルトがオフになるので、ロールタイムラインを表示する場合はオンにしてください。 - ロールに強制的にNSFWを付与するポリシーを追加 @@ -46,10 +48,10 @@ - データセーバーモードを追加 * 画像が全て隠れた状態で表示されるようになります - 1枚だけのメディアリストの画像のアスペクト比を画像に応じて縦長にするように +- プロフィール設定「追加情報」の項目の削除と並び替えができるように - 新しい実績を追加 - Fix: AiScript APIのMk:dialogで何も返していなかったのをNULLを返すように修正 - Fix: リアクションをホバーした時のユーザーリストで猫耳が切れてしまっていた問題を修正 -- プロフィール設定「追加情報」の項目の削除と並び替えができるように ### Server - channel/searchのqueryが空の場合に全てのチャンネルを返すように変更 diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 2376f8b06b..402eeac16e 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1031,6 +1031,10 @@ continue: "続ける" preservedUsernames: "予約ユーザー名" preservedUsernamesDescription: "予約するユーザー名を改行で列挙します。ここで指定されたユーザー名はアカウント作成時に使えなくなりますが、管理者によるアカウント作成時はこの制限を受けません。また、既に存在するアカウントも影響を受けません。" createNoteFromTheFile: "このファイルからノートを作成" +archive: "アーカイブ" +channelArchiveConfirmTitle: "{name}をアーカイブしますか?" +channelArchiveConfirmDescription: "アーカイブすると、チャンネル一覧や検索結果に表示されなくなり、新たな書き込みもできなくなります。" +thisChannelArchived: "このチャンネルはアーカイブされています。" _serverRules: description: "新規登録前に表示する、サーバーの簡潔なルールを設定します。内容は利用規約の要約とすることを推奨します。" diff --git a/packages/backend/migration/1683328299359-channelArchive.js b/packages/backend/migration/1683328299359-channelArchive.js new file mode 100644 index 0000000000..83695ff537 --- /dev/null +++ b/packages/backend/migration/1683328299359-channelArchive.js @@ -0,0 +1,13 @@ +export class ChannelArchive1683328299359 { + name = 'ChannelArchive1683328299359' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "channel" ADD "isArchived" boolean NOT NULL DEFAULT false`); + await queryRunner.query(`CREATE INDEX "IDX_cc7c72974f1b2f385a8921f094" ON "channel" ("isArchived") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_cc7c72974f1b2f385a8921f094"`); + await queryRunner.query(`ALTER TABLE "channel" DROP COLUMN "isArchived"`); + } +} diff --git a/packages/backend/src/core/entities/ChannelEntityService.ts b/packages/backend/src/core/entities/ChannelEntityService.ts index 05eb836580..15ffd44861 100644 --- a/packages/backend/src/core/entities/ChannelEntityService.ts +++ b/packages/backend/src/core/entities/ChannelEntityService.ts @@ -75,6 +75,7 @@ export class ChannelEntityService { bannerUrl: banner ? this.driveFileEntityService.getPublicUrl(banner) : null, pinnedNoteIds: channel.pinnedNoteIds, color: channel.color, + isArchived: channel.isArchived, usersCount: channel.usersCount, notesCount: channel.notesCount, diff --git a/packages/backend/src/models/entities/Channel.ts b/packages/backend/src/models/entities/Channel.ts index ebbfc439ad..d7c4583da3 100644 --- a/packages/backend/src/models/entities/Channel.ts +++ b/packages/backend/src/models/entities/Channel.ts @@ -70,6 +70,12 @@ export class Channel { }) public color: string; + @Index() + @Column('boolean', { + default: false, + }) + public isArchived: boolean; + @Index() @Column('integer', { default: 0, diff --git a/packages/backend/src/models/json-schema/channel.ts b/packages/backend/src/models/json-schema/channel.ts index cb42c782b1..fd61a70c0e 100644 --- a/packages/backend/src/models/json-schema/channel.ts +++ b/packages/backend/src/models/json-schema/channel.ts @@ -30,6 +30,10 @@ export const packedChannelSchema = { format: 'url', nullable: true, optional: false, }, + isArchived: { + type: 'boolean', + optional: false, nullable: false, + }, notesCount: { type: 'number', nullable: false, optional: false, diff --git a/packages/backend/src/server/api/endpoints/channels/featured.ts b/packages/backend/src/server/api/endpoints/channels/featured.ts index d25faae38d..1a8d1164c7 100644 --- a/packages/backend/src/server/api/endpoints/channels/featured.ts +++ b/packages/backend/src/server/api/endpoints/channels/featured.ts @@ -38,6 +38,7 @@ export default class extends Endpoint { super(meta, paramDef, async (ps, me) => { const query = this.channelsRepository.createQueryBuilder('channel') .where('channel.lastNotedAt IS NOT NULL') + .andWhere('channel.isArchived = FALSE') .orderBy('channel.lastNotedAt', 'DESC'); const channels = await query.take(10).getMany(); diff --git a/packages/backend/src/server/api/endpoints/channels/owned.ts b/packages/backend/src/server/api/endpoints/channels/owned.ts index 59df0616be..6556e6e105 100644 --- a/packages/backend/src/server/api/endpoints/channels/owned.ts +++ b/packages/backend/src/server/api/endpoints/channels/owned.ts @@ -45,6 +45,7 @@ export default class extends Endpoint { ) { super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.channelsRepository.createQueryBuilder(), ps.sinceId, ps.untilId) + .andWhere('channel.isArchived = FALSE') .andWhere({ userId: me.id }); const channels = await query diff --git a/packages/backend/src/server/api/endpoints/channels/search.ts b/packages/backend/src/server/api/endpoints/channels/search.ts index 900723ff8a..a3b40b0bbd 100644 --- a/packages/backend/src/server/api/endpoints/channels/search.ts +++ b/packages/backend/src/server/api/endpoints/channels/search.ts @@ -46,7 +46,8 @@ export default class extends Endpoint { private queryService: QueryService, ) { super(meta, paramDef, async (ps, me) => { - const query = this.queryService.makePaginationQuery(this.channelsRepository.createQueryBuilder('channel'), ps.sinceId, ps.untilId); + const query = this.queryService.makePaginationQuery(this.channelsRepository.createQueryBuilder('channel'), ps.sinceId, ps.untilId) + .andWhere('channel.isArchived = FALSE'); if (ps.query !== '') { if (ps.type === 'nameAndDescription') { diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index a4e38d429d..30d7f8b244 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -47,6 +47,7 @@ export const paramDef = { name: { type: 'string', minLength: 1, maxLength: 128 }, description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, bannerId: { type: 'string', format: 'misskey:id', nullable: true }, + isArchived: { type: 'boolean', nullable: true }, pinnedNoteIds: { type: 'array', items: { @@ -106,6 +107,7 @@ export default class extends Endpoint { ...(ps.description !== undefined ? { description: ps.description } : {}), ...(ps.pinnedNoteIds !== undefined ? { pinnedNoteIds: ps.pinnedNoteIds } : {}), ...(ps.color !== undefined ? { color: ps.color } : {}), + ...(typeof ps.isArchived === 'boolean' ? { isArchived: ps.isArchived } : {}), ...(banner ? { bannerId: banner.id } : {}), }); diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index fa2dc447d8..3f7f2cdece 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -262,7 +262,7 @@ export default class extends Endpoint { let channel: Channel | null = null; if (ps.channelId != null) { - channel = await this.channelsRepository.findOneBy({ id: ps.channelId }); + channel = await this.channelsRepository.findOneBy({ id: ps.channelId, isArchived: false }); if (channel == null) { throw new ApiError(meta.errors.noSuchChannel); diff --git a/packages/frontend/src/pages/channel-editor.vue b/packages/frontend/src/pages/channel-editor.vue index 488738f31c..4050c087da 100644 --- a/packages/frontend/src/pages/channel-editor.vue +++ b/packages/frontend/src/pages/channel-editor.vue @@ -46,8 +46,9 @@ -
+
{{ channelId ? i18n.ts.save : i18n.ts.create }} + {{ i18n.ts.archive }}
@@ -151,6 +152,23 @@ function save() { } } +async function archive() { + const { canceled } = await os.confirm({ + type: 'warning', + title: i18n.t('channelArchiveConfirmTitle', { name: name }), + text: i18n.ts.channelArchiveConfirmDescription, + }); + + if (canceled) return; + + os.api('channels/update', { + channelId: props.channelId, + isArchived: true, + }).then(() => { + os.success(); + }); +} + function setBannerImage(evt) { selectFile(evt.currentTarget ?? evt.target, null).then(file => { bannerId = file.id; diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index 30e18c32ba..0a2f66d4fc 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -28,6 +28,8 @@
+ {{ i18n.ts.thisChannelArchived }} + @@ -77,6 +79,7 @@ import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import { defaultStore } from '@/store'; import MkNote from '@/components/MkNote.vue'; +import MkInfo from '@/components/MkInfo.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; const router = useRouter(); -- cgit v1.2.3-freya