summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
author1Step621 <86859447+1STEP621@users.noreply.github.com>2024-02-06 16:45:21 +0900
committerGitHub <noreply@github.com>2024-02-06 16:45:21 +0900
commit74245df3829622a3cc0c880ea710b5c1c4f5c584 (patch)
tree3f6f4f1c598f4bd75be6bbfcd1d5deee8daa5adc /packages
parentenhance(frontend): KeepAliveのページキャッシュを削除できるよ... (diff)
downloadmisskey-74245df3829622a3cc0c880ea710b5c1c4f5c584.tar.gz
misskey-74245df3829622a3cc0c880ea710b5c1c4f5c584.tar.bz2
misskey-74245df3829622a3cc0c880ea710b5c1c4f5c584.zip
Enhance(frontend): フロント側でもリアクション権限のチェックをするように (#13134)
* フロント側でもリアクション権限のチェックをするように * update CHANGELOG.md * lint fixes * remove unrelated diffs * deny -> reject denyは「(信用しないことを理由に)拒否する」という意味らしい * allow -> accept * EmojiSimpleにlocalOnlyを含めるように * リアクション権限のない絵文字は打てないように(ダイアログを出すのではなく) * regenerate type definitions * lint fix * remove unused locales * remove unnecessary async
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/src/core/entities/EmojiEntityService.ts1
-rw-r--r--packages/backend/src/models/json-schema/emoji.ts4
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue4
-rw-r--r--packages/frontend/src/components/MkEmojiPickerDialog.vue3
-rw-r--r--packages/frontend/src/components/MkEmojiPickerWindow.vue4
-rw-r--r--packages/frontend/src/components/MkNote.vue2
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue2
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.reaction.vue18
-rw-r--r--packages/frontend/src/pages/settings/emoji-picker.vue2
-rw-r--r--packages/frontend/src/scripts/check-reaction-permissions.ts8
-rw-r--r--packages/frontend/src/scripts/reaction-picker.ts6
-rw-r--r--packages/misskey-js/src/autogen/apiClientJSDoc.ts2
-rw-r--r--packages/misskey-js/src/autogen/endpoint.ts2
-rw-r--r--packages/misskey-js/src/autogen/entities.ts2
-rw-r--r--packages/misskey-js/src/autogen/models.ts2
-rw-r--r--packages/misskey-js/src/autogen/types.ts3
16 files changed, 49 insertions, 16 deletions
diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts
index 5b97cfad5e..655c4c5ada 100644
--- a/packages/backend/src/core/entities/EmojiEntityService.ts
+++ b/packages/backend/src/core/entities/EmojiEntityService.ts
@@ -31,6 +31,7 @@ export class EmojiEntityService {
category: emoji.category,
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
url: emoji.publicUrl || emoji.originalUrl,
+ localOnly: emoji.localOnly ? true : undefined,
isSensitive: emoji.isSensitive ? true : undefined,
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0 ? emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : undefined,
};
diff --git a/packages/backend/src/models/json-schema/emoji.ts b/packages/backend/src/models/json-schema/emoji.ts
index 99a58f8773..954eb98d57 100644
--- a/packages/backend/src/models/json-schema/emoji.ts
+++ b/packages/backend/src/models/json-schema/emoji.ts
@@ -27,6 +27,10 @@ export const packedEmojiSimpleSchema = {
type: 'string',
optional: false, nullable: false,
},
+ localOnly: {
+ type: 'boolean',
+ optional: true, nullable: false,
+ },
isSensitive: {
type: 'boolean',
optional: true, nullable: false,
diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue
index 58160cdf5b..f5ab7a2e29 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -118,6 +118,7 @@ import { i18n } from '@/i18n.js';
import { defaultStore } from '@/store.js';
import { customEmojiCategories, customEmojis, customEmojisMap } from '@/custom-emojis.js';
import { $i } from '@/account.js';
+import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js';
const props = withDefaults(defineProps<{
showPinned?: boolean;
@@ -126,6 +127,7 @@ const props = withDefaults(defineProps<{
asDrawer?: boolean;
asWindow?: boolean;
asReactionPicker?: boolean; // 今は使われてないが将来的に使いそう
+ targetNote?: Misskey.entities.Note;
}>(), {
showPinned: true,
});
@@ -340,7 +342,7 @@ watch(q, () => {
});
function filterAvailable(emoji: Misskey.entities.EmojiSimple): boolean {
- return ((emoji.roleIdsThatCanBeUsedThisEmojiAsReaction == null || emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0) || ($i && $i.roles.some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction?.includes(r.id)))) ?? false;
+ return !props.targetNote || checkReactionPermissions($i!, props.targetNote, emoji);
}
function focus() {
diff --git a/packages/frontend/src/components/MkEmojiPickerDialog.vue b/packages/frontend/src/components/MkEmojiPickerDialog.vue
index 6660dcf1ed..444e8a4cec 100644
--- a/packages/frontend/src/components/MkEmojiPickerDialog.vue
+++ b/packages/frontend/src/components/MkEmojiPickerDialog.vue
@@ -24,6 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:showPinned="showPinned"
:pinnedEmojis="pinnedEmojis"
:asReactionPicker="asReactionPicker"
+ :targetNote="targetNote"
:asDrawer="type === 'drawer'"
:max-height="maxHeight"
@chosen="chosen"
@@ -32,6 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
+import * as Misskey from 'misskey-js';
import { shallowRef } from 'vue';
import MkModal from '@/components/MkModal.vue';
import MkEmojiPicker from '@/components/MkEmojiPicker.vue';
@@ -43,6 +45,7 @@ const props = withDefaults(defineProps<{
showPinned?: boolean;
pinnedEmojis?: string[],
asReactionPicker?: boolean;
+ targetNote?: Misskey.entities.Note;
choseAndClose?: boolean;
}>(), {
manualShowing: null,
diff --git a/packages/frontend/src/components/MkEmojiPickerWindow.vue b/packages/frontend/src/components/MkEmojiPickerWindow.vue
index 1a2c55e785..2a6828f242 100644
--- a/packages/frontend/src/components/MkEmojiPickerWindow.vue
+++ b/packages/frontend/src/components/MkEmojiPickerWindow.vue
@@ -13,12 +13,13 @@ SPDX-License-Identifier: AGPL-3.0-only
:front="true"
@closed="emit('closed')"
>
- <MkEmojiPicker :showPinned="showPinned" :asReactionPicker="asReactionPicker" asWindow :class="$style.picker" @chosen="chosen"/>
+ <MkEmojiPicker :showPinned="showPinned" :asReactionPicker="asReactionPicker" :targetNote="targetNote" asWindow :class="$style.picker" @chosen="chosen"/>
</MkWindow>
</template>
<script lang="ts" setup>
import { } from 'vue';
+import * as Misskey from 'misskey-js';
import MkWindow from '@/components/MkWindow.vue';
import MkEmojiPicker from '@/components/MkEmojiPicker.vue';
@@ -26,6 +27,7 @@ withDefaults(defineProps<{
src?: HTMLElement;
showPinned?: boolean;
asReactionPicker?: boolean;
+ targetNote?: Misskey.entities.Note
}>(), {
showPinned: true,
});
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 735ec86564..27e8bc45b7 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -385,7 +385,7 @@ function react(viaKeyboard = false): void {
}
} else {
blur();
- reactionPicker.show(reactButton.value ?? null, reaction => {
+ reactionPicker.show(reactButton.value ?? null, note.value, reaction => {
sound.playMisskeySfx('reaction');
if (props.mock) {
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index dd956b21ad..a53dd90d27 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -385,7 +385,7 @@ function react(viaKeyboard = false): void {
}
} else {
blur();
- reactionPicker.show(reactButton.value ?? null, reaction => {
+ reactionPicker.show(reactButton.value ?? null, note.value, reaction => {
sound.playMisskeySfx('reaction');
misskeyApi('notes/reactions/create', {
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index ffbf62a45c..67b448ccb7 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -32,6 +32,8 @@ import { claimAchievement } from '@/scripts/achievements.js';
import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
import * as sound from '@/scripts/sound.js';
+import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js';
+import { customEmojis } from '@/custom-emojis.js';
const props = defineProps<{
reaction: string;
@@ -48,13 +50,19 @@ const emit = defineEmits<{
const buttonEl = shallowRef<HTMLElement>();
-const canToggle = computed(() => !props.reaction.match(/@\w/) && $i);
+const isCustomEmoji = computed(() => props.reaction.includes(':'));
+const emoji = computed(() => isCustomEmoji.value ? customEmojis.value.find(emoji => emoji.name === props.reaction.replace(/:/g, '').replace(/@\./, '')) : null);
+
+const canToggle = computed(() => {
+ return !props.reaction.match(/@\w/) && $i
+ && (emoji.value && checkReactionPermissions($i, props.note, emoji.value))
+ || !isCustomEmoji.value;
+});
+const canGetInfo = computed(() => !props.reaction.match(/@\w/) && props.reaction.includes(':'));
async function toggleReaction() {
if (!canToggle.value) return;
- // TODO: その絵文字を使う権限があるかどうか確認
-
const oldReaction = props.note.myReaction;
if (oldReaction) {
const confirm = await os.confirm({
@@ -101,8 +109,8 @@ async function toggleReaction() {
}
async function menu(ev) {
- if (!canToggle.value) return;
- if (!props.reaction.includes(':')) return;
+ if (!canGetInfo.value) return;
+
os.popupMenu([{
text: i18n.ts.info,
icon: 'ti ti-info-circle',
diff --git a/packages/frontend/src/pages/settings/emoji-picker.vue b/packages/frontend/src/pages/settings/emoji-picker.vue
index 61f3332122..1215af35cf 100644
--- a/packages/frontend/src/pages/settings/emoji-picker.vue
+++ b/packages/frontend/src/pages/settings/emoji-picker.vue
@@ -157,7 +157,7 @@ const chooseEmoji = (ev: MouseEvent) => pickEmoji(pinnedEmojis, ev);
const setDefaultEmoji = () => setDefault(pinnedEmojis);
function previewReaction(ev: MouseEvent) {
- reactionPicker.show(getHTMLElement(ev));
+ reactionPicker.show(getHTMLElement(ev), null);
}
function previewEmoji(ev: MouseEvent) {
diff --git a/packages/frontend/src/scripts/check-reaction-permissions.ts b/packages/frontend/src/scripts/check-reaction-permissions.ts
new file mode 100644
index 0000000000..c9d2a5bfc6
--- /dev/null
+++ b/packages/frontend/src/scripts/check-reaction-permissions.ts
@@ -0,0 +1,8 @@
+import * as Misskey from 'misskey-js';
+
+export function checkReactionPermissions(me: Misskey.entities.MeDetailed, note: Misskey.entities.Note, emoji: Misskey.entities.EmojiSimple): boolean {
+ const roleIdsThatCanBeUsedThisEmojiAsReaction = emoji.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [];
+ return !(emoji.localOnly && note.user.host !== me.host)
+ && !(emoji.isSensitive && (note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote'))
+ && (roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || me.roles.some(role => roleIdsThatCanBeUsedThisEmojiAsReaction.includes(role.id)));
+}
diff --git a/packages/frontend/src/scripts/reaction-picker.ts b/packages/frontend/src/scripts/reaction-picker.ts
index a13351b536..193ac838a2 100644
--- a/packages/frontend/src/scripts/reaction-picker.ts
+++ b/packages/frontend/src/scripts/reaction-picker.ts
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
+import * as Misskey from 'misskey-js';
import { defineAsyncComponent, Ref, ref } from 'vue';
import { popup } from '@/os.js';
import { defaultStore } from '@/store.js';
@@ -10,6 +11,7 @@ import { defaultStore } from '@/store.js';
class ReactionPicker {
private src: Ref<HTMLElement | null> = ref(null);
private manualShowing = ref(false);
+ private targetNote: Ref<Misskey.entities.Note | null> = ref(null);
private onChosen?: (reaction: string) => void;
private onClosed?: () => void;
@@ -23,6 +25,7 @@ class ReactionPicker {
src: this.src,
pinnedEmojis: reactionsRef,
asReactionPicker: true,
+ targetNote: this.targetNote,
manualShowing: this.manualShowing,
}, {
done: reaction => {
@@ -38,8 +41,9 @@ class ReactionPicker {
});
}
- public show(src: HTMLElement | null, onChosen?: ReactionPicker['onChosen'], onClosed?: ReactionPicker['onClosed']) {
+ public show(src: HTMLElement | null, targetNote: Misskey.entities.Note | null, onChosen?: ReactionPicker['onChosen'], onClosed?: ReactionPicker['onClosed']) {
this.src.value = src;
+ this.targetNote.value = targetNote;
this.manualShowing.value = true;
this.onChosen = onChosen;
this.onClosed = onClosed;
diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
index 7c727d2878..cb761493a2 100644
--- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts
+++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
@@ -1,6 +1,6 @@
/*
* version: 2024.2.0-beta.8
- * generatedAt: 2024-02-04T11:51:13.598Z
+ * generatedAt: 2024-02-04T16:51:09.469Z
*/
import type { SwitchCaseResponseType } from '../api.js';
diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts
index cf9f96b526..10ec645a53 100644
--- a/packages/misskey-js/src/autogen/endpoint.ts
+++ b/packages/misskey-js/src/autogen/endpoint.ts
@@ -1,6 +1,6 @@
/*
* version: 2024.2.0-beta.8
- * generatedAt: 2024-02-04T11:51:13.595Z
+ * generatedAt: 2024-02-04T16:51:09.467Z
*/
import type {
diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts
index 2930f2cb7f..04b52e9fb6 100644
--- a/packages/misskey-js/src/autogen/entities.ts
+++ b/packages/misskey-js/src/autogen/entities.ts
@@ -1,6 +1,6 @@
/*
* version: 2024.2.0-beta.8
- * generatedAt: 2024-02-04T11:51:13.593Z
+ * generatedAt: 2024-02-04T16:51:09.466Z
*/
import { operations } from './types.js';
diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts
index f01beaa706..ee14b22f74 100644
--- a/packages/misskey-js/src/autogen/models.ts
+++ b/packages/misskey-js/src/autogen/models.ts
@@ -1,6 +1,6 @@
/*
* version: 2024.2.0-beta.8
- * generatedAt: 2024-02-04T11:51:13.592Z
+ * generatedAt: 2024-02-04T16:51:09.465Z
*/
import { components } from './types.js';
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 77a493fe2e..cce2dadcdb 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -3,7 +3,7 @@
/*
* version: 2024.2.0-beta.8
- * generatedAt: 2024-02-04T11:51:13.473Z
+ * generatedAt: 2024-02-04T16:51:09.378Z
*/
/**
@@ -4423,6 +4423,7 @@ export type components = {
name: string;
category: string | null;
url: string;
+ localOnly?: boolean;
isSensitive?: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction?: string[];
};