Skip to content

Commit

Permalink
Disable pds appview routes (#1644)
Browse files Browse the repository at this point in the history
* wip

* remove all canProxyReadc

* finish cleanup

* clean up tests

* fix up tests

* fix api tests

* fix build

* fix compression test

* update image tests

* fix dev envs

* build branch

* fix service file

* re-enable getPopular

* format

* rm unused sharp code

* dont build branch
  • Loading branch information
dholms authored Sep 22, 2023
1 parent 86bbf08 commit 558981e
Show file tree
Hide file tree
Showing 131 changed files with 414 additions and 32,715 deletions.
19 changes: 15 additions & 4 deletions packages/api/tests/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ describe('agent', () => {

// put the agent through the auth flow
AtpAgent.configure({ fetch: tokenExpiredFetchHandler })
const res1 = await agent.api.app.bsky.feed.getTimeline()
const res1 = await createPost(agent)
AtpAgent.configure({ fetch: defaultFetchHandler })

expect(res1.success).toEqual(true)
Expand Down Expand Up @@ -267,9 +267,9 @@ describe('agent', () => {
// put the agent through the auth flow
AtpAgent.configure({ fetch: tokenExpiredFetchHandler })
const [res1, res2, res3] = await Promise.all([
agent.api.app.bsky.feed.getTimeline(),
agent.api.app.bsky.feed.getTimeline(),
agent.api.app.bsky.feed.getTimeline(),
createPost(agent),
createPost(agent),
createPost(agent),
])
AtpAgent.configure({ fetch: defaultFetchHandler })

Expand Down Expand Up @@ -462,3 +462,14 @@ describe('agent', () => {
})
})
})

const createPost = async (agent: AtpAgent) => {
return agent.api.com.atproto.repo.createRecord({
repo: agent.session?.did ?? '',
collection: 'app.bsky.feed.post',
record: {
text: 'hello there',
createdAt: new Date().toISOString(),
},
})
}
39 changes: 26 additions & 13 deletions packages/api/tests/bsky-agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ describe('agent', () => {
await close()
})

const getProfileDisplayName = async (
agent: BskyAgent,
): Promise<string | undefined> => {
try {
const res = await agent.api.app.bsky.actor.profile.get({
repo: agent.session?.did || '',
rkey: 'self',
})
return res.value.displayName ?? ''
} catch (err) {
return undefined
}
}

it('upsertProfile correctly creates and updates profiles.', async () => {
const agent = new BskyAgent({ service: server.url })

Expand All @@ -28,9 +42,8 @@ describe('agent', () => {
email: '[email protected]',
password: 'password',
})

const profile1 = await agent.getProfile({ actor: agent.session?.did || '' })
expect(profile1.data.displayName).toBeFalsy()
const displayName1 = await getProfileDisplayName(agent)
expect(displayName1).toBeFalsy()

await agent.upsertProfile((existing) => {
expect(existing).toBeFalsy()
Expand All @@ -39,8 +52,8 @@ describe('agent', () => {
}
})

const profile2 = await agent.getProfile({ actor: agent.session?.did || '' })
expect(profile2.data.displayName).toBe('Bob')
const displayName2 = await getProfileDisplayName(agent)
expect(displayName2).toBe('Bob')

await agent.upsertProfile((existing) => {
expect(existing).toBeTruthy()
Expand All @@ -49,8 +62,8 @@ describe('agent', () => {
}
})

const profile3 = await agent.getProfile({ actor: agent.session?.did || '' })
expect(profile3.data.displayName).toBe('BOB')
const displayName3 = await getProfileDisplayName(agent)
expect(displayName3).toBe('BOB')
})

it('upsertProfile correctly handles CAS failures.', async () => {
Expand All @@ -62,8 +75,8 @@ describe('agent', () => {
password: 'password',
})

const profile1 = await agent.getProfile({ actor: agent.session?.did || '' })
expect(profile1.data.displayName).toBeFalsy()
const displayName1 = await getProfileDisplayName(agent)
expect(displayName1).toBeFalsy()

let hasConflicted = false
let ranTwice = false
Expand All @@ -88,8 +101,8 @@ describe('agent', () => {
})
expect(ranTwice).toBe(true)

const profile2 = await agent.getProfile({ actor: agent.session?.did || '' })
expect(profile2.data.displayName).toBe('Bob')
const displayName2 = await getProfileDisplayName(agent)
expect(displayName2).toBe('Bob')
})

it('upsertProfile wont endlessly retry CAS failures.', async () => {
Expand All @@ -101,8 +114,8 @@ describe('agent', () => {
password: 'password',
})

const profile1 = await agent.getProfile({ actor: agent.session?.did || '' })
expect(profile1.data.displayName).toBeFalsy()
const displayName1 = await getProfileDisplayName(agent)
expect(displayName1).toBeFalsy()

const p = agent.upsertProfile(async (_existing) => {
await agent.com.atproto.repo.putRecord({
Expand Down
13 changes: 3 additions & 10 deletions packages/dev-env/src/pds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ export class TestPds {
appUrlPasswordReset: 'app://forgot-password',
emailNoReplyAddress: '[email protected]',
publicUrl: 'https://pds.public.url',
imgUriSalt: '9dd04221f5755bce5f55f47464c27e1e',
imgUriKey:
'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8',
dbPostgresUrl: cfg.dbPostgresUrl,
maxSubscriptionBuffer: 200,
repoBackfillLimitMs: 1000 * 60 * 60, // 1hr
Expand All @@ -67,7 +64,8 @@ export class TestPds {
labelerKeywords: { label_me: 'test-label', label_me_2: 'test-label-2' },
feedGenDid: 'did:example:feedGen',
dbTxLockNonce: await randomStr(32, 'base32'),
bskyAppViewProxy: !!cfg.bskyAppViewEndpoint,
bskyAppViewEndpoint: cfg.bskyAppViewEndpoint ?? 'http://fake_address',
bskyAppViewDid: cfg.bskyAppViewDid ?? 'did:example:fake',
bskyAppViewCdnUrlPattern: 'http://cdn.appview.com/%s/%s/%s',
...cfg,
})
Expand All @@ -82,11 +80,7 @@ export class TestPds {
: pds.Database.memory()
await db.migrateToLatestOrThrow()

if (
config.bskyAppViewEndpoint &&
config.bskyAppViewProxy &&
!cfg.enableInProcessAppView
) {
if (cfg.bskyAppViewEndpoint && !cfg.enableInProcessAppView) {
// Disable communication to app view within pds
MessageDispatcher.prototype.send = async () => {}
}
Expand All @@ -97,7 +91,6 @@ export class TestPds {
repoSigningKey,
plcRotationKey,
config,
algos: cfg.algos,
})

await server.start()
Expand Down
1 change: 0 additions & 1 deletion packages/dev-env/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export type PdsConfig = Partial<pds.ServerConfig> & {
plcUrl: string
migration?: string
enableInProcessAppView?: boolean
algos?: pds.MountedAlgos
enableLabelsCache?: boolean
}

Expand Down
3 changes: 1 addition & 2 deletions packages/pds/src/api/com/atproto/identity/resolveHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ export default function (server: Server, ctx: AppContext) {
}

// this is not someone on our server, but we help with resolving anyway

if (!did && ctx.canProxyRead()) {
if (!did) {
did = await tryResolveFromAppview(ctx.appviewAgent, handle)
}

Expand Down
34 changes: 14 additions & 20 deletions packages/pds/src/api/com/atproto/repo/getRecord.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AtUri } from '@atproto/syntax'
import { InvalidRequestError } from '@atproto/xrpc-server'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { InvalidRequestError } from '@atproto/xrpc-server'

export default function (server: Server, ctx: AppContext) {
server.com.atproto.repo.getRecord(async ({ params }) => {
Expand All @@ -14,29 +14,23 @@ export default function (server: Server, ctx: AppContext) {
const record = await ctx.services
.record(ctx.db)
.getRecord(uri, cid || null)
if (record) {
return {
encoding: 'application/json',
body: {
uri: record.uri,
cid: record.cid,
value: record.value,
},
}
if (!record) {
throw new InvalidRequestError(`Could not locate record: ${uri}`)
}
}

if (ctx.canProxyRead()) {
const res = await ctx.appviewAgent.api.com.atproto.repo.getRecord(params)
return {
encoding: 'application/json',
body: res.data,
body: {
uri: record.uri,
cid: record.cid,
value: record.value,
},
}
} else {
const uri = AtUri.make(did || repo, collection, rkey)
throw new InvalidRequestError(
`Could not locate record: ${uri.toString()}`,
)
}

const res = await ctx.appviewAgent.api.com.atproto.repo.getRecord(params)
return {
encoding: 'application/json',
body: res.data,
}
})
}
55 changes: 6 additions & 49 deletions packages/pds/src/app-view/api/app/bsky/actor/getProfile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { InvalidRequestError } from '@atproto/xrpc-server'
import { Server } from '../../../../../lexicon'
import { softDeleted } from '../../../../../db/util'
import AppContext from '../../../../../context'
import { authPassthru } from '../../../../../api/com/atproto/admin/util'
import { OutputSchema } from '../../../../../lexicon/types/app/bsky/actor/getProfile'
Expand All @@ -13,57 +11,16 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ req, auth, params }) => {
const requester =
auth.credentials.type === 'access' ? auth.credentials.did : null
if (ctx.canProxyRead()) {
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfile(
params,
requester
? await ctx.serviceAuthHeaders(requester)
: authPassthru(req),
)
if (res.data.did === requester) {
return await handleReadAfterWrite(
ctx,
requester,
res,
getProfileMunge,
)
}
return {
encoding: 'application/json',
body: res.data,
}
}

// As long as user has triage permission, we know that they are a moderator user and can see taken down profiles
const canViewTakendownProfile =
auth.credentials.type === 'role' && auth.credentials.triage
const { actor } = params
const { db, services } = ctx
const actorService = services.appView.actor(db)

const actorRes = await actorService.getActor(actor, true)

if (!actorRes) {
throw new InvalidRequestError('Profile not found')
}
if (!canViewTakendownProfile && softDeleted(actorRes)) {
throw new InvalidRequestError(
'Account has been taken down',
'AccountTakedown',
)
}
const profile = await actorService.views.profileDetailed(
actorRes,
requester,
{ includeSoftDeleted: canViewTakendownProfile },
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfile(
params,
requester ? await ctx.serviceAuthHeaders(requester) : authPassthru(req),
)
if (!profile) {
throw new InvalidRequestError('Profile not found')
if (res.data.did === requester) {
return await handleReadAfterWrite(ctx, requester, res, getProfileMunge)
}

return {
encoding: 'application/json',
body: profile,
body: res.data,
}
},
})
Expand Down
39 changes: 8 additions & 31 deletions packages/pds/src/app-view/api/app/bsky/actor/getProfiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,17 @@ export default function (server: Server, ctx: AppContext) {
auth: ctx.accessVerifier,
handler: async ({ auth, params }) => {
const requester = auth.credentials.did
if (ctx.canProxyRead()) {
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfiles(
params,
await ctx.serviceAuthHeaders(requester),
)
const hasSelf = res.data.profiles.some((prof) => prof.did === requester)
if (hasSelf) {
return await handleReadAfterWrite(
ctx,
requester,
res,
getProfilesMunge,
)
}
return {
encoding: 'application/json',
body: res.data,
}
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfiles(
params,
await ctx.serviceAuthHeaders(requester),
)
const hasSelf = res.data.profiles.some((prof) => prof.did === requester)
if (hasSelf) {
return await handleReadAfterWrite(ctx, requester, res, getProfilesMunge)
}

const { actors } = params
const { db, services } = ctx
const actorService = services.appView.actor(db)

const actorsRes = await actorService.getActors(actors)

return {
encoding: 'application/json',
body: {
profiles: await actorService.views.hydrateProfilesDetailed(
actorsRes,
requester,
),
},
body: res.data,
}
},
})
Expand Down
Loading

0 comments on commit 558981e

Please sign in to comment.