@atproto/pds 0.5.12 → 0.5.15

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 (326) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/api/app/bsky/notification/index.d.ts.map +1 -1
  3. package/dist/api/app/bsky/notification/index.js +2 -0
  4. package/dist/api/app/bsky/notification/index.js.map +1 -1
  5. package/dist/api/app/bsky/notification/unregisterPush.d.ts +4 -0
  6. package/dist/api/app/bsky/notification/unregisterPush.d.ts.map +1 -0
  7. package/dist/api/app/bsky/notification/unregisterPush.js +48 -0
  8. package/dist/api/app/bsky/notification/unregisterPush.js.map +1 -0
  9. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +6 -0
  10. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
  11. package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
  12. package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
  13. package/package.json +42 -38
  14. package/build.templates.cjs +0 -22
  15. package/example.env +0 -42
  16. package/jest.config.cjs +0 -27
  17. package/src/account-manager/account-manager.ts +0 -916
  18. package/src/account-manager/db/index.ts +0 -21
  19. package/src/account-manager/db/migrations/001-init.ts +0 -115
  20. package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
  21. package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
  22. package/src/account-manager/db/migrations/004-oauth.ts +0 -122
  23. package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
  24. package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
  25. package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
  26. package/src/account-manager/db/migrations/index.ts +0 -17
  27. package/src/account-manager/db/schema/account-device.ts +0 -14
  28. package/src/account-manager/db/schema/account.ts +0 -16
  29. package/src/account-manager/db/schema/actor.ts +0 -17
  30. package/src/account-manager/db/schema/app-password.ts +0 -13
  31. package/src/account-manager/db/schema/authorization-request.ts +0 -30
  32. package/src/account-manager/db/schema/authorized-client.ts +0 -23
  33. package/src/account-manager/db/schema/device.ts +0 -18
  34. package/src/account-manager/db/schema/email-token.ts +0 -19
  35. package/src/account-manager/db/schema/index.ts +0 -43
  36. package/src/account-manager/db/schema/invite-code.ts +0 -24
  37. package/src/account-manager/db/schema/lexicon.ts +0 -15
  38. package/src/account-manager/db/schema/refresh-token.ts +0 -11
  39. package/src/account-manager/db/schema/repo-root.ts +0 -12
  40. package/src/account-manager/db/schema/token.ts +0 -38
  41. package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
  42. package/src/account-manager/helpers/account-device.ts +0 -63
  43. package/src/account-manager/helpers/account.ts +0 -355
  44. package/src/account-manager/helpers/auth.ts +0 -222
  45. package/src/account-manager/helpers/authorization-request.ts +0 -90
  46. package/src/account-manager/helpers/authorized-client.ts +0 -75
  47. package/src/account-manager/helpers/device.ts +0 -47
  48. package/src/account-manager/helpers/email-token.ts +0 -87
  49. package/src/account-manager/helpers/invite.ts +0 -263
  50. package/src/account-manager/helpers/lexicon.ts +0 -67
  51. package/src/account-manager/helpers/password.ts +0 -136
  52. package/src/account-manager/helpers/repo.ts +0 -24
  53. package/src/account-manager/helpers/scrypt.ts +0 -53
  54. package/src/account-manager/helpers/token.ts +0 -158
  55. package/src/account-manager/helpers/used-refresh-token.ts +0 -30
  56. package/src/account-manager/oauth-store.ts +0 -880
  57. package/src/account-manager/scope-reference-getter.ts +0 -106
  58. package/src/actor-store/actor-store-reader.ts +0 -45
  59. package/src/actor-store/actor-store-resources.ts +0 -8
  60. package/src/actor-store/actor-store-transactor.ts +0 -31
  61. package/src/actor-store/actor-store-writer.ts +0 -17
  62. package/src/actor-store/actor-store.ts +0 -210
  63. package/src/actor-store/blob/reader.ts +0 -160
  64. package/src/actor-store/blob/transactor.ts +0 -383
  65. package/src/actor-store/db/index.ts +0 -20
  66. package/src/actor-store/db/migrations/001-init.ts +0 -105
  67. package/src/actor-store/db/migrations/index.ts +0 -5
  68. package/src/actor-store/db/schema/account-pref.ts +0 -11
  69. package/src/actor-store/db/schema/backlink.ts +0 -9
  70. package/src/actor-store/db/schema/blob.ts +0 -14
  71. package/src/actor-store/db/schema/index.ts +0 -23
  72. package/src/actor-store/db/schema/record-blob.ts +0 -8
  73. package/src/actor-store/db/schema/record.ts +0 -14
  74. package/src/actor-store/db/schema/repo-block.ts +0 -10
  75. package/src/actor-store/db/schema/repo-root.ts +0 -10
  76. package/src/actor-store/migrate.ts +0 -39
  77. package/src/actor-store/preference/reader.ts +0 -48
  78. package/src/actor-store/preference/transactor.ts +0 -55
  79. package/src/actor-store/preference/util.ts +0 -39
  80. package/src/actor-store/record/reader.ts +0 -374
  81. package/src/actor-store/record/transactor.ts +0 -111
  82. package/src/actor-store/repo/reader.ts +0 -31
  83. package/src/actor-store/repo/sql-repo-reader.ts +0 -150
  84. package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
  85. package/src/actor-store/repo/transactor.ts +0 -227
  86. package/src/api/app/bsky/actor/getPreferences.ts +0 -57
  87. package/src/api/app/bsky/actor/getProfile.ts +0 -41
  88. package/src/api/app/bsky/actor/getProfiles.ts +0 -51
  89. package/src/api/app/bsky/actor/index.ts +0 -13
  90. package/src/api/app/bsky/actor/putPreferences.ts +0 -62
  91. package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
  92. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
  93. package/src/api/app/bsky/feed/getFeed.ts +0 -47
  94. package/src/api/app/bsky/feed/getPostThread.ts +0 -251
  95. package/src/api/app/bsky/feed/getTimeline.ts +0 -50
  96. package/src/api/app/bsky/feed/index.ts +0 -15
  97. package/src/api/app/bsky/index.ts +0 -11
  98. package/src/api/app/bsky/notification/index.ts +0 -7
  99. package/src/api/app/bsky/notification/registerPush.ts +0 -71
  100. package/src/api/app/bsky/util/resolver.ts +0 -20
  101. package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
  102. package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
  103. package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
  104. package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
  105. package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
  106. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
  107. package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
  108. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
  109. package/src/api/com/atproto/admin/index.ts +0 -31
  110. package/src/api/com/atproto/admin/sendEmail.ts +0 -47
  111. package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
  112. package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
  113. package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
  114. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
  115. package/src/api/com/atproto/admin/util.ts +0 -66
  116. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
  117. package/src/api/com/atproto/identity/index.ts +0 -17
  118. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
  119. package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
  120. package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
  121. package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
  122. package/src/api/com/atproto/identity/updateHandle.ts +0 -66
  123. package/src/api/com/atproto/index.ts +0 -19
  124. package/src/api/com/atproto/moderation/createReport.ts +0 -41
  125. package/src/api/com/atproto/moderation/index.ts +0 -7
  126. package/src/api/com/atproto/repo/applyWrites.ts +0 -226
  127. package/src/api/com/atproto/repo/createRecord.ts +0 -143
  128. package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
  129. package/src/api/com/atproto/repo/describeRepo.ts +0 -43
  130. package/src/api/com/atproto/repo/getRecord.ts +0 -40
  131. package/src/api/com/atproto/repo/importRepo.ts +0 -101
  132. package/src/api/com/atproto/repo/index.ts +0 -25
  133. package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
  134. package/src/api/com/atproto/repo/listRecords.ts +0 -36
  135. package/src/api/com/atproto/repo/putRecord.ts +0 -211
  136. package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
  137. package/src/api/com/atproto/server/activateAccount.ts +0 -37
  138. package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
  139. package/src/api/com/atproto/server/confirmEmail.ts +0 -39
  140. package/src/api/com/atproto/server/createAccount.ts +0 -327
  141. package/src/api/com/atproto/server/createAppPassword.ts +0 -53
  142. package/src/api/com/atproto/server/createInviteCode.ts +0 -38
  143. package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
  144. package/src/api/com/atproto/server/createSession.ts +0 -97
  145. package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
  146. package/src/api/com/atproto/server/deleteAccount.ts +0 -85
  147. package/src/api/com/atproto/server/deleteSession.ts +0 -23
  148. package/src/api/com/atproto/server/describeServer.ts +0 -29
  149. package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
  150. package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
  151. package/src/api/com/atproto/server/getSession.ts +0 -80
  152. package/src/api/com/atproto/server/index.ts +0 -55
  153. package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
  154. package/src/api/com/atproto/server/refreshSession.ts +0 -72
  155. package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
  156. package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
  157. package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
  158. package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
  159. package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
  160. package/src/api/com/atproto/server/resetPassword.ts +0 -50
  161. package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
  162. package/src/api/com/atproto/server/updateEmail.ts +0 -52
  163. package/src/api/com/atproto/server/util.ts +0 -136
  164. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
  165. package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
  166. package/src/api/com/atproto/sync/getBlob.ts +0 -61
  167. package/src/api/com/atproto/sync/getBlocks.ts +0 -37
  168. package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
  169. package/src/api/com/atproto/sync/getRecord.ts +0 -49
  170. package/src/api/com/atproto/sync/getRepo.ts +0 -75
  171. package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
  172. package/src/api/com/atproto/sync/index.ts +0 -27
  173. package/src/api/com/atproto/sync/listBlobs.ts +0 -33
  174. package/src/api/com/atproto/sync/listRepos.ts +0 -74
  175. package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
  176. package/src/api/com/atproto/sync/util.ts +0 -37
  177. package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
  178. package/src/api/com/atproto/temp/index.ts +0 -7
  179. package/src/api/index.ts +0 -10
  180. package/src/api/proxy.ts +0 -44
  181. package/src/app-view.ts +0 -24
  182. package/src/auth-output.ts +0 -52
  183. package/src/auth-routes.ts +0 -64
  184. package/src/auth-scope.ts +0 -40
  185. package/src/auth-verifier.ts +0 -668
  186. package/src/background.ts +0 -65
  187. package/src/basic-routes.ts +0 -52
  188. package/src/bsky-app-view.ts +0 -33
  189. package/src/config/config.ts +0 -553
  190. package/src/config/env.ts +0 -167
  191. package/src/config/index.ts +0 -3
  192. package/src/config/secrets.ts +0 -54
  193. package/src/context.ts +0 -523
  194. package/src/crawlers.ts +0 -46
  195. package/src/db/cast.ts +0 -52
  196. package/src/db/db.ts +0 -140
  197. package/src/db/index.ts +0 -4
  198. package/src/db/migrator.ts +0 -40
  199. package/src/db/pagination.ts +0 -132
  200. package/src/db/tables/moderation.ts +0 -80
  201. package/src/db/util.ts +0 -108
  202. package/src/did-cache/db/index.ts +0 -21
  203. package/src/did-cache/db/migrations.ts +0 -17
  204. package/src/did-cache/db/schema.ts +0 -9
  205. package/src/did-cache/index.ts +0 -131
  206. package/src/disk-blobstore.ts +0 -172
  207. package/src/error.ts +0 -19
  208. package/src/handle/explicit-slurs.ts +0 -22
  209. package/src/handle/index.ts +0 -49
  210. package/src/handle/reserved.ts +0 -1059
  211. package/src/image/image-url-builder.ts +0 -16
  212. package/src/index.ts +0 -189
  213. package/src/lexicons.ts +0 -4
  214. package/src/logger.ts +0 -35
  215. package/src/mailer/index.ts +0 -111
  216. package/src/mailer/moderation.ts +0 -33
  217. package/src/mailer/templates/confirm-email.d.ts +0 -4
  218. package/src/mailer/templates/confirm-email.hbs +0 -158
  219. package/src/mailer/templates/delete-account.d.ts +0 -4
  220. package/src/mailer/templates/delete-account.hbs +0 -156
  221. package/src/mailer/templates/plc-operation.d.ts +0 -4
  222. package/src/mailer/templates/plc-operation.hbs +0 -153
  223. package/src/mailer/templates/reset-password.d.ts +0 -4
  224. package/src/mailer/templates/reset-password.hbs +0 -154
  225. package/src/mailer/templates/update-email.d.ts +0 -4
  226. package/src/mailer/templates/update-email.hbs +0 -153
  227. package/src/mailer/templates.ts +0 -17
  228. package/src/pipethrough.ts +0 -716
  229. package/src/rate-limits.ts +0 -59
  230. package/src/read-after-write/index.ts +0 -3
  231. package/src/read-after-write/types.ts +0 -35
  232. package/src/read-after-write/util.ts +0 -101
  233. package/src/read-after-write/viewer.ts +0 -290
  234. package/src/redis.ts +0 -25
  235. package/src/repo/index.ts +0 -2
  236. package/src/repo/prepare.ts +0 -266
  237. package/src/repo/types.ts +0 -65
  238. package/src/scripts/README.md +0 -40
  239. package/src/scripts/index.ts +0 -20
  240. package/src/scripts/publish-identity.ts +0 -60
  241. package/src/scripts/rebuild-repo.ts +0 -119
  242. package/src/scripts/rotate-keys.ts +0 -146
  243. package/src/scripts/sequencer-recovery/index.ts +0 -23
  244. package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
  245. package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
  246. package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
  247. package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
  248. package/src/scripts/util.ts +0 -7
  249. package/src/sequencer/db/index.ts +0 -21
  250. package/src/sequencer/db/migrations/001-init.ts +0 -35
  251. package/src/sequencer/db/migrations/index.ts +0 -5
  252. package/src/sequencer/db/schema.ts +0 -19
  253. package/src/sequencer/events.ts +0 -199
  254. package/src/sequencer/index.ts +0 -3
  255. package/src/sequencer/outbox.ts +0 -123
  256. package/src/sequencer/sequencer.ts +0 -290
  257. package/src/util/compression.ts +0 -16
  258. package/src/util/debug.ts +0 -10
  259. package/src/util/http.ts +0 -31
  260. package/src/util/types.ts +0 -7
  261. package/src/well-known.ts +0 -30
  262. package/test.env +0 -2
  263. package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
  264. package/tests/_oauth_client_assets_middleware.ts +0 -23
  265. package/tests/_puppeteer.ts +0 -147
  266. package/tests/_types.d.ts +0 -16
  267. package/tests/_util.ts +0 -191
  268. package/tests/account-deactivation.test.ts +0 -204
  269. package/tests/account-deletion.test.ts +0 -300
  270. package/tests/account-manager.test.ts +0 -462
  271. package/tests/account-migration.test.ts +0 -221
  272. package/tests/account-status.test.ts +0 -206
  273. package/tests/account.test.ts +0 -595
  274. package/tests/app-passwords.test.ts +0 -262
  275. package/tests/auth.test.ts +0 -405
  276. package/tests/blob-deletes.test.ts +0 -204
  277. package/tests/create-post.test.ts +0 -79
  278. package/tests/crud.test.ts +0 -1595
  279. package/tests/db.test.ts +0 -170
  280. package/tests/email-confirmation.test.ts +0 -227
  281. package/tests/entryway-mock.ts +0 -323
  282. package/tests/entryway.test.ts +0 -145
  283. package/tests/file-uploads.test.ts +0 -301
  284. package/tests/get-service-auth.test.ts +0 -81
  285. package/tests/handle-validation.test.ts +0 -56
  286. package/tests/handles.test.ts +0 -274
  287. package/tests/invite-codes.test.ts +0 -367
  288. package/tests/invites-admin.test.ts +0 -252
  289. package/tests/moderation.test.ts +0 -280
  290. package/tests/moderator-auth.test.ts +0 -177
  291. package/tests/oauth.test.ts +0 -334
  292. package/tests/plc-operations.test.ts +0 -239
  293. package/tests/preferences.test.ts +0 -352
  294. package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
  295. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
  296. package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
  297. package/tests/proxied/admin.test.ts +0 -340
  298. package/tests/proxied/feedgen.test.ts +0 -66
  299. package/tests/proxied/notif.test.ts +0 -85
  300. package/tests/proxied/procedures.test.ts +0 -175
  301. package/tests/proxied/proxy-catchall.test.ts +0 -256
  302. package/tests/proxied/proxy-header.test.ts +0 -239
  303. package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
  304. package/tests/proxied/read-after-write.test.ts +0 -382
  305. package/tests/proxied/views.test.ts +0 -608
  306. package/tests/races.test.ts +0 -89
  307. package/tests/rate-limits.test.ts +0 -70
  308. package/tests/recovery.test.ts +0 -180
  309. package/tests/seeds/basic.ts +0 -165
  310. package/tests/seeds/follows.ts +0 -57
  311. package/tests/seeds/likes.ts +0 -14
  312. package/tests/seeds/reposts.ts +0 -18
  313. package/tests/seeds/thread.ts +0 -40
  314. package/tests/seeds/users-bulk.ts +0 -246
  315. package/tests/seeds/users.ts +0 -67
  316. package/tests/sequencer.test.ts +0 -251
  317. package/tests/server.test.ts +0 -151
  318. package/tests/sync/invertible-ops.test.ts +0 -99
  319. package/tests/sync/list.test.ts +0 -43
  320. package/tests/sync/subscribe-repos.test.ts +0 -672
  321. package/tests/sync/sync.test.ts +0 -316
  322. package/tests/takedown-appeal.test.ts +0 -166
  323. package/tsconfig.build.json +0 -9
  324. package/tsconfig.build.tsbuildinfo +0 -1
  325. package/tsconfig.json +0 -7
  326. package/tsconfig.tests.json +0 -8
