feat: collection level headers and authorization (#3505)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
Nivedin
2023-12-13 22:43:18 +05:30
committed by GitHub
parent f3edd001d7
commit 47e009267b
95 changed files with 3221 additions and 970 deletions

View File

@@ -95,13 +95,41 @@ export function runRESTRequest$(
return E.left("script_fail" as const)
}
const effectiveRequest = getEffectiveRESTRequest(
tab.value.document.request,
{
name: "Env",
variables: combineEnvVariables(envs.right),
}
)
const requestAuth =
tab.value.document.request.auth.authType === "inherit" &&
tab.value.document.request.auth.authActive
? tab.value.document.inheritedProperties?.auth.inheritedAuth
: tab.value.document.request.auth
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 ?? { authType: "none", authActive: false },
headers: requestHeaders,
}
const effectiveRequest = getEffectiveRESTRequest(finalRequest, {
name: "Env",
variables: combineEnvVariables(envs.right),
})
const [stream, cancelRun] = createRESTNetworkRequestStream(effectiveRequest)
cancelFunc = cancelRun

View File

@@ -0,0 +1,15 @@
mutation UpdateTeamCollection(
$collectionID: ID!
$newTitle: String
$data: String
) {
updateTeamCollection(
collectionID: $collectionID
newTitle: $newTitle
data: $data
) {
id
title
data
}
}

View File

@@ -3,6 +3,7 @@ query GetCollectionChildren($collectionID: ID!, $cursor: ID) {
children(cursor: $cursor) {
id
title
data
}
}
}

View File

@@ -1,5 +0,0 @@
query GetCollectionTitle($collectionID: ID!) {
collection(collectionID: $collectionID) {
title
}
}

View File

@@ -0,0 +1,6 @@
query GetCollectionTitleAndData($collectionID: ID!) {
collection(collectionID: $collectionID) {
title
data
}
}

View File

