Skip to content
Snippets Groups Projects
Verified Commit ddffbead authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Can now add domains via manage API / UI

parent b69d9f22
No related branches found
No related tags found
No related merge requests found
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): ...@@ -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
...@@ -13,6 +13,7 @@ from django.urls import reverse ...@@ -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): ...@@ -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)
......
...@@ -98,7 +98,10 @@ class ManageInvitationViewSet( ...@@ -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 = (
......
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): ...@@ -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)
......
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): ...@@ -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(
......
<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>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment