1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-24 23:01:05 +03:00

Move the cross signing reset UI in its own page

This commit is contained in:
Quentin Gliech
2024-02-16 19:26:38 +01:00
parent 0d4b941b43
commit aefcc3cae2
16 changed files with 330 additions and 239 deletions

View File

@@ -0,0 +1,139 @@
// Copyright 2024 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { createFileRoute, notFound } from "@tanstack/react-router";
import IconArrowLeft from "@vector-im/compound-design-tokens/icons/arrow-left.svg?react";
import IconKey from "@vector-im/compound-design-tokens/icons/key.svg?react";
import { Alert, Button, Text } from "@vector-im/compound-web";
import { useTranslation } from "react-i18next";
import { useMutation, useQuery } from "urql";
import { z } from "zod";
import BlockList from "../components/BlockList";
import { ButtonLink } from "../components/ButtonLink";
import LoadingSpinner from "../components/LoadingSpinner";
import PageHeading from "../components/PageHeading";
import { graphql } from "../gql";
const searchSchema = z.object({
deepLink: z.boolean().optional(),
});
type Search = z.infer<typeof searchSchema>;
const CURRENT_VIEWER_QUERY = graphql(/* GraphQL */ `
query CurrentViewerQuery {
viewer {
__typename
... on Node {
id
}
}
}
`);
const ALLOW_CROSS_SIGING_RESET_MUTATION = graphql(/* GraphQL */ `
mutation AllowCrossSigningReset($userId: ID!) {
allowUserCrossSigningReset(input: { userId: $userId }) {
user {
id
}
}
}
`);
export const Route = createFileRoute("/reset-cross-signing")({
async loader({ context, abortController: { signal } }) {
const viewer = await context.client.query(
CURRENT_VIEWER_QUERY,
{},
{ fetchOptions: { signal } },
);
if (viewer.error) throw viewer.error;
if (viewer.data?.viewer.__typename !== "User") throw notFound();
},
validateSearch: (search): Search => searchSchema.parse(search),
component: ResetCrossSigning,
});
function ResetCrossSigning(): React.ReactNode {
const { deepLink } = Route.useSearch();
const { t } = useTranslation();
const [viewer] = useQuery({ query: CURRENT_VIEWER_QUERY });
if (viewer.error) throw viewer.error;
if (viewer.data?.viewer.__typename !== "User") throw notFound();
const userId = viewer.data.viewer.id;
const [result, allowReset] = useMutation(ALLOW_CROSS_SIGING_RESET_MUTATION);
const onClick = (): void => {
allowReset({ userId });
};
return (
<BlockList>
<PageHeading
Icon={IconKey}
title={t("frontend.reset_cross_signing.heading")}
invalid
/>
{!result.data && !result.error && (
<>
<Text className="text-justify">
{t("frontend.reset_cross_signing.description")}
</Text>
<Button
kind="primary"
destructive
disabled={result.fetching}
onClick={onClick}
>
{!!result.fetching && <LoadingSpinner inline />}
{t("frontend.reset_cross_signing.button")}
</Button>
</>
)}
{result.data && (
<Alert
type="info"
title={t("frontend.reset_cross_signing.success.title")}
>
{t("frontend.reset_cross_signing.success.description")}
</Alert>
)}
{result.error && (
<Alert
type="critical"
title={t("frontend.reset_cross_signing.failure.title")}
>
{t("frontend.reset_cross_signing.failure.description")}
</Alert>
)}
{!deepLink && (
<ButtonLink
to=".."
from={Route.fullPath}
kind="tertiary"
Icon={IconArrowLeft}
>
{t("action.back")}
</ButtonLink>
)}
</BlockList>
);
}