refactor: inherit header from multiple collecions

This commit is contained in:
nivedin
2023-11-30 19:43:46 +05:30
committed by Andrew Bastin
parent b893607ad1
commit 0a54455fe7
9 changed files with 145 additions and 89 deletions

View File

@@ -40,8 +40,8 @@
<HttpAuthorization <HttpAuthorization
v-model="editableCollection.auth" v-model="editableCollection.auth"
:is-collection-property="true" :is-collection-property="true"
:is-root-collection="editingProperties.isRootCollection" :is-root-collection="editingProperties?.isRootCollection"
:inherited-properties="editingProperties.inheritedProperties" :inherited-properties="editingProperties?.inheritedProperties"
/> />
<AppBanner <AppBanner
:banner="{ :banner="{
@@ -93,7 +93,7 @@ type EditingProperties = {
collection: HoppCollection<HoppRESTRequest> | TeamCollection | null collection: HoppCollection<HoppRESTRequest> | TeamCollection | null
isRootCollection: boolean isRootCollection: boolean
path: string path: string
inheritedProperties: HoppInheritedProperty | null inheritedProperties: HoppInheritedProperty | undefined
} }
const props = withDefaults( const props = withDefaults(

View File

@@ -302,6 +302,7 @@ const editingProperties = ref<{
collection: null, collection: null,
isRootCollection: false, isRootCollection: false,
path: "", path: "",
inheritedProperties: undefined,
}) })
const confirmModalTitle = ref<string | null>(null) const confirmModalTitle = ref<string | null>(null)
@@ -678,7 +679,7 @@ const onAddRequest = (requestName: string) => {
if (!path) return if (!path) return
const insertionIndex = saveRESTRequestAs(path, newRequest) const insertionIndex = saveRESTRequestAs(path, newRequest)
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path) const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
tabs.createNewTab({ tabs.createNewTab({
request: newRequest, request: newRequest,
@@ -691,8 +692,6 @@ const onAddRequest = (requestName: string) => {
inheritedProperties: { inheritedProperties: {
auth, auth,
headers, headers,
parentName: name,
parentId: path,
}, },
}) })
@@ -1330,8 +1329,7 @@ const selectRequest = (selectedRequest: {
// If there is a request with this save context, switch into it // If there is a request with this save context, switch into it
let possibleTab = null let possibleTab = null
const { auth, headers, name } = const { auth, headers } = cascaseParentCollectionForHeaderAuth(folderPath)
cascaseParentCollectionForHeaderAuth(folderPath)
if (collectionsType.value.type === "team-collections") { if (collectionsType.value.type === "team-collections") {
possibleTab = tabs.getTabRefWithSaveContext({ possibleTab = tabs.getTabRefWithSaveContext({
@@ -1369,9 +1367,7 @@ const selectRequest = (selectedRequest: {
requestIndex: parseInt(requestIndex), requestIndex: parseInt(requestIndex),
}, },
inheritedProperties: { inheritedProperties: {
parentId: folderPath || "", auth,
parentName: name,
auth: auth,
headers, headers,
}, },
}) })
@@ -1405,7 +1401,7 @@ const dropRequest = (payload: {
let possibleTab = null let possibleTab = null
if (collectionsType.value.type === "my-collections" && folderPath) { if (collectionsType.value.type === "my-collections" && folderPath) {
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth( const { auth, headers } = cascaseParentCollectionForHeaderAuth(
destinationCollectionIndex destinationCollectionIndex
) )
@@ -1427,8 +1423,6 @@ const dropRequest = (payload: {
} }
possibleTab.value.document.inheritedProperties = { possibleTab.value.document.inheritedProperties = {
parentId: destinationCollectionIndex,
parentName: name,
auth, auth,
headers, headers,
} }
@@ -1600,13 +1594,11 @@ const dropCollection = (payload: {
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}` `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
) )
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth( const { auth, headers } = cascaseParentCollectionForHeaderAuth(
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}` `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
) )
const inheritedProperty = { const inheritedProperty = {
parentId: `${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
parentName: name,
auth, auth,
headers, headers,
} }
@@ -1983,12 +1975,9 @@ const editProperties = (payload: {
let inheritedProperties = {} let inheritedProperties = {}
if (parentIndex) { if (parentIndex) {
const { auth, headers, name } = const { auth, headers } = cascaseParentCollectionForHeaderAuth(parentIndex)
cascaseParentCollectionForHeaderAuth(parentIndex)
inheritedProperties = { inheritedProperties = {
parentId: parentIndex ?? "",
parentName: name,
auth, auth,
headers, headers,
} as HoppInheritedProperty } as HoppInheritedProperty
@@ -2016,12 +2005,10 @@ const setCollectionProperties = (newCollection: {
editRESTFolder(path, collection) editRESTFolder(path, collection)
} }
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(path) const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
nextTick(() => { nextTick(() => {
updateInheritedPropertiesForAffectedRequests(path, { updateInheritedPropertiesForAffectedRequests(path, {
parentId: path,
parentName: name,
auth, auth,
headers, headers,
}) })

View File

@@ -155,8 +155,8 @@
<div v-if="auth.authType === 'inherit'" class="p-4"> <div v-if="auth.authType === 'inherit'" class="p-4">
<span v-if="inheritedProperties?.auth"> <span v-if="inheritedProperties?.auth">
Inherited Inherited
{{ getAuthName(inheritedProperties.auth.authType) }} from Parent {{ getAuthName(inheritedProperties.auth.inheritedAuth.authType) }}
Collection {{ inheritedProperties?.parentName }} from Parent Collection {{ inheritedProperties?.auth.parentName }}
</span> </span>
<span v-else> <span v-else>
Please save this request in any collection to inherit the Please save this request in any collection to inherit the
@@ -232,7 +232,10 @@ const auth = useVModel(props, "modelValue", emit)
onMounted(() => { onMounted(() => {
if (props.isRootCollection && auth.value.authType === "inherit") { if (props.isRootCollection && auth.value.authType === "inherit") {
console.log("isRootCollection", auth.value.authType) console.log("isRootCollection", auth.value.authType)
auth.value.authType = "none" auth.value = {
authType: "none",
authActive: true,
}
} }
}) })

View File

@@ -242,17 +242,14 @@
:placeholder="`${t('count.value', { count: index + 1 })}`" :placeholder="`${t('count.value', { count: index + 1 })}`"
readonly readonly
/> />
<span class=""> <HoppButtonSecondary
<HoppButtonSecondary v-if="header.source === 'auth'"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="t(masking ? 'state.show' : 'state.hide')" :title="t(masking ? 'state.show' : 'state.hide')"
:icon=" :icon="masking && header.source === 'auth' ? IconEye : IconEyeOff"
masking && header.source === 'auth' ? IconEye : IconEyeOff @click="toggleMask()"
" />
:disabled="header.source !== 'auth'" <span class="aspect-square w-[2.05rem]"></span>
@click="toggleMask()"
/>
</span>
<span> <span>
<HoppButtonSecondary <HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
@@ -578,13 +575,13 @@ const inheritedProperties = computed(() => {
) )
const headers = inheritedHeaders.map((header, index) => ({ const headers = inheritedHeaders.map((header, index) => ({
inheritedFrom: props.inheritedProperties?.parentName, inheritedFrom: props.inheritedProperties?.headers[index].parentName,
source: "headers", source: "headers",
id: `header-${index}`, id: `header-${index}`,
header: { header: {
key: header.key, key: header.inheritedHeader?.key,
value: header.value, value: header.inheritedHeader?.value,
active: header.active, active: header.inheritedHeader?.active,
}, },
})) }))
@@ -602,7 +599,7 @@ const inheritedProperties = computed(() => {
const computedAuthHeader = getComputedAuthHeaders( const computedAuthHeader = getComputedAuthHeaders(
aggregateEnvs.value, aggregateEnvs.value,
request.value, request.value,
props.inheritedProperties.auth props.inheritedProperties.auth.inheritedAuth
)[0] )[0]
if ( if (
@@ -612,7 +609,7 @@ const inheritedProperties = computed(() => {
) { ) {
auth = [ auth = [
{ {
inheritedFrom: props.inheritedProperties?.parentName, inheritedFrom: props.inheritedProperties?.auth.parentName,
source: "auth", source: "auth",
id: `header-auth`, id: `header-auth`,
header: computedAuthHeader, header: computedAuthHeader,

View File

@@ -98,17 +98,31 @@ export function runRESTRequest$(
const requestAuth = const requestAuth =
tab.value.document.request.auth.authType === "inherit" && tab.value.document.request.auth.authType === "inherit" &&
tab.value.document.request.auth.authActive tab.value.document.request.auth.authActive
? tab.value.document.inheritedProperties?.auth ? tab.value.document.inheritedProperties?.auth.inheritedAuth
: tab.value.document.request.auth : tab.value.document.request.auth
const requestHeaders = [ let requestHeaders
...(tab.value.document.inheritedProperties?.headers ?? []),
...tab.value.document.request.headers, 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 = { const finalRequest = {
...tab.value.document.request, ...tab.value.document.request,
auth: requestAuth, auth: requestAuth ?? { authType: "none", authActive: false },
headers: requestHeaders, headers: requestHeaders,
} }

View File

@@ -121,16 +121,48 @@ export function updateInheritedPropertiesForAffectedRequests(
) )
}) })
const filteredTabs = tabs.filter((tab) => { const tabsEffectedByAuth = tabs.filter((tab) => {
return ( return (
tab.value.document.inheritedProperties && 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 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) { function resetSaveContextForAffectedRequests(folderPath: string) {

View File

@@ -1,8 +1,14 @@
import { HoppRESTRequest } from "@hoppscotch/data" import { HoppRESTRequest } from "@hoppscotch/data"
export type HoppInheritedProperty = { export type HoppInheritedProperty = {
parentId: string auth: {
parentName: string parentID: string
auth?: HoppRESTRequest["auth"] parentName: string
headers?: HoppRESTRequest["headers"] inheritedAuth: HoppRESTRequest["auth"]
}
headers: {
parentID: string
parentName: string
inheritedHeader?: HoppRESTRequest["headers"][number]
}[]
} }

View File

@@ -48,7 +48,6 @@ export const getComputedAuthHeaders = (
auth?: HoppRESTRequest["auth"] auth?: HoppRESTRequest["auth"]
) => { ) => {
const request = auth ? { auth: auth ?? { authActive: false } } : req const request = auth ? { auth: auth ?? { authActive: false } } : req
// If Authorization header is also being user-defined, that takes priority // If Authorization header is also being user-defined, that takes priority
if (req && req.headers.find((h) => h.key.toLowerCase() === "authorization")) if (req && req.headers.find((h) => h.key.toLowerCase() === "authorization"))
return [] return []
@@ -136,16 +135,18 @@ export type ComputedHeader = {
export const getComputedHeaders = ( export const getComputedHeaders = (
req: HoppRESTRequest, req: HoppRESTRequest,
envVars: Environment["variables"] envVars: Environment["variables"]
): ComputedHeader[] => [ ): ComputedHeader[] => {
...getComputedAuthHeaders(envVars, req).map((header) => ({ return [
source: "auth" as const, ...getComputedAuthHeaders(envVars, req).map((header) => ({
header, source: "auth" as const,
})), header,
...getComputedBodyHeaders(req).map((header) => ({ })),
source: "body" as const, ...getComputedBodyHeaders(req).map((header) => ({
header, source: "body" as const,
})), header,
] })),
]
}
export type ComputedParam = { export type ComputedParam = {
source: "auth" source: "auth"

View File

@@ -10,6 +10,7 @@ import { cloneDeep } from "lodash-es"
import { resolveSaveContextOnRequestReorder } from "~/helpers/collection/request" import { resolveSaveContextOnRequestReorder } from "~/helpers/collection/request"
import { getService } from "~/modules/dioc" import { getService } from "~/modules/dioc"
import { RESTTabService } from "~/services/tab/rest" import { RESTTabService } from "~/services/tab/rest"
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
const defaultRESTCollectionState = { const defaultRESTCollectionState = {
state: [ state: [
@@ -65,19 +66,22 @@ export function navigateToFolderWithIndexPath(
export function cascaseParentCollectionForHeaderAuth( export function cascaseParentCollectionForHeaderAuth(
folderPath: string | undefined folderPath: string | undefined
) { ) {
let auth: HoppRESTRequest["auth"] = { let auth: HoppInheritedProperty["auth"] = {
authType: "none", parentID: folderPath ?? "",
authActive: false, parentName: "",
inheritedAuth: {
authType: "inherit",
authActive: false,
},
} }
const headers: HoppRESTRequest["headers"] = [] const headers: HoppInheritedProperty["headers"] = []
let name = "" if (!folderPath) return { auth, headers }
if (!folderPath) return { auth, headers, name: "" }
const path = folderPath.split("/").map((i) => parseInt(i)) const path = folderPath.split("/").map((i) => parseInt(i))
// Check if the path is empty or invalid // Check if the path is empty or invalid
if (!path || path.length === 0) { if (!path || path.length === 0) {
console.error("Invalid path:", folderPath) 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' // 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 // Check if parentFolder is undefined or null
if (!parentFolder) { if (!parentFolder) {
console.error("Parent folder not found for path:", path) console.error("Parent folder not found for path:", path)
return { auth, headers, name: "" } return { auth, headers }
} }
const parentFolderAuth = parentFolder.auth const parentFolderAuth = parentFolder.auth
const parentFolderHeaders = parentFolder.headers const parentFolderHeaders = parentFolder.headers
const isRootCollection = path.length === 1
// Check if authType is not 'inherit' // Check if authType is not 'inherit'
if (parentFolderAuth?.authType !== "inherit") { if (parentFolderAuth?.authType !== "inherit" || isRootCollection) {
auth = parentFolderAuth || auth auth = {
name = parentFolder.name parentID: parentFolder.id ?? folderPath,
parentName: parentFolder.name,
inheritedAuth: parentFolderAuth,
}
} }
// Update headers, overwriting duplicates by key // Update headers, overwriting duplicates by key
if (parentFolderHeaders) { if (parentFolderHeaders) {
const activeHeaders = parentFolderHeaders.filter((h) => h.active) const activeHeaders = parentFolderHeaders.filter((h) => h.active)
activeHeaders.forEach((header) => { 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) { if (index !== -1) {
// Replace the existing header with the same key // Replace the existing header with the same key
headers[index] = header headers[index] = {
parentID: currentPath,
parentName: parentFolder.name,
inheritedHeader: header,
}
} else { } 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) { function reorderItems(array: unknown[], from: number, to: number) {
@@ -201,11 +221,7 @@ const restCollectionDispatchers = defineDispatchers({
requests: [], requests: [],
auth: { auth: {
authType: "inherit", authType: "inherit",
authActive: false, authActive: true,
auth: {
authType: "inherit",
authActive: false,
},
}, },
headers: [], headers: [],
}) })
@@ -768,7 +784,7 @@ const gqlCollectionDispatchers = defineDispatchers({
requests: [], requests: [],
auth: { auth: {
authType: "inherit", authType: "inherit",
authActive: false, authActive: true,
}, },
headers: [], headers: [],
}) })