Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Allow dynamic labeler header through ozone #2442

Merged
merged 24 commits into from
May 22, 2024
Merged

Conversation

foysalit
Copy link
Contributor

This PR aims to allow moderators of an ozone instance plug in an external ozone service/moderation authority and view labels they have added to a given subject.

The current implementation only adds this to getRecord lexicon but lays out the ground work to easily enable this for other lexicons.

@bnewbold
Copy link
Collaborator

Cool!

Any thoughts on adding labels on repoView, to be symmetric with the addition to recordView? Both of the "ViewDetail" variants already have labels.

@foysalit foysalit requested a review from devinivy April 24, 2024 14:05
@@ -263,14 +263,26 @@ export class AtpAgent {
'atproto-proxy': this.proxyHeader,
}
}

const labelerHeaderName = 'atproto-accept-labelers'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pfrazee wanted to run these changes by you

Comment on lines 21 to 26
const labelers = ctx.reqLabelers(req)
const labelMap = await ctx.hydrator.label.getLabelsForSubjects(
[uri],
labelers,
)
const labels = Array.from(labelMap.get(uri)?.labels?.values() || [])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hydrating labels here in repo.getRecord is a little bit funky since it's quietly off-contract (and I don't think we'll want to add it to the contract). I believe we had plans for the appview to implement com.atproto.label.queryLabels to provide the labels on arbitrary subjects, which I think would speak to ozone's use case. Perhaps we could implement that now, I don't think it's going to be super big lift.

@bnewbold what do you think?

const labelMap = await ctx.hydrator.label.getLabelsForSubjects(
uriPatterns,
// If sources are provided, use them. Otherwise, use the labelers from the request header
sources
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this creates some kind of confusion because someone might pass different labelers through header and then pass different labelers through the source param and get results only for the source param.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always ignore the header values here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess my question is, should we? to me, it feels a bit nicer to be able to just send it via header and ignore source param entirely.

Copy link
Collaborator

@devinivy devinivy May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my view it's not really the purpose of the header, which is about looking at the content of the response and applying labels to it. This endpoint doesn't really serve any contents that can be labeled, so it's a little bit outside the purview of the header. As you pointed out, it may also cause confusion because there's a parameter dedicated to querying specific labelers, and it's not well-defined how that parameter and the header should interact with each other. By relying only on the dedicated parameter here, I think it makes the behavior pretty clear/predictable. @bnewbold @dholms any thoughts to add?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright we're no longer defaulting to labelers in header and throwing error if sources param is missing.

@@ -45,3 +46,52 @@ export function retryableHttp(err: unknown) {
const retryableHttpStatusCodes = new Set([
408, 425, 429, 500, 502, 503, 504, 522, 524,
])

export type ParsedLabelers = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is copied from bsky/src/utils

foysalit added 3 commits May 2, 2024 23:22
✅ Update pds snapshots

✅ Update ozone snapshots

✅ Update pds snapshots

✅ Update pds snapshots

✅ Update pds snapshots

✅ Update pds snapshots
@foysalit foysalit force-pushed the forward-labeler-in-ozone branch from 3b70ca1 to cac18fe Compare May 2, 2024 22:44
const ozoneKey = await Secp256k1Keypair.create({ exportable: true })
const ozoneDid = await createOzoneDid(network.plc.url, ozoneKey)
thirdPartyLabeler = await TestOzone.create({
port: ozone.port + Math.floor(Math.random() * 10) + 1,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the issue you were running into with ozone.port + 10 from before this change? My understanding is that it was trying to ensure the port was out of the range of ports assigned by dev-env. With this change, I'm not sure if the port assignment will be outside that range, you may end-up with overlap.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was causing tests to fail randomly but it may have been a separate issue, let me try reverting this to see what happens.

@foysalit foysalit requested a review from devinivy May 8, 2024 21:35
@@ -6,7 +6,7 @@ import { INVALID_HANDLE } from '@atproto/syntax'
export default function (server: Server, ctx: AppContext) {
server.com.atproto.admin.getAccountInfos({
auth: ctx.authVerifier.optionalStandardOrRole,
handler: async ({ params, auth }) => {
handler: async ({ params, auth, req }) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lingering changes here can probably be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good eye!

redact: new Set(),
},
)
const labels = uriPatterns.map((uri) => labelMap.getBySubject(uri)).flat()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even 👀

Suggested change
const labels = uriPatterns.map((uri) => labelMap.getBySubject(uri)).flat()
const labels = uriPatterns.flatMap((uri) => labelMap.getBySubject(uri))

labelers?: ParsedLabelers,
): Promise<Label[]> {
if (!labelers?.dids.length && !labelers?.redact.size) return []
const auth = await this.appviewAuth(labelers)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can omit auth from here now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep thanks 👍

Comment on lines 1 to 13
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { pipethrough } from '../../../../pipethrough'

export default function (server: Server, ctx: AppContext) {
server.com.atproto.label.queryLabels({
auth: ctx.authVerifier.accessCheckTakedown,
handler: async ({ req, auth }) => {
const requester = auth.credentials.did
return pipethrough(ctx, req, requester)
},
})
}
Copy link
Collaborator

@devinivy devinivy May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey good news, we actually don't need to add every new endpoint to the pds anymore 😆 Daniel covered this recently in #2425, so now the PDS will proxy any lexrpc endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep realized that when syncing main with mod-manager branch but forgot to adjust here. cleaned it up now!

@foysalit foysalit requested a review from devinivy May 15, 2024 17:08
Copy link
Collaborator

@devinivy devinivy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid! Before merge mind just adding a pnpm changeset for a patch version bump of the @atproto/api package?

@foysalit foysalit merged commit 1f560f0 into main May 22, 2024
10 checks passed
@foysalit foysalit deleted the forward-labeler-in-ozone branch May 22, 2024 15:55
@github-actions github-actions bot mentioned this pull request May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants