Show private key after API key creation
This commit is contained in:
		
							
								
								
									
										58
									
								
								virtweb_frontend/src/dialogs/CreatedTokenDialog.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								virtweb_frontend/src/dialogs/CreatedTokenDialog.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
import {
 | 
			
		||||
  Button,
 | 
			
		||||
  Dialog,
 | 
			
		||||
  DialogActions,
 | 
			
		||||
  DialogContent,
 | 
			
		||||
  DialogTitle,
 | 
			
		||||
  Typography,
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { APITokenURL, CreatedAPIToken } from "../api/TokensApi";
 | 
			
		||||
import { CopyToClipboard } from "../widgets/CopyToClipboard";
 | 
			
		||||
import { InlineCode } from "../widgets/InlineCode";
 | 
			
		||||
 | 
			
		||||
export function CreatedTokenDialog(p: {
 | 
			
		||||
  createdToken: CreatedAPIToken;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const close = () => {
 | 
			
		||||
    navigate(APITokenURL(p.createdToken.token));
 | 
			
		||||
  };
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog open>
 | 
			
		||||
      <DialogTitle>Token successfully created</DialogTitle>
 | 
			
		||||
      <DialogContent>
 | 
			
		||||
        <Typography>
 | 
			
		||||
          Your token was successfully created. You need now to copy the private
 | 
			
		||||
          key, as it will be technically impossible to recover it after closing
 | 
			
		||||
          this dialog.
 | 
			
		||||
        </Typography>
 | 
			
		||||
 | 
			
		||||
        <InfoBlock label="Key ID" value={p.createdToken.token.id} />
 | 
			
		||||
        <InfoBlock label="Key algorithm" value={p.createdToken.priv_key.alg} />
 | 
			
		||||
        <InfoBlock label="Private key" value={p.createdToken.priv_key.priv} />
 | 
			
		||||
      </DialogContent>
 | 
			
		||||
      <DialogActions>
 | 
			
		||||
        <Button onClick={close} color="error">
 | 
			
		||||
          I copied the key, close this dialog
 | 
			
		||||
        </Button>
 | 
			
		||||
      </DialogActions>
 | 
			
		||||
    </Dialog>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function InfoBlock(
 | 
			
		||||
  p: React.PropsWithChildren<{ label: string; value: string }>
 | 
			
		||||
): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      style={{ display: "flex", flexDirection: "column", margin: "20px 10px" }}
 | 
			
		||||
    >
 | 
			
		||||
      <Typography variant="overline">{p.label}</Typography>
 | 
			
		||||
      <CopyToClipboard content={p.value}>
 | 
			
		||||
        <InlineCode>{p.value}</InlineCode>
 | 
			
		||||
      </CopyToClipboard>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,13 @@
 | 
			
		||||
import { Button } from "@mui/material";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { useNavigate, useParams } from "react-router-dom";
 | 
			
		||||
import { APIToken, APITokenURL, TokensApi } from "../api/TokensApi";
 | 
			
		||||
import {
 | 
			
		||||
  APIToken,
 | 
			
		||||
  APITokenURL,
 | 
			
		||||
  CreatedAPIToken,
 | 
			
		||||
  TokensApi,
 | 
			
		||||
} from "../api/TokensApi";
 | 
			
		||||
import { CreatedTokenDialog } from "../dialogs/CreatedTokenDialog";
 | 
			
		||||
import { useAlert } from "../hooks/providers/AlertDialogProvider";
 | 
			
		||||
import { useLoadingMessage } from "../hooks/providers/LoadingMessageProvider";
 | 
			
		||||
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
 | 
			
		||||
@@ -18,6 +24,10 @@ export function CreateApiTokenRoute(): React.ReactElement {
 | 
			
		||||
  const snackbar = useSnackbar();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const [createdToken, setCreatedToken] = React.useState<
 | 
			
		||||
    CreatedAPIToken | undefined
 | 
			
		||||
  >();
 | 
			
		||||
 | 
			
		||||
  const [token] = React.useState<APIToken>({
 | 
			
		||||
    id: "",
 | 
			
		||||
    name: "",
 | 
			
		||||
@@ -32,8 +42,7 @@ export function CreateApiTokenRoute(): React.ReactElement {
 | 
			
		||||
    try {
 | 
			
		||||
      const res = await TokensApi.Create(n);
 | 
			
		||||
      snackbar("The api token was successfully created!");
 | 
			
		||||
      // TODO : show a modal to give token information
 | 
			
		||||
      navigate(APITokenURL(res.token));
 | 
			
		||||
      setCreatedToken(res);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      alert(`Failed to create API token!\n${e}`);
 | 
			
		||||
@@ -41,12 +50,16 @@ export function CreateApiTokenRoute(): React.ReactElement {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <EditApiTokenRouteInner
 | 
			
		||||
      token={token}
 | 
			
		||||
      creating={true}
 | 
			
		||||
      onCancel={() => navigate("/tokens")}
 | 
			
		||||
      onSave={createApiToken}
 | 
			
		||||
    />
 | 
			
		||||
    <>
 | 
			
		||||
      {createdToken && <CreatedTokenDialog createdToken={createdToken} />}
 | 
			
		||||
 | 
			
		||||
      <EditApiTokenRouteInner
 | 
			
		||||
        token={token}
 | 
			
		||||
        creating={true}
 | 
			
		||||
        onCancel={() => navigate("/tokens")}
 | 
			
		||||
        onSave={createApiToken}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								virtweb_frontend/src/widgets/InlineCode.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								virtweb_frontend/src/widgets/InlineCode.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
export function InlineCode(p: React.PropsWithChildren): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <code
 | 
			
		||||
      style={{
 | 
			
		||||
        display: "inline-block",
 | 
			
		||||
        backgroundColor: "black",
 | 
			
		||||
        color: "white",
 | 
			
		||||
        wordBreak: "break-all",
 | 
			
		||||
        wordWrap: "break-word",
 | 
			
		||||
        whiteSpace: "pre-wrap",
 | 
			
		||||
        padding: "0px 7px",
 | 
			
		||||
        borderRadius: "5px",
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      {p.children}
 | 
			
		||||
    </code>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@ import React, { PropsWithChildren } from "react";
 | 
			
		||||
import { NetworkHookStatus, ServerApi } from "../../api/ServerApi";
 | 
			
		||||
import { AsyncWidget } from "../AsyncWidget";
 | 
			
		||||
import { CopyToClipboard } from "../CopyToClipboard";
 | 
			
		||||
import { InlineCode } from "../InlineCode";
 | 
			
		||||
 | 
			
		||||
export function NetworkHookStatusWidget(p: {
 | 
			
		||||
  hiddenIfInstalled: boolean;
 | 
			
		||||
@@ -72,25 +73,6 @@ function NetworkHookStatusWidgetInner(p: {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function InlineCode(p: PropsWithChildren): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <code
 | 
			
		||||
      style={{
 | 
			
		||||
        display: "inline-block",
 | 
			
		||||
        backgroundColor: "black",
 | 
			
		||||
        color: "white",
 | 
			
		||||
        wordBreak: "break-all",
 | 
			
		||||
        wordWrap: "break-word",
 | 
			
		||||
        whiteSpace: "pre-wrap",
 | 
			
		||||
        padding: "0px 7px",
 | 
			
		||||
        borderRadius: "5px",
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      {p.children}
 | 
			
		||||
    </code>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function CodeBlock(p: PropsWithChildren): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <pre
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user