@atproto/pds 0.5.11 → 0.5.14

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 (322) hide show
  1. package/CHANGELOG.md +46 -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/package.json +42 -38
  10. package/build.templates.cjs +0 -22
  11. package/example.env +0 -42
  12. package/jest.config.cjs +0 -27
  13. package/src/account-manager/account-manager.ts +0 -916
  14. package/src/account-manager/db/index.ts +0 -21
  15. package/src/account-manager/db/migrations/001-init.ts +0 -115
  16. package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
  17. package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
  18. package/src/account-manager/db/migrations/004-oauth.ts +0 -122
  19. package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
  20. package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
  21. package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
  22. package/src/account-manager/db/migrations/index.ts +0 -17
  23. package/src/account-manager/db/schema/account-device.ts +0 -14
  24. package/src/account-manager/db/schema/account.ts +0 -16
  25. package/src/account-manager/db/schema/actor.ts +0 -17
  26. package/src/account-manager/db/schema/app-password.ts +0 -13
  27. package/src/account-manager/db/schema/authorization-request.ts +0 -30
  28. package/src/account-manager/db/schema/authorized-client.ts +0 -23
  29. package/src/account-manager/db/schema/device.ts +0 -18
  30. package/src/account-manager/db/schema/email-token.ts +0 -19
  31. package/src/account-manager/db/schema/index.ts +0 -43
  32. package/src/account-manager/db/schema/invite-code.ts +0 -24
  33. package/src/account-manager/db/schema/lexicon.ts +0 -15
  34. package/src/account-manager/db/schema/refresh-token.ts +0 -11
  35. package/src/account-manager/db/schema/repo-root.ts +0 -12
  36. package/src/account-manager/db/schema/token.ts +0 -38
  37. package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
  38. package/src/account-manager/helpers/account-device.ts +0 -63
  39. package/src/account-manager/helpers/account.ts +0 -355
  40. package/src/account-manager/helpers/auth.ts +0 -222
  41. package/src/account-manager/helpers/authorization-request.ts +0 -90
  42. package/src/account-manager/helpers/authorized-client.ts +0 -75
  43. package/src/account-manager/helpers/device.ts +0 -47
  44. package/src/account-manager/helpers/email-token.ts +0 -87
  45. package/src/account-manager/helpers/invite.ts +0 -263
  46. package/src/account-manager/helpers/lexicon.ts +0 -67
  47. package/src/account-manager/helpers/password.ts +0 -136
  48. package/src/account-manager/helpers/repo.ts +0 -24
  49. package/src/account-manager/helpers/scrypt.ts +0 -53
  50. package/src/account-manager/helpers/token.ts +0 -158
  51. package/src/account-manager/helpers/used-refresh-token.ts +0 -30
  52. package/src/account-manager/oauth-store.ts +0 -880
  53. package/src/account-manager/scope-reference-getter.ts +0 -106
  54. package/src/actor-store/actor-store-reader.ts +0 -45
  55. package/src/actor-store/actor-store-resources.ts +0 -8
  56. package/src/actor-store/actor-store-transactor.ts +0 -31
  57. package/src/actor-store/actor-store-writer.ts +0 -17
  58. package/src/actor-store/actor-store.ts +0 -210
  59. package/src/actor-store/blob/reader.ts +0 -160
  60. package/src/actor-store/blob/transactor.ts +0 -383
  61. package/src/actor-store/db/index.ts +0 -20
  62. package/src/actor-store/db/migrations/001-init.ts +0 -105
  63. package/src/actor-store/db/migrations/index.ts +0 -5
  64. package/src/actor-store/db/schema/account-pref.ts +0 -11
  65. package/src/actor-store/db/schema/backlink.ts +0 -9
  66. package/src/actor-store/db/schema/blob.ts +0 -14
  67. package/src/actor-store/db/schema/index.ts +0 -23
  68. package/src/actor-store/db/schema/record-blob.ts +0 -8
  69. package/src/actor-store/db/schema/record.ts +0 -14
  70. package/src/actor-store/db/schema/repo-block.ts +0 -10
  71. package/src/actor-store/db/schema/repo-root.ts +0 -10
  72. package/src/actor-store/migrate.ts +0 -39
  73. package/src/actor-store/preference/reader.ts +0 -48
  74. package/src/actor-store/preference/transactor.ts +0 -55
  75. package/src/actor-store/preference/util.ts +0 -39
  76. package/src/actor-store/record/reader.ts +0 -374
  77. package/src/actor-store/record/transactor.ts +0 -111
  78. package/src/actor-store/repo/reader.ts +0 -31
  79. package/src/actor-store/repo/sql-repo-reader.ts +0 -150
  80. package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
  81. package/src/actor-store/repo/transactor.ts +0 -227
  82. package/src/api/app/bsky/actor/getPreferences.ts +0 -57
  83. package/src/api/app/bsky/actor/getProfile.ts +0 -41
  84. package/src/api/app/bsky/actor/getProfiles.ts +0 -51
  85. package/src/api/app/bsky/actor/index.ts +0 -13
  86. package/src/api/app/bsky/actor/putPreferences.ts +0 -62
  87. package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
  88. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
  89. package/src/api/app/bsky/feed/getFeed.ts +0 -47
  90. package/src/api/app/bsky/feed/getPostThread.ts +0 -251
  91. package/src/api/app/bsky/feed/getTimeline.ts +0 -50
  92. package/src/api/app/bsky/feed/index.ts +0 -15
  93. package/src/api/app/bsky/index.ts +0 -11
  94. package/src/api/app/bsky/notification/index.ts +0 -7
  95. package/src/api/app/bsky/notification/registerPush.ts +0 -71
  96. package/src/api/app/bsky/util/resolver.ts +0 -20
  97. package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
  98. package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
  99. package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
  100. package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
  101. package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
  102. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
  103. package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
  104. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
  105. package/src/api/com/atproto/admin/index.ts +0 -31
  106. package/src/api/com/atproto/admin/sendEmail.ts +0 -47
  107. package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
  108. package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
  109. package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
  110. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
  111. package/src/api/com/atproto/admin/util.ts +0 -66
  112. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
  113. package/src/api/com/atproto/identity/index.ts +0 -17
  114. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
  115. package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
  116. package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
  117. package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
  118. package/src/api/com/atproto/identity/updateHandle.ts +0 -66
  119. package/src/api/com/atproto/index.ts +0 -19
  120. package/src/api/com/atproto/moderation/createReport.ts +0 -41
  121. package/src/api/com/atproto/moderation/index.ts +0 -7
  122. package/src/api/com/atproto/repo/applyWrites.ts +0 -226
  123. package/src/api/com/atproto/repo/createRecord.ts +0 -143
  124. package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
  125. package/src/api/com/atproto/repo/describeRepo.ts +0 -43
  126. package/src/api/com/atproto/repo/getRecord.ts +0 -40
  127. package/src/api/com/atproto/repo/importRepo.ts +0 -101
  128. package/src/api/com/atproto/repo/index.ts +0 -25
  129. package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
  130. package/src/api/com/atproto/repo/listRecords.ts +0 -36
  131. package/src/api/com/atproto/repo/putRecord.ts +0 -211
  132. package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
  133. package/src/api/com/atproto/server/activateAccount.ts +0 -37
  134. package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
  135. package/src/api/com/atproto/server/confirmEmail.ts +0 -39
  136. package/src/api/com/atproto/server/createAccount.ts +0 -327
  137. package/src/api/com/atproto/server/createAppPassword.ts +0 -53
  138. package/src/api/com/atproto/server/createInviteCode.ts +0 -38
  139. package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
  140. package/src/api/com/atproto/server/createSession.ts +0 -97
  141. package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
  142. package/src/api/com/atproto/server/deleteAccount.ts +0 -85
  143. package/src/api/com/atproto/server/deleteSession.ts +0 -23
  144. package/src/api/com/atproto/server/describeServer.ts +0 -29
  145. package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
  146. package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
  147. package/src/api/com/atproto/server/getSession.ts +0 -80
  148. package/src/api/com/atproto/server/index.ts +0 -55
  149. package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
  150. package/src/api/com/atproto/server/refreshSession.ts +0 -72
  151. package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
  152. package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
  153. package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
  154. package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
  155. package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
  156. package/src/api/com/atproto/server/resetPassword.ts +0 -50
  157. package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
  158. package/src/api/com/atproto/server/updateEmail.ts +0 -52
  159. package/src/api/com/atproto/server/util.ts +0 -136
  160. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
  161. package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
  162. package/src/api/com/atproto/sync/getBlob.ts +0 -61
  163. package/src/api/com/atproto/sync/getBlocks.ts +0 -37
  164. package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
  165. package/src/api/com/atproto/sync/getRecord.ts +0 -49
  166. package/src/api/com/atproto/sync/getRepo.ts +0 -75
  167. package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
  168. package/src/api/com/atproto/sync/index.ts +0 -27
  169. package/src/api/com/atproto/sync/listBlobs.ts +0 -33
  170. package/src/api/com/atproto/sync/listRepos.ts +0 -74
  171. package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
  172. package/src/api/com/atproto/sync/util.ts +0 -37
  173. package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
  174. package/src/api/com/atproto/temp/index.ts +0 -7
  175. package/src/api/index.ts +0 -10
  176. package/src/api/proxy.ts +0 -44
  177. package/src/app-view.ts +0 -24
  178. package/src/auth-output.ts +0 -52
  179. package/src/auth-routes.ts +0 -64
  180. package/src/auth-scope.ts +0 -40
  181. package/src/auth-verifier.ts +0 -668
  182. package/src/background.ts +0 -65
  183. package/src/basic-routes.ts +0 -52
  184. package/src/bsky-app-view.ts +0 -33
  185. package/src/config/config.ts +0 -553
  186. package/src/config/env.ts +0 -167
  187. package/src/config/index.ts +0 -3
  188. package/src/config/secrets.ts +0 -54
  189. package/src/context.ts +0 -523
  190. package/src/crawlers.ts +0 -46
  191. package/src/db/cast.ts +0 -52
  192. package/src/db/db.ts +0 -140
  193. package/src/db/index.ts +0 -4
  194. package/src/db/migrator.ts +0 -40
  195. package/src/db/pagination.ts +0 -132
  196. package/src/db/tables/moderation.ts +0 -80
  197. package/src/db/util.ts +0 -108
  198. package/src/did-cache/db/index.ts +0 -21
  199. package/src/did-cache/db/migrations.ts +0 -17
  200. package/src/did-cache/db/schema.ts +0 -9
  201. package/src/did-cache/index.ts +0 -131
  202. package/src/disk-blobstore.ts +0 -172
  203. package/src/error.ts +0 -19
  204. package/src/handle/explicit-slurs.ts +0 -22
  205. package/src/handle/index.ts +0 -49
  206. package/src/handle/reserved.ts +0 -1059
  207. package/src/image/image-url-builder.ts +0 -16
  208. package/src/index.ts +0 -189
  209. package/src/lexicons.ts +0 -4
  210. package/src/logger.ts +0 -35
  211. package/src/mailer/index.ts +0 -111
  212. package/src/mailer/moderation.ts +0 -33
  213. package/src/mailer/templates/confirm-email.d.ts +0 -4
  214. package/src/mailer/templates/confirm-email.hbs +0 -158
  215. package/src/mailer/templates/delete-account.d.ts +0 -4
  216. package/src/mailer/templates/delete-account.hbs +0 -156
  217. package/src/mailer/templates/plc-operation.d.ts +0 -4
  218. package/src/mailer/templates/plc-operation.hbs +0 -153
  219. package/src/mailer/templates/reset-password.d.ts +0 -4
  220. package/src/mailer/templates/reset-password.hbs +0 -154
  221. package/src/mailer/templates/update-email.d.ts +0 -4
  222. package/src/mailer/templates/update-email.hbs +0 -153
  223. package/src/mailer/templates.ts +0 -17
  224. package/src/pipethrough.ts +0 -716
  225. package/src/rate-limits.ts +0 -59
  226. package/src/read-after-write/index.ts +0 -3
  227. package/src/read-after-write/types.ts +0 -35
  228. package/src/read-after-write/util.ts +0 -101
  229. package/src/read-after-write/viewer.ts +0 -290
  230. package/src/redis.ts +0 -25
  231. package/src/repo/index.ts +0 -2
  232. package/src/repo/prepare.ts +0 -266
  233. package/src/repo/types.ts +0 -65
  234. package/src/scripts/README.md +0 -40
  235. package/src/scripts/index.ts +0 -20
  236. package/src/scripts/publish-identity.ts +0 -60
  237. package/src/scripts/rebuild-repo.ts +0 -119
  238. package/src/scripts/rotate-keys.ts +0 -146
  239. package/src/scripts/sequencer-recovery/index.ts +0 -23
  240. package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
  241. package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
  242. package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
  243. package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
  244. package/src/scripts/util.ts +0 -7
  245. package/src/sequencer/db/index.ts +0 -21
  246. package/src/sequencer/db/migrations/001-init.ts +0 -35
  247. package/src/sequencer/db/migrations/index.ts +0 -5
  248. package/src/sequencer/db/schema.ts +0 -19
  249. package/src/sequencer/events.ts +0 -199
  250. package/src/sequencer/index.ts +0 -3
  251. package/src/sequencer/outbox.ts +0 -123
  252. package/src/sequencer/sequencer.ts +0 -290
  253. package/src/util/compression.ts +0 -16
  254. package/src/util/debug.ts +0 -10
  255. package/src/util/http.ts +0 -31
  256. package/src/util/types.ts +0 -7
  257. package/src/well-known.ts +0 -30
  258. package/test.env +0 -2
  259. package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
  260. package/tests/_oauth_client_assets_middleware.ts +0 -23
  261. package/tests/_puppeteer.ts +0 -147
  262. package/tests/_types.d.ts +0 -16
  263. package/tests/_util.ts +0 -191
  264. package/tests/account-deactivation.test.ts +0 -204
  265. package/tests/account-deletion.test.ts +0 -300
  266. package/tests/account-manager.test.ts +0 -462
  267. package/tests/account-migration.test.ts +0 -221
  268. package/tests/account-status.test.ts +0 -206
  269. package/tests/account.test.ts +0 -595
  270. package/tests/app-passwords.test.ts +0 -262
  271. package/tests/auth.test.ts +0 -405
  272. package/tests/blob-deletes.test.ts +0 -204
  273. package/tests/create-post.test.ts +0 -79
  274. package/tests/crud.test.ts +0 -1595
  275. package/tests/db.test.ts +0 -170
  276. package/tests/email-confirmation.test.ts +0 -227
  277. package/tests/entryway-mock.ts +0 -323
  278. package/tests/entryway.test.ts +0 -145
  279. package/tests/file-uploads.test.ts +0 -301
  280. package/tests/get-service-auth.test.ts +0 -81
  281. package/tests/handle-validation.test.ts +0 -56
  282. package/tests/handles.test.ts +0 -274
  283. package/tests/invite-codes.test.ts +0 -367
  284. package/tests/invites-admin.test.ts +0 -252
  285. package/tests/moderation.test.ts +0 -280
  286. package/tests/moderator-auth.test.ts +0 -177
  287. package/tests/oauth.test.ts +0 -334
  288. package/tests/plc-operations.test.ts +0 -239
  289. package/tests/preferences.test.ts +0 -352
  290. package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
  291. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
  292. package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
  293. package/tests/proxied/admin.test.ts +0 -340
  294. package/tests/proxied/feedgen.test.ts +0 -66
  295. package/tests/proxied/notif.test.ts +0 -85
  296. package/tests/proxied/procedures.test.ts +0 -175
  297. package/tests/proxied/proxy-catchall.test.ts +0 -256
  298. package/tests/proxied/proxy-header.test.ts +0 -239
  299. package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
  300. package/tests/proxied/read-after-write.test.ts +0 -382
  301. package/tests/proxied/views.test.ts +0 -608
  302. package/tests/races.test.ts +0 -89
  303. package/tests/rate-limits.test.ts +0 -70
  304. package/tests/recovery.test.ts +0 -180
  305. package/tests/seeds/basic.ts +0 -165
  306. package/tests/seeds/follows.ts +0 -57
  307. package/tests/seeds/likes.ts +0 -14
  308. package/tests/seeds/reposts.ts +0 -18
  309. package/tests/seeds/thread.ts +0 -40
  310. package/tests/seeds/users-bulk.ts +0 -246
  311. package/tests/seeds/users.ts +0 -67
  312. package/tests/sequencer.test.ts +0 -251
  313. package/tests/server.test.ts +0 -151
  314. package/tests/sync/invertible-ops.test.ts +0 -99
  315. package/tests/sync/list.test.ts +0 -43
  316. package/tests/sync/subscribe-repos.test.ts +0 -672
  317. package/tests/sync/sync.test.ts +0 -316
  318. package/tests/takedown-appeal.test.ts +0 -166
  319. package/tsconfig.build.json +0 -9
  320. package/tsconfig.build.tsbuildinfo +0 -1
  321. package/tsconfig.json +0 -7
  322. 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)