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

Can't process Accept activity after Follow when activity.actor doesn't exist #12720

Open
pfefferle opened this issue Dec 19, 2023 · 21 comments
Open
Labels
🐛Bug Unexpected behavior 🌌Federation The Federation/ActivityPub feature packages/backend Server side specific issue/PR

Comments

@pfefferle
Copy link

💡 Summary

I am the maintainer of the WordPress ActivityPub plugin: https://wordpress.org/plugins/activitypub/

I tried to follow my Blogs User Account and the process stucks "In progress". The Blog receives the Follow Request and also sends the Accept response and Misskey seem to be fine with the Accept:

[status_code] => 202
[protocol_version] => 1.1
[success] => 1
[redirects] => 0
[url] => https://misskey.io/inbox
[history] => Array()

When I try to refresh the profile I receive the following error:

Endpoint: federation/update-remote-user
Info: {"e":{"message":"Cannot perform update query because update values are not defined. Call \"qb.set(...)\" method to specify updated values.","code":"UpdateValuesMissingError","id":"636723f6-a119-4a1e-b824-346150f611bb"}}
Date: 2023-12-19T17:17:23.482Z

I already experimented with Misskey some 4 month ago without issues:

Screenshot 2023-12-19 at 19 48 38

The IDs I tried are:

🥰 Expected Behavior

It should be possible to follow a User on a WordPress Blog and to refresh the profile informations.

🤬 Actual Behavior

See summary.

📝 Steps to Reproduce

  1. Go to a misskey instance
  2. search for @[email protected]
  3. Press "Follow" button
  4. Try to refresh the profile

💻 Frontend Environment

* Model and OS of the device(s): Mac OS X
* Browser: Firefox
* Server URL: https://misskey.io/
* Misskey: v2023.11.1-io.5a

🛰 Backend Environment (for server admin)

* Installation Method or Hosting Service: misskey.io
* Misskey: v2023.11.1-io.5a
* Node:
* PostgreSQL:
* Redis:
* OS and Architecture:
@pfefferle pfefferle added the ⚠️bug? This might be a bug label Dec 19, 2023
@kakkokari-gtyih kakkokari-gtyih added packages/backend Server side specific issue/PR 🌌Federation The Federation/ActivityPub feature labels Dec 20, 2023
@saschanaz
Copy link
Member

Info: {"e":{"message":"Cannot perform update query because update values are not defined. Call "qb.set(...)" method to specify updated values.","code":"UpdateValuesMissingError","id":"636723f6-a119-4a1e-b824-346150f611bb"}}

That's definitely a TypeORM error 🤔

@saschanaz
Copy link
Member

The server side log says:

WARN 1 [queue inbox] failed(TypeError: Cannot read properties of undefined (reading 'id')) id=288775 attempts=1/8 age=12ms activity=https://notiz.blog/author/matthias-pfefferle/...

id is undefined? 🤔🤔🤔🤔

@pfefferle
Copy link
Author

pfefferle commented Dec 20, 2023

So the ID-URI needs to be publicly accessible even for an Accept?

@saschanaz
Copy link
Member

I'll have to dig more as I'm not very familiar with typeorm and the log doesn't say the line number, but the error should be from somewhere here or below:

// Update user
await this.usersRepository.update(exist.id, updates);
if (person.publicKey) {
await this.userPublickeysRepository.update({ userId: exist.id }, {
keyId: person.publicKey.id,
keyPem: person.publicKey.publicKeyPem,
});
}

Since the actor information is already fetched, the function just loads it from the local data, which should include the ID:

const exist = await this.fetchPerson(uri) as MiRemoteUser | null;
if (exist === null) return;

So the ID-URI needs to be publicly accessible even for an Accept?

Per the above I would say no. Maybe the initial fetch for the actor goes wrong?

@saschanaz
Copy link
Member

saschanaz commented Dec 20, 2023

The server side log says:

WARN 1 [queue inbox] failed(TypeError: Cannot read properties of undefined (reading 'id')) id=288775 attempts=1/8 age=12ms activity=https://notiz.blog/author/matthias-pfefferle/...

id is undefined? 🤔🤔🤔🤔

Hmm, that one actually seems more like a general JS error. Can exist be undefined, when the code checks only null? (== null is generally better IMO.) (Edit: no, it may have totally different error stack starting from InboxProcessorService.process.)

@saschanaz
Copy link
Member

saschanaz commented Dec 20, 2023

When I try to refresh the profile I receive the following error:

Endpoint: federation/update-remote-user
Info: {"e":{"message":"Cannot perform update query because update values are not defined. Call \"qb.set(...)\" method to specify updated values.","code":"UpdateValuesMissingError","id":"636723f6-a119-4a1e-b824-346150f611bb"}}
Date: 2023-12-19T17:17:23.482Z

For this part, how did you trigger that endpoint? It's an admin-only endpoint that is hidden by bbef2a9 (🤔 cc @syuilo), are you manually creating the API request?

Anyway, I did the manual request and got the stack:

  e: {
    message: 'Cannot perform update query because update values are not defined. Call "qb.set(...)" method to specify updated values.',
    code: 'UpdateValuesMissingError',
    stack: 'UpdateValuesMissingError: Cannot perform update query because update values are not defined. Call "qb.set(...)" method to specify updated values.\n' +
      '    at UpdateQueryBuilder.createUpdateExpression (C:\\Users\\Kagami\\Documents\\GitHub\\hitoriskey\\node_modules\\.pnpm\\[email protected][email protected][email protected]\\node_modules\\typeorm\\query-builder\\UpdateQueryBuilder.js:430:19)\n' +
      '    at UpdateQueryBuilder.getQuery (C:\\Users\\Kagami\\Documents\\GitHub\\hitoriskey\\node_modules\\.pnpm\\[email protected][email protected][email protected]\\node_modules\\typeorm\\query-builder\\UpdateQueryBuilder.js:34:21)\n' +
      '    at UpdateQueryBuilder.getQueryAndParameters (C:\\Users\\Kagami\\Documents\\GitHub\\hitoriskey\\node_modules\\.pnpm\\[email protected][email protected][email protected]\\node_modules\\typeorm\\query-builder\\QueryBuilder.js:274:28)\n' +
      '    at UpdateQueryBuilder.execute (C:\\Users\\Kagami\\Documents\\GitHub\\hitoriskey\\node_modules\\.pnpm\\[email protected][email protected][email protected]\\node_modules\\typeorm\\query-builder\\UpdateQueryBuilder.js:81:50)\n' +
      '    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n' +
      '    at async ApPersonService.updatePerson (file:///C:/Users/Kagami/Documents/GitHub/hitoriskey/packages/backend/built/core/activitypub/models/ApPersonService.js:412:9)\n' +
      '    at async file:///C:/Users/Kagami/Documents/GitHub/hitoriskey/packages/backend/built/server/api/endpoints/federation/update-remote-user.js:41:13\n' +
      '    at async ApiCallService.call (file:///C:/Users/Kagami/Documents/GitHub/hitoriskey/packages/backend/built/server/api/ApiCallService.js:316:16)',
    id: '52ae54be-ed51-45f8-a18c-71bbe31534fa'
  }

... which points to:

// 該当ユーザーが既にフォロワーになっていた場合はFollowingもアップデートする
await this.followingsRepository.update(
{ followerId: exist.id },
{ followerSharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox },
);

@saschanaz
Copy link
Member

saschanaz commented Dec 20, 2023

curl -H 'Accept: application/activity+json' https://notiz.blog/author/matthias-pfefferle/ gives no sharedInbox indeed, which seems the cause for the update-remote-user endpoint at least. (Should it be required though? 🤔)

@saschanaz
Copy link
Member

https://w3c.github.io/activitypub/#actor-objects

sharedInbox
An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. sharedInbox endpoints SHOULD also be publicly readable OrderedCollection objects containing objects addressed to the Public special collection. Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint.

So it should be optional.

@saschanaz
Copy link
Member

saschanaz commented Dec 20, 2023

With #12727 I get:

WARN 1  [queue inbox]   failed(TypeError: Cannot read properties of undefined (reading 'id')
    at getApId (file:///misskey/packages/backend/built/core/activitypub/type.js:23:22)
    at ApDbResolverService.parseUri (file:///misskey/packages/backend/built/core/activitypub/ApDbResolverService.js:46:29)
    at ApDbResolverService.getUserFromApId (file:///misskey/packages/backend/built/core/activitypub/ApDbResolverService.js:77:29)
    at ApInboxService.acceptFollow (file:///misskey/packages/backend/built/core/activitypub/ApInboxService.js:202:57)
    at ApInboxService.accept (file:///misskey/packages/backend/built/core/activitypub/ApInboxService.js:197:49)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async ApInboxService.performOneActivity (file:///misskey/packages/backend/built/core/activitypub/ApInboxService.js:141:13)
    at async ApInboxService.performActivity (file:///misskey/packages/backend/built/core/activitypub/ApInboxService.js:119:13)
    at async InboxProcessorService.process (file:///misskey/packages/backend/built/queue/processors/InboxProcessorService.js:167:9)
    at async Worker.processJob (/misskey/node_modules/.pnpm/[email protected]/node_modules/bullmq/dist/cjs/classes/worker.js:350:28)
    at async Worker.retryIfFailed (/misskey/node_modules/.pnpm/[email protected]/node_modules/bullmq/dist/cjs/classes/worker.js:535:24)) id=289285 attempts=1/8 age=12ms activity=https://notiz.blog/author/matthias-pfefferle/#follow-sekai.social/users/9ke0mh0ps3ln0008-1703112007

Which is:

@bindThis
private async acceptFollow(actor: MiRemoteUser, activity: IFollow): Promise<string> {
// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
const follower = await this.apDbResolverService.getUserFromApId(activity.actor);

Somehow activity.actor is undefined?

@pfefferle
Copy link
Author

pfefferle commented Dec 21, 2023

For this part, how did you trigger that endpoint?

I used the "Update remote user information" feature.

Screenshot 2023-12-21 at 10 50 14

And the error stack was part of the response message.

Screenshot 2023-12-21 at 10 57 32

(sharedInbox) So it should be optional.

Yes it is optional and even if it makes sense for bigger instances with a lot of users, it does not make sense for small WordPress instances with only some few users.

@pfefferle
Copy link
Author

pfefferle commented Dec 21, 2023

I experimented with a shared inbox and then I can at least run "Update remote user information" without issues, but following is still a problem.

I use the same URL for the Actor-ID and Actor-URL, could that be an issue for Misskey?

This is my other blog with the sharedInbox enabled if you need a test instance:

@saschanaz
Copy link
Member

I think the following and update-remote thing is technically separate issues, but we'll see...

@saschanaz
Copy link
Member

I use the same URL for the Actor-ID and Actor-URL, could that be an issue for Misskey?

That should be okay IMO. Can you check how the data look like for the Accept activity? Does it have actor field? I don't think this is required per the spec, though.

@pfefferle
Copy link
Author

Here is an Accept example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
      "PropertyValue": "schema:PropertyValue",
      "schema": "http://schema.org#",
      "pt": "https://joinpeertube.org/ns#",
      "toot": "http://joinmastodon.org/ns#",
      "webfinger": "https://webfinger.net/#",
      "litepub": "http://litepub.social/ns#",
      "lemmy": "https://join-lemmy.org/ns#",
      "value": "schema:value",
      "Hashtag": "as:Hashtag",
      "featured": {
        "@id": "toot:featured",
        "@type": "@id"
      },
      "featuredTags": {
        "@id": "toot:featuredTags",
        "@type": "@id"
      },
      "alsoKnownAs": {
        "@id": "as:alsoKnownAs",
        "@type": "@id"
      },
      "moderators": {
        "@id": "lemmy:moderators",
        "@type": "@id"
      },
      "postingRestrictedToMods": "lemmy:postingRestrictedToMods",
      "discoverable": "toot:discoverable",
      "indexable": "toot:indexable",
      "sensitive": "as:sensitive",
      "resource": "webfinger:resource"
    }
  ],
  "id": "https://pfefferle.org/author/pfefferle/#follow/1703174869",
  "type": "Accept",
  "object": {
    "id": "https://misskey.io/follows/9niynkoa4zjm0021",
    "type": "Follow"
  },
  "actor": "https://pfefferle.org/author/pfefferle/",
  "to": "https://misskey.io/users/7xgdnovq9y"
}

@pfefferle
Copy link
Author

oh, it seems to miss the actor in the object... will check why this!

@saschanaz
Copy link
Member

Technically Misskey should be able to infer the actor from the id https://misskey.io/follows/9niynkoa4zjm0021, but it seems the implementation totally ignores it as acceptFollow doesn't use it at all. 👀

@pfefferle
Copy link
Author

@saschanaz You saved my day and my christmas holidays!!! I found the issue in the code that strips the actor and the object!

I will fix it asap and release a new update!

So the follow issue is solved, sorry for keeping you busy and thanks a lot for your help debugging this issue!

@saschanaz
Copy link
Member

saschanaz commented Dec 21, 2023

Congrats! 🎉

(Let's keep this issue open to track supporting implementations without those fields)

@pfefferle
Copy link
Author

(Let's keep this issue to track supporting implementations without those fields)

Besides of that, should I keep this issue open because of the sharedInbox problem?

@saschanaz
Copy link
Member

Yup, but ideally we should have two separate issues for each.

@pfefferle
Copy link
Author

Ok, I will file a separate issue for the sharedInbox issue.

@saschanaz saschanaz changed the title Can't follow WordPress with ActivityPub plugin enabled Can't process Accept activity after Follow when activity.actor doesn't exist Dec 21, 2023
@saschanaz saschanaz added 🐛Bug Unexpected behavior and removed ⚠️bug? This might be a bug labels Dec 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛Bug Unexpected behavior 🌌Federation The Federation/ActivityPub feature packages/backend Server side specific issue/PR
Projects
Development

No branches or pull requests

3 participants