Optional service config in pds distribution (#2211)
* make appview and mod services optional on pds * pds: allow configuring a reporting service optionally separate from an administrative mod service * tidy
This commit is contained in:
parent
4e0271bddf
commit
9f90203f20
packages/pds
src
api
app/bsky
actor
getPreferences.tsgetProfile.tsgetProfiles.tsgetSuggestions.tsputPreferences.tssearchActors.tssearchActorsTypeahead.ts
feed
getActorFeeds.tsgetActorLikes.tsgetAuthorFeed.tsgetFeed.tsgetFeedGenerator.tsgetFeedGenerators.tsgetLikes.tsgetListFeed.tsgetPostThread.tsgetPosts.tsgetRepostedBy.tsgetSuggestedFeeds.tsgetTimeline.tssearchPosts.ts
graph
getBlocks.tsgetFollowers.tsgetFollows.tsgetList.tsgetListBlocks.tsgetListMutes.tsgetLists.tsgetMutes.tsgetSuggestedFollowsByActor.tsmuteActor.tsmuteActorList.tsunmuteActor.tsunmuteActorList.ts
notification
unspecced
com/atproto
config
context.tstests/proxied
@ -3,6 +3,7 @@ import AppContext from '../../../../context'
|
||||
import { AuthScope } from '../../../../auth-verifier'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
if (!ctx.cfg.bskyAppView) return
|
||||
server.app.bsky.actor.getPreferences({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth }) => {
|
||||
|
@ -12,13 +12,15 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
const METHOD_NSID = 'app.bsky.actor.getProfile'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.actor.getProfile({
|
||||
auth: ctx.authVerifier.accessOrRole,
|
||||
handler: async ({ req, auth, params }) => {
|
||||
const requester =
|
||||
auth.credentials.type === 'access' ? auth.credentials.did : null
|
||||
const res = await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
requester ? await ctx.appviewAuthHeaders(requester) : authPassthru(req),
|
||||
|
@ -11,13 +11,15 @@ import {
|
||||
const METHOD_NSID = 'app.bsky.actor.getProfiles'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.actor.getProfiles({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
const res = await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.actor.getSuggestions({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.actor.getSuggestions',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -4,6 +4,7 @@ import AppContext from '../../../../context'
|
||||
import { AccountPreference } from '../../../../actor-store/preference/reader'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
if (!ctx.cfg.bskyAppView) return
|
||||
server.app.bsky.actor.putPreferences({
|
||||
auth: ctx.authVerifier.accessCheckTakedown,
|
||||
handler: async ({ auth, input }) => {
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.actor.searchActors({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.actor.searchActors',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.actor.searchActorsTypeahead({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.actor.searchActorsTypeahead',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getActorFeeds({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getActorFeeds',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -12,13 +12,15 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
const METHOD_NSID = 'app.bsky.feed.getActorLikes'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getActorLikes({
|
||||
auth: ctx.authVerifier.accessOrRole,
|
||||
handler: async ({ req, params, auth }) => {
|
||||
const requester =
|
||||
auth.credentials.type === 'access' ? auth.credentials.did : null
|
||||
const res = await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
requester ? await ctx.appviewAuthHeaders(requester) : authPassthru(req),
|
||||
|
@ -13,13 +13,15 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
const METHOD_NSID = 'app.bsky.feed.getAuthorFeed'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getAuthorFeed({
|
||||
auth: ctx.authVerifier.accessOrRole,
|
||||
handler: async ({ req, params, auth }) => {
|
||||
const requester =
|
||||
auth.credentials.type === 'access' ? auth.credentials.did : null
|
||||
const res = await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
requester ? await ctx.appviewAuthHeaders(requester) : authPassthru(req),
|
||||
|
@ -3,13 +3,16 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!appViewAgent || !bskyAppView) return
|
||||
server.app.bsky.feed.getFeed({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ req, params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
const { data: feed } =
|
||||
await ctx.appViewAgent.api.app.bsky.feed.getFeedGenerator(
|
||||
await appViewAgent.api.app.bsky.feed.getFeedGenerator(
|
||||
{ feed: params.feed },
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
)
|
||||
@ -21,7 +24,7 @@ export default function (server: Server, ctx: AppContext) {
|
||||
serviceAuthHeaders.headers['accept-language'] =
|
||||
req.headers['accept-language']
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getFeed',
|
||||
params,
|
||||
serviceAuthHeaders,
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getFeedGenerator({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getFeedGenerator',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getFeedGenerators({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getFeedGenerators',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getLikes({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getLikes',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getListFeed({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getListFeed',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import assert from 'node:assert'
|
||||
import { AtUri } from '@atproto/syntax'
|
||||
import { Headers, XRPCError } from '@atproto/xrpc'
|
||||
import { Server } from '../../../../lexicon'
|
||||
@ -26,6 +27,8 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
const METHOD_NSID = 'app.bsky.feed.getPostThread'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getPostThread({
|
||||
auth: ctx.authVerifier.accessOrRole,
|
||||
handler: async ({ req, params, auth }) => {
|
||||
@ -34,7 +37,7 @@ export default function (server: Server, ctx: AppContext) {
|
||||
|
||||
if (!requester) {
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
authPassthru(req),
|
||||
@ -43,7 +46,7 @@ export default function (server: Server, ctx: AppContext) {
|
||||
|
||||
try {
|
||||
const res = await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
@ -200,6 +203,7 @@ const readAfterWriteNotFound = async (
|
||||
const highestParent = getHighestParent(thread)
|
||||
if (highestParent) {
|
||||
try {
|
||||
assert(ctx.appViewAgent)
|
||||
const parentsRes = await ctx.appViewAgent.api.app.bsky.feed.getPostThread(
|
||||
{ uri: highestParent, parentHeight: params.parentHeight, depth: 0 },
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getPosts({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getPosts',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getRepostedBy({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getRepostedBy',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getSuggestedFeeds({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.getSuggestedFeeds',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -11,12 +11,14 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
const METHOD_NSID = 'app.bsky.feed.getTimeline'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.getTimeline({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
const res = await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
METHOD_NSID,
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.feed.searchPosts({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.feed.searchPosts',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getBlocks({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getBlocks',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -4,13 +4,15 @@ import { authPassthru } from '../../../proxy'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getFollowers({
|
||||
auth: ctx.authVerifier.accessOrRole,
|
||||
handler: async ({ req, params, auth }) => {
|
||||
const requester =
|
||||
auth.credentials.type === 'access' ? auth.credentials.did : null
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getFollowers',
|
||||
params,
|
||||
requester ? await ctx.appviewAuthHeaders(requester) : authPassthru(req),
|
||||
|
@ -4,13 +4,15 @@ import { authPassthru } from '../../../proxy'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getFollows({
|
||||
auth: ctx.authVerifier.accessOrRole,
|
||||
handler: async ({ req, params, auth }) => {
|
||||
const requester =
|
||||
auth.credentials.type === 'access' ? auth.credentials.did : null
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getFollows',
|
||||
params,
|
||||
requester ? await ctx.appviewAuthHeaders(requester) : authPassthru(req),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getList({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getList',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getListBlocks({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getListBlocks',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getListMutes({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getListMutes',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getLists({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getLists',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getMutes({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getMutes',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.graph.getSuggestedFollowsByActor({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.graph.getSuggestedFollowsByActor',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -2,12 +2,14 @@ import { Server } from '../../../../lexicon'
|
||||
import AppContext from '../../../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
if (!appViewAgent) return
|
||||
server.app.bsky.graph.muteActor({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, input }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
await ctx.appViewAgent.api.app.bsky.graph.muteActor(input.body, {
|
||||
await appViewAgent.api.app.bsky.graph.muteActor(input.body, {
|
||||
...(await ctx.appviewAuthHeaders(requester)),
|
||||
encoding: 'application/json',
|
||||
})
|
||||
|
@ -2,12 +2,14 @@ import { Server } from '../../../../lexicon'
|
||||
import AppContext from '../../../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
if (!appViewAgent) return
|
||||
server.app.bsky.graph.muteActorList({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, input }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
await ctx.appViewAgent.api.app.bsky.graph.muteActorList(input.body, {
|
||||
await appViewAgent.api.app.bsky.graph.muteActorList(input.body, {
|
||||
...(await ctx.appviewAuthHeaders(requester)),
|
||||
encoding: 'application/json',
|
||||
})
|
||||
|
@ -2,12 +2,14 @@ import { Server } from '../../../../lexicon'
|
||||
import AppContext from '../../../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
if (!appViewAgent) return
|
||||
server.app.bsky.graph.unmuteActor({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, input }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
await ctx.appViewAgent.api.app.bsky.graph.unmuteActor(input.body, {
|
||||
await appViewAgent.api.app.bsky.graph.unmuteActor(input.body, {
|
||||
...(await ctx.appviewAuthHeaders(requester)),
|
||||
encoding: 'application/json',
|
||||
})
|
||||
|
@ -2,12 +2,14 @@ import { Server } from '../../../../lexicon'
|
||||
import AppContext from '../../../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
if (!appViewAgent) return
|
||||
server.app.bsky.graph.unmuteActorList({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, input }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
await ctx.appViewAgent.api.app.bsky.graph.unmuteActorList(input.body, {
|
||||
await appViewAgent.api.app.bsky.graph.unmuteActorList(input.body, {
|
||||
...(await ctx.appviewAuthHeaders(requester)),
|
||||
encoding: 'application/json',
|
||||
})
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.notification.getUnreadCount({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.notification.getUnreadCount',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,12 +3,14 @@ import AppContext from '../../../../context'
|
||||
import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.notification.listNotifications({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ params, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.notification.listNotifications',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -6,6 +6,8 @@ import { AtpAgent } from '@atproto/api'
|
||||
import { getDidDoc } from '../util/resolver'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
if (!appViewAgent) return
|
||||
server.app.bsky.notification.registerPush({
|
||||
auth: ctx.authVerifier.accessDeactived,
|
||||
handler: async ({ auth, input }) => {
|
||||
@ -16,14 +18,11 @@ export default function (server: Server, ctx: AppContext) {
|
||||
|
||||
const authHeaders = await ctx.serviceAuthHeaders(did, serviceDid)
|
||||
|
||||
if (ctx.cfg.bskyAppView.did === serviceDid) {
|
||||
await ctx.appViewAgent.api.app.bsky.notification.registerPush(
|
||||
input.body,
|
||||
{
|
||||
...authHeaders,
|
||||
encoding: 'application/json',
|
||||
},
|
||||
)
|
||||
if (ctx.cfg.bskyAppView?.did === serviceDid) {
|
||||
await appViewAgent.api.app.bsky.notification.registerPush(input.body, {
|
||||
...authHeaders,
|
||||
encoding: 'application/json',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,14 @@ import { Server } from '../../../../lexicon'
|
||||
import AppContext from '../../../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { appViewAgent } = ctx
|
||||
if (!appViewAgent) return
|
||||
server.app.bsky.notification.updateSeen({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ input, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
|
||||
await ctx.appViewAgent.api.app.bsky.notification.updateSeen(input.body, {
|
||||
await appViewAgent.api.app.bsky.notification.updateSeen(input.body, {
|
||||
...(await ctx.appviewAuthHeaders(requester)),
|
||||
encoding: 'application/json',
|
||||
})
|
||||
|
@ -4,12 +4,14 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
// THIS IS A TEMPORARY UNSPECCED ROUTE
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.unspecced.getPopularFeedGenerators({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.unspecced.getPopularFeedGenerators',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -4,12 +4,14 @@ import { pipethrough } from '../../../../pipethrough'
|
||||
|
||||
// THIS IS A TEMPORARY UNSPECCED ROUTE
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { bskyAppView } = ctx.cfg
|
||||
if (!bskyAppView) return
|
||||
server.app.bsky.unspecced.getTaggedSuggestions({
|
||||
auth: ctx.authVerifier.access,
|
||||
handler: async ({ auth, params }) => {
|
||||
const requester = auth.credentials.did
|
||||
return pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
bskyAppView.url,
|
||||
'app.bsky.unspecced.getTaggedSuggestions',
|
||||
params,
|
||||
await ctx.appviewAuthHeaders(requester),
|
||||
|
@ -3,15 +3,16 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.createCommunicationTemplate({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, input }) => {
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.admin.createCommunicationTemplate(
|
||||
await moderationAgent.com.atproto.admin.createCommunicationTemplate(
|
||||
input.body,
|
||||
authPassthru(req, true),
|
||||
)
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: result,
|
||||
|
@ -3,10 +3,12 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.deleteCommunicationTemplate({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, input }) => {
|
||||
await ctx.moderationAgent.com.atproto.admin.deleteCommunicationTemplate(
|
||||
await moderationAgent.com.atproto.admin.deleteCommunicationTemplate(
|
||||
input.body,
|
||||
authPassthru(req, true),
|
||||
)
|
||||
|
@ -3,15 +3,16 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.emitModerationEvent({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, input }) => {
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.admin.emitModerationEvent(
|
||||
await moderationAgent.com.atproto.admin.emitModerationEvent(
|
||||
input.body,
|
||||
authPassthru(req, true),
|
||||
)
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: result,
|
||||
|
@ -3,11 +3,13 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.getModerationEvent({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, params }) => {
|
||||
const { data } =
|
||||
await ctx.moderationAgent.com.atproto.admin.getModerationEvent(
|
||||
await moderationAgent.com.atproto.admin.getModerationEvent(
|
||||
params,
|
||||
authPassthru(req),
|
||||
)
|
||||
|
@ -3,11 +3,13 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.getRecord({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, params }) => {
|
||||
const { data: recordDetailAppview } =
|
||||
await ctx.moderationAgent.com.atproto.admin.getRecord(
|
||||
await moderationAgent.com.atproto.admin.getRecord(
|
||||
params,
|
||||
authPassthru(req),
|
||||
)
|
||||
|
@ -3,10 +3,12 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.getRepo({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, params }) => {
|
||||
const res = await ctx.moderationAgent.com.atproto.admin.getRepo(
|
||||
const res = await moderationAgent.com.atproto.admin.getRepo(
|
||||
params,
|
||||
authPassthru(req),
|
||||
)
|
||||
|
@ -3,15 +3,16 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.listCommunicationTemplates({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req }) => {
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.admin.listCommunicationTemplates(
|
||||
await moderationAgent.com.atproto.admin.listCommunicationTemplates(
|
||||
{},
|
||||
authPassthru(req, true),
|
||||
)
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: result,
|
||||
|
@ -3,11 +3,13 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.queryModerationEvents({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, params }) => {
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.admin.queryModerationEvents(
|
||||
await moderationAgent.com.atproto.admin.queryModerationEvents(
|
||||
params,
|
||||
authPassthru(req),
|
||||
)
|
||||
|
@ -3,11 +3,13 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.queryModerationStatuses({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, params }) => {
|
||||
const { data } =
|
||||
await ctx.moderationAgent.com.atproto.admin.queryModerationStatuses(
|
||||
await moderationAgent.com.atproto.admin.queryModerationStatuses(
|
||||
params,
|
||||
authPassthru(req),
|
||||
)
|
||||
|
@ -3,11 +3,13 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.searchRepos({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, params }) => {
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.admin.searchRepos(
|
||||
await moderationAgent.com.atproto.admin.searchRepos(
|
||||
params,
|
||||
authPassthru(req),
|
||||
)
|
||||
|
@ -43,21 +43,25 @@ export default function (server: Server, ctx: AppContext) {
|
||||
{ content },
|
||||
{ subject, to: account.email },
|
||||
)
|
||||
await ctx.moderationAgent.api.com.atproto.admin.emitModerationEvent(
|
||||
{
|
||||
event: {
|
||||
$type: 'com.atproto.admin.defs#modEventEmail',
|
||||
subjectLine: subject,
|
||||
comment,
|
||||
|
||||
if (ctx.moderationAgent) {
|
||||
await ctx.moderationAgent.api.com.atproto.admin.emitModerationEvent(
|
||||
{
|
||||
event: {
|
||||
$type: 'com.atproto.admin.defs#modEventEmail',
|
||||
subjectLine: subject,
|
||||
comment,
|
||||
},
|
||||
subject: {
|
||||
$type: 'com.atproto.admin.defs#repoRef',
|
||||
did: recipientDid,
|
||||
},
|
||||
createdBy: senderDid,
|
||||
},
|
||||
subject: {
|
||||
$type: 'com.atproto.admin.defs#repoRef',
|
||||
did: recipientDid,
|
||||
},
|
||||
createdBy: senderDid,
|
||||
},
|
||||
{ ...authPassthru(req), encoding: 'application/json' },
|
||||
)
|
||||
{ ...authPassthru(req), encoding: 'application/json' },
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: { sent: true },
|
||||
|
@ -3,11 +3,13 @@ import AppContext from '../../../../context'
|
||||
import { authPassthru } from '../../../proxy'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
const { moderationAgent } = ctx
|
||||
if (!moderationAgent) return
|
||||
server.com.atproto.admin.updateCommunicationTemplate({
|
||||
auth: ctx.authVerifier.role,
|
||||
handler: async ({ req, input }) => {
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.admin.updateCommunicationTemplate(
|
||||
await moderationAgent.com.atproto.admin.updateCommunicationTemplate(
|
||||
input.body,
|
||||
authPassthru(req, true),
|
||||
)
|
||||
|
@ -33,7 +33,7 @@ export default function (server: Server, ctx: AppContext) {
|
||||
}
|
||||
|
||||
// this is not someone on our server, but we help with resolving anyway
|
||||
if (!did) {
|
||||
if (!did && ctx.appViewAgent) {
|
||||
did = await tryResolveFromAppView(ctx.appViewAgent, handle)
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,22 @@
|
||||
import { Server } from '../../../../lexicon'
|
||||
import AppContext from '../../../../context'
|
||||
import { InvalidRequestError } from '@atproto/xrpc-server'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.com.atproto.moderation.createReport({
|
||||
auth: ctx.authVerifier.accessCheckTakedown,
|
||||
handler: async ({ input, auth }) => {
|
||||
const requester = auth.credentials.did
|
||||
if (!ctx.reportingAgent) {
|
||||
throw new InvalidRequestError(
|
||||
'Your hosting service is not configured with a moderation provider. If this seems in error, reach out to your hosting provider.',
|
||||
)
|
||||
}
|
||||
const { data: result } =
|
||||
await ctx.moderationAgent.com.atproto.moderation.createReport(
|
||||
await ctx.reportingAgent.com.atproto.moderation.createReport(
|
||||
input.body,
|
||||
{
|
||||
...(await ctx.moderationAuthHeaders(requester)),
|
||||
...(await ctx.reportingAuthHeaders(requester)),
|
||||
encoding: 'application/json',
|
||||
},
|
||||
)
|
||||
|
@ -28,6 +28,10 @@ export default function (server: Server, ctx: AppContext) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx.cfg.bskyAppView) {
|
||||
throw new InvalidRequestError(`Could not locate record`)
|
||||
}
|
||||
|
||||
return await pipethrough(
|
||||
ctx.cfg.bskyAppView.url,
|
||||
'com.atproto.repo.getRecord',
|
||||
|
@ -97,7 +97,7 @@ export type AuthVerifierOpts = {
|
||||
dids: {
|
||||
pds: string
|
||||
entryway?: string
|
||||
admin: string
|
||||
admin?: string
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,6 +254,9 @@ export class AuthVerifier {
|
||||
}
|
||||
|
||||
adminService = async (reqCtx: ReqCtx): Promise<AdminServiceOutput> => {
|
||||
if (!this.dids.admin) {
|
||||
throw new AuthRequiredError('Untrusted issuer', 'UntrustedIss')
|
||||
}
|
||||
const payload = await this.verifyServiceJwt(reqCtx, {
|
||||
aud: this.dids.entryway ?? this.dids.pds,
|
||||
iss: [this.dids.admin],
|
||||
|
@ -168,19 +168,46 @@ export const envToCfg = (env: ServerEnvironment): ServerConfig => {
|
||||
repoBackfillLimitMs: env.repoBackfillLimitMs ?? DAY,
|
||||
}
|
||||
|
||||
assert(env.bskyAppViewUrl)
|
||||
assert(env.bskyAppViewDid)
|
||||
const bskyAppViewCfg: ServerConfig['bskyAppView'] = {
|
||||
url: env.bskyAppViewUrl,
|
||||
did: env.bskyAppViewDid,
|
||||
cdnUrlPattern: env.bskyAppViewCdnUrlPattern,
|
||||
let bskyAppViewCfg: ServerConfig['bskyAppView'] = null
|
||||
if (env.bskyAppViewUrl) {
|
||||
assert(
|
||||
env.bskyAppViewDid,
|
||||
'if bsky appview service url is configured, must configure its did as well.',
|
||||
)
|
||||
bskyAppViewCfg = {
|
||||
url: env.bskyAppViewUrl,
|
||||
did: env.bskyAppViewDid,
|
||||
cdnUrlPattern: env.bskyAppViewCdnUrlPattern,
|
||||
}
|
||||
}
|
||||
|
||||
assert(env.modServiceUrl)
|
||||
assert(env.modServiceDid)
|
||||
const modServiceCfg: ServerConfig['modService'] = {
|
||||
url: env.modServiceUrl,
|
||||
did: env.modServiceDid,
|
||||
let modServiceCfg: ServerConfig['modService'] = null
|
||||
if (env.modServiceUrl) {
|
||||
assert(
|
||||
env.modServiceDid,
|
||||
'if mod service url is configured, must configure its did as well.',
|
||||
)
|
||||
modServiceCfg = {
|
||||
url: env.modServiceUrl,
|
||||
did: env.modServiceDid,
|
||||
}
|
||||
}
|
||||
|
||||
let reportServiceCfg: ServerConfig['reportService'] = null
|
||||
if (env.reportServiceUrl) {
|
||||
assert(
|
||||
env.reportServiceDid,
|
||||
'if report service url is configured, must configure its did as well.',
|
||||
)
|
||||
reportServiceCfg = {
|
||||
url: env.reportServiceUrl,
|
||||
did: env.reportServiceDid,
|
||||
}
|
||||
}
|
||||
|
||||
// if there's a mod service, default report service into it
|
||||
if (modServiceCfg && !reportServiceCfg) {
|
||||
reportServiceCfg = modServiceCfg
|
||||
}
|
||||
|
||||
const redisCfg: ServerConfig['redis'] = env.redisScratchAddress
|
||||
@ -216,6 +243,7 @@ export const envToCfg = (env: ServerEnvironment): ServerConfig => {
|
||||
subscription: subscriptionCfg,
|
||||
bskyAppView: bskyAppViewCfg,
|
||||
modService: modServiceCfg,
|
||||
reportService: reportServiceCfg,
|
||||
redis: redisCfg,
|
||||
rateLimits: rateLimitsCfg,
|
||||
crawlers: crawlersCfg,
|
||||
@ -233,8 +261,9 @@ export type ServerConfig = {
|
||||
email: EmailConfig | null
|
||||
moderationEmail: EmailConfig | null
|
||||
subscription: SubscriptionConfig
|
||||
bskyAppView: BksyAppViewConfig
|
||||
modService: ModServiceConfig
|
||||
bskyAppView: BksyAppViewConfig | null
|
||||
modService: ModServiceConfig | null
|
||||
reportService: ReportServiceConfig | null
|
||||
redis: RedisScratchConfig | null
|
||||
rateLimits: RateLimitsConfig
|
||||
crawlers: string[]
|
||||
@ -344,3 +373,8 @@ export type ModServiceConfig = {
|
||||
url: string
|
||||
did: string
|
||||
}
|
||||
|
||||
export type ReportServiceConfig = {
|
||||
url: string
|
||||
did: string
|
||||
}
|
||||
|
@ -76,6 +76,10 @@ export const readEnv = (): ServerEnvironment => {
|
||||
modServiceUrl: envStr('PDS_MOD_SERVICE_URL'),
|
||||
modServiceDid: envStr('PDS_MOD_SERVICE_DID'),
|
||||
|
||||
// report service
|
||||
reportServiceUrl: envStr('PDS_REPORT_SERVICE_URL'),
|
||||
reportServiceDid: envStr('PDS_REPORT_SERVICE_DID'),
|
||||
|
||||
// rate limits
|
||||
rateLimitsEnabled: envBool('PDS_RATE_LIMITS_ENABLED'),
|
||||
rateLimitBypassKey: envStr('PDS_RATE_LIMIT_BYPASS_KEY'),
|
||||
@ -176,6 +180,10 @@ export type ServerEnvironment = {
|
||||
modServiceUrl?: string
|
||||
modServiceDid?: string
|
||||
|
||||
// report service
|
||||
reportServiceUrl?: string
|
||||
reportServiceDid?: string
|
||||
|
||||
// rate limits
|
||||
rateLimitsEnabled?: boolean
|
||||
rateLimitBypassKey?: string
|
||||
|
@ -1,3 +1,4 @@
|
||||
import assert from 'node:assert'
|
||||
import * as nodemailer from 'nodemailer'
|
||||
import { Redis } from 'ioredis'
|
||||
import * as plc from '@did-plc/lib'
|
||||
@ -42,8 +43,9 @@ export type AppContextOptions = {
|
||||
backgroundQueue: BackgroundQueue
|
||||
redisScratch?: Redis
|
||||
crawlers: Crawlers
|
||||
appViewAgent: AtpAgent
|
||||
moderationAgent: AtpAgent
|
||||
appViewAgent?: AtpAgent
|
||||
moderationAgent?: AtpAgent
|
||||
reportingAgent?: AtpAgent
|
||||
entrywayAgent?: AtpAgent
|
||||
authVerifier: AuthVerifier
|
||||
plcRotationKey: crypto.Keypair
|
||||
@ -67,8 +69,9 @@ export class AppContext {
|
||||
public backgroundQueue: BackgroundQueue
|
||||
public redisScratch?: Redis
|
||||
public crawlers: Crawlers
|
||||
public appViewAgent: AtpAgent
|
||||
public moderationAgent: AtpAgent
|
||||
public appViewAgent: AtpAgent | undefined
|
||||
public moderationAgent: AtpAgent | undefined
|
||||
public reportingAgent: AtpAgent | undefined
|
||||
public entrywayAgent: AtpAgent | undefined
|
||||
public authVerifier: AuthVerifier
|
||||
public plcRotationKey: crypto.Keypair
|
||||
@ -90,6 +93,7 @@ export class AppContext {
|
||||
this.crawlers = opts.crawlers
|
||||
this.appViewAgent = opts.appViewAgent
|
||||
this.moderationAgent = opts.moderationAgent
|
||||
this.reportingAgent = opts.reportingAgent
|
||||
this.entrywayAgent = opts.entrywayAgent
|
||||
this.authVerifier = opts.authVerifier
|
||||
this.plcRotationKey = opts.plcRotationKey
|
||||
@ -161,9 +165,15 @@ export class AppContext {
|
||||
? getRedisClient(cfg.redis.address, cfg.redis.password)
|
||||
: undefined
|
||||
|
||||
const appViewAgent = new AtpAgent({ service: cfg.bskyAppView.url })
|
||||
const moderationAgent = new AtpAgent({ service: cfg.modService.url })
|
||||
|
||||
const appViewAgent = cfg.bskyAppView
|
||||
? new AtpAgent({ service: cfg.bskyAppView.url })
|
||||
: undefined
|
||||
const moderationAgent = cfg.modService
|
||||
? new AtpAgent({ service: cfg.modService.url })
|
||||
: undefined
|
||||
const reportingAgent = cfg.reportService
|
||||
? new AtpAgent({ service: cfg.reportService.url })
|
||||
: undefined
|
||||
const entrywayAgent = cfg.entryway
|
||||
? new AtpAgent({ service: cfg.entryway.url })
|
||||
: undefined
|
||||
@ -189,7 +199,7 @@ export class AppContext {
|
||||
dids: {
|
||||
pds: cfg.service.did,
|
||||
entryway: cfg.entryway?.did,
|
||||
admin: cfg.modService.did,
|
||||
admin: cfg.modService?.did,
|
||||
},
|
||||
})
|
||||
|
||||
@ -211,8 +221,8 @@ export class AppContext {
|
||||
accountManager,
|
||||
appViewAgent,
|
||||
pdsHostname: cfg.service.hostname,
|
||||
appviewDid: cfg.bskyAppView.did,
|
||||
appviewCdnUrlPattern: cfg.bskyAppView.cdnUrlPattern,
|
||||
appviewDid: cfg.bskyAppView?.did,
|
||||
appviewCdnUrlPattern: cfg.bskyAppView?.cdnUrlPattern,
|
||||
})
|
||||
|
||||
return new AppContext({
|
||||
@ -231,6 +241,7 @@ export class AppContext {
|
||||
crawlers,
|
||||
appViewAgent,
|
||||
moderationAgent,
|
||||
reportingAgent,
|
||||
entrywayAgent,
|
||||
authVerifier,
|
||||
plcRotationKey,
|
||||
@ -240,13 +251,20 @@ export class AppContext {
|
||||
}
|
||||
|
||||
async appviewAuthHeaders(did: string) {
|
||||
assert(this.cfg.bskyAppView)
|
||||
return this.serviceAuthHeaders(did, this.cfg.bskyAppView.did)
|
||||
}
|
||||
|
||||
async moderationAuthHeaders(did: string) {
|
||||
assert(this.cfg.modService)
|
||||
return this.serviceAuthHeaders(did, this.cfg.modService.did)
|
||||
}
|
||||
|
||||
async reportingAuthHeaders(did: string) {
|
||||
assert(this.cfg.reportService)
|
||||
return this.serviceAuthHeaders(did, this.cfg.reportService.did)
|
||||
}
|
||||
|
||||
async serviceAuthHeaders(did: string, aud: string) {
|
||||
const keypair = await this.actorStore.keypair(did)
|
||||
return createServiceAuthHeaders({
|
||||
|
@ -1,4 +1,5 @@
|
||||
import util from 'util'
|
||||
import util from 'node:util'
|
||||
import assert from 'node:assert'
|
||||
import AtpAgent from '@atproto/api'
|
||||
import { TestNetwork, SeedClient, RecordRef } from '@atproto/dev-env'
|
||||
import basicSeed from '../seeds/basic'
|
||||
@ -43,6 +44,7 @@ describe('proxy read after write', () => {
|
||||
})
|
||||
|
||||
it('handles image formatting', async () => {
|
||||
assert(network.pds.ctx.cfg.bskyAppView)
|
||||
const blob = await sc.uploadFile(
|
||||
alice,
|
||||
'../dev-env/src/seed/img/key-landscape-small.jpg',
|
||||
@ -123,6 +125,7 @@ describe('proxy read after write', () => {
|
||||
})
|
||||
|
||||
it('handles read after write on threads with record embeds', async () => {
|
||||
assert(network.pds.ctx.cfg.bskyAppView)
|
||||
const img = await sc.uploadFile(
|
||||
alice,
|
||||
'../dev-env/src/seed/img/key-landscape-small.jpg',
|
||||
|
Loading…
x
Reference in New Issue
Block a user