From 3401ab012869662a5c1a624479165fcc81408c3f Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 10:04:14 +0900 Subject: [PATCH 01/19] :art: --- packages/frontend/src/pages/welcome.setup.vue | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/packages/frontend/src/pages/welcome.setup.vue b/packages/frontend/src/pages/welcome.setup.vue index 212d156a83..7728d97a65 100644 --- a/packages/frontend/src/pages/welcome.setup.vue +++ b/packages/frontend/src/pages/welcome.setup.vue @@ -1,8 +1,11 @@ @@ -72,6 +76,7 @@ import { signout, $i } from '@/account'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import { unisonReload } from '@/scripts/unison-reload'; +import FormSection from '@/components/form/section.vue'; const reportError = computed(defaultStore.makeGetterSetter('reportError')); const enableCondensedLineForAcct = computed(defaultStore.makeGetterSetter('enableCondensedLineForAcct')); From 78273f9f0da58f458665f8f070b324541eb49828 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 10:42:01 +0900 Subject: [PATCH 03/19] Update 01_bug-report.md --- .github/ISSUE_TEMPLATE/01_bug-report.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/01_bug-report.md b/.github/ISSUE_TEMPLATE/01_bug-report.md index b4a2f69879..f6fd593c85 100644 --- a/.github/ISSUE_TEMPLATE/01_bug-report.md +++ b/.github/ISSUE_TEMPLATE/01_bug-report.md @@ -37,7 +37,10 @@ Please include errors from the developer console and/or server log files if you ## 📌 Environment + Misskey version: +PostgreSQL version: +Redis version: Your OS: Your browser: From 84beecd27f17d512b85af300040f9ab45a5c67ad Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 11:27:41 +0900 Subject: [PATCH 04/19] fix lint --- packages/frontend/src/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/init.ts b/packages/frontend/src/init.ts index ddc1931d4c..91a009e8f8 100644 --- a/packages/frontend/src/init.ts +++ b/packages/frontend/src/init.ts @@ -449,7 +449,7 @@ if ($i) { const latestDonationInfoShownAt = miLocalStorage.getItem('latestDonationInfoShownAt'); const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo'); - if (neverShowDonationInfo !== 'true' && (new Date($i.createdAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith("/miauth")) { + if (neverShowDonationInfo !== 'true' && (new Date($i.createdAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) { if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) { popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {}, 'closed'); } From 6ad9a9677a88556f8e380b2e04359e2a4f9d75f6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 11:31:32 +0900 Subject: [PATCH 05/19] fix test --- packages/backend/src/core/entities/UserEntityService.ts | 2 +- packages/backend/src/server/api/endpoints/admin/show-user.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index b822c5dce4..4e2f0317dd 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -412,7 +412,7 @@ export class UserEntityService implements OnModuleInit { userId: meId, targetUserId: user.id, }).then(row => row?.memo ?? null), - moderationNote: iAmModerator ? profile!.moderationNote : null, + moderationNote: iAmModerator ? (profile!.moderationNote ?? '') : null, } : {}), ...(opts.detail && isMe ? { diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 9d19efbbcf..42229c8f23 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -80,7 +80,7 @@ export default class extends Endpoint { isSilenced: isSilenced, isSuspended: user.isSuspended, lastActiveDate: user.lastActiveDate, - moderationNote: profile.moderationNote, + moderationNote: profile.moderationNote ?? '', signins, policies: await this.roleService.getUserPolicies(user.id), roles: await this.roleEntityService.packMany(roles, me), From 29a84230b0d3216442c955599485be5f6511aa78 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 11:59:06 +0900 Subject: [PATCH 06/19] =?UTF-8?q?enhance(backend):=20SearchService.searchN?= =?UTF-8?q?ote=E3=81=A7host=E6=8C=87=E5=AE=9A=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/SearchService.ts | 8 ++++++++ packages/backend/src/server/api/endpoints/notes/search.ts | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/SearchService.ts b/packages/backend/src/core/SearchService.ts index 1c18a52fae..e68fde088d 100644 --- a/packages/backend/src/core/SearchService.ts +++ b/packages/backend/src/core/SearchService.ts @@ -117,6 +117,7 @@ export class SearchService { public async searchNote(q: string, me: User | null, opts: { userId?: Note['userId'] | null; channelId?: Note['channelId'] | null; + host?: string | null; }, pagination: { untilId?: Note['id']; sinceId?: Note['id']; @@ -131,6 +132,13 @@ export class SearchService { if (pagination.sinceId) filter.qs.push({ op: '>', k: 'createdAt', v: this.idService.parse(pagination.sinceId).date.getTime() }); if (opts.userId) filter.qs.push({ op: '=', k: 'userId', v: opts.userId }); if (opts.channelId) filter.qs.push({ op: '=', k: 'channelId', v: opts.channelId }); + if (opts.host) { + if (opts.host === '.') { + // TODO: Meilisearchが2023/05/07現在値がNULLかどうかのクエリが書けない + } else { + filter.qs.push({ op: '=', k: 'userHost', v: opts.host }); + } + } const res = await this.meilisearchNoteIndex!.search(q, { sort: ['createdAt:desc'], matchingStrategy: 'all', diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 990ba526d9..f6385400c3 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -42,8 +42,7 @@ export const paramDef = { offset: { type: 'integer', default: 0 }, host: { type: 'string', - nullable: true, - description: 'The local host is represented with `null`.', + description: 'The local host is represented with `.`.', }, userId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, channelId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, @@ -73,6 +72,7 @@ export default class extends Endpoint { const notes = await this.searchService.searchNote(ps.query, me, { userId: ps.userId, channelId: ps.channelId, + host: ps.host, }, { untilId: ps.untilId, sinceId: ps.sinceId, From 95e7e003fdc050f1b40aff0c26b668011a490d0d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 12:04:16 +0900 Subject: [PATCH 07/19] fix test --- packages/backend/src/core/entities/UserEntityService.ts | 2 +- packages/backend/test/e2e/users.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 4e2f0317dd..a7f62c05f7 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -412,7 +412,7 @@ export class UserEntityService implements OnModuleInit { userId: meId, targetUserId: user.id, }).then(row => row?.memo ?? null), - moderationNote: iAmModerator ? (profile!.moderationNote ?? '') : null, + moderationNote: iAmModerator ? (profile!.moderationNote ?? '') : undefined, } : {}), ...(opts.detail && isMe ? { diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 917b9fbc94..c1a57f102f 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -112,7 +112,6 @@ describe('ユーザー', () => { securityKeys: user.securityKeys, roles: user.roles, memo: user.memo, - moderationNote: user.moderationNote, }); }; From 8a9cc0e71173355e4c5f2a3460f883d93601c5b6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 12:53:41 +0900 Subject: [PATCH 08/19] fix text --- packages/backend/test/e2e/users.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index c1a57f102f..90a0b49eab 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -221,8 +221,8 @@ describe('ユーザー', () => { }, 1000 * 60 * 2); beforeAll(async () => { - root = await signup({ username: 'alice' }); - alice = root; + root = await signup({ username: 'root' }); + alice = await signup({ username: 'alice' }); aliceNote = await post(alice, { text: 'test' }) as any; alicePage = await page(alice); aliceList = (await api('users/list/create', { name: 'aliceList' }, alice)).body; From 61c12290fd930e5391db2a174a3504132a0c69e7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 16:41:37 +0900 Subject: [PATCH 09/19] fix test --- packages/backend/test/e2e/users.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 90a0b49eab..a24c984b37 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -52,7 +52,7 @@ describe('ユーザー', () => { type User = MeDetailed & { token: string }; const show = async (id: string, me = alice): Promise => { - return successfulApiCall({ endpoint: 'users/show', parameters: { userId: id }, user: me }) as any; + return successfulApiCall({ endpoint: 'users/show', parameters: { userId: id }, user: root }) as any; }; // UserLiteのキーが過不足なく入っている? From 50985b2ffd3ea3a88d43031c939058825cacb8a8 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 16:42:19 +0900 Subject: [PATCH 10/19] fix test --- packages/backend/test/e2e/users.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index a24c984b37..b4ccd40845 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -51,8 +51,8 @@ describe('ユーザー', () => { type User = MeDetailed & { token: string }; - const show = async (id: string, me = alice): Promise => { - return successfulApiCall({ endpoint: 'users/show', parameters: { userId: id }, user: root }) as any; + const show = async (id: string, me = root): Promise => { + return successfulApiCall({ endpoint: 'users/show', parameters: { userId: id }, user: me }) as any; }; // UserLiteのキーが過不足なく入っている? From 95a2de8d5429c67ccd404f72c247e8ee5267a01d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 17:36:13 +0900 Subject: [PATCH 11/19] =?UTF-8?q?fix(backend):=20=E5=87=8D=E7=B5=90?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=9F=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC?= =?UTF-8?q?=E3=81=8C=E4=B8=80=E9=83=A8API=E3=81=AE=E3=83=AC=E3=82=B9?= =?UTF-8?q?=E3=83=9D=E3=83=B3=E3=82=B9=E3=81=AB=E5=90=AB=E3=81=BE=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + packages/backend/src/server/api/endpoints/hashtags/users.ts | 3 ++- packages/backend/src/server/api/endpoints/users.ts | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7105a72dcd..78d7b9fa0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ - Fix: Content-Dispositionのパースでエラーが発生した場合にダウンロードが完了しない問題を修正 - Fix: API: i/update avatarIdとbannerIdにnullを渡した時、画像がリセットされない問題を修正 - Fix: .wav, .flacが再生できない問題を修正(新しくアップロードされたファイルのみ修正が適用されます) +- Fix: 凍結されたユーザーが一部APIのレスポンスに含まれる問題を修正 - Fix: メモリの使用量を`used - buffers - cached`ではなく`total - available`で求めるように(環境によって正常に計測できていなかったため) ## 13.11.3 diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts index c3f2ea9ea7..dd3549020e 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/users.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts @@ -44,7 +44,8 @@ export default class extends Endpoint { ) { super(meta, paramDef, async (ps, me) => { const query = this.usersRepository.createQueryBuilder('user') - .where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) }); + .where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) }) + .andWhere('user.isSuspended = FALSE'); const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5)); diff --git a/packages/backend/src/server/api/endpoints/users.ts b/packages/backend/src/server/api/endpoints/users.ts index 8becb68a34..28cd9f6ce5 100644 --- a/packages/backend/src/server/api/endpoints/users.ts +++ b/packages/backend/src/server/api/endpoints/users.ts @@ -50,8 +50,9 @@ export default class extends Endpoint { private queryService: QueryService, ) { super(meta, paramDef, async (ps, me) => { - const query = this.usersRepository.createQueryBuilder('user'); - query.where('user.isExplorable = TRUE'); + const query = this.usersRepository.createQueryBuilder('user') + .where('user.isExplorable = TRUE') + .andWhere('user.isSuspended = FALSE'); switch (ps.state) { case 'alive': query.andWhere('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break; From 8957a89024d3a56f4ea097c4ff09e418bc15f82d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 17:38:06 +0900 Subject: [PATCH 12/19] update test --- packages/backend/test/e2e/users.ts | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index b4ccd40845..51537dda16 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -566,10 +566,10 @@ describe('ユーザー', () => { { label: '空文字', memo: '', expects: null }, { label: 'null', memo: null }, ])('を書き換えることができる(メモを$labelに)', async ({ memo, expects }) => { - const expected = { ...await show(bob.id), memo: expects === undefined ? memo : expects }; + const expected = { ...await show(bob.id, alice), memo: expects === undefined ? memo : expects }; const parameters = { userId: bob.id, memo }; await successfulApiCall({ endpoint: 'users/update-memo', parameters, user: alice }); - const response = await show(bob.id); + const response = await show(bob.id, alice); assert.deepStrictEqual(response, expected); }); @@ -588,7 +588,7 @@ describe('ユーザー', () => { const response = await successfulApiCall({ endpoint: 'users', parameters, user: alice }); // 結果の並びを事前にアサートするのは困難なので返ってきたidに対応するユーザーが返っており、ソート順が正しいことだけを検証する - const users = await Promise.all(response.map(u => show(u.id))); + const users = await Promise.all(response.map(u => show(u.id, alice))); const expected = users.sort((x, y) => { const index = (selector(x) < selector(y)) ? -1 : (selector(x) > selector(y)) ? 1 : 0; return index * (parameters.sort?.startsWith('+') ? -1 : 1); @@ -602,13 +602,13 @@ describe('ユーザー', () => { { label: 'ブロックしてきているユーザーが含まれる', user: (): User => userBlockingAlice, excluded: true }, { label: '承認制ユーザーが含まれる', user: (): User => userLocking }, { label: 'サイレンスユーザーが含まれる', user: (): User => userSilenced }, - { label: 'サスペンドユーザーが含まれる', user: (): User => userSuspended }, + { label: 'サスペンドユーザーが含まれない', user: (): User => userSuspended, excluded: true }, { label: '削除済ユーザーが含まれる', user: (): User => userDeletedBySelf }, { label: '削除済(byAdmin)ユーザーが含まれる', user: (): User => userDeletedByAdmin }, ] as const)('をリスト形式で取得することができ、結果に$label', async ({ user, excluded }) => { const parameters = { limit: 100 }; const response = await successfulApiCall({ endpoint: 'users', parameters, user: alice }); - const expected = (excluded ?? false) ? [] : [await show(user().id)]; + const expected = (excluded ?? false) ? [] : [await show(user().id, alice)]; assert.deepStrictEqual(response.filter((u) => u.id === user().id), expected); }); test.todo('をリスト形式で取得することができる(リモート, hostname指定)'); @@ -635,7 +635,7 @@ describe('ユーザー', () => { { label: 'Moderatorになっている', user: (): User => userModerator, me: (): User => userModerator, selector: (user: User): unknown => user.isModerator }, { label: '自分以外から見たときはModeratorか判定できない', user: (): User => userModerator, selector: (user: User): unknown => user.isModerator, expected: (): undefined => undefined }, { label: 'サイレンスになっている', user: (): User => userSilenced, selector: (user: User): unknown => user.isSilenced }, - { label: 'サスペンドになっている', user: (): User => userSuspended, selector: (user: User): unknown => user.isSuspended }, + //{ label: 'サスペンドになっている', user: (): User => userSuspended, selector: (user: User): unknown => user.isSuspended }, { label: '削除済みになっている', user: (): User => userDeletedBySelf, me: (): User => userDeletedBySelf, selector: (user: User): unknown => user.isDeleted }, { label: '自分以外から見たときは削除済みか判定できない', user: (): User => userDeletedBySelf, selector: (user: User): unknown => user.isDeleted, expected: (): undefined => undefined }, { label: '削除済み(byAdmin)になっている', user: (): User => userDeletedByAdmin, me: (): User => userDeletedByAdmin, selector: (user: User): unknown => user.isDeleted }, @@ -717,13 +717,13 @@ describe('ユーザー', () => { test('を検索することができる', async () => { const parameters = { query: 'carol', limit: 10 }; const response = await successfulApiCall({ endpoint: 'users/search', parameters, user: alice }); - const expected = [await show(carol.id)]; + const expected = [await show(carol.id, alice)]; assert.deepStrictEqual(response, expected); }); test('を検索することができる(UserLite)', async () => { const parameters = { query: 'carol', detail: false, limit: 10 }; const response = await successfulApiCall({ endpoint: 'users/search', parameters, user: alice }); - const expected = [userLite(await show(carol.id))]; + const expected = [userLite(await show(carol.id, alice))]; assert.deepStrictEqual(response, expected); }); test.each([ @@ -739,7 +739,7 @@ describe('ユーザー', () => { ] as const)('を検索することができ、結果に$labelが含まれる', async ({ user, excluded }) => { const parameters = { query: user().username, limit: 1 }; const response = await successfulApiCall({ endpoint: 'users/search', parameters, user: alice }); - const expected = (excluded ?? false) ? [] : [await show(user().id)]; + const expected = (excluded ?? false) ? [] : [await show(user().id, alice)]; assert.deepStrictEqual(response, expected); }); test.todo('を検索することができる(リモート)'); @@ -760,7 +760,7 @@ describe('ユーザー', () => { { label: 'ローカル', parameters: { host: '.', limit: 1 }, user: (): User[] => [userFollowedByAlice] }, ])('をID&ホスト指定で検索できる($label)', async ({ parameters, user }) => { const response = await successfulApiCall({ endpoint: 'users/search-by-username-and-host', parameters, user: alice }); - const expected = await Promise.all(user().map(u => show(u.id))); + const expected = await Promise.all(user().map(u => show(u.id, alice))); assert.deepStrictEqual(response, expected); }); test.each([ @@ -776,7 +776,7 @@ describe('ユーザー', () => { ] as const)('をID&ホスト指定で検索でき、結果に$label', async ({ user, excluded }) => { const parameters = { username: user().username }; const response = await successfulApiCall({ endpoint: 'users/search-by-username-and-host', parameters, user: alice }); - const expected = (excluded ?? false) ? [] : [await show(user().id)]; + const expected = (excluded ?? false) ? [] : [await show(user().id, alice)]; assert.deepStrictEqual(response, expected); }); test.todo('をID&ホスト指定で検索できる(リモート)'); @@ -788,7 +788,7 @@ describe('ユーザー', () => { const parameters = { userId: alice.id, limit: 5 }; const response = await successfulApiCall({ endpoint: 'users/get-frequently-replied-users', parameters, user: alice }); const expected = await Promise.all(usersReplying.slice(0, parameters.limit).map(async (s, i) => ({ - user: await show(s.id), + user: await show(s.id, alice), weight: (usersReplying.length - i) / usersReplying.length, }))); assert.deepStrictEqual(response, expected); @@ -800,7 +800,7 @@ describe('ユーザー', () => { { label: 'ブロックしてきているユーザーが含まれない', user: (): User => userBlockingAlice, excluded: true }, { label: '承認制ユーザーが含まれる', user: (): User => userLocking }, { label: 'サイレンスユーザーが含まれる', user: (): User => userSilenced }, - { label: 'サスペンドユーザーが含まれない', user: (): User => userSuspended }, + //{ label: 'サスペンドユーザーが含まれない', user: (): User => userSuspended, excluded: true }, { label: '削除済ユーザーが含まれる', user: (): User => userDeletedBySelf }, { label: '削除済(byAdmin)ユーザーが含まれる', user: (): User => userDeletedByAdmin }, ] as const)('がよくリプライをするユーザーのリストを取得でき、結果に$label', async ({ user, excluded }) => { @@ -808,7 +808,7 @@ describe('ユーザー', () => { await post(alice, { text: `@${user().username} test`, replyId: replyTo.id }); const parameters = { userId: alice.id, limit: 100 }; const response = await successfulApiCall({ endpoint: 'users/get-frequently-replied-users', parameters, user: alice }); - const expected = (excluded ?? false) ? [] : [await show(user().id)]; + const expected = (excluded ?? false) ? [] : [await show(user().id, alice)]; assert.deepStrictEqual(response.map(s => s.user).filter((u) => u.id === user().id), expected); }); @@ -827,7 +827,7 @@ describe('ユーザー', () => { await successfulApiCall({ endpoint: 'i/update', parameters: { description: `#${hashtag}` }, user: alice }); const parameters = { tag: hashtag, limit: 5, ...sort }; const response = await successfulApiCall({ endpoint: 'hashtags/users', parameters, user: alice }); - const users = await Promise.all(response.map(u => show(u.id))); + const users = await Promise.all(response.map(u => show(u.id, alice))); const expected = users.sort((x, y) => { const index = (selector(x) < selector(y)) ? -1 : (selector(x) > selector(y)) ? 1 : 0; return index * (parameters.sort.startsWith('+') ? -1 : 1); @@ -841,10 +841,10 @@ describe('ユーザー', () => { { label: 'ブロックしてきているユーザーが含まれる', user: (): User => userBlockingAlice }, { label: '承認制ユーザーが含まれる', user: (): User => userLocking }, { label: 'サイレンスユーザーが含まれる', user: (): User => userSilenced }, - { label: 'サスペンドユーザーが含まれる', user: (): User => userSuspended }, + { label: 'サスペンドユーザーが含まれない', user: (): User => userSuspended, excluded: true }, { label: '削除済ユーザーが含まれる', user: (): User => userDeletedBySelf }, { label: '削除済(byAdmin)ユーザーが含まれる', user: (): User => userDeletedByAdmin }, - ] as const)('をハッシュタグ指定で取得することができ、結果に$label', async ({ user }) => { + ] as const)('をハッシュタグ指定で取得することができ、結果に$label', async ({ user, excluded }) => { const hashtag = `user_test${user().username}`; if (user() !== userSuspended) { // サスペンドユーザーはupdateできない。 @@ -852,7 +852,7 @@ describe('ユーザー', () => { } const parameters = { tag: hashtag, limit: 100, sort: '-follower' } as const; const response = await successfulApiCall({ endpoint: 'hashtags/users', parameters, user: alice }); - const expected = [await show(user().id)]; + const expected = (excluded ?? false) ? [] : [await show(user().id, alice)]; assert.deepStrictEqual(response, expected); }); test.todo('をハッシュタグ指定で取得することができる(リモート)'); @@ -875,7 +875,7 @@ describe('ユーザー', () => { await successfulApiCall({ endpoint: 'admin/update-meta', parameters: { pinnedUsers: [bob.username, `@${carol.username}`] }, user: root }); const parameters = {} as const; const response = await successfulApiCall({ endpoint: 'pinned-users', parameters, user: alice }); - const expected = await Promise.all([bob, carol].map(u => show(u.id))); + const expected = await Promise.all([bob, carol].map(u => show(u.id, alice))); assert.deepStrictEqual(response, expected); }); From 963aa4939f7fab0310866e45a55ea2f3b976f816 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 17:55:50 +0900 Subject: [PATCH 13/19] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d7b9fa0d..6cab373373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ ### General - アカウントの引っ越し(フォロワー引き継ぎ)に対応 - * 一度引っ越したアカウントは利用に制限がかかります - Meilisearchを全文検索に使用できるようになりました - 新規登録前に簡潔なルールをユーザーに表示できる、サーバールール機能を追加 - ユーザーへの自分用メモ機能 From 8310d929dc1ca3d5d0e6bc9628eedc8ea4117122 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 17:57:55 +0900 Subject: [PATCH 14/19] =?UTF-8?q?enhance(frontend):=20=E9=96=B2=E8=A6=A7?= =?UTF-8?q?=E6=B3=A8=E6=84=8F=E8=A8=AD=E5=AE=9A=E3=81=95=E3=82=8C=E3=81=9F?= =?UTF-8?q?=E7=94=BB=E5=83=8F=E3=81=AF=E8=A1=A8=E7=A4=BA=E3=81=97=E3=81=9F?= =?UTF-8?q?=E7=8A=B6=E6=85=8B=E3=81=A7=E3=82=82=E3=81=9D=E3=82=8C=E3=81=8C?= =?UTF-8?q?=E9=96=B2=E8=A6=A7=E6=B3=A8=E6=84=8F=E3=81=A0=E3=81=A8=E5=88=86?= =?UTF-8?q?=E3=81=8B=E3=82=8B=E8=A1=A8=E7=A4=BA=E3=82=92=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + packages/frontend/src/components/MkMediaImage.vue | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cab373373..daa3f6c86c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ * 絵文字ピッカーから入力可能になります - データセーバーモードを追加 * 画像が全て隠れた状態で表示されるようになります +- 閲覧注意設定された画像は表示した状態でもそれが閲覧注意だと分かる表示をするように - 1枚だけのメディアリストの画像のアスペクト比を画像に応じて縦長にするように - プロフィール設定「追加情報」の項目の削除と並び替えができるように - 新しい実績を追加 diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index f815ef32dd..0634ea5c0e 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -20,6 +20,7 @@
GIF
ALT
+
NSFW
From 448a933f7704a3392e0c249a2236f0178f9c5fe3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 May 2023 18:18:32 +0900 Subject: [PATCH 15/19] =?UTF-8?q?enhance(frontend):=20=E3=83=A2=E3=83=87?= =?UTF-8?q?=E3=83=AC=E3=83=BC=E3=82=BF=E3=83=BC=E3=81=AF=E3=83=8E=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=81=AB=E6=B7=BB=E4=BB=98=E3=81=95=E3=82=8C=E3=81=9F?= =?UTF-8?q?=E7=94=BB=E5=83=8F=E4=B8=8A=E3=81=8B=E3=82=89=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?NSFW=E8=A8=AD=E5=AE=9A=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../frontend/src/components/MkMediaImage.vue | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index daa3f6c86c..1d2a0032e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ - データセーバーモードを追加 * 画像が全て隠れた状態で表示されるようになります - 閲覧注意設定された画像は表示した状態でもそれが閲覧注意だと分かる表示をするように +- モデレーターはノートに添付された画像上から直接NSFW設定できるように - 1枚だけのメディアリストの画像のアスペクト比を画像に応じて縦長にするように - プロフィール設定「追加情報」の項目の削除と並び替えができるように - 新しい実績を追加 diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index 0634ea5c0e..42dc9e79ff 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -23,6 +23,7 @@
NSFW
+ @@ -34,6 +35,8 @@ import bytes from '@/filters/bytes'; import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue'; import { defaultStore } from '@/store'; import { i18n } from '@/i18n'; +import * as os from '@/os'; +import { iAmModerator } from '@/account'; const props = defineProps<{ image: misskey.entities.DriveFile; @@ -57,6 +60,17 @@ watch(() => props.image, () => { deep: true, immediate: true, }); + +function showMenu(ev: MouseEvent) { + os.popupMenu([...(iAmModerator ? [{ + text: i18n.ts.markAsSensitive, + icon: 'ti ti-eye-off', + action: () => { + os.apiWithDialog('drive/files/update', { fileId: props.image.id, isSensitive: true }); + }, + }] : [])], ev.currentTarget ?? ev.target); +} +