@@ -2,6 +2,7 @@ query GetSingleCollection($collectionID: ID!) {
collection(collectionID: $collectionID) {
id
title
data
parent {
id
}

View File

@@ -2,5 +2,6 @@ query RootCollectionsOfTeam($teamID: ID!, $cursor: ID) {
rootCollectionsOfTeam(teamID: $teamID, cursor: $cursor) {
id
title
data
}
}

View File

@@ -2,6 +2,7 @@ subscription TeamCollectionAdded($teamID: ID!) {
teamCollectionAdded(teamID: $teamID) {
id
title
data
parent {
id
}

View File

@@ -2,6 +2,7 @@ subscription TeamCollectionUpdated($teamID: ID!) {
teamCollectionUpdated(teamID: $teamID) {
id
title
data
parent {
id
}

View File

@@ -4,7 +4,6 @@ import * as TE from "fp-ts/TaskEither"
import { pipe, flow } from "fp-ts/function"
import {
HoppCollection,
HoppRESTRequest,
makeCollection,
translateToNewRequest,
} from "@hoppscotch/data"
@@ -15,7 +14,7 @@ import {
ExportAsJsonDocument,
GetCollectionChildrenIDsDocument,
GetCollectionRequestsDocument,
GetCollectionTitleDocument,
GetCollectionTitleAndDataDocument,
} from "./graphql"
export const BACKEND_PAGE_SIZE = 10
@@ -85,16 +84,19 @@ export const getCompleteCollectionTree = (
pipe(
TE.Do,
TE.bind("title", () =>
TE.bind("titleAndData", () =>
pipe(
() =>
runGQLQuery({
query: GetCollectionTitleDocument,
query: GetCollectionTitleAndDataDocument,
variables: {
collectionID: collID,
},
}),
TE.map((x) => x.collection!.title)
TE.map((result) => ({
title: result.collection!.title,
data: result.collection!.data,
}))
)
),
TE.bind("children", () =>
@@ -108,24 +110,36 @@ export const getCompleteCollectionTree = (
TE.bind("requests", () => () => getCollectionRequests(collID)),
TE.map(
({ title, children, requests }) =>
({ titleAndData, children, requests }) =>
<TeamCollection>{
id: collID,
children,
requests,
title,
title: titleAndData.title,
data: titleAndData.data,
}
)
)
export const teamCollToHoppRESTColl = (
coll: TeamCollection
): HoppCollection<HoppRESTRequest> =>
makeCollection({
): HoppCollection => {
const data =
coll.data && coll.data !== "null"
? JSON.parse(coll.data)
: {
auth: { authType: "inherit", authActive: true },
headers: [],
}
return makeCollection({
name: coll.title,
folders: coll.children?.map(teamCollToHoppRESTColl) ?? [],
requests: coll.requests?.map((x) => x.request) ?? [],
auth: data.auth ?? { authType: "inherit", authActive: true },
headers: data.headers ?? [],
})
}
/**
* Get the JSON string of all the collection of the specified team

View File

@@ -21,6 +21,9 @@ import {
UpdateCollectionOrderDocument,
UpdateCollectionOrderMutation,
UpdateCollectionOrderMutationVariables,
UpdateTeamCollectionDocument,
UpdateTeamCollectionMutation,
UpdateTeamCollectionMutationVariables,
} from "../graphql"
type CreateNewRootCollectionError = "team_coll/short_title"
@@ -122,3 +125,18 @@ export const importJSONToTeam = (collectionJSON: string, teamID: string) =>
teamID,
}
)
export const updateTeamCollection = (
collectionID: string,
data?: string,
newTitle?: string
) =>
runMutation<
UpdateTeamCollectionMutation,
UpdateTeamCollectionMutationVariables,
""
>(UpdateTeamCollectionDocument, {
collectionID,
data,
newTitle,
})

View File

@@ -1,10 +1,12 @@
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
import { HoppCollection } from "@hoppscotch/data"
import { getAffectedIndexes } from "./affectedIndex"
import { GetSingleRequestDocument } from "../backend/graphql"
import { runGQLQuery } from "../backend/GQLClient"
import * as E from "fp-ts/Either"
import { getService } from "~/modules/dioc"
import { RESTTabService } from "~/services/tab/rest"
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
import { GQLTabService } from "~/services/tab/graphql"
/**
* Resolve save context on reorder
@@ -108,6 +110,135 @@ export function updateSaveContextForAffectedRequests(
}
}
/**
* Used to check the new folder path is close to the save context folder path or not
* @param folderPathCurrent The path saved as the inherited path in the inherited properties
* @param newFolderPath The incomming path
* @param saveContextPath The save context of the request
* @returns The path which is close to saveContext.folderPath
*/
function folderPathCloseToSaveContext(
folderPathCurrent: string | undefined,
newFolderPath: string,
saveContextPath: string
) {
if (!folderPathCurrent) return newFolderPath
const folderPathCurrentArray = folderPathCurrent.split("/")
const newFolderPathArray = newFolderPath.split("/")
const saveContextFolderPathArray = saveContextPath.split("/")
let folderPathCurrentMatch = 0
for (let i = 0; i < folderPathCurrentArray.length; i++) {
if (folderPathCurrentArray[i] === saveContextFolderPathArray[i]) {
folderPathCurrentMatch++
}
}
let newFolderPathMatch = 0
for (let i = 0; i < newFolderPathArray.length; i++) {
if (newFolderPathArray[i] === saveContextFolderPathArray[i]) {
newFolderPathMatch++
}
}
if (folderPathCurrentMatch > newFolderPathMatch) {
return folderPathCurrent
}
return newFolderPath
}
export function updateInheritedPropertiesForAffectedRequests(
path: string,
inheritedProperties: HoppInheritedProperty,
type: "rest" | "graphql",
workspace: "personal" | "team" = "personal"
) {
const tabService =
type === "rest" ? getService(RESTTabService) : getService(GQLTabService)
let tabs
if (workspace === "personal") {
tabs = tabService.getTabsRefTo((tab) => {
return (
tab.document.saveContext?.originLocation === "user-collection" &&
tab.document.saveContext.folderPath.startsWith(path)
)
})
} else {
tabs = tabService.getTabsRefTo((tab) => {
return (
tab.document.saveContext?.originLocation === "team-collection" &&
tab.document.saveContext.collectionID?.startsWith(path)
)
})
}
const tabsEffectedByAuth = tabs.filter((tab) => {
if (workspace === "personal") {
return (
tab.value.document.saveContext?.originLocation === "user-collection" &&
tab.value.document.saveContext.folderPath.startsWith(path) &&
path ===
folderPathCloseToSaveContext(
tab.value.document.inheritedProperties?.auth.parentID,
path,
tab.value.document.saveContext.folderPath
)
)
}
return (
tab.value.document.saveContext?.originLocation === "team-collection" &&
tab.value.document.saveContext.collectionID?.startsWith(path) &&
path ===
folderPathCloseToSaveContext(
tab.value.document.inheritedProperties?.auth.parentID,
path,
tab.value.document.saveContext.collectionID
)
)
})
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) {
const tabService = getService(RESTTabService)
const tabs = tabService.getTabsRefTo((tab) => {
@@ -152,9 +283,9 @@ export async function resetTeamRequestsContext() {
}
export function getFoldersByPath(
collections: HoppCollection<HoppRESTRequest>[],
collections: HoppCollection[],
path: string
): HoppCollection<HoppRESTRequest>[] {
): HoppCollection[] {
if (!path) return collections
// path will be like this "0/0/1" these are the indexes of the folders

View File

@@ -1,4 +1,8 @@
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
import {
HoppCollection,
HoppGQLRequest,
HoppRESTRequest,
} from "@hoppscotch/data"
import { getAffectedIndexes } from "./affectedIndex"
import { RESTTabService } from "~/services/tab/rest"
import { getService } from "~/modules/dioc"
@@ -53,9 +57,9 @@ export function resolveSaveContextOnRequestReorder(payload: {
}
export function getRequestsByPath(
collections: HoppCollection<HoppRESTRequest>[],
collections: HoppCollection[],
path: string
): HoppRESTRequest[] {
): HoppRESTRequest[] | HoppGQLRequest[] {
// path will be like this "0/0/1" these are the indexes of the folders
const pathArray = path.split("/").map((index) => parseInt(index))

View File

@@ -27,7 +27,7 @@ export const getDefaultGQLRequest = (): HoppGQLRequest => ({
}`,
query: DEFAULT_QUERY,
auth: {
authType: "none",
authType: "inherit",
authActive: true,
},
})

View File

@@ -1,6 +1,7 @@
import { HoppGQLRequest } from "@hoppscotch/data"
import { GQLResponseEvent } from "./connection"
import { GQLOptionTabs } from "~/components/graphql/RequestOptions.vue"
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
export type HoppGQLSaveContext =
| {
@@ -73,4 +74,10 @@ export type HoppGQLDocument = {
* Options tab preference for the current tab's document
*/
optionTabPreference?: GQLOptionTabs
/**
* The inherited properties from the parent collection
* (if any)
*/
inheritedProperties?: HoppInheritedProperty
}

View File

@@ -1,7 +1,5 @@
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
import { HoppCollection } from "@hoppscotch/data"
export const gqlCollectionsExporter = (
gqlCollections: HoppCollection<HoppGQLRequest>[]
) => {
export const gqlCollectionsExporter = (gqlCollections: HoppCollection[]) => {
return JSON.stringify(gqlCollections, null, 2)
}

View File

@@ -1,7 +1,5 @@
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
import { HoppCollection } from "@hoppscotch/data"
export const myCollectionsExporter = (
myCollections: HoppCollection<HoppRESTRequest>[]
) => {
export const myCollectionsExporter = (myCollections: HoppCollection[]) => {
return JSON.stringify(myCollections, null, 2)
}

View File

@@ -2,15 +2,12 @@ import { pipe, flow } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither"
import * as O from "fp-ts/Option"
import * as RA from "fp-ts/ReadonlyArray"
import {
translateToNewRESTCollection,
HoppCollection,
HoppRESTRequest,
} from "@hoppscotch/data"
import { translateToNewRESTCollection, HoppCollection } from "@hoppscotch/data"
import { isPlainObject as _isPlainObject } from "lodash-es"
import { IMPORTER_INVALID_FILE_FORMAT } from "."
import { safeParseJSON } from "~/helpers/functional/json"
import { translateToNewGQLCollection } from "@hoppscotch/data"
export const hoppRESTImporter = (content: string) =>
pipe(
@@ -33,12 +30,10 @@ const isPlainObject = (value: any): value is object => _isPlainObject(value)
/**
* checks if a collection matches the schema for a hoppscotch collection.
* as of now we are only checking if the collection has a "v" key in it.
* here 2 is the latest version of the schema.
*/
const isValidCollection = (
collection: unknown
): collection is HoppCollection<HoppRESTRequest> =>
isPlainObject(collection) && "v" in collection
const isValidCollection = (collection: unknown): collection is HoppCollection =>
isPlainObject(collection) && "v" in collection && collection.v === 2
/**
* checks if a collection is a valid hoppscotch collection.
@@ -56,3 +51,29 @@ const validateCollection = (collection: unknown) => {
*/
const makeCollectionsArray = (collections: unknown | unknown[]): unknown[] =>
Array.isArray(collections) ? collections : [collections]
export const hoppGQLImporter = (content: string) =>
pipe(
safeParseJSON(content),
O.chain(
flow(
makeCollectionsArray,
RA.map(validateGQLCollection),
O.sequenceArray,
O.map(RA.toArray)
)
),
TE.fromOption(() => IMPORTER_INVALID_FILE_FORMAT)
)
/**
*
* @param collection the collection to validate
* @returns the collection if it is valid, else a translated version of the collection
*/
export const validateGQLCollection = (collection: unknown) => {
if (isValidCollection(collection)) {
return O.some(collection)
}
return O.some(translateToNewGQLCollection(collection))
}

View File

@@ -1,12 +1,12 @@
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
import { HoppCollection } from "@hoppscotch/data"
import * as E from "fp-ts/Either"
// TODO: add zod validation
export const hoppGqlCollectionsImporter = (
content: string
): E.Either<"INVALID_JSON", HoppCollection<HoppGQLRequest>[]> => {
): E.Either<"INVALID_JSON", HoppCollection[]> => {
return E.tryCatch(
() => JSON.parse(content) as HoppCollection<HoppGQLRequest>[],
() => JSON.parse(content) as HoppCollection[],
() => "INVALID_JSON"
)
}

View File

@@ -192,7 +192,7 @@ const getHoppRequest = (req: InsomniaRequestResource): HoppRESTRequest =>
const getHoppFolder = (
folderRes: InsomniaFolderResource,
resources: InsomniaResource[]
): HoppCollection<HoppRESTRequest> =>
): HoppCollection =>
makeCollection({
name: folderRes.name ?? "",
folders: getFoldersIn(folderRes, resources).map((f) =>

View File

@@ -12,7 +12,6 @@ import {
HoppRESTHeader,
HoppRESTParam,
HoppRESTReqBody,
HoppRESTRequest,
knownContentTypes,
makeRESTRequest,
HoppCollection,
@@ -581,7 +580,7 @@ const convertPathToHoppReqs = (
const convertOpenApiDocToHopp = (
doc: OpenAPI.Document
): TE.TaskEither<never, HoppCollection<HoppRESTRequest>[]> => {
): TE.TaskEither<never, HoppCollection[]> => {
const name = doc.info.title
const paths = Object.entries(doc.paths ?? {})
@@ -589,7 +588,7 @@ const convertOpenApiDocToHopp = (
.flat()
return TE.of([
makeCollection<HoppRESTRequest>({
makeCollection({
name,
folders: [],
requests: paths,

View File

@@ -283,7 +283,7 @@ const getHoppRequest = (item: Item): HoppRESTRequest => {
})
}
const getHoppFolder = (ig: ItemGroup<Item>): HoppCollection<HoppRESTRequest> =>
const getHoppFolder = (ig: ItemGroup<Item>): HoppCollection =>
makeCollection({
name: ig.name,
folders: pipe(

View File

@@ -2,6 +2,7 @@ import { HoppRESTRequest } from "@hoppscotch/data"
import { HoppRESTResponse } from "../types/HoppRESTResponse"
import { HoppTestResult } from "../types/HoppTestResult"
import { RESTOptionTabs } from "~/components/http/RequestOptions.vue"
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
export type HoppRESTSaveContext =
| {
@@ -80,4 +81,10 @@ export type HoppRESTDocument = {
* Options tab preference for the current tab's document
*/
optionTabPreference?: RESTOptionTabs
/**
* The inherited properties from the parent collection
* (if any)
*/
inheritedProperties?: HoppInheritedProperty
}

View File

@@ -8,4 +8,5 @@ export interface TeamCollection {
title: string
children: TeamCollection[] | null
requests: TeamRequest[] | null
data: string | null
}

View File

@@ -1,6 +1,10 @@
import * as E from "fp-ts/Either"
import { BehaviorSubject, Subscription } from "rxjs"
import { translateToNewRequest } from "@hoppscotch/data"
import {
HoppRESTAuth,
HoppRESTHeader,
translateToNewRequest,
} from "@hoppscotch/data"
import { pull, remove } from "lodash-es"
import { Subscription as WSubscription } from "wonka"
import { runGQLQuery, runGQLSubscription } from "../backend/GQLClient"
@@ -21,6 +25,7 @@ import {
TeamRequestOrderUpdatedDocument,
TeamCollectionOrderUpdatedDocument,
} from "~/helpers/backend/graphql"
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
const TEAMS_BACKEND_PAGE_SIZE = 10
@@ -542,6 +547,7 @@ export default class NewTeamCollectionAdapter {
children: null,
requests: null,
title: title,
data: null,
},
parentID ?? null
)
@@ -693,6 +699,7 @@ export default class NewTeamCollectionAdapter {
children: null,
requests: null,
title: result.right.teamCollectionAdded.title,
data: result.right.teamCollectionAdded.data ?? null,
},
result.right.teamCollectionAdded.parent?.id ?? null
)
@@ -715,6 +722,7 @@ export default class NewTeamCollectionAdapter {
this.updateCollection({
id: result.right.teamCollectionUpdated.id,
title: result.right.teamCollectionUpdated.title,
data: result.right.teamCollectionUpdated.data,
})
})
@@ -931,6 +939,7 @@ export default class NewTeamCollectionAdapter {
<TeamCollection>{
id: el.id,
title: el.title,
data: el.data,
children: null,
requests: null,
}
@@ -1024,4 +1033,104 @@ export default class NewTeamCollectionAdapter {
)
}
}
public cascadeParentCollectionForHeaderAuth(folderPath: string) {
let auth: HoppInheritedProperty["auth"] = {
parentID: folderPath ?? "",
parentName: "",
inheritedAuth: {
authType: "none",
authActive: true,
},
}
const headers: HoppInheritedProperty["headers"] = []
if (!folderPath) return { auth, headers }
const path = folderPath.split("/")
// Check if the path is empty or invalid
if (!path || path.length === 0) {
console.error("Invalid path:", folderPath)
return { auth, headers }
}
// Loop through the path and get the last parent folder with authType other than 'inherit'
for (let i = 0; i < path.length; i++) {
const parentFolder = findCollInTree(this.collections$.value, path[i])
// Check if parentFolder is undefined or null
if (!parentFolder) {
console.error("Parent folder not found for path:", path)
return { auth, headers }
}
const data: {
auth: HoppRESTAuth
headers: HoppRESTHeader[]
} = parentFolder.data
? JSON.parse(parentFolder.data)
: {
auth: null,
headers: null,
}
if (!data.auth) {
data.auth = {
authType: "inherit",
authActive: true,
}
auth.parentID = [...path.slice(0, i + 1)].join("/")
auth.parentName = parentFolder.title
}
if (!data.headers) data.headers = []
const parentFolderAuth = data.auth
const parentFolderHeaders = data.headers
if (parentFolderAuth?.authType === "inherit" && path.length === 1) {
auth = {
parentID: [...path.slice(0, i + 1)].join("/"),
parentName: parentFolder.title,
inheritedAuth: auth.inheritedAuth,
}
}
if (parentFolderAuth?.authType !== "inherit") {
auth = {
parentID: [...path.slice(0, i + 1)].join("/"),
parentName: parentFolder.title,
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.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] = {
parentID: currentPath,
parentName: parentFolder.title,
inheritedHeader: header,
}
} else {
headers.push({
parentID: currentPath,
parentName: parentFolder.title,
inheritedHeader: header,
})
}
})
}
}
return { auth, headers }
}
}

View File

@@ -0,0 +1,19 @@
import {
GQLHeader,
HoppGQLAuth,
HoppRESTHeader,
HoppRESTAuth,
} from "@hoppscotch/data"
export type HoppInheritedProperty = {
auth: {
parentID: string
parentName: string
inheritedAuth: HoppRESTAuth | HoppGQLAuth
}
headers: {
parentID: string
parentName: string
inheritedHeader: HoppRESTHeader | GQLHeader
}[]
}

View File

@@ -42,22 +42,26 @@ export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
* @param envVars Currently active environment variables
* @returns The list of headers
*/
const getComputedAuthHeaders = (
req: HoppRESTRequest,
envVars: Environment["variables"]
export const getComputedAuthHeaders = (
envVars: Environment["variables"],
req?: HoppRESTRequest,
auth?: HoppRESTRequest["auth"]
) => {
const request = auth ? { auth: auth ?? { authActive: false } } : req
// If Authorization header is also being user-defined, that takes priority
if (req.headers.find((h) => h.key.toLowerCase() === "authorization"))
if (req && req.headers.find((h) => h.key.toLowerCase() === "authorization"))
return []
if (!req.auth.authActive) return []
if (!request) return []
if (!request.auth || !request.auth.authActive) return []
const headers: HoppRESTHeader[] = []
// TODO: Support a better b64 implementation than btoa ?
if (req.auth.authType === "basic") {
const username = parseTemplateString(req.auth.username, envVars)
const password = parseTemplateString(req.auth.password, envVars)
if (request.auth.authType === "basic") {
const username = parseTemplateString(request.auth.username, envVars)
const password = parseTemplateString(request.auth.password, envVars)
headers.push({
active: true,
@@ -65,22 +69,21 @@ const getComputedAuthHeaders = (
value: `Basic ${btoa(`${username}:${password}`)}`,
})
} else if (
req.auth.authType === "bearer" ||
req.auth.authType === "oauth-2"
request.auth.authType === "bearer" ||
request.auth.authType === "oauth-2"
) {
headers.push({
active: true,
key: "Authorization",
value: `Bearer ${parseTemplateString(req.auth.token, envVars)}`,
value: `Bearer ${parseTemplateString(request.auth.token, envVars)}`,
})
} else if (req.auth.authType === "api-key") {
const { key, value, addTo } = req.auth
if (addTo === "Headers") {
} else if (request.auth.authType === "api-key") {
const { key, addTo } = request.auth
if (addTo === "Headers" && key) {
headers.push({
active: true,
key: parseTemplateString(key, envVars),
value: parseTemplateString(value, envVars),
value: parseTemplateString(request.auth.value ?? "", envVars),
})
}
}
@@ -131,16 +134,18 @@ export type ComputedHeader = {
export const getComputedHeaders = (
req: HoppRESTRequest,
envVars: Environment["variables"]
): ComputedHeader[] => [
...getComputedAuthHeaders(req, envVars).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"
@@ -160,7 +165,7 @@ export const getComputedParams = (
): ComputedParam[] => {
// When this gets complex, its best to split this function off (like with getComputedHeaders)
// API-key auth can be added to query params
if (!req.auth.authActive) return []
if (!req.auth || !req.auth.authActive) return []
if (req.auth.authType !== "api-key") return []
if (req.auth.addTo !== "Query params") return []