annotate sat/plugins/plugin_comp_ap_gateway/http_server.py @ 4009:48e8b3dba793

component AP gateway (http/outbox): return data when no RSM is available
author Goffi <goffi@goffi.org>
date Thu, 16 Mar 2023 15:56:11 +0100
parents 54a6b44f173b
children 4ef473116499
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # Libervia ActivityPub Gateway
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
19 import time
3821
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
20 import html
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
21 from typing import Optional, Dict, List, Any
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
22 import json
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
23 from urllib import parse
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
24 from collections import deque
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
25 import unicodedata
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
26
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
27 from twisted.web import http, resource as web_resource, server
3821
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
28 from twisted.web import static
3977
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
29 from twisted.web import util as web_util
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
30 from twisted.python import failure
3833
381340b9a9ee component AP gateway: convert XMPP mentions to AP:
Goffi <goffi@goffi.org>
parents: 3826
diff changeset
31 from twisted.internet import defer
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
32 from twisted.words.protocols.jabber import jid, error
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
33 from wokkel import pubsub, rsm
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
34
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
35 from sat.core import exceptions
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 from sat.core.constants import Const as C
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
37 from sat.core.i18n import _
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
38 from sat.core.core_types import SatXMPPEntity
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 from sat.core.log import getLogger
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
40 from sat.tools.common import date_utils, uri
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
41 from sat.memory.sqla_mapping import SubscriptionState
3729
86eea17cafa7 component AP gateway: split plugin in several files:
Goffi <goffi@goffi.org>
parents: 3728
diff changeset
42
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
43 from .constants import (
3977
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
44 NS_AP, MEDIA_TYPE_AP, CONTENT_TYPE_AP, TYPE_ACTOR, TYPE_INBOX, TYPE_SHARED_INBOX,
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
45 TYPE_OUTBOX, TYPE_EVENT, AP_REQUEST_TYPES, PAGE_SIZE, ACTIVITY_TYPES_LOWER,
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
46 ACTIVIY_NO_ACCOUNT_ALLOWED, SIGN_HEADERS, HS2019, SIGN_EXP, TYPE_FOLLOWERS,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
47 TYPE_FOLLOWING, TYPE_ITEM, TYPE_LIKE, TYPE_REACTION, ST_AP_CACHE
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
48 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
49 from .regex import RE_SIG_PARAM
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
50
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
51
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 log = getLogger(__name__)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
54 VERSION = unicodedata.normalize(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
55 'NFKD',
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
56 f"{C.APP_NAME} ActivityPub Gateway {C.APP_VERSION}"
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
57 )
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
58
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
59
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 class HTTPAPGServer(web_resource.Resource):
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 """HTTP Server handling ActivityPub S2S protocol"""
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 isLeaf = True
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
63
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 def __init__(self, ap_gateway):
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 self.apg = ap_gateway
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
66 self._seen_digest = deque(maxlen=50)
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 super().__init__()
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
68
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
69 def responseCode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
70 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
71 request: "HTTPRequest",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
72 http_code: int,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
73 msg: Optional[str] = None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
74 ) -> None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
75 """Log and set HTTP return code and associated message"""
3833
381340b9a9ee component AP gateway: convert XMPP mentions to AP:
Goffi <goffi@goffi.org>
parents: 3826
diff changeset
76 if msg is not None:
381340b9a9ee component AP gateway: convert XMPP mentions to AP:
Goffi <goffi@goffi.org>
parents: 3826
diff changeset
77 log.warning(msg)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
78 request.setResponseCode(http_code, None if msg is None else msg.encode())
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
79
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
80 def _onRequestError(self, failure_: failure.Failure, request: "HTTPRequest") -> None:
3996
7a6c7abd7dbb component AP gateway (http_server): use log.exception instead of log.error
Goffi <goffi@goffi.org>
parents: 3995
diff changeset
81 log.exception(f"Internal error: {failure_.value}")
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
82 self.responseCode(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
83 request,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
84 http.INTERNAL_SERVER_ERROR,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
85 f"internal error: {failure_.value}"
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
86 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
87 request.finish()
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
88 raise failure_
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
89
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
90 async def webfinger(self, request):
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 url_parsed = parse.urlparse(request.uri.decode())
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 query = parse.parse_qs(url_parsed.query)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 resource = query.get("resource", [""])[0]
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 account = resource[5:].strip()
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 if not resource.startswith("acct:") or not account:
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 return web_resource.ErrorPage(
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 http.BAD_REQUEST, "Bad Request" , "Invalid webfinger resource"
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 ).render(request)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
99
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 actor_url = self.apg.buildAPURL(TYPE_ACTOR, account)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
101
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 resp = {
3882
1bd44367337d component AP gateway: add `aliases` to webfinger data
Goffi <goffi@goffi.org>
parents: 3881
diff changeset
103 "aliases": [actor_url],
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 "subject": resource,
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 "links": [
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 {
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 "rel": "self",
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 "type": "application/activity+json",
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 "href": actor_url
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 }
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 ]
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 }
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 request.setHeader("content-type", CONTENT_TYPE_AP)
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
114 request.write(json.dumps(resp).encode())
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
115 request.finish()
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
116
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
117 async def handleUndoActivity(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
118 self,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
119 request: "HTTPRequest",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
120 data: dict,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
121 account_jid: jid.JID,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
122 node: Optional[str],
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
123 ap_account: str,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
124 ap_url: str,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
125 signing_actor: str
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
126 ) -> None:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
127 if node is None:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
128 node = self.apg._m.namespace
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
129 client = await self.apg.getVirtualClient(signing_actor)
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
130 object_ = data.get("object")
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
131 if isinstance(object_, str):
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
132 # we check first if it's not a cached object
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
133 ap_cache_key = f"{ST_AP_CACHE}{object_}"
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
134 value = await self.apg.client._ap_storage.get(ap_cache_key)
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
135 else:
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
136 value = None
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
137 if value is not None:
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
138 objects = [value]
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
139 # because we'll undo the activity, we can remove it from cache
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
140 await self.apg.client._ap_storage.remove(ap_cache_key)
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
141 else:
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
142 objects = await self.apg.apGetList(data, "object")
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
143 for obj in objects:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
144 type_ = obj.get("type")
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
145 actor = await self.apg.apGetSenderActor(obj)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
146 if actor != signing_actor:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
147 log.warning(f"ignoring object not attributed to signing actor: {data}")
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
148 continue
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
149
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
150 if type_ == "Follow":
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
151 try:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
152 target_account = obj["object"]
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
153 except KeyError:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
154 log.warning(f'ignoring invalid object, missing "object" key: {data}')
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
155 continue
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
156 if not self.apg.isLocalURL(target_account):
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
157 log.warning(f"ignoring unfollow request to non local actor: {data}")
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
158 continue
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
159 await self.apg._p.unsubscribe(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
160 client,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
161 account_jid,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
162 node,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
163 sender=client.jid,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
164 )
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
165 elif type_ == "Announce":
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
166 # we can use directly the Announce object, as only the "id" field is
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
167 # needed
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
168 await self.apg.newAPDeleteItem(client, None, node, obj)
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
169 elif type_ == TYPE_LIKE:
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
170 await self.handleAttachmentItem(client, obj, {"noticed": False})
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
171 elif type_ == TYPE_REACTION:
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
172 await self.handleAttachmentItem(client, obj, {
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
173 "reactions": {"operation": "update", "remove": [obj["content"]]}
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
174 })
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
175 else:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
176 log.warning(f"Unmanaged undo type: {type_!r}")
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
177
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
178 async def handleFollowActivity(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
179 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
180 request: "HTTPRequest",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
181 data: dict,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
182 account_jid: jid.JID,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
183 node: Optional[str],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
184 ap_account: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
185 ap_url: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
186 signing_actor: str
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
187 ) -> None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
188 if node is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
189 node = self.apg._m.namespace
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
190 client = await self.apg.getVirtualClient(signing_actor)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
191 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
192 subscription = await self.apg._p.subscribe(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
193 client,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
194 account_jid,
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
195 node,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
196 # subscriptions from AP are always public
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
197 options=self.apg._pps.setPublicOpt()
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
198 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
199 except pubsub.SubscriptionPending:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
200 log.info(f"subscription to node {node!r} of {account_jid} is pending")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
201 # TODO: manage SubscriptionUnconfigured
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
202 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
203 if subscription.state != "subscribed":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
204 # other states should raise an Exception
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
205 raise exceptions.InternalError('"subscribed" state was expected')
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
206 inbox = await self.apg.getAPInboxFromId(signing_actor, use_shared=False)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
207 actor_id = self.apg.buildAPURL(TYPE_ACTOR, ap_account)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
208 accept_data = self.apg.createActivity(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
209 "Accept", actor_id, object_=data
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
210 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
211 await self.apg.signAndPost(inbox, actor_id, accept_data)
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
212 await self.apg._c.synchronise(client, account_jid, node, resync=False)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
213
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
214 async def handleAcceptActivity(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
215 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
216 request: "HTTPRequest",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
217 data: dict,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
218 account_jid: jid.JID,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
219 node: Optional[str],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
220 ap_account: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
221 ap_url: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
222 signing_actor: str
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
223 ) -> None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
224 if node is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
225 node = self.apg._m.namespace
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
226 client = await self.apg.getVirtualClient(signing_actor)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
227 objects = await self.apg.apGetList(data, "object")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
228 for obj in objects:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
229 type_ = obj.get("type")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
230 if type_ == "Follow":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
231 follow_node = await self.apg.host.memory.storage.getPubsubNode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
232 client, client.jid, node, with_subscriptions=True
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
233 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
234 if follow_node is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
235 log.warning(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
236 f"Received a follow accept on an unknown node: {node!r} at "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
237 f"{client.jid}. Ignoring it"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
238 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
239 continue
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
240 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
241 sub = next(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
242 s for s in follow_node.subscriptions if s.subscriber==account_jid
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
243 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
244 except StopIteration:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
245 log.warning(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
246 "Received a follow accept on a node without subscription: "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
247 f"{node!r} at {client.jid}. Ignoring it"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
248 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
249 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
250 if sub.state == SubscriptionState.SUBSCRIBED:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
251 log.warning(f"Already subscribed to {node!r} at {client.jid}")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
252 elif sub.state == SubscriptionState.PENDING:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
253 follow_node.subscribed = True
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
254 sub.state = SubscriptionState.SUBSCRIBED
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
255 await self.apg.host.memory.storage.add(follow_node)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
256 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
257 raise exceptions.InternalError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
258 f"Unhandled subscription state {sub.state!r}"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
259 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
260 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
261 log.warning(f"Unmanaged accept type: {type_!r}")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
262
3793
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
263 async def handleDeleteActivity(
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
264 self,
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
265 request: "HTTPRequest",
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
266 data: dict,
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
267 account_jid: Optional[jid.JID],
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
268 node: Optional[str],
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
269 ap_account: Optional[str],
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
270 ap_url: str,
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
271 signing_actor: str
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
272 ):
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
273 if node is None:
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
274 node = self.apg._m.namespace
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
275 client = await self.apg.getVirtualClient(signing_actor)
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
276 objects = await self.apg.apGetList(data, "object")
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
277 for obj in objects:
3807
2032826cfbcf component AP gateway typing + remove unused `activity` arg from `newAPDeleteItem`
Goffi <goffi@goffi.org>
parents: 3804
diff changeset
278 await self.apg.newAPDeleteItem(client, account_jid, node, obj)
3793
b5c9021020df component AP gateway: convert `Delete` AP activities to corresponding Pubsub `retract`:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
279
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
280 async def handleNewAPItems(
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
281 self,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
282 request: "HTTPRequest",
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
283 data: dict,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
284 account_jid: Optional[jid.JID],
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
285 node: Optional[str],
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
286 signing_actor: str,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
287 repeated: bool = False,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
288 ):
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
289 """Helper method to handle workflow for new AP items
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
290
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
291 accept globally the same parameter as for handleCreateActivity
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
292 @param repeated: if True, the item is an item republished from somewhere else
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
293 """
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
294 if "_repeated" in data:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
295 log.error(
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
296 '"_repeated" field already present in given AP item, this should not '
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
297 f"happen. Ignoring object from {signing_actor}\n{data}"
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
298 )
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
299 raise exceptions.DataError("unexpected field in item")
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
300 client = await self.apg.getVirtualClient(signing_actor)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
301 objects = await self.apg.apGetList(data, "object")
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
302 for obj in objects:
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
303 if node is None:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
304 if obj.get("type") == TYPE_EVENT:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
305 node = self.apg._events.namespace
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
306 else:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
307 node = self.apg._m.namespace
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
308 sender = await self.apg.apGetSenderActor(obj)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
309 if repeated:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
310 # we don't check sender when item is repeated, as it should be different
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
311 # from post author in this case
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
312 sender_jid = await self.apg.getJIDFromId(sender)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
313 repeater_jid = await self.apg.getJIDFromId(signing_actor)
3870
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
314 repeated_item_id = obj["id"]
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
315 if self.apg.isLocalURL(repeated_item_id):
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
316 # the repeated object is from XMPP, we need to parse the URL to find
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
317 # the right ID
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
318 url_type, url_args = self.apg.parseAPURL(repeated_item_id)
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
319 if url_type != "item":
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
320 raise exceptions.DataError(
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
321 "local URI is not an item: {repeated_id}"
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
322 )
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
323 try:
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
324 url_account, url_item_id = url_args
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
325 if not url_account or not url_item_id:
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
326 raise ValueError
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
327 except (RuntimeError, ValueError):
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
328 raise exceptions.DataError(
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
329 "local URI is invalid: {repeated_id}"
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
330 )
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
331 else:
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
332 url_jid, url_node = await self.apg.getJIDAndNode(url_account)
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
333 if ((url_jid != sender_jid
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
334 or url_node and url_node != self.apg._m.namespace)):
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
335 raise exceptions.DataError(
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
336 "announced ID doesn't match sender ({sender}): "
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
337 f"[repeated_item_id]"
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
338 )
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
339
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
340 repeated_item_id = url_item_id
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
341
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
342 obj["_repeated"] = {
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
343 "by": repeater_jid.full(),
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
344 "at": data.get("published"),
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
345 "uri": uri.buildXMPPUri(
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
346 "pubsub",
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
347 path=sender_jid.full(),
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
348 node=self.apg._m.namespace,
3870
bd84d289fc94 component AP gateway: fix item ID for XMPP items on Announce:
Goffi <goffi@goffi.org>
parents: 3869
diff changeset
349 item=repeated_item_id
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
350 )
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
351 }
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
352 # we must use activity's id and targets, not the original item ones
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
353 for field in ("id", "to", "bto", "cc", "bcc"):
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
354 obj[field] = data.get(field)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
355 else:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
356 if sender != signing_actor:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
357 log.warning(
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
358 "Ignoring object not attributed to signing actor: {obj}"
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
359 )
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
360 continue
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
361
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
362 await self.apg.newAPItem(client, account_jid, node, obj)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
363
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
364 async def handleCreateActivity(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
365 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
366 request: "HTTPRequest",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
367 data: dict,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
368 account_jid: Optional[jid.JID],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
369 node: Optional[str],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
370 ap_account: Optional[str],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
371 ap_url: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
372 signing_actor: str
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
373 ):
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
374 await self.handleNewAPItems(request, data, account_jid, node, signing_actor)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
375
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
376 async def handleUpdateActivity(
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
377 self,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
378 request: "HTTPRequest",
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
379 data: dict,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
380 account_jid: Optional[jid.JID],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
381 node: Optional[str],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
382 ap_account: Optional[str],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
383 ap_url: str,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
384 signing_actor: str
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
385 ):
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
386 # Update is the same as create: the item ID stays the same, thus the item will be
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
387 # overwritten
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
388 await self.handleNewAPItems(request, data, account_jid, node, signing_actor)
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
389
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
390 async def handleAnnounceActivity(
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
391 self,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
392 request: "HTTPRequest",
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
393 data: dict,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
394 account_jid: Optional[jid.JID],
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
395 node: Optional[str],
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
396 ap_account: Optional[str],
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
397 ap_url: str,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
398 signing_actor: str
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
399 ):
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
400 # we create a new item
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
401 await self.handleNewAPItems(
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
402 request,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
403 data,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
404 account_jid,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
405 node,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
406 signing_actor,
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
407 repeated=True
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
408 )
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
409
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
410 async def handleAttachmentItem(
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
411 self,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
412 client: SatXMPPEntity,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
413 data: dict,
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
414 attachment_data: dict
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
415 ) -> None:
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
416 target_ids = data.get("object")
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
417 if not target_ids:
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
418 raise exceptions.DataError("object should be set")
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
419 elif isinstance(target_ids, list):
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
420 try:
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
421 target_ids = [o["id"] for o in target_ids]
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
422 except (KeyError, TypeError):
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
423 raise exceptions.DataError(f"invalid object: {target_ids!r}")
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
424 elif isinstance(target_ids, dict):
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
425 obj_id = target_ids.get("id")
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
426 if not obj_id or not isinstance(obj_id, str):
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
427 raise exceptions.DataError(f"invalid object: {target_ids!r}")
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
428 target_ids = [obj_id]
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
429 elif isinstance(target_ids, str):
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
430 target_ids = [target_ids]
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
431
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
432 # XXX: we have to cache AP items because some implementation (Pleroma notably)
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
433 # don't keep object accessible, and we need to be able to retrieve them for
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
434 # UNDO. Current implementation will grow, we need to add a way to flush it after
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
435 # a while.
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
436 # TODO: add a way to flush old cached AP items.
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
437 await client._ap_storage.aset(f"{ST_AP_CACHE}{data['id']}", data)
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
438
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
439 for target_id in target_ids:
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
440 if not self.apg.isLocalURL(target_id):
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
441 log.debug(f"ignoring non local target ID: {target_id}")
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
442 continue
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
443 url_type, url_args = self.apg.parseAPURL(target_id)
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
444 if url_type != TYPE_ITEM:
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
445 log.warning(f"unexpected local URL for attachment on item {target_id}")
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
446 continue
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
447 try:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
448 account, item_id = url_args
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
449 except ValueError:
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
450 raise ValueError(f"invalid URL: {target_id}")
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
451 author_jid, item_node = await self.apg.getJIDAndNode(account)
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
452 if item_node is None:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
453 item_node = self.apg._m.namespace
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
454 attachment_node = self.apg._pa.getAttachmentNodeName(
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
455 author_jid, item_node, item_id
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
456 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
457 cached_node = await self.apg.host.memory.storage.getPubsubNode(
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
458 client,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
459 author_jid,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
460 attachment_node,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
461 with_subscriptions=True,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
462 create=True
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
463 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
464 found_items, __ = await self.apg.host.memory.storage.getItems(
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
465 cached_node, item_ids=[client.jid.userhost()]
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
466 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
467 if not found_items:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
468 old_item_elt = None
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
469 else:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
470 found_item = found_items[0]
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
471 old_item_elt = found_item.data
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
472
3980
9b5092225e46 component AP gateway: fix pubsub attachment plugin call following renaming.
Goffi <goffi@goffi.org>
parents: 3977
diff changeset
473 item_elt = await self.apg._pa.apply_set_handler(
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
474 client,
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
475 {"extra": attachment_data},
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
476 old_item_elt,
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
477 None
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
478 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
479 # we reparse the element, as there can be other attachments
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
480 attachments_data = self.apg._pa.items2attachmentData(client, [item_elt])
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
481 # and we update the cache
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
482 await self.apg.host.memory.storage.cachePubsubItems(
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
483 client,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
484 cached_node,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
485 [item_elt],
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
486 attachments_data or [{}]
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
487 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
488
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
489 if self.apg.isVirtualJID(author_jid):
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
490 # the attachment is on t a virtual pubsub service (linking to an AP item),
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
491 # we notify all subscribers
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
492 for subscription in cached_node.subscriptions:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
493 if subscription.state != SubscriptionState.SUBSCRIBED:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
494 continue
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
495 self.apg.pubsub_service.notifyPublish(
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
496 author_jid,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
497 attachment_node,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
498 [(subscription.subscriber, None, [item_elt])]
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
499 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
500 else:
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
501 # the attachment is on an XMPP item, we publish it to the attachment node
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
502 await self.apg._p.sendItems(
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
503 client, author_jid, attachment_node, [item_elt]
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
504 )
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
505
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
506 async def handleLikeActivity(
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
507 self,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
508 request: "HTTPRequest",
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
509 data: dict,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
510 account_jid: Optional[jid.JID],
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
511 node: Optional[str],
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
512 ap_account: Optional[str],
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
513 ap_url: str,
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
514 signing_actor: str
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
515 ) -> None:
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
516 client = await self.apg.getVirtualClient(signing_actor)
3888
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
517 await self.handleAttachmentItem(client, data, {"noticed": True})
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
518
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
519 async def handleEmojireactActivity(
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
520 self,
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
521 request: "HTTPRequest",
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
522 data: dict,
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
523 account_jid: Optional[jid.JID],
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
524 node: Optional[str],
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
525 ap_account: Optional[str],
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
526 ap_url: str,
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
527 signing_actor: str
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
528 ) -> None:
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
529 client = await self.apg.getVirtualClient(signing_actor)
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
530 await self.handleAttachmentItem(client, data, {
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
531 "reactions": {"operation": "update", "add": [data["content"]]}
aa7197b67c26 component AP gateway: AP <=> XMPP reactions conversions:
Goffi <goffi@goffi.org>
parents: 3884
diff changeset
532 })
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
533
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
534 async def handleJoinActivity(
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
535 self,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
536 request: "HTTPRequest",
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
537 data: dict,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
538 account_jid: Optional[jid.JID],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
539 node: Optional[str],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
540 ap_account: Optional[str],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
541 ap_url: str,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
542 signing_actor: str
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
543 ) -> None:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
544 client = await self.apg.getVirtualClient(signing_actor)
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
545 await self.handleAttachmentItem(client, data, {"rsvp": {"attending": "yes"}})
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
546
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
547 async def handleLeaveActivity(
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
548 self,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
549 request: "HTTPRequest",
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
550 data: dict,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
551 account_jid: Optional[jid.JID],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
552 node: Optional[str],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
553 ap_account: Optional[str],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
554 ap_url: str,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
555 signing_actor: str
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
556 ) -> None:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
557 client = await self.apg.getVirtualClient(signing_actor)
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
558 await self.handleAttachmentItem(client, data, {"rsvp": {"attending": "no"}})
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
559
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
560 async def APActorRequest(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
561 self,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
562 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
563 data: Optional[dict],
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
564 account_jid: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
565 node: Optional[str],
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
566 ap_account: str,
3826
81c79b7cafa7 tests (unit/ap-gateway): tests for XMPP identity/vCard4 <=> AP actor data conversion:
Goffi <goffi@goffi.org>
parents: 3821
diff changeset
567 ap_url: str,
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
568 signing_actor: Optional[str]
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
569 ) -> dict:
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
570 inbox = self.apg.buildAPURL(TYPE_INBOX, ap_account)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
571 shared_inbox = self.apg.buildAPURL(TYPE_SHARED_INBOX)
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
572 outbox = self.apg.buildAPURL(TYPE_OUTBOX, ap_account)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
573 followers = self.apg.buildAPURL(TYPE_FOLLOWERS, ap_account)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
574 following = self.apg.buildAPURL(TYPE_FOLLOWING, ap_account)
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
575
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
576 # we have to use AP account as preferredUsername because it is used to retrieve
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
577 # actor handle (see https://socialhub.activitypub.rocks/t/how-to-retrieve-user-server-tld-handle-from-actors-url/2196)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
578 preferred_username = ap_account.split("@", 1)[0]
3821
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
579
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
580 identity_data = await self.apg._i.getIdentity(self.apg.client, account_jid)
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
581 if node and node.startswith(self.apg._events.namespace):
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
582 events = outbox
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
583 else:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
584 events_account = await self.apg.getAPAccountFromJidAndNode(
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
585 account_jid, self.apg._events.namespace
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
586 )
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
587 events = self.apg.buildAPURL(TYPE_OUTBOX, events_account)
3821
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
588
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
589 actor_data = {
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
590 "@context": [
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
591 "https://www.w3.org/ns/activitystreams",
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
592 "https://w3id.org/security/v1"
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
593 ],
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
594
3994
69d970f974ff component AP gateway: don't percent-encode `@`:
Goffi <goffi@goffi.org>
parents: 3992
diff changeset
595 # XXX: Mastodon doesn't like percent-encode arobas, so we have to unescape it
69d970f974ff component AP gateway: don't percent-encode `@`:
Goffi <goffi@goffi.org>
parents: 3992
diff changeset
596 # if it is escaped
69d970f974ff component AP gateway: don't percent-encode `@`:
Goffi <goffi@goffi.org>
parents: 3992
diff changeset
597 "id": ap_url.replace("%40", "@"),
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
598 "type": "Person",
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
599 "preferredUsername": preferred_username,
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
600 "inbox": inbox,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
601 "outbox": outbox,
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
602 "events": events,
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
603 "followers": followers,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
604 "following": following,
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
605 "publicKey": {
3826
81c79b7cafa7 tests (unit/ap-gateway): tests for XMPP identity/vCard4 <=> AP actor data conversion:
Goffi <goffi@goffi.org>
parents: 3821
diff changeset
606 "id": f"{ap_url}#main-key",
81c79b7cafa7 tests (unit/ap-gateway): tests for XMPP identity/vCard4 <=> AP actor data conversion:
Goffi <goffi@goffi.org>
parents: 3821
diff changeset
607 "owner": ap_url,
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
608 "publicKeyPem": self.apg.public_key_pem
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
609 },
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
610 "endpoints": {
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
611 "sharedInbox": shared_inbox,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
612 "events": events,
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
613 },
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
614 }
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
615
3821
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
616 if identity_data.get("nicknames"):
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
617 actor_data["name"] = identity_data["nicknames"][0]
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
618 if identity_data.get("description"):
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
619 # description is plain text while summary expects HTML
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
620 actor_data["summary"] = html.escape(identity_data["description"])
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
621 if identity_data.get("avatar"):
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
622 avatar_data = identity_data["avatar"]
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
623 try:
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
624 filename = avatar_data["filename"]
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
625 media_type = avatar_data["media_type"]
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
626 except KeyError:
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
627 log.error(f"incomplete avatar data: {identity_data!r}")
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
628 else:
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
629 avatar_url = self.apg.buildAPURL("avatar", filename)
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
630 actor_data["icon"] = {
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
631 "type": "Image",
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
632 "url": avatar_url,
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
633 "mediaType": media_type
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
634 }
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
635
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
636 return actor_data
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
637
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
638 def getCanonicalURL(self, request: "HTTPRequest") -> str:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
639 return parse.urljoin(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
640 f"https://{self.apg.public_url}",
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
641 request.path.decode().rstrip("/")
3994
69d970f974ff component AP gateway: don't percent-encode `@`:
Goffi <goffi@goffi.org>
parents: 3992
diff changeset
642 # we unescape "@" for the same reason as in [APActorRequest]
69d970f974ff component AP gateway: don't percent-encode `@`:
Goffi <goffi@goffi.org>
parents: 3992
diff changeset
643 ).replace("%40", "@")
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
644
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
645 def queryData2RSMRequest(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
646 self,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
647 query_data: Dict[str, List[str]]
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
648 ) -> rsm.RSMRequest:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
649 """Get RSM kwargs to use with RSMRequest from query data"""
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
650 page = query_data.get("page")
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
651
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
652 if page == ["first"]:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
653 return rsm.RSMRequest(max_=PAGE_SIZE, before="")
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
654 elif page == ["last"]:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
655 return rsm.RSMRequest(max_=PAGE_SIZE)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
656 else:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
657 for query_key in ("index", "before", "after"):
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
658 try:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
659 kwargs={query_key: query_data[query_key][0], "max_": PAGE_SIZE}
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
660 except (KeyError, IndexError, ValueError):
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
661 pass
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
662 else:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
663 return rsm.RSMRequest(**kwargs)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
664 raise ValueError(f"Invalid query data: {query_data!r}")
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
665
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
666 async def APOutboxPageRequest(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
667 self,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
668 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
669 data: Optional[dict],
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
670 account_jid: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
671 node: Optional[str],
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
672 ap_account: str,
3729
86eea17cafa7 component AP gateway: split plugin in several files:
Goffi <goffi@goffi.org>
parents: 3728
diff changeset
673 ap_url: str,
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
674 query_data: Dict[str, List[str]]
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
675 ) -> dict:
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
676 if node is None:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
677 node = self.apg._m.namespace
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
678 # we only keep useful keys, and sort to have consistent URL which can
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
679 # be used as ID
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
680 url_keys = sorted(set(query_data) & {"page", "index", "before", "after"})
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
681 query_data = {k: query_data[k] for k in url_keys}
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
682 try:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
683 items, metadata = await self.apg._p.getItems(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
684 client=self.apg.client,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
685 service=account_jid,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
686 node=node,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
687 rsm_request=self.queryData2RSMRequest(query_data),
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
688 extra = {C.KEY_USE_CACHE: False}
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
689 )
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
690 except error.StanzaError as e:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
691 log.warning(f"Can't get data from pubsub node {node} at {account_jid}: {e}")
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
692 return {}
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
693
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
694 base_url = self.getCanonicalURL(request)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
695 url = f"{base_url}?{parse.urlencode(query_data, True)}"
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
696 if node and node.startswith(self.apg._events.namespace):
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
697 ordered_items = [
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
698 await self.apg.ap_events.event_data_2_ap_item(
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
699 self.apg._events.event_elt_2_event_data(item),
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
700 account_jid
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
701 )
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
702 for item in reversed(items)
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
703 ]
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
704 else:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
705 ordered_items = [
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
706 await self.apg.mb_data_2_ap_item(
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
707 self.apg.client,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
708 await self.apg._m.item2mbdata(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
709 self.apg.client,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
710 item,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
711 account_jid,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
712 node
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
713 )
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
714 )
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
715 for item in reversed(items)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
716 ]
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
717 ret_data = {
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
718 "@context": ["https://www.w3.org/ns/activitystreams"],
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
719 "id": url,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
720 "type": "OrderedCollectionPage",
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
721 "partOf": base_url,
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
722 "orderedItems": ordered_items
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
723 }
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
724
4009
48e8b3dba793 component AP gateway (http/outbox): return data when no RSM is available
Goffi <goffi@goffi.org>
parents: 4005
diff changeset
725 if "rsm" not in metadata:
48e8b3dba793 component AP gateway (http/outbox): return data when no RSM is available
Goffi <goffi@goffi.org>
parents: 4005
diff changeset
726 # no RSM available, we return what we have
48e8b3dba793 component AP gateway (http/outbox): return data when no RSM is available
Goffi <goffi@goffi.org>
parents: 4005
diff changeset
727 return ret_data
48e8b3dba793 component AP gateway (http/outbox): return data when no RSM is available
Goffi <goffi@goffi.org>
parents: 4005
diff changeset
728
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
729 # AP OrderedCollection must be in reversed chronological order, thus the opposite
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
730 # of what we get with RSM (at least with Libervia Pubsub)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
731 if not metadata["complete"]:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
732 try:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
733 last= metadata["rsm"]["last"]
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
734 except KeyError:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
735 last = None
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
736 ret_data["prev"] = f"{base_url}?{parse.urlencode({'after': last})}"
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
737 if metadata["rsm"]["index"] != 0:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
738 try:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
739 first= metadata["rsm"]["first"]
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
740 except KeyError:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
741 first = None
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
742 ret_data["next"] = f"{base_url}?{parse.urlencode({'before': first})}"
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
743
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
744 return ret_data
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
745
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
746 async def APOutboxRequest(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
747 self,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
748 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
749 data: Optional[dict],
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
750 account_jid: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
751 node: Optional[str],
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
752 ap_account: str,
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
753 ap_url: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
754 signing_actor: Optional[str]
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
755 ) -> dict:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
756 if node is None:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
757 node = self.apg._m.namespace
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
758
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
759 parsed_url = parse.urlparse(request.uri.decode())
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
760 query_data = parse.parse_qs(parsed_url.query)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
761 if query_data:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
762 return await self.APOutboxPageRequest(
3995
27e5294649c2 component AP gateway: fix missing argument when calling APOutboxPageRequest
Goffi <goffi@goffi.org>
parents: 3994
diff changeset
763 request, data, account_jid, node, ap_account, ap_url, query_data
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
764 )
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
765
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
766 # XXX: we can't use disco#info here because this request won't work on a bare jid
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
767 # due to security considerations of XEP-0030 (we don't have presence
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
768 # subscription).
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
769 # The current workaround is to do a request as if RSM was available, and actually
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
770 # check its availability according to result.
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
771 try:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
772 __, metadata = await self.apg._p.getItems(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
773 client=self.apg.client,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
774 service=account_jid,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
775 node=node,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
776 max_items=0,
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
777 rsm_request=rsm.RSMRequest(max_=0),
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
778 extra = {C.KEY_USE_CACHE: False}
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
779 )
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
780 except error.StanzaError as e:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
781 log.warning(f"Can't get data from pubsub node {node} at {account_jid}: {e}")
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
782 return {}
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
783 try:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
784 items_count = metadata["rsm"]["count"]
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
785 except KeyError:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
786 log.warning(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
787 f"No RSM metadata found when requesting pubsub node {node} at "
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
788 f"{account_jid}, defaulting to items_count=20"
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
789 )
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
790 items_count = 20
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
791
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
792 url = self.getCanonicalURL(request)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
793 url_first_page = f"{url}?{parse.urlencode({'page': 'first'})}"
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
794 url_last_page = f"{url}?{parse.urlencode({'page': 'last'})}"
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
795 return {
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
796 "@context": ["https://www.w3.org/ns/activitystreams"],
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
797 "id": url,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
798 "totalItems": items_count,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
799 "type": "OrderedCollection",
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
800 "first": url_first_page,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
801 "last": url_last_page,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
802 }
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
803
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
804 async def APInboxRequest(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
805 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
806 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
807 data: Optional[dict],
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
808 account_jid: Optional[jid.JID],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
809 node: Optional[str],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
810 ap_account: Optional[str],
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
811 ap_url: str,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
812 signing_actor: Optional[str]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
813 ) -> None:
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
814 assert data is not None
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
815 if signing_actor is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
816 raise exceptions.InternalError("signing_actor must be set for inbox requests")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
817 await self.checkSigningActor(data, signing_actor)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
818 activity_type = (data.get("type") or "").lower()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
819 if not activity_type in ACTIVITY_TYPES_LOWER:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
820 return self.responseCode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
821 request,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
822 http.UNSUPPORTED_MEDIA_TYPE,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
823 f"request is not an activity, ignoring"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
824 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
825
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
826 if account_jid is None and activity_type not in ACTIVIY_NO_ACCOUNT_ALLOWED:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
827 return self.responseCode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
828 request,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
829 http.UNSUPPORTED_MEDIA_TYPE,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
830 f"{activity_type.title()!r} activity must target an account"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
831 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
832
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
833 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
834 method = getattr(self, f"handle{activity_type.title()}Activity")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
835 except AttributeError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
836 return self.responseCode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
837 request,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
838 http.UNSUPPORTED_MEDIA_TYPE,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
839 f"{activity_type.title()} activity is not yet supported"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
840 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
841 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
842 await method(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
843 request, data, account_jid, node, ap_account, ap_url, signing_actor
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
844 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
845
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
846 async def APFollowersRequest(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
847 self,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
848 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
849 data: Optional[dict],
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
850 account_jid: jid.JID,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
851 node: Optional[str],
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
852 ap_account: Optional[str],
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
853 ap_url: str,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
854 signing_actor: Optional[str]
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
855 ) -> dict:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
856 if node is None:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
857 node = self.apg._m.namespace
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
858 client = self.apg.client
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
859 subscribers = await self.apg._pps.getPublicNodeSubscriptions(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
860 client, account_jid, node
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
861 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
862 followers = []
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
863 for subscriber in subscribers.keys():
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
864 if self.apg.isVirtualJID(subscriber):
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
865 # the subscriber is an AP user subscribed with this gateway
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
866 ap_account = self.apg._e.unescape(subscriber.user)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
867 else:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
868 # regular XMPP user
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
869 ap_account = await self.apg.getAPAccountFromJidAndNode(subscriber, node)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
870 followers.append(ap_account)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
871
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
872 url = self.getCanonicalURL(request)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
873 return {
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
874 "@context": ["https://www.w3.org/ns/activitystreams"],
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
875 "type": "OrderedCollection",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
876 "id": url,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
877 "totalItems": len(subscribers),
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
878 "first": {
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
879 "type": "OrderedCollectionPage",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
880 "id": url,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
881 "orderedItems": followers
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
882 }
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
883 }
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
884
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
885 async def APFollowingRequest(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
886 self,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
887 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
888 data: Optional[dict],
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
889 account_jid: jid.JID,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
890 node: Optional[str],
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
891 ap_account: Optional[str],
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
892 ap_url: str,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
893 signing_actor: Optional[str]
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
894 ) -> dict[str, Any]:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
895 client = self.apg.client
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
896 subscriptions = await self.apg._pps.subscriptions(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
897 client, account_jid, node
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
898 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
899 following = []
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
900 for sub_dict in subscriptions:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
901 service = jid.JID(sub_dict["service"])
3869
c0bcbcf5b4b7 component AP gateway: handle `Like` and `Undo`/`Like` activities:
Goffi <goffi@goffi.org>
parents: 3847
diff changeset
902 if self.apg.isVirtualJID(service):
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
903 # the subscription is to an AP actor with this gateway
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
904 ap_account = self.apg._e.unescape(service.user)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
905 else:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
906 # regular XMPP user
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
907 ap_account = await self.apg.getAPAccountFromJidAndNode(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
908 service, sub_dict["node"]
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
909 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
910 following.append(ap_account)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
911
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
912 url = self.getCanonicalURL(request)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
913 return {
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
914 "@context": ["https://www.w3.org/ns/activitystreams"],
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
915 "type": "OrderedCollection",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
916 "id": url,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
917 "totalItems": len(subscriptions),
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
918 "first": {
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
919 "type": "OrderedCollectionPage",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
920 "id": url,
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
921 "orderedItems": following
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
922 }
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
923 }
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
924
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
925 async def APRequest(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
926 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
927 request: "HTTPRequest",
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
928 data: Optional[dict] = None,
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
929 signing_actor: Optional[str] = None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
930 ) -> None:
3847
aaa4e7815ba8 component AP gateway: new `verbose` attribute in AP gateway to activate debug logs:
Goffi <goffi@goffi.org>
parents: 3846
diff changeset
931 if self.apg.verbose:
3881
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
932 from pprint import pformat
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
933 to_log = [
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
934 "",
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
935 f"<<< got {request.method.decode()} request - {request.uri.decode()}"
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
936 ]
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
937 if data is not None:
3881
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
938 to_log.append(pformat(data))
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
939 if self.apg.verbose>=3:
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
940 headers = "\n".join(
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
941 f" {k.decode()}: {v.decode()}"
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
942 for k,v in request.getAllHeaders().items()
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
943 )
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
944 to_log.append(f" headers:\n{headers}")
3847
aaa4e7815ba8 component AP gateway: new `verbose` attribute in AP gateway to activate debug logs:
Goffi <goffi@goffi.org>
parents: 3846
diff changeset
945
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
946 path = request.path.decode()
3729
86eea17cafa7 component AP gateway: split plugin in several files:
Goffi <goffi@goffi.org>
parents: 3728
diff changeset
947 ap_url = parse.urljoin(
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
948 f"https://{self.apg.public_url}",
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
949 path
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
950 )
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
951 request_type, extra_args = self.apg.parseAPURL(ap_url)
3992
1c84268752a1 component AP gateway: fix bad condition
Goffi <goffi@goffi.org>
parents: 3991
diff changeset
952 if ((MEDIA_TYPE_AP not in (request.getHeader("accept") or "")
3977
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
953 and request_type in self.apg.html_redirect)):
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
954 # this is not a AP request, and we have a redirections for it
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
955 kw = {}
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
956 if extra_args:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
957 kw["jid"], kw["node"] = await self.apg.getJIDAndNode(extra_args[0])
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
958 kw["jid_user"] = kw["jid"].user
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
959 if kw["node"] is None:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
960 kw["node"] = self.apg._m.namespace
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
961 if len(extra_args) > 1:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
962 kw["item"] = extra_args[1]
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
963 else:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
964 kw["item"] = ""
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
965 else:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
966 kw["jid"], kw["jid_user"], kw["node"], kw["item"] = "", "", "", ""
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
967
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
968 redirections = self.apg.html_redirect[request_type]
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
969 for redirection in redirections:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
970 filters = redirection["filters"]
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
971 if not filters:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
972 break
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
973 # if we have filter, they must all match
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
974 elif all(v in kw[k] for k,v in filters.items()):
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
975 break
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
976 else:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
977 # no redirection is matching
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
978 redirection = None
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
979
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
980 if redirection is not None:
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
981 kw = {k: parse.quote(str(v), safe="") for k,v in kw.items()}
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
982 target_url = redirection["url"].format(**kw)
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
983 content = web_util.redirectTo(target_url.encode(), request)
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
984 request.write(content)
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
985 request.finish()
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
986 return
6fa4ca0c047e component AP gateway: HTML redirection:
Goffi <goffi@goffi.org>
parents: 3904
diff changeset
987
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
988 if len(extra_args) == 0:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
989 if request_type != "shared_inbox":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
990 raise exceptions.DataError(f"Invalid request type: {request_type!r}")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
991 ret_data = await self.APInboxRequest(
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
992 request, data, None, None, None, ap_url, signing_actor
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
993 )
3821
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
994 elif request_type == "avatar":
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
995 if len(extra_args) != 1:
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
996 raise exceptions.DataError("avatar argument expected in URL")
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
997 avatar_filename = extra_args[0]
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
998 avatar_path = self.apg.host.common_cache.getPath(avatar_filename)
0b1c30ff2cbb component AP: XMPP identity => AP actor data converstion:
Goffi <goffi@goffi.org>
parents: 3807
diff changeset
999 return static.File(str(avatar_path)).render(request)
3846
cc13efdd8360 component AP gateway: return item when `item` URL is used:
Goffi <goffi@goffi.org>
parents: 3844
diff changeset
1000 elif request_type == "item":
cc13efdd8360 component AP gateway: return item when `item` URL is used:
Goffi <goffi@goffi.org>
parents: 3844
diff changeset
1001 ret_data = await self.apg.apGetLocalObject(ap_url)
3904
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
1002 if "@context" not in ret_data:
0aa7023dcd08 component AP gateway: events:
Goffi <goffi@goffi.org>
parents: 3888
diff changeset
1003 ret_data["@context"] = [NS_AP]
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1004 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1005 if len(extra_args) > 1:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1006 log.warning(f"unexpected extra arguments: {extra_args!r}")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1007 ap_account = extra_args[0]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1008 account_jid, node = await self.apg.getJIDAndNode(ap_account)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1009 if request_type not in AP_REQUEST_TYPES.get(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1010 request.method.decode().upper(), []
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1011 ):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1012 raise exceptions.DataError(f"Invalid request type: {request_type!r}")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1013 method = getattr(self, f"AP{request_type.title()}Request")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1014 ret_data = await method(
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1015 request, data, account_jid, node, ap_account, ap_url, signing_actor
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1016 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1017 if ret_data is not None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1018 request.setHeader("content-type", CONTENT_TYPE_AP)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1019 request.write(json.dumps(ret_data).encode())
3881
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
1020 if self.apg.verbose:
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
1021 to_log.append(f"--- RET (code: {request.code})---")
3847
aaa4e7815ba8 component AP gateway: new `verbose` attribute in AP gateway to activate debug logs:
Goffi <goffi@goffi.org>
parents: 3846
diff changeset
1022 if self.apg.verbose>=2:
3881
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
1023 if ret_data is not None:
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
1024 to_log.append(f"{pformat(ret_data)}")
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
1025 to_log.append("---")
2e4a0f6050bd component AP gateway: better verbose logging:
Goffi <goffi@goffi.org>
parents: 3870
diff changeset
1026 log.info("\n".join(to_log))
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1027 request.finish()
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1028
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1029 async def APPostRequest(self, request: "HTTPRequest") -> None:
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1030 try:
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1031 data = json.load(request.content)
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1032 if not isinstance(data, dict):
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1033 log.warning(f"JSON data should be an object (uri={request.uri.decode()})")
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1034 self.responseCode(
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1035 request,
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1036 http.BAD_REQUEST,
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1037 f"invalid body, was expecting a JSON object"
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1038 )
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1039 request.finish()
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1040 return
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1041 except (json.JSONDecodeError, ValueError) as e:
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1042 self.responseCode(
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1043 request,
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1044 http.BAD_REQUEST,
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1045 f"invalid json in inbox request: {e}"
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1046 )
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1047 request.finish()
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1048 return
4005
54a6b44f173b component AP gateway: reset stream position after getting payload:
Goffi <goffi@goffi.org>
parents: 3996
diff changeset
1049 else:
54a6b44f173b component AP gateway: reset stream position after getting payload:
Goffi <goffi@goffi.org>
parents: 3996
diff changeset
1050 request.content.seek(0)
54a6b44f173b component AP gateway: reset stream position after getting payload:
Goffi <goffi@goffi.org>
parents: 3996
diff changeset
1051
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1052 try:
3983
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1053 if data["type"] == "Delete" and data["actor"] == data["object"]:
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1054 # we don't handle actor deletion
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1055 request.setResponseCode(http.ACCEPTED)
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1056 log.debug(f"ignoring actor deletion ({data['actor']})")
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1057 # TODO: clean data in cache coming from this actor, maybe with a tombstone
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1058 request.finish()
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1059 return
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1060 except KeyError:
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1061 pass
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1062
31c3d6652115 component AP gateway: ignore actor delection notifications:
Goffi <goffi@goffi.org>
parents: 3982
diff changeset
1063 try:
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1064 signing_actor = await self.checkSignature(request)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1065 except exceptions.EncryptionError as e:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1066 self.responseCode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1067 request,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1068 http.FORBIDDEN,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1069 f"invalid signature: {e}"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1070 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1071 request.finish()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1072 return
3982
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1073 except Exception as e:
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1074 self.responseCode(
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1075 request,
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1076 http.INTERNAL_SERVER_ERROR,
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1077 f"Can't check signature: {e}"
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1078 )
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1079 request.finish()
74f7c10a48bc component AP gateway: properly close the HTTP connection on `checkSignature` exception:
Goffi <goffi@goffi.org>
parents: 3981
diff changeset
1080 return
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1081
3844
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1082 request.setResponseCode(http.ACCEPTED)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1083
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1084 digest = request.getHeader("digest")
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1085 if digest in self._seen_digest:
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1086 log.debug(f"Ignoring duplicated request (digest: {digest!r})")
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1087 request.finish()
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1088 return
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1089 self._seen_digest.append(digest)
65e5718e7710 component AP gateway: `Announce` activity implementation:
Goffi <goffi@goffi.org>
parents: 3833
diff changeset
1090
3802
983df907d456 component AP gateway: set POST default response code to 202 (accepted)
Goffi <goffi@goffi.org>
parents: 3793
diff changeset
1091 # default response code, may be changed, e.g. in case of exception
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
1092 try:
3981
acc9dfc8ba8d component AP gateway: parse body immediately on `POST` request:
Goffi <goffi@goffi.org>
parents: 3980
diff changeset
1093 return await self.APRequest(request, data, signing_actor)
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
1094 except Exception as e:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
1095 self._onRequestError(failure.Failure(e), request)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1096
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1097 async def checkSigningActor(self, data: dict, signing_actor: str) -> None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1098 """That that signing actor correspond to actor declared in data
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1099
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1100 @param data: request payload
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1101 @param signing_actor: actor ID of the signing entity, as returned by
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1102 checkSignature
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1103 @raise exceptions.NotFound: no actor found in data
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1104 @raise exceptions.EncryptionError: signing actor doesn't match actor in data
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1105 """
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1106 actor = await self.apg.apGetSenderActor(data)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1107
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1108 if signing_actor != actor:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1109 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1110 f"signing actor ({signing_actor}) doesn't match actor in data ({actor})"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1111 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1112
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1113 async def checkSignature(self, request: "HTTPRequest") -> str:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1114 """Check and validate HTTP signature
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1115
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1116 @return: id of the signing actor
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1117
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1118 @raise exceptions.EncryptionError: signature is not present or doesn't match
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1119 """
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1120 signature = request.getHeader("Signature")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1121 if signature is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1122 raise exceptions.EncryptionError("No signature found")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1123 sign_data = {
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1124 m["key"]: m["uq_value"] or m["quoted_value"][1:-1]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1125 for m in RE_SIG_PARAM.finditer(signature)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1126 }
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1127 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1128 key_id = sign_data["keyId"]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1129 except KeyError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1130 raise exceptions.EncryptionError('"keyId" is missing from signature')
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1131 algorithm = sign_data.get("algorithm", HS2019)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1132 signed_headers = sign_data.get(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1133 "headers",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1134 "(created)" if algorithm==HS2019 else "date"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1135 ).lower().split()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1136 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1137 headers_to_check = SIGN_HEADERS[None] + SIGN_HEADERS[request.method]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1138 except KeyError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1139 raise exceptions.InternalError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1140 f"there should be a list of headers for {request.method} method"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1141 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1142 if not headers_to_check:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1143 raise exceptions.InternalError("headers_to_check must not be empty")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1144
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1145 for header in headers_to_check:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1146 if isinstance(header, tuple):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1147 if len(set(header).intersection(signed_headers)) == 0:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1148 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1149 f"at least one of following header must be signed: {header}"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1150 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1151 elif header not in signed_headers:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1152 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1153 f"the {header!r} header must be signed"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1154 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1155
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1156 body = request.content.read()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1157 request.content.seek(0)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1158 headers = {}
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1159 for to_sign in signed_headers:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1160 if to_sign == "(request-target)":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1161 method = request.method.decode().lower()
3884
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1162 uri = request.uri.decode()
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1163 headers[to_sign] = f"{method} /{uri.lstrip('/')}"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1164 elif to_sign in ("(created)", "(expires)"):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1165 if algorithm != HS2019:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1166 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1167 f"{to_sign!r} pseudo-header can only be used with {HS2019} "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1168 "algorithm"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1169 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1170 key = to_sign[1:-1]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1171 value = sign_data.get(key)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1172 if not value:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1173 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1174 "{key!r} parameter is missing from signature"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1175 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1176 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1177 if float(value) < 0:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1178 raise ValueError
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1179 except ValueError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1180 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1181 f"{to_sign} must be a Unix timestamp"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1182 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1183 headers[to_sign] = value
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1184 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1185 value = request.getHeader(to_sign)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1186 if not value:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1187 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1188 f"value of header {to_sign!r} is missing!"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1189 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1190 elif to_sign == "host":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1191 # we check Forwarded/X-Forwarded-Host headers
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1192 # as we need original host if a proxy has modified the header
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1193 forwarded = request.getHeader("forwarded")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1194 if forwarded is not None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1195 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1196 host = [
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1197 f[5:] for f in forwarded.split(";")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1198 if f.startswith("host=")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1199 ][0] or None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1200 except IndexError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1201 host = None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1202 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1203 host = None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1204 if host is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1205 host = request.getHeader("x-forwarded-host")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1206 if host:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1207 value = host
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1208 elif to_sign == "digest":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1209 hashes = {
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1210 algo.lower(): hash_ for algo, hash_ in (
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1211 digest.split("=", 1) for digest in value.split(",")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1212 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1213 }
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1214 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1215 given_digest = hashes["sha-256"]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1216 except KeyError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1217 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1218 "Only SHA-256 algorithm is currently supported for digest"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1219 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1220 __, computed_digest = self.apg.getDigest(body)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1221 if given_digest != computed_digest:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1222 raise exceptions.EncryptionError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1223 f"SHA-256 given and computed digest differ:\n"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1224 f"given: {given_digest!r}\ncomputed: {computed_digest!r}"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1225 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1226 headers[to_sign] = value
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1227
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1228 # date check
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1229 limit_ts = time.time() + SIGN_EXP
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1230 if "(created)" in headers:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1231 created = float(headers["created"])
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1232 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1233 created = date_utils.date_parse(headers["date"])
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1234
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1235
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1236 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1237 expires = float(headers["expires"])
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1238 except KeyError:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1239 pass
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1240 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1241 if expires < created:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1242 log.warning(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1243 f"(expires) [{expires}] set in the past of (created) [{created}] "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1244 "ignoring it according to specs"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1245 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1246 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1247 limit_ts = min(limit_ts, expires)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1248
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1249 if created > limit_ts:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1250 raise exceptions.EncryptionError("Signature has expired")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1251
3884
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1252 try:
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1253 return await self.apg.checkSignature(
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1254 sign_data["signature"],
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1255 key_id,
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1256 headers
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1257 )
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1258 except exceptions.EncryptionError:
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1259 method, url = headers["(request-target)"].rsplit(' ', 1)
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1260 headers["(request-target)"] = f"{method} {parse.unquote(url)}"
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1261 log.debug(
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1262 "Using workaround for (request-target) encoding bug in signature, "
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1263 "see https://github.com/mastodon/mastodon/issues/18871"
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1264 )
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1265 return await self.apg.checkSignature(
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1266 sign_data["signature"],
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1267 key_id,
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1268 headers
cea52400623d component AP gateway: work around encoding bug in Mastodon:
Goffi <goffi@goffi.org>
parents: 3882
diff changeset
1269 )
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1270
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1271 def render(self, request):
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1272 request.setHeader("server", VERSION)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1273 return super().render(request)
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1274
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1275 def render_GET(self, request):
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1276 path = request.path.decode().lstrip("/")
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1277 if path.startswith(".well-known/webfinger"):
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1278 defer.ensureDeferred(self.webfinger(request))
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1279 return server.NOT_DONE_YET
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1280 elif path.startswith(self.apg.ap_path):
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
1281 d = defer.ensureDeferred(self.APRequest(request))
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
1282 d.addErrback(self._onRequestError, request)
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1283 return server.NOT_DONE_YET
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
1284
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1285 return web_resource.NoResource().render(request)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1286
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1287 def render_POST(self, request):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1288 path = request.path.decode().lstrip("/")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1289 if not path.startswith(self.apg.ap_path):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1290 return web_resource.NoResource().render(request)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1291 defer.ensureDeferred(self.APPostRequest(request))
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1292 return server.NOT_DONE_YET
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
1293
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1294
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1295 class HTTPRequest(server.Request):
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1296 pass
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1297
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1298
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1299 class HTTPServer(server.Site):
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1300 requestFactory = HTTPRequest
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1301
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1302 def __init__(self, ap_gateway):
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1303 super().__init__(HTTPAPGServer(ap_gateway))