Skip to content

Commit

Permalink
Merge pull request #2653 from threefoldtech/development_edit_sshKey
Browse files Browse the repository at this point in the history
Make ssh key editable
  • Loading branch information
amiraabouhadid authored May 9, 2024
2 parents fccd8f5 + c0b1ba6 commit c7e57db
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@
</v-dialog>

<!-- View SSH Key -->
<ssh-data-dialog :open="isViewSSHKey" :selected-key="selectedKey" @close="onCloseSelectKey" />
<ssh-data-dialog
:open="isViewSSHKey"
:selected-key="selectedKey"
:all-keys="selectedKeys"
@close="onCloseSelectKey"
/>
</template>

<script lang="ts">
Expand Down
75 changes: 67 additions & 8 deletions packages/playground/src/components/ssh_keys/SshDataDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,28 @@
<template v-slot:default>
<v-card>
<v-toolbar color="primary" class="custom-toolbar">
<p class="mb-5">SSH-Key Detials</p>
<p class="mb-5">SSH-Key Details</p>
</v-toolbar>

<v-card-text>
<template v-for="[_key, value] of Object.entries(selectedKey).sort()" :key="_key">
<template v-if="!notNeededFields.includes(_key)">
<CopyInputWrapper v-if="_key !== 'publicKey'" :data="value" #="{ props: copyInputProps }">
<v-text-field v-bind="{ ...copyInputProps }" :label="_key" :model-value="value" :readonly="true" />
<v-text-field
v-bind="{ ...copyInputProps }"
:label="_key"
v-model="currentKey[_key as keyof SSHKeyData]"
:readonly="_key === 'fingerPrint'"
:rules="[(value: string) => !!value || `${_key} is required.`, _key === 'name' ? validateName(currentKey.name): true]"
/>
</CopyInputWrapper>
<CopyInputWrapper v-else :data="value" #="{ props: copyInputProps }">
<v-textarea
:class="value.length ? 'ssh-key' : ''"
:model-value="value"
:readonly="true"
v-model="currentKey[_key]"
label="Public SSH Key"
no-resize
:spellcheck="false"
:rules="sshRules(currentKey[_key])"
v-bind="{ ...copyInputProps }"
/>
</CopyInputWrapper>
Expand All @@ -49,6 +54,7 @@
<v-spacer></v-spacer>
<div class="mt-2">
<v-btn color="white" variant="outlined" text="Close" @click="$emit('close')"></v-btn>
<v-btn color="primary" variant="outlined" text="Save" @click="updateKey" :loading="loading"></v-btn>
</div>
</v-card-actions>
</v-card>
Expand All @@ -57,13 +63,14 @@
</template>

<script lang="ts">
import { capitalize, defineComponent, type PropType } from "vue";
import { capitalize, defineComponent, type PropType, ref, watch } from "vue";
import type { SSHKeyData } from "@/types";
import SSHKeysManagement from "@/utils/ssh";
export default defineComponent({
name: "SSHDataDialog",
emits: ["close"],
emits: ["close", "update"],
props: {
open: {
type: Boolean,
Expand All @@ -73,12 +80,64 @@ export default defineComponent({
type: Object as PropType<SSHKeyData>,
required: true,
},
allKeys: {
type: Object as PropType<SSHKeyData[]>,
required: true,
},
},
setup() {
setup(props, ctx) {
const currentKey = ref<SSHKeyData>(props.selectedKey);
const loading = ref<boolean>(false);
watch(
() => props.open,
newValue => {
if (newValue) {
currentKey.value = { ...props.selectedKey };
loading.value = false;
}
},
);
const notNeededFields = ["id", "activating", "deleting", "isActive", "createdAt"];
const sshKeysManagement = new SSHKeysManagement();
const updateKey = () => {
loading.value = true;
ctx.emit("update", currentKey.value);
};
function sshRules(value: any) {
return [
(v: string) => !!v || " The SSH key is required.",
(v: string) =>
sshKeysManagement.isValidSSHKey(v) ||
"The SSH key you provided is not valid. Please double-check that it is copied correctly and follows the correct format.",
(v: string) => {
if (v === props.selectedKey.publicKey) {
return true;
}
const found = props.allKeys.find(key => key.publicKey === v);
return found ? "You have another key with the same public key." : true;
},
];
}
function validateName(name: string): string | boolean {
if (name === props.selectedKey.name) {
return true;
}
const found = props.allKeys.find(key => key.name === name);
return found ? "You have another key with the same name." : true;
}
return {
notNeededFields,
capitalize,
updateKey,
currentKey,
sshRules,
loading,
validateName,
};
},
});
Expand Down
4 changes: 1 addition & 3 deletions packages/playground/src/utils/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,7 @@ class SSHKeysManagement {
list(): SSHKeyData[] {
let keys: SSHKeyData[] = [];

if (!this.migrated()) {
keys = this.migrate();
} else {
if (this.migrated()) {
keys = this.oldKey as unknown as SSHKeyData[];
}

Expand Down
21 changes: 20 additions & 1 deletion packages/playground/src/views/sshkey_view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,13 @@
/>

<!-- View -->
<ssh-data-dialog :open="isViewKey" :selected-key="selectedKey" @close="isViewKey = false" />
<ssh-data-dialog
:open="isViewKey"
:all-keys="allKeys"
:selected-key="selectedKey"
@close="isViewKey = false"
@update="updateKeys"
/>
</template>

<script lang="ts" setup>
Expand Down Expand Up @@ -276,6 +282,19 @@ const addKey = async (key: SSHKeyData) => {
closeDialog();
};
const updateKeys = async (updatedKey: SSHKeyData) => {
const index = allKeys.value.findIndex(key => key.id === updatedKey.id);
allKeys.value[index] = { ...updatedKey };
try {
await sshKeysManagement.update(allKeys.value);
createCustomToast("SSH Key updated successfully.", ToastType.success);
} catch (error) {
createCustomToast("Failed to update the SSH Key.", ToastType.danger);
} finally {
isViewKey.value = false;
}
};
const generateSSHKeys = async (key: SSHKeyData) => {
generatingSSH.value = true;
const keys = await generateKeyPair({
Expand Down

0 comments on commit c7e57db

Please sign in to comment.