@atproto/oauth-provider 0.5.1 → 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 (325) hide show
  1. package/CHANGELOG.md +39 -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 +13 -5
  7. package/dist/account/account-store.d.ts.map +1 -1
  8. package/dist/account/account-store.js +24 -8
  9. package/dist/account/account-store.js.map +1 -1
  10. package/dist/account/account.d.ts +1 -11
  11. package/dist/account/account.d.ts.map +1 -1
  12. package/dist/account/{sign-up-data.d.ts → sign-up-input.d.ts} +5 -5
  13. package/dist/account/sign-up-input.d.ts.map +1 -0
  14. package/dist/account/{sign-up-data.js → sign-up-input.js} +3 -3
  15. package/dist/account/sign-up-input.js.map +1 -0
  16. package/dist/assets/assets-middleware.d.ts +2 -0
  17. package/dist/assets/assets-middleware.d.ts.map +1 -1
  18. package/dist/assets/assets-middleware.js +12 -14
  19. package/dist/assets/assets-middleware.js.map +1 -1
  20. package/dist/errors/invalid-invite-code-error.d.ts +5 -0
  21. package/dist/errors/invalid-invite-code-error.d.ts.map +1 -0
  22. package/dist/errors/invalid-invite-code-error.js +11 -0
  23. package/dist/errors/invalid-invite-code-error.js.map +1 -0
  24. package/dist/errors/oauth-error.d.ts +2 -2
  25. package/dist/errors/oauth-error.js.map +1 -1
  26. package/dist/lib/csp/index.d.ts +5 -6
  27. package/dist/lib/csp/index.d.ts.map +1 -1
  28. package/dist/lib/csp/index.js +14 -11
  29. package/dist/lib/csp/index.js.map +1 -1
  30. package/dist/lib/hcaptcha.d.ts +5 -3
  31. package/dist/lib/hcaptcha.d.ts.map +1 -1
  32. package/dist/lib/hcaptcha.js +7 -4
  33. package/dist/lib/hcaptcha.js.map +1 -1
  34. package/dist/lib/html/build-document.d.ts +2 -2
  35. package/dist/lib/html/build-document.d.ts.map +1 -1
  36. package/dist/lib/html/build-document.js +11 -7
  37. package/dist/lib/html/build-document.js.map +1 -1
  38. package/dist/lib/html/html.d.ts.map +1 -1
  39. package/dist/lib/html/html.js +10 -13
  40. package/dist/lib/html/html.js.map +1 -1
  41. package/dist/lib/html/util.d.ts +0 -1
  42. package/dist/lib/html/util.d.ts.map +1 -1
  43. package/dist/lib/html/util.js +0 -4
  44. package/dist/lib/html/util.js.map +1 -1
  45. package/dist/lib/http/response.d.ts +3 -1
  46. package/dist/lib/http/response.d.ts.map +1 -1
  47. package/dist/lib/http/response.js +3 -0
  48. package/dist/lib/http/response.js.map +1 -1
  49. package/dist/lib/http/security-headers.d.ts +48 -0
  50. package/dist/lib/http/security-headers.d.ts.map +1 -0
  51. package/dist/lib/http/security-headers.js +62 -0
  52. package/dist/lib/http/security-headers.js.map +1 -0
  53. package/dist/lib/util/type.d.ts +8 -0
  54. package/dist/lib/util/type.d.ts.map +1 -1
  55. package/dist/lib/util/type.js.map +1 -1
  56. package/dist/oauth-errors.d.ts +1 -0
  57. package/dist/oauth-errors.d.ts.map +1 -1
  58. package/dist/oauth-errors.js +3 -1
  59. package/dist/oauth-errors.js.map +1 -1
  60. package/dist/oauth-hooks.d.ts +4 -25
  61. package/dist/oauth-hooks.d.ts.map +1 -1
  62. package/dist/oauth-provider.d.ts.map +1 -1
  63. package/dist/oauth-provider.js +26 -25
  64. package/dist/oauth-provider.js.map +1 -1
  65. package/dist/output/backend-data.d.ts +4 -0
  66. package/dist/output/backend-data.d.ts.map +1 -0
  67. package/dist/output/backend-data.js +19 -0
  68. package/dist/output/backend-data.js.map +1 -0
  69. package/dist/output/build-authorize-data.d.ts +3 -19
  70. package/dist/output/build-authorize-data.d.ts.map +1 -1
  71. package/dist/output/build-authorize-data.js.map +1 -1
  72. package/dist/output/build-customization-data.d.ts +11 -18
  73. package/dist/output/build-customization-data.d.ts.map +1 -1
  74. package/dist/output/build-customization-data.js +1 -1
  75. package/dist/output/build-customization-data.js.map +1 -1
  76. package/dist/output/build-error-data.d.ts +3 -0
  77. package/dist/output/build-error-data.d.ts.map +1 -0
  78. package/dist/output/build-error-data.js +10 -0
  79. package/dist/output/build-error-data.js.map +1 -0
  80. package/dist/output/build-error-payload.d.ts +2 -1
  81. package/dist/output/build-error-payload.d.ts.map +1 -1
  82. package/dist/output/build-error-payload.js.map +1 -1
  83. package/dist/output/output-manager.d.ts +10 -4
  84. package/dist/output/output-manager.d.ts.map +1 -1
  85. package/dist/output/output-manager.js +68 -39
  86. package/dist/output/output-manager.js.map +1 -1
  87. package/dist/output/send-web-page.d.ts +6 -10
  88. package/dist/output/send-web-page.d.ts.map +1 -1
  89. package/dist/output/send-web-page.js +27 -47
  90. package/dist/output/send-web-page.js.map +1 -1
  91. package/dist/signer/signed-token-payload.d.ts +3 -3
  92. package/dist/signer/signer.d.ts +2 -2
  93. package/package.json +7 -39
  94. package/src/account/account-manager.ts +55 -34
  95. package/src/account/account-store.ts +29 -6
  96. package/src/account/account.ts +1 -14
  97. package/src/account/{sign-up-data.ts → sign-up-input.ts} +2 -2
  98. package/src/assets/assets-middleware.ts +11 -17
  99. package/src/errors/invalid-invite-code-error.ts +10 -0
  100. package/src/errors/oauth-error.ts +1 -1
  101. package/src/lib/csp/index.ts +16 -13
  102. package/src/lib/hcaptcha.ts +10 -7
  103. package/src/lib/html/build-document.ts +15 -8
  104. package/src/lib/html/html.ts +11 -18
  105. package/src/lib/html/util.ts +0 -4
  106. package/src/lib/http/response.ts +9 -1
  107. package/src/lib/http/security-headers.ts +91 -0
  108. package/src/lib/util/type.ts +18 -0
  109. package/src/oauth-errors.ts +1 -0
  110. package/src/oauth-hooks.ts +4 -25
  111. package/src/oauth-provider.ts +40 -34
  112. package/src/output/backend-data.ts +18 -0
  113. package/src/output/build-authorize-data.ts +3 -26
  114. package/src/output/build-customization-data.ts +2 -13
  115. package/src/output/build-error-data.ts +8 -0
  116. package/src/output/build-error-payload.ts +4 -2
  117. package/src/output/output-manager.ts +86 -47
  118. package/src/output/send-web-page.ts +29 -58
  119. package/tsconfig.backend.json +1 -2
  120. package/tsconfig.backend.tsbuildinfo +1 -1
  121. package/tsconfig.json +1 -5
  122. package/.linguirc +0 -57
  123. package/dist/account/sign-up-data.d.ts.map +0 -1
  124. package/dist/account/sign-up-data.js.map +0 -1
  125. package/dist/assets/app/bundle-manifest.json +0 -614
  126. package/dist/assets/app/index-ItwwtJ8r.js +0 -36
  127. package/dist/assets/app/index-ItwwtJ8r.js.map +0 -1
  128. package/dist/assets/app/main-B_dNxQo_.js +0 -4
  129. package/dist/assets/app/main-B_dNxQo_.js.map +0 -1
  130. package/dist/assets/app/main-CSatvmRR.css +0 -3
  131. package/dist/assets/app/main-CSatvmRR.js +0 -306
  132. package/dist/assets/app/main-CSatvmRR.js.map +0 -1
  133. package/dist/assets/app/messages-BQeltXSF.js +0 -4
  134. package/dist/assets/app/messages-BQeltXSF.js.map +0 -1
  135. package/dist/assets/app/messages-BQkEhfjg.js +0 -4
  136. package/dist/assets/app/messages-BQkEhfjg.js.map +0 -1
  137. package/dist/assets/app/messages-BUjKj_UJ.js +0 -4
  138. package/dist/assets/app/messages-BUjKj_UJ.js.map +0 -1
  139. package/dist/assets/app/messages-BWIQa8fO.js +0 -4
  140. package/dist/assets/app/messages-BWIQa8fO.js.map +0 -1
  141. package/dist/assets/app/messages-BaNVb0bp.js +0 -4
  142. package/dist/assets/app/messages-BaNVb0bp.js.map +0 -1
  143. package/dist/assets/app/messages-BaizVXcF.js +0 -4
  144. package/dist/assets/app/messages-BaizVXcF.js.map +0 -1
  145. package/dist/assets/app/messages-BfoClA1Y.js +0 -4
  146. package/dist/assets/app/messages-BfoClA1Y.js.map +0 -1
  147. package/dist/assets/app/messages-BsKGDZnC.js +0 -4
  148. package/dist/assets/app/messages-BsKGDZnC.js.map +0 -1
  149. package/dist/assets/app/messages-Bu-TJhml.js +0 -4
  150. package/dist/assets/app/messages-Bu-TJhml.js.map +0 -1
  151. package/dist/assets/app/messages-BvOKnBQk.js +0 -4
  152. package/dist/assets/app/messages-BvOKnBQk.js.map +0 -1
  153. package/dist/assets/app/messages-BxDzCiWz.js +0 -4
  154. package/dist/assets/app/messages-BxDzCiWz.js.map +0 -1
  155. package/dist/assets/app/messages-CDgFOy4S.js +0 -4
  156. package/dist/assets/app/messages-CDgFOy4S.js.map +0 -1
  157. package/dist/assets/app/messages-CLbTz0o9.js +0 -4
  158. package/dist/assets/app/messages-CLbTz0o9.js.map +0 -1
  159. package/dist/assets/app/messages-CNwSh0t7.js +0 -4
  160. package/dist/assets/app/messages-CNwSh0t7.js.map +0 -1
  161. package/dist/assets/app/messages-CSMNJ6P8.js +0 -4
  162. package/dist/assets/app/messages-CSMNJ6P8.js.map +0 -1
  163. package/dist/assets/app/messages-CZQUw3mp.js +0 -4
  164. package/dist/assets/app/messages-CZQUw3mp.js.map +0 -1
  165. package/dist/assets/app/messages-CZT41oVp.js +0 -4
  166. package/dist/assets/app/messages-CZT41oVp.js.map +0 -1
  167. package/dist/assets/app/messages-C_b-d3t8.js +0 -4
  168. package/dist/assets/app/messages-C_b-d3t8.js.map +0 -1
  169. package/dist/assets/app/messages-C_u3MTc2.js +0 -4
  170. package/dist/assets/app/messages-C_u3MTc2.js.map +0 -1
  171. package/dist/assets/app/messages-Cn8nHZic.js +0 -4
  172. package/dist/assets/app/messages-Cn8nHZic.js.map +0 -1
  173. package/dist/assets/app/messages-CtDywJUm.js +0 -4
  174. package/dist/assets/app/messages-CtDywJUm.js.map +0 -1
  175. package/dist/assets/app/messages-CurtIjBF.js +0 -4
  176. package/dist/assets/app/messages-CurtIjBF.js.map +0 -1
  177. package/dist/assets/app/messages-Cv6zIbaP.js +0 -4
  178. package/dist/assets/app/messages-Cv6zIbaP.js.map +0 -1
  179. package/dist/assets/app/messages-D1eLQuPE.js +0 -4
  180. package/dist/assets/app/messages-D1eLQuPE.js.map +0 -1
  181. package/dist/assets/app/messages-D8vHEaYW.js +0 -4
  182. package/dist/assets/app/messages-D8vHEaYW.js.map +0 -1
  183. package/dist/assets/app/messages-DJ1Q4GeC.js +0 -4
  184. package/dist/assets/app/messages-DJ1Q4GeC.js.map +0 -1
  185. package/dist/assets/app/messages-DRL3exqd.js +0 -4
  186. package/dist/assets/app/messages-DRL3exqd.js.map +0 -1
  187. package/dist/assets/app/messages-DWLPQRTp.js +0 -4
  188. package/dist/assets/app/messages-DWLPQRTp.js.map +0 -1
  189. package/dist/assets/app/messages-DjVaE9YE.js +0 -4
  190. package/dist/assets/app/messages-DjVaE9YE.js.map +0 -1
  191. package/dist/assets/app/messages-DqpMfFJR.js +0 -4
  192. package/dist/assets/app/messages-DqpMfFJR.js.map +0 -1
  193. package/dist/assets/app/messages-ETjhJBEN.js +0 -4
  194. package/dist/assets/app/messages-ETjhJBEN.js.map +0 -1
  195. package/dist/assets/app/messages-EUKrgrGn.js +0 -4
  196. package/dist/assets/app/messages-EUKrgrGn.js.map +0 -1
  197. package/dist/assets/app/messages-QQrOUcPW.js +0 -4
  198. package/dist/assets/app/messages-QQrOUcPW.js.map +0 -1
  199. package/dist/assets/app/messages-e2QGqFL6.js +0 -4
  200. package/dist/assets/app/messages-e2QGqFL6.js.map +0 -1
  201. package/dist/assets/app/messages-p61py7gD.js +0 -4
  202. package/dist/assets/app/messages-p61py7gD.js.map +0 -1
  203. package/dist/assets/asset.d.ts +0 -9
  204. package/dist/assets/asset.d.ts.map +0 -1
  205. package/dist/assets/asset.js +0 -3
  206. package/dist/assets/asset.js.map +0 -1
  207. package/dist/assets/index.d.ts +0 -5
  208. package/dist/assets/index.d.ts.map +0 -1
  209. package/dist/assets/index.js +0 -78
  210. package/dist/assets/index.js.map +0 -1
  211. package/rollup.config.js +0 -98
  212. package/src/assets/app/app.tsx +0 -43
  213. package/src/assets/app/backend-data.ts +0 -27
  214. package/src/assets/app/backend-types.ts +0 -66
  215. package/src/assets/app/components/forms/button-toggle-visibility.tsx +0 -43
  216. package/src/assets/app/components/forms/button.tsx +0 -60
  217. package/src/assets/app/components/forms/fieldset.tsx +0 -55
  218. package/src/assets/app/components/forms/form-card-async.tsx +0 -103
  219. package/src/assets/app/components/forms/form-card.tsx +0 -49
  220. package/src/assets/app/components/forms/input-checkbox.tsx +0 -73
  221. package/src/assets/app/components/forms/input-container.tsx +0 -107
  222. package/src/assets/app/components/forms/input-email-address.tsx +0 -66
  223. package/src/assets/app/components/forms/input-new-password.tsx +0 -62
  224. package/src/assets/app/components/forms/input-password.tsx +0 -88
  225. package/src/assets/app/components/forms/input-text.tsx +0 -76
  226. package/src/assets/app/components/forms/input-token.tsx +0 -94
  227. package/src/assets/app/components/forms/wizard-card.tsx +0 -116
  228. package/src/assets/app/components/layouts/layout-title-page.tsx +0 -77
  229. package/src/assets/app/components/layouts/layout-welcome.tsx +0 -73
  230. package/src/assets/app/components/utils/account-identifier.tsx +0 -23
  231. package/src/assets/app/components/utils/account-image.tsx +0 -33
  232. package/src/assets/app/components/utils/admonition.tsx +0 -52
  233. package/src/assets/app/components/utils/client-name.tsx +0 -45
  234. package/src/assets/app/components/utils/error-card.tsx +0 -93
  235. package/src/assets/app/components/utils/error-message.tsx +0 -62
  236. package/src/assets/app/components/utils/help-card.tsx +0 -46
  237. package/src/assets/app/components/utils/icons.tsx +0 -88
  238. package/src/assets/app/components/utils/link-anchor.tsx +0 -28
  239. package/src/assets/app/components/utils/link-title.tsx +0 -26
  240. package/src/assets/app/components/utils/multi-lang-string.tsx +0 -56
  241. package/src/assets/app/components/utils/password-strength-label.tsx +0 -37
  242. package/src/assets/app/components/utils/password-strength-meter.tsx +0 -58
  243. package/src/assets/app/components/utils/url-viewer.tsx +0 -73
  244. package/src/assets/app/cookies.ts +0 -11
  245. package/src/assets/app/hooks/use-api.ts +0 -178
  246. package/src/assets/app/hooks/use-async-action.ts +0 -120
  247. package/src/assets/app/hooks/use-bound-dispatch.ts +0 -5
  248. package/src/assets/app/hooks/use-browser-color-scheme.ts +0 -31
  249. package/src/assets/app/hooks/use-csrf-token.ts +0 -5
  250. package/src/assets/app/hooks/use-random-string.ts +0 -37
  251. package/src/assets/app/hooks/use-stepper.ts +0 -87
  252. package/src/assets/app/index.html +0 -182
  253. package/src/assets/app/lib/api.ts +0 -267
  254. package/src/assets/app/lib/clsx.ts +0 -6
  255. package/src/assets/app/lib/json-client.ts +0 -94
  256. package/src/assets/app/lib/password.ts +0 -98
  257. package/src/assets/app/lib/ref.ts +0 -17
  258. package/src/assets/app/lib/util.ts +0 -13
  259. package/src/assets/app/locales/an/messages.po +0 -492
  260. package/src/assets/app/locales/ast/messages.po +0 -492
  261. package/src/assets/app/locales/ca/messages.po +0 -492
  262. package/src/assets/app/locales/da/messages.po +0 -492
  263. package/src/assets/app/locales/de/messages.po +0 -492
  264. package/src/assets/app/locales/el/messages.po +0 -492
  265. package/src/assets/app/locales/en/messages.po +0 -492
  266. package/src/assets/app/locales/en-GB/messages.po +0 -492
  267. package/src/assets/app/locales/es/messages.po +0 -492
  268. package/src/assets/app/locales/eu/messages.po +0 -492
  269. package/src/assets/app/locales/fi/messages.po +0 -492
  270. package/src/assets/app/locales/fr/messages.po +0 -492
  271. package/src/assets/app/locales/ga/messages.po +0 -492
  272. package/src/assets/app/locales/gl/messages.po +0 -492
  273. package/src/assets/app/locales/hi/messages.po +0 -492
  274. package/src/assets/app/locales/hu/messages.po +0 -492
  275. package/src/assets/app/locales/ia/messages.po +0 -492
  276. package/src/assets/app/locales/id/messages.po +0 -492
  277. package/src/assets/app/locales/it/messages.po +0 -492
  278. package/src/assets/app/locales/ja/messages.po +0 -492
  279. package/src/assets/app/locales/km/messages.po +0 -492
  280. package/src/assets/app/locales/ko/messages.po +0 -492
  281. package/src/assets/app/locales/load.ts +0 -8
  282. package/src/assets/app/locales/locale-context.ts +0 -19
  283. package/src/assets/app/locales/locale-provider.tsx +0 -112
  284. package/src/assets/app/locales/locale-selector.tsx +0 -58
  285. package/src/assets/app/locales/locales.ts +0 -168
  286. package/src/assets/app/locales/ne/messages.po +0 -492
  287. package/src/assets/app/locales/nl/messages.po +0 -492
  288. package/src/assets/app/locales/pl/messages.po +0 -492
  289. package/src/assets/app/locales/pt-BR/messages.po +0 -492
  290. package/src/assets/app/locales/ro/messages.po +0 -492
  291. package/src/assets/app/locales/ru/messages.po +0 -492
  292. package/src/assets/app/locales/sv/messages.po +0 -492
  293. package/src/assets/app/locales/th/messages.po +0 -492
  294. package/src/assets/app/locales/tr/messages.po +0 -492
  295. package/src/assets/app/locales/uk/messages.po +0 -492
  296. package/src/assets/app/locales/vi/messages.po +0 -492
  297. package/src/assets/app/locales/zh-CN/messages.po +0 -492
  298. package/src/assets/app/locales/zh-HK/messages.po +0 -492
  299. package/src/assets/app/locales/zh-TW/messages.po +0 -492
  300. package/src/assets/app/main.css +0 -33
  301. package/src/assets/app/main.tsx +0 -44
  302. package/src/assets/app/views/authorize/accept/accept-form.tsx +0 -150
  303. package/src/assets/app/views/authorize/accept/accept-view.tsx +0 -70
  304. package/src/assets/app/views/authorize/authorize-view.tsx +0 -180
  305. package/src/assets/app/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
  306. package/src/assets/app/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
  307. package/src/assets/app/views/authorize/reset-password/reset-password-view.tsx +0 -127
  308. package/src/assets/app/views/authorize/sign-in/sign-in-form.tsx +0 -244
  309. package/src/assets/app/views/authorize/sign-in/sign-in-picker.tsx +0 -116
  310. package/src/assets/app/views/authorize/sign-in/sign-in-view.tsx +0 -145
  311. package/src/assets/app/views/authorize/sign-up/sign-up-account-form.tsx +0 -140
  312. package/src/assets/app/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
  313. package/src/assets/app/views/authorize/sign-up/sign-up-handle-form.tsx +0 -289
  314. package/src/assets/app/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
  315. package/src/assets/app/views/authorize/sign-up/sign-up-view.tsx +0 -158
  316. package/src/assets/app/views/authorize/welcome/welcome-view.tsx +0 -56
  317. package/src/assets/app/views/error/error-view.tsx +0 -31
  318. package/src/assets/asset.ts +0 -9
  319. package/src/assets/index.ts +0 -86
  320. package/tailwind.config.js +0 -31
  321. package/tsconfig.frontend.json +0 -11
  322. package/tsconfig.frontend.tsbuildinfo +0 -1
  323. package/tsconfig.tools.json +0 -8
  324. package/tsconfig.tools.tsbuildinfo +0 -1
  325. 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-label={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
- }