Authorization.vue (hoppscotch-2.2.1) | : | Authorization.vue (hoppscotch-3.0.0) | ||
---|---|---|---|---|
<template> | <template> | |||
<div> | <div class="flex flex-col flex-1"> | |||
<div | <div | |||
class="sticky z-10 flex items-center justify-between flex-1 pl-4 border-b bg-primary border-dividerLight top-upperSecondaryStickyFold" | class="sticky z-10 flex items-center justify-between pl-4 border-b bg-prim ary border-dividerLight top-upperMobileSecondaryStickyFold sm:top-upperSecondary StickyFold" | |||
> | > | |||
<span class="flex items-center"> | <span class="flex items-center"> | |||
<label class="font-semibold text-secondaryLight"> | <label class="font-semibold text-secondaryLight"> | |||
{{ $t("authorization.type") }} | {{ t("authorization.type") }} | |||
</label> | </label> | |||
<tippy | <tippy | |||
ref="authTypeOptions" | ref="authTypeOptions" | |||
interactive | interactive | |||
trigger="click" | trigger="click" | |||
theme="popover" | theme="popover" | |||
arrow | arrow | |||
> | > | |||
<template #trigger> | <span class="select-wrapper"> | |||
<span class="select-wrapper"> | <ButtonSecondary class="pr-8 ml-2 rounded-none" :label="authName" /> | |||
<ButtonSecondary | </span> | |||
class="pr-8 ml-2 rounded-none" | <template #content="{ hide }"> | |||
:label="authName" | <div | |||
class="flex flex-col" | ||||
tabindex="0" | ||||
role="menu" | ||||
@keyup.escape="hide()" | ||||
> | ||||
<SmartItem | ||||
label="None" | ||||
:icon="authName === 'None' ? IconCircleDot : IconCircle" | ||||
:active="authName === 'None'" | ||||
@click=" | ||||
() => { | ||||
authType = 'none' | ||||
hide() | ||||
} | ||||
" | ||||
/> | /> | |||
</span> | <SmartItem | |||
label="Basic Auth" | ||||
:icon="authName === 'Basic Auth' ? IconCircleDot : IconCircle" | ||||
:active="authName === 'Basic Auth'" | ||||
@click=" | ||||
() => { | ||||
authType = 'basic' | ||||
hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="Bearer Token" | ||||
:icon="authName === 'Bearer' ? IconCircleDot : IconCircle" | ||||
:active="authName === 'Bearer'" | ||||
@click=" | ||||
() => { | ||||
authType = 'bearer' | ||||
hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="OAuth 2.0" | ||||
:icon="authName === 'OAuth 2.0' ? IconCircleDot : IconCircle" | ||||
:active="authName === 'OAuth 2.0'" | ||||
@click=" | ||||
() => { | ||||
authType = 'oauth-2' | ||||
hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="API key" | ||||
:icon="authName === 'API key' ? IconCircleDot : IconCircle" | ||||
:active="authName === 'API key'" | ||||
@click=" | ||||
() => { | ||||
authType = 'api-key' | ||||
hide() | ||||
} | ||||
" | ||||
/> | ||||
</div> | ||||
</template> | </template> | |||
<SmartItem | ||||
label="None" | ||||
:icon=" | ||||
authName === 'None' | ||||
? 'radio_button_checked' | ||||
: 'radio_button_unchecked' | ||||
" | ||||
:active="authName === 'None'" | ||||
@click.native=" | ||||
() => { | ||||
authType = 'none' | ||||
authTypeOptions.tippy().hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="Basic Auth" | ||||
:icon=" | ||||
authName === 'Basic Auth' | ||||
? 'radio_button_checked' | ||||
: 'radio_button_unchecked' | ||||
" | ||||
:active="authName === 'Basic Auth'" | ||||
@click.native=" | ||||
() => { | ||||
authType = 'basic' | ||||
authTypeOptions.tippy().hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="Bearer Token" | ||||
:icon=" | ||||
authName === 'Bearer' | ||||
? 'radio_button_checked' | ||||
: 'radio_button_unchecked' | ||||
" | ||||
:active="authName === 'Bearer'" | ||||
@click.native=" | ||||
() => { | ||||
authType = 'bearer' | ||||
authTypeOptions.tippy().hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="OAuth 2.0" | ||||
:icon=" | ||||
authName === 'OAuth 2.0' | ||||
? 'radio_button_checked' | ||||
: 'radio_button_unchecked' | ||||
" | ||||
:active="authName === 'OAuth 2.0'" | ||||
@click.native=" | ||||
() => { | ||||
authType = 'oauth-2' | ||||
authTypeOptions.tippy().hide() | ||||
} | ||||
" | ||||
/> | ||||
<SmartItem | ||||
label="API key" | ||||
:icon=" | ||||
authName === 'API key' | ||||
? 'radio_button_checked' | ||||
: 'radio_button_unchecked' | ||||
" | ||||
:active="authName === 'API key'" | ||||
@click.native=" | ||||
() => { | ||||
authType = 'api-key' | ||||
authTypeOptions.tippy().hide() | ||||
} | ||||
" | ||||
/> | ||||
</tippy> | </tippy> | |||
</span> | </span> | |||
<div class="flex"> | <div class="flex"> | |||
<!-- <SmartCheckbox | <!-- <SmartCheckbox | |||
:on="!URLExcludes.auth" | :on="!URLExcludes.auth" | |||
@change="setExclude('auth', !$event)" | @change="setExclude('auth', !$event)" | |||
> | > | |||
{{ $t("authorization.include_in_url") }} | {{ $t("authorization.include_in_url") }} | |||
</SmartCheckbox> --> | </SmartCheckbox>--> | |||
<SmartCheckbox | <SmartCheckbox | |||
:on="authActive" | :on="authActive" | |||
class="px-2" | class="px-2" | |||
@change="authActive = !authActive" | @change="authActive = !authActive" | |||
>{{ t("state.enabled") }}</SmartCheckbox | ||||
> | > | |||
{{ $t("state.enabled") }} | ||||
</SmartCheckbox> | ||||
<ButtonSecondary | <ButtonSecondary | |||
v-tippy="{ theme: 'tooltip' }" | v-tippy="{ theme: 'tooltip' }" | |||
to="https://docs.hoppscotch.io/features/authorization" | to="https://docs.hoppscotch.io/features/authorization" | |||
blank | blank | |||
:title="$t('app.wiki')" | :title="t('app.wiki')" | |||
svg="help-circle" | :icon="IconHelpCircle" | |||
/> | /> | |||
<ButtonSecondary | <ButtonSecondary | |||
v-tippy="{ theme: 'tooltip' }" | v-tippy="{ theme: 'tooltip' }" | |||
:title="$t('action.clear')" | :title="t('action.clear')" | |||
svg="trash-2" | :icon="IconTrash2" | |||
@click.native="clearContent" | @click="clearContent" | |||
/> | /> | |||
</div> | </div> | |||
</div> | </div> | |||
<div | <div | |||
v-if="authType === 'none'" | v-if="authType === 'none'" | |||
class="flex flex-col items-center justify-center p-4 text-secondaryLight" | class="flex flex-col items-center justify-center p-4 text-secondaryLight" | |||
> | > | |||
<img | <img | |||
:src="`/images/states/${$colorMode.value}/login.svg`" | :src="`/images/states/${colorMode.value}/login.svg`" | |||
loading="lazy" | loading="lazy" | |||
class="inline-flex flex-col object-contain object-center w-16 h-16 my-4" | class="inline-flex flex-col object-contain object-center w-16 h-16 my-4" | |||
:alt="`${$t('empty.authorization')}`" | :alt="`${t('empty.authorization')}`" | |||
/> | /> | |||
<span class="pb-4 text-center"> | <span class="pb-4 text-center">{{ t("empty.authorization") }}</span> | |||
{{ $t("empty.authorization") }} | ||||
</span> | ||||
<ButtonSecondary | <ButtonSecondary | |||
outline | outline | |||
:label="$t('app.documentation')" | :label="t('app.documentation')" | |||
to="https://docs.hoppscotch.io/features/authorization" | to="https://docs.hoppscotch.io/features/authorization" | |||
blank | blank | |||
svg="external-link" | :icon="IconExternalLink" | |||
reverse | reverse | |||
class="mb-4" | class="mb-4" | |||
/> | /> | |||
</div> | </div> | |||
<div v-else class="flex border-b border-dividerLight"> | <div v-else class="flex flex-1 border-b border-dividerLight"> | |||
<div class="w-2/3 border-r border-dividerLight"> | <div class="w-2/3 border-r border-dividerLight"> | |||
<div v-if="authType === 'basic'"> | <div v-if="authType === 'basic'"> | |||
<div class="flex border-b border-dividerLight"> | <div class="flex flex-1 border-b border-dividerLight"> | |||
<SmartEnvInput | <SmartEnvInput | |||
v-model="basicUsername" | v-model="basicUsername" | |||
:placeholder="$t('authorization.username')" | :placeholder="t('authorization.username')" | |||
styles="bg-transparent flex flex-1 py-1 px-4" | ||||
/> | /> | |||
</div> | </div> | |||
<div class="flex border-b border-dividerLight"> | <div class="flex flex-1 border-b border-dividerLight"> | |||
<SmartEnvInput | <SmartEnvInput | |||
v-model="basicPassword" | v-model="basicPassword" | |||
:placeholder="$t('authorization.password')" | :placeholder="t('authorization.password')" | |||
styles="bg-transparent flex flex-1 py-1 px-4" | ||||
/> | /> | |||
</div> | </div> | |||
</div> | </div> | |||
<div v-if="authType === 'bearer'"> | <div v-if="authType === 'bearer'"> | |||
<div class="flex border-b border-dividerLight"> | <div class="flex flex-1 border-b border-dividerLight"> | |||
<SmartEnvInput | <SmartEnvInput v-model="bearerToken" placeholder="Token" /> | |||
v-model="bearerToken" | ||||
placeholder="Token" | ||||
styles="bg-transparent flex flex-1 py-1 px-4" | ||||
/> | ||||
</div> | </div> | |||
</div> | </div> | |||
<div v-if="authType === 'oauth-2'"> | <div v-if="authType === 'oauth-2'"> | |||
<div class="flex border-b border-dividerLight"> | <div class="flex flex-1 border-b border-dividerLight"> | |||
<SmartEnvInput | <SmartEnvInput v-model="oauth2Token" placeholder="Token" /> | |||
v-model="oauth2Token" | ||||
placeholder="Token" | ||||
styles="bg-transparent flex flex-1 py-1 px-4" | ||||
/> | ||||
</div> | </div> | |||
<HttpOAuth2Authorization /> | <HttpOAuth2Authorization /> | |||
</div> | </div> | |||
<div v-if="authType === 'api-key'"> | <div v-if="authType === 'api-key'"> | |||
<div class="flex border-b border-dividerLight"> | <div class="flex flex-1 border-b border-dividerLight"> | |||
<SmartEnvInput | <SmartEnvInput v-model="apiKey" placeholder="Key" /> | |||
v-model="apiKey" | ||||
placeholder="Key" | ||||
styles="bg-transparent flex flex-1 py-1 px-4" | ||||
/> | ||||
</div> | </div> | |||
<div class="flex border-b border-dividerLight"> | <div class="flex flex-1 border-b border-dividerLight"> | |||
<SmartEnvInput | <SmartEnvInput v-model="apiValue" placeholder="Value" /> | |||
v-model="apiValue" | ||||
placeholder="Value" | ||||
styles="bg-transparent flex flex-1 py-1 px-4" | ||||
/> | ||||
</div> | </div> | |||
<div class="flex items-center border-b border-dividerLight"> | <div class="flex items-center border-b border-dividerLight"> | |||
<label class="ml-4 text-secondaryLight"> | <span class="flex items-center"> | |||
{{ $t("authorization.pass_key_by") }} | <label class="ml-4 text-secondaryLight"> | |||
</label> | {{ t("authorization.pass_key_by") }} | |||
<tippy | </label> | |||
ref="addToOptions" | <tippy | |||
interactive | ref="addToOptions" | |||
trigger="click" | interactive | |||
theme="popover" | trigger="click" | |||
arrow | theme="popover" | |||
> | arrow | |||
<template #trigger> | > | |||
<span class="select-wrapper"> | <span class="select-wrapper"> | |||
<ButtonSecondary | <ButtonSecondary | |||
:label="addTo || $t('state.none')" | :label="addTo || t('state.none')" | |||
class="pr-8 ml-2 rounded-none" | class="pr-8 ml-2 rounded-none" | |||
/> | /> | |||
</span> | </span> | |||
</template> | <template #content="{ hide }"> | |||
<SmartItem | <div | |||
:icon=" | class="flex flex-col" | |||
addTo === 'Headers' | tabindex="0" | |||
? 'radio_button_checked' | role="menu" | |||
: 'radio_button_unchecked' | @keyup.escape="hide()" | |||
" | > | |||
:active="addTo === 'Headers'" | <SmartItem | |||
:label="'Headers'" | :icon="addTo === 'Headers' ? IconCircleDot : IconCircle" | |||
@click.native=" | :active="addTo === 'Headers'" | |||
() => { | :label="'Headers'" | |||
addTo = 'Headers' | @click=" | |||
addToOptions.tippy().hide() | () => { | |||
} | addTo = 'Headers' | |||
" | hide() | |||
/> | } | |||
<SmartItem | " | |||
:icon=" | /> | |||
addTo === 'Query params' | <SmartItem | |||
? 'radio_button_checked' | :icon=" | |||
: 'radio_button_unchecked' | addTo === 'Query params' ? IconCircleDot : IconCircle | |||
" | " | |||
:active="addTo === 'Query params'" | :active="addTo === 'Query params'" | |||
:label="'Query params'" | :label="'Query params'" | |||
@click.native=" | @click=" | |||
() => { | () => { | |||
addTo = 'Query params' | addTo = 'Query params' | |||
addToOptions.tippy().hide() | hide() | |||
} | } | |||
" | " | |||
/> | /> | |||
</tippy> | </div> | |||
</template> | ||||
</tippy> | ||||
</span> | ||||
</div> | </div> | |||
</div> | </div> | |||
</div> | </div> | |||
<div | <div | |||
class="sticky h-full p-4 overflow-auto bg-primary top-upperTertiaryStick yFold min-w-46 max-w-1/3 z-9" | class="sticky h-full p-4 overflow-auto bg-primary top-upperTertiaryStick yFold min-w-46 max-w-1/3 z-9" | |||
> | > | |||
<div class="pb-2 text-secondaryLight"> | <div class="pb-2 text-secondaryLight"> | |||
{{ $t("helpers.authorization") }} | {{ t("helpers.authorization") }} | |||
</div> | </div> | |||
<SmartAnchor | <SmartAnchor | |||
class="link" | class="link" | |||
:label="`${$t('authorization.learn')} \xA0 →`" | :label="t('authorization.learn')" | |||
:icon="IconExternalLink" | ||||
to="https://docs.hoppscotch.io/features/authorization" | to="https://docs.hoppscotch.io/features/authorization" | |||
blank | blank | |||
reverse | ||||
/> | /> | |||
</div> | </div> | |||
</div> | </div> | |||
</div> | </div> | |||
</template> | </template> | |||
<script lang="ts"> | <script setup lang="ts"> | |||
import { computed, defineComponent, ref, Ref } from "@nuxtjs/composition-api" | import IconHelpCircle from "~icons/lucide/help-circle" | |||
import IconTrash2 from "~icons/lucide/trash-2" | ||||
import IconExternalLink from "~icons/lucide/external-link" | ||||
import IconCircleDot from "~icons/lucide/circle-dot" | ||||
import IconCircle from "~icons/lucide/circle" | ||||
import { computed, ref, Ref } from "vue" | ||||
import { | import { | |||
HoppRESTAuthBasic, | HoppRESTAuthBasic, | |||
HoppRESTAuthBearer, | HoppRESTAuthBearer, | |||
HoppRESTAuthOAuth2, | HoppRESTAuthOAuth2, | |||
HoppRESTAuthAPIKey, | HoppRESTAuthAPIKey, | |||
} from "@hoppscotch/data" | } from "@hoppscotch/data" | |||
import { pluckRef, useStream } from "~/helpers/utils/composables" | import { pluckRef } from "@composables/ref" | |||
import { useStream } from "@composables/stream" | ||||
import { useI18n } from "@composables/i18n" | ||||
import { useColorMode } from "@composables/theming" | ||||
import { restAuth$, setRESTAuth } from "~/newstore/RESTSession" | import { restAuth$, setRESTAuth } from "~/newstore/RESTSession" | |||
import { useSetting } from "~/newstore/settings" | ||||
export default defineComponent({ | const t = useI18n() | |||
setup() { | ||||
const auth = useStream( | const colorMode = useColorMode() | |||
restAuth$, | ||||
{ authType: "none", authActive: true }, | ||||
setRESTAuth | ||||
) | ||||
const authType = pluckRef(auth, "authType") | ||||
const authName = computed(() => { | ||||
if (authType.value === "basic") return "Basic Auth" | ||||
else if (authType.value === "bearer") return "Bearer" | ||||
else if (authType.value === "oauth-2") return "OAuth 2.0" | ||||
else if (authType.value === "api-key") return "API key" | ||||
else return "None" | ||||
}) | ||||
const authActive = pluckRef(auth, "authActive") | ||||
const basicUsername = pluckRef(auth as Ref<HoppRESTAuthBasic>, "username") | ||||
const basicPassword = pluckRef(auth as Ref<HoppRESTAuthBasic>, "password") | ||||
const bearerToken = pluckRef(auth as Ref<HoppRESTAuthBearer>, "token") | ||||
const oauth2Token = pluckRef(auth as Ref<HoppRESTAuthOAuth2>, "token") | ||||
const apiKey = pluckRef(auth as Ref<HoppRESTAuthAPIKey>, "key") | ||||
const apiValue = pluckRef(auth as Ref<HoppRESTAuthAPIKey>, "value") | ||||
const addTo = pluckRef(auth as Ref<HoppRESTAuthAPIKey>, "addTo") | ||||
if (typeof addTo.value === "undefined") { | ||||
addTo.value = "Headers" | ||||
apiKey.value = "" | ||||
apiValue.value = "" | ||||
} | ||||
const URLExcludes = useSetting("URL_EXCLUDES") | const auth = useStream( | |||
const clearContent = () => { | restAuth$, | |||
auth.value = { | { authType: "none", authActive: true }, | |||
authType: "none", | setRESTAuth | |||
authActive: true, | ) | |||
} | const authType = pluckRef(auth, "authType") | |||
} | const authName = computed(() => { | |||
return { | if (authType.value === "basic") return "Basic Auth" | |||
auth, | else if (authType.value === "bearer") return "Bearer" | |||
authType, | else if (authType.value === "oauth-2") return "OAuth 2.0" | |||
authName, | else if (authType.value === "api-key") return "API key" | |||
authActive, | else return "None" | |||
basicUsername, | ||||
basicPassword, | ||||
bearerToken, | ||||
oauth2Token, | ||||
URLExcludes, | ||||
clearContent, | ||||
apiKey, | ||||
apiValue, | ||||
addTo, | ||||
authTypeOptions: ref<any | null>(null), | ||||
addToOptions: ref<any | null>(null), | ||||
} | ||||
}, | ||||
}) | }) | |||
const authActive = pluckRef(auth, "authActive") | ||||
const basicUsername = pluckRef(auth as Ref<HoppRESTAuthBasic>, "username") | ||||
const basicPassword = pluckRef(auth as Ref<HoppRESTAuthBasic>, "password") | ||||
const bearerToken = pluckRef(auth as Ref<HoppRESTAuthBearer>, "token") | ||||
const oauth2Token = pluckRef(auth as Ref<HoppRESTAuthOAuth2>, "token") | ||||
const apiKey = pluckRef(auth as Ref<HoppRESTAuthAPIKey>, "key") | ||||
const apiValue = pluckRef(auth as Ref<HoppRESTAuthAPIKey>, "value") | ||||
const addTo = pluckRef(auth as Ref<HoppRESTAuthAPIKey>, "addTo") | ||||
if (typeof addTo.value === "undefined") { | ||||
addTo.value = "Headers" | ||||
apiKey.value = "" | ||||
apiValue.value = "" | ||||
} | ||||
const clearContent = () => { | ||||
auth.value = { | ||||
authType: "none", | ||||
authActive: true, | ||||
} | ||||
} | ||||
const authTypeOptions = ref<any | null>(null) | ||||
const addToOptions = ref<any | null>(null) | ||||
</script> | </script> | |||
End of changes. 37 change blocks. | ||||
233 lines changed or deleted | 192 lines changed or added |