|
@@ -156,6 +156,65 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</draggable>
|
|
|
+
|
|
|
+ <draggable
|
|
|
+ v-model="computedHeaders"
|
|
|
+ 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="mask(header)"
|
|
|
+ :placeholder="`${t('count.value', { count: index + 1 })}`"
|
|
|
+ readonly
|
|
|
+ />
|
|
|
+ <span>
|
|
|
+ <HoppButtonSecondary
|
|
|
+ v-if="header.source === 'auth'"
|
|
|
+ v-tippy="{ theme: 'tooltip' }"
|
|
|
+ :title="t(masking ? 'state.show' : 'state.hide')"
|
|
|
+ :icon="masking ? IconEye : IconEyeOff"
|
|
|
+ @click="toggleMask()"
|
|
|
+ />
|
|
|
+ <HoppButtonSecondary
|
|
|
+ v-else
|
|
|
+ v-tippy="{ theme: 'tooltip' }"
|
|
|
+ :icon="IconArrowUpRight"
|
|
|
+ :title="t('request.go_to_authorization_tab')"
|
|
|
+ class="cursor-auto text-primary hover:text-primary"
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ <span>
|
|
|
+ <HoppButtonSecondary
|
|
|
+ v-tippy="{ theme: 'tooltip' }"
|
|
|
+ :icon="IconArrowUpRight"
|
|
|
+ :title="t('request.go_to_authorization_tab')"
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </draggable>
|
|
|
+
|
|
|
<HoppSmartPlaceholder
|
|
|
v-if="workingHeaders.length === 0"
|
|
|
:src="`/images/states/${colorMode.value}/add_category.svg`"
|
|
@@ -184,7 +243,12 @@ import IconCheckCircle from "~icons/lucide/check-circle"
|
|
|
import IconTrash from "~icons/lucide/trash"
|
|
|
import IconCircle from "~icons/lucide/circle"
|
|
|
import IconWrapText from "~icons/lucide/wrap-text"
|
|
|
-import { reactive, ref, watch } from "vue"
|
|
|
+import IconArrowUpRight from "~icons/lucide/arrow-up-right"
|
|
|
+import IconLock from "~icons/lucide/lock"
|
|
|
+import IconEye from "~icons/lucide/eye"
|
|
|
+import IconEyeOff from "~icons/lucide/eye-off"
|
|
|
+
|
|
|
+import { computed, reactive, ref, watch } from "vue"
|
|
|
import * as E from "fp-ts/Either"
|
|
|
import * as O from "fp-ts/Option"
|
|
|
import * as A from "fp-ts/Array"
|
|
@@ -206,6 +270,7 @@ import { commonHeaders } from "~/helpers/headers"
|
|
|
import { useCodemirror } from "@composables/codemirror"
|
|
|
import { objRemoveKey } from "~/helpers/functional/object"
|
|
|
import { useVModel } from "@vueuse/core"
|
|
|
+import { HoppGQLHeader } from "~/helpers/graphql"
|
|
|
|
|
|
const colorMode = useColorMode()
|
|
|
const t = useI18n()
|
|
@@ -321,6 +386,7 @@ watch(workingHeaders, (newWorkingHeaders) => {
|
|
|
)
|
|
|
)
|
|
|
|
|
|
+ console.log("not-equal", workingHeaders.value)
|
|
|
if (!isEqual(request.value.headers, fixedHeaders)) {
|
|
|
request.value.headers = cloneDeep(fixedHeaders)
|
|
|
}
|
|
@@ -429,4 +495,88 @@ const clearContent = () => {
|
|
|
|
|
|
bulkHeaders.value = ""
|
|
|
}
|
|
|
+
|
|
|
+const getComputedAuthHeaders = (
|
|
|
+ req?: HoppGQLRequest,
|
|
|
+ auth?: HoppGQLRequest["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 []
|
|
|
+
|
|
|
+ if (!request) return []
|
|
|
+
|
|
|
+ if (!request.auth || !request.auth.authActive) return []
|
|
|
+
|
|
|
+ const headers: HoppGQLHeader[] = []
|
|
|
+
|
|
|
+ // TODO: Support a better b64 implementation than btoa ?
|
|
|
+ if (request.auth.authType === "basic") {
|
|
|
+ const username = request.auth.username
|
|
|
+ const password = request.auth.password
|
|
|
+
|
|
|
+ headers.push({
|
|
|
+ active: true,
|
|
|
+ key: "Authorization",
|
|
|
+ value: `Basic ${btoa(`${username}:${password}`)}`,
|
|
|
+ })
|
|
|
+ } else if (
|
|
|
+ request.auth.authType === "bearer" ||
|
|
|
+ request.auth.authType === "oauth-2"
|
|
|
+ ) {
|
|
|
+ headers.push({
|
|
|
+ active: true,
|
|
|
+ key: "Authorization",
|
|
|
+ value: `Bearer ${request.auth.token}`,
|
|
|
+ })
|
|
|
+ } else if (request.auth.authType === "api-key") {
|
|
|
+ const { key, value, addTo } = request.auth
|
|
|
+
|
|
|
+ if (addTo === "Headers") {
|
|
|
+ headers.push({
|
|
|
+ active: true,
|
|
|
+ key,
|
|
|
+ value,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return headers
|
|
|
+}
|
|
|
+
|
|
|
+const getComputedHeaders = (req: HoppGQLRequest) => {
|
|
|
+ return [
|
|
|
+ ...getComputedAuthHeaders(req).map((header) => ({
|
|
|
+ source: "auth" as const,
|
|
|
+ header,
|
|
|
+ })),
|
|
|
+ ]
|
|
|
+}
|
|
|
+
|
|
|
+const computedHeaders = computed(() =>
|
|
|
+ getComputedHeaders(request.value).map((header, index) => ({
|
|
|
+ id: `header-${index}`,
|
|
|
+ ...header,
|
|
|
+ }))
|
|
|
+)
|
|
|
+
|
|
|
+const masking = ref(true)
|
|
|
+
|
|
|
+const toggleMask = () => {
|
|
|
+ masking.value = !masking.value
|
|
|
+}
|
|
|
+
|
|
|
+const mask = (header: any) => {
|
|
|
+ if (header.source === "auth" && masking.value)
|
|
|
+ return header.header.value.replace(/\S/gi, "*")
|
|
|
+ return header.header.value
|
|
|
+}
|
|
|
+
|
|
|
+// const changeTab = (tab: ComputedHeader["source"]) => {
|
|
|
+// if (tab === "auth") emit("change-tab", "authorization")
|
|
|
+// else emit("change-tab", "bodyParams")
|
|
|
+// }
|
|
|
+
|
|
|
+console.log("compoyed-header", computedHeaders.value)
|
|
|
</script>
|