@atproto/oauth-provider 0.5.2 → 0.6.0

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 +31 -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 +5 -3
  24. package/dist/lib/hcaptcha.d.ts.map +1 -1
  25. package/dist/lib/hcaptcha.js +7 -4
  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 +7 -40
  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 +10 -7
  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,150 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import type { OAuthClientMetadata } from '@atproto/oauth-types'
3
- import { Account, ScopeDetail } from '../../../backend-types.ts'
4
- import { Button } from '../../../components/forms/button.tsx'
5
- import {
6
- FormCard,
7
- FormCardProps,
8
- } from '../../../components/forms/form-card.tsx'
9
- import { AccountIdentifier } from '../../../components/utils/account-identifier.tsx'
10
- import { ClientName } from '../../../components/utils/client-name.tsx'
11
- import { Override } from '../../../lib/util.ts'
12
-
13
- export type AcceptFormProps = Override<
14
- Omit<FormCardProps, 'onSubmit' | 'cancel' | 'actions' | 'children'>,
15
- {
16
- clientId: string
17
- clientMetadata: OAuthClientMetadata
18
- clientTrusted: boolean
19
-
20
- account: Account
21
- scopeDetails?: ScopeDetail[]
22
-
23
- onAccept: () => void
24
- onReject: () => void
25
- onBack?: () => void
26
- }
27
- >
28
-
29
- export function AcceptForm({
30
- clientId,
31
- clientMetadata,
32
- clientTrusted,
33
-
34
- account,
35
- scopeDetails,
36
-
37
- onAccept,
38
- onReject,
39
- onBack,
40
-
41
- // FormCardProps
42
- ...props
43
- }: AcceptFormProps) {
44
- const { t } = useLingui()
45
- return (
46
- <FormCard
47
- {...props}
48
- onSubmit={(event) => {
49
- event.preventDefault()
50
- onAccept()
51
- }}
52
- cancel={onBack && <Button onClick={onBack}>Back</Button>}
53
- actions={
54
- <>
55
- <Button type="submit" color="brand">
56
- <Trans>Authorize</Trans>
57
- </Button>
58
-
59
- <Button onClick={onReject}>
60
- <Trans>Deny access</Trans>
61
- </Button>
62
- </>
63
- }
64
- >
65
- {clientTrusted && clientMetadata.logo_uri && (
66
- <div key="logo" className="flex items-center justify-center">
67
- <img
68
- crossOrigin="anonymous"
69
- src={clientMetadata.logo_uri}
70
- alt={clientMetadata.client_name}
71
- className="w-16 h-16 rounded-full"
72
- />
73
- </div>
74
- )}
75
- <p>
76
- <Trans>
77
- <ClientName
78
- clientId={clientId}
79
- clientMetadata={clientMetadata}
80
- clientTrusted={clientTrusted}
81
- />{' '}
82
- is asking for permission to access your account (
83
- <AccountIdentifier account={account} />
84
- ).
85
- </Trans>
86
- </p>
87
-
88
- <p>
89
- <Trans>
90
- By clicking{' '}
91
- <b>
92
- <Trans>Authorize</Trans>
93
- </b>
94
- , you allow this application to perform the following actions in
95
- accordance with their{' '}
96
- <a
97
- role="link"
98
- href={clientMetadata.tos_uri}
99
- rel="nofollow noopener"
100
- target="_blank"
101
- className="text-brand underline"
102
- >
103
- <Trans>terms of service</Trans>
104
- </a>
105
- {' and '}
106
- <a
107
- role="link"
108
- href={clientMetadata.policy_uri}
109
- rel="nofollow noopener"
110
- target="_blank"
111
- className="text-brand underline"
112
- >
113
- <Trans>privacy policy</Trans>
114
- </a>
115
- :
116
- </Trans>
117
- </p>
118
-
119
- {scopeDetails?.length ? (
120
- <ul
121
- className="list-disc list-inside"
122
- key="scopes"
123
- aria-label={t`Requested permissions`}
124
- >
125
- {scopeDetails.map(({ scope, description }) => (
126
- <li key={scope}>
127
- {description || <ScopeDescription scope={scope} />}
128
- </li>
129
- ))}
130
- </ul>
131
- ) : null}
132
- </FormCard>
133
- )
134
- }
135
-
136
- type ScopeDescriptionProps = {
137
- scope: string
138
- }
139
- function ScopeDescription({ scope }: ScopeDescriptionProps) {
140
- switch (scope) {
141
- case 'atproto':
142
- return <Trans>Uniquely identify you</Trans>
143
- case 'transition:generic':
144
- return <Trans>Access your account data (except chat messages)</Trans>
145
- case 'transition:chat.bsky':
146
- return <Trans>Access your chat messages</Trans>
147
- default:
148
- return scope
149
- }
150
- }
@@ -1,70 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import type { OAuthClientMetadata } from '@atproto/oauth-types'
3
- import { Account, ScopeDetail } 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 { AcceptForm } from './accept-form.tsx'
10
-
11
- export type AcceptViewProps = Override<
12
- LayoutTitlePageProps,
13
- {
14
- clientId: string
15
- clientMetadata: OAuthClientMetadata
16
- clientTrusted: boolean
17
-
18
- account: Account
19
- scopeDetails?: ScopeDetail[]
20
-
21
- onAccept: () => void
22
- onReject: () => void
23
- onBack?: () => void
24
- }
25
- >
26
-
27
- export function AcceptView({
28
- clientId,
29
- clientMetadata,
30
- clientTrusted,
31
- account,
32
- scopeDetails,
33
- onAccept,
34
- onReject,
35
- onBack,
36
-
37
- // LayoutTitlePage
38
- title,
39
- subtitle = (
40
- <Trans>
41
- Grant access to your{' '}
42
- <b className="text-slate-800 dark:text-slate-200">
43
- {account.preferred_username || account.email || account.sub}
44
- </b>{' '}
45
- account
46
- </Trans>
47
- ),
48
- ...props
49
- }: AcceptViewProps) {
50
- const { t } = useLingui()
51
-
52
- return (
53
- <LayoutTitlePage
54
- {...props}
55
- title={title ?? t`Authorize`}
56
- subtitle={subtitle}
57
- >
58
- <AcceptForm
59
- clientId={clientId}
60
- clientMetadata={clientMetadata}
61
- clientTrusted={clientTrusted}
62
- account={account}
63
- scopeDetails={scopeDetails}
64
- onBack={onBack}
65
- onAccept={onAccept}
66
- onReject={onReject}
67
- />
68
- </LayoutTitlePage>
69
- )
70
- }
@@ -1,180 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { useEffect, useState } from 'react'
3
- import type { AuthorizeData, CustomizationData } from '../../backend-types.ts'
4
- import {
5
- LayoutTitlePage,
6
- LayoutTitlePageProps,
7
- } from '../../components/layouts/layout-title-page.tsx'
8
- import { useApi } from '../../hooks/use-api.ts'
9
- import { useBoundDispatch } from '../../hooks/use-bound-dispatch.ts'
10
- import { Override } from '../../lib/util.ts'
11
- import { AcceptView } from './accept/accept-view.tsx'
12
- import { ResetPasswordView } from './reset-password/reset-password-view.tsx'
13
- import { SignInView } from './sign-in/sign-in-view.tsx'
14
- import { SignUpView } from './sign-up/sign-up-view.tsx'
15
- import { WelcomeView } from './welcome/welcome-view.tsx'
16
-
17
- export type AuthorizeViewProps = Override<
18
- LayoutTitlePageProps,
19
- {
20
- customizationData?: CustomizationData
21
- authorizeData: AuthorizeData
22
- }
23
- >
24
-
25
- enum View {
26
- Welcome,
27
- SignUp,
28
- SignIn,
29
- ResetPassword,
30
- Accept,
31
- Done,
32
- }
33
-
34
- export function AuthorizeView({
35
- authorizeData,
36
- customizationData,
37
-
38
- // LayoutTitlePage
39
- ...props
40
- }: AuthorizeViewProps) {
41
- const { t } = useLingui()
42
-
43
- const forceSignIn = authorizeData?.loginHint != null
44
-
45
- const initialView = forceSignIn ? View.SignIn : View.Welcome
46
- const [view, setView] = useState<View>(initialView)
47
-
48
- const showDone = useBoundDispatch(setView, View.Done)
49
- const showSignIn = useBoundDispatch(setView, View.SignIn)
50
- const showResetPassword = useBoundDispatch(setView, View.ResetPassword)
51
- const showSignUp = useBoundDispatch(setView, View.SignUp)
52
- const showAccept = useBoundDispatch(setView, View.Accept)
53
- const showWelcome = useBoundDispatch(setView, View.Welcome)
54
-
55
- const [resetPasswordHint, setResetPasswordHint] = useState<
56
- string | undefined
57
- >(undefined)
58
-
59
- const {
60
- sessions,
61
- selectSub,
62
- doValidateNewHandle,
63
- doSignUp,
64
- doSignIn,
65
- doInitiatePasswordReset,
66
- doConfirmResetPassword,
67
- doAccept,
68
- doReject,
69
- } = useApi({ ...authorizeData, onRedirected: showDone })
70
-
71
- // Navigate when the user signs-in (selects a new session)
72
- const session = sessions.find((s) => s.selected && !s.loginRequired)
73
- useEffect(() => {
74
- if (session) {
75
- if (session.consentRequired) showAccept()
76
- else doAccept(session.account)
77
- }
78
- }, [session, doAccept, showAccept])
79
-
80
- const canSignUp =
81
- Boolean(customizationData?.availableUserDomains?.length) &&
82
- !authorizeData.loginHint
83
-
84
- // Fool-proofing
85
- const resetNeeded =
86
- (view === View.SignUp && !canSignUp) || (view === View.Accept && !session)
87
- useEffect(() => {
88
- if (resetNeeded) showWelcome()
89
- }, [resetNeeded, showWelcome])
90
-
91
- if (view === View.Welcome) {
92
- return (
93
- <WelcomeView
94
- {...props}
95
- customizationData={customizationData}
96
- onSignIn={showSignIn}
97
- onSignUp={canSignUp ? showSignUp : undefined}
98
- onCancel={doReject}
99
- />
100
- )
101
- }
102
-
103
- if (view === View.SignUp) {
104
- return (
105
- <SignUpView
106
- {...props}
107
- customizationData={customizationData}
108
- onValidateNewHandle={doValidateNewHandle}
109
- onBack={showWelcome}
110
- onDone={doSignUp}
111
- />
112
- )
113
- }
114
-
115
- if (view === View.ResetPassword) {
116
- return (
117
- <ResetPasswordView
118
- {...props}
119
- emailDefault={resetPasswordHint}
120
- onresetPasswordRequest={doInitiatePasswordReset}
121
- onResetPasswordConfirm={doConfirmResetPassword}
122
- onBack={forceSignIn ? showSignIn : showWelcome}
123
- />
124
- )
125
- }
126
-
127
- if (view === View.SignIn) {
128
- return (
129
- <SignInView
130
- {...props}
131
- loginHint={authorizeData.loginHint}
132
- sessions={sessions}
133
- selectSub={selectSub}
134
- onSignIn={doSignIn}
135
- onBack={forceSignIn ? doReject : showWelcome}
136
- onForgotPassword={(email) => {
137
- showResetPassword()
138
- setResetPasswordHint(email)
139
- }}
140
- />
141
- )
142
- }
143
-
144
- if (view === View.Accept) {
145
- // TypeSafety: should never be null here
146
- if (!session) return null
147
-
148
- return (
149
- <AcceptView
150
- {...props}
151
- clientId={authorizeData.clientId}
152
- clientMetadata={authorizeData.clientMetadata}
153
- clientTrusted={authorizeData.clientTrusted}
154
- account={session.account}
155
- scopeDetails={authorizeData.scopeDetails}
156
- onAccept={() => doAccept(session.account)}
157
- onReject={doReject}
158
- onBack={
159
- forceSignIn
160
- ? undefined
161
- : () => {
162
- selectSub(null)
163
- setView(sessions.length ? View.SignIn : View.Welcome)
164
- }
165
- }
166
- />
167
- )
168
- }
169
-
170
- if (view === View.Done) {
171
- return (
172
- <LayoutTitlePage {...props} title={props.title ?? t`Login complete`}>
173
- <Trans>You are being redirected...</Trans>
174
- </LayoutTitlePage>
175
- )
176
- }
177
-
178
- // Fool-proofing
179
- throw new Error('Unexpected application state')
180
- }
@@ -1,88 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { useRef, useState } from 'react'
3
- import { Fieldset } from '../../../components/forms/fieldset.tsx'
4
- import {
5
- FormCardAsync,
6
- FormCardAsyncProps,
7
- } from '../../../components/forms/form-card-async.tsx'
8
- import { InputNewPassword } from '../../../components/forms/input-new-password.tsx'
9
- import { InputToken } from '../../../components/forms/input-token.tsx'
10
- import { Admonition } from '../../../components/utils/admonition.tsx'
11
- import { useRandomString } from '../../../hooks/use-random-string.ts'
12
- import { Override } from '../../../lib/util.ts'
13
-
14
- export type ResetPasswordConfirmFormProps = Override<
15
- FormCardAsyncProps,
16
- {
17
- onSubmit: (
18
- data: {
19
- token: string
20
- password: string
21
- },
22
- signal: AbortSignal,
23
- ) => void | PromiseLike<void>
24
-
25
- tokenPattern?: string
26
- tokenFormat?: string
27
- tokenParseValue?: (value: string) => string | false
28
- }
29
- >
30
-
31
- export function ResetPasswordConfirmForm({
32
- onSubmit,
33
-
34
- // FormCardAsyncProps
35
- invalid,
36
- ...props
37
- }: ResetPasswordConfirmFormProps) {
38
- const tokenAriaId = useRandomString({ prefix: 'reset-pwd-email-' })
39
- const passwordRef = useRef<HTMLInputElement>(null)
40
-
41
- const [token, setToken] = useState<string | null>(null)
42
- const [password, setPassword] = useState<string | undefined>(undefined)
43
-
44
- return (
45
- <FormCardAsync
46
- {...props}
47
- onSubmit={(signal) => {
48
- if (token && password) return onSubmit({ token, password }, signal)
49
- }}
50
- invalid={invalid || !token || !password}
51
- >
52
- <Admonition role="info">
53
- <p id={tokenAriaId} className="text-md">
54
- <Trans>
55
- You will receive an email with a "reset code". Enter that code here
56
- then enter your new password.
57
- </Trans>
58
- </p>
59
- </Admonition>
60
-
61
- <Fieldset label={<Trans>Reset code</Trans>}>
62
- <InputToken
63
- name="code"
64
- aria-labelledby={tokenAriaId}
65
- enterKeyHint="next"
66
- required
67
- autoFocus={true}
68
- onToken={(token) => {
69
- setToken(token)
70
- // Auto-focus next field when token is complete
71
- if (token) passwordRef.current?.focus()
72
- }}
73
- />
74
- </Fieldset>
75
-
76
- <Fieldset label={<Trans>New password</Trans>}>
77
- <InputNewPassword
78
- ref={passwordRef}
79
- name="password"
80
- enterKeyHint="done"
81
- required
82
- password={password}
83
- onPassword={setPassword}
84
- />
85
- </Fieldset>
86
- </FormCardAsync>
87
- )
88
- }
@@ -1,80 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { useCallback, 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 { Admonition } from '../../../components/utils/admonition.tsx'
11
- import { useRandomString } from '../../../hooks/use-random-string.ts'
12
- import { mergeRefs } from '../../../lib/ref.ts'
13
- import { Override } from '../../../lib/util.ts'
14
-
15
- export type ResetPasswordRequestFormProps = Override<
16
- Omit<FormCardAsyncProps, 'children'>,
17
- {
18
- emailDefault?: string
19
- onSubmit: (
20
- data: { email: string },
21
- signal: AbortSignal,
22
- ) => void | PromiseLike<void>
23
- }
24
- >
25
-
26
- export function ResetPasswordRequestForm({
27
- emailDefault,
28
- onSubmit,
29
-
30
- // FormCardAsyncProps
31
- invalid,
32
- ref,
33
- ...props
34
- }: ResetPasswordRequestFormProps) {
35
- const { t } = useLingui()
36
- const emailAriaId = useRandomString({ prefix: 'reset-pwd-email-' })
37
- const [email, setEmail] = useState(emailDefault)
38
-
39
- const ctrlRef = useRef<AsyncActionController>(null)
40
-
41
- const doSubmit = useCallback(
42
- (signal: AbortSignal) => {
43
- if (email) return onSubmit({ email }, signal)
44
- },
45
- [email, onSubmit],
46
- )
47
-
48
- return (
49
- <FormCardAsync
50
- {...props}
51
- ref={mergeRefs([ref, ctrlRef])}
52
- invalid={invalid || !email}
53
- onSubmit={doSubmit}
54
- >
55
- <Fieldset label={<Trans>Email address</Trans>}>
56
- <InputEmailAddress
57
- name="email"
58
- placeholder={t`Enter your email address`}
59
- aria-labelledby={emailAriaId}
60
- title={t`Email address`}
61
- required
62
- autoFocus={true}
63
- value={email}
64
- onEmail={(email) => {
65
- ctrlRef.current?.reset()
66
- setEmail(email)
67
- }}
68
- />
69
- <Admonition role="info">
70
- <p id={emailAriaId} className="">
71
- <Trans>
72
- Enter the email you used to create your account. We'll send you a
73
- "reset code" so you can set a new password.
74
- </Trans>
75
- </p>
76
- </Admonition>
77
- </Fieldset>
78
- </FormCardAsync>
79
- )
80
- }
@@ -1,127 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { useState } from 'react'
3
- import { Button } from '../../../components/forms/button.tsx'
4
- import {
5
- LayoutTitlePage,
6
- LayoutTitlePageProps,
7
- } from '../../../components/layouts/layout-title-page.tsx'
8
- import { Override } from '../../../lib/util.ts'
9
- import { ResetPasswordConfirmForm } from './reset-password-confirm-form.tsx'
10
- import { ResetPasswordRequestForm } from './reset-password-request-form.tsx'
11
-
12
- export type ResetPasswordViewProps = Override<
13
- LayoutTitlePageProps,
14
- {
15
- emailDefault?: string
16
- onresetPasswordRequest: (
17
- data: { email: string },
18
- signal: AbortSignal,
19
- ) => void | PromiseLike<void>
20
- onResetPasswordConfirm: (
21
- data: {
22
- token: string
23
- password: string
24
- },
25
- signal: AbortSignal,
26
- ) => void | PromiseLike<void>
27
- onBack: () => void
28
- }
29
- >
30
-
31
- enum View {
32
- RequestReset,
33
- ConfirmReset,
34
- PasswordUpdated,
35
- }
36
-
37
- export function ResetPasswordView({
38
- emailDefault,
39
- onresetPasswordRequest,
40
- onResetPasswordConfirm,
41
- onBack,
42
-
43
- // LayoutTitlePage
44
- ...props
45
- }: ResetPasswordViewProps) {
46
- const { t } = useLingui()
47
- const [view, setView] = useState<View>(View.RequestReset)
48
-
49
- if (view === View.RequestReset) {
50
- return (
51
- <LayoutTitlePage
52
- {...props}
53
- title={props.title || t`Forgot Password`}
54
- subtitle={
55
- props.subtitle || <Trans>Let's get your password reset!</Trans>
56
- }
57
- >
58
- <ResetPasswordRequestForm
59
- emailDefault={emailDefault}
60
- submitLabel={<Trans>Next</Trans>}
61
- onSubmit={async (data, signal) => {
62
- await onresetPasswordRequest(data, signal)
63
- if (!signal.aborted) setView(View.ConfirmReset)
64
- }}
65
- cancelLabel={<Trans>Back</Trans>}
66
- onCancel={onBack}
67
- />
68
- <hr className="my-5 border-gray-300 dark:border-gray-700" />
69
- <center>
70
- <Button transparent onClick={() => setView(View.ConfirmReset)}>
71
- <Trans>Already have a code?</Trans>
72
- </Button>
73
- </center>
74
- </LayoutTitlePage>
75
- )
76
- }
77
-
78
- if (view === View.ConfirmReset) {
79
- return (
80
- <LayoutTitlePage
81
- {...props}
82
- title={props.title || t`Reset Password`}
83
- subtitle={
84
- props.subtitle || (
85
- <Trans>Enter the code you received to reset your password.</Trans>
86
- )
87
- }
88
- >
89
- <ResetPasswordConfirmForm
90
- submitLabel={<Trans>Next</Trans>}
91
- onSubmit={async (data, signal) => {
92
- await onResetPasswordConfirm(data, signal)
93
- if (!signal.aborted) setView(View.PasswordUpdated)
94
- }}
95
- cancelLabel={<Trans>Back</Trans>}
96
- onCancel={onBack}
97
- />
98
- </LayoutTitlePage>
99
- )
100
- }
101
-
102
- if (view === View.PasswordUpdated) {
103
- return (
104
- <LayoutTitlePage
105
- {...props}
106
- title={props.title || t`Password Updated`}
107
- subtitle={
108
- props.subtitle || <Trans>Your password has been updated!</Trans>
109
- }
110
- >
111
- <center>
112
- <h2 className="text-xl font-bold pb-2">
113
- <Trans>Password updated!</Trans>
114
- </h2>
115
- <p className="pb-4">
116
- <Trans>You can now sign in with your new password.</Trans>
117
- </p>
118
- <Button color="brand" onClick={onBack}>
119
- <Trans>Okay</Trans>
120
- </Button>
121
- </center>
122
- </LayoutTitlePage>
123
- )
124
- }
125
-
126
- throw new Error(`Invalid view: ${view}`)
127
- }