mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-14 07:35:35 +02:00
Merge branch 'develop' into room
This commit is contained in:
@@ -135,6 +135,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkA :to="notePage(appearNote)">
|
||||
<MkTime :time="appearNote.createdAt" mode="detail" colored/>
|
||||
</MkA>
|
||||
<span style="margin-left: 0.5em;">
|
||||
<span style="border: 1px solid var(--MI_THEME-divider); margin-right: 0.5em;"></span>
|
||||
<i v-if="appearNote.visibility === 'public'" class="ti ti-world"></i>
|
||||
<i v-else-if="appearNote.visibility === 'home'" class="ti ti-home"></i>
|
||||
<i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
|
||||
<i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
|
||||
<span style="margin-left: 0.3em;">{{ i18n.ts._visibility[appearNote.visibility] }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<MkReactionsViewer
|
||||
v-if="appearNote.reactionAcceptance !== 'likeOnly'"
|
||||
|
||||
@@ -22,21 +22,21 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { get as webAuthnRequest } from '@github/webauthn-json/browser-ponyfill';
|
||||
import { startAuthentication } from '@simplewebauthn/browser';
|
||||
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
import type { AuthenticationPublicKeyCredential } from '@github/webauthn-json/browser-ponyfill';
|
||||
import type { PublicKeyCredentialRequestOptionsJSON, AuthenticationResponseJSON } from '@simplewebauthn/browser';
|
||||
|
||||
const props = defineProps<{
|
||||
credentialRequest: CredentialRequestOptions;
|
||||
credentialRequest: PublicKeyCredentialRequestOptionsJSON;
|
||||
isPerformingPasswordlessLogin?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'done', credential: AuthenticationPublicKeyCredential): void;
|
||||
(ev: 'done', credential: AuthenticationResponseJSON): void;
|
||||
(ev: 'useTotp'): void;
|
||||
}>();
|
||||
|
||||
@@ -44,7 +44,7 @@ const queryingKey = ref(true);
|
||||
|
||||
async function queryKey() {
|
||||
queryingKey.value = true;
|
||||
await webAuthnRequest(props.credentialRequest)
|
||||
await startAuthentication({ optionsJSON: props.credentialRequest })
|
||||
.catch(() => {
|
||||
return Promise.reject(null);
|
||||
})
|
||||
|
||||
@@ -67,8 +67,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, ref, shallowRef, useTemplateRef } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { supported as webAuthnSupported, parseRequestOptionsFromJSON } from '@github/webauthn-json/browser-ponyfill';
|
||||
import type { AuthenticationPublicKeyCredential } from '@github/webauthn-json/browser-ponyfill';
|
||||
import { browserSupportsWebAuthn } from '@simplewebauthn/browser';
|
||||
import type { PublicKeyCredentialRequestOptionsJSON, AuthenticationResponseJSON } from '@simplewebauthn/browser';
|
||||
import type { OpenOnRemoteOptions } from '@/utility/please-login.js';
|
||||
import type { PwResponse } from '@/components/MkSignin.password.vue';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
@@ -108,21 +108,18 @@ const userInfo = ref<null | Misskey.entities.UserDetailed>(null);
|
||||
const password = ref('');
|
||||
|
||||
//#region Passkey Passwordless
|
||||
const credentialRequest = shallowRef<CredentialRequestOptions | null>(null);
|
||||
const credentialRequest = shallowRef<PublicKeyCredentialRequestOptionsJSON | null>(null);
|
||||
const passkeyContext = ref('');
|
||||
const doingPasskeyFromInputPage = ref(false);
|
||||
|
||||
function onPasskeyLogin(): void {
|
||||
if (webAuthnSupported()) {
|
||||
if (browserSupportsWebAuthn()) {
|
||||
doingPasskeyFromInputPage.value = true;
|
||||
waiting.value = true;
|
||||
misskeyApi('signin-with-passkey', {})
|
||||
.then((res) => {
|
||||
passkeyContext.value = res.context ?? '';
|
||||
credentialRequest.value = parseRequestOptionsFromJSON({
|
||||
// @ts-expect-error TODO: misskey-js由来の型(@simplewebauthn/types)とフロントエンド由来の型(@github/webauthn-json)が合わない
|
||||
publicKey: res.option,
|
||||
});
|
||||
credentialRequest.value = res.option;
|
||||
|
||||
page.value = 'passkey';
|
||||
waiting.value = false;
|
||||
@@ -131,12 +128,12 @@ function onPasskeyLogin(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function onPasskeyDone(credential: AuthenticationPublicKeyCredential): void {
|
||||
function onPasskeyDone(credential: AuthenticationResponseJSON): void {
|
||||
waiting.value = true;
|
||||
|
||||
if (doingPasskeyFromInputPage.value) {
|
||||
misskeyApi<Misskey.entities.SigninWithPasskeyResponse>('signin-with-passkey', {
|
||||
credential: credential.toJSON(),
|
||||
misskeyApi('signin-with-passkey', {
|
||||
credential: credential,
|
||||
context: passkeyContext.value,
|
||||
}).then((res) => {
|
||||
if (res.signinResponse == null) {
|
||||
@@ -150,8 +147,7 @@ function onPasskeyDone(credential: AuthenticationPublicKeyCredential): void {
|
||||
tryLogin({
|
||||
username: userInfo.value.username,
|
||||
password: password.value,
|
||||
// @ts-expect-error TODO: misskey-js由来の型(@simplewebauthn/types)とフロントエンド由来の型(@github/webauthn-json)が合わない
|
||||
credential: credential.toJSON(),
|
||||
credential: credential,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -253,11 +249,8 @@ async function tryLogin(req: Partial<Misskey.entities.SigninFlowRequest>): Promi
|
||||
break;
|
||||
}
|
||||
case 'passkey': {
|
||||
if (webAuthnSupported()) {
|
||||
credentialRequest.value = parseRequestOptionsFromJSON({
|
||||
// @ts-expect-error TODO: misskey-js由来の型(@simplewebauthn/types)とフロントエンド由来の型(@github/webauthn-json)が合わない
|
||||
publicKey: res.authRequest,
|
||||
});
|
||||
if (browserSupportsWebAuthn()) {
|
||||
credentialRequest.value = res.authRequest;
|
||||
page.value = 'passkey';
|
||||
} else {
|
||||
page.value = 'totp';
|
||||
|
||||
@@ -86,7 +86,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
import { defineAsyncComponent, onDeactivated, onUnmounted, ref } from 'vue';
|
||||
import { url as local } from '@@/js/config.js';
|
||||
import { versatileLang } from '@@/js/intl-const.js';
|
||||
import type { summaly } from '@misskey-dev/summaly';
|
||||
import type { SummalyResult } from '@misskey-dev/summaly';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
import { deviceKind } from '@/utility/device-kind.js';
|
||||
@@ -96,8 +96,6 @@ import { store } from '@/store.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
import { maybeMakeRelative } from '@@/js/url.js';
|
||||
|
||||
type SummalyResult = Awaited<ReturnType<typeof summaly>>;
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
url: string;
|
||||
detail?: boolean;
|
||||
|
||||
@@ -161,6 +161,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</template>
|
||||
</XFolder>
|
||||
|
||||
<XFolder v-if="matchQuery([i18n.ts._role._options.canCreateChannel, 'canCreateChannel'])" v-model:policyMeta="policyMetaModel.canCreateChannel" :isBaseRole="isBaseRole" :readonly="readonly">
|
||||
<template #label>{{ i18n.ts._role._options.canCreateChannel }}</template>
|
||||
<template #suffix>{{ valuesModel.canCreateChannel ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||
<template #default="{ disabled }">
|
||||
<MkSwitch v-model="valuesModel.canCreateChannel" :disabled="disabled">
|
||||
<template #label>{{ i18n.ts.enable }}</template>
|
||||
</MkSwitch>
|
||||
</template>
|
||||
</XFolder>
|
||||
|
||||
<XFolder v-if="matchQuery([i18n.ts._role._options.driveCapacity, 'driveCapacityMb'])" v-model:policyMeta="policyMetaModel.driveCapacityMb" :isBaseRole="isBaseRole" :readonly="readonly">
|
||||
<template #label>{{ i18n.ts._role._options.driveCapacity }}</template>
|
||||
<template #valueText>{{ valuesModel.driveCapacityMb }}MB</template>
|
||||
|
||||
@@ -139,6 +139,7 @@ async function assign() {
|
||||
|
||||
await os.apiWithDialog('admin/roles/assign', { roleId: role.id, userId: user.id, expiresAt });
|
||||
//role.users.push(user);
|
||||
usersPaginator.reload();
|
||||
}
|
||||
|
||||
async function unassign(userId: Misskey.entities.User['id'], ev: PointerEvent) {
|
||||
@@ -149,6 +150,7 @@ async function unassign(userId: Misskey.entities.User['id'], ev: PointerEvent) {
|
||||
action: async () => {
|
||||
await os.apiWithDialog('admin/roles/unassign', { roleId: role.id, userId: userId });
|
||||
//role.users = role.users.filter(u => u.id !== userId);
|
||||
usersPaginator.reload();
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</MkPagination>
|
||||
</div>
|
||||
<div v-else-if="tab === 'owned'" class="_gaps">
|
||||
<MkButton type="routerLink" primary rounded to="/channels/new"><i class="ti ti-plus"></i> {{ i18n.ts.createNew }}</MkButton>
|
||||
<MkButton v-if="$i?.policies.canCreateChannel" type="routerLink" primary rounded to="/channels/new"><i class="ti ti-plus"></i> {{ i18n.ts.createNew }}</MkButton>
|
||||
<MkPagination v-slot="{items}" :paginator="ownedPaginator">
|
||||
<div :class="$style.root">
|
||||
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
|
||||
@@ -74,6 +74,7 @@ import { definePage } from '@/page.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { Paginator } from '@/utility/paginator.js';
|
||||
import { $i } from '@/i.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
@@ -48,11 +48,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
{{ i18n.ts._2fa.securityKeyInfo }}
|
||||
</MkInfo>
|
||||
|
||||
<MkInfo v-if="!webAuthnSupported()" warn>
|
||||
<MkInfo v-if="!browserSupportsWebAuthn()" warn>
|
||||
{{ i18n.ts._2fa.securityKeyNotSupported }}
|
||||
</MkInfo>
|
||||
|
||||
<MkInfo v-else-if="webAuthnSupported() && !$i.twoFactorEnabled" warn>
|
||||
<MkInfo v-else-if="browserSupportsWebAuthn() && !$i.twoFactorEnabled" warn>
|
||||
{{ i18n.ts._2fa.registerTOTPBeforeKey }}
|
||||
</MkInfo>
|
||||
|
||||
@@ -83,8 +83,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, computed } from 'vue';
|
||||
import { supported as webAuthnSupported, create as webAuthnCreate, parseCreationOptionsFromJSON } from '@github/webauthn-json/browser-ponyfill';
|
||||
import { computed } from 'vue';
|
||||
import { browserSupportsWebAuthn, startRegistration } from '@simplewebauthn/browser';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
@@ -196,12 +196,9 @@ async function addSecurityKey() {
|
||||
const auth = await os.authenticateDialog();
|
||||
if (auth.canceled) return;
|
||||
|
||||
const registrationOptions = parseCreationOptionsFromJSON({
|
||||
// @ts-expect-error misskey-js側に型がない
|
||||
publicKey: await os.apiWithDialog('i/2fa/register-key', {
|
||||
password: auth.result.password,
|
||||
token: auth.result.token,
|
||||
}),
|
||||
const registrationOptions = await os.apiWithDialog('i/2fa/register-key', {
|
||||
password: auth.result.password,
|
||||
token: auth.result.token,
|
||||
});
|
||||
|
||||
const name = await os.inputText({
|
||||
@@ -214,7 +211,7 @@ async function addSecurityKey() {
|
||||
if (name.canceled) return;
|
||||
|
||||
const credential = await os.promiseDialog(
|
||||
webAuthnCreate(registrationOptions),
|
||||
startRegistration({ optionsJSON: registrationOptions }),
|
||||
null,
|
||||
() => {}, // ユーザーのキャンセルはrejectなのでエラーダイアログを出さない
|
||||
i18n.ts._2fa.tapSecurityKey,
|
||||
@@ -228,8 +225,7 @@ async function addSecurityKey() {
|
||||
password: auth.result.password,
|
||||
token: auth.result.token,
|
||||
name: name.result,
|
||||
// @ts-expect-error misskey-js側に型がない
|
||||
credential: credential.toJSON(),
|
||||
credential: credential,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user