@@ -1,263 +0,0 @@
1
- import { chunkArray } from '@atproto/common'
2
- import { DatetimeString, DidString, currentDatetimeString } from '@atproto/lex'
3
- import { InvalidRequestError } from '@atproto/xrpc-server'
4
- import { countAll } from '../../db/index.js'
5
- import { com } from '../../lexicons/index.js'
6
- import { AccountDb, InviteCode } from '../db/index.js'
7
-
8
- export type CodeDetail = com.atproto.server.defs.InviteCode
9
- export type CodeUse = com.atproto.server.defs.InviteCodeUse
10
-
11
- export const createInviteCodes = async (
12
- db: AccountDb,
13
- toCreate: { account: string; codes: string[] }[],
14
- useCount: number,
15
- ) => {
16
- const now = currentDatetimeString()
17
- const rows = toCreate.flatMap((account) =>
18
- account.codes.map((code) => ({
19
- code: code,
20
- availableUses: useCount,
21
- disabled: 0 as const,
22
- forAccount: account.account,
23
- createdBy: 'admin',
24
- createdAt: now,
25
- })),
26
- )
27
- await Promise.all(
28
- chunkArray(rows, 50).map((chunk) =>
29
- db.executeWithRetry(db.db.insertInto('invite_code').values(chunk)),
30
- ),
31
- )
32
- }
33
-
34
- export const createAccountInviteCodes = async (
35
- db: AccountDb,
36
- forAccount: string,
37
- codes: string[],
38
- expectedTotal: number,
39
- disabled: 0 | 1,
40
- ): Promise<CodeDetail[]> => {
41
- const now = currentDatetimeString()
42
- const rows: InviteCode[] = codes.map((code) => ({
43
- code,
44
- availableUses: 1,
45
- disabled,
46
- forAccount,
47
- createdBy: forAccount,
48
- createdAt: now,
49
- }))
50
- await db.executeWithRetry(db.db.insertInto('invite_code').values(rows))
51
-
52
- const finalRoutineInviteCodes = await db.db
53
- .selectFrom('invite_code')
54
- .where('forAccount', '=', forAccount)
55
- .where('createdBy', '!=', 'admin') // dont count admin-gifted codes aginast the user
56
- .selectAll()
57
- .execute()
58
- if (finalRoutineInviteCodes.length > expectedTotal) {
59
- throw new InvalidRequestError(
60
- 'attempted to create additional codes in another request',
61
- 'DuplicateCreate',
62
- )
63
- }
64
-
65
- return rows.map((row) => ({
66
- ...row,
67
- available: 1,
68
- disabled: row.disabled === 1,
69
- uses: [],
70
- }))
71
- }
72
-
73
- export const recordInviteUse = async (
74
- db: AccountDb,
75
- opts: {
76
- did: DidString
77
- inviteCode: string | undefined
78
- now: DatetimeString
79
- },
80
- ) => {
81
- if (!opts.inviteCode) return
82
- await db.executeWithRetry(
83
- db.db.insertInto('invite_code_use').values({
84
- code: opts.inviteCode,
85
- usedBy: opts.did,
86
- usedAt: opts.now,
87
- }),
88
- )
89
- }
90
-
91
- export const ensureInviteIsAvailable = async (
92
- db: AccountDb,
93
- inviteCode: string,
94
- ): Promise<void> => {
95
- const invite = await db.db
96
- .selectFrom('invite_code')
97
- .leftJoin('actor', 'actor.did', 'invite_code.forAccount')
98
- .where('takedownRef', 'is', null)
99
- .selectAll('invite_code')
100
- .where('code', '=', inviteCode)
101
- .executeTakeFirst()
102
-
103
- if (!invite || invite.disabled) {
104
- throw new InvalidRequestError(
105
- 'Provided invite code not available',
106
- 'InvalidInviteCode',
107
- )
108
- }
109
-
110
- const uses = await db.db
111
- .selectFrom('invite_code_use')
112
- .select(countAll.as('count'))
113
- .where('code', '=', inviteCode)
114
- .executeTakeFirstOrThrow()
115
-
116
- if (invite.availableUses <= uses.count) {
117
- throw new InvalidRequestError(
118
- 'Provided invite code not available',
119
- 'InvalidInviteCode',
120
- )
121
- }
122
- }
123
-
124
- export const selectInviteCodesQb = (db: AccountDb) => {
125
- const ref = db.db.dynamic.ref
126
- const builder = db.db
127
- .selectFrom('invite_code')
128
- .select([
129
- 'invite_code.code as code',
130
- 'invite_code.availableUses as available',
131
- 'invite_code.disabled as disabled',
132
- 'invite_code.forAccount as forAccount',
133
- 'invite_code.createdBy as createdBy',
134
- 'invite_code.createdAt as createdAt',
135
- db.db
136
- .selectFrom('invite_code_use')
137
- .select(countAll.as('count'))
138
- .whereRef('invite_code_use.code', '=', ref('invite_code.code'))
139
- .as('uses'),
140
- ])
141
- return db.db.selectFrom(builder.as('codes')).selectAll()
142
- }
143
-
144
- export const getAccountsInviteCodes = async (
145
- db: AccountDb,
146
- dids: string[],
147
- ): Promise<Map<string, CodeDetail[]>> => {
148
- const results = new Map<string, CodeDetail[]>()
149
- // We don't want to pass an empty array to kysely and let's avoid running a query entirely if there is nothing to match for
150
- if (!dids.length) return results
151
- const res = await selectInviteCodesQb(db)
152
- .where('forAccount', 'in', dids)
153
- .execute()
154
- const codes = res.map((row) => row.code)
155
- const uses = await getInviteCodesUses(db, codes)
156
- res.forEach((row) => {
157
- const existing = results.get(row.forAccount) ?? []
158
- results.set(row.forAccount, [
159
- ...existing,
160
- {
161
- ...row,
162
- uses: uses[row.code] ?? [],
163
- disabled: row.disabled === 1,
164
- } satisfies com.atproto.server.defs.InviteCode,
165
- ])
166
- })
167
- return results
168
- }
169
-
170
- export const getInviteCodesUses = async (
171
- db: AccountDb,
172
- codes: string[],
173
- ): Promise<Record<string, CodeUse[]>> => {
174
- const uses: Record<string, CodeUse[]> = {}
175
- if (codes.length > 0) {
176
- const usesRes = await db.db
177
- .selectFrom('invite_code_use')
178
- .where('code', 'in', codes)
179
- .orderBy('usedAt', 'desc')
180
- .selectAll()
181
- .execute()
182
- for (const use of usesRes) {
183
- const { code, usedBy, usedAt } = use
184
- uses[code] ??= []
185
- uses[code].push({ usedBy, usedAt })
186
- }
187
- }
188
- return uses
189
- }
190
-
191
- export const getInvitedByForAccounts = async (
192
- db: AccountDb,
193
- dids: DidString[],
194
- ): Promise<Record<string, CodeDetail>> => {
195
- if (dids.length < 1) return {}
196
- const codeDetailsRes = await selectInviteCodesQb(db)
197
- .where('code', 'in', (qb) =>
198
- qb
199
- .selectFrom('invite_code_use')
200
- .where('usedBy', 'in', dids)
201
- .select('code')
202
- .distinct(),
203
- )
204
- .execute()
205
- const uses = await getInviteCodesUses(
206
- db,
207
- codeDetailsRes.map((row) => row.code),
208
- )
209
- const codeDetails = codeDetailsRes.map(
210
- ({ uses: _, disabled, createdAt, ...row }): CodeDetail => ({
211
- ...row,
212
- createdAt,
213
- uses: uses[row.code] ?? [],
214
- disabled: disabled === 1,
215
- }),
216
- )
217
-
218
- const result: Record<string, CodeDetail> = {}
219
-
220
- for (const cur of codeDetails) {
221
- for (const use of cur.uses) {
222
- result[use.usedBy] = cur
223
- }
224
- }
225
-
226
- return result
227
- }
228
-
229
- export const disableInviteCodes = async (
230
- db: AccountDb,
231
- opts: { codes: string[]; accounts: string[] },
232
- ) => {
233
- const { codes, accounts } = opts
234
- if (codes.length > 0) {
235
- await db.executeWithRetry(
236
- db.db
237
- .updateTable('invite_code')
238
- .set({ disabled: 1 })
239
- .where('code', 'in', codes),
240
- )
241
- }
242
- if (accounts.length > 0) {
243
- await db.executeWithRetry(
244
- db.db
245
- .updateTable('invite_code')
246
- .set({ disabled: 1 })
247
- .where('forAccount', 'in', accounts),
248
- )
249
- }
250
- }
251
-
252
- export const setAccountInvitesDisabled = async (
253
- db: AccountDb,
254
- did: DidString,
255
- disabled: boolean,
256
- ) => {
257
- await db.executeWithRetry(
258
- db.db
259
- .updateTable('account')
260
- .where('did', '=', did)
261
- .set({ invitesDisabled: disabled ? 1 : 0 }),
262
- )
263
- }
@@ -1,67 +0,0 @@
1
- import { LEXICON_REFRESH_FREQUENCY, LexiconData } from '@atproto/oauth-provider'
2
- import { fromDateISO, fromJson, toDateISO, toJson } from '../../db/index.js'
3
- import { AccountDb } from '../db/index.js'
4
-
5
- export async function upsert(db: AccountDb, nsid: string, data: LexiconData) {
6
- // @TODO not annotated as `Omit<Insertable<Lexicon>, 'nsid'>`. Insertable's
7
- // nullable/non-nullable key partition evaluates `IsNullable<InsertType<…>>`
8
- // per column, which for the recursive `JsonEncoded<LexiconDocument>` column
9
- // overflows the tsgo (TS7) checker's instantiation depth (TS2589). The older
10
- // tsc handled it; the `.values()`/`.doUpdateSet()` calls below still
11
- // type-check this object against the insert type regardless.
12
- const updates = {
13
- ...data,
14
- createdAt: toDateISO(data.createdAt),
15
- updatedAt: toDateISO(data.updatedAt),
16
- lastSucceededAt: data.lastSucceededAt
17
- ? toDateISO(data.lastSucceededAt)
18
- : null,
19
- lexicon: data.lexicon ? toJson(data.lexicon) : null,
20
- }
21
-
22
- await db.executeWithRetry(
23
- db.db
24
- .insertInto('lexicon')
25
- .values({ ...updates, nsid })
26
- .onConflict((oc) => oc.column('nsid').doUpdateSet(updates)),
27
- )
28
-
29
- // Garbage collection: remove old, never resolved, lexicons.
30
- // Uses "lexicon_failures_idx"
31
- await db.executeWithRetry(
32
- db.db
33
- .deleteFrom('lexicon')
34
- .where('lexicon', 'is', null)
35
- .where(
36
- 'updatedAt',
37
- '<',
38
- toDateISO(new Date(Date.now() - LEXICON_REFRESH_FREQUENCY)),
39
- ),
40
- )
41
- }
42
-
43
- export async function find(
44
- db: AccountDb,
45
- nsid: string,
46
- ): Promise<LexiconData | null> {
47
- const row = await db.db
48
- .selectFrom('lexicon')
49
- .selectAll()
50
- .where('nsid', '=', nsid)
51
- .executeTakeFirst()
52
- if (!row) return null
53
-
54
- return {
55
- ...row,
56
- createdAt: fromDateISO(row.createdAt),
57
- updatedAt: fromDateISO(row.updatedAt),
58
- lastSucceededAt: row.lastSucceededAt
59
- ? fromDateISO(row.lastSucceededAt)
60
- : null,
61
- lexicon: row.lexicon ? fromJson(row.lexicon) : null,
62
- }
63
- }
64
-
65
- export async function remove(db: AccountDb, nsid: string) {
66
- await db.db.deleteFrom('lexicon').where('nsid', '=', nsid).execute()
67
- }
@@ -1,136 +0,0 @@
1
- import { randomStr } from '@atproto/crypto'
2
- import { DatetimeString, currentDatetimeString } from '@atproto/lex'
3
- import { InvalidRequestError } from '@atproto/xrpc-server'
4
- import { com } from '../../lexicons/index.js'
5
- import { AccountDb } from '../db/index.js'
6
- import * as scrypt from './scrypt.js'
7
-
8
- export type AppPassDescript = {
9
- name: string
10
- privileged: boolean
11
- }
12
-
13
- export const verifyAccountPassword = async (
14
- db: AccountDb,
15
- did: string,
16
- password: string,
17
- ): Promise<boolean> => {
18
- const found = await db.db
19
- .selectFrom('account')
20
- .selectAll()
21
- .where('did', '=', did)
22
- .executeTakeFirst()
23
- return found ? await scrypt.verify(password, found.passwordScrypt) : false
24
- }
25
-
26
- export const verifyAppPassword = async (
27
- db: AccountDb,
28
- did: string,
29
- password: string,
30
- ): Promise<AppPassDescript | null> => {
31
- const passwordScrypt = await scrypt.hashAppPassword(did, password)
32
- const found = await db.db
33
- .selectFrom('app_password')
34
- .selectAll()
35
- .where('did', '=', did)
36
- .where('passwordScrypt', '=', passwordScrypt)
37
- .executeTakeFirst()
38
- if (!found) return null
39
- return {
40
- name: found.name,
41
- privileged: found.privileged === 1 ? true : false,
42
- }
43
- }
44
-
45
- export const updateUserPassword = async (
46
- db: AccountDb,
47
- opts: {
48
- did: string
49
- passwordScrypt: string
50
- },
51
- ) => {
52
- await db.executeWithRetry(
53
- db.db
54
- .updateTable('account')
55
- .set({ passwordScrypt: opts.passwordScrypt })
56
- .where('did', '=', opts.did),
57
- )
58
- }
59
-
60
- export const createAppPassword = async (
61
- db: AccountDb,
62
- did: string,
63
- name: string,
64
- privileged: boolean,
65
- ): Promise<com.atproto.server.createAppPassword.AppPassword> => {
66
- // create an app password with format:
67
- // 1234-abcd-5678-efgh
68
- const str = randomStr(16, 'base32').slice(0, 16)
69
- const chunks = [
70
- str.slice(0, 4),
71
- str.slice(4, 8),
72
- str.slice(8, 12),
73
- str.slice(12, 16),
74
- ]
75
- const password = chunks.join('-')
76
- const passwordScrypt = await scrypt.hashAppPassword(did, password)
77
- const [got] = await db.executeWithRetry(
78
- db.db
79
- .insertInto('app_password')
80
- .values({
81
- did,
82
- name,
83
- passwordScrypt,
84
- createdAt: currentDatetimeString(),
85
- privileged: privileged ? 1 : 0,
86
- })
87
- .returningAll(),
88
- )
89
- if (!got) {
90
- throw new InvalidRequestError('could not create app-specific password')
91
- }
92
- return {
93
- name,
94
- password,
95
- createdAt: got.createdAt,
96
- privileged,
97
- }
98
- }
99
-
100
- export const listAppPasswords = async (
101
- db: AccountDb,
102
- did: string,
103
- ): Promise<
104
- { name: string; createdAt: DatetimeString; privileged: boolean }[]
105
- > => {
106
- const res = await db.db
107
- .selectFrom('app_password')
108
- .select(['name', 'createdAt', 'privileged'])
109
- .where('did', '=', did)
110
- .orderBy('createdAt', 'desc')
111
- .execute()
112
- return res.map((row) => ({
113
- name: row.name,
114
- createdAt: row.createdAt,
115
- privileged: row.privileged === 1 ? true : false,
116
- }))
117
- }
118
-
119
- export const deleteAppPassword = async (
120
- db: AccountDb,
121
- did: string,
122
- name: string,
123
- ) => {
124
- await db.executeWithRetry(
125
- db.db
126
- .deleteFrom('app_password')
127
- .where('did', '=', did)
128
- .where('name', '=', name),
129
- )
130
- }
131
-
132
- export const deleteAllAppPasswords = async (db: AccountDb, did: string) => {
133
- await db.executeWithRetry(
134
- db.db.deleteFrom('app_password').where('did', '=', did),
135
- )
136
- }
@@ -1,24 +0,0 @@
1
- import { Cid, currentDatetimeString } from '@atproto/lex'
2
- import { AccountDb } from '../db/index.js'
3
-
4
- export const updateRoot = async (
5
- db: AccountDb,
6
- did: string,
7
- cid: Cid,
8
- rev: string,
9
- ) => {
10
- // @TODO balance risk of a race in the case of a long retry
11
- await db.executeWithRetry(
12
- db.db
13
- .insertInto('repo_root')
14
- .values({
15
- did,
16
- cid: cid.toString(),
17
- rev,
18
- indexedAt: currentDatetimeString(),
19
- })
20
- .onConflict((oc) =>
21
- oc.column('did').doUpdateSet({ cid: cid.toString(), rev }),
22
- ),
23
- )
24
- }
@@ -1,53 +0,0 @@
1
- import crypto from 'node:crypto'
2
- import * as ui8 from 'uint8arrays'
3
- import { sha256 } from '@atproto/crypto'
4
-
5
- export const OLD_PASSWORD_MAX_LENGTH = 512
6
- export const NEW_PASSWORD_MAX_LENGTH = 256
7
-
8
- export const genSaltAndHash = (password: string): Promise<string> => {
9
- const salt = crypto.randomBytes(16).toString('hex')
10
- return hashWithSalt(password, salt)
11
- }
12
-
13
- export const hashWithSalt = (
14
- password: string,
15
- salt: string,
16
- ): Promise<string> => {
17
- return new Promise((resolve, reject) => {
18
- crypto.scrypt(password, salt, 64, (err, hash) => {
19
- if (err) return reject(err)
20
- resolve(salt + ':' + hash.toString('hex'))
21
- })
22
- })
23
- }
24
-
25
- export const verify = async (
26
- password: string,
27
- storedHash: string,
28
- ): Promise<boolean> => {
29
- const [salt, hash] = storedHash.split(':')
30
- const derivedHash = await getDerivedHash(password, salt)
31
- return hash === derivedHash
32
- }
33
-
34
- export const getDerivedHash = (
35
- password: string,
36
- salt: string,
37
- ): Promise<string> => {
38
- return new Promise((resolve, reject) => {
39
- crypto.scrypt(password, salt, 64, (err, derivedHash) => {
40
- if (err) return reject(err)
41
- resolve(derivedHash.toString('hex'))
42
- })
43
- })
44
- }
45
-
46
- export const hashAppPassword = async (
47
- did: string,
48
- password: string,
49
- ): Promise<string> => {
50
- const sha = await sha256(did)
51
- const salt = ui8.toString(sha.slice(0, 16), 'hex')
52
- return hashWithSalt(password, salt)
53
- }
@@ -1,158 +0,0 @@
1
- import { Selectable } from 'kysely'
2
- import {
3
- Code,
4
- Did,
5
- NewTokenData,
6
- RefreshToken,
7
- TokenData,
8
- TokenId,
9
- } from '@atproto/oauth-provider'
10
- import { fromDateISO, fromJson, toDateISO, toJson } from '../../db/index.js'
11
- import { AccountDb, Token } from '../db/index.js'
12
- import { selectAccountQB } from './account.js'
13
-
14
- export function toTokenData(row: Selectable<Token>): TokenData {
15
- return {
16
- createdAt: fromDateISO(row.createdAt),
17
- expiresAt: fromDateISO(row.expiresAt),
18
- updatedAt: fromDateISO(row.updatedAt),
19
- clientId: row.clientId,
20
- clientAuth: fromJson(row.clientAuth),
21
- deviceId: row.deviceId,
22
- did: row.did,
23
- parameters: fromJson(row.parameters),
24
- code: row.code,
25
- scope: row.scope,
26
- }
27
- }
28
-
29
- const selectTokenInfoQB = (db: AccountDb) =>
30
- selectAccountQB(db, { includeDeactivated: true })
31
- // uses "token_did_idx" index (though unlikely in practice)
32
- .innerJoin('token', 'token.did', 'actor.did')
33
- .select([
34
- 'token.id',
35
- 'token.tokenId',
36
- 'token.createdAt',
37
- 'token.updatedAt',
38
- 'token.expiresAt',
39
- 'token.clientId',
40
- 'token.clientAuth',
41
- 'token.deviceId',
42
- 'token.did',
43
- 'token.parameters',
44
- 'token.details',
45
- 'token.code',
46
- 'token.currentRefreshToken',
47
- 'token.scope',
48
- ])
49
-
50
- export const createQB = (
51
- db: AccountDb,
52
- tokenId: TokenId,
53
- data: TokenData,
54
- refreshToken?: RefreshToken,
55
- ) => {
56
- return db.db.insertInto('token').values({
57
- tokenId,
58
- createdAt: toDateISO(data.createdAt),
59
- expiresAt: toDateISO(data.expiresAt),
60
- updatedAt: toDateISO(data.updatedAt),
61
- clientId: data.clientId,
62
- clientAuth: toJson(data.clientAuth),
63
- deviceId: data.deviceId,
64
- did: data.did,
65
- parameters: toJson(data.parameters),
66
- details: data.details ? toJson(data.details) : null,
67
- code: data.code,
68
- currentRefreshToken: refreshToken || null,
69
- scope: data.scope,
70
- })
71
- }
72
-
73
- export const forRotateQB = (db: AccountDb, id: TokenId) =>
74
- db.db
75
- .selectFrom('token')
76
- .where('tokenId', '=', id)
77
- .where('currentRefreshToken', 'is not', null)
78
- .select(['id', 'currentRefreshToken'])
79
-
80
- export const findByQB = (
81
- db: AccountDb,
82
- search: {
83
- id?: number
84
- did?: Did
85
- code?: Code
86
- tokenId?: TokenId
87
- currentRefreshToken?: RefreshToken
88
- },
89
- ) => {
90
- if (
91
- search.id === undefined &&
92
- search.did === undefined &&
93
- search.code === undefined &&
94
- search.tokenId === undefined &&
95
- search.currentRefreshToken === undefined
96
- ) {
97
- // Prevent accidental scan
98
- throw new TypeError('At least one search parameter is required')
99
- }
100
-
101
- return selectTokenInfoQB(db)
102
- .$if(search.id !== undefined, (qb) =>
103
- // uses primary key index
104
- qb.where('token.id', '=', search.id!),
105
- )
106
- .$if(search.did !== undefined, (qb) =>
107
- // uses "token_did_idx" index
108
- qb.where('token.did', '=', search.did!),
109
- )
110
- .$if(search.code !== undefined, (qb) =>
111
- // uses "token_code_idx" partial index (hence the null check)
112
- qb
113
- .where('token.code', '=', search.code!)
114
- .where('token.code', 'is not', null),
115
- )
116
- .$if(search.tokenId !== undefined, (qb) =>
117
- // uses "token_token_id_idx"
118
- qb.where('token.tokenId', '=', search.tokenId!),
119
- )
120
- .$if(search.currentRefreshToken !== undefined, (qb) =>
121
- // uses "token_refresh_token_unique_idx"
122
- qb.where('token.currentRefreshToken', '=', search.currentRefreshToken!),
123
- )
124
- }
125
-
126
- export const removeByDid = async (db: AccountDb, did: Did) => {
127
- await db.executeWithRetry(
128
- db.db
129
- .deleteFrom('token')
130
- // uses "token_did_idx" index
131
- .where('did', '=', did),
132
- )
133
- }
134
-
135
- export const rotateQB = (
136
- db: AccountDb,
137
- id: number,
138
- newTokenId: TokenId,
139
- newRefreshToken: RefreshToken,
140
- newData: NewTokenData,
141
- ) =>
142
- db.db
143
- .updateTable('token')
144
- .set({
145
- tokenId: newTokenId,
146
- currentRefreshToken: newRefreshToken,
147
-
148
- expiresAt: toDateISO(newData.expiresAt),
149
- updatedAt: toDateISO(newData.updatedAt),
150
- clientAuth: toJson(newData.clientAuth),
151
- scope: newData.scope,
152
- })
153
- // uses primary key index
154
- .where('id', '=', id)
155
-
156
- export const removeQB = (db: AccountDb, tokenId: TokenId) =>
157
- // uses "used_refresh_token_fk" to cascade delete
158
- db.db.deleteFrom('token').where('tokenId', '=', tokenId)