feat: added inherit auth-header for personal gql
This commit is contained in:
@@ -240,15 +240,14 @@ const saveRequestAs = async () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
`${picked.value.collectionIndex}`
|
`${picked.value.collectionIndex}`,
|
||||||
|
"rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||||
auth,
|
auth,
|
||||||
headers,
|
headers,
|
||||||
parentId: `${picked.value.collectionIndex}`,
|
|
||||||
parentName: name,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
@@ -278,15 +277,14 @@ const saveRequestAs = async () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
picked.value.folderPath
|
picked.value.folderPath,
|
||||||
|
"rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||||
auth,
|
auth,
|
||||||
headers,
|
headers,
|
||||||
parentId: picked.value.folderPath,
|
|
||||||
parentName: name,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
@@ -317,15 +315,14 @@ const saveRequestAs = async () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const { auth, headers, name } = cascaseParentCollectionForHeaderAuth(
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
picked.value.folderPath
|
picked.value.folderPath,
|
||||||
|
"rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||||
auth,
|
auth,
|
||||||
headers,
|
headers,
|
||||||
parentId: picked.value.folderPath,
|
|
||||||
parentName: name,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
@@ -412,6 +409,16 @@ const saveRequestAs = async () => {
|
|||||||
workspaceType: "team",
|
workspaceType: "team",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
picked.value.folderPath,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
|
||||||
requestSaved()
|
requestSaved()
|
||||||
} else if (picked.value.pickedType === "gql-my-folder") {
|
} else if (picked.value.pickedType === "gql-my-folder") {
|
||||||
// TODO: Check for GQL request ?
|
// TODO: Check for GQL request ?
|
||||||
@@ -427,6 +434,16 @@ const saveRequestAs = async () => {
|
|||||||
workspaceType: "team",
|
workspaceType: "team",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
picked.value.folderPath,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
|
||||||
requestSaved()
|
requestSaved()
|
||||||
} else if (picked.value.pickedType === "gql-my-collection") {
|
} else if (picked.value.pickedType === "gql-my-collection") {
|
||||||
// TODO: Check for GQL request ?
|
// TODO: Check for GQL request ?
|
||||||
@@ -442,6 +459,16 @@ const saveRequestAs = async () => {
|
|||||||
workspaceType: "team",
|
workspaceType: "team",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
`${picked.value.collectionIndex}`,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
|
||||||
requestSaved()
|
requestSaved()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ const addNewCollection = () => {
|
|||||||
name: name.value,
|
name: name.value,
|
||||||
folders: [],
|
folders: [],
|
||||||
requests: [],
|
requests: [],
|
||||||
|
auth: {
|
||||||
|
authType: "inherit",
|
||||||
|
authActive: true,
|
||||||
|
},
|
||||||
|
headers: [],
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,21 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
<HoppSmartItem
|
||||||
|
ref="propertiesAction"
|
||||||
|
:icon="IconSettings2"
|
||||||
|
:label="t('action.properties')"
|
||||||
|
:shortcut="['P']"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
emit('edit-properties', {
|
||||||
|
collectionIndex: String(collectionIndex),
|
||||||
|
collection: collection,
|
||||||
|
})
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</tippy>
|
</tippy>
|
||||||
@@ -155,7 +170,14 @@
|
|||||||
@edit-folder="$emit('edit-folder', $event)"
|
@edit-folder="$emit('edit-folder', $event)"
|
||||||
@edit-request="$emit('edit-request', $event)"
|
@edit-request="$emit('edit-request', $event)"
|
||||||
@duplicate-request="$emit('duplicate-request', $event)"
|
@duplicate-request="$emit('duplicate-request', $event)"
|
||||||
|
@edit-properties="
|
||||||
|
$emit('edit-properties', {
|
||||||
|
collectionIndex: `${collectionIndex}/${String(index)}`,
|
||||||
|
collection: folder,
|
||||||
|
})
|
||||||
|
"
|
||||||
@select="$emit('select', $event)"
|
@select="$emit('select', $event)"
|
||||||
|
@select-request="$emit('select-request', $event)"
|
||||||
/>
|
/>
|
||||||
<CollectionsGraphqlRequest
|
<CollectionsGraphqlRequest
|
||||||
v-for="(request, index) in collection.requests"
|
v-for="(request, index) in collection.requests"
|
||||||
@@ -171,6 +193,7 @@
|
|||||||
@edit-request="$emit('edit-request', $event)"
|
@edit-request="$emit('edit-request', $event)"
|
||||||
@duplicate-request="$emit('duplicate-request', $event)"
|
@duplicate-request="$emit('duplicate-request', $event)"
|
||||||
@select="$emit('select', $event)"
|
@select="$emit('select', $event)"
|
||||||
|
@select-request="$emit('select-request', $event)"
|
||||||
/>
|
/>
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
v-if="
|
v-if="
|
||||||
@@ -214,6 +237,7 @@ import IconFolderPlus from "~icons/lucide/folder-plus"
|
|||||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||||
import IconEdit from "~icons/lucide/edit"
|
import IconEdit from "~icons/lucide/edit"
|
||||||
import IconTrash2 from "~icons/lucide/trash-2"
|
import IconTrash2 from "~icons/lucide/trash-2"
|
||||||
|
import IconSettings2 from "~icons/lucide/settings-2"
|
||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { useColorMode } from "@composables/theming"
|
import { useColorMode } from "@composables/theming"
|
||||||
@@ -224,15 +248,16 @@ import {
|
|||||||
import { Picked } from "~/helpers/types/HoppPicked"
|
import { Picked } from "~/helpers/types/HoppPicked"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { GQLTabService } from "~/services/tab/graphql"
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
|
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps<{
|
||||||
picked: { type: Object, default: null },
|
picked: Picked | null
|
||||||
// Whether the viewing context is related to picking (activates 'select' events)
|
// Whether the viewing context is related to picking (activates 'select' events)
|
||||||
saveRequest: { type: Boolean, default: false },
|
saveRequest: boolean
|
||||||
collectionIndex: { type: Number, default: null },
|
collectionIndex: number | null
|
||||||
collection: { type: Object, default: () => ({}) },
|
collection: HoppCollection<HoppGQLRequest>
|
||||||
isFiltered: Boolean,
|
isFiltered: boolean
|
||||||
})
|
}>()
|
||||||
|
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -248,7 +273,15 @@ const emit = defineEmits<{
|
|||||||
(e: "add-request", i: any): void
|
(e: "add-request", i: any): void
|
||||||
(e: "add-folder", i: any): void
|
(e: "add-folder", i: any): void
|
||||||
(e: "edit-folder", i: any): void
|
(e: "edit-folder", i: any): void
|
||||||
|
(
|
||||||
|
e: "edit-properties",
|
||||||
|
payload: {
|
||||||
|
collectionIndex: string | null
|
||||||
|
collection: HoppCollection<HoppGQLRequest>
|
||||||
|
}
|
||||||
|
): void
|
||||||
(e: "edit-collection"): void
|
(e: "edit-collection"): void
|
||||||
|
(e: "select-request", i: any): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
// Template refs
|
// Template refs
|
||||||
|
|||||||
@@ -121,6 +121,21 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
<HoppSmartItem
|
||||||
|
ref="propertiesAction"
|
||||||
|
:icon="IconSettings2"
|
||||||
|
:label="t('action.properties')"
|
||||||
|
:shortcut="['P']"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
emit('edit-properties', {
|
||||||
|
collectionIndex: collectionIndex,
|
||||||
|
collection: collection,
|
||||||
|
})
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</tippy>
|
</tippy>
|
||||||
@@ -149,7 +164,14 @@
|
|||||||
@edit-folder="emit('edit-folder', $event)"
|
@edit-folder="emit('edit-folder', $event)"
|
||||||
@edit-request="emit('edit-request', $event)"
|
@edit-request="emit('edit-request', $event)"
|
||||||
@duplicate-request="emit('duplicate-request', $event)"
|
@duplicate-request="emit('duplicate-request', $event)"
|
||||||
|
@edit-properties="
|
||||||
|
emit('edit-properties', {
|
||||||
|
collectionIndex: `${folderPath}/${String(subFolderIndex)}`,
|
||||||
|
collection: subFolder,
|
||||||
|
})
|
||||||
|
"
|
||||||
@select="emit('select', $event)"
|
@select="emit('select', $event)"
|
||||||
|
@select-request="$emit('select-request', $event)"
|
||||||
/>
|
/>
|
||||||
<CollectionsGraphqlRequest
|
<CollectionsGraphqlRequest
|
||||||
v-for="(request, index) in folder.requests"
|
v-for="(request, index) in folder.requests"
|
||||||
@@ -165,6 +187,7 @@
|
|||||||
@edit-request="emit('edit-request', $event)"
|
@edit-request="emit('edit-request', $event)"
|
||||||
@duplicate-request="emit('duplicate-request', $event)"
|
@duplicate-request="emit('duplicate-request', $event)"
|
||||||
@select="emit('select', $event)"
|
@select="emit('select', $event)"
|
||||||
|
@select-request="$emit('select-request', $event)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
@@ -198,6 +221,7 @@ import IconMoreVertical from "~icons/lucide/more-vertical"
|
|||||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||||
import IconFolder from "~icons/lucide/folder"
|
import IconFolder from "~icons/lucide/folder"
|
||||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||||
|
import IconSettings2 from "~icons/lucide/settings-2"
|
||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { useColorMode } from "@composables/theming"
|
import { useColorMode } from "@composables/theming"
|
||||||
@@ -205,6 +229,8 @@ import { removeGraphqlFolder, moveGraphqlRequest } from "~/newstore/collections"
|
|||||||
import { computed, ref } from "vue"
|
import { computed, ref } from "vue"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { GQLTabService } from "~/services/tab/graphql"
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
|
import { Picked } from "~/helpers/types/HoppPicked"
|
||||||
|
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
@@ -212,16 +238,16 @@ const colorMode = useColorMode()
|
|||||||
|
|
||||||
const tabs = useService(GQLTabService)
|
const tabs = useService(GQLTabService)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps<{
|
||||||
picked: { type: Object, default: null },
|
picked: Picked
|
||||||
// Whether the request is in a selectable mode (activates 'select' event)
|
// Whether the request is in a selectable mode (activates 'select' event)
|
||||||
saveRequest: { type: Boolean, default: false },
|
saveRequest: boolean
|
||||||
folder: { type: Object, default: () => ({}) },
|
folder: HoppCollection<HoppGQLRequest>
|
||||||
folderIndex: { type: Number, default: null },
|
folderIndex: number
|
||||||
collectionIndex: { type: Number, default: null },
|
collectionIndex: number
|
||||||
folderPath: { type: String, default: null },
|
folderPath: string
|
||||||
isFiltered: Boolean,
|
isFiltered: boolean
|
||||||
})
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
"select",
|
"select",
|
||||||
@@ -230,6 +256,8 @@ const emit = defineEmits([
|
|||||||
"add-folder",
|
"add-folder",
|
||||||
"edit-folder",
|
"edit-folder",
|
||||||
"duplicate-request",
|
"duplicate-request",
|
||||||
|
"edit-properties",
|
||||||
|
"select-request",
|
||||||
])
|
])
|
||||||
|
|
||||||
// Template refs
|
// Template refs
|
||||||
|
|||||||
@@ -178,7 +178,12 @@ const isActive = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// TODO: Better types please
|
// TODO: Better types please
|
||||||
const emit = defineEmits(["select", "edit-request", "duplicate-request"])
|
const emit = defineEmits([
|
||||||
|
"select",
|
||||||
|
"edit-request",
|
||||||
|
"duplicate-request",
|
||||||
|
"select-request",
|
||||||
|
])
|
||||||
|
|
||||||
const dragging = ref(false)
|
const dragging = ref(false)
|
||||||
const confirmRemove = ref(false)
|
const confirmRemove = ref(false)
|
||||||
@@ -202,36 +207,11 @@ const selectRequest = () => {
|
|||||||
if (props.saveRequest) {
|
if (props.saveRequest) {
|
||||||
pick()
|
pick()
|
||||||
} else {
|
} else {
|
||||||
const possibleTab = tabs.getTabRefWithSaveContext({
|
emit("select-request", {
|
||||||
originLocation: "user-collection",
|
request: props.request,
|
||||||
folderPath: props.folderPath,
|
folderPath: props.folderPath,
|
||||||
requestIndex: props.requestIndex,
|
requestIndex: props.requestIndex,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Switch to that request if that request is open
|
|
||||||
if (possibleTab) {
|
|
||||||
tabs.setActiveTab(possibleTab.value.id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tabs.createNewTab({
|
|
||||||
saveContext: {
|
|
||||||
originLocation: "user-collection",
|
|
||||||
folderPath: props.folderPath,
|
|
||||||
requestIndex: props.requestIndex,
|
|
||||||
},
|
|
||||||
request: cloneDeep(
|
|
||||||
makeGQLRequest({
|
|
||||||
name: props.request.name,
|
|
||||||
url: props.request.url,
|
|
||||||
query: props.request.query,
|
|
||||||
headers: props.request.headers,
|
|
||||||
variables: props.request.variables,
|
|
||||||
auth: props.request.auth,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
isDirty: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,9 @@
|
|||||||
@edit-request="editRequest($event)"
|
@edit-request="editRequest($event)"
|
||||||
@duplicate-request="duplicateRequest($event)"
|
@duplicate-request="duplicateRequest($event)"
|
||||||
@select-collection="$emit('use-collection', collection)"
|
@select-collection="$emit('use-collection', collection)"
|
||||||
|
@edit-properties="editProperties($event)"
|
||||||
@select="$emit('select', $event)"
|
@select="$emit('select', $event)"
|
||||||
|
@select-request="selectRequest($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
@@ -142,16 +144,25 @@
|
|||||||
v-if="showModalImportExport"
|
v-if="showModalImportExport"
|
||||||
@hide-modal="displayModalImportExport(false)"
|
@hide-modal="displayModalImportExport(false)"
|
||||||
/>
|
/>
|
||||||
|
<CollectionsProperties
|
||||||
|
:show="showModalEditProperties"
|
||||||
|
:editing-properties="editingProperties"
|
||||||
|
@hide-modal="displayModalEditProperties(false)"
|
||||||
|
@set-collection-properties="setCollectionProperties"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue"
|
import { nextTick, ref } from "vue"
|
||||||
import { clone, cloneDeep } from "lodash-es"
|
import { clone, cloneDeep } from "lodash-es"
|
||||||
import {
|
import {
|
||||||
graphqlCollections$,
|
graphqlCollections$,
|
||||||
addGraphqlFolder,
|
addGraphqlFolder,
|
||||||
saveGraphqlRequestAs,
|
saveGraphqlRequestAs,
|
||||||
|
cascaseParentCollectionForHeaderAuth,
|
||||||
|
editGraphqlCollection,
|
||||||
|
editGraphqlFolder,
|
||||||
} from "~/newstore/collections"
|
} from "~/newstore/collections"
|
||||||
import IconPlus from "~icons/lucide/plus"
|
import IconPlus from "~icons/lucide/plus"
|
||||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||||
@@ -163,8 +174,14 @@ import { platform } from "~/platform"
|
|||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { GQLTabService } from "~/services/tab/graphql"
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
|
import {
|
||||||
|
HoppCollection,
|
||||||
|
HoppGQLRequest,
|
||||||
|
makeGQLRequest,
|
||||||
|
} from "@hoppscotch/data"
|
||||||
import { Picked } from "~/helpers/types/HoppPicked"
|
import { Picked } from "~/helpers/types/HoppPicked"
|
||||||
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
|
import { updateInheritedPropertiesForAffectedRequests } from "~/helpers/collection/collection"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
@@ -185,6 +202,7 @@ const showModalAddRequest = ref(false)
|
|||||||
const showModalAddFolder = ref(false)
|
const showModalAddFolder = ref(false)
|
||||||
const showModalEditFolder = ref(false)
|
const showModalEditFolder = ref(false)
|
||||||
const showModalEditRequest = ref(false)
|
const showModalEditRequest = ref(false)
|
||||||
|
const showModalEditProperties = ref(false)
|
||||||
|
|
||||||
const editingCollection = ref<HoppCollection<HoppGQLRequest> | null>(null)
|
const editingCollection = ref<HoppCollection<HoppGQLRequest> | null>(null)
|
||||||
const editingCollectionIndex = ref<number | null>(null)
|
const editingCollectionIndex = ref<number | null>(null)
|
||||||
@@ -195,6 +213,18 @@ const editingFolderPath = ref("")
|
|||||||
const editingRequest = ref<HoppGQLRequest | null>(null)
|
const editingRequest = ref<HoppGQLRequest | null>(null)
|
||||||
const editingRequestIndex = ref<number | null>(null)
|
const editingRequestIndex = ref<number | null>(null)
|
||||||
|
|
||||||
|
const editingProperties = ref<{
|
||||||
|
collection: HoppCollection<HoppGQLRequest> | null
|
||||||
|
isRootCollection: boolean
|
||||||
|
path: string
|
||||||
|
inheritedProperties?: HoppInheritedProperty
|
||||||
|
}>({
|
||||||
|
collection: null,
|
||||||
|
isRootCollection: false,
|
||||||
|
path: "",
|
||||||
|
inheritedProperties: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
const filterText = ref("")
|
const filterText = ref("")
|
||||||
|
|
||||||
const filteredCollections = computed(() => {
|
const filteredCollections = computed(() => {
|
||||||
@@ -276,6 +306,12 @@ const displayModalEditRequest = (shouldDisplay: boolean) => {
|
|||||||
if (!shouldDisplay) resetSelectedData()
|
if (!shouldDisplay) resetSelectedData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const displayModalEditProperties = (show: boolean) => {
|
||||||
|
showModalEditProperties.value = show
|
||||||
|
|
||||||
|
if (!show) resetSelectedData()
|
||||||
|
}
|
||||||
|
|
||||||
const editCollection = (
|
const editCollection = (
|
||||||
collection: HoppCollection<HoppGQLRequest>,
|
collection: HoppCollection<HoppGQLRequest>,
|
||||||
collectionIndex: number
|
collectionIndex: number
|
||||||
@@ -302,6 +338,11 @@ const onAddRequest = ({
|
|||||||
|
|
||||||
saveGraphqlRequestAs(path, newRequest)
|
saveGraphqlRequestAs(path, newRequest)
|
||||||
|
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
path,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
|
||||||
tabs.createNewTab({
|
tabs.createNewTab({
|
||||||
saveContext: {
|
saveContext: {
|
||||||
originLocation: "user-collection",
|
originLocation: "user-collection",
|
||||||
@@ -310,6 +351,10 @@ const onAddRequest = ({
|
|||||||
},
|
},
|
||||||
request: newRequest,
|
request: newRequest,
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
|
inheritedProperties: {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
@@ -401,6 +446,128 @@ const duplicateRequest = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectRequest = ({
|
||||||
|
request,
|
||||||
|
folderPath,
|
||||||
|
requestIndex,
|
||||||
|
}: {
|
||||||
|
request: HoppGQLRequest
|
||||||
|
folderPath: string
|
||||||
|
requestIndex: number
|
||||||
|
}) => {
|
||||||
|
const possibleTab = tabs.getTabRefWithSaveContext({
|
||||||
|
originLocation: "user-collection",
|
||||||
|
folderPath: folderPath,
|
||||||
|
requestIndex: requestIndex,
|
||||||
|
})
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
folderPath,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
// Switch to that request if that request is open
|
||||||
|
if (possibleTab) {
|
||||||
|
tabs.setActiveTab(possibleTab.value.id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tabs.createNewTab({
|
||||||
|
saveContext: {
|
||||||
|
originLocation: "user-collection",
|
||||||
|
folderPath: folderPath,
|
||||||
|
requestIndex: requestIndex,
|
||||||
|
},
|
||||||
|
request: cloneDeep(
|
||||||
|
makeGQLRequest({
|
||||||
|
name: request.name,
|
||||||
|
url: request.url,
|
||||||
|
query: request.query,
|
||||||
|
headers: request.headers,
|
||||||
|
variables: request.variables,
|
||||||
|
auth: request.auth,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
isDirty: false,
|
||||||
|
inheritedProperties: {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the collection is already in the root
|
||||||
|
* @param id - path of the collection
|
||||||
|
* @returns boolean - true if the collection is already in the root
|
||||||
|
*/
|
||||||
|
const isAlreadyInRoot = (id: string) => {
|
||||||
|
const indexPath = id.split("/")
|
||||||
|
return indexPath.length === 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const editProperties = ({
|
||||||
|
collectionIndex,
|
||||||
|
collection,
|
||||||
|
}: {
|
||||||
|
collectionIndex: string | null
|
||||||
|
collection: HoppCollection<HoppGQLRequest> | null
|
||||||
|
}) => {
|
||||||
|
if (collectionIndex === null || collection === null) return
|
||||||
|
|
||||||
|
const parentIndex = collectionIndex.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
|
||||||
|
let inheritedProperties = {}
|
||||||
|
|
||||||
|
if (parentIndex) {
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
parentIndex,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
inheritedProperties = {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
} as HoppInheritedProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
editingProperties.value = {
|
||||||
|
collection,
|
||||||
|
isRootCollection: isAlreadyInRoot(collectionIndex),
|
||||||
|
path: collectionIndex,
|
||||||
|
inheritedProperties,
|
||||||
|
}
|
||||||
|
|
||||||
|
displayModalEditProperties(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const setCollectionProperties = (newCollection: {
|
||||||
|
collection: HoppCollection<HoppGQLRequest>
|
||||||
|
path: string
|
||||||
|
isRootCollection: boolean
|
||||||
|
}) => {
|
||||||
|
const { collection, path, isRootCollection } = newCollection
|
||||||
|
if (isRootCollection) {
|
||||||
|
editGraphqlCollection(parseInt(path), collection)
|
||||||
|
} else {
|
||||||
|
editGraphqlFolder(path, collection)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
path,
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
updateInheritedPropertiesForAffectedRequests(
|
||||||
|
path,
|
||||||
|
{
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
"graphql"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
displayModalEditProperties(false)
|
||||||
|
}
|
||||||
const resetSelectedData = () => {
|
const resetSelectedData = () => {
|
||||||
editingCollection.value = null
|
editingCollection.value = null
|
||||||
editingCollectionIndex.value = null
|
editingCollectionIndex.value = null
|
||||||
|
|||||||
@@ -679,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 } = cascaseParentCollectionForHeaderAuth(path)
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path, "rest")
|
||||||
|
|
||||||
tabs.createNewTab({
|
tabs.createNewTab({
|
||||||
request: newRequest,
|
request: newRequest,
|
||||||
@@ -1329,7 +1329,10 @@ 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 } = cascaseParentCollectionForHeaderAuth(folderPath)
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
folderPath,
|
||||||
|
"rest"
|
||||||
|
)
|
||||||
|
|
||||||
if (collectionsType.value.type === "team-collections") {
|
if (collectionsType.value.type === "team-collections") {
|
||||||
possibleTab = tabs.getTabRefWithSaveContext({
|
possibleTab = tabs.getTabRefWithSaveContext({
|
||||||
@@ -1402,7 +1405,8 @@ const dropRequest = (payload: {
|
|||||||
|
|
||||||
if (collectionsType.value.type === "my-collections" && folderPath) {
|
if (collectionsType.value.type === "my-collections" && folderPath) {
|
||||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
destinationCollectionIndex
|
destinationCollectionIndex,
|
||||||
|
"rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
possibleTab = tabs.getTabRefWithSaveContext({
|
possibleTab = tabs.getTabRefWithSaveContext({
|
||||||
@@ -1595,7 +1599,8 @@ const dropCollection = (payload: {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`
|
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
|
||||||
|
"rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
const inheritedProperty = {
|
const inheritedProperty = {
|
||||||
@@ -1605,7 +1610,8 @@ const dropCollection = (payload: {
|
|||||||
|
|
||||||
updateInheritedPropertiesForAffectedRequests(
|
updateInheritedPropertiesForAffectedRequests(
|
||||||
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
|
`${destinationCollectionIndex}/${totalFoldersOfDestinationCollection}`,
|
||||||
inheritedProperty
|
inheritedProperty,
|
||||||
|
"rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
draggingToRoot.value = false
|
draggingToRoot.value = false
|
||||||
@@ -1975,7 +1981,10 @@ const editProperties = (payload: {
|
|||||||
let inheritedProperties = {}
|
let inheritedProperties = {}
|
||||||
|
|
||||||
if (parentIndex) {
|
if (parentIndex) {
|
||||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(parentIndex)
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(
|
||||||
|
parentIndex,
|
||||||
|
"rest"
|
||||||
|
)
|
||||||
|
|
||||||
inheritedProperties = {
|
inheritedProperties = {
|
||||||
auth,
|
auth,
|
||||||
@@ -2005,13 +2014,17 @@ const setCollectionProperties = (newCollection: {
|
|||||||
editRESTFolder(path, collection)
|
editRESTFolder(path, collection)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path)
|
const { auth, headers } = cascaseParentCollectionForHeaderAuth(path, "rest")
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
updateInheritedPropertiesForAffectedRequests(path, {
|
updateInheritedPropertiesForAffectedRequests(
|
||||||
auth,
|
path,
|
||||||
headers,
|
{
|
||||||
})
|
auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
"rest"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
displayModalEditProperties(false)
|
displayModalEditProperties(false)
|
||||||
|
|||||||
@@ -37,6 +37,18 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
<HoppSmartItem
|
||||||
|
v-if="!isRootCollection"
|
||||||
|
label="Inherit"
|
||||||
|
:icon="authName === 'Inherit' ? IconCircleDot : IconCircle"
|
||||||
|
:active="authName === 'Inherit'"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
auth.authType = 'inherit'
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
label="Basic Auth"
|
label="Basic Auth"
|
||||||
:icon="authName === 'Basic Auth' ? IconCircleDot : IconCircle"
|
:icon="authName === 'Basic Auth' ? IconCircleDot : IconCircle"
|
||||||
@@ -149,6 +161,17 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="auth.authType === 'inherit'" class="p-4">
|
||||||
|
<span v-if="inheritedProperties?.auth">
|
||||||
|
Inherited
|
||||||
|
{{ 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
|
||||||
|
authorization
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div v-if="auth.authType === 'bearer'">
|
<div v-if="auth.authType === 'bearer'">
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
@@ -203,6 +226,8 @@ import { pluckRef } from "@composables/ref"
|
|||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { useColorMode } from "@composables/theming"
|
import { useColorMode } from "@composables/theming"
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
|
import { onMounted } from "vue"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
@@ -210,12 +235,24 @@ const colorMode = useColorMode()
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: HoppGQLAuth
|
modelValue: HoppGQLAuth
|
||||||
|
isCollectionProperty?: boolean
|
||||||
|
isRootCollection?: boolean
|
||||||
|
inheritedProperties?: HoppInheritedProperty
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "update:modelValue", value: HoppGQLAuth): void
|
(e: "update:modelValue", value: HoppGQLAuth): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.isRootCollection && auth.value.authType === "inherit") {
|
||||||
|
auth.value = {
|
||||||
|
authType: "none",
|
||||||
|
authActive: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const auth = useVModel(props, "modelValue", emit)
|
const auth = useVModel(props, "modelValue", emit)
|
||||||
|
|
||||||
const AUTH_KEY_NAME = {
|
const AUTH_KEY_NAME = {
|
||||||
@@ -224,12 +261,20 @@ const AUTH_KEY_NAME = {
|
|||||||
"oauth-2": "OAuth 2.0",
|
"oauth-2": "OAuth 2.0",
|
||||||
"api-key": "API key",
|
"api-key": "API key",
|
||||||
none: "None",
|
none: "None",
|
||||||
|
inherit: "Inherit",
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const authType = pluckRef(auth, "authType")
|
const authType = pluckRef(auth, "authType")
|
||||||
|
|
||||||
const authName = computed(() =>
|
const authName = computed(() =>
|
||||||
AUTH_KEY_NAME[authType.value] ? AUTH_KEY_NAME[authType.value] : "None"
|
AUTH_KEY_NAME[authType.value] ? AUTH_KEY_NAME[authType.value] : "None"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const getAuthName = (type: HoppGQLAuth["authType"] | undefined) => {
|
||||||
|
if (!type) return "None"
|
||||||
|
return AUTH_KEY_NAME[type] ? AUTH_KEY_NAME[type] : "None"
|
||||||
|
}
|
||||||
|
|
||||||
const authActive = pluckRef(auth, "authActive")
|
const authActive = pluckRef(auth, "authActive")
|
||||||
|
|
||||||
const clearContent = () => {
|
const clearContent = () => {
|
||||||
|
|||||||
@@ -215,6 +215,60 @@
|
|||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
|
|
||||||
|
<draggable
|
||||||
|
v-model="inheritedProperties"
|
||||||
|
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="
|
||||||
|
header.source === 'auth' ? mask(header) : header.header.value
|
||||||
|
"
|
||||||
|
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||||
|
readonly
|
||||||
|
/>
|
||||||
|
<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 v-else class="aspect-square w-[2.05rem]"></span>
|
||||||
|
<span>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:icon="IconInfo"
|
||||||
|
:title="`This header is inherited from Parent Collection ${
|
||||||
|
header.inheritedFrom ?? ''
|
||||||
|
}`"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</draggable>
|
||||||
|
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
v-if="workingHeaders.length === 0"
|
v-if="workingHeaders.length === 0"
|
||||||
:src="`/images/states/${colorMode.value}/add_category.svg`"
|
:src="`/images/states/${colorMode.value}/add_category.svg`"
|
||||||
@@ -247,7 +301,7 @@ import IconArrowUpRight from "~icons/lucide/arrow-up-right"
|
|||||||
import IconLock from "~icons/lucide/lock"
|
import IconLock from "~icons/lucide/lock"
|
||||||
import IconEye from "~icons/lucide/eye"
|
import IconEye from "~icons/lucide/eye"
|
||||||
import IconEyeOff from "~icons/lucide/eye-off"
|
import IconEyeOff from "~icons/lucide/eye-off"
|
||||||
|
import IconInfo from "~icons/lucide/info"
|
||||||
import { computed, reactive, ref, watch } from "vue"
|
import { computed, reactive, ref, watch } from "vue"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
@@ -272,13 +326,18 @@ import { objRemoveKey } from "~/helpers/functional/object"
|
|||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { HoppGQLHeader } from "~/helpers/graphql"
|
import { HoppGQLHeader } from "~/helpers/graphql"
|
||||||
import { throwError } from "~/helpers/functional/error"
|
import { throwError } from "~/helpers/functional/error"
|
||||||
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
|
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
// v-model integration with props and emit
|
// v-model integration with props and emit
|
||||||
const props = defineProps<{ modelValue: HoppGQLRequest }>()
|
const props = defineProps<{
|
||||||
|
modelValue: HoppGQLRequest
|
||||||
|
isCollectionProperty?: boolean
|
||||||
|
inheritedProperties?: HoppInheritedProperty
|
||||||
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "update:modelValue", value: HoppGQLRequest): void
|
(e: "update:modelValue", value: HoppGQLRequest): void
|
||||||
@@ -565,6 +624,64 @@ const computedHeaders = computed(() =>
|
|||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const inheritedProperties = computed(() => {
|
||||||
|
if (!props.inheritedProperties?.auth || !props.inheritedProperties.headers)
|
||||||
|
return []
|
||||||
|
|
||||||
|
//filter out headers that are already in the request headers
|
||||||
|
|
||||||
|
const inheritedHeaders = props.inheritedProperties.headers.filter(
|
||||||
|
(header) =>
|
||||||
|
!request.value.headers.some(
|
||||||
|
(requestHeader) => requestHeader.key === header.key
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const headers = inheritedHeaders.map((header, index) => ({
|
||||||
|
inheritedFrom: props.inheritedProperties?.headers[index].parentName,
|
||||||
|
source: "headers",
|
||||||
|
id: `header-${index}`,
|
||||||
|
header: {
|
||||||
|
key: header.inheritedHeader?.key,
|
||||||
|
value: header.inheritedHeader?.value,
|
||||||
|
active: header.inheritedHeader?.active,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
let auth = [] as {
|
||||||
|
inheritedFrom: string
|
||||||
|
source: "auth"
|
||||||
|
id: string
|
||||||
|
header: {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
active: boolean
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
|
||||||
|
const computedAuthHeader = getComputedAuthHeaders(
|
||||||
|
request.value,
|
||||||
|
props.inheritedProperties.auth.inheritedAuth
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
if (
|
||||||
|
computedAuthHeader &&
|
||||||
|
request.value.auth.authType === "inherit" &&
|
||||||
|
request.value.auth.authActive
|
||||||
|
) {
|
||||||
|
auth = [
|
||||||
|
{
|
||||||
|
inheritedFrom: props.inheritedProperties?.auth.parentName,
|
||||||
|
source: "auth",
|
||||||
|
id: `header-auth`,
|
||||||
|
header: computedAuthHeader,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...headers, ...auth]
|
||||||
|
})
|
||||||
|
|
||||||
const masking = ref(true)
|
const masking = ref(true)
|
||||||
|
|
||||||
const toggleMask = () => {
|
const toggleMask = () => {
|
||||||
|
|||||||
@@ -34,10 +34,16 @@
|
|||||||
:label="`${t('tab.headers')}`"
|
:label="`${t('tab.headers')}`"
|
||||||
:info="activeGQLHeadersCount === 0 ? null : `${activeGQLHeadersCount}`"
|
:info="activeGQLHeadersCount === 0 ? null : `${activeGQLHeadersCount}`"
|
||||||
>
|
>
|
||||||
<GraphqlHeaders v-model="request" />
|
<GraphqlHeaders
|
||||||
|
v-model="request"
|
||||||
|
:inherited-properties="inheritedProperties"
|
||||||
|
/>
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab :id="'authorization'" :label="`${t('tab.authorization')}`">
|
<HoppSmartTab :id="'authorization'" :label="`${t('tab.authorization')}`">
|
||||||
<GraphqlAuthorization v-model="request.auth" />
|
<GraphqlAuthorization
|
||||||
|
v-model="request.auth"
|
||||||
|
:inherited-properties="inheritedProperties"
|
||||||
|
/>
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
</HoppSmartTabs>
|
</HoppSmartTabs>
|
||||||
<CollectionsSaveRequest
|
<CollectionsSaveRequest
|
||||||
@@ -69,6 +75,7 @@ import { useService } from "dioc/vue"
|
|||||||
import { InterceptorService } from "~/services/interceptor.service"
|
import { InterceptorService } from "~/services/interceptor.service"
|
||||||
import { editGraphqlRequest } from "~/newstore/collections"
|
import { editGraphqlRequest } from "~/newstore/collections"
|
||||||
import { GQLTabService } from "~/services/tab/graphql"
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
|
|
||||||
const VALID_GQL_OPERATIONS = [
|
const VALID_GQL_OPERATIONS = [
|
||||||
"query",
|
"query",
|
||||||
@@ -93,6 +100,7 @@ const props = withDefaults(
|
|||||||
response?: GQLResponseEvent[] | null
|
response?: GQLResponseEvent[] | null
|
||||||
optionTab?: GQLOptionTabs
|
optionTab?: GQLOptionTabs
|
||||||
tabId: string
|
tabId: string
|
||||||
|
inheritedProperties?: HoppInheritedProperty
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
response: null,
|
response: null,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
v-model="tab.document.request"
|
v-model="tab.document.request"
|
||||||
v-model:response="tab.document.response"
|
v-model:response="tab.document.response"
|
||||||
v-model:option-tab="tab.document.optionTabPreference"
|
v-model:option-tab="tab.document.optionTabPreference"
|
||||||
|
v-model:inherited-properties="tab.document.inheritedProperties"
|
||||||
:tab-id="tab.id"
|
:tab-id="tab.id"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -231,7 +231,6 @@ 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)
|
|
||||||
auth.value = {
|
auth.value = {
|
||||||
authType: "none",
|
authType: "none",
|
||||||
authActive: true,
|
authActive: true,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import * as E from "fp-ts/Either"
|
|||||||
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 "../types/HoppInheritedProperties"
|
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||||
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve save context on reorder
|
* Resolve save context on reorder
|
||||||
@@ -111,9 +112,11 @@ export function updateSaveContextForAffectedRequests(
|
|||||||
|
|
||||||
export function updateInheritedPropertiesForAffectedRequests(
|
export function updateInheritedPropertiesForAffectedRequests(
|
||||||
path: string,
|
path: string,
|
||||||
inheritedProperties: HoppInheritedProperty
|
inheritedProperties: HoppInheritedProperty,
|
||||||
|
type: "rest" | "graphql"
|
||||||
) {
|
) {
|
||||||
const tabService = getService(RESTTabService)
|
const tabService =
|
||||||
|
type === "rest" ? getService(RESTTabService) : getService(GQLTabService)
|
||||||
const tabs = tabService.getTabsRefTo((tab) => {
|
const tabs = tabService.getTabsRefTo((tab) => {
|
||||||
return (
|
return (
|
||||||
tab.document.saveContext?.originLocation === "user-collection" &&
|
tab.document.saveContext?.originLocation === "user-collection" &&
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const getDefaultGQLRequest = (): HoppGQLRequest => ({
|
|||||||
}`,
|
}`,
|
||||||
query: DEFAULT_QUERY,
|
query: DEFAULT_QUERY,
|
||||||
auth: {
|
auth: {
|
||||||
authType: "none",
|
authType: "inherit",
|
||||||
authActive: true,
|
authActive: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { HoppGQLRequest } from "@hoppscotch/data"
|
import { HoppGQLRequest } from "@hoppscotch/data"
|
||||||
import { GQLResponseEvent } from "./connection"
|
import { GQLResponseEvent } from "./connection"
|
||||||
import { GQLOptionTabs } from "~/components/graphql/RequestOptions.vue"
|
import { GQLOptionTabs } from "~/components/graphql/RequestOptions.vue"
|
||||||
|
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||||
|
|
||||||
export type HoppGQLSaveContext =
|
export type HoppGQLSaveContext =
|
||||||
| {
|
| {
|
||||||
@@ -73,4 +74,10 @@ export type HoppGQLDocument = {
|
|||||||
* Options tab preference for the current tab's document
|
* Options tab preference for the current tab's document
|
||||||
*/
|
*/
|
||||||
optionTabPreference?: GQLOptionTabs
|
optionTabPreference?: GQLOptionTabs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The inherited properties from the parent collection
|
||||||
|
* (if any)
|
||||||
|
*/
|
||||||
|
inheritedProperties?: HoppInheritedProperty
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,12 @@ export function navigateToFolderWithIndexPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function cascaseParentCollectionForHeaderAuth(
|
export function cascaseParentCollectionForHeaderAuth(
|
||||||
folderPath: string | undefined
|
folderPath: string | undefined,
|
||||||
|
type: "rest" | "graphql"
|
||||||
) {
|
) {
|
||||||
|
const collectionStore =
|
||||||
|
type === "rest" ? restCollectionStore : graphqlCollectionStore
|
||||||
|
|
||||||
let auth: HoppInheritedProperty["auth"] = {
|
let auth: HoppInheritedProperty["auth"] = {
|
||||||
parentID: folderPath ?? "",
|
parentID: folderPath ?? "",
|
||||||
parentName: "",
|
parentName: "",
|
||||||
@@ -87,7 +91,7 @@ export function cascaseParentCollectionForHeaderAuth(
|
|||||||
// 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'
|
||||||
for (let i = 0; i < path.length; i++) {
|
for (let i = 0; i < path.length; i++) {
|
||||||
const parentFolder = navigateToFolderWithIndexPath(
|
const parentFolder = navigateToFolderWithIndexPath(
|
||||||
restCollectionStore.value.state,
|
collectionStore.value.state,
|
||||||
[...path.slice(0, i + 1)] // Create a copy of the path array
|
[...path.slice(0, i + 1)] // Create a copy of the path array
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export function translateToNewGQLCollection(
|
|||||||
const folders = (x.folders ?? []).map(translateToNewGQLCollection)
|
const folders = (x.folders ?? []).map(translateToNewGQLCollection)
|
||||||
const requests = (x.requests ?? []).map(translateToGQLRequest)
|
const requests = (x.requests ?? []).map(translateToGQLRequest)
|
||||||
|
|
||||||
const auth = x.auth ?? "None"
|
const auth = x.auth ?? { authType: "inherit", authActive: true }
|
||||||
const headers = x.headers ?? []
|
const headers = x.headers ?? []
|
||||||
|
|
||||||
const obj = makeCollection<HoppGQLRequest>({
|
const obj = makeCollection<HoppGQLRequest>({
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export {
|
|||||||
HoppGQLAuthBearer,
|
HoppGQLAuthBearer,
|
||||||
HoppGQLAuthNone,
|
HoppGQLAuthNone,
|
||||||
HoppGQLAuthOAuth2,
|
HoppGQLAuthOAuth2,
|
||||||
|
HoppGQLAuthInherit,
|
||||||
} from "./v/2"
|
} from "./v/2"
|
||||||
|
|
||||||
export const GQL_REQ_SCHEMA_VERSION = 2
|
export const GQL_REQ_SCHEMA_VERSION = 2
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { defineVersion } from "verzod"
|
|||||||
import { GQLHeader, V1_SCHEMA } from "./1"
|
import { GQLHeader, V1_SCHEMA } from "./1"
|
||||||
|
|
||||||
export const HoppGQLAuthNone = z.object({
|
export const HoppGQLAuthNone = z.object({
|
||||||
authType: z.literal("none")
|
authType: z.literal("none"),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type HoppGQLAuthNone = z.infer<typeof HoppGQLAuthNone>
|
export type HoppGQLAuthNone = z.infer<typeof HoppGQLAuthNone>
|
||||||
@@ -12,7 +12,7 @@ export const HoppGQLAuthBasic = z.object({
|
|||||||
authType: z.literal("basic"),
|
authType: z.literal("basic"),
|
||||||
|
|
||||||
username: z.string().catch(""),
|
username: z.string().catch(""),
|
||||||
password: z.string().catch("")
|
password: z.string().catch(""),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type HoppGQLAuthBasic = z.infer<typeof HoppGQLAuthBasic>
|
export type HoppGQLAuthBasic = z.infer<typeof HoppGQLAuthBasic>
|
||||||
@@ -20,7 +20,7 @@ export type HoppGQLAuthBasic = z.infer<typeof HoppGQLAuthBasic>
|
|||||||
export const HoppGQLAuthBearer = z.object({
|
export const HoppGQLAuthBearer = z.object({
|
||||||
authType: z.literal("bearer"),
|
authType: z.literal("bearer"),
|
||||||
|
|
||||||
token: z.string().catch("")
|
token: z.string().catch(""),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type HoppGQLAuthBearer = z.infer<typeof HoppGQLAuthBearer>
|
export type HoppGQLAuthBearer = z.infer<typeof HoppGQLAuthBearer>
|
||||||
@@ -33,7 +33,7 @@ export const HoppGQLAuthOAuth2 = z.object({
|
|||||||
authURL: z.string().catch(""),
|
authURL: z.string().catch(""),
|
||||||
accessTokenURL: z.string().catch(""),
|
accessTokenURL: z.string().catch(""),
|
||||||
clientID: z.string().catch(""),
|
clientID: z.string().catch(""),
|
||||||
scope: z.string().catch("")
|
scope: z.string().catch(""),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type HoppGQLAuthOAuth2 = z.infer<typeof HoppGQLAuthOAuth2>
|
export type HoppGQLAuthOAuth2 = z.infer<typeof HoppGQLAuthOAuth2>
|
||||||
@@ -43,22 +43,31 @@ export const HoppGQLAuthAPIKey = z.object({
|
|||||||
|
|
||||||
key: z.string().catch(""),
|
key: z.string().catch(""),
|
||||||
value: z.string().catch(""),
|
value: z.string().catch(""),
|
||||||
addTo: z.string().catch("Headers")
|
addTo: z.string().catch("Headers"),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type HoppGQLAuthAPIKey = z.infer<typeof HoppGQLAuthAPIKey>
|
export type HoppGQLAuthAPIKey = z.infer<typeof HoppGQLAuthAPIKey>
|
||||||
|
|
||||||
export const HoppGQLAuth = z.discriminatedUnion("authType", [
|
export const HoppGQLAuthInherit = z.object({
|
||||||
HoppGQLAuthNone,
|
authType: z.literal("inherit"),
|
||||||
HoppGQLAuthBasic,
|
})
|
||||||
HoppGQLAuthBearer,
|
|
||||||
HoppGQLAuthOAuth2,
|
export type HoppGQLAuthInherit = z.infer<typeof HoppGQLAuthInherit>
|
||||||
HoppGQLAuthAPIKey
|
|
||||||
]).and(
|
export const HoppGQLAuth = z
|
||||||
z.object({
|
.discriminatedUnion("authType", [
|
||||||
authActive: z.boolean()
|
HoppGQLAuthNone,
|
||||||
})
|
HoppGQLAuthBasic,
|
||||||
)
|
HoppGQLAuthBearer,
|
||||||
|
HoppGQLAuthOAuth2,
|
||||||
|
HoppGQLAuthAPIKey,
|
||||||
|
HoppGQLAuthInherit,
|
||||||
|
])
|
||||||
|
.and(
|
||||||
|
z.object({
|
||||||
|
authActive: z.boolean(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
export type HoppGQLAuth = z.infer<typeof HoppGQLAuth>
|
export type HoppGQLAuth = z.infer<typeof HoppGQLAuth>
|
||||||
|
|
||||||
@@ -72,7 +81,7 @@ const V2_SCHEMA = z.object({
|
|||||||
query: z.string(),
|
query: z.string(),
|
||||||
variables: z.string(),
|
variables: z.string(),
|
||||||
|
|
||||||
auth: HoppGQLAuth
|
auth: HoppGQLAuth,
|
||||||
})
|
})
|
||||||
|
|
||||||
export default defineVersion({
|
export default defineVersion({
|
||||||
@@ -85,7 +94,7 @@ export default defineVersion({
|
|||||||
auth: {
|
auth: {
|
||||||
authActive: true,
|
authActive: true,
|
||||||
authType: "none",
|
authType: "none",
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user