Skip to content

Commit

Permalink
Paste option for dist gpg keys
Browse files Browse the repository at this point in the history
  • Loading branch information
ThetaSinner committed Feb 20, 2024
1 parent 3c14b78 commit 8c77b32
Showing 1 changed file with 79 additions and 57 deletions.
136 changes: 79 additions & 57 deletions ui/src/trusted/trusted/DistributeGpgKey.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,55 @@ import { readKey } from "openpgp";
import { useNotificationsStore } from "../../store/notifications-store";
import KeyList from "../../component/KeyList.vue";
const selected = ref<Partial<GpgKeyDist>>({});
const creating = ref(false);
const inputField = ref<HTMLElement | null>(null);
const client = inject("client") as ComputedRef<AppAgentClient>;
const notifications = useNotificationsStore();
const selected = ref<Partial<GpgKeyDist>>({});
const creating = ref(false);
const inputType = ref<'file' | 'paste'>('file');
const fileInputField = ref<HTMLElement | null>(null);
const textAreaInputField = ref<HTMLElement | null>(null);
const isGpgKeyValid = computed(() => {
return true && selected.value.fingerprint;
});
const handleNewKeyProvided = (armoredKey: string) => {
selected.value.public_key = armoredKey as string;
readKey({ armoredKey: selected.value.public_key })
.then(async (key) => {
selected.value.fingerprint = key.getFingerprint();
if (key.users) {
const user = key.users[0];
if (user.userID) {
const userId = user.userID;
if (userId.userID) {
selected.value.name = userId.name;
}
if (userId.email) {
selected.value.email = userId.email;
}
}
}
const expirationDate = await key.getExpirationTime();
if (typeof expirationDate == "object") {
selected.value.expires_at = expirationDate as Date;
}
})
.catch((e) => {
notifications.pushNotification({
message: `${e}`,
type: "error",
});
});
};
const onPublicKeySelect = async (event: Event) => {
if (!event.target) return;
Expand All @@ -32,41 +69,9 @@ const onPublicKeySelect = async (event: Event) => {
reader.onload = (evt) => {
const armoredKey = evt.target?.result;
if (!armoredKey) return;
selected.value.public_key = armoredKey as string;
readKey({ armoredKey: selected.value.public_key })
.then(async (key) => {
selected.value.fingerprint = key.getFingerprint();
if (key.users) {
const user = key.users[0];
if (user.userID) {
const userId = user.userID;
if (userId.userID) {
selected.value.name = userId.name;
}
if (userId.email) {
selected.value.email = userId.email;
}
}
}
const expirationDate = await key.getExpirationTime();
if (typeof expirationDate == "object") {
selected.value.expires_at = expirationDate as Date;
}
})
.catch((e) => {
notifications.pushNotification({
message: `${e}`,
type: "error",
});
});
handleNewKeyProvided(armoredKey as string);
};
reader.onerror = (evt) => {
Expand All @@ -77,13 +82,34 @@ const onPublicKeySelect = async (event: Event) => {
};
};
const onPublicKeyPaste = async (event: Event) => {
if (event.type === 'paste') {
const value = (event as ClipboardEvent).clipboardData?.getData('text/plain');
if (!value) return;
handleNewKeyProvided(value);
} else {
if (!event.target) return;
const value = (event.target as HTMLTextAreaElement).value;
// Change event will fire on click away after a paste so filter that out
if (!value || value === selected.value.public_key) return;
handleNewKeyProvided(value);
}
};
const resetForm = async () => {
selected.value.fingerprint = "";
selected.value.expires_at = undefined;
selected.value.public_key = "";
if (inputField.value) {
(inputField.value as HTMLInputElement).value = "";
if (fileInputField.value) {
(fileInputField.value as HTMLInputElement).value = "";
}
if (textAreaInputField.value) {
(textAreaInputField.value as HTMLTextAreaElement).value = "";
}
};
Expand Down Expand Up @@ -120,14 +146,18 @@ const distributeGpgKey = async () => {
<template>
<p class="text-lg">Distribute your GPG public key</p>

<div class="flex justify-center">
<div role="tablist" class="tabs tabs-boxed w-1/2">
<a role="tab" :class="{ tab: true, 'tab-active': inputType === 'file' }" @click="inputType = 'file'">Select file</a>
<a role="tab" :class="{ tab: true, 'tab-active': inputType === 'paste' }" @click="inputType = 'paste'">Paste</a>
</div>
</div>

<div class="flex justify-center my-3">
<input
type="file"
accept="text/*,.asc"
@change="onPublicKeySelect"
ref="inputField"
class="file-input file-input-bordered file-input-primary"
/>
<input v-if="inputType === 'file'" type="file" accept="text/*,.asc" @change="onPublicKeySelect" ref="fileInputField"
class="file-input file-input-bordered file-input-primary" />
<textarea v-else class="textarea textarea-ghost w-1/2" placeholder="Paste your GPG public key here"
@change="onPublicKeyPaste" @paste="onPublicKeyPaste" ref="textAreaInputField"></textarea>
</div>

<div v-if="selected.fingerprint" class="mt-5">
Expand All @@ -136,23 +166,15 @@ const distributeGpgKey = async () => {
<KeyList :keys="[selected as GpgKeyDist]" :readonly="true"></KeyList>
</div>

<div class="flex justify-center my-3">
<div class="flex justify-end my-3">
<div class="join">
<button
class="btn btn-primary join-item"
:disabled="!isGpgKeyValid || creating"
@click="distributeGpgKey"
>
<button class="btn btn-primary join-item" :disabled="!isGpgKeyValid || creating" @click="distributeGpgKey">
<span v-if="creating" class="loading loading-spinner"></span>
<span v-else>{{
creating ? "Creating..." : "Distribute Gpg Key"
}}</span>
</button>
<button
class="btn btn-secondary join-item"
:disabled="!selected.fingerprint"
@click="resetForm"
>
<button class="btn btn-secondary join-item" :disabled="!selected.fingerprint" @click="resetForm">
Cancel
</button>
</div>
Expand Down

0 comments on commit 8c77b32

Please sign in to comment.