Skip to content

Commit

Permalink
Merge pull request #11 from OpenEVSE/jeremypoulter/issue29
Browse files Browse the repository at this point in the history
UI for Certificate management
  • Loading branch information
jeremypoulter authored Aug 7, 2024
2 parents e765f3a + e914b2d commit 9bcbcf7
Show file tree
Hide file tree
Showing 13 changed files with 426 additions and 79 deletions.
3 changes: 2 additions & 1 deletion jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
* a value or a type, so tell TypeScript to enforce using
* `import type` instead of `import` for Types.
*/
"importsNotUsedAsValues": "error",
"verbatimModuleSyntax": true,
"ignoreDeprecations": "5.0",
"isolatedModules": true,
"resolveJsonModule": true,
/**
Expand Down
97 changes: 97 additions & 0 deletions src/components/blocks/configuration/Certificates.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script>
import { uistates_store } from "./../../../lib/stores/uistates.js";
import { _ } from 'svelte-i18n'
import Box from "./../../ui/Box.svelte";
import Borders from "./../../ui/Borders.svelte";
import Button from "../../ui/Button.svelte"
import IconButton from "../../ui/IconButton.svelte"
import CertificatesModal from "./CertificatesModal.svelte";
import { certificate_store } from "../../../lib/stores/certificates.js"
import { config_store } from "./../../../lib/stores/config.js";
import { serialQueue } from "./../../../lib/queue.js";
let certificates_modal_opened = false
let removeCertificateState = ""
async function removeCertificate(id) {
let certificate = $certificate_store.findIndex(item => item.id === id)
removeCertificateState = "loading"
if (certificate > -1)
{
if(await serialQueue.add(() => certificate_store.remove(id)))
{
let config = { };
[
"mqtt_certitficate_id",
"www_certitficate_id"
].forEach(key => {
if ($config_store[key] == id) {
config[key] = ""
}
});
if (Object.keys(config).length > 0) {
await serialQueue.add(() => config_store.upload(config));
}
$certificate_store.splice(certificate,1)
$certificate_store = $certificate_store
removeCertificateState = ""
}
}
}
function uploadCertificate() {
certificates_modal_opened = true;
}
</script>

<Box title={$_("config.titles.certificates")} icon="mdi:certificate" back={true}>
<div class="my-2 is-flex is-justify-content-center is-align-items-center is-flex-direction-column" >
<Borders>
{#if $certificate_store.length}
<table class="table is-size-6 has-text-weight-normal" >
<thead>
<tr>
<th class="has-text-centered has-text-dark"><abbr title={$_("config.certificates.id")}>{$_("config.certificates.id")}</abbr></th>
<th class="has-text-centered has-text-dark"><abbr title={$_("config.certificates.type")}>{$_("config.certificates.type")}</abbr></th>
<th class="has-text-centered has-text-dark"><abbr title="{$_("config.certificates.name")}">{$_("config.certificates.name")}</abbr></th>
<th></th>
</tr>
</thead>
<tbody>
{#each $certificate_store as item}
<tr>
<td class="has-text-dark">{ item.id }</td>
<td class="has-text-dark">{ $_("config.certificates."+item.type) }</td>
<td class="has-text-dark">{ item.name }</td>
<td class="has-text-dark">
<div class="delabs">
<div class="del">
<IconButton
icon="fa6-solid:xmark"
size="is-size-5"
state={removeCertificateState}
color="has-text-danger"
butn_submit={()=>{removeCertificate(item.id)}}
/>
</div>
</div>
</td>
</tr>
{/each}
</tbody>
</table>
{:else}
<div class="content">{$_("config.certificates.empty")}</div>
{/if}
</Borders>
<div class="mt-4">
<Button name={$_("config.certificates.upload")} butn_submit={uploadCertificate}/>
</div>
</div>

</Box>

{#if certificates_modal_opened}
<CertificatesModal bind:is_opened={certificates_modal_opened} />
{/if}
128 changes: 128 additions & 0 deletions src/components/blocks/configuration/CertificatesModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<script>
import { _ } from 'svelte-i18n'
import Box from "../../ui/Box.svelte";
import Borders from "../../ui/Borders.svelte";
import Button from "../../ui/Button.svelte"
import Select from "../../ui/Select.svelte";
import InputForm from "../../ui/InputForm.svelte";
import { serialQueue } from "../../../lib/queue.js";
import Modal from "../..//ui/Modal.svelte";
import { certificate_store } from "../../../lib/stores/certificates.js"
import { validateFormData } from "./../../../lib/utils.js";
import { uistates_store } from "./../../../lib/stores/uistates.js";
import { get } from 'svelte/store'
export let is_opened = false;
let formdata = {
type: {val: undefined, input: undefined, status: "", req: true},
name: {val: undefined, input: undefined, status: "", req: true},
private_key: {val: undefined, input: undefined, status: "", req: true},
certificate: {val: undefined, input: undefined, status: "", req: true}
}
let saveCertificateState = ""
let timeout
function alert(msg) {
get(uistates_store).alertbox.title = "error"
get(uistates_store).alertbox.body = msg
get(uistates_store).alertbox.visible = true
}
async function saveCertificate()
{
saveCertificateState = "loading";
formdata.private_key.req = formdata.type.val === "client";
let valid = validateFormData({data: formdata, i18n_path: "config.certificates.missing-", req: true});
if (!valid.ok) {
saveCertificateState = "error";
alert(valid.msg)
return;
}
let certificate = {
name: formdata.name.val,
certificate: formdata.certificate.val
};
if (formdata.type.val === "client") {
certificate.key = formdata.private_key.val;
}
let res = await serialQueue.add(() => certificate_store.upload(certificate));
if(res.success)
{
saveCertificateState = "ok";
certificate.type = formdata.type.val;
certificate.id = res.id;
$certificate_store.push(certificate)
timeout = setTimeout(() => {
is_opened = false
}, 500)
} else {
saveCertificateState = "error";
alert(res.msg)
}
$certificate_store = $certificate_store
}
</script>

<Modal fit bind:is_opened>

<Box title={$_("config.titles.certificates")} icon="mdi:certificate">
<div class="is-flex is-align-items-center is-justify-content-center px-6-tablet">
<div class="has-text-centered">
<div class="">
<Select
items={[
{ name: $_("config.certificates.root"), value: "root" },
{ name: $_("config.certificates.client"), value: "client" }
]}
title={$_("config.certificates.type")}
bind:this={formdata.type.input}
bind:value={formdata.type.val}
bind:status={formdata.type.status}
/>

<InputForm
is_inline size={30}
title="{$_("config.certificates.name")}*"
placeholder="{$_("config.certificates.name_placeholder")}"
bind:this={formdata.name.input}
bind:value={formdata.name.val}
bind:status={formdata.name.status}
/>
</div>

<div>
<InputForm
title="{$_("config.certificates.certificate")}*"
multiline monospace
bind:this={formdata.certificate.input}
bind:value={formdata.certificate.val} placeholder="-----BEGIN CERTIFICATE-----..."
bind:status={formdata.certificate.status}
/>
</div>

{#if "client" === formdata.type.val}
<div>
<InputForm
title="{$_("config.certificates.private_key")}*"
multiline monospace
bind:this={formdata.private_key.input}
bind:value={formdata.private_key.val} placeholder="-----BEGIN RSA PRIVATE KEY-----..."
bind:status={formdata.private_key.status}
/>
</div>
{/if}
</div>
</div>
<div class="mt-4 is-flex is-justify-content-center mb-4">
<Button name={$_("save")} color="is-info" butn_submit={saveCertificate} state={saveCertificateState} />
<Button name={$_("cancel")} color="is-danger" butn_submit={()=>is_opened = false} />
</div>

</Box>

</Modal>
2 changes: 2 additions & 0 deletions src/components/blocks/configuration/Dev.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script>
import { tesla_store } from "./../../../lib/stores/tesla.js";
import { schedule_store } from "./../../../lib/stores/schedule.js";
import { certificate_store } from "./../../../lib/stores/certificates.js";
import { plan_store } from "./../../../lib/stores/plan.js";
import { override_store } from "./../../../lib/stores/override.js";
import { limit_store } from "./../../../lib/stores/limit.js";
Expand Down Expand Up @@ -82,6 +83,7 @@
data.status = {...$status_store}
data.plan = {...$plan_store}
data.schedule = {...$schedule_store}
data.certificates = {...$certificate_store}
data.config = {...$config_store}
data.limits = {...$limit_store}
data.tesla = {...$tesla_store}
Expand Down
Loading

0 comments on commit 9bcbcf7

Please sign in to comment.