Skip to content

Commit

Permalink
feat(auth) allow certificate adding with tokens WD-4251 canonical#343
Browse files Browse the repository at this point in the history
  • Loading branch information
edlerd committed Jun 7, 2023
1 parent 36f4014 commit 98a4a2c
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const InstanceDetail = lazy(() => import("pages/instances/InstanceDetail"));
const StorageList = lazy(() => import("pages/storage/StorageList"));
const ProfileDetail = lazy(() => import("pages/profiles/ProfileDetail"));
const OperationList = lazy(() => import("pages/operations/OperationList"));
const CertificateAdd = lazy(() => import("pages/certificates/CertificateAdd"));
const CertificateGenerate = lazy(
() => import("pages/certificates/CertificateGenerate")
);
Expand Down Expand Up @@ -239,6 +240,7 @@ const App: FC = () => {
path="/ui/certificates/generate"
element={<CertificateGenerate />}
/>
<Route path="/ui/certificates/add" element={<CertificateAdd />} />
<Route path="*" element={<NoMatch />} />
</Routes>
</Suspense>
Expand Down
18 changes: 18 additions & 0 deletions src/api/certificates.tsx
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
import { handleResponse } from "util/helpers";

export const checkAuth = () =>
fetch("/1.0/certificates").then((response) => response.status !== 403);

export const addCertificate = (token: string) => {
return new Promise((resolve, reject) => {
fetch(`/1.0/certificates`, {
method: "POST",
body: JSON.stringify({
type: "client",
password: token,
name: "some-name",
}),
})
.then(handleResponse)
.then(resolve)
.catch(reject);
});
};
2 changes: 1 addition & 1 deletion src/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ const Navigation: FC = () => {
<li className="p-side-navigation__item">
<NavLink
className="p-side-navigation__link"
to="/ui/certificates/generate"
to="/ui/certificates"
title="Authentication"
>
<Icon
Expand Down
87 changes: 87 additions & 0 deletions src/pages/certificates/CertificateAdd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { FC } from "react";
import { Col, Row } from "@canonical/react-components";
import { Navigate } from "react-router-dom";
import { useAuth } from "context/auth";
import Loader from "components/Loader";
import CertificateAddForm from "pages/certificates/CertificateAddForm";
import NotificationRow from "components/NotificationRow";

const CertificateAdd: FC = () => {
const { isAuthenticated, isAuthLoading } = useAuth();

if (isAuthLoading) {
return <Loader />;
}

if (isAuthenticated) {
return <Navigate to="/ui" replace={true} />;
}

return (
<main className="l-main certificate-generate">
<div className="p-panel">
<div className="p-panel__header is-sticky">
<h1 className="p-panel__title">Add existing certificate</h1>
</div>
<div className="p-panel__content">
<NotificationRow />
<Row className="u-no-margin--left">
<Col size={12}>
<ol className="p-stepped-list--detailed">
<li className="p-stepped-list__item">
<Row>
<Col size={3}>
<h2 className="p-stepped-list__title p-heading--3">
Create token
</h2>
</Col>
<Col size={6}>
<div className="p-stepped-list__content">
<p>Generate a token on the command line</p>
<div className="p-code-snippet">
<pre className="p-code-snippet__block--icon">
<code>lxc config trust add --name lxd-ui</code>
</pre>
</div>
</div>
</Col>
</Row>
</li>
<li className="p-stepped-list__item">
<Row>
<Col size={3}>
<h2 className="p-stepped-list__title p-heading--3">
Use token
</h2>
</Col>
<Col size={6}>
<div className="p-stepped-list__content">
<CertificateAddForm />
</div>
</Col>
</Row>
</li>
<li className="p-stepped-list__item u-no-margin--bottom">
<Row>
<Col size={3}>
<h2 className="p-stepped-list__title p-heading--3">
Done
</h2>
</Col>
<Col size={6}>
<div className="p-stepped-list__content">
<p>Enjoy LXD UI.</p>
</div>
</Col>
</Row>
</li>
</ol>
</Col>
</Row>
</div>
</div>
</main>
);
};

export default CertificateAdd;
40 changes: 40 additions & 0 deletions src/pages/certificates/CertificateAddForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { FC, useState } from "react";
import { Button, Form, Textarea } from "@canonical/react-components";
import { addCertificate } from "api/certificates";
import { useNotify } from "context/notify";

const CertificateAddForm: FC = () => {
const notify = useNotify();
const [token, setToken] = useState("");

const useToken = () => {
addCertificate(token)
.then(() => {
location.reload();
})
.catch((e) => notify.failure("Error using token", e));
};

return (
<Form>
<Textarea
id="token"
name="token"
label="Paste the token from the previous step"
placeholder="Paste your token here"
rows={3}
onChange={(e) => setToken(e.target.value)}
/>
<Button
appearance="positive"
disabled={token.length < 1}
type="button"
onClick={useToken}
>
Import
</Button>
</Form>
);
};

export default CertificateAddForm;
7 changes: 7 additions & 0 deletions src/pages/certificates/CertificateMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ const CertificateMain: FC = () => {
>
Setup
</Button>
<p>
If you have imported a client certificate to your Browser previously,
add it to this LXD instance using tokens.
</p>
<Button appearance="" onClick={() => navigate("/ui/certificates/add")}>
Add cert
</Button>
</EmptyState>
</BaseLayout>
);
Expand Down

0 comments on commit 98a4a2c

Please sign in to comment.