Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正
- Fix: 2月29日を誕生日に設定している場合、閏年以外は3月1日を誕生日として扱うように修正
- Fix: `Mk:C:container` の `borderWidth` が正しく反映されない問題を修正
- Fix: mCaptchaが正しく動作しない問題を修正

### Server
- Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@analytics/google-analytics": "1.1.0",
"@discordapp/twemoji": "16.0.1",
"@github/webauthn-json": "2.1.1",
"@mcaptcha/vanilla-glue": "0.1.0-rc2",
"@mcaptcha/core-glue": "0.1.0-alpha-5",
"@misskey-dev/browser-image-resizer": "2024.1.0",
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-replace": "6.0.3",
Expand Down
63 changes: 44 additions & 19 deletions packages/frontend/src/components/MkCaptcha.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<div>
<span v-if="!available">Loading<MkEllipsis/></span>
<div v-if="props.provider == 'mcaptcha'">
<div id="mcaptcha__widget-container" class="m-captcha-style"></div>
<div ref="captchaEl"></div>
<iframe
v-if="mCaptchaIframeUrl != null"
ref="mCaptchaIframe"
:src="mCaptchaIframeUrl"
style="border: none; max-width: 320px; width: 100%; height: 100%; max-height: 80px;"
></iframe>
</div>
<div v-if="props.provider == 'testcaptcha'" style="background: #eee; border: solid 1px #888; padding: 8px; color: #000; max-width: 320px; display: flex; gap: 10px; align-items: center; box-shadow: 2px 2px 6px #0004; border-radius: 4px;">
<img src="/client-assets/testcaptcha.png" style="width: 60px; height: 60px; "/>
Expand All @@ -26,7 +30,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>

<script lang="ts" setup>
import { ref, useTemplateRef, computed, onMounted, onBeforeUnmount, watch, onUnmounted } from 'vue';
import { ref, useTemplateRef, computed, onMounted, onBeforeUnmount, watch, onUnmounted, nextTick } from 'vue';
import type Reciever_typeReferenceOnly from '@mcaptcha/core-glue';
import { store } from '@/store.js';

// APIs provided by Captcha services
Expand Down Expand Up @@ -71,6 +76,19 @@ const available = ref(false);

const captchaEl = useTemplateRef('captchaEl');
const captchaWidgetId = ref<string | undefined>(undefined);

let mCaptchaReciever: Reciever_typeReferenceOnly | null = null;
const mCaptchaIframe = useTemplateRef('mCaptchaIframe');
const mCaptchaRemoveState = ref(false);
const mCaptchaIframeUrl = computed(() => {
if (props.provider === 'mcaptcha' && !mCaptchaRemoveState.value && props.instanceUrl && props.sitekey) {
const url = new URL('/widget', props.instanceUrl);
url.searchParams.set('sitekey', props.sitekey);
return url.toString();
}
return null;
});

const testcaptchaInput = ref('');
const testcaptchaPassed = ref(false);

Expand Down Expand Up @@ -129,8 +147,14 @@ function reset() {
if (_DEV_) console.warn(error);
}
}

testcaptchaPassed.value = false;
testcaptchaInput.value = '';

if (mCaptchaReciever != null) {
mCaptchaReciever.destroy();
mCaptchaReciever = null;
}
}

function remove() {
Expand All @@ -143,6 +167,10 @@ function remove() {
if (_DEV_) console.warn(error);
}
}

if (props.provider === 'mcaptcha') {
mCaptchaRemoveState.value = true;
}
}

async function requestRender() {
Expand All @@ -160,32 +188,29 @@ async function requestRender() {
'error-callback': () => callback(undefined),
});
} else if (props.provider === 'mcaptcha' && props.instanceUrl && props.sitekey) {
const { default: Widget } = await import('@mcaptcha/vanilla-glue');
new Widget({
const { default: Reciever } = await import('@mcaptcha/core-glue');
mCaptchaReciever = new Reciever({
siteKey: {
instanceUrl: new URL(props.instanceUrl),
key: props.sitekey,
instanceUrl: new URL(props.instanceUrl),
},
}, (token: string) => {
callback(token);
});
mCaptchaReciever.listen();
mCaptchaRemoveState.value = false;
} else {
window.setTimeout(requestRender, 1);
window.setTimeout(requestRender, 50);
}
}

function clearWidget() {
if (props.provider === 'mcaptcha') {
const container = window.document.getElementById('mcaptcha__widget-container');
if (container) {
container.innerHTML = '';
}
} else {
reset();
remove();
reset();
remove();

if (captchaEl.value) {
// レンダリング先のコンテナの中身を掃除し、フォームが増殖するのを抑止
captchaEl.value.innerHTML = '';
}
if (captchaEl.value) {
// レンダリング先のコンテナの中身を掃除し、フォームが増殖するのを抑止
captchaEl.value.innerHTML = '';
}
}

Expand Down
Loading
Loading