mirror of https://github.com/halo-dev/halo
fix: prevent undefined key name when creating Secret (#6964)
#### What type of PR is this? /area ui /kind bug /milestone 2.20.x #### What this PR does / why we need it: 修复使用 Secret 输入框创建 Secret 时,stringData 的 key 可能为 undefined 的问题。 #### Which issue(s) this PR fixes: See https://github.com/halo-sigs/plugin-alist/issues/23#issuecomment-2443499980 for more #### Special notes for your reviewer: #### Does this PR introduce a user-facing change? ```release-note 修复使用 Secret 输入框创建 Secret 时,stringData 的 key 可能为 undefined 的问题。 ```pull/6972/head
parent
25086ee3e6
commit
fdc90aff5c
|
@ -12,6 +12,7 @@ import { useQueryClient } from "@tanstack/vue-query";
|
||||||
import { onClickOutside } from "@vueuse/core";
|
import { onClickOutside } from "@vueuse/core";
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import { computed, ref, watch, type PropType } from "vue";
|
import { computed, ref, watch, type PropType } from "vue";
|
||||||
|
import SecretCreationModal from "./components/SecretCreationModal.vue";
|
||||||
import SecretEditModal from "./components/SecretEditModal.vue";
|
import SecretEditModal from "./components/SecretEditModal.vue";
|
||||||
import SecretListModal from "./components/SecretListModal.vue";
|
import SecretListModal from "./components/SecretListModal.vue";
|
||||||
import { Q_KEY, useSecretsFetch } from "./composables/use-secrets-fetch";
|
import { Q_KEY, useSecretsFetch } from "./composables/use-secrets-fetch";
|
||||||
|
@ -25,6 +26,8 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const requiredKey = computed(() => props.context.requiredKey);
|
||||||
|
|
||||||
const selectedSecret = ref<Secret>();
|
const selectedSecret = ref<Secret>();
|
||||||
const dropdownVisible = ref(false);
|
const dropdownVisible = ref(false);
|
||||||
const text = ref("");
|
const text = ref("");
|
||||||
|
@ -137,10 +140,11 @@ const scrollToSelected = () => {
|
||||||
|
|
||||||
// Check required key and edit secret
|
// Check required key and edit secret
|
||||||
function hasRequiredKey(secret: Secret) {
|
function hasRequiredKey(secret: Secret) {
|
||||||
return !!secret.stringData?.[props.context.requiredKey as string];
|
return !!secret.stringData?.[requiredKey.value as string];
|
||||||
}
|
}
|
||||||
const secretToUpdate = ref<Secret>();
|
const secretToUpdate = ref<Secret>();
|
||||||
const secretEditModalVisible = ref(false);
|
const secretEditModalVisible = ref(false);
|
||||||
|
const secretCreationModalVisible = ref(false);
|
||||||
|
|
||||||
const handleSelect = (secret?: Secret) => {
|
const handleSelect = (secret?: Secret) => {
|
||||||
if (!secret || secret.metadata.name === props.context._value) {
|
if (!secret || secret.metadata.name === props.context._value) {
|
||||||
|
@ -159,7 +163,7 @@ const handleSelect = (secret?: Secret) => {
|
||||||
if (!hasRequiredKey(secret)) {
|
if (!hasRequiredKey(secret)) {
|
||||||
const stringDataToUpdate = {
|
const stringDataToUpdate = {
|
||||||
...secret.stringData,
|
...secret.stringData,
|
||||||
[props.context.requiredKey as string]: "",
|
[requiredKey.value ? (requiredKey.value as string) : ""]: "",
|
||||||
};
|
};
|
||||||
secretToUpdate.value = {
|
secretToUpdate.value = {
|
||||||
...secret,
|
...secret,
|
||||||
|
@ -177,6 +181,11 @@ const secretListModalVisible = ref(false);
|
||||||
|
|
||||||
// Create new secret
|
// Create new secret
|
||||||
async function handleCreateSecret() {
|
async function handleCreateSecret() {
|
||||||
|
if (!requiredKey.value) {
|
||||||
|
secretCreationModalVisible.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { data: newSecret } = await coreApiClient.secret.createSecret({
|
const { data: newSecret } = await coreApiClient.secret.createSecret({
|
||||||
secret: {
|
secret: {
|
||||||
metadata: {
|
metadata: {
|
||||||
|
@ -187,7 +196,7 @@ async function handleCreateSecret() {
|
||||||
apiVersion: "v1alpha1",
|
apiVersion: "v1alpha1",
|
||||||
type: "Opaque",
|
type: "Opaque",
|
||||||
stringData: {
|
stringData: {
|
||||||
[props.context.requiredKey as string]: text.value,
|
[requiredKey.value as string]: text.value,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -212,6 +221,13 @@ async function handleCreateSecret() {
|
||||||
:secret="secretToUpdate"
|
:secret="secretToUpdate"
|
||||||
@close="secretEditModalVisible = false"
|
@close="secretEditModalVisible = false"
|
||||||
/>
|
/>
|
||||||
|
<SecretCreationModal
|
||||||
|
v-if="secretCreationModalVisible"
|
||||||
|
:form-state="{
|
||||||
|
stringDataArray: [{ key: requiredKey ? requiredKey as string : '', value: text || '' }],
|
||||||
|
}"
|
||||||
|
@close="secretCreationModalVisible = false"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
ref="wrapperRef"
|
ref="wrapperRef"
|
||||||
class="flex h-full w-full items-center border border-gray-300 transition-all"
|
class="flex h-full w-full items-center border border-gray-300 transition-all"
|
||||||
|
|
|
@ -12,6 +12,13 @@ import SecretForm from "./SecretForm.vue";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
formState?: SecretFormState;
|
||||||
|
}>(),
|
||||||
|
{ formState: undefined }
|
||||||
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: "close"): void;
|
(event: "close"): void;
|
||||||
}>();
|
}>();
|
||||||
|
@ -61,7 +68,7 @@ function onSubmit(data: SecretFormState) {
|
||||||
:width="600"
|
:width="600"
|
||||||
@close="emit('close')"
|
@close="emit('close')"
|
||||||
>
|
>
|
||||||
<SecretForm @submit="onSubmit" />
|
<SecretForm :form-state="formState" @submit="onSubmit" />
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<VSpace>
|
<VSpace>
|
||||||
|
|
Loading…
Reference in New Issue