Browse Source

refactor: inherit header from multiple collecions

nivedin 1 year ago
parent
commit
0a54455fe7

+ 3 - 3
packages/hoppscotch-common/src/components/collections/Properties.vue

@@ -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(

+ 8 - 21
packages/hoppscotch-common/src/components/collections/index.vue

@@ -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,
     })

+ 6 - 3
packages/hoppscotch-common/src/components/http/Authorization.vue

@@ -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,
+    }
   }
 })
 

+ 14 - 17
packages/hoppscotch-common/src/components/http/Headers.vue

@@ -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,

+ 20 - 6
packages/hoppscotch-common/src/helpers/RequestRunner.ts

@@ -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,
     }
 

+ 35 - 3
packages/hoppscotch-common/src/helpers/collection/collection.ts

@@ -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) {

+ 10 - 4
packages/hoppscotch-common/src/helpers/types/HoppInheritedProperties.ts

@@ -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]
+  }[]
 }

+ 12 - 11
packages/hoppscotch-common/src/helpers/utils/EffectiveURL.ts

@@ -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"

+ 37 - 21
packages/hoppscotch-common/src/newstore/collections.ts

@@ -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: [],
     })