refactor: inherit header from multiple collecions
This commit is contained in:
@@ -40,8 +40,8 @@
|
||||
<HttpAuthorization
|
||||
v-model="editableCollection.auth"
|
||||
:is-collection-property="true"
|
||||
:is-root-collection="editingProperties.isRootCollection"
|
||||
:inherited-properties="editingProperties.inheritedProperties"
|
||||
:is-root-collection="editingProperties?.isRootCollection"
|
||||
:inherited-properties="editingProperties?.inheritedProperties"
|
||||
/>
|
||||
<AppBanner
|
||||
:banner="{
|
||||
@@ -93,7 +93,7 @@ type EditingProperties = {
|
||||
collection: HoppCollection<HoppRESTRequest> | TeamCollection | null
|
||||
isRootCollection: boolean
|
||||
path: string
|
||||
inheritedProperties: HoppInheritedProperty | null
|
||||
inheritedProperties: HoppInheritedProperty | undefined
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
|
||||
@@ -302,6 +302,7 @@ const editingProperties = ref<{
|
||||
collection: null,
|
||||
isRootCollection: false,
|
||||
path: "",
|
||||
inheritedProperties: undefined,
|
||||
})
|
||||
|
||||
const confirmModalTitle = ref<string | null>(null)
|
||||
@@ -678,7 +679,7 @@ const onAddRequest = (requestName: string) => {
|
||||
if (!path) return
|
||||
const insertionIndex = saveRESTRequestAs(path, newRequest)
|
||||
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
|
||||
|
||||
tabs.createNewTab({
|
||||
request: newRequest,
|
||||
@@ -691,8 +692,6 @@ const onAddRequest = (requestName: string) => {
|
||||
inheritedProperties: {
|
||||
auth,
|
||||
headers,
|
||||
parentName: name,
|
||||
parentId: path,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1330,8 +1329,7 @@ const selectRequest = (selectedRequest: {
|
||||
// If there is a request with this save context, switch into it
|
||||
let possibleTab = null
|
||||
|
||||
const { auth, headers, name } =
|
||||
cascaseParentCollectionForHeaderAuth(folderPath)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(folderPath)
|
||||
|
||||
if (collectionsType.value.type === "team-collections") {
|
||||
possibleTab = tabs.getTabRefWithSaveContext({
|
||||
@@ -1369,9 +1367,7 @@ const selectRequest = (selectedRequest: {
|
||||
requestIndex: parseInt(requestIndex),
|
||||
},
|
||||
inheritedProperties: {
|
||||
parentId: folderPath || "",
|
||||
parentName: name,
|
||||
auth: auth,
|
||||
auth,
|
||||
headers,
|
||||
},
|
||||
})
|
||||
@@ -1405,7 +1401,7 @@ const dropRequest = (payload: {
|
||||
let possibleTab = null
|
||||
|
||||
if (collectionsType.value.type === "my-collections" && folderPath) {
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
destinationCollectionIndex
|
||||
)
|
||||
|
||||
@@ -1427,8 +1423,6 @@ const dropRequest = (payload: {
|
||||
}
|
||||
|
||||
possibleTab.value.document.inheritedProperties = {
|
||||
parentId: destinationCollectionIndex,
|
||||
parentName: name,
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
@@ -1600,13 +1594,11 @@ const dropCollection = (payload: {
|
||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
|
||||
)
|
||||
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
|
||||
)
|
||||
|
||||
const inheritedProperty = {
|
||||
parentId: `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
|
||||
parentName: name,
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
@@ -1983,12 +1975,9 @@ const editProperties = (payload: {
|
||||
let inheritedProperties = {}
|
||||
|
||||
if (parentIndex) {
|
||||
const { auth, headers, name } =
|
||||
cascaseParentCollectionForHeaderAuth(parentIndex)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(parentIndex)
|
||||
|
||||
inheritedProperties = {
|
||||
parentId: parentIndex ?? "",
|
||||
parentName: name,
|
||||
auth,
|
||||
headers,
|
||||
} as HoppInheritedProperty
|
||||
@@ -2016,12 +2005,10 @@ const setCollectionProperties = (newCollection: {
|
||||
editRESTFolder(path, collection)
|
||||
}
|
||||
|
||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path)
|
||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
|
||||
|
||||
nextTick(() => {
|
||||
updateInheritedPropertiesForAffectedRequests(path, {
|
||||
parentId: path,
|
||||
parentName: name,
|
||||
auth,
|
||||
headers,
|
||||
})
|
||||
|
||||
@@ -155,8 +155,8 @@
|
||||
<div v-if="auth.authType === 'inherit'" class="p-4">
|
||||
<span v-if="inheritedProperties?.auth">
|
||||
Inherited
|
||||
{{ getAuthName(inheritedProperties.auth.authType) }} from Parent
|
||||
Collection {{ inheritedProperties?.parentName }}
|
||||
{{ getAuthName(inheritedProperties.auth.inheritedAuth.authType) }}
|
||||
from Parent Collection {{ inheritedProperties?.auth.parentName }}
|
||||
</span>
|
||||
<span v-else>
|
||||
Please save this request in any collection to inherit the
|
||||
@@ -232,7 +232,10 @@ const auth = useVModel(props, "modelValue", emit)
|
||||
onMounted(() => {
|
||||
if (props.isRootCollection && auth.value.authType === "inherit") {
|
||||
console.log("isRootCollection", auth.value.authType)
|
||||
auth.value.authType = "none"
|
||||
auth.value = {
|
||||
authType: "none",
|
||||
authActive: true,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -242,17 +242,14 @@
|
||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||
readonly
|
||||
/>
|
||||
<span class="">
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t(masking ? 'state.show' : 'state.hide')"
|
||||
:icon="
|
||||
masking && header.source === 'auth' ? IconEye : IconEyeOff
|
||||
"
|
||||
:disabled="header.source !== 'auth'"
|
||||
@click="toggleMask()"
|
||||
/>
|
||||
</span>
|
||||
<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 class="aspect-square w-[2.05rem]"></span>
|
||||
<span>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
@@ -578,13 +575,13 @@ const inheritedProperties = computed(() => {
|
||||
)
|
||||
|
||||
const headers = inheritedHeaders.map((header, index) => ({
|
||||
inheritedFrom: props.inheritedProperties?.parentName,
|
||||
inheritedFrom: props.inheritedProperties?.headers[index].parentName,
|
||||
source: "headers",
|
||||
id: `header-${index}`,
|
||||
header: {
|
||||
key: header.key,
|
||||
value: header.value,
|
||||
active: header.active,
|
||||
key: header.inheritedHeader?.key,
|
||||
value: header.inheritedHeader?.value,
|
||||
active: header.inheritedHeader?.active,
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -602,7 +599,7 @@ const inheritedProperties = computed(() => {
|
||||
const computedAuthHeader = getComputedAuthHeaders(
|
||||
aggregateEnvs.value,
|
||||
request.value,
|
||||
props.inheritedProperties.auth
|
||||
props.inheritedProperties.auth.inheritedAuth
|
||||
)[0]
|
||||
|
||||
if (
|
||||
@@ -612,7 +609,7 @@ const inheritedProperties = computed(() => {
|
||||
) {
|
||||
auth = [
|
||||
{
|
||||
inheritedFrom: props.inheritedProperties?.parentName,
|
||||
inheritedFrom: props.inheritedProperties?.auth.parentName,
|
||||
source: "auth",
|
||||
id: `header-auth`,
|
||||
header: computedAuthHeader,
|
||||
|
||||
@@ -98,17 +98,31 @@ export function runRESTRequest$(
|
||||
const requestAuth =
|
||||
tab.value.document.request.auth.authType === "inherit" &&
|
||||
tab.value.document.request.auth.authActive
|
||||
? tab.value.document.inheritedProperties?.auth
|
||||
? tab.value.document.inheritedProperties?.auth.inheritedAuth
|
||||
: tab.value.document.request.auth
|
||||
|
||||
const requestHeaders = [
|
||||
...(tab.value.document.inheritedProperties?.headers ?? []),
|
||||
...tab.value.document.request.headers,
|
||||
]
|
||||
let requestHeaders
|
||||
|
||||
const inheritedHeaders =
|
||||
tab.value.document.inheritedProperties?.headers.map((header) => {
|
||||
if (header.inheritedHeader) {
|
||||
return header.inheritedHeader
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
||||
if (inheritedHeaders) {
|
||||
requestHeaders = [
|
||||
...inheritedHeaders,
|
||||
...tab.value.document.request.headers,
|
||||
]
|
||||
} else {
|
||||
requestHeaders = [...tab.value.document.request.headers]
|
||||
}
|
||||
|
||||
const finalRequest = {
|
||||
...tab.value.document.request,
|
||||
auth: requestAuth,
|
||||
auth: requestAuth ?? { authType: "none", authActive: false },
|
||||
headers: requestHeaders,
|
||||
}
|
||||
|
||||
|
||||
@@ -121,16 +121,48 @@ export function updateInheritedPropertiesForAffectedRequests(
|
||||
)
|
||||
})
|
||||
|
||||
const filteredTabs = tabs.filter((tab) => {
|
||||
const tabsEffectedByAuth = tabs.filter((tab) => {
|
||||
return (
|
||||
tab.value.document.inheritedProperties &&
|
||||
tab.value.document.inheritedProperties.parentId === path
|
||||
tab.value.document.inheritedProperties.auth.parentID === path
|
||||
)
|
||||
})
|
||||
|
||||
for (const tab of filteredTabs) {
|
||||
const tabsEffectedByHeaders = tabs.filter((tab) => {
|
||||
return (
|
||||
tab.value.document.inheritedProperties &&
|
||||
tab.value.document.inheritedProperties.headers.some(
|
||||
(header) => header.parentID === path
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
for (const tab of tabsEffectedByAuth) {
|
||||
tab.value.document.inheritedProperties = inheritedProperties
|
||||
}
|
||||
|
||||
for (const tab of tabsEffectedByHeaders) {
|
||||
const headers = tab.value.document.inheritedProperties?.headers.map(
|
||||
(header) => {
|
||||
if (header.parentID === path) {
|
||||
return {
|
||||
...header,
|
||||
inheritedHeader: inheritedProperties.headers.find(
|
||||
(inheritedHeader) =>
|
||||
inheritedHeader.inheritedHeader?.key ===
|
||||
header.inheritedHeader?.key
|
||||
)?.inheritedHeader,
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
||||
)
|
||||
|
||||
tab.value.document.inheritedProperties = {
|
||||
...tab.value.document.inheritedProperties,
|
||||
headers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetSaveContextForAffectedRequests(folderPath: string) {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
|
||||
export type HoppInheritedProperty = {
|
||||
parentId: string
|
||||
parentName: string
|
||||
auth?: HoppRESTRequest["auth"]
|
||||
headers?: HoppRESTRequest["headers"]
|
||||
auth: {
|
||||
parentID: string
|
||||
parentName: string
|
||||
inheritedAuth: HoppRESTRequest["auth"]
|
||||
}
|
||||
headers: {
|
||||
parentID: string
|
||||
parentName: string
|
||||
inheritedHeader?: HoppRESTRequest["headers"][number]
|
||||
}[]
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ export const getComputedAuthHeaders = (
|
||||
auth?: HoppRESTRequest["auth"]
|
||||
) => {
|
||||
const request = auth ? { auth: auth ?? { authActive: false } } : req
|
||||
|
||||
// If Authorization header is also being user-defined, that takes priority
|
||||
if (req && req.headers.find((h) => h.key.toLowerCase() === "authorization"))
|
||||
return []
|
||||
@@ -136,16 +135,18 @@ export type ComputedHeader = {
|
||||
export const getComputedHeaders = (
|
||||
req: HoppRESTRequest,
|
||||
envVars: Environment["variables"]
|
||||
): ComputedHeader[] => [
|
||||
...getComputedAuthHeaders(envVars, req).map((header) => ({
|
||||
source: "auth" as const,
|
||||
header,
|
||||
})),
|
||||
...getComputedBodyHeaders(req).map((header) => ({
|
||||
source: "body" as const,
|
||||
header,
|
||||
})),
|
||||
]
|
||||
): ComputedHeader[] => {
|
||||
return [
|
||||
...getComputedAuthHeaders(envVars, req).map((header) => ({
|
||||
source: "auth" as const,
|
||||
header,
|
||||
})),
|
||||
...getComputedBodyHeaders(req).map((header) => ({
|
||||
source: "body" as const,
|
||||
header,
|
||||
})),
|
||||
]
|
||||
}
|
||||
|
||||
export type ComputedParam = {
|
||||
source: "auth"
|
||||
|
||||
@@ -10,6 +10,7 @@ import { cloneDeep } from "lodash-es"
|
||||
import { resolveSaveContextOnRequestReorder } from "~/helpers/collection/request"
|
||||
import { getService } from "~/modules/dioc"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
|
||||
const defaultRESTCollectionState = {
|
||||
state: [
|
||||
@@ -65,19 +66,22 @@ export function navigateToFolderWithIndexPath(
|
||||
export function cascaseParentCollectionForHeaderAuth(
|
||||
folderPath: string | undefined
|
||||
) {
|
||||
let auth: HoppRESTRequest["auth"] = {
|
||||
authType: "none",
|
||||
authActive: false,
|
||||
let auth: HoppInheritedProperty["auth"] = {
|
||||
parentID: folderPath ?? "",
|
||||
parentName: "",
|
||||
inheritedAuth: {
|
||||
authType: "inherit",
|
||||
authActive: false,
|
||||
},
|
||||
}
|
||||
const headers: HoppRESTRequest["headers"] = []
|
||||
let name = ""
|
||||
if (!folderPath) return { auth, headers, name: "" }
|
||||
const headers: HoppInheritedProperty["headers"] = []
|
||||
if (!folderPath) return { auth, headers }
|
||||
const path = folderPath.split("/").map((i) => parseInt(i))
|
||||
|
||||
// Check if the path is empty or invalid
|
||||
if (!path || path.length === 0) {
|
||||
console.error("Invalid path:", folderPath)
|
||||
return { auth, headers, name: "" }
|
||||
return { auth, headers }
|
||||
}
|
||||
|
||||
// Loop through the path and get the last parent folder with authType other than 'inherit'
|
||||
@@ -90,33 +94,49 @@ export function cascaseParentCollectionForHeaderAuth(
|
||||
// Check if parentFolder is undefined or null
|
||||
if (!parentFolder) {
|
||||
console.error("Parent folder not found for path:", path)
|
||||
return { auth, headers, name: "" }
|
||||
return { auth, headers }
|
||||
}
|
||||
|
||||
const parentFolderAuth = parentFolder.auth
|
||||
const parentFolderHeaders = parentFolder.headers
|
||||
|
||||
const isRootCollection = path.length === 1
|
||||
|
||||
// Check if authType is not 'inherit'
|
||||
if (parentFolderAuth?.authType !== "inherit") {
|
||||
auth = parentFolderAuth || auth
|
||||
name = parentFolder.name
|
||||
if (parentFolderAuth?.authType !== "inherit" || isRootCollection) {
|
||||
auth = {
|
||||
parentID: parentFolder.id ?? folderPath,
|
||||
parentName: parentFolder.name,
|
||||
inheritedAuth: parentFolderAuth,
|
||||
}
|
||||
}
|
||||
// Update headers, overwriting duplicates by key
|
||||
if (parentFolderHeaders) {
|
||||
const activeHeaders = parentFolderHeaders.filter((h) => h.active)
|
||||
activeHeaders.forEach((header) => {
|
||||
const index = headers.findIndex((h) => h.key === header.key)
|
||||
const index = headers.findIndex(
|
||||
(h) => h.inheritedHeader?.key === header.key
|
||||
)
|
||||
const currentPath = [...path.slice(0, i + 1)].join("/")
|
||||
if (index !== -1) {
|
||||
// Replace the existing header with the same key
|
||||
headers[index] = header
|
||||
headers[index] = {
|
||||
parentID: currentPath,
|
||||
parentName: parentFolder.name,
|
||||
inheritedHeader: header,
|
||||
}
|
||||
} else {
|
||||
headers.push(header)
|
||||
headers.push({
|
||||
parentID: currentPath,
|
||||
parentName: parentFolder.name,
|
||||
inheritedHeader: header,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return { auth, headers, name }
|
||||
return { auth, headers }
|
||||
}
|
||||
|
||||
function reorderItems(array: unknown[], from: number, to: number) {
|
||||
@@ -201,11 +221,7 @@ const restCollectionDispatchers = defineDispatchers({
|
||||
requests: [],
|
||||
auth: {
|
||||
authType: "inherit",
|
||||
authActive: false,
|
||||
auth: {
|
||||
authType: "inherit",
|
||||
authActive: false,
|
||||
},
|
||||
authActive: true,
|
||||
},
|
||||
headers: [],
|
||||
})
|
||||
@@ -768,7 +784,7 @@ const gqlCollectionDispatchers = defineDispatchers({
|
||||
requests: [],
|
||||
auth: {
|
||||
authType: "inherit",
|
||||
authActive: false,
|
||||
authActive: true,
|
||||
},
|
||||
headers: [],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user