Can now add domains via manage API / UI

merge-requests/552/head
Eliot Berriot 2019-01-05 18:21:35 +01:00
rodzic b69d9f221b
commit ddffbeadfa
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: DD6965E2476E5C27
6 zmienionych plików z 90 dodań i 5 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
import mimetypes import mimetypes
from os.path import splitext from os.path import splitext
from django.core import validators
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.files.images import get_image_dimensions from django.core.files.images import get_image_dimensions
from django.template.defaultfilters import filesizeformat from django.template.defaultfilters import filesizeformat
@ -150,3 +151,17 @@ class FileValidator(object):
} }
raise ValidationError(message) raise ValidationError(message)
class DomainValidator(validators.URLValidator):
message = "Enter a valid domain name."
def __call__(self, value):
"""
This is a bit hackish but since we don't have any built-in domain validator,
we use the url one, and prepend http:// in front of it.
If it fails, we know the domain is not valid.
"""
super().__call__("http://{}".format(value))
return value

Wyświetl plik

@ -13,6 +13,7 @@ from django.urls import reverse
from funkwhale_api.common import session from funkwhale_api.common import session
from funkwhale_api.common import utils as common_utils from funkwhale_api.common import utils as common_utils
from funkwhale_api.common import validators as common_validators
from funkwhale_api.music import utils as music_utils from funkwhale_api.music import utils as music_utils
from . import utils as federation_utils from . import utils as federation_utils
@ -83,7 +84,11 @@ class DomainQuerySet(models.QuerySet):
class Domain(models.Model): class Domain(models.Model):
name = models.CharField(primary_key=True, max_length=255) name = models.CharField(
primary_key=True,
max_length=255,
validators=[common_validators.DomainValidator()],
)
creation_date = models.DateTimeField(default=timezone.now) creation_date = models.DateTimeField(default=timezone.now)
nodeinfo_fetch_date = models.DateTimeField(default=None, null=True, blank=True) nodeinfo_fetch_date = models.DateTimeField(default=None, null=True, blank=True)
nodeinfo = JSONField(default=empty_dict, max_length=50000, blank=True) nodeinfo = JSONField(default=empty_dict, max_length=50000, blank=True)

Wyświetl plik

@ -98,7 +98,10 @@ class ManageInvitationViewSet(
class ManageDomainViewSet( class ManageDomainViewSet(
mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet,
): ):
lookup_value_regex = r"[a-zA-Z0-9\-\.]+" lookup_value_regex = r"[a-zA-Z0-9\-\.]+"
queryset = ( queryset = (

Wyświetl plik

@ -1,3 +1,5 @@
import pytest
from funkwhale_api.manage import serializers from funkwhale_api.manage import serializers
@ -53,6 +55,13 @@ def test_manage_domain_serializer(factories, now):
assert s.data == expected assert s.data == expected
def test_manage_domain_serializer_validates_hostname(db):
s = serializers.ManageDomainSerializer(data={"name": "hello world"})
with pytest.raises(serializers.serializers.ValidationError):
s.is_valid(raise_exception=True)
def test_manage_actor_serializer(factories, now): def test_manage_actor_serializer(factories, now):
actor = factories["federation.Actor"]() actor = factories["federation.Actor"]()
setattr(actor, "uploads_count", 66) setattr(actor, "uploads_count", 66)

Wyświetl plik

@ -1,6 +1,7 @@
import pytest import pytest
from django.urls import reverse from django.urls import reverse
from funkwhale_api.federation import models as federation_models
from funkwhale_api.federation import tasks as federation_tasks from funkwhale_api.federation import tasks as federation_tasks
from funkwhale_api.manage import serializers, views from funkwhale_api.manage import serializers, views
@ -90,6 +91,14 @@ def test_domain_detail(factories, superuser_api_client):
assert response.data["name"] == d.pk assert response.data["name"] == d.pk
def test_domain_create(superuser_api_client):
url = reverse("api:v1:manage:federation:domains-list")
response = superuser_api_client.post(url, {"name": "test.federation"})
assert response.status_code == 201
assert federation_models.Domain.objects.filter(pk="test.federation").exists()
def test_domain_nodeinfo(factories, superuser_api_client, mocker): def test_domain_nodeinfo(factories, superuser_api_client, mocker):
domain = factories["federation.Domain"]() domain = factories["federation.Domain"]()
url = reverse( url = reverse(

Wyświetl plik

@ -1,26 +1,70 @@
<template> <template>
<main v-title="labels.domains"> <main v-title="labels.domains">
<section class="ui vertical stripe segment"> <section class="ui vertical stripe segment">
<h2 class="ui header"><translate>Domains</translate></h2> <h2 class="ui left floated header"><translate>Domains</translate></h2>
<div class="ui hidden divider"></div> <form class="ui right floated form" @submit.prevent="createDomain">
<div v-if="errors && errors.length > 0" class="ui negative message">
<div class="header"><translate>Error while creating domain</translate></div>
<ul class="list">
<li v-for="error in errors">{{ error }}</li>
</ul>
</div>
<div class="inline fields">
<div class="field">
<label for="domain"><translate>Add a domain</translate></label>
<input type="text" id="domain" v-model="domainName">
</div>
<div class="field">
<button :class="['ui', {'loading': isCreating}, 'green', 'button']" type="submit" :disabled="isCreating">
<label for="domain"><translate>Add</translate></label>
</button>
</div>
</div>
</form>
<div class="ui clearing hidden divider"></div>
<domains-table></domains-table> <domains-table></domains-table>
</section> </section>
</main> </main>
</template> </template>
<script> <script>
import DomainsTable from "@/components/manage/moderation/DomainsTable" import axios from 'axios'
import DomainsTable from "@/components/manage/moderation/DomainsTable"
export default { export default {
components: { components: {
DomainsTable DomainsTable
}, },
data () {
return {
domainName: '',
isCreating: false,
errors: []
}
},
computed: { computed: {
labels() { labels() {
return { return {
domains: this.$gettext("Domains") domains: this.$gettext("Domains")
} }
} }
},
methods: {
createDomain () {
let self = this
this.isCreating = true
this.errors = []
axios.post('manage/federation/domains/', {name: this.domainName}).then((response) => {
this.isCreating = false
this.$router.push({
name: "manage.moderation.domains.detail",
params: {'id': response.data.name}
})
}, (error) => {
self.isCreating = false
self.errors = error.backendErrors
})
}
} }
} }
</script> </script>