Compare commits
1 Commits
fix/shared
...
fix/gql-hi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d28bc580c6 |
@@ -676,16 +676,9 @@ export const INFRA_CONFIG_RESET_FAILED = 'infra_config/reset_failed' as const;
|
|||||||
*/
|
*/
|
||||||
export const INFRA_CONFIG_INVALID_INPUT = 'infra_config/invalid_input' as const;
|
export const INFRA_CONFIG_INVALID_INPUT = 'infra_config/invalid_input' as const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Infra Config service (auth provider/mailer/audit logs) not configured
|
|
||||||
* (InfraConfigService)
|
|
||||||
*/
|
|
||||||
export const INFRA_CONFIG_SERVICE_NOT_CONFIGURED =
|
|
||||||
'infra_config/service_not_configured' as const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error message for when the database table does not exist
|
* Error message for when the database table does not exist
|
||||||
* (InfraConfigService)
|
* (InfraConfigService)
|
||||||
*/
|
*/
|
||||||
export const DATABASE_TABLE_NOT_EXIST =
|
export const DATABASE_TABLE_NOT_EXIST =
|
||||||
'Database migration not found. Please check the documentation for assistance: https://docs.hoppscotch.io/documentation/self-host/community-edition/install-and-build#running-migrations';
|
'Database migration not performed. Please check the FAQ for assistance: https://docs.hoppscotch.io/support/getting-started/faq';
|
||||||
|
|||||||
@@ -15,13 +15,11 @@ import {
|
|||||||
INFRA_CONFIG_NOT_LISTED,
|
INFRA_CONFIG_NOT_LISTED,
|
||||||
INFRA_CONFIG_RESET_FAILED,
|
INFRA_CONFIG_RESET_FAILED,
|
||||||
INFRA_CONFIG_UPDATE_FAILED,
|
INFRA_CONFIG_UPDATE_FAILED,
|
||||||
INFRA_CONFIG_SERVICE_NOT_CONFIGURED,
|
|
||||||
} from 'src/errors';
|
} from 'src/errors';
|
||||||
import { throwErr, validateEmail, validateSMTPUrl } from 'src/utils';
|
import { throwErr, validateEmail, validateSMTPUrl } from 'src/utils';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { ServiceStatus, stopApp } from './helper';
|
import { ServiceStatus, stopApp } from './helper';
|
||||||
import { EnableAndDisableSSOArgs, InfraConfigArgs } from './input-args';
|
import { EnableAndDisableSSOArgs, InfraConfigArgs } from './input-args';
|
||||||
import { AuthProvider } from 'src/auth/helper';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InfraConfigService implements OnModuleInit {
|
export class InfraConfigService implements OnModuleInit {
|
||||||
@@ -126,7 +124,7 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
cast(dbInfraConfig: DBInfraConfig) {
|
cast(dbInfraConfig: DBInfraConfig) {
|
||||||
return <InfraConfig>{
|
return <InfraConfig>{
|
||||||
name: dbInfraConfig.name,
|
name: dbInfraConfig.name,
|
||||||
value: dbInfraConfig.value ?? '',
|
value: dbInfraConfig.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,38 +182,6 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the service is configured or not
|
|
||||||
* @param service Service can be Auth Provider, Mailer, Audit Log etc.
|
|
||||||
* @returns Either true or false
|
|
||||||
*/
|
|
||||||
isServiceConfigured(service: AuthProvider) {
|
|
||||||
switch (service) {
|
|
||||||
case AuthProvider.GOOGLE:
|
|
||||||
return (
|
|
||||||
this.configService.get<string>('INFRA.GOOGLE_CLIENT_ID') &&
|
|
||||||
this.configService.get<string>('INFRA.GOOGLE_CLIENT_SECRET')
|
|
||||||
);
|
|
||||||
case AuthProvider.GITHUB:
|
|
||||||
return (
|
|
||||||
this.configService.get<string>('INFRA.GITHUB_CLIENT_ID') &&
|
|
||||||
!this.configService.get<string>('INFRA.GITHUB_CLIENT_SECRET')
|
|
||||||
);
|
|
||||||
case AuthProvider.MICROSOFT:
|
|
||||||
return (
|
|
||||||
this.configService.get<string>('INFRA.MICROSOFT_CLIENT_ID') &&
|
|
||||||
!this.configService.get<string>('INFRA.MICROSOFT_CLIENT_SECRET')
|
|
||||||
);
|
|
||||||
case AuthProvider.EMAIL:
|
|
||||||
return (
|
|
||||||
this.configService.get<string>('INFRA.MAILER_SMTP_URL') &&
|
|
||||||
this.configService.get<string>('INFRA.MAILER_ADDRESS_FROM')
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable or Disable SSO for login/signup
|
* Enable or Disable SSO for login/signup
|
||||||
* @param provider Auth Provider to enable or disable
|
* @param provider Auth Provider to enable or disable
|
||||||
@@ -229,21 +195,15 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
|
|
||||||
let updatedAuthProviders = allowedAuthProviders;
|
let updatedAuthProviders = allowedAuthProviders;
|
||||||
|
|
||||||
for (let i = 0; i < providerInfo.length; i++) {
|
providerInfo.forEach(({ provider, status }) => {
|
||||||
const { provider, status } = providerInfo[i];
|
|
||||||
|
|
||||||
if (status === ServiceStatus.ENABLE) {
|
if (status === ServiceStatus.ENABLE) {
|
||||||
const isConfigured = this.isServiceConfigured(provider);
|
|
||||||
if (!isConfigured) {
|
|
||||||
throwErr(INFRA_CONFIG_SERVICE_NOT_CONFIGURED);
|
|
||||||
}
|
|
||||||
updatedAuthProviders.push(provider);
|
updatedAuthProviders.push(provider);
|
||||||
} else if (status === ServiceStatus.DISABLE) {
|
} else if (status === ServiceStatus.DISABLE) {
|
||||||
updatedAuthProviders = updatedAuthProviders.filter(
|
updatedAuthProviders = updatedAuthProviders.filter(
|
||||||
(p) => p !== provider,
|
(p) => p !== provider,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
updatedAuthProviders = [...new Set(updatedAuthProviders)];
|
updatedAuthProviders = [...new Set(updatedAuthProviders)];
|
||||||
|
|
||||||
@@ -326,9 +286,6 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the values of the InfraConfigs
|
|
||||||
*/
|
|
||||||
validateEnvValues(
|
validateEnvValues(
|
||||||
infraConfigs: {
|
infraConfigs: {
|
||||||
name: InfraConfigEnumForClient | InfraConfigEnum;
|
name: InfraConfigEnumForClient | InfraConfigEnum;
|
||||||
@@ -345,24 +302,6 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
const isValidEmail = validateEmail(infraConfigs[i].value);
|
const isValidEmail = validateEmail(infraConfigs[i].value);
|
||||||
if (!isValidEmail) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
if (!isValidEmail) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
||||||
break;
|
break;
|
||||||
case InfraConfigEnumForClient.GOOGLE_CLIENT_ID:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.GOOGLE_CLIENT_SECRET:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.GITHUB_CLIENT_ID:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.GITHUB_CLIENT_SECRET:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.MICROSOFT_CLIENT_ID:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.MICROSOFT_CLIENT_SECRET:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
"generate_token": "Generate Token",
|
"generate_token": "Generate Token",
|
||||||
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
||||||
"include_in_url": "Include in URL",
|
"include_in_url": "Include in URL",
|
||||||
"inherited_from": "Inherited {auth} from parent collection {collection} ",
|
"inherited_from": "Inherited from {auth} from Parent Collection {collection} ",
|
||||||
"learn": "Learn how",
|
"learn": "Learn how",
|
||||||
"oauth": {
|
"oauth": {
|
||||||
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
||||||
@@ -295,7 +295,6 @@
|
|||||||
"incorrect_email": "Incorrect email",
|
"incorrect_email": "Incorrect email",
|
||||||
"invalid_link": "Invalid link",
|
"invalid_link": "Invalid link",
|
||||||
"invalid_link_description": "The link you clicked is invalid or expired.",
|
"invalid_link_description": "The link you clicked is invalid or expired.",
|
||||||
"invalid_embed_link": "The embed does not exist or is invalid.",
|
|
||||||
"json_parsing_failed": "Invalid JSON",
|
"json_parsing_failed": "Invalid JSON",
|
||||||
"json_prettify_invalid_body": "Couldn't prettify an invalid body, solve json syntax errors and try again",
|
"json_prettify_invalid_body": "Couldn't prettify an invalid body, solve json syntax errors and try again",
|
||||||
"network_error": "There seems to be a network error. Please try again.",
|
"network_error": "There seems to be a network error. Please try again.",
|
||||||
@@ -314,12 +313,10 @@
|
|||||||
"export": {
|
"export": {
|
||||||
"as_json": "Export as JSON",
|
"as_json": "Export as JSON",
|
||||||
"create_secret_gist": "Create secret Gist",
|
"create_secret_gist": "Create secret Gist",
|
||||||
"create_secret_gist_tooltip_text": "Export as secret Gist",
|
|
||||||
"failed": "Something went wrong while exporting",
|
"failed": "Something went wrong while exporting",
|
||||||
"secret_gist_success": "Successfully exported as secret Gist",
|
"gist_created": "Gist created",
|
||||||
"require_github": "Login with GitHub to create secret gist",
|
"require_github": "Login with GitHub to create secret gist",
|
||||||
"title": "Export",
|
"title": "Export"
|
||||||
"success": "Successfully exported"
|
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"all": "All",
|
"all": "All",
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { HoppCollection } from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { PropType, computed, ref } from "vue"
|
|
||||||
|
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { UrlSource } from "~/helpers/import-export/import/import-sources/UrlSource"
|
import { UrlSource } from "~/helpers/import-export/import/import-sources/UrlSource"
|
||||||
|
|
||||||
@@ -27,9 +24,11 @@ import {
|
|||||||
} from "~/helpers/import-export/import/importers"
|
} from "~/helpers/import-export/import/importers"
|
||||||
|
|
||||||
import { defineStep } from "~/composables/step-components"
|
import { defineStep } from "~/composables/step-components"
|
||||||
|
import { PropType, computed, ref } from "vue"
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
||||||
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||||
@@ -49,7 +48,7 @@ import { getTeamCollectionJSON } from "~/helpers/backend/helpers"
|
|||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { collectionsGistExporter } from "~/helpers/import-export/export/gistExport"
|
||||||
import { myCollectionsExporter } from "~/helpers/import-export/export/myCollections"
|
import { myCollectionsExporter } from "~/helpers/import-export/export/myCollections"
|
||||||
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
||||||
|
|
||||||
@@ -84,8 +83,6 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
const myCollections = useReadonlyStream(restCollections$, [])
|
|
||||||
|
|
||||||
const showImportFailedError = () => {
|
const showImportFailedError = () => {
|
||||||
toast.error(t("import.failed"))
|
toast.error(t("import.failed"))
|
||||||
}
|
}
|
||||||
@@ -471,13 +468,8 @@ const HoppGistCollectionsExporter: ImporterOrExporter = {
|
|||||||
icon: IconGithub,
|
icon: IconGithub,
|
||||||
disabled: !currentUser.value
|
disabled: !currentUser.value
|
||||||
? true
|
? true
|
||||||
: currentUser.value?.provider !== "github.com",
|
: currentUser.value.provider !== "github.com",
|
||||||
title:
|
title: t("export.create_secret_gist"),
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
currentUser?.value?.provider === "github.com"
|
|
||||||
? "export.create_secret_gist_tooltip_text"
|
|
||||||
: "export.require_github",
|
|
||||||
applicableTo: ["personal-workspace", "team-workspace"],
|
applicableTo: ["personal-workspace", "team-workspace"],
|
||||||
isLoading: isHoppGistCollectionExporterInProgress,
|
isLoading: isHoppGistCollectionExporterInProgress,
|
||||||
},
|
},
|
||||||
@@ -494,27 +486,13 @@ const HoppGistCollectionsExporter: ImporterOrExporter = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (E.isRight(collectionJSON)) {
|
if (E.isRight(collectionJSON)) {
|
||||||
if (!JSON.parse(collectionJSON.right).length) {
|
collectionsGistExporter(collectionJSON.right, accessToken)
|
||||||
isHoppGistCollectionExporterInProgress.value = false
|
|
||||||
return toast.error(t("error.no_collections_to_export"))
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await gistExporter(collectionJSON.right, accessToken)
|
|
||||||
|
|
||||||
if (E.isLeft(res)) {
|
|
||||||
toast.error(t("export.failed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(t("export.secret_gist_success"))
|
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_COLLECTION",
|
type: "HOPP_EXPORT_COLLECTION",
|
||||||
exporter: "gist",
|
exporter: "gist",
|
||||||
platform: "rest",
|
platform: "rest",
|
||||||
})
|
})
|
||||||
|
|
||||||
platform.io.openExternalLink(res.right)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isHoppGistCollectionExporterInProgress.value = false
|
isHoppGistCollectionExporterInProgress.value = false
|
||||||
@@ -582,6 +560,8 @@ const selectedTeamID = computed(() => {
|
|||||||
: undefined
|
: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const myCollections = useReadonlyStream(restCollections$, [])
|
||||||
|
|
||||||
const getCollectionJSON = async () => {
|
const getCollectionJSON = async () => {
|
||||||
if (
|
if (
|
||||||
props.collectionsType.type === "team-collections" &&
|
props.collectionsType.type === "team-collections" &&
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
@select="onSelect"
|
@select="onSelect"
|
||||||
@update-team="updateTeam"
|
@update-team="updateTeam"
|
||||||
@update-collection-type="updateCollectionType"
|
@update-collection-type="updateCollectionType"
|
||||||
@set-team-collection-adapter="teamCollectionAdapter = $event"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -87,7 +86,6 @@ import { platform } from "~/platform"
|
|||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
import { GQLTabService } from "~/services/tab/graphql"
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
import TeamCollectionAdapter from "~/helpers/teams/TeamCollectionAdapter"
|
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -95,8 +93,6 @@ const toast = useToast()
|
|||||||
const RESTTabs = useService(RESTTabService)
|
const RESTTabs = useService(RESTTabService)
|
||||||
const GQLTabs = useService(GQLTabService)
|
const GQLTabs = useService(GQLTabService)
|
||||||
|
|
||||||
const teamCollectionAdapter = ref<TeamCollectionAdapter>()
|
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||||
|
|
||||||
type CollectionType =
|
type CollectionType =
|
||||||
@@ -384,6 +380,7 @@ const saveRequestAs = async () => {
|
|||||||
platform: "rest",
|
platform: "rest",
|
||||||
workspaceType: "team",
|
workspaceType: "team",
|
||||||
})
|
})
|
||||||
|
|
||||||
pipe(
|
pipe(
|
||||||
updateTeamRequest(picked.value.requestID, data),
|
updateTeamRequest(picked.value.requestID, data),
|
||||||
TE.match(
|
TE.match(
|
||||||
@@ -391,31 +388,7 @@ const saveRequestAs = async () => {
|
|||||||
toast.error(`${getErrorMessage(err)}`)
|
toast.error(`${getErrorMessage(err)}`)
|
||||||
modalLoadingState.value = false
|
modalLoadingState.value = false
|
||||||
},
|
},
|
||||||
(result) => {
|
() => {
|
||||||
const { updateRequest } = result
|
|
||||||
|
|
||||||
RESTTabs.currentActiveTab.value.document = {
|
|
||||||
request: requestUpdated,
|
|
||||||
isDirty: false,
|
|
||||||
saveContext: {
|
|
||||||
originLocation: "team-collection",
|
|
||||||
requestID: updateRequest.id,
|
|
||||||
collectionID: updateRequest.collectionID,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (teamCollectionAdapter.value) {
|
|
||||||
const { auth, headers } =
|
|
||||||
teamCollectionAdapter.value.cascadeParentCollectionForHeaderAuth(
|
|
||||||
updateRequest.collectionID
|
|
||||||
)
|
|
||||||
|
|
||||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
|
||||||
auth,
|
|
||||||
headers,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modalLoadingState.value = false
|
modalLoadingState.value = false
|
||||||
requestSaved()
|
requestSaved()
|
||||||
}
|
}
|
||||||
@@ -543,18 +516,6 @@ const updateTeamCollectionOrFolder = (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (teamCollectionAdapter.value) {
|
|
||||||
const { auth, headers } =
|
|
||||||
teamCollectionAdapter.value.cascadeParentCollectionForHeaderAuth(
|
|
||||||
createRequestInCollection.collection.id
|
|
||||||
)
|
|
||||||
|
|
||||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
|
||||||
auth,
|
|
||||||
headers,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modalLoadingState.value = false
|
modalLoadingState.value = false
|
||||||
requestSaved()
|
requestSaved()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,16 +9,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { HoppCollection } from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
import { ref } from "vue"
|
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
|
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
|
||||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||||
@@ -31,7 +30,7 @@ import {
|
|||||||
} from "~/newstore/collections"
|
} from "~/newstore/collections"
|
||||||
import { hoppGqlCollectionsImporter } from "~/helpers/import-export/import/hoppGql"
|
import { hoppGqlCollectionsImporter } from "~/helpers/import-export/import/hoppGql"
|
||||||
import { gqlCollectionsExporter } from "~/helpers/import-export/export/gqlCollections"
|
import { gqlCollectionsExporter } from "~/helpers/import-export/export/gqlCollections"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { gqlCollectionsGistExporter } from "~/helpers/import-export/export/gqlCollectionsGistExporter"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { hoppGQLImporter } from "~/helpers/import-export/import/hopp"
|
import { hoppGQLImporter } from "~/helpers/import-export/import/hopp"
|
||||||
|
|
||||||
@@ -43,10 +42,6 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
const gqlCollections = useReadonlyStream(graphqlCollections$, [])
|
|
||||||
|
|
||||||
const isGqlCollectionGistExportInProgress = ref(false)
|
|
||||||
|
|
||||||
const GqlCollectionsHoppImporter: ImporterOrExporter = {
|
const GqlCollectionsHoppImporter: ImporterOrExporter = {
|
||||||
metadata: {
|
metadata: {
|
||||||
id: "import.from_json",
|
id: "import.from_json",
|
||||||
@@ -124,6 +119,8 @@ const GqlCollectionsGistImporter: ImporterOrExporter = {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const gqlCollections = useReadonlyStream(graphqlCollections$, [])
|
||||||
|
|
||||||
const GqlCollectionsHoppExporter: ImporterOrExporter = {
|
const GqlCollectionsHoppExporter: ImporterOrExporter = {
|
||||||
metadata: {
|
metadata: {
|
||||||
id: "export.as_json",
|
id: "export.as_json",
|
||||||
@@ -162,35 +159,29 @@ const GqlCollectionsGistExporter: ImporterOrExporter = {
|
|||||||
metadata: {
|
metadata: {
|
||||||
id: "export.as_gist",
|
id: "export.as_gist",
|
||||||
name: "export.create_secret_gist",
|
name: "export.create_secret_gist",
|
||||||
title:
|
title: !currentUser
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
? "export.require_github"
|
||||||
// @ts-ignore
|
: // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
currentUser?.value?.provider === "github.com"
|
// @ts-ignore
|
||||||
? "export.create_secret_gist_tooltip_text"
|
currentUser.provider !== "github.com"
|
||||||
: "export.require_github",
|
? `export.require_github`
|
||||||
|
: "export.create_secret_gist",
|
||||||
icon: IconUser,
|
icon: IconUser,
|
||||||
disabled: !currentUser.value
|
disabled: !currentUser.value
|
||||||
? true
|
? true
|
||||||
: currentUser.value?.provider !== "github.com",
|
: currentUser.value.provider !== "github.com",
|
||||||
applicableTo: ["personal-workspace"],
|
applicableTo: ["personal-workspace"],
|
||||||
isLoading: isGqlCollectionGistExportInProgress,
|
|
||||||
},
|
},
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (!gqlCollections.value.length) {
|
|
||||||
return toast.error(t("error.no_collections_to_export"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentUser.value) {
|
if (!currentUser.value) {
|
||||||
toast.error(t("profile.no_permission"))
|
toast.error(t("profile.no_permission"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isGqlCollectionGistExportInProgress.value = true
|
|
||||||
|
|
||||||
const accessToken = currentUser.value?.accessToken
|
const accessToken = currentUser.value?.accessToken
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
const res = await gistExporter(
|
const res = await gqlCollectionsGistExporter(
|
||||||
JSON.stringify(gqlCollections.value),
|
JSON.stringify(gqlCollections.value),
|
||||||
accessToken
|
accessToken
|
||||||
)
|
)
|
||||||
@@ -200,7 +191,7 @@ const GqlCollectionsGistExporter: ImporterOrExporter = {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success(t("export.secret_gist_success"))
|
toast.success(t("export.success"))
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_COLLECTION",
|
type: "HOPP_EXPORT_COLLECTION",
|
||||||
@@ -210,8 +201,6 @@ const GqlCollectionsGistExporter: ImporterOrExporter = {
|
|||||||
|
|
||||||
platform.io.openExternalLink(res.right)
|
platform.io.openExternalLink(res.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
isGqlCollectionGistExportInProgress.value = false
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,6 @@ const emit = defineEmits<{
|
|||||||
(event: "select", payload: Picked | null): void
|
(event: "select", payload: Picked | null): void
|
||||||
(event: "update-team", team: SelectedTeam): void
|
(event: "update-team", team: SelectedTeam): void
|
||||||
(event: "update-collection-type", type: CollectionType["type"]): void
|
(event: "update-collection-type", type: CollectionType["type"]): void
|
||||||
(event: "set-team-collection-adapter", adapter: TeamCollectionAdapter): void
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||||
@@ -355,7 +354,6 @@ watch(
|
|||||||
(newTeam) => {
|
(newTeam) => {
|
||||||
if (newTeam) {
|
if (newTeam) {
|
||||||
teamCollectionAdapter.changeTeamID(newTeam.id)
|
teamCollectionAdapter.changeTeamID(newTeam.id)
|
||||||
emit("set-team-collection-adapter", teamCollectionAdapter)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,17 +9,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Environment } from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
import { ref } from "vue"
|
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
import { hoppEnvImporter } from "~/helpers/import-export/import/hoppEnv"
|
import { hoppEnvImporter } from "~/helpers/import-export/import/hoppEnv"
|
||||||
|
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
import {
|
import {
|
||||||
appendEnvironments,
|
appendEnvironments,
|
||||||
addGlobalEnvVariable,
|
addGlobalEnvVariable,
|
||||||
@@ -41,7 +39,7 @@ import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
|||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { useReadonlyStream } from "~/composables/stream"
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { environmentsGistExporter } from "~/helpers/import-export/export/environmentsGistExport"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
@@ -60,8 +58,6 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
const isEnvironmentGistExportInProgress = ref(false)
|
|
||||||
|
|
||||||
const isTeamEnvironment = computed(() => {
|
const isTeamEnvironment = computed(() => {
|
||||||
return props.environmentType === "TEAM_ENV"
|
return props.environmentType === "TEAM_ENV"
|
||||||
})
|
})
|
||||||
@@ -266,44 +262,35 @@ const HoppEnvironmentsGistExporter: ImporterOrExporter = {
|
|||||||
title:
|
title:
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
currentUser?.value?.provider === "github.com"
|
currentUser?.provider === "github.com"
|
||||||
? "export.create_secret_gist_tooltip_text"
|
? "export.create_secret_gist"
|
||||||
: "export.require_github",
|
: "export.require_github",
|
||||||
icon: IconUser,
|
icon: IconUser,
|
||||||
disabled: !currentUser.value
|
disabled: !currentUser.value
|
||||||
? true
|
? true
|
||||||
: currentUser.value?.provider !== "github.com",
|
: currentUser.value.provider !== "github.com",
|
||||||
applicableTo: ["personal-workspace", "team-workspace"],
|
applicableTo: ["personal-workspace", "team-workspace"],
|
||||||
isLoading: isEnvironmentGistExportInProgress,
|
|
||||||
},
|
},
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (!environmentJson.value.length) {
|
|
||||||
return toast.error(t("error.no_environments_to_export"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentUser.value) {
|
if (!currentUser.value) {
|
||||||
toast.error(t("profile.no_permission"))
|
toast.error(t("profile.no_permission"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isEnvironmentGistExportInProgress.value = true
|
|
||||||
|
|
||||||
const accessToken = currentUser.value?.accessToken
|
const accessToken = currentUser.value?.accessToken
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
const res = await gistExporter(
|
const res = await environmentsGistExporter(
|
||||||
JSON.stringify(environmentJson.value),
|
JSON.stringify(environmentJson.value),
|
||||||
accessToken,
|
accessToken
|
||||||
"hoppscotch-environment.json"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (E.isLeft(res)) {
|
if (E.isLeft(res)) {
|
||||||
toast.error(t("export.failed"))
|
toast.error(t("export.failed"))
|
||||||
isEnvironmentGistExportInProgress.value = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success(t("export.secret_gist_success"))
|
toast.success(t("export.success"))
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_ENVIRONMENT",
|
type: "HOPP_EXPORT_ENVIRONMENT",
|
||||||
@@ -312,8 +299,6 @@ const HoppEnvironmentsGistExporter: ImporterOrExporter = {
|
|||||||
|
|
||||||
platform.io.openExternalLink(res.right)
|
platform.io.openExternalLink(res.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
isEnvironmentGistExportInProgress.value = false
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div v-if="loading" class="flex flex-col items-center justify-center p-4">
|
<div v-if="loading" class="flex flex-col items-center justify-center">
|
||||||
<HoppSmartSpinner class="mb-4" />
|
<HoppSmartSpinner class="mb-4" />
|
||||||
<span class="text-secondaryLight">{{ t("state.loading") }}</span>
|
<span class="text-secondaryLight">{{ t("state.loading") }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -451,7 +451,7 @@ const getErrorMessage = (err: GQLError<string>) => {
|
|||||||
}
|
}
|
||||||
switch (err.error) {
|
switch (err.error) {
|
||||||
case "shortcode/not_found":
|
case "shortcode/not_found":
|
||||||
return t("shared_requests.not_found")
|
return t("shared_request.not_found")
|
||||||
default:
|
default:
|
||||||
return t("error.something_went_wrong")
|
return t("error.something_went_wrong")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,5 @@ mutation UpdateRequest($data: UpdateTeamRequestInput!, $requestID: ID!) {
|
|||||||
updateRequest(data: $data, requestID: $requestID) {
|
updateRequest(data: $data, requestID: $requestID) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
collectionID
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { createGist } from "~/helpers/gist"
|
||||||
|
|
||||||
|
export const environmentsGistExporter = async (
|
||||||
|
environmentsJSON: string,
|
||||||
|
accessToken: string
|
||||||
|
) => {
|
||||||
|
const res = await createGist(
|
||||||
|
environmentsJSON,
|
||||||
|
"hoppscotch-collections.json",
|
||||||
|
accessToken
|
||||||
|
)()
|
||||||
|
|
||||||
|
if (E.isLeft(res)) {
|
||||||
|
return E.left(res.left)
|
||||||
|
}
|
||||||
|
return E.right(res.right.data.html_url as string)
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import * as E from "fp-ts/Either"
|
|
||||||
import { createGist } from "~/helpers/gist"
|
|
||||||
|
|
||||||
export const gistExporter = async (
|
|
||||||
JSONFileContents: string,
|
|
||||||
accessToken: string,
|
|
||||||
fileName = "hoppscotch-collections.json"
|
|
||||||
) => {
|
|
||||||
if (!accessToken) {
|
|
||||||
return E.left("Invalid User")
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await createGist(JSONFileContents, fileName, accessToken)()
|
|
||||||
|
|
||||||
if (E.isLeft(res)) {
|
|
||||||
return E.left(res.left)
|
|
||||||
}
|
|
||||||
return E.right(res.right.data.html_url as string)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { createGist } from "~/helpers/gist"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
|
||||||
|
export const collectionsGistExporter = async (
|
||||||
|
collectionJSON: string,
|
||||||
|
accessToken: string
|
||||||
|
) => {
|
||||||
|
if (!accessToken) {
|
||||||
|
return E.left("Invalid User")
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await createGist(
|
||||||
|
collectionJSON,
|
||||||
|
"hoppscotch-collections.json",
|
||||||
|
accessToken
|
||||||
|
)()
|
||||||
|
|
||||||
|
if (E.isLeft(res)) {
|
||||||
|
return E.left(res.left)
|
||||||
|
}
|
||||||
|
return E.right(true)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { createGist } from "~/helpers/gist"
|
||||||
|
|
||||||
|
export const gqlCollectionsGistExporter = async (
|
||||||
|
gqlCollectionsJSON: string,
|
||||||
|
accessToken: string
|
||||||
|
) => {
|
||||||
|
const res = await createGist(
|
||||||
|
gqlCollectionsJSON,
|
||||||
|
"hoppscotch-collections.json",
|
||||||
|
accessToken
|
||||||
|
)()
|
||||||
|
|
||||||
|
if (E.isLeft(res)) {
|
||||||
|
return E.left(res.left)
|
||||||
|
}
|
||||||
|
return E.right(res.right.data.html_url as string)
|
||||||
|
}
|
||||||
@@ -156,7 +156,6 @@ export default class ShortcodeListAdapter {
|
|||||||
const [shortcodeCreated$, shortcodeCreatedSub] = runAuthOnlyGQLSubscription(
|
const [shortcodeCreated$, shortcodeCreatedSub] = runAuthOnlyGQLSubscription(
|
||||||
{
|
{
|
||||||
query: ShortcodeCreatedDocument,
|
query: ShortcodeCreatedDocument,
|
||||||
variables: {},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -173,7 +172,6 @@ export default class ShortcodeListAdapter {
|
|||||||
const [shortcodeRevoked$, shortcodeRevokedSub] = runAuthOnlyGQLSubscription(
|
const [shortcodeRevoked$, shortcodeRevokedSub] = runAuthOnlyGQLSubscription(
|
||||||
{
|
{
|
||||||
query: ShortcodeDeletedDocument,
|
query: ShortcodeDeletedDocument,
|
||||||
variables: {},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -190,7 +188,6 @@ export default class ShortcodeListAdapter {
|
|||||||
const [shortcodeUpdated$, shortcodeUpdatedSub] = runAuthOnlyGQLSubscription(
|
const [shortcodeUpdated$, shortcodeUpdatedSub] = runAuthOnlyGQLSubscription(
|
||||||
{
|
{
|
||||||
query: ShortcodeUpdatedDocument,
|
query: ShortcodeUpdatedDocument,
|
||||||
variables: {},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1034,11 +1034,6 @@ export default class NewTeamCollectionAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL team collections
|
|
||||||
* @param folderPath the path of the folder to cascade the auth from
|
|
||||||
* @returns the inherited auth and headers for the given folder path
|
|
||||||
*/
|
|
||||||
public cascadeParentCollectionForHeaderAuth(folderPath: string) {
|
public cascadeParentCollectionForHeaderAuth(folderPath: string) {
|
||||||
let auth: HoppInheritedProperty["auth"] = {
|
let auth: HoppInheritedProperty["auth"] = {
|
||||||
parentID: folderPath ?? "",
|
parentID: folderPath ?? "",
|
||||||
@@ -1094,10 +1089,7 @@ export default class NewTeamCollectionAdapter {
|
|||||||
const parentFolderAuth = data.auth
|
const parentFolderAuth = data.auth
|
||||||
const parentFolderHeaders = data.headers
|
const parentFolderHeaders = data.headers
|
||||||
|
|
||||||
if (
|
if (parentFolderAuth?.authType === "inherit" && path.length === 1) {
|
||||||
parentFolderAuth?.authType === "inherit" &&
|
|
||||||
[...path.slice(0, i + 1)].length === 1
|
|
||||||
) {
|
|
||||||
auth = {
|
auth = {
|
||||||
parentID: [...path.slice(0, i + 1)].join("/"),
|
parentID: [...path.slice(0, i + 1)].join("/"),
|
||||||
parentName: parentFolder.title,
|
parentName: parentFolder.title,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
HoppCollection,
|
HoppCollection,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
HoppGQLAuth,
|
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||||
import { cloneDeep } from "lodash-es"
|
import { cloneDeep } from "lodash-es"
|
||||||
@@ -12,9 +11,6 @@ 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"
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
import { HoppRESTAuth } from "@hoppscotch/data"
|
|
||||||
import { HoppRESTHeaders } from "@hoppscotch/data"
|
|
||||||
import { HoppGQLHeader } from "~/helpers/graphql"
|
|
||||||
|
|
||||||
const defaultRESTCollectionState = {
|
const defaultRESTCollectionState = {
|
||||||
state: [
|
state: [
|
||||||
@@ -67,12 +63,6 @@ export function navigateToFolderWithIndexPath(
|
|||||||
return target !== undefined ? target : null
|
return target !== undefined ? target : null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL personal collections
|
|
||||||
* @param folderPath the path of the folder to cascade the auth from
|
|
||||||
* @param type the type of collection
|
|
||||||
* @returns the inherited auth and headers for the given folder path
|
|
||||||
*/
|
|
||||||
export function cascadeParentCollectionForHeaderAuth(
|
export function cascadeParentCollectionForHeaderAuth(
|
||||||
folderPath: string | undefined,
|
folderPath: string | undefined,
|
||||||
type: "rest" | "graphql"
|
type: "rest" | "graphql"
|
||||||
@@ -113,16 +103,10 @@ export function cascadeParentCollectionForHeaderAuth(
|
|||||||
return { auth, headers }
|
return { auth, headers }
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentFolderAuth = parentFolder.auth as HoppRESTAuth | HoppGQLAuth
|
const parentFolderAuth = parentFolder.auth
|
||||||
const parentFolderHeaders = parentFolder.headers as
|
const parentFolderHeaders = parentFolder.headers
|
||||||
| HoppRESTHeaders
|
|
||||||
| HoppGQLHeader[]
|
|
||||||
|
|
||||||
// check if the parent folder has authType 'inherit' and if it is the root folder
|
// check if the parent folder has authType 'inherit' and if it is the root folder
|
||||||
if (
|
if (parentFolderAuth?.authType === "inherit" && path.length === 1) {
|
||||||
parentFolderAuth?.authType === "inherit" &&
|
|
||||||
[...path.slice(0, i + 1)].length === 1
|
|
||||||
) {
|
|
||||||
auth = {
|
auth = {
|
||||||
parentID: [...path.slice(0, i + 1)].join("/"),
|
parentID: [...path.slice(0, i + 1)].join("/"),
|
||||||
parentName: parentFolder.name,
|
parentName: parentFolder.name,
|
||||||
|
|||||||
@@ -1,58 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col justify-center">
|
<div class="flex flex-col flex-1 w-full">
|
||||||
<div
|
|
||||||
v-if="invalidLink"
|
|
||||||
class="flex flex-1 flex-col items-center justify-center p-8"
|
|
||||||
>
|
|
||||||
<icon-lucide-alert-triangle class="svg-icons mb-2 opacity-75" />
|
|
||||||
<h1 class="heading text-center">
|
|
||||||
{{ t("error.invalid_link") }}
|
|
||||||
</h1>
|
|
||||||
<p class="mt-2 text-center">
|
|
||||||
{{ t("error.invalid_embed_link") }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Embeds
|
<Embeds
|
||||||
v-else-if="!invalidLink && tab"
|
v-if="tab"
|
||||||
v-model:modelTab="tab"
|
v-model:modelTab="tab"
|
||||||
:properties="properties"
|
:properties="properties"
|
||||||
:shared-request-i-d="sharedRequestID"
|
:shared-request-i-d="sharedRequestID"
|
||||||
/>
|
/>
|
||||||
<div v-else class="flex flex-1 flex-col items-center justify-center p-4">
|
|
||||||
<div
|
|
||||||
v-if="sharedRequestDetails.loading"
|
|
||||||
class="flex flex-1 flex-col items-center justify-center p-4"
|
|
||||||
>
|
|
||||||
<HoppSmartSpinner />
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<div
|
|
||||||
v-if="
|
|
||||||
!sharedRequestDetails.loading && E.isLeft(sharedRequestDetails.data)
|
|
||||||
"
|
|
||||||
class="flex flex-col items-center p-4"
|
|
||||||
>
|
|
||||||
<icon-lucide-alert-triangle class="svg-icons mb-2 opacity-75" />
|
|
||||||
<h1 class="heading text-center">
|
|
||||||
{{ t("error.invalid_link") }}
|
|
||||||
</h1>
|
|
||||||
<p class="mt-2 text-center">
|
|
||||||
{{ t("error.invalid_embed_link") }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="
|
|
||||||
!sharedRequestDetails.loading &&
|
|
||||||
E.isRight(sharedRequestDetails.data)
|
|
||||||
"
|
|
||||||
class="flex flex-1 flex-col items-center justify-center p-4"
|
|
||||||
>
|
|
||||||
<h1 class="heading">
|
|
||||||
{{ t("state.loading") }}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -75,9 +28,6 @@ import {
|
|||||||
import { HoppTab } from "~/services/tab"
|
import { HoppTab } from "~/services/tab"
|
||||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||||
import { applySetting } from "~/newstore/settings"
|
import { applySetting } from "~/newstore/settings"
|
||||||
import { useI18n } from "~/composables/i18n"
|
|
||||||
|
|
||||||
const t = useI18n()
|
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|||||||
@@ -244,13 +244,9 @@ export class PersistenceService extends Service {
|
|||||||
private setupSettingsPersistence() {
|
private setupSettingsPersistence() {
|
||||||
const settingsKey = "settings"
|
const settingsKey = "settings"
|
||||||
let settingsData = JSON.parse(
|
let settingsData = JSON.parse(
|
||||||
window.localStorage.getItem(settingsKey) ?? "null"
|
window.localStorage.getItem(settingsKey) || "{}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!settingsData) {
|
|
||||||
settingsData = getDefaultSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate data read from localStorage
|
// Validate data read from localStorage
|
||||||
const result = SETTINGS_SCHEMA.safeParse(settingsData)
|
const result = SETTINGS_SCHEMA.safeParse(settingsData)
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const SettingsDefSchema = z.object({
|
|||||||
httpUser: z.boolean(),
|
httpUser: z.boolean(),
|
||||||
httpPassword: z.boolean(),
|
httpPassword: z.boolean(),
|
||||||
bearerToken: z.boolean(),
|
bearerToken: z.boolean(),
|
||||||
oauth2Token: z.optional(z.boolean()),
|
oauth2Token: z.boolean(),
|
||||||
}),
|
}),
|
||||||
THEME_COLOR: ThemeColorSchema,
|
THEME_COLOR: ThemeColorSchema,
|
||||||
BG_COLOR: BgColorSchema,
|
BG_COLOR: BgColorSchema,
|
||||||
@@ -103,10 +103,13 @@ export const LOCAL_STATE_SCHEMA = z.union([
|
|||||||
.strict(),
|
.strict(),
|
||||||
])
|
])
|
||||||
|
|
||||||
export const SETTINGS_SCHEMA = SettingsDefSchema.extend({
|
export const SETTINGS_SCHEMA = z.union([
|
||||||
EXTENSIONS_ENABLED: z.optional(z.boolean()),
|
z.object({}).strict(),
|
||||||
PROXY_ENABLED: z.optional(z.boolean()),
|
SettingsDefSchema.extend({
|
||||||
})
|
EXTENSIONS_ENABLED: z.optional(z.boolean()),
|
||||||
|
PROXY_ENABLED: z.optional(z.boolean()),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
export const REST_HISTORY_ENTRY_SCHEMA = z
|
export const REST_HISTORY_ENTRY_SCHEMA = z
|
||||||
.object({
|
.object({
|
||||||
@@ -205,7 +208,7 @@ export const MQTT_REQUEST_SCHEMA = z.nullable(
|
|||||||
z
|
z
|
||||||
.object({
|
.object({
|
||||||
endpoint: z.string(),
|
endpoint: z.string(),
|
||||||
clientID: z.optional(z.string()),
|
clientID: z.string(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user