[doc] show done?
This commit is contained in:
parent
a49cec70b2
commit
33f9218a8d
1 changed files with 174 additions and 11 deletions
185
docs/show.org
185
docs/show.org
|
@ -88,7 +88,7 @@ ME = {
|
|||
"sharedInbox": config.BASE_URL + "/inbox",
|
||||
},
|
||||
"url": config.ID + "/", # Important for Mastodon
|
||||
"manuallyApprovesFollowers": False,
|
||||
"manuallyApprovesFollowers": config.MANUALLY_APPROVES_FOLLOWERS,
|
||||
"attachment": [],
|
||||
"icon": {
|
||||
"mediaType": "image/png",
|
||||
|
@ -118,7 +118,6 @@ def locate_user() -> Response:
|
|||
GET http://coscup.localhost/user/show
|
||||
#+end_src
|
||||
|
||||
|
||||
** WebFinger
|
||||
#+begin_src python
|
||||
from flask import Flask, abort, request, Response, jsonify
|
||||
|
@ -163,9 +162,7 @@ def wellknown_webfinger() -> Response:
|
|||
GET http://coscup.localhost/.well-known/webfinger?resource=acct:show@coscup.localhost
|
||||
#+end_src
|
||||
|
||||
|
||||
** HTTP Signature
|
||||
|
||||
other.localhost --Follow-> coscup.localhost
|
||||
|
||||
#+begin_src json
|
||||
|
@ -174,7 +171,7 @@ other.localhost --Follow-> coscup.localhost
|
|||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": "http://other.localhost/9ef8847d72434cff82254f36ff88e710",
|
||||
"type": "Follow",
|
||||
"actor": "http://other.localhost",
|
||||
"actor": "http://other.localhost/accounts/other",
|
||||
"object": "http://coscup.localhost/meow/show"
|
||||
}
|
||||
|
||||
|
@ -205,15 +202,14 @@ def parse_signature(
|
|||
detail[name.lower()] = value
|
||||
signature_details = {
|
||||
"headers": detail["headers"].split(),
|
||||
"signature": (detail["signature"]),
|
||||
"signature": detail["signature"],
|
||||
"algorithm": detail["algorithm"],
|
||||
"keyid": detail["keyid"],
|
||||
}
|
||||
return signature_details
|
||||
#+end_src
|
||||
|
||||
|
||||
parse_signature(headers["signature"])
|
||||
parsed_signature = parse_signature(headers["signature"])
|
||||
#+begin_src json
|
||||
{"algorithm": "rsa-sha256",
|
||||
"headers": ["(request-target)", "user-agent", "host", "date", "digest", "content-type"],
|
||||
|
@ -221,7 +217,6 @@ parse_signature(headers["signature"])
|
|||
"signature": "irioDQuhYstSvafpl6DW4d31wDPRiTv7MZGyBo3j4kkc2TrfOweH3WRMMnoaWwl4LAI2WYLoKefeQpOg7Rm7ZEffsoLOzZvgdWJBm8lnOEgieyy5l2Vq1mlcS2PRJCisYGdzAwFOBkcHk0WKAZXvs1ieRV34NHfM8JF+DjrCBTZ/U9LyxULBwC6tPQTh9tflCOwXZOzXUq17C+2Uzsr8h4tDHjbmrG7OAcvYiPeOUKaP+InoE6j9ViHllhidNCPL0y8b1c7c72ruN48kF42OfyfUeiuCcuLwdp8eYBlTdG/ZsT2YXyKruwim3tTD1TtyW4Vfll+F/4/1RfWHsc9LrQ=="}
|
||||
#+end_src
|
||||
|
||||
|
||||
#+begin_src python
|
||||
import base64
|
||||
from Crypto.Hash import SHA256
|
||||
|
@ -254,16 +249,17 @@ def build_signature_string(
|
|||
return "\n".join(sign_str)
|
||||
|
||||
|
||||
build_signature_string(
|
||||
signature_string = build_signature_string(
|
||||
request.method # "post"
|
||||
request.path # "/inbox"
|
||||
parse_signature(headers["signature"])["headers"], # ["(request-target)", "user-agent", "host", "date", "digest", "content-type"]
|
||||
parsed_signature["headers"], # ["(request-target)", "user-agent", "host", "date", "digest", "content-type"]
|
||||
calculate_digest(request.data),
|
||||
headers,
|
||||
)
|
||||
|
||||
#+end_src
|
||||
|
||||
signature_string
|
||||
#+begin_quote
|
||||
(request-target): post /inbox
|
||||
user-agent: something/fediverse+app
|
||||
|
@ -272,3 +268,170 @@ date: Tue, 11 Jul 2023 04:21:11 GMT
|
|||
digest: SHA-256=WzNniTyRBcZpgK7a6zYJBgsdKIQmFEPPfysh/ZzKb2o=
|
||||
content-type: application/activity+json
|
||||
#+end_quote
|
||||
|
||||
#+begin_src python
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.Signature import PKCS1_v1_5
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
def verify_signature(
|
||||
signature_string: str,
|
||||
signature: bytes, # base64.b64decode(parsed_signature["signature"])
|
||||
pubkey: str,
|
||||
) -> bool :
|
||||
pubkey = RSA.importKey(pubkey)
|
||||
signer = PKCS1_v1_5.new(pubkey)
|
||||
digest = SHA256.new()
|
||||
digest.update(signature_string.encode("utf-8"))
|
||||
return signer.verify(digest, signature)
|
||||
#+end_src
|
||||
|
||||
** Activity!
|
||||
*** Follow / Accept
|
||||
other.localhost --Follow-> coscup.localhost
|
||||
#+begin_src json
|
||||
{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": "http://other.localhost/9ef8847d72434cff82254f36ff88e710",
|
||||
"type": "Follow",
|
||||
"actor": "http://other.localhost/accounts/other",
|
||||
"object": "http://coscup.localhost/meow/show"
|
||||
}
|
||||
#+end_src
|
||||
|
||||
#+begin_src python
|
||||
def _process_inbox_request(...):
|
||||
...
|
||||
actor = feact_actor(ap_object["actor"])
|
||||
...
|
||||
if "Follow" == ap_object["type"]:
|
||||
if _handle_follow(actor, ap_object):
|
||||
...
|
||||
elif "Create" == ap_object["type"]:
|
||||
if _handle_create(ap_object):
|
||||
...
|
||||
|
||||
|
||||
def _handle_follow(...):
|
||||
if ME["id"] != ap_object["object"]:
|
||||
logger.warning("wrong follow object!" + .ap_object["id"])
|
||||
return False
|
||||
|
||||
if MANUALLY_APPROVES_FOLLOWERS:
|
||||
save_follow_request(ap_object)
|
||||
return True
|
||||
|
||||
_send_accept(actor, ap_object)
|
||||
save_follower()
|
||||
return True
|
||||
|
||||
|
||||
async def _send_accept(...) -> None :
|
||||
reply_id = BASE_URL + str(uuid.uuid4())
|
||||
|
||||
actor_url = actor["inbox"]
|
||||
payload = {
|
||||
"@context": AS_CTX,
|
||||
"id": reply_id,
|
||||
"type": "Accept",
|
||||
"actor": ID, # http://coscup.localhost/user/show
|
||||
"object": ap_object["id"], # http://other.localhost/9ef8847d72434cff82254f36ff88e710
|
||||
}
|
||||
|
||||
post(actor_url, payload)
|
||||
#+end_src
|
||||
|
||||
*** Creat!
|
||||
#+begin_src json
|
||||
{
|
||||
"@context" : [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"Emoji" : "toot:Emoji",
|
||||
"atomUri" : "ostatus:atomUri",
|
||||
"conversation" : "ostatus:conversation",
|
||||
"focalPoint" : {
|
||||
"@container" : "@list",
|
||||
"@id" : "toot:focalPoint"
|
||||
},
|
||||
"inReplyToAtomUri" : "ostatus:inReplyToAtomUri",
|
||||
"ostatus" : "http://ostatus.org#",
|
||||
"sensitive" : "as:sensitive",
|
||||
"toot" : "http://joinmastodon.org/ns#",
|
||||
"votersCount" : "toot:votersCount"
|
||||
}
|
||||
],
|
||||
"type":"Create",
|
||||
"published" : "2023-07-13T16:04:57Z",
|
||||
"cc" : ["http://coscup.localhost/users/show/followers"],
|
||||
"to" : ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"id" : "http://coscup.localhost/79d42b46-aa2f-4837-835a-5f75ce9a253f",
|
||||
"object": {
|
||||
"attributedTo" : "http://coscup.localhost/user/show",
|
||||
"cc" : ["http://coscup.localhost/users/show/followers"],
|
||||
"to" : ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"id" : "http://coscup.localhost/79d42b46-aa2f-4837-835a-5f75ce9a253f",
|
||||
"content" : "<p>Hello World!</p>",
|
||||
"inReplyTo" : null,
|
||||
"published" : "2023-07-13T16:04:57Z",
|
||||
"sensitive" : false,
|
||||
"summary" : null,
|
||||
"tag" : [],
|
||||
"type" : "Note",
|
||||
"url" : "http://coscup.localhost/79d42b46-aa2f-4837-835a-5f75ce9a253f"
|
||||
},
|
||||
}
|
||||
#+end_src
|
||||
|
||||
#+begin_src python
|
||||
def _send_create(...):
|
||||
object_id = BASE_URL + str(uuid.uuid4())
|
||||
to = []
|
||||
cc = []
|
||||
if visibility == "public":
|
||||
to = [ap.AS_PUBLIC]
|
||||
cc = [f"{BASE_URL}/followers"]
|
||||
else:
|
||||
raise ValueError(f"Unsupport visibility {visibility}")
|
||||
|
||||
ap_object = {
|
||||
"type": "Note",
|
||||
"id": object_id,
|
||||
"attributedTo": ID,
|
||||
"content": content,
|
||||
"to": to,
|
||||
"cc": cc,
|
||||
"published": published,
|
||||
"url": object_id,
|
||||
"tag": [],
|
||||
"content": content, # <p>Hello World!<p>
|
||||
"summary": summary,
|
||||
"inReplyTo": reply_id,
|
||||
"sensitive": sensitive,
|
||||
"attachment": [],
|
||||
}
|
||||
|
||||
recipients = set()
|
||||
for actor in get_followers():
|
||||
recipients.add(actor.sharedInbox or actor.inbox_url)
|
||||
|
||||
ap_object = wrap_ap_object(ap_object)
|
||||
|
||||
for inbox_url in recipients:
|
||||
post(inbox_url, ap_object,)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def wrap_ap_object(...):
|
||||
return {
|
||||
"@context": AS_EXTENDED_CTX,
|
||||
"actor": config.ID,
|
||||
"to": ap_object.get("to", []),
|
||||
"cc": ap_object.get("cc", []),
|
||||
"id": ap_object["id"],
|
||||
"object": ap_object,
|
||||
"published": now()
|
||||
"type": "Create",
|
||||
}
|
||||
#+end_src
|
||||
|
|
Loading…
Reference in a new issue