takahe/users/models/system_actor.py

75 lines
2.3 KiB
Python

from typing import Literal
from django.conf import settings
from core.models import Config
from core.signatures import HttpSignature, RsaKeys
class SystemActor:
"""
Represents the system actor, that we use to sign all HTTP requests
that are not on behalf of an Identity.
Note that this needs Config.system to be set to be initialised.
"""
def __init__(self):
self.private_key = Config.system.system_actor_private_key
self.public_key = Config.system.system_actor_public_key
self.actor_uri = f"https://{settings.MAIN_DOMAIN}/actor/"
self.public_key_id = self.actor_uri + "#main-key"
self.profile_uri = f"https://{settings.MAIN_DOMAIN}/about/"
self.username = "__system__"
def absolute_profile_uri(self):
return self.profile_uri
def generate_keys(self):
self.private_key, self.public_key = RsaKeys.generate_keypair()
Config.set_system("system_actor_private_key", self.private_key)
Config.set_system("system_actor_public_key", self.public_key)
@classmethod
def generate_keys_if_needed(cls):
# Load the system config into the right place
Config.system = Config.load_system()
instance = cls()
if "-----BEGIN" not in instance.private_key:
instance.generate_keys()
def to_ap(self):
return {
"id": self.actor_uri,
"type": "Application",
"inbox": self.actor_uri + "inbox/",
"endpoints": {
"sharedInbox": f"https://{settings.MAIN_DOMAIN}/inbox/",
},
"preferredUsername": self.username,
"url": self.profile_uri,
"as:manuallyApprovesFollowers": True,
"publicKey": {
"id": self.public_key_id,
"owner": self.actor_uri,
"publicKeyPem": self.public_key,
},
}
async def signed_request(
self,
method: Literal["get", "post"],
uri: str,
body: dict | None = None,
):
"""
Performs a signed request on behalf of the System Actor.
"""
return await HttpSignature.signed_request(
method=method,
uri=uri,
body=body,
private_key=self.private_key,
key_id=self.public_key_id,
)