summaryrefslogtreecommitdiffstats
path: root/users/models/system_actor.py
blob: fb5a9e110c2b1b7431b416ebe5dbb699f795f991 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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,
        )