Can now serve track from remote library
This commit is contained in:
parent
b29ca44797
commit
9612b1bace
22 changed files with 270 additions and 138 deletions
|
|
@ -58,21 +58,12 @@ OBJECT_TYPES = [
|
|||
'Video',
|
||||
] + ACTIVITY_TYPES
|
||||
|
||||
|
||||
def deliver(activity, on_behalf_of, to=[]):
|
||||
from . import actors
|
||||
logger.info('Preparing activity delivery to %s', to)
|
||||
auth = requests_http_signature.HTTPSignatureAuth(
|
||||
use_auth_header=False,
|
||||
headers=[
|
||||
'(request-target)',
|
||||
'user-agent',
|
||||
'host',
|
||||
'date',
|
||||
'content-type',],
|
||||
algorithm='rsa-sha256',
|
||||
key=on_behalf_of.private_key.encode('utf-8'),
|
||||
key_id=on_behalf_of.private_key_id,
|
||||
)
|
||||
auth = signing.get_auth(
|
||||
on_behalf_of.private_key, on_behalf_of.private_key_id)
|
||||
for url in to:
|
||||
recipient_actor = actors.get_actor(url)
|
||||
logger.debug('delivering to %s', recipient_actor.inbox_url)
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ from rest_framework.exceptions import PermissionDenied
|
|||
from dynamic_preferences.registries import global_preferences_registry
|
||||
|
||||
from . import activity
|
||||
from . import keys
|
||||
from . import models
|
||||
from . import serializers
|
||||
from . import signing
|
||||
from . import utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -51,24 +53,37 @@ class SystemActor(object):
|
|||
additional_attributes = {}
|
||||
manually_approves_followers = False
|
||||
|
||||
def get_request_auth(self):
|
||||
actor = self.get_actor_instance()
|
||||
return signing.get_auth(
|
||||
actor.private_key, actor.private_key_id)
|
||||
|
||||
def serialize(self):
|
||||
actor = self.get_actor_instance()
|
||||
serializer = serializers.ActorSerializer(actor)
|
||||
return serializer.data
|
||||
|
||||
def get_actor_instance(self):
|
||||
try:
|
||||
return models.Actor.objects.get(url=self.get_actor_url())
|
||||
except models.Actor.DoesNotExist:
|
||||
pass
|
||||
private, public = keys.get_key_pair()
|
||||
args = self.get_instance_argument(
|
||||
self.id,
|
||||
name=self.name,
|
||||
summary=self.summary,
|
||||
**self.additional_attributes
|
||||
)
|
||||
url = args.pop('url')
|
||||
a, created = models.Actor.objects.get_or_create(
|
||||
url=url,
|
||||
defaults=args,
|
||||
)
|
||||
return a
|
||||
args['private_key'] = private.decode('utf-8')
|
||||
args['public_key'] = public.decode('utf-8')
|
||||
return models.Actor.objects.create(**args)
|
||||
|
||||
def get_actor_url(self):
|
||||
return utils.full_url(
|
||||
reverse(
|
||||
'federation:instance-actors-detail',
|
||||
kwargs={'actor': self.id}))
|
||||
|
||||
def get_instance_argument(self, id, name, summary, **kwargs):
|
||||
preferences = global_preferences_registry.manager()
|
||||
|
|
@ -78,10 +93,7 @@ class SystemActor(object):
|
|||
'type': 'Person',
|
||||
'name': name.format(host=settings.FEDERATION_HOSTNAME),
|
||||
'manually_approves_followers': True,
|
||||
'url': utils.full_url(
|
||||
reverse(
|
||||
'federation:instance-actors-detail',
|
||||
kwargs={'actor': id})),
|
||||
'url': self.get_actor_url(),
|
||||
'shared_inbox_url': utils.full_url(
|
||||
reverse(
|
||||
'federation:instance-actors-inbox',
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ class SignatureAuthentication(authentication.BaseAuthentication):
|
|||
def authenticate(self, request):
|
||||
setattr(request, 'actor', None)
|
||||
actor = self.authenticate_actor(request)
|
||||
if not actor:
|
||||
return
|
||||
user = AnonymousUser()
|
||||
setattr(request, 'actor', actor)
|
||||
return (user, None)
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import transaction
|
||||
|
||||
from dynamic_preferences.registries import global_preferences_registry
|
||||
|
||||
from funkwhale_api.federation import keys
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = (
|
||||
'Generate a public/private key pair for your instance,'
|
||||
' for federation purposes. If a key pair already exists, does nothing.'
|
||||
)
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--replace',
|
||||
action='store_true',
|
||||
dest='replace',
|
||||
default=False,
|
||||
help='Replace existing key pair, if any',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--noinput', '--no-input', action='store_false', dest='interactive',
|
||||
help="Do NOT prompt the user for input of any kind.",
|
||||
)
|
||||
|
||||
@transaction.atomic
|
||||
def handle(self, *args, **options):
|
||||
preferences = global_preferences_registry.manager()
|
||||
existing_public = preferences['federation__public_key']
|
||||
existing_private = preferences['federation__public_key']
|
||||
|
||||
if existing_public or existing_private and not options['replace']:
|
||||
raise CommandError(
|
||||
'Keys are already present! '
|
||||
'Replace them with --replace if you know what you are doing.')
|
||||
|
||||
if options['interactive']:
|
||||
message = (
|
||||
'Are you sure you want to do this?\n\n'
|
||||
"Type 'yes' to continue, or 'no' to cancel: "
|
||||
)
|
||||
if input(''.join(message)) != 'yes':
|
||||
raise CommandError("Operation cancelled.")
|
||||
private, public = keys.get_key_pair()
|
||||
preferences['federation__public_key'] = public.decode('utf-8')
|
||||
preferences['federation__private_key'] = private.decode('utf-8')
|
||||
|
||||
self.stdout.write(
|
||||
'Your new key pair was generated.'
|
||||
'Your public key is now:\n\n{}'.format(public.decode('utf-8'))
|
||||
)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 2.0.3 on 2018-04-07 08:52
|
||||
# Generated by Django 2.0.3 on 2018-04-07 10:10
|
||||
|
||||
import django.contrib.postgres.fields.jsonb
|
||||
from django.db import migrations, models
|
||||
|
|
@ -10,7 +10,6 @@ import uuid
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('music', '0022_importbatch_import_request'),
|
||||
('federation', '0002_auto_20180403_1620'),
|
||||
]
|
||||
|
||||
|
|
@ -70,7 +69,6 @@ class Migration(migrations.Migration):
|
|||
('title', models.CharField(max_length=500)),
|
||||
('metadata', django.contrib.postgres.fields.jsonb.JSONField(default={}, max_length=10000)),
|
||||
('library', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tracks', to='federation.Library')),
|
||||
('local_track_file', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='library_track', to='music.TrackFile')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
|
|
@ -192,13 +192,6 @@ class LibraryTrack(models.Model):
|
|||
published_date = models.DateTimeField(null=True, blank=True)
|
||||
library = models.ForeignKey(
|
||||
Library, related_name='tracks', on_delete=models.CASCADE)
|
||||
local_track_file = models.OneToOneField(
|
||||
'music.TrackFile',
|
||||
related_name='library_track',
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
artist_name = models.CharField(max_length=500)
|
||||
album_title = models.CharField(max_length=500)
|
||||
title = models.CharField(max_length=500)
|
||||
|
|
|
|||
|
|
@ -53,3 +53,18 @@ def verify_django(django_request, public_key):
|
|||
request.headers[h] = str(v)
|
||||
prepared_request = request.prepare()
|
||||
return verify(request, public_key)
|
||||
|
||||
|
||||
def get_auth(private_key, private_key_id):
|
||||
return requests_http_signature.HTTPSignatureAuth(
|
||||
use_auth_header=False,
|
||||
headers=[
|
||||
'(request-target)',
|
||||
'user-agent',
|
||||
'host',
|
||||
'date',
|
||||
'content-type'],
|
||||
algorithm='rsa-sha256',
|
||||
key=private_key.encode('utf-8'),
|
||||
key_id=private_key_id,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue