Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/apps/web/components/credentials/NewToken.tsx
blob: 80640aca1781fec54b832593112b0b250ebec7c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
// SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1

"use client";

import { useEffect, useState } from "react";
import {
  callOAuthApi,
  signsPeopleIn,
  type ApplicationCredentials,
  type ApplicationKind,
  type SessionView,
} from "@/lib/credentials";
import { getCredentialsMessages } from "@/lib/credentials-messages";
import type { Locale } from "@/lib/localization";
import { AccountSignInNotice } from "./AccountSignInNotice";
import { ApplicationForm } from "./ApplicationForm";
import { CredentialsCard } from "./CredentialsCard";

/**
 * The second step of a new token: the form of the chosen type, and then the
 * client identifier and the secret, shown once.
 */
export function NewToken({
  locale,
  kind,
}: {
  locale: Locale;
  kind: ApplicationKind;
}) {
  const { form, common, details } = getCredentialsMessages(locale);
  const [created, setCreated] = useState<ApplicationCredentials | null>(null);
  const [signedOut, setSignedOut] = useState(false);

  // Nobody signed in to the Progmasoft account: show where to sign in.
  useEffect(() => {
    void callOAuthApi<SessionView>("/session").then((result) => {
      setSignedOut(result.kind === "signedOut");
    });
  }, []);

  if (signedOut) {
    return <AccountSignInNotice locale={locale} />;
  }
  if (created) {
    return (
      <CredentialsCard
        locale={locale}
        title={details.tokenCreated}
        credentials={created}
      />
    );
  }

  return (
    <ApplicationForm
      locale={locale}
      kind={kind}
      initial={{
        displayName: "",
        homepage: "",
        redirectUris: [],
        postLogoutRedirectUris: [],
        scopes: signsPeopleIn(kind) ? ["profile"] : [],
      }}
      submitLabel={form.create}
      onSubmit={async (submission) => {
        const result = await callOAuthApi<ApplicationCredentials>(
          "/applications",
          { method: "POST", body: submission },
        );
        switch (result.kind) {
          case "ok":
            setCreated(result.value);
            return null;
          case "signedOut":
            setSignedOut(true);
            return null;
          case "refused":
            return result.errors;
          default:
            return { form: common.unreachable };
        }
      }}
    />
  );
}