Compare commits

...

7 Commits

Author SHA1 Message Date
Erin 60f3a5ae27
Merge 5641b0b3ad into daf9ae5d4a 2024-09-17 21:01:35 +09:00
FineArchs daf9ae5d4a
ScratchpadにUIインスペクターを追加 (#14565)
* add ui list

* Update scratchpad.vue

* experiment

* design change

* redesign

* redesign

* Update ja-JP.yml

* redesign

* component properties

* whole json

* use textarea

* fix import

* stringify function

* Update CHANGELOG.md

* UI Component Monitor -> UI Inspector

* uiInspectorOpenedFlags -> uiInspectorOpenedComponents

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

* fix

* change key i -> c.value.id

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2024-09-17 20:11:50 +09:00
syuilo a5e61b8c19 Revert "refactor"
This reverts commit 0134e6e420.
2024-09-17 17:05:52 +09:00
syuilo cacdf9d939 refactor
MkMisskeyFlavoredMarkdown -> MkMfm
2024-09-17 17:03:09 +09:00
syuilo 0134e6e420 refactor 2024-09-17 17:00:48 +09:00
かっこかり 6bd6af440f
fix(frontend): 絵文字関連のスタイルが崩れているのを修正 (#14559)
* fix(frontend): 絵文字関連のスタイルが崩れていたのを修正 (MisskeyIO#725)

(cherry picked from commit 00fd684a7b382aaeb3355a1c80dc24078a5caa61)

* Update Changelog

* ✌️

---------

Co-authored-by: Yuuki <yukikum57@gmail.com>
2024-09-17 15:41:52 +09:00
Erin Shepherd 5641b0b3ad fix: Refetch user keys when HTTP Signature validation fails
If a user has had a key rotation, and nobody on this server follows
that user, we will not receive the Update activity with the new key

Therefore, when we encounter key validation errors we should check
for an up-to-date key.

References (other implementations):

 * [Mastodon](fc9ab61448/app/controllers/concerns/signature_verification.rb (L96))
 * [Akkoma](https://akkoma.dev/AkkomaGang/http_signatures/src/branch/main/lib/http_signatures/http_signatures.ex#L46)
2023-10-17 15:00:26 +02:00
13 changed files with 106 additions and 14 deletions

View File

@ -9,8 +9,11 @@
- Enhance: サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように
- Enhance: アイコンデコレーション管理画面にプレビューを追加
- Enhance: コントロールパネル内のファイル一覧でセンシティブなファイルを区別しやすく
- Enhance: ScratchpadにUIインスペクターを追加
- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正
- Fix: 月の違う同じ日はセパレータが表示されないのを修正
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725)
### Server
- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように

View File

@ -592,6 +592,8 @@ ascendingOrder: "昇順"
descendingOrder: "降順"
scratchpad: "スクラッチパッド"
scratchpadDescription: "スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。"
uiInspector: "UIインスペクター"
uiInspectorDescription: "メモリ上に存在しているUIコンポーネントのインスタンスの一覧を見ることができます。UIコンポーネントはUi:C:系関数により生成されます。"
output: "出力"
script: "スクリプト"
disablePagesScript: "Pagesのスクリプトを無効にする"

View File

@ -169,6 +169,19 @@ export class ApDbResolverService implements OnApplicationShutdown {
};
}
/**
* Miskey User -> Refetched Key
*/
@bindThis
public async refetchPublicKeyForApId(user: MiRemoteUser): Promise<MiUserPublickey | null> {
await this.apPersonService.updatePerson(user.uri!);
const key = this.userPublickeysRepository.findOneBy({ userId: user.id });
if (key != null) {
await this.publicKeyByUserIdCache.set(user.id, key);
}
return key;
}
@bindThis
public dispose(): void {
this.publicKeyCache.dispose();

View File

@ -106,7 +106,18 @@ export class InboxProcessorService {
}
// HTTP-Signatureの検証
const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem);
let httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem);
// If signature validation failed, try refetching the actor
if (!httpSignatureValidated) {
authUser.key = await this.apDbResolverService.refetchPublicKeyForApId(authUser.user);
if (authUser.key == null) {
throw new Bull.UnrecoverableError('skip: failed to re-resolve user publicKey');
}
httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem);
}
// また、signatureのsignerは、activity.actorと一致する必要がある
if (!httpSignatureValidated || authUser.user.uri !== activity.actor) {

View File

@ -611,6 +611,7 @@ defineExpose({
width: auto;
height: auto;
min-width: 0;
padding: 0;
&:disabled {
cursor: not-allowed;
@ -717,7 +718,7 @@ defineExpose({
> .item {
position: relative;
padding: 0;
padding: 0 3px;
width: var(--eachSize);
height: var(--eachSize);
contain: strict;

View File

@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:withTooltip="true"
:reaction="notification.reaction.replace(/^:(\w+):$/, ':$1@.:')"
:noStyle="true"
style="width: 100%; height: 100%;"
style="width: 100%; height: 100% !important; object-fit: contain;"
/>
</div>
</div>
@ -122,7 +122,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:withTooltip="true"
:reaction="reaction.reaction.replace(/^:(\w+):$/, ':$1@.:')"
:noStyle="true"
style="width: 100%; height: 100%;"
style="width: 100%; height: 100% !important; object-fit: contain;"
/>
</div>
</div>

View File

@ -36,6 +36,7 @@ const emit = defineEmits<{
.icon {
display: block;
width: 60px;
max-height: 60px;
font-size: 60px; // unicodewidth
margin: 0 auto;
object-fit: contain;

View File

@ -63,6 +63,7 @@ function getReactionName(reaction: string): string {
.reactionIcon {
display: block;
width: 60px;
max-height: 60px;
font-size: 60px; // unicodewidth
object-fit: contain;
margin: 0 auto;

View File

@ -2,16 +2,15 @@
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import { expect, within } from '@storybook/test';
import MkMisskeyFlavoredMarkdown from './MkMisskeyFlavoredMarkdown.js';
import MkMfm from './MkMfm.js';
export const Default = {
render(args) {
return {
components: {
MkMisskeyFlavoredMarkdown,
MkMfm,
},
setup() {
return {
@ -25,7 +24,7 @@ export const Default = {
};
},
},
template: '<MkMisskeyFlavoredMarkdown v-bind="props" />',
template: '<MkMfm v-bind="props" />',
};
},
async play({ canvasElement, args }) {
@ -54,25 +53,25 @@ export const Default = {
parameters: {
layout: 'centered',
},
} satisfies StoryObj<typeof MkMisskeyFlavoredMarkdown>;
} satisfies StoryObj<typeof MkMfm>;
export const Plain = {
...Default,
args: {
...Default.args,
plain: true,
},
} satisfies StoryObj<typeof MkMisskeyFlavoredMarkdown>;
} satisfies StoryObj<typeof MkMfm>;
export const Nowrap = {
...Default,
args: {
...Default.args,
nowrap: true,
},
} satisfies StoryObj<typeof MkMisskeyFlavoredMarkdown>;
} satisfies StoryObj<typeof MkMfm>;
export const IsNotNote = {
...Default,
args: {
...Default.args,
isNote: false,
},
} satisfies StoryObj<typeof MkMisskeyFlavoredMarkdown>;
} satisfies StoryObj<typeof MkMfm>;

View File

@ -5,7 +5,7 @@
import { App } from 'vue';
import Mfm from './global/MkMisskeyFlavoredMarkdown.js';
import Mfm from './global/MkMfm.js';
import MkA from './global/MkA.vue';
import MkAcct from './global/MkAcct.vue';
import MkAvatar from './global/MkAvatar.vue';

View File

@ -344,6 +344,7 @@ definePageMetadata(() => ({
> .img {
width: 42px;
height: 42px;
object-fit: contain;
}
> .body {
@ -390,6 +391,7 @@ definePageMetadata(() => ({
> .img {
width: 32px;
height: 32px;
object-fit: contain;
}
> .body {

View File

@ -30,6 +30,24 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkContainer>
<MkContainer :foldable="true" :expanded="false">
<template #header>{{ i18n.ts.uiInspector }}</template>
<div :class="$style.uiInspector">
<div v-for="c in components" :key="c.value.id">
<div :class="$style.uiInspectorType">{{ c.value.type }}</div>
<div :class="$style.uiInspectorId">{{ c.value.id }}</div>
<button :class="$style.uiInspectorPropsToggle" @click="() => uiInspectorOpenedComponents.set(c, !uiInspectorOpenedComponents.get(c))">
<i v-if="uiInspectorOpenedComponents.get(c)" class="ti ti-chevron-up icon"></i>
<i v-else class="ti ti-chevron-down icon"></i>
</button>
<div v-if="uiInspectorOpenedComponents.get(c)">
<MkTextarea :modelValue="stringifyUiProps(c.value)" code readonly></MkTextarea>
</div>
</div>
<div :class="$style.uiInspectorDescription">{{ i18n.ts.uiInspectorDescription }}</div>
</div>
</MkContainer>
<div class="">
{{ i18n.ts.scratchpadDescription }}
</div>
@ -43,6 +61,7 @@ import { onDeactivated, onUnmounted, Ref, ref, watch, computed } from 'vue';
import { Interpreter, Parser, utils } from '@syuilo/aiscript';
import MkContainer from '@/components/MkContainer.vue';
import MkButton from '@/components/MkButton.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkCodeEditor from '@/components/MkCodeEditor.vue';
import { aiScriptReadline, createAiScriptEnv } from '@/scripts/aiscript/api.js';
import * as os from '@/os.js';
@ -61,6 +80,7 @@ const logs = ref<any[]>([]);
const root = ref<AsUiRoot>();
const components = ref<Ref<AsUiComponent>[]>([]);
const uiKey = ref(0);
const uiInspectorOpenedComponents = ref(new Map<string, boolean>);
const saved = miLocalStorage.getItem('scratchpad');
if (saved) {
@ -71,6 +91,14 @@ watch(code, () => {
miLocalStorage.setItem('scratchpad', code.value);
});
function stringifyUiProps(uiProps) {
return JSON.stringify(
{ ...uiProps, type: undefined, id: undefined },
(k, v) => typeof v === 'function' ? '<function>' : v,
2
);
}
async function run() {
if (aiscript) aiscript.abort();
root.value = undefined;
@ -192,4 +220,35 @@ definePageMetadata(() => ({
}
}
}
.uiInspector {
display: grid;
gap: 8px;
padding: 16px;
}
.uiInspectorType {
display: inline-block;
border: hidden;
border-radius: 10px;
background-color: var(--panelHighlight);
padding: 2px 8px;
font-size: 12px;
}
.uiInspectorId {
display: inline-block;
padding-left: 8px;
}
.uiInspectorDescription {
display: block;
font-size: 12px;
padding-top: 16px;
}
.uiInspectorPropsToggle {
background: none;
border: none;
}
</style>