@atproto/oauth-provider 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/account/account-manager.d.ts +7 -5
  3. package/dist/account/account-manager.d.ts.map +1 -1
  4. package/dist/account/account-manager.js +34 -25
  5. package/dist/account/account-manager.js.map +1 -1
  6. package/dist/account/account-store.d.ts +7 -0
  7. package/dist/account/account-store.d.ts.map +1 -1
  8. package/dist/account/account-store.js.map +1 -1
  9. package/dist/account/account.d.ts +1 -11
  10. package/dist/account/account.d.ts.map +1 -1
  11. package/dist/account/{sign-up-data.d.ts → sign-up-input.d.ts} +3 -3
  12. package/dist/account/sign-up-input.d.ts.map +1 -0
  13. package/dist/account/{sign-up-data.js → sign-up-input.js} +3 -3
  14. package/dist/account/sign-up-input.js.map +1 -0
  15. package/dist/assets/assets-middleware.d.ts +2 -0
  16. package/dist/assets/assets-middleware.d.ts.map +1 -1
  17. package/dist/assets/assets-middleware.js +12 -14
  18. package/dist/assets/assets-middleware.js.map +1 -1
  19. package/dist/lib/csp/index.d.ts +5 -6
  20. package/dist/lib/csp/index.d.ts.map +1 -1
  21. package/dist/lib/csp/index.js +14 -11
  22. package/dist/lib/csp/index.js.map +1 -1
  23. package/dist/lib/hcaptcha.d.ts +15 -12
  24. package/dist/lib/hcaptcha.d.ts.map +1 -1
  25. package/dist/lib/hcaptcha.js +11 -7
  26. package/dist/lib/hcaptcha.js.map +1 -1
  27. package/dist/lib/html/build-document.d.ts +2 -2
  28. package/dist/lib/html/build-document.d.ts.map +1 -1
  29. package/dist/lib/html/build-document.js +11 -7
  30. package/dist/lib/html/build-document.js.map +1 -1
  31. package/dist/lib/html/html.d.ts.map +1 -1
  32. package/dist/lib/html/html.js +10 -13
  33. package/dist/lib/html/html.js.map +1 -1
  34. package/dist/lib/html/util.d.ts +0 -1
  35. package/dist/lib/html/util.d.ts.map +1 -1
  36. package/dist/lib/html/util.js +0 -4
  37. package/dist/lib/html/util.js.map +1 -1
  38. package/dist/lib/http/response.d.ts +3 -1
  39. package/dist/lib/http/response.d.ts.map +1 -1
  40. package/dist/lib/http/response.js +3 -0
  41. package/dist/lib/http/response.js.map +1 -1
  42. package/dist/lib/http/security-headers.d.ts +48 -0
  43. package/dist/lib/http/security-headers.d.ts.map +1 -0
  44. package/dist/lib/http/security-headers.js +62 -0
  45. package/dist/lib/http/security-headers.js.map +1 -0
  46. package/dist/lib/util/type.d.ts +8 -0
  47. package/dist/lib/util/type.d.ts.map +1 -1
  48. package/dist/lib/util/type.js.map +1 -1
  49. package/dist/oauth-hooks.d.ts +4 -25
  50. package/dist/oauth-hooks.d.ts.map +1 -1
  51. package/dist/oauth-provider.js +2 -2
  52. package/dist/oauth-provider.js.map +1 -1
  53. package/dist/output/backend-data.d.ts +4 -0
  54. package/dist/output/backend-data.d.ts.map +1 -0
  55. package/dist/output/backend-data.js +19 -0
  56. package/dist/output/backend-data.js.map +1 -0
  57. package/dist/output/build-authorize-data.d.ts +3 -19
  58. package/dist/output/build-authorize-data.d.ts.map +1 -1
  59. package/dist/output/build-authorize-data.js.map +1 -1
  60. package/dist/output/build-customization-data.d.ts +11 -18
  61. package/dist/output/build-customization-data.d.ts.map +1 -1
  62. package/dist/output/build-customization-data.js +1 -1
  63. package/dist/output/build-customization-data.js.map +1 -1
  64. package/dist/output/build-error-data.d.ts +3 -0
  65. package/dist/output/build-error-data.d.ts.map +1 -0
  66. package/dist/output/build-error-data.js +10 -0
  67. package/dist/output/build-error-data.js.map +1 -0
  68. package/dist/output/build-error-payload.d.ts +2 -1
  69. package/dist/output/build-error-payload.d.ts.map +1 -1
  70. package/dist/output/build-error-payload.js.map +1 -1
  71. package/dist/output/output-manager.d.ts +10 -4
  72. package/dist/output/output-manager.d.ts.map +1 -1
  73. package/dist/output/output-manager.js +68 -39
  74. package/dist/output/output-manager.js.map +1 -1
  75. package/dist/output/send-web-page.d.ts +6 -10
  76. package/dist/output/send-web-page.d.ts.map +1 -1
  77. package/dist/output/send-web-page.js +27 -47
  78. package/dist/output/send-web-page.js.map +1 -1
  79. package/dist/signer/signed-token-payload.d.ts +3 -3
  80. package/dist/signer/signer.d.ts +2 -2
  81. package/package.json +8 -41
  82. package/src/account/account-manager.ts +55 -34
  83. package/src/account/account-store.ts +8 -0
  84. package/src/account/account.ts +1 -14
  85. package/src/account/{sign-up-data.ts → sign-up-input.ts} +2 -2
  86. package/src/assets/assets-middleware.ts +11 -17
  87. package/src/lib/csp/index.ts +16 -13
  88. package/src/lib/hcaptcha.ts +14 -10
  89. package/src/lib/html/build-document.ts +15 -8
  90. package/src/lib/html/html.ts +11 -18
  91. package/src/lib/html/util.ts +0 -4
  92. package/src/lib/http/response.ts +9 -1
  93. package/src/lib/http/security-headers.ts +91 -0
  94. package/src/lib/util/type.ts +18 -0
  95. package/src/oauth-hooks.ts +4 -25
  96. package/src/oauth-provider.ts +2 -2
  97. package/src/output/backend-data.ts +18 -0
  98. package/src/output/build-authorize-data.ts +3 -26
  99. package/src/output/build-customization-data.ts +2 -13
  100. package/src/output/build-error-data.ts +8 -0
  101. package/src/output/build-error-payload.ts +4 -2
  102. package/src/output/output-manager.ts +86 -47
  103. package/src/output/send-web-page.ts +29 -58
  104. package/tsconfig.backend.json +1 -2
  105. package/tsconfig.backend.tsbuildinfo +1 -1
  106. package/tsconfig.json +1 -5
  107. package/.linguirc +0 -57
  108. package/dist/account/sign-up-data.d.ts.map +0 -1
  109. package/dist/account/sign-up-data.js.map +0 -1
  110. package/dist/assets/app/bundle-manifest.json +0 -614
  111. package/dist/assets/app/index-DZHZ9kCP.js +0 -36
  112. package/dist/assets/app/index-DZHZ9kCP.js.map +0 -1
  113. package/dist/assets/app/main-B_dNxQo_.js +0 -4
  114. package/dist/assets/app/main-B_dNxQo_.js.map +0 -1
  115. package/dist/assets/app/main-Dr6y26KY.css +0 -3
  116. package/dist/assets/app/main-Dr6y26KY.js +0 -306
  117. package/dist/assets/app/main-Dr6y26KY.js.map +0 -1
  118. package/dist/assets/app/messages-6_mYuGzB.js +0 -4
  119. package/dist/assets/app/messages-6_mYuGzB.js.map +0 -1
  120. package/dist/assets/app/messages-7wdeBTpD.js +0 -4
  121. package/dist/assets/app/messages-7wdeBTpD.js.map +0 -1
  122. package/dist/assets/app/messages-B-YFoWKc.js +0 -4
  123. package/dist/assets/app/messages-B-YFoWKc.js.map +0 -1
  124. package/dist/assets/app/messages-B10DUOE-.js +0 -4
  125. package/dist/assets/app/messages-B10DUOE-.js.map +0 -1
  126. package/dist/assets/app/messages-B4AwFEeZ.js +0 -4
  127. package/dist/assets/app/messages-B4AwFEeZ.js.map +0 -1
  128. package/dist/assets/app/messages-BDP8MyEC.js +0 -4
  129. package/dist/assets/app/messages-BDP8MyEC.js.map +0 -1
  130. package/dist/assets/app/messages-BIS87lxQ.js +0 -4
  131. package/dist/assets/app/messages-BIS87lxQ.js.map +0 -1
  132. package/dist/assets/app/messages-BI_Wbjdt.js +0 -4
  133. package/dist/assets/app/messages-BI_Wbjdt.js.map +0 -1
  134. package/dist/assets/app/messages-BMAouhRx.js +0 -4
  135. package/dist/assets/app/messages-BMAouhRx.js.map +0 -1
  136. package/dist/assets/app/messages-BdckMnJj.js +0 -4
  137. package/dist/assets/app/messages-BdckMnJj.js.map +0 -1
  138. package/dist/assets/app/messages-BgBLzc46.js +0 -4
  139. package/dist/assets/app/messages-BgBLzc46.js.map +0 -1
  140. package/dist/assets/app/messages-BobD78yK.js +0 -4
  141. package/dist/assets/app/messages-BobD78yK.js.map +0 -1
  142. package/dist/assets/app/messages-BtThT9UZ.js +0 -4
  143. package/dist/assets/app/messages-BtThT9UZ.js.map +0 -1
  144. package/dist/assets/app/messages-BwKHkbeh.js +0 -4
  145. package/dist/assets/app/messages-BwKHkbeh.js.map +0 -1
  146. package/dist/assets/app/messages-C417YUvA.js +0 -4
  147. package/dist/assets/app/messages-C417YUvA.js.map +0 -1
  148. package/dist/assets/app/messages-C4CxO4bO.js +0 -4
  149. package/dist/assets/app/messages-C4CxO4bO.js.map +0 -1
  150. package/dist/assets/app/messages-C5vd04e6.js +0 -4
  151. package/dist/assets/app/messages-C5vd04e6.js.map +0 -1
  152. package/dist/assets/app/messages-CAri2Wnz.js +0 -4
  153. package/dist/assets/app/messages-CAri2Wnz.js.map +0 -1
  154. package/dist/assets/app/messages-CPtWTZeG.js +0 -4
  155. package/dist/assets/app/messages-CPtWTZeG.js.map +0 -1
  156. package/dist/assets/app/messages-CiaM5zm8.js +0 -4
  157. package/dist/assets/app/messages-CiaM5zm8.js.map +0 -1
  158. package/dist/assets/app/messages-CkL-L2R6.js +0 -4
  159. package/dist/assets/app/messages-CkL-L2R6.js.map +0 -1
  160. package/dist/assets/app/messages-Cy_4XLNe.js +0 -4
  161. package/dist/assets/app/messages-Cy_4XLNe.js.map +0 -1
  162. package/dist/assets/app/messages-D5_ad-Eo.js +0 -4
  163. package/dist/assets/app/messages-D5_ad-Eo.js.map +0 -1
  164. package/dist/assets/app/messages-DChMl9mT.js +0 -4
  165. package/dist/assets/app/messages-DChMl9mT.js.map +0 -1
  166. package/dist/assets/app/messages-DWX-DIfv.js +0 -4
  167. package/dist/assets/app/messages-DWX-DIfv.js.map +0 -1
  168. package/dist/assets/app/messages-DgfsOphe.js +0 -4
  169. package/dist/assets/app/messages-DgfsOphe.js.map +0 -1
  170. package/dist/assets/app/messages-Dj5B_DR6.js +0 -4
  171. package/dist/assets/app/messages-Dj5B_DR6.js.map +0 -1
  172. package/dist/assets/app/messages-Dwzqo4eA.js +0 -4
  173. package/dist/assets/app/messages-Dwzqo4eA.js.map +0 -1
  174. package/dist/assets/app/messages-ESCIXJR7.js +0 -4
  175. package/dist/assets/app/messages-ESCIXJR7.js.map +0 -1
  176. package/dist/assets/app/messages-dglB2edb.js +0 -4
  177. package/dist/assets/app/messages-dglB2edb.js.map +0 -1
  178. package/dist/assets/app/messages-e_ClRrWc.js +0 -4
  179. package/dist/assets/app/messages-e_ClRrWc.js.map +0 -1
  180. package/dist/assets/app/messages-evvDxmrP.js +0 -4
  181. package/dist/assets/app/messages-evvDxmrP.js.map +0 -1
  182. package/dist/assets/app/messages-pPbdLb5B.js +0 -4
  183. package/dist/assets/app/messages-pPbdLb5B.js.map +0 -1
  184. package/dist/assets/app/messages-tJv8gHL2.js +0 -4
  185. package/dist/assets/app/messages-tJv8gHL2.js.map +0 -1
  186. package/dist/assets/app/messages-vLRVEw96.js +0 -4
  187. package/dist/assets/app/messages-vLRVEw96.js.map +0 -1
  188. package/dist/assets/asset.d.ts +0 -9
  189. package/dist/assets/asset.d.ts.map +0 -1
  190. package/dist/assets/asset.js +0 -3
  191. package/dist/assets/asset.js.map +0 -1
  192. package/dist/assets/index.d.ts +0 -5
  193. package/dist/assets/index.d.ts.map +0 -1
  194. package/dist/assets/index.js +0 -78
  195. package/dist/assets/index.js.map +0 -1
  196. package/rollup.config.js +0 -98
  197. package/src/assets/app/app.tsx +0 -43
  198. package/src/assets/app/backend-data.ts +0 -27
  199. package/src/assets/app/backend-types.ts +0 -66
  200. package/src/assets/app/components/forms/button-toggle-visibility.tsx +0 -43
  201. package/src/assets/app/components/forms/button.tsx +0 -60
  202. package/src/assets/app/components/forms/fieldset.tsx +0 -55
  203. package/src/assets/app/components/forms/form-card-async.tsx +0 -103
  204. package/src/assets/app/components/forms/form-card.tsx +0 -49
  205. package/src/assets/app/components/forms/input-checkbox.tsx +0 -78
  206. package/src/assets/app/components/forms/input-container.tsx +0 -107
  207. package/src/assets/app/components/forms/input-email-address.tsx +0 -65
  208. package/src/assets/app/components/forms/input-new-password.tsx +0 -62
  209. package/src/assets/app/components/forms/input-password.tsx +0 -87
  210. package/src/assets/app/components/forms/input-text.tsx +0 -82
  211. package/src/assets/app/components/forms/input-token.tsx +0 -94
  212. package/src/assets/app/components/forms/wizard-card.tsx +0 -116
  213. package/src/assets/app/components/layouts/layout-title-page.tsx +0 -77
  214. package/src/assets/app/components/layouts/layout-welcome.tsx +0 -73
  215. package/src/assets/app/components/utils/account-identifier.tsx +0 -23
  216. package/src/assets/app/components/utils/account-image.tsx +0 -33
  217. package/src/assets/app/components/utils/admonition.tsx +0 -52
  218. package/src/assets/app/components/utils/client-name.tsx +0 -45
  219. package/src/assets/app/components/utils/error-card.tsx +0 -93
  220. package/src/assets/app/components/utils/error-message.tsx +0 -88
  221. package/src/assets/app/components/utils/help-card.tsx +0 -46
  222. package/src/assets/app/components/utils/icons.tsx +0 -88
  223. package/src/assets/app/components/utils/link-anchor.tsx +0 -28
  224. package/src/assets/app/components/utils/link-title.tsx +0 -26
  225. package/src/assets/app/components/utils/multi-lang-string.tsx +0 -56
  226. package/src/assets/app/components/utils/password-strength-label.tsx +0 -37
  227. package/src/assets/app/components/utils/password-strength-meter.tsx +0 -58
  228. package/src/assets/app/components/utils/url-viewer.tsx +0 -73
  229. package/src/assets/app/cookies.ts +0 -11
  230. package/src/assets/app/hooks/use-api.ts +0 -178
  231. package/src/assets/app/hooks/use-async-action.ts +0 -120
  232. package/src/assets/app/hooks/use-bound-dispatch.ts +0 -5
  233. package/src/assets/app/hooks/use-browser-color-scheme.ts +0 -31
  234. package/src/assets/app/hooks/use-csrf-token.ts +0 -5
  235. package/src/assets/app/hooks/use-random-string.ts +0 -37
  236. package/src/assets/app/hooks/use-stepper.ts +0 -87
  237. package/src/assets/app/index.html +0 -182
  238. package/src/assets/app/lib/api.ts +0 -289
  239. package/src/assets/app/lib/clsx.ts +0 -6
  240. package/src/assets/app/lib/json-client.ts +0 -94
  241. package/src/assets/app/lib/password.ts +0 -98
  242. package/src/assets/app/lib/ref.ts +0 -17
  243. package/src/assets/app/lib/util.ts +0 -13
  244. package/src/assets/app/locales/an/messages.po +0 -490
  245. package/src/assets/app/locales/ast/messages.po +0 -490
  246. package/src/assets/app/locales/ca/messages.po +0 -490
  247. package/src/assets/app/locales/da/messages.po +0 -490
  248. package/src/assets/app/locales/de/messages.po +0 -490
  249. package/src/assets/app/locales/el/messages.po +0 -490
  250. package/src/assets/app/locales/en/messages.po +0 -490
  251. package/src/assets/app/locales/en-GB/messages.po +0 -490
  252. package/src/assets/app/locales/es/messages.po +0 -490
  253. package/src/assets/app/locales/eu/messages.po +0 -490
  254. package/src/assets/app/locales/fi/messages.po +0 -490
  255. package/src/assets/app/locales/fr/messages.po +0 -490
  256. package/src/assets/app/locales/ga/messages.po +0 -490
  257. package/src/assets/app/locales/gl/messages.po +0 -490
  258. package/src/assets/app/locales/hi/messages.po +0 -490
  259. package/src/assets/app/locales/hu/messages.po +0 -490
  260. package/src/assets/app/locales/ia/messages.po +0 -490
  261. package/src/assets/app/locales/id/messages.po +0 -490
  262. package/src/assets/app/locales/it/messages.po +0 -490
  263. package/src/assets/app/locales/ja/messages.po +0 -490
  264. package/src/assets/app/locales/km/messages.po +0 -490
  265. package/src/assets/app/locales/ko/messages.po +0 -490
  266. package/src/assets/app/locales/load.ts +0 -8
  267. package/src/assets/app/locales/locale-context.ts +0 -19
  268. package/src/assets/app/locales/locale-provider.tsx +0 -112
  269. package/src/assets/app/locales/locale-selector.tsx +0 -58
  270. package/src/assets/app/locales/locales.ts +0 -168
  271. package/src/assets/app/locales/ne/messages.po +0 -490
  272. package/src/assets/app/locales/nl/messages.po +0 -490
  273. package/src/assets/app/locales/pl/messages.po +0 -490
  274. package/src/assets/app/locales/pt-BR/messages.po +0 -490
  275. package/src/assets/app/locales/ro/messages.po +0 -490
  276. package/src/assets/app/locales/ru/messages.po +0 -490
  277. package/src/assets/app/locales/sv/messages.po +0 -490
  278. package/src/assets/app/locales/th/messages.po +0 -490
  279. package/src/assets/app/locales/tr/messages.po +0 -490
  280. package/src/assets/app/locales/uk/messages.po +0 -490
  281. package/src/assets/app/locales/vi/messages.po +0 -490
  282. package/src/assets/app/locales/zh-CN/messages.po +0 -490
  283. package/src/assets/app/locales/zh-HK/messages.po +0 -490
  284. package/src/assets/app/locales/zh-TW/messages.po +0 -490
  285. package/src/assets/app/main.css +0 -33
  286. package/src/assets/app/main.tsx +0 -44
  287. package/src/assets/app/views/authorize/accept/accept-form.tsx +0 -150
  288. package/src/assets/app/views/authorize/accept/accept-view.tsx +0 -70
  289. package/src/assets/app/views/authorize/authorize-view.tsx +0 -180
  290. package/src/assets/app/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
  291. package/src/assets/app/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
  292. package/src/assets/app/views/authorize/reset-password/reset-password-view.tsx +0 -127
  293. package/src/assets/app/views/authorize/sign-in/sign-in-form.tsx +0 -242
  294. package/src/assets/app/views/authorize/sign-in/sign-in-picker.tsx +0 -116
  295. package/src/assets/app/views/authorize/sign-in/sign-in-view.tsx +0 -145
  296. package/src/assets/app/views/authorize/sign-up/sign-up-account-form.tsx +0 -142
  297. package/src/assets/app/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
  298. package/src/assets/app/views/authorize/sign-up/sign-up-handle-form.tsx +0 -287
  299. package/src/assets/app/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
  300. package/src/assets/app/views/authorize/sign-up/sign-up-view.tsx +0 -158
  301. package/src/assets/app/views/authorize/welcome/welcome-view.tsx +0 -56
  302. package/src/assets/app/views/error/error-view.tsx +0 -31
  303. package/src/assets/asset.ts +0 -9
  304. package/src/assets/index.ts +0 -86
  305. package/tailwind.config.js +0 -31
  306. package/tsconfig.frontend.json +0 -11
  307. package/tsconfig.frontend.tsbuildinfo +0 -1
  308. package/tsconfig.tools.json +0 -8
  309. package/tsconfig.tools.tsbuildinfo +0 -1
  310. package/vite.config.mjs +0 -16
