195 lines
6.0 KiB
Vue
195 lines
6.0 KiB
Vue
<template>
|
|
<div class="flex flex-col h-full min-h-0">
|
|
<div class="tree-header mb-2 grid grid-cols-2 place-content-between">
|
|
<h1 class="text-lg font-semibold text-gray-900 dark:text-white">Secrets</h1>
|
|
<div class="flex">
|
|
<div class="flex w-full justify-end">
|
|
<sl-dropdown>
|
|
<sl-icon-button slot="trigger" name="plus-square" label="Add Secret"></sl-icon-button>
|
|
<sl-menu>
|
|
<sl-menu-item @click="createSecretDrawer = true">Create secret</sl-menu-item>
|
|
<sl-menu-item @click="createGroupDrawer = true">
|
|
<span v-if="currentPath">Create subgroup</span>
|
|
<span v-else>Create group</span>
|
|
</sl-menu-item>
|
|
</sl-menu>
|
|
</sl-dropdown>
|
|
</div>
|
|
</div>
|
|
<div class="col-span-full">
|
|
<!-- The search would have gone here... -->
|
|
|
|
</div>
|
|
<div id="secret-tree-items" class="flex flex-col h-full min-h-0 col-span-full">
|
|
<div class="flex-1 overflow-y-auto">
|
|
<sl-tree class="w-full" @sl-selection-change="itemSelected" v-if="treeState.secretGroups">
|
|
<template v-if="ungrouped">
|
|
<SecretGroupTreeItem path="ungrouped" name="Ungrouped" groupPath="ungrouped">
|
|
<template v-for="entry in ungrouped">
|
|
<SecretGroupTreeEntry :name="entry.name" groupPath="ungrouped" />
|
|
</template>
|
|
</SecretGroupTreeItem>
|
|
</template>
|
|
<template v-if="secretGroups">
|
|
<SecretGroup v-for="group in secretGroups" :group="group" />
|
|
</template>
|
|
</sl-tree>
|
|
</div>
|
|
<!-- pagination would go here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Drawer label="Create Group" :open="createGroupDrawer" @hide="createGroupDrawer = false">
|
|
<AddGroup
|
|
:parent="currentPath"
|
|
@submit="createGroup"
|
|
@cancel="cancelCreateGroup"
|
|
:key="drawerKey"
|
|
/>
|
|
</Drawer>
|
|
<Drawer label="Create Secret" :open="createSecretDrawer" @hide="createSecretDrawer = false">
|
|
<SecretForm
|
|
:key="createDrawerKey"
|
|
:group="createSecretParent"
|
|
@submit="createSecret"
|
|
@cancel="createSecretDrawer = false"
|
|
/>
|
|
</Drawer>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import type { SshecretObject } from '@/api/types'
|
|
import type { SecretCreate } from '@/client'
|
|
import { computed, ref, reactive, onMounted, watch } from 'vue'
|
|
import { useTreeState } from '@/store/useTreeState'
|
|
import { useAlertsStore } from '@/store/useAlertsStore'
|
|
import { SshecretAdmin } from '@/client'
|
|
import { SshecretObjectType } from '@/api/types'
|
|
import SecretGroup from '@/components/secrets/SecretGroup.vue'
|
|
import SecretGroupTreeItem from '@/components/secrets/SecretGroupTreeItem.vue'
|
|
import SecretGroupTreeEntry from '@/components/secrets/SecretGroupTreeEntry.vue'
|
|
import AddGroup from '@/components/secrets/AddGroup.vue'
|
|
import SecretForm from '@/components/secrets/SecretForm.vue'
|
|
import Drawer from '@/components/common/Drawer.vue'
|
|
|
|
const treeState = useTreeState()
|
|
const alerts = useAlertsStore()
|
|
|
|
const ungrouped = computed(() => treeState.secretGroups.ungrouped)
|
|
const secretGroups = computed(() => treeState.secretGroups.groups)
|
|
|
|
const groupSelected = computed(() => {
|
|
if (!treeState.selected) {
|
|
return false
|
|
}
|
|
if (treesState.selected.objectType === SshecretObject.SecretGroup) {
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
|
|
const drawerKey = ref(0)
|
|
const createDrawerKey = ref(0)
|
|
const createGroupDrawer = ref<boolean>(false)
|
|
const createSecretDrawer = ref<boolean>(false)
|
|
|
|
function cancelCreateGroup() {
|
|
createGroupDrawer.value = false
|
|
drawerKey.value += 1
|
|
}
|
|
|
|
const currentPath = computed(() => {
|
|
if (treeState.selected && treeState.selected.objectType === SshecretObjectType.SecretGroup) {
|
|
return treeState.selected.id
|
|
}
|
|
return ''
|
|
})
|
|
|
|
const createSecretParent = computed(() => {
|
|
if (treeState.selected && treeState.selected.objectType === SshecretObjectType.SecretGroup) {
|
|
return treeState.selected.id
|
|
}
|
|
return null
|
|
})
|
|
|
|
async function loadGroups() {
|
|
await treeState.getSecretGroups()
|
|
}
|
|
|
|
const drawerKeyName = computed(() => `${currentPath.value}_${drawerKey.value}`)
|
|
|
|
async function itemSelected(event: Event) {
|
|
if (event.detail.selection.length == 0) {
|
|
treeState.unselect()
|
|
} else {
|
|
const el = event.detail.selection[0] as HTMLElement
|
|
const childType = el.dataset.type
|
|
if (childType === 'secret') {
|
|
const secretName = el.dataset.name
|
|
treeState.selectSecret(secretName, null)
|
|
} else if (childType === 'group') {
|
|
const groupPath = el.dataset.groupPath
|
|
if (groupPath === 'ungrouped') {
|
|
treeState.unselect()
|
|
} else {
|
|
treeState.selectGroup(groupPath)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function createGroup(path: string) {
|
|
// Create a group
|
|
console.log('Submit called')
|
|
const response = await SshecretAdmin.addSecretGroupApiV1SecretsGroupsPost({
|
|
body: {
|
|
name: path,
|
|
},
|
|
})
|
|
if (response.status === 200) {
|
|
console.log('Success. Group created.')
|
|
alerts.showAlert('Group created', 'success')
|
|
createGroupDrawer.value = false
|
|
drawerKey.value += 1
|
|
|
|
await loadGroups()
|
|
} else {
|
|
console.error(response)
|
|
alerts.showAlert('Group creation failed', 'error')
|
|
}
|
|
}
|
|
|
|
async function createSecret(secretCreate: SecretCreate) {
|
|
console.log('Creating secret')
|
|
const response = await SshecretAdmin.addSecretApiV1SecretsPost({
|
|
body: secretCreate,
|
|
})
|
|
if (response.status == 200) {
|
|
alerts.showAlert('Secret created', 'success')
|
|
// We can close the drawer now.
|
|
createSecretDrawer.value = false
|
|
createDrawerKey.value += 1
|
|
|
|
await loadGroups()
|
|
// Also update all the clients affected
|
|
for (const clientId in secretCreate.clients) {
|
|
console.log('Refreshing client: ', clientId)
|
|
await treeState.refreshClient(clientId)
|
|
}
|
|
|
|
treeState.selectSecret(secretCreate.name)
|
|
} else {
|
|
console.log(response)
|
|
alerts.showAlert('Secret creation failed', 'error')
|
|
}
|
|
}
|
|
|
|
watch(
|
|
() => treeState.secretGroupRevision,
|
|
() => {
|
|
treeState.getSecretGroups()
|
|
},
|
|
)
|
|
|
|
onMounted(loadGroups)
|
|
</script>
|