feat: collection level headers and authorization (#3505)
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div class="flex flex-1 flex-col">
|
||||
<div
|
||||
class="sticky top-upperMobileSecondaryStickyFold z-10 flex flex-shrink-0 items-center justify-between overflow-x-auto border-b border-dividerLight bg-primary pl-4 sm:top-upperSecondaryStickyFold"
|
||||
class="sticky z-10 flex flex-shrink-0 items-center justify-between overflow-x-auto border-b border-dividerLight bg-primary pl-4"
|
||||
:class="{
|
||||
'top-upperMobileSecondaryStickyFold sm:top-upperSecondaryStickyFold':
|
||||
!isCollectionProperty,
|
||||
'top-propertiesPrimaryStickyFold': isCollectionProperty,
|
||||
}"
|
||||
>
|
||||
<label class="truncate font-semibold text-secondaryLight">
|
||||
{{ t("request.header_list") }}
|
||||
@@ -203,6 +208,61 @@
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
|
||||
<draggable
|
||||
v-model="inheritedProperties"
|
||||
item-key="id"
|
||||
animation="250"
|
||||
handle=".draggable-handle"
|
||||
draggable=".draggable-content"
|
||||
ghost-class="cursor-move"
|
||||
chosen-class="bg-primaryLight"
|
||||
drag-class="cursor-grabbing"
|
||||
>
|
||||
<template #item="{ element: header, index }">
|
||||
<div
|
||||
class="draggable-content group flex divide-x divide-dividerLight border-b border-dividerLight"
|
||||
>
|
||||
<span>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconLock"
|
||||
class="cursor-auto bg-divider text-secondaryLight opacity-25"
|
||||
tabindex="-1"
|
||||
/>
|
||||
</span>
|
||||
<SmartEnvInput
|
||||
v-model="header.header.key"
|
||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||
readonly
|
||||
/>
|
||||
<SmartEnvInput
|
||||
:model-value="
|
||||
header.source === 'auth' ? mask(header) : header.header.value
|
||||
"
|
||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||
readonly
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="header.source === 'auth'"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t(masking ? 'state.show' : 'state.hide')"
|
||||
:icon="masking && header.source === 'auth' ? IconEye : IconEyeOff"
|
||||
@click="toggleMask()"
|
||||
/>
|
||||
<span v-else class="aspect-square w-[2.05rem]"></span>
|
||||
<span>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:icon="IconInfo"
|
||||
:title="`This header is inherited from Parent Collection ${
|
||||
header.inheritedFrom ?? ''
|
||||
}`"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
|
||||
<HoppSmartPlaceholder
|
||||
v-if="workingHeaders.length === 0"
|
||||
:src="`/images/states/${colorMode.value}/add_category.svg`"
|
||||
@@ -236,6 +296,7 @@ import IconEye from "~icons/lucide/eye"
|
||||
import IconEyeOff from "~icons/lucide/eye-off"
|
||||
import IconArrowUpRight from "~icons/lucide/arrow-up-right"
|
||||
import IconWrapText from "~icons/lucide/wrap-text"
|
||||
import IconInfo from "~icons/lucide/info"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { computed, reactive, ref, watch } from "vue"
|
||||
import { isEqual, cloneDeep } from "lodash-es"
|
||||
@@ -264,12 +325,14 @@ import { objRemoveKey } from "~/helpers/functional/object"
|
||||
import {
|
||||
ComputedHeader,
|
||||
getComputedHeaders,
|
||||
getComputedAuthHeaders,
|
||||
} from "~/helpers/utils/EffectiveURL"
|
||||
import { aggregateEnvs$, getAggregateEnvs } from "~/newstore/environments"
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { useService } from "dioc/vue"
|
||||
import { InspectionService, InspectorResult } from "~/services/inspection"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
@@ -288,7 +351,11 @@ const linewrapEnabled = ref(true)
|
||||
const deletionToast = ref<{ goAway: (delay: number) => void } | null>(null)
|
||||
|
||||
// v-model integration with props and emit
|
||||
const props = defineProps<{ modelValue: HoppRESTRequest }>()
|
||||
const props = defineProps<{
|
||||
modelValue: HoppRESTRequest
|
||||
isCollectionProperty?: boolean
|
||||
inheritedProperties?: HoppInheritedProperty
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "change-tab", value: RESTOptionTabs): void
|
||||
@@ -494,6 +561,72 @@ const computedHeaders = computed(() =>
|
||||
)
|
||||
)
|
||||
|
||||
const inheritedProperties = computed(() => {
|
||||
if (!props.inheritedProperties?.auth || !props.inheritedProperties.headers)
|
||||
return []
|
||||
|
||||
//filter out headers that are already in the request headers
|
||||
|
||||
const inheritedHeaders = props.inheritedProperties.headers.filter(
|
||||
(header) =>
|
||||
!request.value.headers.some(
|
||||
(requestHeader) => requestHeader.key === header.inheritedHeader?.key
|
||||
)
|
||||
)
|
||||
|
||||
const headers = inheritedHeaders
|
||||
.filter(
|
||||
(header) =>
|
||||
header.inheritedHeader !== null &&
|
||||
header.inheritedHeader !== undefined &&
|
||||
header.inheritedHeader.active
|
||||
)
|
||||
.map((header, index) => ({
|
||||
inheritedFrom: props.inheritedProperties?.headers[index].parentName,
|
||||
source: "headers",
|
||||
id: `header-${index}`,
|
||||
header: {
|
||||
key: header.inheritedHeader?.key,
|
||||
value: header.inheritedHeader?.value,
|
||||
active: header.inheritedHeader?.active,
|
||||
},
|
||||
}))
|
||||
|
||||
let auth = [] as {
|
||||
inheritedFrom: string
|
||||
source: "auth"
|
||||
id: string
|
||||
header: {
|
||||
key: string
|
||||
value: string
|
||||
active: boolean
|
||||
}
|
||||
}[]
|
||||
|
||||
const computedAuthHeader = getComputedAuthHeaders(
|
||||
aggregateEnvs.value,
|
||||
request.value,
|
||||
props.inheritedProperties.auth.inheritedAuth
|
||||
)[0]
|
||||
|
||||
if (
|
||||
computedAuthHeader &&
|
||||
request.value.auth.authType === "inherit" &&
|
||||
request.value.auth.authActive
|
||||
) {
|
||||
auth = [
|
||||
{
|
||||
inheritedFrom: props.inheritedProperties?.auth.parentName,
|
||||
source: "auth",
|
||||
id: `header-auth`,
|
||||
header: computedAuthHeader,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
return [...headers, ...auth]
|
||||
})
|
||||
|
||||
const masking = ref(true)
|
||||
|
||||
const toggleMask = () => {
|
||||
|
||||
Reference in New Issue
Block a user