80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
|
import base64
|
||
|
import uuid
|
||
|
from functools import partial
|
||
|
|
||
|
import urlman
|
||
|
from cryptography.hazmat.primitives import serialization
|
||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||
|
from django.conf import settings
|
||
|
from django.db import models
|
||
|
from django.utils import timezone
|
||
|
|
||
|
|
||
|
def upload_namer(prefix, instance, filename):
|
||
|
"""
|
||
|
Names uploaded images etc.
|
||
|
"""
|
||
|
now = timezone.now()
|
||
|
filename = base64.b32encode(uuid.uuid4().bytes).decode("ascii")
|
||
|
return f"{prefix}/{now.year}/{now.month}/{now.day}/{filename}"
|
||
|
|
||
|
|
||
|
class Identity(models.Model):
|
||
|
"""
|
||
|
Represents both local and remote Fediverse identities (actors)
|
||
|
"""
|
||
|
|
||
|
# The handle includes the domain!
|
||
|
handle = models.CharField(max_length=500, unique=True)
|
||
|
name = models.CharField(max_length=500, blank=True, null=True)
|
||
|
bio = models.TextField(blank=True, null=True)
|
||
|
|
||
|
profile_image = models.ImageField(upload_to=partial(upload_namer, "profile_images"))
|
||
|
background_image = models.ImageField(
|
||
|
upload_to=partial(upload_namer, "background_images")
|
||
|
)
|
||
|
|
||
|
local = models.BooleanField()
|
||
|
users = models.ManyToManyField("users.User", related_name="identities")
|
||
|
private_key = models.TextField(null=True, blank=True)
|
||
|
public_key = models.TextField(null=True, blank=True)
|
||
|
|
||
|
created = models.DateTimeField(auto_now_add=True)
|
||
|
updated = models.DateTimeField(auto_now=True)
|
||
|
deleted = models.DateTimeField(null=True, blank=True)
|
||
|
|
||
|
@property
|
||
|
def short_handle(self):
|
||
|
if self.handle.endswith("@" + settings.DEFAULT_DOMAIN):
|
||
|
return self.handle.split("@", 1)[0]
|
||
|
return self.handle
|
||
|
|
||
|
@property
|
||
|
def domain(self):
|
||
|
return self.handle.split("@", 1)[1]
|
||
|
|
||
|
def generate_keypair(self):
|
||
|
private_key = rsa.generate_private_key(
|
||
|
public_exponent=65537,
|
||
|
key_size=2048,
|
||
|
)
|
||
|
self.private_key = private_key.private_bytes(
|
||
|
encoding=serialization.Encoding.PEM,
|
||
|
format=serialization.PrivateFormat.PKCS8,
|
||
|
encryption_algorithm=serialization.NoEncryption(),
|
||
|
)
|
||
|
self.public_key = private_key.public_key().public_bytes(
|
||
|
encoding=serialization.Encoding.PEM,
|
||
|
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
||
|
)
|
||
|
self.save()
|
||
|
|
||
|
def __str__(self):
|
||
|
return self.name or self.handle
|
||
|
|
||
|
class urls(urlman.Urls):
|
||
|
view = "/@{self.short_handle}/"
|
||
|
actor = "{view}actor/"
|
||
|
inbox = "{actor}inbox/"
|
||
|
activate = "{view}activate/"
|