Authorization.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <template>
  2. <div class="flex flex-col flex-1">
  3. <div
  4. class="sticky z-10 flex items-center justify-between pl-4 border-b bg-primary border-dividerLight top-upperSecondaryStickyFold"
  5. >
  6. <span class="flex items-center">
  7. <label class="font-semibold text-secondaryLight">
  8. {{ $t("authorization.type") }}
  9. </label>
  10. <tippy
  11. ref="authTypeOptions"
  12. interactive
  13. trigger="click"
  14. theme="popover"
  15. arrow
  16. >
  17. <template #trigger>
  18. <span class="select-wrapper">
  19. <ButtonSecondary
  20. class="pr-8 ml-2 rounded-none"
  21. :label="authName"
  22. />
  23. </span>
  24. </template>
  25. <SmartItem
  26. label="None"
  27. :icon="
  28. authName === 'None'
  29. ? 'radio_button_checked'
  30. : 'radio_button_unchecked'
  31. "
  32. :active="authName === 'None'"
  33. @click.native="
  34. () => {
  35. authType = 'none'
  36. authTypeOptions.tippy().hide()
  37. }
  38. "
  39. />
  40. <SmartItem
  41. label="Basic Auth"
  42. :icon="
  43. authName === 'Basic Auth'
  44. ? 'radio_button_checked'
  45. : 'radio_button_unchecked'
  46. "
  47. :active="authName === 'Basic Auth'"
  48. @click.native="
  49. () => {
  50. authType = 'basic'
  51. authTypeOptions.tippy().hide()
  52. }
  53. "
  54. />
  55. <SmartItem
  56. label="Bearer Token"
  57. :icon="
  58. authName === 'Bearer'
  59. ? 'radio_button_checked'
  60. : 'radio_button_unchecked'
  61. "
  62. :active="authName === 'Bearer'"
  63. @click.native="
  64. () => {
  65. authType = 'bearer'
  66. authTypeOptions.tippy().hide()
  67. }
  68. "
  69. />
  70. <SmartItem
  71. label="OAuth 2.0"
  72. :icon="
  73. authName === 'OAuth 2.0'
  74. ? 'radio_button_checked'
  75. : 'radio_button_unchecked'
  76. "
  77. :active="authName === 'OAuth 2.0'"
  78. @click.native="
  79. () => {
  80. authType = 'oauth-2'
  81. authTypeOptions.tippy().hide()
  82. }
  83. "
  84. />
  85. <SmartItem
  86. label="API key"
  87. :icon="
  88. authName === 'API key'
  89. ? 'radio_button_checked'
  90. : 'radio_button_unchecked'
  91. "
  92. :active="authName === 'API key'"
  93. @click.native="
  94. () => {
  95. authType = 'api-key'
  96. authTypeOptions.tippy().hide()
  97. }
  98. "
  99. />
  100. </tippy>
  101. </span>
  102. <div class="flex">
  103. <!-- <SmartCheckbox
  104. :on="!URLExcludes.auth"
  105. @change="setExclude('auth', !$event)"
  106. >
  107. {{ $t("authorization.include_in_url") }}
  108. </SmartCheckbox> -->
  109. <SmartCheckbox
  110. :on="authActive"
  111. class="px-2"
  112. @change="authActive = !authActive"
  113. >
  114. {{ $t("state.enabled") }}
  115. </SmartCheckbox>
  116. <ButtonSecondary
  117. v-tippy="{ theme: 'tooltip' }"
  118. to="https://docs.hoppscotch.io/features/authorization"
  119. blank
  120. :title="$t('app.wiki')"
  121. svg="help-circle"
  122. />
  123. <ButtonSecondary
  124. v-tippy="{ theme: 'tooltip' }"
  125. :title="$t('action.clear')"
  126. svg="trash-2"
  127. @click.native="clearContent"
  128. />
  129. </div>
  130. </div>
  131. <div
  132. v-if="authType === 'none'"
  133. class="flex flex-col items-center justify-center p-4 text-secondaryLight"
  134. >
  135. <img
  136. :src="`/images/states/${$colorMode.value}/login.svg`"
  137. loading="lazy"
  138. class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
  139. :alt="`${$t('empty.authorization')}`"
  140. />
  141. <span class="pb-4 text-center">
  142. {{ $t("empty.authorization") }}
  143. </span>
  144. <ButtonSecondary
  145. outline
  146. :label="$t('app.documentation')"
  147. to="https://docs.hoppscotch.io/features/authorization"
  148. blank
  149. svg="external-link"
  150. reverse
  151. class="mb-4"
  152. />
  153. </div>
  154. <div v-else class="flex flex-1 border-b border-dividerLight">
  155. <div class="w-2/3 border-r border-dividerLight">
  156. <div v-if="authType === 'basic'">
  157. <div class="flex flex-1 border-b border-dividerLight">
  158. <SmartEnvInput
  159. v-model="basicUsername"
  160. :placeholder="$t('authorization.username')"
  161. styles="bg-transparent flex flex-1 py-1 px-4"
  162. />
  163. </div>
  164. <div class="flex flex-1 border-b border-dividerLight">
  165. <SmartEnvInput
  166. v-model="basicPassword"
  167. :placeholder="$t('authorization.password')"
  168. styles="bg-transparent flex flex-1 py-1 px-4"
  169. />
  170. </div>
  171. </div>
  172. <div v-if="authType === 'bearer'">
  173. <div class="flex flex-1 border-b border-dividerLight">
  174. <SmartEnvInput
  175. v-model="bearerToken"
  176. placeholder="Token"
  177. styles="bg-transparent flex flex-1 py-1 px-4"
  178. />
  179. </div>
  180. </div>
  181. <div v-if="authType === 'oauth-2'">
  182. <div class="flex flex-1 border-b border-dividerLight">
  183. <SmartEnvInput
  184. v-model="oauth2Token"
  185. placeholder="Token"
  186. styles="bg-transparent flex flex-1 py-1 px-4"
  187. />
  188. </div>
  189. <HttpOAuth2Authorization />
  190. </div>
  191. <div v-if="authType === 'api-key'">
  192. <div class="flex flex-1 border-b border-dividerLight">
  193. <SmartEnvInput
  194. v-model="apiKey"
  195. placeholder="Key"
  196. styles="bg-transparent flex flex-1 py-1 px-4"
  197. />
  198. </div>
  199. <div class="flex flex-1 border-b border-dividerLight">
  200. <SmartEnvInput
  201. v-model="apiValue"
  202. placeholder="Value"
  203. styles="bg-transparent flex flex-1 py-1 px-4"
  204. />
  205. </div>
  206. <div class="flex items-center border-b border-dividerLight">
  207. <label class="ml-4 text-secondaryLight">
  208. {{ $t("authorization.pass_key_by") }}
  209. </label>
  210. <tippy
  211. ref="addToOptions"
  212. interactive
  213. trigger="click"
  214. theme="popover"
  215. arrow
  216. >
  217. <template #trigger>
  218. <span class="select-wrapper">
  219. <ButtonSecondary
  220. :label="addTo || $t('state.none')"
  221. class="pr-8 ml-2 rounded-none"
  222. />
  223. </span>
  224. </template>
  225. <SmartItem
  226. :icon="
  227. addTo === 'Headers'
  228. ? 'radio_button_checked'
  229. : 'radio_button_unchecked'
  230. "
  231. :active="addTo === 'Headers'"
  232. :label="'Headers'"
  233. @click.native="
  234. () => {
  235. addTo = 'Headers'
  236. addToOptions.tippy().hide()
  237. }
  238. "
  239. />
  240. <SmartItem
  241. :icon="
  242. addTo === 'Query params'
  243. ? 'radio_button_checked'
  244. : 'radio_button_unchecked'
  245. "
  246. :active="addTo === 'Query params'"
  247. :label="'Query params'"
  248. @click.native="
  249. () => {
  250. addTo = 'Query params'
  251. addToOptions.tippy().hide()
  252. }
  253. "
  254. />
  255. </tippy>
  256. </div>
  257. </div>
  258. </div>
  259. <div
  260. class="sticky h-full p-4 overflow-auto bg-primary top-upperTertiaryStickyFold min-w-46 max-w-1/3 z-9"
  261. >
  262. <div class="pb-2 text-secondaryLight">
  263. {{ $t("helpers.authorization") }}
  264. </div>
  265. <SmartAnchor
  266. class="link"
  267. :label="`${$t('authorization.learn')} \xA0 →`"
  268. to="https://docs.hoppscotch.io/features/authorization"
  269. blank
  270. />
  271. </div>
  272. </div>
  273. </div>
  274. </template>
  275. <script setup lang="ts">
  276. import { computed, ref, Ref } from "@nuxtjs/composition-api"
  277. import {
  278. HoppGQLAuthAPIKey,
  279. HoppGQLAuthBasic,
  280. HoppGQLAuthBearer,
  281. HoppGQLAuthOAuth2,
  282. } from "@hoppscotch/data"
  283. import { pluckRef, useStream } from "~/helpers/utils/composables"
  284. import { gqlAuth$, setGQLAuth } from "~/newstore/GQLSession"
  285. const auth = useStream(
  286. gqlAuth$,
  287. { authType: "none", authActive: true },
  288. setGQLAuth
  289. )
  290. const authType = pluckRef(auth, "authType")
  291. const authName = computed(() => {
  292. if (authType.value === "basic") return "Basic Auth"
  293. else if (authType.value === "bearer") return "Bearer"
  294. else if (authType.value === "oauth-2") return "OAuth 2.0"
  295. else if (authType.value === "api-key") return "API key"
  296. else return "None"
  297. })
  298. const authActive = pluckRef(auth, "authActive")
  299. const basicUsername = pluckRef(auth as Ref<HoppGQLAuthBasic>, "username")
  300. const basicPassword = pluckRef(auth as Ref<HoppGQLAuthBasic>, "password")
  301. const bearerToken = pluckRef(auth as Ref<HoppGQLAuthBearer>, "token")
  302. const oauth2Token = pluckRef(auth as Ref<HoppGQLAuthOAuth2>, "token")
  303. const apiKey = pluckRef(auth as Ref<HoppGQLAuthAPIKey>, "key")
  304. const apiValue = pluckRef(auth as Ref<HoppGQLAuthAPIKey>, "value")
  305. const addTo = pluckRef(auth as Ref<HoppGQLAuthAPIKey>, "addTo")
  306. if (typeof addTo.value === "undefined") {
  307. addTo.value = "Headers"
  308. apiKey.value = ""
  309. apiValue.value = ""
  310. }
  311. const clearContent = () => {
  312. auth.value = {
  313. authType: "none",
  314. authActive: true,
  315. }
  316. }
  317. const authTypeOptions = ref<any | null>(null)
  318. const addToOptions = ref<any | null>(null)
  319. </script>