@@ -1,242 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { useCallback, useRef, useState } from 'react'
3
- import { Button } from '../../../components/forms/button.tsx'
4
- import { Fieldset } from '../../../components/forms/fieldset.tsx'
5
- import {
6
- FormCardAsync,
7
- FormCardAsyncProps,
8
- } from '../../../components/forms/form-card-async.tsx'
9
- import { InputCheckbox } from '../../../components/forms/input-checkbox.tsx'
10
- import { InputPassword } from '../../../components/forms/input-password.tsx'
11
- import { InputText } from '../../../components/forms/input-text.tsx'
12
- import { InputToken } from '../../../components/forms/input-token.tsx'
13
- import { Admonition } from '../../../components/utils/admonition.tsx'
14
- import { AtSymbolIcon } from '../../../components/utils/icons.tsx'
15
- import { AsyncActionController } from '../../../hooks/use-async-action.ts'
16
- import {
17
- InvalidCredentialsError,
18
- SecondAuthenticationFactorRequiredError,
19
- } from '../../../lib/api.ts'
20
- import { mergeRefs } from '../../../lib/ref.ts'
21
- import { Override } from '../../../lib/util.ts'
22
-
23
- export type SignInFormOutput = {
24
- username: string
25
- password: string
26
- remember?: boolean
27
- }
28
-
29
- export type SignInFormProps = Override<
30
- Omit<FormCardAsyncProps, 'append' | 'onCancel'>,
31
- {
32
- usernameDefault?: string
33
- usernameReadonly?: boolean
34
- rememberDefault?: boolean
35
-
36
- onBack?: () => void
37
- onForgotPassword?: (emailHint?: string) => void
38
- onSubmit: (
39
- credentials: SignInFormOutput,
40
- signal: AbortSignal,
41
- ) => void | PromiseLike<void>
42
- }
43
- >
44
-
45
- export function SignInForm({
46
- usernameDefault = '',
47
- usernameReadonly = false,
48
- rememberDefault = false,
49
-
50
- onSubmit,
51
- onBack,
52
- onForgotPassword,
53
-
54
- // FormCardAsync
55
- ref,
56
- invalid,
57
- children,
58
- ...props
59
- }: SignInFormProps) {
60
- const { t } = useLingui()
61
-
62
- const [username, setUsername] = useState<string>(usernameDefault)
63
- const [password, setPassword] = useState<string>('')
64
- const [remember, setRemember] = useState<boolean>(rememberDefault)
65
- const [otp, setOtp] = useState<string | null>(null)
66
-
67
- const [secondFactor, setSecondFactor] =
68
- useState<null | SecondAuthenticationFactorRequiredError>(null)
69
-
70
- const [loading, setLoading] = useState(false)
71
-
72
- const formRef = useRef<AsyncActionController>(null)
73
-
74
- const clearSecondFactor = useCallback(() => {
75
- setOtp(null)
76
- setSecondFactor(null)
77
- }, [setOtp, setSecondFactor])
78
-
79
- const resetState = useCallback(() => {
80
- clearSecondFactor()
81
- formRef.current?.reset()
82
- }, [clearSecondFactor, formRef])
83
-
84
- const doSubmit = useCallback(
85
- async (signal: AbortSignal) => {
86
- try {
87
- await onSubmit(
88
- {
89
- username,
90
- password,
91
- remember,
92
- ...(secondFactor ? { [secondFactor.type]: otp } : {}),
93
- },
94
- signal,
95
- )
96
- } catch (err) {
97
- if (signal.aborted) {
98
- // If the action was aborted, ignore the error
99
- return
100
- }
101
-
102
- if (err instanceof SecondAuthenticationFactorRequiredError) {
103
- setSecondFactor(err)
104
-
105
- // Do not re-throw 2FA required error to prevent the form from from
106
- // displaying it. Instead, we handle the error by showing the second
107
- // factor form.
108
- return
109
- }
110
-
111
- if (err instanceof InvalidCredentialsError) {
112
- // If the username/password are not valid, clear the second factor
113
- // as valid credentials are a pre-requisite for 2FA.
114
- clearSecondFactor()
115
- }
116
-
117
- // Any thrown err will be displayed through the form's errorRender
118
- throw err
119
- }
120
- },
121
- [username, password, remember, secondFactor, otp, onSubmit],
122
- )
123
-
124
- return (
125
- <FormCardAsync
126
- {...props}
127
- ref={mergeRefs([ref, formRef])}
128
- onLoading={setLoading}
129
- onCancel={onBack}
130
- cancelLabel={t`Back`}
131
- append={children}
132
- invalid={
133
- invalid || !username || !password || (secondFactor != null && !otp)
134
- }
135
- submitLabel={secondFactor ? t`Confirm` : t`Sign in`}
136
- onSubmit={doSubmit}
137
- >
138
- <Fieldset disabled={loading} label={<Trans>Account</Trans>}>
139
- <InputText
140
- icon={<AtSymbolIcon className="w-5" />}
141
- name="username"
142
- type="text"
143
- title={t`Username or email address`}
144
- autoCapitalize="none"
145
- autoCorrect="off"
146
- autoComplete="username"
147
- spellCheck="false"
148
- dir="auto"
149
- enterKeyHint="next"
150
- required
151
- readOnly={usernameReadonly}
152
- disabled={usernameReadonly}
153
- autoFocus
154
- value={username}
155
- onChange={(event) => {
156
- resetState()
157
- setUsername(event.target.value)
158
- }}
159
- />
160
- </Fieldset>
161
-
162
- <InputPassword
163
- name="password"
164
- onChange={(event) => {
165
- resetState()
166
- setPassword(event.target.value)
167
- }}
168
- append={
169
- onForgotPassword && (
170
- <Button
171
- className="text-sm"
172
- type="button"
173
- onClick={() => {
174
- onForgotPassword(username?.includes('@') ? username : undefined)
175
- }}
176
- aria-label={t`Reset your password`}
177
- >
178
- <Trans>Forgot?</Trans>
179
- </Button>
180
- )
181
- }
182
- enterKeyHint={secondFactor ? 'next' : 'done'}
183
- disabled={loading}
184
- required
185
- />
186
-
187
- <Admonition role="status">
188
- <p className="font-bold text-md text-brand pb-1">
189
- <Trans>Warning</Trans>
190
- </p>
191
- <p className="text-sm">
192
- <Trans>
193
- Please verify the domain name of the website before entering your
194
- password. Never enter your password on a domain you do not trust.
195
- </Trans>
196
- </p>
197
- </Admonition>
198
-
199
- <Fieldset
200
- key="remember"
201
- disabled={loading}
202
- label={<Trans>Session</Trans>}
203
- >
204
- <InputCheckbox
205
- name="remember"
206
- title={t`Remember this account on this device`}
207
- enterKeyHint={secondFactor ? 'next' : 'done'}
208
- checked={remember}
209
- onChange={(event) => setRemember(event.target.checked)}
210
- >
211
- <Trans>Remember this account on this device</Trans>
212
- </InputCheckbox>
213
- </Fieldset>
214
-
215
- {secondFactor && (
216
- <Fieldset
217
- key="2fa"
218
- disabled={loading}
219
- label={<Trans>2FA Confirmation</Trans>}
220
- >
221
- <div>
222
- <InputToken
223
- title={t`Confirmation code`}
224
- enterKeyHint="done"
225
- required
226
- autoFocus={true}
227
- value={otp ?? ''}
228
- onToken={setOtp}
229
- />
230
-
231
- <p className="text-slate-600 dark:text-slate-400 text-sm">
232
- <Trans>
233
- Check your {secondFactor.hint} email for a login code and enter
234
- it here.
235
- </Trans>
236
- </p>
237
- </div>
238
- </Fieldset>
239
- )}
240
- </FormCardAsync>
241
- )
242
- }
@@ -1,116 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { Account } from '../../../backend-types.ts'
3
- import { Button } from '../../../components/forms/button.tsx'
4
- import {
5
- FormCard,
6
- FormCardProps,
7
- } from '../../../components/forms/form-card.tsx'
8
- import { InputContainer } from '../../../components/forms/input-container.tsx'
9
- import { AccountImage } from '../../../components/utils/account-image.tsx'
10
- import {
11
- AtSymbolIcon,
12
- CaretRightIcon,
13
- } from '../../../components/utils/icons.tsx'
14
- import { Override } from '../../../lib/util.ts'
15
-
16
- export type SignInPickerProps = Override<
17
- Omit<FormCardProps, 'cancel' | 'actions' | 'append'>,
18
- {
19
- accounts: readonly Account[]
20
-
21
- onAccount: (account: Account) => void
22
- onOther?: () => void
23
- onBack?: () => void
24
- }
25
- >
26
-
27
- export function SignInPicker({
28
- accounts,
29
-
30
- onAccount,
31
- onOther = undefined,
32
- onBack,
33
-
34
- // FormCard
35
- children,
36
- ...props
37
- }: SignInPickerProps) {
38
- const { t } = useLingui()
39
- return (
40
- <FormCard
41
- {...props}
42
- append={children}
43
- actions={null}
44
- cancel={
45
- onBack && (
46
- <Button onClick={onBack}>
47
- <Trans>Back</Trans>
48
- </Button>
49
- )
50
- }
51
- >
52
- <p className="text-slate-600 dark:text-slate-400 text-sm font-medium">
53
- <Trans>Sign in as...</Trans>
54
- </p>
55
-
56
- {accounts.map((account) => {
57
- const [name, identifier] = [
58
- account.name,
59
- account.preferred_username,
60
- account.email,
61
- account.sub,
62
- ].filter(Boolean) as [string, string?]
63
-
64
- return (
65
- <InputContainer
66
- tabIndex={0}
67
- key={account.sub}
68
- onKeyDown={(event) => {
69
- if (event.key === 'Enter' || event.key === ' ') {
70
- onAccount(account)
71
- }
72
- }}
73
- onClick={() => onAccount(account)}
74
- role="button"
75
- aria-label={t`Sign in as ${account.name}`}
76
- icon={<AccountImage src={account.picture} alt={name} />}
77
- append={<CaretRightIcon aria-hidden className="h-4" />}
78
- >
79
- <span className="flex flex-wrap items-center">
80
- <span className="font-medium truncate mr-2" arial-label={t`Name`}>
81
- {name}
82
- </span>
83
- {identifier && (
84
- <span
85
- className="text-sm text-neutral-500 dark:text-neutral-400 truncate"
86
- arial-label={t`Identifier`}
87
- >
88
- {identifier}
89
- </span>
90
- )}
91
- </span>
92
- </InputContainer>
93
- )
94
- })}
95
-
96
- {onOther && (
97
- <InputContainer
98
- key="other"
99
- tabIndex={0}
100
- onKeyDown={(event) => {
101
- if (event.key === 'Enter' || event.key === ' ') onOther()
102
- }}
103
- onClick={onOther}
104
- aria-label={t`Login to account that is not listed`}
105
- role="button"
106
- append={<CaretRightIcon aria-hidden className="h-4" />}
107
- icon={<AtSymbolIcon aria-hidden className="h-4" />}
108
- >
109
- <span className="truncate text-slate-700 dark:text-slate-400">
110
- <Trans>Another account</Trans>
111
- </span>
112
- </InputContainer>
113
- )}
114
- </FormCard>
115
- )
116
- }
@@ -1,145 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { useCallback, useEffect, useMemo, useState } from 'react'
3
- import { Session } from '../../../backend-types.ts'
4
- import {
5
- LayoutTitlePage,
6
- LayoutTitlePageProps,
7
- } from '../../../components/layouts/layout-title-page.tsx'
8
- import { Override } from '../../../lib/util.ts'
9
- import { SignInForm, SignInFormOutput } from './sign-in-form.tsx'
10
- import { SignInPicker } from './sign-in-picker.tsx'
11
-
12
- export type SignInViewProps = Override<
13
- LayoutTitlePageProps,
14
- {
15
- sessions: readonly Session[]
16
- selectSub: (sub: string | null) => void
17
- loginHint?: string
18
-
19
- onSignIn: (
20
- credentials: SignInFormOutput,
21
- signal: AbortSignal,
22
- ) => void | PromiseLike<void>
23
- onForgotPassword?: (emailHint?: string) => void
24
- onBack?: () => void
25
- }
26
- >
27
-
28
- export function SignInView({
29
- loginHint,
30
- sessions,
31
- selectSub,
32
-
33
- onSignIn,
34
- onForgotPassword,
35
- onBack,
36
-
37
- // LayoutTitlePage
38
- title,
39
- subtitle,
40
- ...props
41
- }: SignInViewProps) {
42
- const { t } = useLingui()
43
- const session = useMemo(() => sessions.find((s) => s.selected), [sessions])
44
- const clearSession = useCallback(() => selectSub(null), [selectSub])
45
- const accounts = useMemo(() => sessions.map((s) => s.account), [sessions])
46
- const [showSignInForm, setShowSignInForm] = useState(sessions.length === 0)
47
-
48
- title ??= t`Sign in`
49
-
50
- useEffect(() => {
51
- // Make sure the "back" action shows the account picker instead of the
52
- // sign-in form (since the account was added to the list of current
53
- // sessions).
54
- if (session) setShowSignInForm(false)
55
- }, [session])
56
-
57
- if (session) {
58
- // All set (parent view will handle the redirect)
59
- if (!session.loginRequired) return null
60
-
61
- return (
62
- <LayoutTitlePage
63
- {...props}
64
- title={title}
65
- subtitle={subtitle ?? <Trans>Confirm your password to continue</Trans>}
66
- >
67
- <SignInForm
68
- onSubmit={onSignIn}
69
- onForgotPassword={onForgotPassword}
70
- onBack={clearSession}
71
- usernameDefault={
72
- session.account.preferred_username || session.account.sub
73
- }
74
- usernameReadonly={true}
75
- rememberDefault={true}
76
- />
77
- </LayoutTitlePage>
78
- )
79
- }
80
-
81
- if (loginHint) {
82
- return (
83
- <LayoutTitlePage
84
- {...props}
85
- title={title}
86
- subtitle={subtitle ?? <Trans>Enter your password</Trans>}
87
- >
88
- <SignInForm
89
- onSubmit={onSignIn}
90
- onForgotPassword={onForgotPassword}
91
- onBack={onBack}
92
- usernameDefault={loginHint}
93
- usernameReadonly={true}
94
- />
95
- </LayoutTitlePage>
96
- )
97
- }
98
-
99
- if (sessions.length === 0) {
100
- return (
101
- <LayoutTitlePage
102
- {...props}
103
- title={title}
104
- subtitle={subtitle ?? <Trans>Enter your username and password</Trans>}
105
- >
106
- <SignInForm
107
- onSubmit={onSignIn}
108
- onForgotPassword={onForgotPassword}
109
- onBack={onBack}
110
- />
111
- </LayoutTitlePage>
112
- )
113
- }
114
-
115
- if (showSignInForm) {
116
- return (
117
- <LayoutTitlePage
118
- {...props}
119
- title={title}
120
- subtitle={subtitle ?? <Trans>Enter your username and password</Trans>}
121
- >
122
- <SignInForm
123
- onSubmit={onSignIn}
124
- onForgotPassword={onForgotPassword}
125
- onBack={() => setShowSignInForm(false)}
126
- />
127
- </LayoutTitlePage>
128
- )
129
- }
130
-
131
- return (
132
- <LayoutTitlePage
133
- {...props}
134
- title={title}
135
- subtitle={subtitle ?? <Trans>Select from an existing account</Trans>}
136
- >
137
- <SignInPicker
138
- accounts={accounts}
139
- onAccount={(a) => selectSub(a.sub)}
140
- onOther={() => setShowSignInForm(true)}
141
- onBack={onBack}
142
- />
143
- </LayoutTitlePage>
144
- )
145
- }
@@ -1,142 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { ReactNode, useEffect, useMemo, useRef, useState } from 'react'
3
- import { Fieldset } from '../../../components/forms/fieldset.tsx'
4
- import {
5
- AsyncActionController,
6
- FormCardAsync,
7
- FormCardAsyncProps,
8
- } from '../../../components/forms/form-card-async.tsx'
9
- import { InputEmailAddress } from '../../../components/forms/input-email-address.tsx'
10
- import { InputNewPassword } from '../../../components/forms/input-new-password.tsx'
11
- import { InputText } from '../../../components/forms/input-text.tsx'
12
- import { TokenIcon } from '../../../components/utils/icons.tsx'
13
- import { mergeRefs } from '../../../lib/ref.ts'
14
- import { Override } from '../../../lib/util.ts'
15
-
16
- export type SignUpAccountFormOutput = {
17
- email: string
18
- password: string
19
- inviteCode?: string
20
- }
21
-
22
- export type SignUpAccountFormProps = Override<
23
- Omit<
24
- FormCardAsyncProps,
25
- 'append' | 'onCancel' | 'onSubmit' | 'submitLabel' | 'cancelLabel'
26
- >,
27
- {
28
- inviteCodeRequired?: boolean
29
-
30
- credentials?: SignUpAccountFormOutput
31
- onCredentials?: (credentials?: SignUpAccountFormOutput) => void
32
-
33
- onNext: (signal: AbortSignal) => void | PromiseLike<void>
34
- nextLabel?: ReactNode
35
-
36
- onPrev?: () => void
37
- prevLabel?: ReactNode
38
- }
39
- >
40
-
41
- export function SignUpAccountForm({
42
- inviteCodeRequired = true,
43
-
44
- credentials: creds,
45
- onCredentials,
46
-
47
- onNext,
48
- nextLabel,
49
-
50
- onPrev,
51
- prevLabel,
52
-
53
- // FormCardAsyncProps
54
- children,
55
- ref,
56
- invalid,
57
- ...props
58
- }: SignUpAccountFormProps) {
59
- const { t } = useLingui()
60
-
61
- const [email, setEmail] = useState(creds?.email)
62
- const [password, setPassword] = useState(creds?.password)
63
- const [inviteCode, setInviteCode] = useState(creds?.inviteCode)
64
-
65
- const formRef = useRef<AsyncActionController>(null)
66
- const resetForm = () => formRef.current?.reset()
67
-
68
- const credentials = useMemo(
69
- () =>
70
- email && password && (!inviteCodeRequired || inviteCode)
71
- ? {
72
- email,
73
- password,
74
- inviteCode: inviteCodeRequired ? inviteCode : undefined,
75
- }
76
- : undefined,
77
- [email, password, inviteCode, inviteCodeRequired],
78
- )
79
-
80
- useEffect(() => {
81
- onCredentials?.(credentials)
82
- }, [credentials, onCredentials])
83
-
84
- return (
85
- <FormCardAsync
86
- {...props}
87
- ref={mergeRefs([ref, formRef])}
88
- invalid={invalid || !credentials}
89
- onCancel={onPrev}
90
- cancelLabel={prevLabel}
91
- onSubmit={onNext}
92
- submitLabel={nextLabel}
93
- append={children}
94
- >
95
- {inviteCodeRequired && (
96
- <Fieldset label={<Trans>Invite code</Trans>}>
97
- <InputText
98
- icon={<TokenIcon className="w-5" />}
99
- autoFocus
100
- name="inviteCode"
101
- title={t`Invite code`}
102
- placeholder={t`example-com-xxxxx-xxxxx`}
103
- required
104
- value={inviteCode || ''}
105
- onChange={(event) => {
106
- setInviteCode(event.target.value || undefined)
107
- resetForm()
108
- }}
109
- enterKeyHint="next"
110
- />
111
- </Fieldset>
112
- )}
113
-
114
- <Fieldset label={<Trans>Email</Trans>}>
115
- <InputEmailAddress
116
- autoFocus={!inviteCodeRequired}
117
- name="email"
118
- enterKeyHint="next"
119
- required
120
- defaultValue={email}
121
- onEmail={(email) => {
122
- setEmail(email)
123
- resetForm()
124
- }}
125
- />
126
- </Fieldset>
127
-
128
- <Fieldset label={<Trans>Password</Trans>}>
129
- <InputNewPassword
130
- name="password"
131
- enterKeyHint="next"
132
- required
133
- password={password}
134
- onPassword={(value) => {
135
- setPassword(value)
136
- resetForm()
137
- }}
138
- />
139
- </Fieldset>
140
- </FormCardAsync>
141
- )
142
- }
@@ -1,51 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { JSX } from 'react'
3
- import { LinkDefinition } from '../../../backend-types.ts'
4
- import { LinkAnchor } from '../../../components/utils/link-anchor.tsx'
5
- import { clsx } from '../../../lib/clsx.ts'
6
- import { Override } from '../../../lib/util.ts'
7
-
8
- export type SignUpDisclaimerProps = Override<
9
- Omit<JSX.IntrinsicElements['p'], 'children'>,
10
- {
11
- links?: readonly LinkDefinition[]
12
- }
13
- >
14
-
15
- export function SignUpDisclaimer({
16
- links,
17
-
18
- // p
19
- className,
20
- ...attrs
21
- }: SignUpDisclaimerProps) {
22
- const tosLink = links?.find((l) => l.rel === 'terms-of-service')
23
- const ppLink = links?.find((l) => l.rel === 'privacy-policy')
24
-
25
- return (
26
- <p
27
- className={clsx('text-sm text-slate-500 dark:text-slate-400', className)}
28
- {...attrs}
29
- >
30
- <Trans>
31
- By creating an account you agree to the{' '}
32
- {tosLink ? (
33
- <LinkAnchor className="text-brand underline" link={tosLink}>
34
- <Trans>Terms of Service</Trans>
35
- </LinkAnchor>
36
- ) : (
37
- <Trans>Terms of Service</Trans>
38
- )}
39
- {' and the '}
40
- {ppLink ? (
41
- <LinkAnchor className="text-brand underline" link={ppLink}>
42
- <Trans>Privacy Policy</Trans>
43
- </LinkAnchor>
44
- ) : (
45
- <Trans>Privacy Policy</Trans>
46
- )}{' '}
47
- of this service.
48
- </Trans>
49
- </p>
50
- )
51
- }