2018-04-27 22:25:47 +00:00
|
|
|
import datetime
|
2018-04-02 16:07:46 +00:00
|
|
|
import logging
|
2018-03-31 13:47:21 +00:00
|
|
|
|
|
|
|
from django.conf import settings
|
2018-04-02 16:07:46 +00:00
|
|
|
from django.utils import timezone
|
2018-04-01 20:11:46 +00:00
|
|
|
|
2018-06-10 08:55:16 +00:00
|
|
|
from funkwhale_api.common import preferences, session
|
2019-01-30 10:54:43 +00:00
|
|
|
from funkwhale_api.users import models as users_models
|
2018-04-07 14:20:34 +00:00
|
|
|
|
2019-01-30 10:54:43 +00:00
|
|
|
from . import keys, models, serializers
|
2018-03-31 13:47:21 +00:00
|
|
|
|
2018-04-02 16:07:46 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2018-03-31 13:47:21 +00:00
|
|
|
|
|
|
|
def get_actor_data(actor_url):
|
2020-08-24 11:43:31 +00:00
|
|
|
logger.debug("Fetching actor %s", actor_url)
|
2018-04-07 14:20:34 +00:00
|
|
|
response = session.get_session().get(
|
2022-01-09 11:40:49 +00:00
|
|
|
actor_url,
|
|
|
|
headers={"Accept": "application/activity+json"},
|
2018-03-31 16:41:35 +00:00
|
|
|
)
|
2018-03-31 13:47:21 +00:00
|
|
|
response.raise_for_status()
|
2018-03-31 16:41:35 +00:00
|
|
|
try:
|
|
|
|
return response.json()
|
2018-06-10 10:06:46 +00:00
|
|
|
except Exception:
|
2022-11-23 21:36:56 +00:00
|
|
|
raise ValueError(f"Invalid actor payload: {response.text}")
|
2018-03-31 13:47:21 +00:00
|
|
|
|
2018-04-08 11:33:36 +00:00
|
|
|
|
2019-01-11 10:04:11 +00:00
|
|
|
def get_actor(fid, skip_cache=False):
|
|
|
|
if not skip_cache:
|
|
|
|
try:
|
2019-01-30 10:54:43 +00:00
|
|
|
actor = models.Actor.objects.select_related().get(fid=fid)
|
2019-01-11 10:04:11 +00:00
|
|
|
except models.Actor.DoesNotExist:
|
|
|
|
actor = None
|
|
|
|
fetch_delta = datetime.timedelta(
|
|
|
|
minutes=preferences.get("federation__actor_fetch_delay")
|
|
|
|
)
|
|
|
|
if actor and actor.last_fetch_date > timezone.now() - fetch_delta:
|
|
|
|
# cache is hot, we can return as is
|
|
|
|
return actor
|
2018-09-06 18:35:02 +00:00
|
|
|
data = get_actor_data(fid)
|
2018-04-02 16:07:46 +00:00
|
|
|
serializer = serializers.ActorSerializer(data=data)
|
|
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
|
2018-04-27 22:25:47 +00:00
|
|
|
return serializer.save(last_fetch_date=timezone.now())
|
2019-01-30 10:54:43 +00:00
|
|
|
|
|
|
|
|
2020-03-13 11:16:51 +00:00
|
|
|
_CACHE = {}
|
|
|
|
|
|
|
|
|
|
|
|
def get_service_actor(cache=True):
|
|
|
|
if cache and "service_actor" in _CACHE:
|
|
|
|
return _CACHE["service_actor"]
|
|
|
|
|
2019-01-30 10:54:43 +00:00
|
|
|
name, domain = (
|
|
|
|
settings.FEDERATION_SERVICE_ACTOR_USERNAME,
|
|
|
|
settings.FEDERATION_HOSTNAME,
|
|
|
|
)
|
|
|
|
try:
|
2020-03-13 11:16:51 +00:00
|
|
|
actor = models.Actor.objects.select_related().get(
|
2019-01-30 10:54:43 +00:00
|
|
|
preferred_username=name, domain__name=domain
|
|
|
|
)
|
|
|
|
except models.Actor.DoesNotExist:
|
|
|
|
pass
|
2020-03-13 11:16:51 +00:00
|
|
|
else:
|
|
|
|
_CACHE["service_actor"] = actor
|
|
|
|
return actor
|
2019-01-30 10:54:43 +00:00
|
|
|
|
|
|
|
args = users_models.get_actor_data(name)
|
|
|
|
private, public = keys.get_key_pair()
|
|
|
|
args["private_key"] = private.decode("utf-8")
|
|
|
|
args["public_key"] = public.decode("utf-8")
|
|
|
|
args["type"] = "Service"
|
2020-03-13 11:16:51 +00:00
|
|
|
actor = models.Actor.objects.create(**args)
|
|
|
|
_CACHE["service_actor"] = actor
|
|
|
|
return actor
|