Authorization.vue 10 KB

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