Skip to content

Commit

Permalink
Add functionality to delete credential groups in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
davelopez committed Jan 15, 2025
1 parent c3d4854 commit 1bdacdb
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 3 deletions.
14 changes: 14 additions & 0 deletions client/src/components/Tool/ToolCredentials.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,19 @@ async function onSavedCredentials(providedCredentials: CreateSourceCredentialsPa
}
}
async function onDeleteCredentialsGroup(reference: string, groupName: string) {
busyMessage.value = "Updating your credentials...";
isBusy.value = true;
try {
userCredentialsStore.deleteCredentialsGroupForTool(props.toolId, reference, groupName);
} catch (error) {
// TODO: Implement error handling.
console.error("Error deleting user credentials group", error);
} finally {
isBusy.value = false;
}
}
checkUserCredentials();
</script>

Expand Down Expand Up @@ -197,6 +210,7 @@ checkUserCredentials();
:tool-version="props.toolVersion"
:tool-credentials-definition="credentialsDefinition"
:user-tool-credentials="userCredentials"
@delete-credentials-group="onDeleteCredentialsGroup"
@save-credentials="onSavedCredentials" />
</BModal>
</div>
Expand Down
10 changes: 10 additions & 0 deletions client/src/components/User/Credentials/ManageToolCredentials.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const providedCredentials = ref<CreateSourceCredentialsPayload>(initializeCreden
const emit = defineEmits<{
(e: "save-credentials", credentials: CreateSourceCredentialsPayload): void;
(e: "delete-credentials-group", reference: string, groupName: string): void;
}>();
function saveCredentials() {
Expand Down Expand Up @@ -103,6 +104,14 @@ function onNewCredentialsSet(credential: ServiceCredentialPayload, newSet: Servi
}
}
function onDeleteCredentialsGroup(reference: string, groupName: string) {
const credentialFound = providedCredentials.value.credentials.find((c) => c.reference === reference);
if (credentialFound) {
credentialFound.groups = credentialFound.groups.filter((g) => g.name !== groupName);
emit("delete-credentials-group", reference, groupName);
}
}
function onCurrentSetChange(credential: ServiceCredentialPayload, newSet: ServiceGroupPayload) {
const credentialFound = providedCredentials.value.credentials.find((c) => c.reference === credential.reference);
if (credentialFound) {
Expand Down Expand Up @@ -133,6 +142,7 @@ function getServiceCredentialsDefinition(reference: string): ServiceCredentialsD
:credential-payload="credential"
class="mb-2"
@new-credentials-set="onNewCredentialsSet"
@delete-credentials-group="onDeleteCredentialsGroup"
@update-current-set="onCurrentSetChange" />
<button class="btn-primary" @click="saveCredentials">Save Credentials</button>
</div>
Expand Down
43 changes: 40 additions & 3 deletions client/src/components/User/Credentials/ServiceCredentials.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { faTrash } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { BBadge, BCard } from "bootstrap-vue";
import { computed, ref } from "vue";
import Multiselect from "vue-multiselect";
Expand All @@ -24,19 +26,27 @@ const props = defineProps<Props>();
const selectedSet = ref<ServiceGroupPayload | undefined>(
props.credentialPayload.groups.find((group) => group.name === props.credentialPayload.current_group)
);
const availableSets = computed<ServiceGroupPayload[]>(() => Object.values(props.credentialPayload.groups));
const isAddingNewSet = ref(false);
const newSetName = ref<string>("");
const availableSets = computed<ServiceGroupPayload[]>(() => Object.values(props.credentialPayload.groups));
const canCreateNewSet = computed<boolean>(
() => newSetName.value.trim() !== "" && !availableSets.value.some((set) => set.name === newSetName.value)
);
const canShowSetSelector = computed<boolean>(
() => props.credentialDefinition.multiple && availableSets.value.length > 1
);
const isAddingNewSet = ref(false);
const canDeleteSet = computed<boolean>(() => selectedSet.value?.name !== "default");
const emit = defineEmits<{
(e: "new-credentials-set", credential: ServiceCredentialPayload, newSet: ServiceGroupPayload): void;
(e: "update-current-set", credential: ServiceCredentialPayload, newSet: ServiceGroupPayload): void;
(e: "delete-credentials-group", reference: string, groupName: string): void;
}>();
function onAddingNewSet() {
Expand Down Expand Up @@ -92,6 +102,19 @@ function getVariableTitle(name: string, type: CredentialType): string {
function getVariableDescription(name: string, type: CredentialType): string | undefined {
return getVariableDefinition(name, type).description;
}
function onDeleteGroup() {
if (selectedSet.value) {
//TODO: Implement confirmation dialog.
const groupNameToDelete = selectedSet.value.name;
const defaultSet = availableSets.value.find((set) => set.name === "default");
if (defaultSet) {
selectedSet.value = defaultSet;
onCurrentSetChange(defaultSet);
}
emit("delete-credentials-group", props.credentialPayload.reference, groupNameToDelete);
}
}
</script>

<template>
Expand Down Expand Up @@ -123,7 +146,7 @@ function getVariableDescription(name: string, type: CredentialType): string | un
</h3>
<p>{{ credentialDefinition.description }}</p>
<div v-if="selectedSet">
<div v-if="canShowSetSelector">
<div v-if="canShowSetSelector" class="set-selection-bar">
<b>Using set:</b>
<Multiselect
v-model="selectedSet"
Expand All @@ -134,6 +157,14 @@ function getVariableDescription(name: string, type: CredentialType): string | un
track-by="name"
label="name"
@select="onCurrentSetChange" />
<button
v-if="canDeleteSet"
size="sm"
class="mx-2"
title="Delete this set of credentials."
@click="onDeleteGroup">
<FontAwesomeIcon :icon="faTrash" />
</button>
</div>

<div v-for="variable in selectedSet.variables" :key="variable.name">
Expand Down Expand Up @@ -198,4 +229,10 @@ function getVariableDescription(name: string, type: CredentialType): string | un
gap: 1em;
align-items: center;
}
.set-selection-bar {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 1em;
}
</style>
38 changes: 38 additions & 0 deletions client/src/stores/userCredentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,43 @@ export const useUserCredentialsStore = defineScopedStore("userCredentialsStore",
return data;
}

async function deleteCredentialsGroupForTool(toolId: string, reference: string, groupName: string): Promise<void> {
const userId = ensureUserIsRegistered();
const key = getKey(toolId);
const credentials = userCredentialsForTools.value[key];

if (credentials) {
const serviceCredentials = credentials.find((credential) => credential.reference === reference);
if (!serviceCredentials) {
throw new Error(`No credentials found for reference ${reference}`);
}
const group = serviceCredentials.groups[groupName];
if (!group) {
throw new Error(`No group found for name ${groupName}`);
}
const { error } = await GalaxyApi().DELETE(
"/api/users/{user_id}/credentials/{user_credentials_id}/{group_id}",
{
params: {
path: { user_id: userId, user_credentials_id: serviceCredentials.id, group_id: group.id },
},
}
);

if (error) {
throw Error(`Failed to delete user credentials group for tool ${toolId}: ${error.err_msg}`);
}
// Remove the group from the credentials
const updatedCredentials = credentials.map((credential) => {
if (credential.id === reference) {
delete credential.groups[groupName];
}
return credential;
});
set(userCredentialsForTools.value, key, updatedCredentials);
}
}

function ensureUserIsRegistered(): string {
if (currentUserId === "anonymous") {
throw new Error("Only registered users can have tool credentials");
Expand All @@ -89,5 +126,6 @@ export const useUserCredentialsStore = defineScopedStore("userCredentialsStore",
getAllUserCredentialsForTool,
fetchAllUserCredentialsForTool,
saveUserCredentialsForTool,
deleteCredentialsGroupForTool,
};
});

0 comments on commit 1bdacdb

Please sign in to comment.