@atproto/bsky 0.0.75 → 0.0.77
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 +18 -0
- package/dist/api/app/bsky/actor/getProfiles.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/getProfiles.js +9 -1
- package/dist/api/app/bsky/actor/getProfiles.js.map +1 -1
- package/dist/api/app/bsky/actor/searchActorsTypeahead.js +10 -2
- package/dist/api/app/bsky/actor/searchActorsTypeahead.js.map +1 -1
- package/dist/api/app/bsky/feed/getActorLikes.js +2 -2
- package/dist/api/app/bsky/feed/getActorLikes.js.map +1 -1
- package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getFeed.js +8 -1
- package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
- package/dist/api/app/bsky/feed/getLikes.js +6 -6
- package/dist/api/app/bsky/feed/getLikes.js.map +1 -1
- package/dist/api/app/bsky/feed/getPosts.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getPosts.js +12 -5
- package/dist/api/app/bsky/feed/getPosts.js.map +1 -1
- package/dist/api/app/bsky/feed/getQuotes.d.ts +4 -0
- package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -0
- package/dist/api/app/bsky/feed/getQuotes.js +67 -0
- package/dist/api/app/bsky/feed/getQuotes.js.map +1 -0
- package/dist/api/app/bsky/feed/getRepostedBy.js +6 -6
- package/dist/api/app/bsky/feed/getRepostedBy.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.js +4 -4
- package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
- package/dist/api/app/bsky/graph/getFollowers.js +8 -8
- package/dist/api/app/bsky/graph/getFollowers.js.map +1 -1
- package/dist/api/app/bsky/graph/getList.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getList.js +32 -2
- package/dist/api/app/bsky/graph/getList.js.map +1 -1
- package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
- package/dist/api/app/bsky/notification/listNotifications.js +29 -8
- package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +2 -0
- package/dist/api/index.js.map +1 -1
- package/dist/auth-verifier.d.ts +8 -3
- package/dist/auth-verifier.d.ts.map +1 -1
- package/dist/auth-verifier.js +43 -29
- package/dist/auth-verifier.js.map +1 -1
- package/dist/data-plane/server/db/database-schema.d.ts +4 -2
- package/dist/data-plane/server/db/database-schema.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.js +15 -0
- package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.js.map +1 -0
- package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.js +30 -0
- package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.js.map +1 -0
- package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.js +20 -0
- package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.js.map +1 -0
- package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.js +28 -0
- package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.js.map +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/index.js +5 -1
- package/dist/data-plane/server/db/migrations/index.js.map +1 -1
- package/dist/data-plane/server/db/tables/post-agg.d.ts +1 -0
- package/dist/data-plane/server/db/tables/post-agg.d.ts.map +1 -1
- package/dist/data-plane/server/db/tables/post-gate.d.ts +14 -0
- package/dist/data-plane/server/db/tables/post-gate.d.ts.map +1 -0
- package/dist/data-plane/server/db/tables/post-gate.js +4 -0
- package/dist/data-plane/server/db/tables/post-gate.js.map +1 -0
- package/dist/data-plane/server/db/tables/post.d.ts +3 -0
- package/dist/data-plane/server/db/tables/post.d.ts.map +1 -1
- package/dist/data-plane/server/db/tables/quote.d.ts +16 -0
- package/dist/data-plane/server/db/tables/quote.d.ts.map +1 -0
- package/dist/data-plane/server/db/tables/quote.js +4 -0
- package/dist/data-plane/server/db/tables/quote.js.map +1 -0
- package/dist/data-plane/server/indexing/index.d.ts +2 -0
- package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/index.js +6 -0
- package/dist/data-plane/server/indexing/index.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post-gate.d.ts +10 -0
- package/dist/data-plane/server/indexing/plugins/post-gate.d.ts.map +1 -0
- package/dist/data-plane/server/indexing/plugins/post-gate.js +101 -0
- package/dist/data-plane/server/indexing/plugins/post-gate.js.map +1 -0
- package/dist/data-plane/server/indexing/plugins/post.d.ts +2 -0
- package/dist/data-plane/server/indexing/plugins/post.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post.js +122 -15
- package/dist/data-plane/server/indexing/plugins/post.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/thread-gate.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/thread-gate.js +12 -0
- package/dist/data-plane/server/indexing/plugins/thread-gate.js.map +1 -1
- package/dist/data-plane/server/routes/index.d.ts.map +1 -1
- package/dist/data-plane/server/routes/index.js +2 -0
- package/dist/data-plane/server/routes/index.js.map +1 -1
- package/dist/data-plane/server/routes/interactions.d.ts.map +1 -1
- package/dist/data-plane/server/routes/interactions.js +2 -1
- package/dist/data-plane/server/routes/interactions.js.map +1 -1
- package/dist/data-plane/server/routes/quotes.d.ts +6 -0
- package/dist/data-plane/server/routes/quotes.d.ts.map +1 -0
- package/dist/data-plane/server/routes/quotes.js +27 -0
- package/dist/data-plane/server/routes/quotes.js.map +1 -0
- package/dist/data-plane/server/routes/records.d.ts.map +1 -1
- package/dist/data-plane/server/routes/records.js +11 -1
- package/dist/data-plane/server/routes/records.js.map +1 -1
- package/dist/data-plane/server/util.d.ts +6 -7
- package/dist/data-plane/server/util.d.ts.map +1 -1
- package/dist/data-plane/server/util.js +1 -9
- package/dist/data-plane/server/util.js.map +1 -1
- package/dist/hydration/feed.d.ts +10 -0
- package/dist/hydration/feed.d.ts.map +1 -1
- package/dist/hydration/feed.js +31 -7
- package/dist/hydration/feed.js.map +1 -1
- package/dist/hydration/hydrator.d.ts +5 -2
- package/dist/hydration/hydrator.d.ts.map +1 -1
- package/dist/hydration/hydrator.js +102 -38
- package/dist/hydration/hydrator.js.map +1 -1
- package/dist/hydration/util.d.ts +0 -1
- package/dist/hydration/util.d.ts.map +1 -1
- package/dist/hydration/util.js +1 -5
- package/dist/hydration/util.js.map +1 -1
- package/dist/lexicon/index.d.ts +2 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +4 -0
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +141 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +142 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/embed/record.d.ts +8 -1
- package/dist/lexicon/types/app/bsky/embed/record.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/embed/record.js +11 -1
- package/dist/lexicon/types/app/bsky/embed/record.js.map +1 -1
- package/dist/lexicon/types/app/bsky/feed/defs.d.ts +2 -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/feed/getQuotes.d.ts +44 -0
- package/dist/lexicon/types/app/bsky/feed/getQuotes.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/feed/getQuotes.js +3 -0
- package/dist/lexicon/types/app/bsky/feed/getQuotes.js.map +1 -0
- package/dist/lexicon/types/app/bsky/feed/postgate.d.ts +25 -0
- package/dist/lexicon/types/app/bsky/feed/postgate.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/feed/postgate.js +27 -0
- package/dist/lexicon/types/app/bsky/feed/postgate.js.map +1 -0
- package/dist/lexicon/types/app/bsky/feed/threadgate.d.ts +2 -0
- package/dist/lexicon/types/app/bsky/feed/threadgate.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/feed/threadgate.js.map +1 -1
- package/dist/proto/bsky_connect.d.ts +21 -1
- package/dist/proto/bsky_connect.d.ts.map +1 -1
- package/dist/proto/bsky_connect.js +20 -0
- package/dist/proto/bsky_connect.js.map +1 -1
- package/dist/proto/bsky_pb.d.ts +96 -0
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +306 -4
- package/dist/proto/bsky_pb.js.map +1 -1
- package/dist/util/uris.d.ts +12 -0
- package/dist/util/uris.d.ts.map +1 -0
- package/dist/util/uris.js +34 -0
- package/dist/util/uris.js.map +1 -0
- package/dist/views/index.d.ts +8 -2
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +83 -39
- package/dist/views/index.js.map +1 -1
- package/dist/views/types.d.ts +1 -1
- package/dist/views/types.d.ts.map +1 -1
- package/dist/views/types.js.map +1 -1
- package/dist/views/util.d.ts +11 -1
- package/dist/views/util.d.ts.map +1 -1
- package/dist/views/util.js +19 -8
- package/dist/views/util.js.map +1 -1
- package/package.json +6 -6
- package/proto/bsky.proto +33 -0
- package/src/api/app/bsky/actor/getProfiles.ts +10 -1
- package/src/api/app/bsky/actor/searchActorsTypeahead.ts +9 -4
- package/src/api/app/bsky/feed/getActorLikes.ts +1 -1
- package/src/api/app/bsky/feed/getFeed.ts +12 -1
- package/src/api/app/bsky/feed/getLikes.ts +1 -1
- package/src/api/app/bsky/feed/getPosts.ts +10 -2
- package/src/api/app/bsky/feed/getQuotes.ts +105 -0
- package/src/api/app/bsky/feed/getRepostedBy.ts +1 -1
- package/src/api/app/bsky/feed/searchPosts.ts +1 -1
- package/src/api/app/bsky/graph/getFollowers.ts +1 -1
- package/src/api/app/bsky/graph/getList.ts +47 -4
- package/src/api/app/bsky/notification/listNotifications.ts +32 -6
- package/src/api/index.ts +2 -0
- package/src/auth-verifier.ts +78 -51
- package/src/data-plane/server/db/database-schema.ts +7 -3
- package/src/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.ts +12 -0
- package/src/data-plane/server/db/migrations/20240723T220703655Z-quotes.ts +28 -0
- package/src/data-plane/server/db/migrations/20240801T193939827Z-post-gate.ts +17 -0
- package/src/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.ts +25 -0
- package/src/data-plane/server/db/migrations/index.ts +4 -0
- package/src/data-plane/server/db/tables/post-agg.ts +1 -0
- package/src/data-plane/server/db/tables/post-gate.ts +12 -0
- package/src/data-plane/server/db/tables/post.ts +3 -0
- package/src/data-plane/server/db/tables/quote.ts +15 -0
- package/src/data-plane/server/indexing/index.ts +7 -0
- package/src/data-plane/server/indexing/plugins/post-gate.ts +104 -0
- package/src/data-plane/server/indexing/plugins/post.ts +151 -16
- package/src/data-plane/server/indexing/plugins/thread-gate.ts +12 -0
- package/src/data-plane/server/routes/index.ts +2 -0
- package/src/data-plane/server/routes/interactions.ts +2 -1
- package/src/data-plane/server/routes/quotes.ts +32 -0
- package/src/data-plane/server/routes/records.ts +11 -1
- package/src/data-plane/server/util.ts +0 -8
- package/src/hydration/feed.ts +58 -12
- package/src/hydration/hydrator.ts +112 -24
- package/src/hydration/util.ts +0 -4
- package/src/lexicon/index.ts +12 -0
- package/src/lexicon/lexicons.ts +145 -0
- package/src/lexicon/types/app/bsky/embed/record.ts +19 -0
- package/src/lexicon/types/app/bsky/feed/defs.ts +2 -0
- package/src/lexicon/types/app/bsky/feed/getQuotes.ts +54 -0
- package/src/lexicon/types/app/bsky/feed/postgate.ts +47 -0
- package/src/lexicon/types/app/bsky/feed/threadgate.ts +2 -0
- package/src/proto/bsky_connect.ts +24 -0
- package/src/proto/bsky_pb.ts +289 -0
- package/src/util/uris.ts +31 -0
- package/src/views/index.ts +90 -35
- package/src/views/types.ts +1 -0
- package/src/views/util.ts +37 -7
- package/tests/__snapshots__/feed-generation.test.ts.snap +37 -0
- package/tests/admin/admin-auth.test.ts +15 -8
- package/tests/auth.test.ts +2 -1
- package/tests/data-plane/__snapshots__/indexing.test.ts.snap +18 -0
- package/tests/data-plane/handle-invalidation.test.ts +31 -5
- package/tests/data-plane/indexing.test.ts +139 -23
- package/tests/data-plane/thread-mutes.test.ts +41 -9
- package/tests/feed-generation.test.ts +150 -32
- package/tests/postgates.test.ts +186 -0
- package/tests/seed/feed-hidden-replies.ts +62 -0
- package/tests/seed/postgates.ts +56 -0
- package/tests/server.test.ts +1 -1
- package/tests/views/__snapshots__/author-feed.test.ts.snap +56 -0
- package/tests/views/__snapshots__/block-lists.test.ts.snap +6 -0
- package/tests/views/__snapshots__/blocks.test.ts.snap +10 -0
- package/tests/views/__snapshots__/list-feed.test.ts.snap +22 -0
- package/tests/views/__snapshots__/lists.test.ts.snap +145 -26
- package/tests/views/__snapshots__/mute-lists.test.ts.snap +8 -0
- package/tests/views/__snapshots__/mutes.test.ts.snap +6 -0
- package/tests/views/__snapshots__/posts.test.ts.snap +12 -0
- package/tests/views/__snapshots__/quotes.test.ts.snap +399 -0
- package/tests/views/__snapshots__/starter-packs.test.ts.snap +245 -4
- package/tests/views/__snapshots__/thread.test.ts.snap +50 -0
- package/tests/views/__snapshots__/timeline.test.ts.snap +170 -0
- package/tests/views/account-deactivation.test.ts +8 -2
- package/tests/views/actor-likes.test.ts +27 -6
- package/tests/views/actor-search.test.ts +5 -1
- package/tests/views/author-feed.test.ts +76 -21
- package/tests/views/block-lists.test.ts +201 -40
- package/tests/views/blocks.test.ts +245 -46
- package/tests/views/feed-hidden-replies.test.ts +246 -0
- package/tests/views/feed-view-post.test.ts +501 -0
- package/tests/views/follows.test.ts +133 -22
- package/tests/views/known-followers.test.ts +43 -7
- package/tests/views/labeler-service.test.ts +36 -6
- package/tests/views/likes.test.ts +8 -5
- package/tests/views/list-feed.test.ts +25 -4
- package/tests/views/lists.test.ts +73 -31
- package/tests/views/mute-lists.test.ts +101 -29
- package/tests/views/mutes.test.ts +77 -17
- package/tests/views/notifications.test.ts +141 -25
- package/tests/views/posts.test.ts +13 -2
- package/tests/views/profile.test.ts +37 -11
- package/tests/views/quotes.test.ts +105 -0
- package/tests/views/reposts.test.ts +31 -5
- package/tests/views/starter-packs.test.ts +83 -3
- package/tests/views/suggested-follows.test.ts +31 -5
- package/tests/views/suggestions.test.ts +37 -6
- package/tests/views/thread.test.ts +121 -20
- package/tests/views/threadgating.test.ts +128 -22
- package/tests/views/timeline.test.ts +67 -14
package/src/auth-verifier.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthRequiredError,
|
|
3
|
+
parseReqNsid,
|
|
3
4
|
verifyJwt as verifyServiceJwt,
|
|
4
5
|
} from '@atproto/xrpc-server'
|
|
5
6
|
import * as ui8 from 'uint8arrays'
|
|
@@ -17,6 +18,11 @@ type ReqCtx = {
|
|
|
17
18
|
req: express.Request
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
type StandardAuthOpts = {
|
|
22
|
+
skipAudCheck?: boolean
|
|
23
|
+
lxmCheck?: (method?: string) => boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
export enum RoleStatus {
|
|
21
27
|
Valid,
|
|
22
28
|
Invalid,
|
|
@@ -80,61 +86,55 @@ export class AuthVerifier {
|
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
// verifiers (arrow fns to preserve scope)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
standardOptionalParameterized =
|
|
90
|
+
(opts: StandardAuthOpts) =>
|
|
91
|
+
async (ctx: ReqCtx): Promise<StandardOutput | NullOutput> => {
|
|
92
|
+
// @TODO remove! basic auth + did supported just for testing.
|
|
93
|
+
if (isBasicToken(ctx.req)) {
|
|
94
|
+
const aud = this.ownDid
|
|
95
|
+
const iss = ctx.req.headers['appview-as-did']
|
|
96
|
+
if (typeof iss !== 'string' || !iss.startsWith('did:')) {
|
|
97
|
+
throw new AuthRequiredError('bad issuer')
|
|
98
|
+
}
|
|
99
|
+
if (!this.parseRoleCreds(ctx.req).admin) {
|
|
100
|
+
throw new AuthRequiredError('bad credentials')
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
credentials: { type: 'standard', iss, aud },
|
|
104
|
+
}
|
|
105
|
+
} else if (isBearerToken(ctx.req)) {
|
|
106
|
+
const { iss, aud } = await this.verifyServiceJwt(ctx, {
|
|
107
|
+
lxmCheck: opts.lxmCheck,
|
|
108
|
+
iss: null,
|
|
109
|
+
aud: null,
|
|
110
|
+
})
|
|
111
|
+
if (!opts.skipAudCheck && !this.standardAudienceDids.has(aud)) {
|
|
112
|
+
throw new AuthRequiredError(
|
|
113
|
+
'jwt audience does not match service did',
|
|
114
|
+
'BadJwtAudience',
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
credentials: {
|
|
119
|
+
type: 'standard',
|
|
120
|
+
iss,
|
|
121
|
+
aud,
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
return this.nullCreds()
|
|
97
126
|
}
|
|
98
127
|
}
|
|
99
|
-
const { iss, aud } = await this.verifyServiceJwt(ctx, {
|
|
100
|
-
aud: null,
|
|
101
|
-
iss: null,
|
|
102
|
-
})
|
|
103
|
-
if (!this.standardAudienceDids.has(aud)) {
|
|
104
|
-
throw new AuthRequiredError(
|
|
105
|
-
'jwt audience does not match service did',
|
|
106
|
-
'BadJwtAudience',
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
return {
|
|
110
|
-
credentials: {
|
|
111
|
-
type: 'standard',
|
|
112
|
-
iss,
|
|
113
|
-
aud,
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
128
|
|
|
118
|
-
standardOptional
|
|
119
|
-
|
|
120
|
-
): Promise<StandardOutput | NullOutput> => {
|
|
121
|
-
if (isBearerToken(ctx.req) || isBasicToken(ctx.req)) {
|
|
122
|
-
return this.standard(ctx)
|
|
123
|
-
}
|
|
124
|
-
return this.nullCreds()
|
|
125
|
-
}
|
|
129
|
+
standardOptional: (ctx: ReqCtx) => Promise<StandardOutput | NullOutput> =
|
|
130
|
+
this.standardOptionalParameterized({})
|
|
126
131
|
|
|
127
|
-
|
|
128
|
-
ctx
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return this.nullCreds()
|
|
132
|
+
standard = async (ctx: ReqCtx): Promise<StandardOutput> => {
|
|
133
|
+
const output = await this.standardOptional(ctx)
|
|
134
|
+
if (output.credentials.type === 'none') {
|
|
135
|
+
throw new AuthRequiredError(undefined, 'AuthMissing')
|
|
132
136
|
}
|
|
133
|
-
|
|
134
|
-
aud: null,
|
|
135
|
-
iss: null,
|
|
136
|
-
})
|
|
137
|
-
return { credentials: { type: 'standard', iss, aud } }
|
|
137
|
+
return output as StandardOutput
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
role = (ctx: ReqCtx): RoleOutput => {
|
|
@@ -215,7 +215,11 @@ export class AuthVerifier {
|
|
|
215
215
|
|
|
216
216
|
async verifyServiceJwt(
|
|
217
217
|
reqCtx: ReqCtx,
|
|
218
|
-
opts: {
|
|
218
|
+
opts: {
|
|
219
|
+
iss: string[] | null
|
|
220
|
+
aud: string | null
|
|
221
|
+
lxmCheck?: (method?: string) => boolean
|
|
222
|
+
},
|
|
219
223
|
) {
|
|
220
224
|
const getSigningKey = async (
|
|
221
225
|
iss: string,
|
|
@@ -243,17 +247,40 @@ export class AuthVerifier {
|
|
|
243
247
|
}
|
|
244
248
|
return didKey
|
|
245
249
|
}
|
|
250
|
+
const assertLxmCheck = () => {
|
|
251
|
+
const lxm = parseReqNsid(reqCtx.req)
|
|
252
|
+
if (
|
|
253
|
+
(opts.lxmCheck && !opts.lxmCheck(payload.lxm)) ||
|
|
254
|
+
(!opts.lxmCheck && payload.lxm !== lxm)
|
|
255
|
+
) {
|
|
256
|
+
throw new AuthRequiredError(
|
|
257
|
+
payload.lxm !== undefined
|
|
258
|
+
? `bad jwt lexicon method ("lxm"). must match: ${lxm}`
|
|
259
|
+
: `missing jwt lexicon method ("lxm"). must match: ${lxm}`,
|
|
260
|
+
'BadJwtLexiconMethod',
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
246
264
|
|
|
247
265
|
const jwtStr = bearerTokenFromReq(reqCtx.req)
|
|
248
266
|
if (!jwtStr) {
|
|
249
267
|
throw new AuthRequiredError('missing jwt', 'MissingJwt')
|
|
250
268
|
}
|
|
269
|
+
// if validating additional scopes, skip scope check in initial validation & follow up afterwards
|
|
251
270
|
const payload = await verifyServiceJwt(
|
|
252
271
|
jwtStr,
|
|
253
272
|
opts.aud,
|
|
254
273
|
null,
|
|
255
274
|
getSigningKey,
|
|
256
275
|
)
|
|
276
|
+
if (
|
|
277
|
+
!payload.iss.endsWith('#atproto_labeler') ||
|
|
278
|
+
payload.lxm !== undefined
|
|
279
|
+
) {
|
|
280
|
+
// @TODO currently permissive of labelers who dont set lxm yet.
|
|
281
|
+
// we'll allow ozone self-hosters to upgrade before removing this condition.
|
|
282
|
+
assertLxmCheck()
|
|
283
|
+
}
|
|
257
284
|
return { iss: payload.iss, aud: payload.aud }
|
|
258
285
|
}
|
|
259
286
|
|
|
@@ -6,7 +6,8 @@ import * as post from './tables/post'
|
|
|
6
6
|
import * as postEmbed from './tables/post-embed'
|
|
7
7
|
import * as postAgg from './tables/post-agg'
|
|
8
8
|
import * as repost from './tables/repost'
|
|
9
|
-
import * as
|
|
9
|
+
import * as threadgate from './tables/thread-gate'
|
|
10
|
+
import * as postgate from './tables/post-gate'
|
|
10
11
|
import * as feedItem from './tables/feed-item'
|
|
11
12
|
import * as follow from './tables/follow'
|
|
12
13
|
import * as like from './tables/like'
|
|
@@ -35,6 +36,7 @@ import * as taggedSuggestion from './tables/tagged-suggestion'
|
|
|
35
36
|
import * as blobTakedown from './tables/blob-takedown'
|
|
36
37
|
import * as labeler from './tables/labeler'
|
|
37
38
|
import * as starterPack from './tables/starter-pack'
|
|
39
|
+
import * as quote from './tables/quote'
|
|
38
40
|
|
|
39
41
|
export type DatabaseSchemaType = duplicateRecord.PartialDB &
|
|
40
42
|
profile.PartialDB &
|
|
@@ -43,7 +45,8 @@ export type DatabaseSchemaType = duplicateRecord.PartialDB &
|
|
|
43
45
|
postEmbed.PartialDB &
|
|
44
46
|
postAgg.PartialDB &
|
|
45
47
|
repost.PartialDB &
|
|
46
|
-
|
|
48
|
+
threadgate.PartialDB &
|
|
49
|
+
postgate.PartialDB &
|
|
47
50
|
feedItem.PartialDB &
|
|
48
51
|
follow.PartialDB &
|
|
49
52
|
like.PartialDB &
|
|
@@ -71,7 +74,8 @@ export type DatabaseSchemaType = duplicateRecord.PartialDB &
|
|
|
71
74
|
blobTakedown.PartialDB &
|
|
72
75
|
labeler.PartialDB &
|
|
73
76
|
starterPack.PartialDB &
|
|
74
|
-
taggedSuggestion.PartialDB
|
|
77
|
+
taggedSuggestion.PartialDB &
|
|
78
|
+
quote.PartialDB
|
|
75
79
|
|
|
76
80
|
export type DatabaseSchema = Kysely<DatabaseSchemaType>
|
|
77
81
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.alterTable('post_agg')
|
|
6
|
+
.addColumn('quoteCount', 'bigint', (col) => col.notNull().defaultTo(0))
|
|
7
|
+
.execute()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
11
|
+
await db.schema.alterTable('post_agg').dropColumn('quoteCount').execute()
|
|
12
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Kysely, sql } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable('quote')
|
|
6
|
+
.addColumn('uri', 'varchar', (col) => col.primaryKey())
|
|
7
|
+
.addColumn('cid', 'varchar', (col) => col.notNull())
|
|
8
|
+
.addColumn('subject', 'varchar', (col) => col.notNull())
|
|
9
|
+
.addColumn('subjectCid', 'varchar', (col) => col.notNull())
|
|
10
|
+
.addColumn('createdAt', 'varchar', (col) => col.notNull())
|
|
11
|
+
.addColumn('indexedAt', 'varchar', (col) => col.notNull())
|
|
12
|
+
.addColumn('sortAt', 'varchar', (col) =>
|
|
13
|
+
col
|
|
14
|
+
.generatedAlwaysAs(sql`least("createdAt", "indexedAt")`)
|
|
15
|
+
.stored()
|
|
16
|
+
.notNull(),
|
|
17
|
+
)
|
|
18
|
+
.execute()
|
|
19
|
+
await db.schema
|
|
20
|
+
.createIndex('quote_subject_cursor_idx')
|
|
21
|
+
.on('quote')
|
|
22
|
+
.columns(['subject', 'sortAt', 'cid'])
|
|
23
|
+
.execute()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
27
|
+
await db.schema.dropTable('quote').execute()
|
|
28
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable('post_gate')
|
|
6
|
+
.addColumn('uri', 'varchar', (col) => col.primaryKey())
|
|
7
|
+
.addColumn('cid', 'varchar', (col) => col.notNull())
|
|
8
|
+
.addColumn('creator', 'varchar', (col) => col.notNull())
|
|
9
|
+
.addColumn('postUri', 'varchar', (col) => col.notNull().unique())
|
|
10
|
+
.addColumn('createdAt', 'varchar', (col) => col.notNull())
|
|
11
|
+
.addColumn('indexedAt', 'varchar', (col) => col.notNull())
|
|
12
|
+
.execute()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
16
|
+
await db.schema.dropTable('post_gate').execute()
|
|
17
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.alterTable('post')
|
|
6
|
+
.addColumn('violatesEmbeddingRules', 'boolean')
|
|
7
|
+
.execute()
|
|
8
|
+
await db.schema
|
|
9
|
+
.alterTable('post')
|
|
10
|
+
.addColumn('hasThreadGate', 'boolean')
|
|
11
|
+
.execute()
|
|
12
|
+
await db.schema
|
|
13
|
+
.alterTable('post')
|
|
14
|
+
.addColumn('hasPostGate', 'boolean')
|
|
15
|
+
.execute()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
19
|
+
await db.schema
|
|
20
|
+
.alterTable('post')
|
|
21
|
+
.dropColumn('violatesEmbeddingRules')
|
|
22
|
+
.execute()
|
|
23
|
+
await db.schema.alterTable('post').dropColumn('hasThreadGate').execute()
|
|
24
|
+
await db.schema.alterTable('post').dropColumn('hasPostGate').execute()
|
|
25
|
+
}
|
|
@@ -38,3 +38,7 @@ export * as _20240530T170337073Z from './20240530T170337073Z-account-deactivatio
|
|
|
38
38
|
export * as _20240606T171229898Z from './20240606T171229898Z-thread-mutes'
|
|
39
39
|
export * as _20240606T222548219Z from './20240606T222548219Z-starter-packs'
|
|
40
40
|
export * as _20240719T203853939Z from './20240719T203853939Z-priority-notifs'
|
|
41
|
+
export * as _20240723T220700077Z from './20240723T220700077Z-quotes-post-aggs'
|
|
42
|
+
export * as _20240723T220703655Z from './20240723T220703655Z-quotes'
|
|
43
|
+
export * as _20240801T193939827Z from './20240801T193939827Z-post-gate'
|
|
44
|
+
export * as _20240808T224251220Z from './20240808T224251220Z-post-gate-flags'
|
|
@@ -15,6 +15,9 @@ export interface Post {
|
|
|
15
15
|
tags: string[] | null
|
|
16
16
|
invalidReplyRoot: boolean | null
|
|
17
17
|
violatesThreadGate: boolean | null
|
|
18
|
+
violatesEmbeddingRules: boolean | null
|
|
19
|
+
hasThreadGate: boolean | null
|
|
20
|
+
hasPostGate: boolean | null
|
|
18
21
|
createdAt: string
|
|
19
22
|
indexedAt: string
|
|
20
23
|
sortAt: GeneratedAlways<string>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { GeneratedAlways } from 'kysely'
|
|
2
|
+
|
|
3
|
+
const tableName = 'quote'
|
|
4
|
+
|
|
5
|
+
export interface Quote {
|
|
6
|
+
uri: string
|
|
7
|
+
cid: string
|
|
8
|
+
subject: string
|
|
9
|
+
subjectCid: string
|
|
10
|
+
createdAt: string
|
|
11
|
+
indexedAt: string
|
|
12
|
+
sortAt: GeneratedAlways<string>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type PartialDB = { [tableName]: Quote }
|
|
@@ -17,6 +17,7 @@ import { Database } from '../db'
|
|
|
17
17
|
import { Actor } from '../db/tables/actor'
|
|
18
18
|
import * as Post from './plugins/post'
|
|
19
19
|
import * as Threadgate from './plugins/thread-gate'
|
|
20
|
+
import * as Postgate from './plugins/post-gate'
|
|
20
21
|
import * as Like from './plugins/like'
|
|
21
22
|
import * as Repost from './plugins/repost'
|
|
22
23
|
import * as Follow from './plugins/follow'
|
|
@@ -38,6 +39,7 @@ export class IndexingService {
|
|
|
38
39
|
records: {
|
|
39
40
|
post: Post.PluginType
|
|
40
41
|
threadGate: Threadgate.PluginType
|
|
42
|
+
postGate: Postgate.PluginType
|
|
41
43
|
like: Like.PluginType
|
|
42
44
|
repost: Repost.PluginType
|
|
43
45
|
follow: Follow.PluginType
|
|
@@ -60,6 +62,7 @@ export class IndexingService {
|
|
|
60
62
|
this.records = {
|
|
61
63
|
post: Post.makePlugin(this.db, this.background),
|
|
62
64
|
threadGate: Threadgate.makePlugin(this.db, this.background),
|
|
65
|
+
postGate: Postgate.makePlugin(this.db, this.background),
|
|
63
66
|
like: Like.makePlugin(this.db, this.background),
|
|
64
67
|
repost: Repost.makePlugin(this.db, this.background),
|
|
65
68
|
follow: Follow.makePlugin(this.db, this.background),
|
|
@@ -365,6 +368,10 @@ export class IndexingService {
|
|
|
365
368
|
.deleteFrom('thread_gate')
|
|
366
369
|
.where('creator', '=', did)
|
|
367
370
|
.execute()
|
|
371
|
+
await this.db.db
|
|
372
|
+
.deleteFrom('post_gate')
|
|
373
|
+
.where('creator', '=', did)
|
|
374
|
+
.execute()
|
|
368
375
|
// notifications
|
|
369
376
|
await this.db.db
|
|
370
377
|
.deleteFrom('notification')
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AtUri, normalizeDatetimeAlways } from '@atproto/syntax'
|
|
2
|
+
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
4
|
+
import * as Postgate from '../../../../lexicon/types/app/bsky/feed/postgate'
|
|
5
|
+
import * as lex from '../../../../lexicon/lexicons'
|
|
6
|
+
import { DatabaseSchema, DatabaseSchemaType } from '../../db/database-schema'
|
|
7
|
+
import { Database } from '../../db'
|
|
8
|
+
import RecordProcessor from '../processor'
|
|
9
|
+
import { BackgroundQueue } from '../../background'
|
|
10
|
+
|
|
11
|
+
const lexId = lex.ids.AppBskyFeedPostgate
|
|
12
|
+
type IndexedGate = DatabaseSchemaType['post_gate']
|
|
13
|
+
|
|
14
|
+
const insertFn = async (
|
|
15
|
+
db: DatabaseSchema,
|
|
16
|
+
uri: AtUri,
|
|
17
|
+
cid: CID,
|
|
18
|
+
obj: Postgate.Record,
|
|
19
|
+
timestamp: string,
|
|
20
|
+
): Promise<IndexedGate | null> => {
|
|
21
|
+
const postUri = new AtUri(obj.post)
|
|
22
|
+
if (postUri.host !== uri.host || postUri.rkey !== uri.rkey) {
|
|
23
|
+
throw new InvalidRequestError(
|
|
24
|
+
'Creator and rkey of post gate does not match its post',
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
const inserted = await db
|
|
28
|
+
.insertInto('post_gate')
|
|
29
|
+
.values({
|
|
30
|
+
uri: uri.toString(),
|
|
31
|
+
cid: cid.toString(),
|
|
32
|
+
creator: uri.host,
|
|
33
|
+
postUri: obj.post,
|
|
34
|
+
createdAt: normalizeDatetimeAlways(obj.createdAt),
|
|
35
|
+
indexedAt: timestamp,
|
|
36
|
+
})
|
|
37
|
+
.onConflict((oc) => oc.doNothing())
|
|
38
|
+
.returningAll()
|
|
39
|
+
.executeTakeFirst()
|
|
40
|
+
await db
|
|
41
|
+
.updateTable('post')
|
|
42
|
+
.where('uri', '=', postUri.toString())
|
|
43
|
+
.set({ hasPostGate: true })
|
|
44
|
+
.executeTakeFirst()
|
|
45
|
+
return inserted || null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const findDuplicate = async (
|
|
49
|
+
db: DatabaseSchema,
|
|
50
|
+
_uri: AtUri,
|
|
51
|
+
obj: Postgate.Record,
|
|
52
|
+
): Promise<AtUri | null> => {
|
|
53
|
+
const found = await db
|
|
54
|
+
.selectFrom('post_gate')
|
|
55
|
+
.where('postUri', '=', obj.post)
|
|
56
|
+
.selectAll()
|
|
57
|
+
.executeTakeFirst()
|
|
58
|
+
return found ? new AtUri(found.uri) : null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const notifsForInsert = () => {
|
|
62
|
+
return []
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const deleteFn = async (
|
|
66
|
+
db: DatabaseSchema,
|
|
67
|
+
uri: AtUri,
|
|
68
|
+
): Promise<IndexedGate | null> => {
|
|
69
|
+
const deleted = await db
|
|
70
|
+
.deleteFrom('post_gate')
|
|
71
|
+
.where('uri', '=', uri.toString())
|
|
72
|
+
.returningAll()
|
|
73
|
+
.executeTakeFirst()
|
|
74
|
+
if (deleted) {
|
|
75
|
+
await db
|
|
76
|
+
.updateTable('post')
|
|
77
|
+
.where('uri', '=', deleted.postUri)
|
|
78
|
+
.set({ hasPostGate: false })
|
|
79
|
+
.executeTakeFirst()
|
|
80
|
+
}
|
|
81
|
+
return deleted || null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const notifsForDelete = () => {
|
|
85
|
+
return { notifs: [], toDelete: [] }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type PluginType = RecordProcessor<Postgate.Record, IndexedGate>
|
|
89
|
+
|
|
90
|
+
export const makePlugin = (
|
|
91
|
+
db: Database,
|
|
92
|
+
background: BackgroundQueue,
|
|
93
|
+
): PluginType => {
|
|
94
|
+
return new RecordProcessor(db, background, {
|
|
95
|
+
lexId,
|
|
96
|
+
insertFn,
|
|
97
|
+
findDuplicate,
|
|
98
|
+
deleteFn,
|
|
99
|
+
notifsForInsert,
|
|
100
|
+
notifsForDelete,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default makePlugin
|