@atproto/pds 0.4.33 → 0.4.35
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.
- package/CHANGELOG.md +17 -0
- package/dist/account-manager/db/migrations/004-oauth.d.ts +4 -0
- package/dist/account-manager/db/migrations/004-oauth.d.ts.map +1 -0
- package/dist/account-manager/db/migrations/004-oauth.js +106 -0
- package/dist/account-manager/db/migrations/004-oauth.js.map +1 -0
- package/dist/account-manager/db/migrations/index.d.ts +2 -0
- package/dist/account-manager/db/migrations/index.d.ts.map +1 -1
- package/dist/account-manager/db/migrations/index.js +2 -0
- package/dist/account-manager/db/migrations/index.js.map +1 -1
- package/dist/account-manager/db/schema/authorization-request.d.ts +19 -0
- package/dist/account-manager/db/schema/authorization-request.d.ts.map +1 -0
- package/dist/account-manager/db/schema/authorization-request.js +5 -0
- package/dist/account-manager/db/schema/authorization-request.js.map +1 -0
- package/dist/account-manager/db/schema/device-account.d.ts +14 -0
- package/dist/account-manager/db/schema/device-account.d.ts.map +1 -0
- package/dist/account-manager/db/schema/device-account.js +5 -0
- package/dist/account-manager/db/schema/device-account.js.map +1 -0
- package/dist/account-manager/db/schema/device.d.ts +16 -0
- package/dist/account-manager/db/schema/device.d.ts.map +1 -0
- package/dist/account-manager/db/schema/device.js +5 -0
- package/dist/account-manager/db/schema/device.js.map +1 -0
- package/dist/account-manager/db/schema/index.d.ts +11 -1
- package/dist/account-manager/db/schema/index.d.ts.map +1 -1
- package/dist/account-manager/db/schema/token.d.ts +24 -0
- package/dist/account-manager/db/schema/token.d.ts.map +1 -0
- package/dist/account-manager/db/schema/token.js +5 -0
- package/dist/account-manager/db/schema/token.js.map +1 -0
- package/dist/account-manager/db/schema/used-refresh-token.d.ts +12 -0
- package/dist/account-manager/db/schema/used-refresh-token.d.ts.map +1 -0
- package/dist/account-manager/db/schema/used-refresh-token.js +5 -0
- package/dist/account-manager/db/schema/used-refresh-token.js.map +1 -0
- package/dist/account-manager/helpers/account.d.ts +27 -5
- package/dist/account-manager/helpers/account.d.ts.map +1 -1
- package/dist/account-manager/helpers/account.js +15 -14
- package/dist/account-manager/helpers/account.js.map +1 -1
- package/dist/account-manager/helpers/authorization-request.d.ts +12 -0
- package/dist/account-manager/helpers/authorization-request.d.ts.map +1 -0
- package/dist/account-manager/helpers/authorization-request.js +59 -0
- package/dist/account-manager/helpers/authorization-request.js.map +1 -0
- package/dist/account-manager/helpers/device-account.d.ts +108 -0
- package/dist/account-manager/helpers/device-account.d.ts.map +1 -0
- package/dist/account-manager/helpers/device-account.js +82 -0
- package/dist/account-manager/helpers/device-account.js.map +1 -0
- package/dist/account-manager/helpers/device.d.ts +9 -0
- package/dist/account-manager/helpers/device.d.ts.map +1 -0
- package/dist/account-manager/helpers/device.js +32 -0
- package/dist/account-manager/helpers/device.js.map +1 -0
- package/dist/account-manager/helpers/token.d.ts +485 -0
- package/dist/account-manager/helpers/token.d.ts.map +1 -0
- package/dist/account-manager/helpers/token.js +123 -0
- package/dist/account-manager/helpers/token.js.map +1 -0
- package/dist/account-manager/helpers/used-refresh-token.d.ts +10 -0
- package/dist/account-manager/helpers/used-refresh-token.d.ts.map +1 -0
- package/dist/account-manager/helpers/used-refresh-token.js +25 -0
- package/dist/account-manager/helpers/used-refresh-token.js.map +1 -0
- package/dist/account-manager/index.d.ts +36 -6
- package/dist/account-manager/index.d.ts.map +1 -1
- package/dist/account-manager/index.js +223 -22
- package/dist/account-manager/index.js.map +1 -1
- package/dist/actor-store/preference/reader.d.ts +2 -1
- package/dist/actor-store/preference/reader.d.ts.map +1 -1
- package/dist/actor-store/preference/reader.js +3 -1
- package/dist/actor-store/preference/reader.js.map +1 -1
- package/dist/actor-store/preference/transactor.d.ts +2 -1
- package/dist/actor-store/preference/transactor.d.ts.map +1 -1
- package/dist/actor-store/preference/transactor.js +7 -1
- package/dist/actor-store/preference/transactor.js.map +1 -1
- package/dist/actor-store/preference/util.d.ts +3 -0
- package/dist/actor-store/preference/util.d.ts.map +1 -0
- package/dist/actor-store/preference/util.js +12 -0
- package/dist/actor-store/preference/util.js.map +1 -0
- package/dist/actor-store/record/reader.d.ts +1 -1
- package/dist/api/app/bsky/actor/getPreferences.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/getPreferences.js +1 -6
- package/dist/api/app/bsky/actor/getPreferences.js.map +1 -1
- package/dist/api/app/bsky/actor/putPreferences.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/putPreferences.js +1 -1
- package/dist/api/app/bsky/actor/putPreferences.js.map +1 -1
- package/dist/api/app/bsky/util/resolver.d.ts +1 -1
- package/dist/api/com/atproto/server/createSession.d.ts.map +1 -1
- package/dist/api/com/atproto/server/createSession.js +7 -31
- package/dist/api/com/atproto/server/createSession.js.map +1 -1
- package/dist/api/com/atproto/server/deleteSession.d.ts.map +1 -1
- package/dist/api/com/atproto/server/deleteSession.js +14 -13
- package/dist/api/com/atproto/server/deleteSession.js.map +1 -1
- package/dist/api/com/atproto/server/getSession.d.ts.map +1 -1
- package/dist/api/com/atproto/server/getSession.js +4 -2
- package/dist/api/com/atproto/server/getSession.js.map +1 -1
- package/dist/api/com/atproto/server/refreshSession.d.ts.map +1 -1
- package/dist/api/com/atproto/server/refreshSession.js +4 -2
- package/dist/api/com/atproto/server/refreshSession.js.map +1 -1
- package/dist/api/com/atproto/sync/getRepoStatus.d.ts.map +1 -1
- package/dist/api/com/atproto/sync/getRepoStatus.js +2 -1
- package/dist/api/com/atproto/sync/getRepoStatus.js.map +1 -1
- package/dist/api/com/atproto/sync/listRepos.js +2 -2
- package/dist/api/com/atproto/sync/listRepos.js.map +1 -1
- package/dist/api/proxy.d.ts.map +1 -1
- package/dist/api/proxy.js +15 -2
- package/dist/api/proxy.js.map +1 -1
- package/dist/auth-routes.d.ts +4 -0
- package/dist/auth-routes.d.ts.map +1 -0
- package/dist/auth-routes.js +24 -0
- package/dist/auth-routes.js.map +1 -0
- package/dist/auth-verifier.d.ts +32 -11
- package/dist/auth-verifier.d.ts.map +1 -1
- package/dist/auth-verifier.js +238 -79
- package/dist/auth-verifier.js.map +1 -1
- package/dist/config/config.d.ts +12 -0
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +45 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/env.d.ts +8 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +10 -0
- package/dist/config/env.js.map +1 -1
- package/dist/config/secrets.d.ts +1 -0
- package/dist/config/secrets.d.ts.map +1 -1
- package/dist/config/secrets.js +1 -0
- package/dist/config/secrets.js.map +1 -1
- package/dist/context.d.ts +6 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +71 -13
- package/dist/context.js.map +1 -1
- package/dist/db/cast.d.ts +15 -0
- package/dist/db/cast.d.ts.map +1 -0
- package/dist/db/cast.js +66 -0
- package/dist/db/cast.js.map +1 -0
- package/dist/db/db.d.ts +2 -2
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +9 -7
- package/dist/db/db.js.map +1 -1
- package/dist/db/index.d.ts +1 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -0
- package/dist/db/index.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +5 -0
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lexicon/index.d.ts +4 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +8 -0
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +51 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +51 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/feed/defs.d.ts +1 -0
- package/dist/lexicon/types/app/bsky/feed/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/feed/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/muteThread.d.ts +29 -0
- package/dist/lexicon/types/app/bsky/graph/muteThread.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/muteThread.js +3 -0
- package/dist/lexicon/types/app/bsky/graph/muteThread.js.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/unmuteThread.d.ts +29 -0
- package/dist/lexicon/types/app/bsky/graph/unmuteThread.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/unmuteThread.js +3 -0
- package/dist/lexicon/types/app/bsky/graph/unmuteThread.js.map +1 -0
- package/dist/logger.d.ts +13 -11
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +80 -64
- package/dist/logger.js.map +1 -1
- package/dist/oauth/detailed-account-store.d.ts +27 -0
- package/dist/oauth/detailed-account-store.d.ts.map +1 -0
- package/dist/oauth/detailed-account-store.js +76 -0
- package/dist/oauth/detailed-account-store.js.map +1 -0
- package/dist/oauth/provider.d.ts +16 -0
- package/dist/oauth/provider.d.ts.map +1 -0
- package/dist/oauth/provider.js +45 -0
- package/dist/oauth/provider.js.map +1 -0
- package/dist/pipethrough.d.ts.map +1 -1
- package/dist/pipethrough.js.map +1 -1
- package/dist/sequencer/events.d.ts +2 -2
- package/example.env +21 -3
- package/package.json +9 -7
- package/src/account-manager/db/migrations/004-oauth.ts +122 -0
- package/src/account-manager/db/migrations/index.ts +2 -0
- package/src/account-manager/db/schema/authorization-request.ts +26 -0
- package/src/account-manager/db/schema/device-account.ts +15 -0
- package/src/account-manager/db/schema/device.ts +18 -0
- package/src/account-manager/db/schema/index.ts +15 -0
- package/src/account-manager/db/schema/token.ts +34 -0
- package/src/account-manager/db/schema/used-refresh-token.ts +13 -0
- package/src/account-manager/helpers/account.ts +16 -21
- package/src/account-manager/helpers/authorization-request.ts +82 -0
- package/src/account-manager/helpers/device-account.ts +135 -0
- package/src/account-manager/helpers/device.ts +45 -0
- package/src/account-manager/helpers/token.ts +185 -0
- package/src/account-manager/helpers/used-refresh-token.ts +30 -0
- package/src/account-manager/index.ts +325 -20
- package/src/actor-store/preference/reader.ts +8 -2
- package/src/actor-store/preference/transactor.ts +10 -0
- package/src/actor-store/preference/util.ts +8 -0
- package/src/api/app/bsky/actor/getPreferences.ts +2 -9
- package/src/api/app/bsky/actor/putPreferences.ts +5 -1
- package/src/api/com/atproto/server/createSession.ts +8 -44
- package/src/api/com/atproto/server/deleteSession.ts +14 -20
- package/src/api/com/atproto/server/getSession.ts +7 -2
- package/src/api/com/atproto/server/refreshSession.ts +6 -2
- package/src/api/com/atproto/sync/getRepoStatus.ts +3 -1
- package/src/api/com/atproto/sync/listRepos.ts +1 -1
- package/src/api/proxy.ts +18 -2
- package/src/auth-routes.ts +27 -0
- package/src/auth-verifier.ts +312 -92
- package/src/config/config.ts +66 -0
- package/src/config/env.ts +24 -0
- package/src/config/secrets.ts +2 -0
- package/src/context.ts +80 -14
- package/src/db/cast.ts +59 -0
- package/src/db/db.ts +15 -12
- package/src/db/index.ts +1 -0
- package/src/error.ts +7 -0
- package/src/index.ts +2 -0
- package/src/lexicon/index.ts +24 -0
- package/src/lexicon/lexicons.ts +52 -0
- package/src/lexicon/types/app/bsky/feed/defs.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/muteThread.ts +38 -0
- package/src/lexicon/types/app/bsky/graph/unmuteThread.ts +38 -0
- package/src/logger.ts +83 -38
- package/src/oauth/detailed-account-store.ts +96 -0
- package/src/oauth/provider.ts +77 -0
- package/src/pipethrough.ts +3 -2
- package/tests/preferences.test.ts +67 -1
- package/tests/proxied/__snapshots__/feedgen.test.ts.snap +4 -1
- package/tests/proxied/__snapshots__/views.test.ts.snap +116 -38
package/src/config/config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import assert from 'node:assert'
|
|
3
3
|
import { DAY, HOUR, SECOND } from '@atproto/common'
|
|
4
|
+
import { Customization } from '@atproto/oauth-provider'
|
|
4
5
|
import { ServerEnvironment } from './env'
|
|
5
6
|
|
|
6
7
|
// off-config but still from env:
|
|
@@ -234,6 +235,54 @@ export const envToCfg = (env: ServerEnvironment): ServerConfig => {
|
|
|
234
235
|
|
|
235
236
|
const crawlersCfg: ServerConfig['crawlers'] = env.crawlers ?? []
|
|
236
237
|
|
|
238
|
+
const fetchCfg: ServerConfig['fetch'] = {
|
|
239
|
+
disableSsrfProtection: env.fetchDisableSsrfProtection ?? false,
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const oauthCfg: ServerConfig['oauth'] = entrywayCfg
|
|
243
|
+
? {
|
|
244
|
+
issuer: entrywayCfg.url,
|
|
245
|
+
provider: false,
|
|
246
|
+
}
|
|
247
|
+
: {
|
|
248
|
+
issuer: serviceCfg.publicUrl,
|
|
249
|
+
provider: {
|
|
250
|
+
customization: {
|
|
251
|
+
name: env.serviceName ?? 'Personal PDS',
|
|
252
|
+
logo: env.logoUrl,
|
|
253
|
+
colors: {
|
|
254
|
+
primary: env.primaryColor,
|
|
255
|
+
error: env.errorColor,
|
|
256
|
+
},
|
|
257
|
+
links: [
|
|
258
|
+
{
|
|
259
|
+
title: 'Home',
|
|
260
|
+
href: env.homeUrl,
|
|
261
|
+
rel: 'bookmark',
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
title: 'Terms of Service',
|
|
265
|
+
href: env.termsOfServiceUrl,
|
|
266
|
+
rel: 'terms-of-service',
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
title: 'Privacy Policy',
|
|
270
|
+
href: env.privacyPolicyUrl,
|
|
271
|
+
rel: 'privacy-policy',
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
title: 'Support',
|
|
275
|
+
href: env.supportUrl,
|
|
276
|
+
rel: 'help',
|
|
277
|
+
},
|
|
278
|
+
].filter(
|
|
279
|
+
(f): f is typeof f & { href: NonNullable<(typeof f)['href']> } =>
|
|
280
|
+
f.href != null,
|
|
281
|
+
),
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
}
|
|
285
|
+
|
|
237
286
|
return {
|
|
238
287
|
service: serviceCfg,
|
|
239
288
|
db: dbCfg,
|
|
@@ -251,6 +300,8 @@ export const envToCfg = (env: ServerEnvironment): ServerConfig => {
|
|
|
251
300
|
redis: redisCfg,
|
|
252
301
|
rateLimits: rateLimitsCfg,
|
|
253
302
|
crawlers: crawlersCfg,
|
|
303
|
+
fetch: fetchCfg,
|
|
304
|
+
oauth: oauthCfg,
|
|
254
305
|
}
|
|
255
306
|
}
|
|
256
307
|
|
|
@@ -271,6 +322,8 @@ export type ServerConfig = {
|
|
|
271
322
|
redis: RedisScratchConfig | null
|
|
272
323
|
rateLimits: RateLimitsConfig
|
|
273
324
|
crawlers: string[]
|
|
325
|
+
fetch: FetchConfig
|
|
326
|
+
oauth: OAuthConfig
|
|
274
327
|
}
|
|
275
328
|
|
|
276
329
|
export type ServiceConfig = {
|
|
@@ -337,6 +390,19 @@ export type EntrywayConfig = {
|
|
|
337
390
|
plcRotationKey: string
|
|
338
391
|
}
|
|
339
392
|
|
|
393
|
+
export type FetchConfig = {
|
|
394
|
+
disableSsrfProtection: boolean
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export type OAuthConfig = {
|
|
398
|
+
issuer: string
|
|
399
|
+
provider:
|
|
400
|
+
| false
|
|
401
|
+
| {
|
|
402
|
+
customization: Customization
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
340
406
|
export type InvitesConfig =
|
|
341
407
|
| {
|
|
342
408
|
required: true
|
package/src/config/env.ts
CHANGED
|
@@ -6,14 +6,22 @@ export const readEnv = (): ServerEnvironment => {
|
|
|
6
6
|
port: envInt('PDS_PORT'),
|
|
7
7
|
hostname: envStr('PDS_HOSTNAME'),
|
|
8
8
|
serviceDid: envStr('PDS_SERVICE_DID'),
|
|
9
|
+
serviceName: envStr('PDS_SERVICE_NAME'),
|
|
9
10
|
version: envStr('PDS_VERSION'),
|
|
11
|
+
homeUrl: envStr('PDS_HOME_URL'),
|
|
12
|
+
logoUrl: envStr('PDS_LOGO_URL'),
|
|
10
13
|
privacyPolicyUrl: envStr('PDS_PRIVACY_POLICY_URL'),
|
|
14
|
+
supportUrl: envStr('PDS_SUPPORT_URL'),
|
|
11
15
|
termsOfServiceUrl: envStr('PDS_TERMS_OF_SERVICE_URL'),
|
|
12
16
|
contactEmailAddress: envStr('PDS_CONTACT_EMAIL_ADDRESS'),
|
|
13
17
|
acceptingImports: envBool('PDS_ACCEPTING_REPO_IMPORTS'),
|
|
14
18
|
blobUploadLimit: envInt('PDS_BLOB_UPLOAD_LIMIT'),
|
|
15
19
|
devMode: envBool('PDS_DEV_MODE'),
|
|
16
20
|
|
|
21
|
+
// branding
|
|
22
|
+
primaryColor: envStr('PDS_PRIMARY_COLOR'),
|
|
23
|
+
errorColor: envStr('PDS_ERROR_COLOR'),
|
|
24
|
+
|
|
17
25
|
// database
|
|
18
26
|
dataDirectory: envStr('PDS_DATA_DIRECTORY'),
|
|
19
27
|
disableWalAutoCheckpoint: envBool('PDS_SQLITE_DISABLE_WAL_AUTO_CHECKPOINT'),
|
|
@@ -97,6 +105,7 @@ export const readEnv = (): ServerEnvironment => {
|
|
|
97
105
|
crawlers: envList('PDS_CRAWLERS'),
|
|
98
106
|
|
|
99
107
|
// secrets
|
|
108
|
+
dpopSecret: envStr('PDS_DPOP_SECRET'),
|
|
100
109
|
jwtSecret: envStr('PDS_JWT_SECRET'),
|
|
101
110
|
adminPassword: envStr('PDS_ADMIN_PASSWORD'),
|
|
102
111
|
|
|
@@ -106,6 +115,9 @@ export const readEnv = (): ServerEnvironment => {
|
|
|
106
115
|
plcRotationKeyK256PrivateKeyHex: envStr(
|
|
107
116
|
'PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX',
|
|
108
117
|
),
|
|
118
|
+
|
|
119
|
+
// fetch
|
|
120
|
+
fetchDisableSsrfProtection: envBool('PDS_DISABLE_SSRF_PROTECTION'),
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
123
|
|
|
@@ -114,14 +126,22 @@ export type ServerEnvironment = {
|
|
|
114
126
|
port?: number
|
|
115
127
|
hostname?: string
|
|
116
128
|
serviceDid?: string
|
|
129
|
+
serviceName?: string
|
|
117
130
|
version?: string
|
|
131
|
+
homeUrl?: string
|
|
132
|
+
logoUrl?: string
|
|
118
133
|
privacyPolicyUrl?: string
|
|
134
|
+
supportUrl?: string
|
|
119
135
|
termsOfServiceUrl?: string
|
|
120
136
|
contactEmailAddress?: string
|
|
121
137
|
acceptingImports?: boolean
|
|
122
138
|
blobUploadLimit?: number
|
|
123
139
|
devMode?: boolean
|
|
124
140
|
|
|
141
|
+
// branding
|
|
142
|
+
primaryColor?: string
|
|
143
|
+
errorColor?: string
|
|
144
|
+
|
|
125
145
|
// database
|
|
126
146
|
dataDirectory?: string
|
|
127
147
|
disableWalAutoCheckpoint?: boolean
|
|
@@ -203,10 +223,14 @@ export type ServerEnvironment = {
|
|
|
203
223
|
crawlers?: string[]
|
|
204
224
|
|
|
205
225
|
// secrets
|
|
226
|
+
dpopSecret?: string
|
|
206
227
|
jwtSecret?: string
|
|
207
228
|
adminPassword?: string
|
|
208
229
|
|
|
209
230
|
// keys
|
|
210
231
|
plcRotationKeyKmsKeyId?: string
|
|
211
232
|
plcRotationKeyK256PrivateKeyHex?: string
|
|
233
|
+
|
|
234
|
+
// fetch
|
|
235
|
+
fetchDisableSsrfProtection?: boolean
|
|
212
236
|
}
|
package/src/config/secrets.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const envToSecrets = (env: ServerEnvironment): ServerSecrets => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
return {
|
|
30
|
+
dpopSecret: env.dpopSecret,
|
|
30
31
|
jwtSecret: env.jwtSecret,
|
|
31
32
|
adminPassword: env.adminPassword,
|
|
32
33
|
plcRotationKey,
|
|
@@ -34,6 +35,7 @@ export const envToSecrets = (env: ServerEnvironment): ServerSecrets => {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export type ServerSecrets = {
|
|
38
|
+
dpopSecret?: string
|
|
37
39
|
jwtSecret: string
|
|
38
40
|
adminPassword: string
|
|
39
41
|
plcRotationKey: SigningKeyKms | SigningKeyMemory
|
package/src/context.ts
CHANGED
|
@@ -12,12 +12,21 @@ import {
|
|
|
12
12
|
RateLimiterOpts,
|
|
13
13
|
createServiceAuthHeaders,
|
|
14
14
|
} from '@atproto/xrpc-server'
|
|
15
|
+
import {
|
|
16
|
+
JoseKey,
|
|
17
|
+
Fetch,
|
|
18
|
+
safeFetchWrap,
|
|
19
|
+
OAuthVerifier,
|
|
20
|
+
} from '@atproto/oauth-provider'
|
|
21
|
+
|
|
15
22
|
import { ServerConfig, ServerSecrets } from './config'
|
|
23
|
+
import { PdsOAuthProvider } from './oauth/provider'
|
|
16
24
|
import {
|
|
17
25
|
AuthVerifier,
|
|
18
26
|
createPublicKeyObject,
|
|
19
27
|
createSecretKeyObject,
|
|
20
28
|
} from './auth-verifier'
|
|
29
|
+
import { fetchLogger } from './logger'
|
|
21
30
|
import { ServerMailer } from './mailer'
|
|
22
31
|
import { ModerationMailer } from './mailer/moderation'
|
|
23
32
|
import { BlobStore } from '@atproto/repo'
|
|
@@ -50,6 +59,8 @@ export type AppContextOptions = {
|
|
|
50
59
|
moderationAgent?: AtpAgent
|
|
51
60
|
reportingAgent?: AtpAgent
|
|
52
61
|
entrywayAgent?: AtpAgent
|
|
62
|
+
safeFetch: Fetch
|
|
63
|
+
authProvider?: PdsOAuthProvider
|
|
53
64
|
authVerifier: AuthVerifier
|
|
54
65
|
plcRotationKey: crypto.Keypair
|
|
55
66
|
cfg: ServerConfig
|
|
@@ -74,7 +85,9 @@ export class AppContext {
|
|
|
74
85
|
public moderationAgent: AtpAgent | undefined
|
|
75
86
|
public reportingAgent: AtpAgent | undefined
|
|
76
87
|
public entrywayAgent: AtpAgent | undefined
|
|
88
|
+
public safeFetch: Fetch
|
|
77
89
|
public authVerifier: AuthVerifier
|
|
90
|
+
public authProvider?: PdsOAuthProvider
|
|
78
91
|
public plcRotationKey: crypto.Keypair
|
|
79
92
|
public cfg: ServerConfig
|
|
80
93
|
|
|
@@ -97,7 +110,9 @@ export class AppContext {
|
|
|
97
110
|
this.moderationAgent = opts.moderationAgent
|
|
98
111
|
this.reportingAgent = opts.reportingAgent
|
|
99
112
|
this.entrywayAgent = opts.entrywayAgent
|
|
113
|
+
this.safeFetch = opts.safeFetch
|
|
100
114
|
this.authVerifier = opts.authVerifier
|
|
115
|
+
this.authProvider = opts.authProvider
|
|
101
116
|
this.plcRotationKey = opts.plcRotationKey
|
|
102
117
|
this.cfg = opts.cfg
|
|
103
118
|
}
|
|
@@ -206,7 +221,12 @@ export class AppContext {
|
|
|
206
221
|
: undefined
|
|
207
222
|
|
|
208
223
|
const jwtSecretKey = createSecretKeyObject(secrets.jwtSecret)
|
|
224
|
+
const jwtPublicKey = cfg.entryway
|
|
225
|
+
? createPublicKeyObject(cfg.entryway.jwtPublicKeyHex)
|
|
226
|
+
: null
|
|
227
|
+
|
|
209
228
|
const accountManager = new AccountManager(
|
|
229
|
+
backgroundQueue,
|
|
210
230
|
cfg.db.accountDbLoc,
|
|
211
231
|
jwtSecretKey,
|
|
212
232
|
cfg.service.did,
|
|
@@ -214,20 +234,6 @@ export class AppContext {
|
|
|
214
234
|
)
|
|
215
235
|
await accountManager.migrateOrThrow()
|
|
216
236
|
|
|
217
|
-
const jwtKey = cfg.entryway
|
|
218
|
-
? createPublicKeyObject(cfg.entryway.jwtPublicKeyHex)
|
|
219
|
-
: jwtSecretKey
|
|
220
|
-
|
|
221
|
-
const authVerifier = new AuthVerifier(accountManager, idResolver, {
|
|
222
|
-
jwtKey, // @TODO support multiple keys?
|
|
223
|
-
adminPass: secrets.adminPassword,
|
|
224
|
-
dids: {
|
|
225
|
-
pds: cfg.service.did,
|
|
226
|
-
entryway: cfg.entryway?.did,
|
|
227
|
-
modService: cfg.modService?.did,
|
|
228
|
-
},
|
|
229
|
-
})
|
|
230
|
-
|
|
231
237
|
const plcRotationKey =
|
|
232
238
|
secrets.plcRotationKey.provider === 'kms'
|
|
233
239
|
? await KmsKeypair.load({
|
|
@@ -250,6 +256,64 @@ export class AppContext {
|
|
|
250
256
|
appviewCdnUrlPattern: cfg.bskyAppView?.cdnUrlPattern,
|
|
251
257
|
})
|
|
252
258
|
|
|
259
|
+
// A fetch() function that protects against SSRF attacks, large responses &
|
|
260
|
+
// known bad domains. This function can safely be used to fetch user
|
|
261
|
+
// provided URLs (unless "disableSsrfProtection" is true, of course).
|
|
262
|
+
const safeFetch = safeFetchWrap({
|
|
263
|
+
allowHttp: cfg.fetch.disableSsrfProtection,
|
|
264
|
+
responseMaxSize: 512 * 1024, // 512kB
|
|
265
|
+
ssrfProtection: !cfg.fetch.disableSsrfProtection,
|
|
266
|
+
fetch: async (input, init) => {
|
|
267
|
+
const request = input instanceof Request ? input : null
|
|
268
|
+
const method = init?.method ?? request?.method ?? 'GET'
|
|
269
|
+
const uri = request?.url ?? String(input)
|
|
270
|
+
fetchLogger.debug({ method, uri }, 'fetch')
|
|
271
|
+
return globalThis.fetch(input, init)
|
|
272
|
+
},
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
const authProvider = cfg.oauth.provider
|
|
276
|
+
? new PdsOAuthProvider({
|
|
277
|
+
issuer: cfg.oauth.issuer,
|
|
278
|
+
keyset: [
|
|
279
|
+
// Note: OpenID compatibility would require an RS256 private key in this list
|
|
280
|
+
await JoseKey.fromKeyLike(jwtSecretKey, undefined, 'HS256'),
|
|
281
|
+
],
|
|
282
|
+
accountManager,
|
|
283
|
+
actorStore,
|
|
284
|
+
localViewer,
|
|
285
|
+
redis: redisScratch,
|
|
286
|
+
dpopSecret: secrets.dpopSecret,
|
|
287
|
+
customization: cfg.oauth.provider.customization,
|
|
288
|
+
safeFetch,
|
|
289
|
+
})
|
|
290
|
+
: undefined
|
|
291
|
+
|
|
292
|
+
const oauthVerifier: OAuthVerifier =
|
|
293
|
+
authProvider ?? // OAuthProvider extends OAuthVerifier
|
|
294
|
+
new OAuthVerifier({
|
|
295
|
+
issuer: cfg.oauth.issuer,
|
|
296
|
+
keyset: [await JoseKey.fromKeyLike(jwtPublicKey!, undefined, 'ES256K')],
|
|
297
|
+
dpopSecret: secrets.dpopSecret,
|
|
298
|
+
redis: redisScratch,
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
const authVerifier = new AuthVerifier(
|
|
302
|
+
accountManager,
|
|
303
|
+
idResolver,
|
|
304
|
+
oauthVerifier,
|
|
305
|
+
{
|
|
306
|
+
publicUrl: cfg.service.publicUrl,
|
|
307
|
+
jwtKey: jwtPublicKey ?? jwtSecretKey,
|
|
308
|
+
adminPass: secrets.adminPassword,
|
|
309
|
+
dids: {
|
|
310
|
+
pds: cfg.service.did,
|
|
311
|
+
entryway: cfg.entryway?.did,
|
|
312
|
+
modService: cfg.modService?.did,
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
)
|
|
316
|
+
|
|
253
317
|
return new AppContext({
|
|
254
318
|
actorStore,
|
|
255
319
|
blobstore,
|
|
@@ -269,7 +333,9 @@ export class AppContext {
|
|
|
269
333
|
moderationAgent,
|
|
270
334
|
reportingAgent,
|
|
271
335
|
entrywayAgent,
|
|
336
|
+
safeFetch,
|
|
272
337
|
authVerifier,
|
|
338
|
+
authProvider,
|
|
273
339
|
plcRotationKey,
|
|
274
340
|
cfg,
|
|
275
341
|
...(overrides ?? {}),
|
package/src/db/cast.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type DateISO = `${string}T${string}Z`
|
|
2
|
+
export const toDateISO = (date: Date): DateISO => date.toISOString() as DateISO
|
|
3
|
+
export const fromDateISO = (date: DateISO): Date => new Date(date)
|
|
4
|
+
|
|
5
|
+
export type Json = string
|
|
6
|
+
export const toJson = (obj: unknown): Json => {
|
|
7
|
+
const json = JSON.stringify(obj)
|
|
8
|
+
if (json === undefined) throw new TypeError('Input not JSONifyable')
|
|
9
|
+
return json as Json
|
|
10
|
+
}
|
|
11
|
+
export const fromJson = <T>(json: Json): T => {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(json) as T
|
|
14
|
+
} catch (cause) {
|
|
15
|
+
throw new TypeError('Database contains invalid JSON', { cause })
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type JsonArray = `[${string}]`
|
|
20
|
+
export const isJsonArray = (json: string): json is JsonArray =>
|
|
21
|
+
// Although the JSON in the DB should have been encoded using toJson,
|
|
22
|
+
// there should not be any leading or trailing whitespace. We will still trim
|
|
23
|
+
// the string to protect against any manual editing of the DB.
|
|
24
|
+
json.trimStart().startsWith('[') && json.trimEnd().endsWith(']')
|
|
25
|
+
export function assertJsonArray(json: string): asserts json is JsonArray {
|
|
26
|
+
if (!isJsonArray(json)) throw new TypeError('Not an Array')
|
|
27
|
+
}
|
|
28
|
+
export const toJsonArray = (obj: readonly unknown[]): JsonArray => {
|
|
29
|
+
const json = toJson(obj)
|
|
30
|
+
assertJsonArray(json)
|
|
31
|
+
return json as JsonArray
|
|
32
|
+
}
|
|
33
|
+
export const fromJsonArray = <T>(json: JsonArray): T[] => {
|
|
34
|
+
assertJsonArray(json)
|
|
35
|
+
return fromJson(json) as T[]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type JsonObject = `{${string}}`
|
|
39
|
+
const isJsonObject = (json: string): json is JsonObject =>
|
|
40
|
+
// Although the JSON in the DB should have been encoded using toJson,
|
|
41
|
+
// there should not be any leading or trailing whitespace. We will still trim
|
|
42
|
+
// the string to protect against any manual editing of the DB.
|
|
43
|
+
json.trimStart().startsWith('{') && json.trimEnd().endsWith('}')
|
|
44
|
+
function assertJsonObject(json: string): asserts json is JsonObject {
|
|
45
|
+
if (!isJsonObject(json)) throw new TypeError('Not an Object')
|
|
46
|
+
}
|
|
47
|
+
export const toJsonObject = (
|
|
48
|
+
obj: Readonly<Record<string, unknown>>,
|
|
49
|
+
): JsonObject => {
|
|
50
|
+
const json = toJson(obj)
|
|
51
|
+
assertJsonObject(json)
|
|
52
|
+
return json as JsonObject
|
|
53
|
+
}
|
|
54
|
+
export const fromJsonObject = <T extends Record<string, unknown>>(
|
|
55
|
+
json: JsonObject,
|
|
56
|
+
): T => {
|
|
57
|
+
assertJsonObject(json)
|
|
58
|
+
return fromJson(json) as T
|
|
59
|
+
}
|
package/src/db/db.ts
CHANGED
|
@@ -51,7 +51,7 @@ export class Database<Schema> {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
async transactionNoRetry<T>(
|
|
54
|
-
fn: (db: Database<Schema>) => Promise<T>,
|
|
54
|
+
fn: (db: Database<Schema>) => T | Promise<T>,
|
|
55
55
|
): Promise<T> {
|
|
56
56
|
this.assertNotTransaction()
|
|
57
57
|
const leakyTxPlugin = new LeakyTxPlugin()
|
|
@@ -60,22 +60,25 @@ export class Database<Schema> {
|
|
|
60
60
|
.transaction()
|
|
61
61
|
.execute(async (txn) => {
|
|
62
62
|
const dbTxn = new Database(txn)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
try {
|
|
64
|
+
const txRes = await fn(dbTxn)
|
|
65
|
+
leakyTxPlugin.endTx()
|
|
66
|
+
const hooks = dbTxn.commitHooks
|
|
67
|
+
return { hooks, txRes }
|
|
68
|
+
} catch (err) {
|
|
69
|
+
leakyTxPlugin.endTx()
|
|
70
|
+
// ensure that all in-flight queries are flushed & the connection is open
|
|
71
|
+
await txn.getExecutor().provideConnection(async () => {})
|
|
72
|
+
throw err
|
|
73
|
+
}
|
|
73
74
|
})
|
|
74
75
|
hooks.map((hook) => hook())
|
|
75
76
|
return txRes
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
async transaction<T>(
|
|
79
|
+
async transaction<T>(
|
|
80
|
+
fn: (db: Database<Schema>) => T | Promise<T>,
|
|
81
|
+
): Promise<T> {
|
|
79
82
|
return retrySqlite(() => this.transactionNoRetry(fn))
|
|
80
83
|
}
|
|
81
84
|
|
package/src/db/index.ts
CHANGED
package/src/error.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { XRPCError } from '@atproto/xrpc-server'
|
|
2
2
|
import { ErrorRequestHandler } from 'express'
|
|
3
3
|
import { httpLogger as log } from './logger'
|
|
4
|
+
import { OAuthError } from '@atproto/oauth-provider'
|
|
4
5
|
|
|
5
6
|
export const handler: ErrorRequestHandler = (err, _req, res, next) => {
|
|
6
7
|
log.error(err, 'unexpected internal server error')
|
|
7
8
|
if (res.headersSent) {
|
|
8
9
|
return next(err)
|
|
9
10
|
}
|
|
11
|
+
|
|
12
|
+
if (err instanceof OAuthError) {
|
|
13
|
+
res.status(err.status).json(err.toJSON())
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
const serverError = XRPCError.fromError(err)
|
|
11
18
|
res.status(serverError.type).json(serverError.payload)
|
|
12
19
|
}
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import events from 'events'
|
|
|
11
11
|
import { Options as XrpcServerOptions } from '@atproto/xrpc-server'
|
|
12
12
|
import { DAY, HOUR, MINUTE, SECOND } from '@atproto/common'
|
|
13
13
|
import API from './api'
|
|
14
|
+
import * as authRoutes from './auth-routes'
|
|
14
15
|
import * as basicRoutes from './basic-routes'
|
|
15
16
|
import * as wellKnown from './well-known'
|
|
16
17
|
import * as error from './error'
|
|
@@ -99,6 +100,7 @@ export class PDS {
|
|
|
99
100
|
|
|
100
101
|
server = API(server, ctx)
|
|
101
102
|
|
|
103
|
+
app.use(authRoutes.createRouter(ctx))
|
|
102
104
|
app.use(basicRoutes.createRouter(ctx))
|
|
103
105
|
app.use(wellKnown.createRouter(ctx))
|
|
104
106
|
app.use(server.xrpc.router)
|
package/src/lexicon/index.ts
CHANGED
|
@@ -120,8 +120,10 @@ import * as AppBskyGraphGetRelationships from './types/app/bsky/graph/getRelatio
|
|
|
120
120
|
import * as AppBskyGraphGetSuggestedFollowsByActor from './types/app/bsky/graph/getSuggestedFollowsByActor'
|
|
121
121
|
import * as AppBskyGraphMuteActor from './types/app/bsky/graph/muteActor'
|
|
122
122
|
import * as AppBskyGraphMuteActorList from './types/app/bsky/graph/muteActorList'
|
|
123
|
+
import * as AppBskyGraphMuteThread from './types/app/bsky/graph/muteThread'
|
|
123
124
|
import * as AppBskyGraphUnmuteActor from './types/app/bsky/graph/unmuteActor'
|
|
124
125
|
import * as AppBskyGraphUnmuteActorList from './types/app/bsky/graph/unmuteActorList'
|
|
126
|
+
import * as AppBskyGraphUnmuteThread from './types/app/bsky/graph/unmuteThread'
|
|
125
127
|
import * as AppBskyLabelerGetServices from './types/app/bsky/labeler/getServices'
|
|
126
128
|
import * as AppBskyNotificationGetUnreadCount from './types/app/bsky/notification/getUnreadCount'
|
|
127
129
|
import * as AppBskyNotificationListNotifications from './types/app/bsky/notification/listNotifications'
|
|
@@ -1604,6 +1606,17 @@ export class AppBskyGraphNS {
|
|
|
1604
1606
|
return this._server.xrpc.method(nsid, cfg)
|
|
1605
1607
|
}
|
|
1606
1608
|
|
|
1609
|
+
muteThread<AV extends AuthVerifier>(
|
|
1610
|
+
cfg: ConfigOf<
|
|
1611
|
+
AV,
|
|
1612
|
+
AppBskyGraphMuteThread.Handler<ExtractAuth<AV>>,
|
|
1613
|
+
AppBskyGraphMuteThread.HandlerReqCtx<ExtractAuth<AV>>
|
|
1614
|
+
>,
|
|
1615
|
+
) {
|
|
1616
|
+
const nsid = 'app.bsky.graph.muteThread' // @ts-ignore
|
|
1617
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1607
1620
|
unmuteActor<AV extends AuthVerifier>(
|
|
1608
1621
|
cfg: ConfigOf<
|
|
1609
1622
|
AV,
|
|
@@ -1625,6 +1638,17 @@ export class AppBskyGraphNS {
|
|
|
1625
1638
|
const nsid = 'app.bsky.graph.unmuteActorList' // @ts-ignore
|
|
1626
1639
|
return this._server.xrpc.method(nsid, cfg)
|
|
1627
1640
|
}
|
|
1641
|
+
|
|
1642
|
+
unmuteThread<AV extends AuthVerifier>(
|
|
1643
|
+
cfg: ConfigOf<
|
|
1644
|
+
AV,
|
|
1645
|
+
AppBskyGraphUnmuteThread.Handler<ExtractAuth<AV>>,
|
|
1646
|
+
AppBskyGraphUnmuteThread.HandlerReqCtx<ExtractAuth<AV>>
|
|
1647
|
+
>,
|
|
1648
|
+
) {
|
|
1649
|
+
const nsid = 'app.bsky.graph.unmuteThread' // @ts-ignore
|
|
1650
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
1651
|
+
}
|
|
1628
1652
|
}
|
|
1629
1653
|
|
|
1630
1654
|
export class AppBskyLabelerNS {
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -5102,6 +5102,9 @@ export const schemaDict = {
|
|
|
5102
5102
|
type: 'string',
|
|
5103
5103
|
format: 'at-uri',
|
|
5104
5104
|
},
|
|
5105
|
+
threadMuted: {
|
|
5106
|
+
type: 'boolean',
|
|
5107
|
+
},
|
|
5105
5108
|
replyDisabled: {
|
|
5106
5109
|
type: 'boolean',
|
|
5107
5110
|
},
|
|
@@ -7675,6 +7678,30 @@ export const schemaDict = {
|
|
|
7675
7678
|
},
|
|
7676
7679
|
},
|
|
7677
7680
|
},
|
|
7681
|
+
AppBskyGraphMuteThread: {
|
|
7682
|
+
lexicon: 1,
|
|
7683
|
+
id: 'app.bsky.graph.muteThread',
|
|
7684
|
+
defs: {
|
|
7685
|
+
main: {
|
|
7686
|
+
type: 'procedure',
|
|
7687
|
+
description:
|
|
7688
|
+
'Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. Requires auth.',
|
|
7689
|
+
input: {
|
|
7690
|
+
encoding: 'application/json',
|
|
7691
|
+
schema: {
|
|
7692
|
+
type: 'object',
|
|
7693
|
+
required: ['root'],
|
|
7694
|
+
properties: {
|
|
7695
|
+
root: {
|
|
7696
|
+
type: 'string',
|
|
7697
|
+
format: 'at-uri',
|
|
7698
|
+
},
|
|
7699
|
+
},
|
|
7700
|
+
},
|
|
7701
|
+
},
|
|
7702
|
+
},
|
|
7703
|
+
},
|
|
7704
|
+
},
|
|
7678
7705
|
AppBskyGraphUnmuteActor: {
|
|
7679
7706
|
lexicon: 1,
|
|
7680
7707
|
id: 'app.bsky.graph.unmuteActor',
|
|
@@ -7721,6 +7748,29 @@ export const schemaDict = {
|
|
|
7721
7748
|
},
|
|
7722
7749
|
},
|
|
7723
7750
|
},
|
|
7751
|
+
AppBskyGraphUnmuteThread: {
|
|
7752
|
+
lexicon: 1,
|
|
7753
|
+
id: 'app.bsky.graph.unmuteThread',
|
|
7754
|
+
defs: {
|
|
7755
|
+
main: {
|
|
7756
|
+
type: 'procedure',
|
|
7757
|
+
description: 'Unmutes the specified thread. Requires auth.',
|
|
7758
|
+
input: {
|
|
7759
|
+
encoding: 'application/json',
|
|
7760
|
+
schema: {
|
|
7761
|
+
type: 'object',
|
|
7762
|
+
required: ['root'],
|
|
7763
|
+
properties: {
|
|
7764
|
+
root: {
|
|
7765
|
+
type: 'string',
|
|
7766
|
+
format: 'at-uri',
|
|
7767
|
+
},
|
|
7768
|
+
},
|
|
7769
|
+
},
|
|
7770
|
+
},
|
|
7771
|
+
},
|
|
7772
|
+
},
|
|
7773
|
+
},
|
|
7724
7774
|
AppBskyLabelerDefs: {
|
|
7725
7775
|
lexicon: 1,
|
|
7726
7776
|
id: 'app.bsky.labeler.defs',
|
|
@@ -11105,8 +11155,10 @@ export const ids = {
|
|
|
11105
11155
|
AppBskyGraphListitem: 'app.bsky.graph.listitem',
|
|
11106
11156
|
AppBskyGraphMuteActor: 'app.bsky.graph.muteActor',
|
|
11107
11157
|
AppBskyGraphMuteActorList: 'app.bsky.graph.muteActorList',
|
|
11158
|
+
AppBskyGraphMuteThread: 'app.bsky.graph.muteThread',
|
|
11108
11159
|
AppBskyGraphUnmuteActor: 'app.bsky.graph.unmuteActor',
|
|
11109
11160
|
AppBskyGraphUnmuteActorList: 'app.bsky.graph.unmuteActorList',
|
|
11161
|
+
AppBskyGraphUnmuteThread: 'app.bsky.graph.unmuteThread',
|
|
11110
11162
|
AppBskyLabelerDefs: 'app.bsky.labeler.defs',
|
|
11111
11163
|
AppBskyLabelerGetServices: 'app.bsky.labeler.getServices',
|
|
11112
11164
|
AppBskyLabelerService: 'app.bsky.labeler.service',
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
|
|
11
|
+
export interface QueryParams {}
|
|
12
|
+
|
|
13
|
+
export interface InputSchema {
|
|
14
|
+
root: string
|
|
15
|
+
[k: string]: unknown
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface HandlerInput {
|
|
19
|
+
encoding: 'application/json'
|
|
20
|
+
body: InputSchema
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface HandlerError {
|
|
24
|
+
status: number
|
|
25
|
+
message?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type HandlerOutput = HandlerError | void
|
|
29
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
30
|
+
auth: HA
|
|
31
|
+
params: QueryParams
|
|
32
|
+
input: HandlerInput
|
|
33
|
+
req: express.Request
|
|
34
|
+
res: express.Response
|
|
35
|
+
}
|
|
36
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
37
|
+
ctx: HandlerReqCtx<HA>,
|
|
38
|
+
) => Promise<HandlerOutput> | HandlerOutput
|