add hostadmin app

This commit is contained in:
j3d1 2023-06-15 20:55:33 +02:00
parent 12191369b7
commit 3cd89b7162
13 changed files with 143 additions and 38 deletions

2
.gitignore vendored
View file

@ -127,3 +127,5 @@ dmypy.json
# Pyre type checker
.pyre/
staticfiles/

View file

@ -11,6 +11,7 @@ from rest_framework.response import Response
from authentication.models import ToolshedUser
from authentication.signature_auth import SignatureAuthenticationLocal
from hostadmin.models import Domain
router = routers.SimpleRouter()
@ -68,33 +69,35 @@ def getUserInfo(request):
@permission_classes([])
@authentication_classes([])
def registerUser(request):
username = request.data.get('username')
domain = request.data.get('domain')
password = request.data.get('password')
email = request.data.get('email')
try:
username = request.data.get('username')
domain = request.data.get('domain')
password = request.data.get('password')
email = request.data.get('email')
errors = {}
if not username:
errors['username'] = 'Username is required'
if not domain:
errors['domain'] = 'Domain is required'
if not password:
errors['password'] = 'Password is required'
if not email:
errors['email'] = 'Email is required'
if ToolshedUser.objects.filter(email=email).exists():
errors['email'] = 'Email already exists'
if ToolshedUser.objects.filter(username=username, domain=domain).exists():
errors['username'] = 'Username already exists'
if errors:
return Response({'errors': errors}, status=400)
errors = {}
if not username:
errors['username'] = 'Username is required'
if not domain:
errors['domain'] = 'Domain is required'
if not password:
errors['password'] = 'Password is required'
if not email:
errors['email'] = 'Email is required'
if ToolshedUser.objects.filter(email=email).exists():
errors['email'] = 'Email already exists'
if ToolshedUser.objects.filter(username=username, domain=domain).exists():
errors['username'] = 'Username already exists'
if errors:
return Response({'errors': errors}, status=400)
Domain.objects.get(name=domain, open_registration=True)
if domain in ['localhost']:
user = ToolshedUser.objects.create_user(username, email, '', domain=domain)
user.set_password(password)
user.save()
return Response({'username': user.username, 'domain': user.domain})
else:
except Domain.DoesNotExist:
return Response({'errors': {'domain': 'Domain does not exist or is not open for registration'}}, status=400)

View file

@ -4,6 +4,7 @@ from django.test import TestCase, Client
from nacl.encoding import HexEncoder
from authentication.models import ToolshedUser, KnownIdentity
from hostadmin.models import Domain
from nacl.signing import SigningKey
@ -73,7 +74,8 @@ class UserTestCase(TestCase):
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
admin.set_password('testpassword')
admin.save()
example_com = type('obj', (object,), {'name': 'example.com'})
example_com = Domain.objects.create(name='example.com', owner=admin, open_registration=True)
example_com.save()
self.local_user1 = ToolshedUser.objects.create_user('testuser', 'test@abc.de', '', domain=example_com.name)
self.local_user1.set_password('testpassword2')
self.local_user1.save()

View file

@ -4,6 +4,7 @@ from nacl.signing import SigningKey
from authentication.models import ToolshedUser, KnownIdentity
from authentication.tests import UserTestCase, SignatureAuthClient
from hostadmin.models import Domain
class KnownIdentityTestCase(TestCase):
@ -85,7 +86,7 @@ class UserModelTestCase(UserTestCase):
def test_create_existing_user(self):
with self.assertRaises(ValueError):
ToolshedUser.objects.create_user('testuser', 'test3@abc.de', '', domain='localhost')
ToolshedUser.objects.create_user('testuser', 'test3@abc.de', '', domain='example.com')
def test_create_existing_user2(self):
key = SigningKey.generate()
@ -96,17 +97,17 @@ class UserModelTestCase(UserTestCase):
def test_create_reuse_email(self):
with self.assertRaises(ValueError):
ToolshedUser.objects.create_user('testuser3', 'test@abc.de', '', domain='localhost')
ToolshedUser.objects.create_user('testuser3', 'test@abc.de', '', domain='example.com')
def test_create_user_invalid_private_key(self):
with self.assertRaises(TypeError):
ToolshedUser.objects.create_user('testuser3', 'test3@abc.de', '', domain='localhost',
ToolshedUser.objects.create_user('testuser3', 'test3@abc.de', '', domain='example.com',
private_key=b'0123456789abcdef0123456789abcdef')
with self.assertRaises(ValueError):
ToolshedUser.objects.create_user('testuser3', 'test3@abc.de', '', domain='localhost',
ToolshedUser.objects.create_user('testuser3', 'test3@abc.de', '', domain='example.com',
private_key='7005c4097')
with self.assertRaises(ValueError):
ToolshedUser.objects.create_user('testuser3', 'test3@abc.de', '', domain='localhost',
ToolshedUser.objects.create_user('testuser3', 'test3@abc.de', '', domain='example.com',
private_key='0123456789abcdef0123456789abcdef'
'Z123456789abcdef0123456789abcdef')
@ -264,7 +265,8 @@ class RegistrationApiTestCase(TestCase):
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
admin.set_password('testpassword')
admin.save()
example_com = type('obj', (object,), {'name': 'localhost'})
example_com = Domain.objects.create(name='example.com', owner=admin, open_registration=True)
example_com.save()
user2 = ToolshedUser.objects.create_user('testuser2', 'test2@abc.de', '', domain=example_com.name)
user2.set_password('testpassword3')
user2.save()
@ -272,20 +274,20 @@ class RegistrationApiTestCase(TestCase):
def test_registration(self):
self.assertEqual(ToolshedUser.objects.all().count(), 2)
reply = self.client.post('/auth/register/',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com',
'email': 'test@abc.de'})
self.assertEqual(reply.status_code, 200)
self.assertTrue('username' in reply.json())
self.assertTrue('domain' in reply.json())
user = ToolshedUser.objects.get(username='testuser')
self.assertEqual(user.email, 'test@abc.de')
self.assertEqual(user.domain, 'localhost')
self.assertEqual(user.domain, 'example.com')
self.assertTrue(user.check_password('testpassword2'))
self.assertEqual(ToolshedUser.objects.all().count(), 3)
def test_registration_fail(self):
reply = self.client.post('/auth/register/',
{'username': '', 'password': 'testpassword2', 'domain': 'localhost',
{'username': '', 'password': 'testpassword2', 'domain': 'example.com',
'email': 'test@abc.de'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
@ -294,7 +296,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_fail2(self):
reply = self.client.post('/auth/register/',
{'password': 'testpassword2', 'domain': 'localhost', 'email': 'test@abc.de'})
{'password': 'testpassword2', 'domain': 'example.com', 'email': 'test@abc.de'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
self.assertTrue('username' in reply.json()['errors'])
@ -302,7 +304,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_fail3(self):
reply = self.client.post('/auth/register/',
{'username': 'testuser', 'password': '', 'domain': 'localhost',
{'username': 'testuser', 'password': '', 'domain': 'example.com',
'email': 'test@abc.de'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
@ -311,7 +313,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_fail4(self):
reply = self.client.post('/auth/register/',
{'username': 'testuser', 'domain': 'localhost', 'email': 'test@abc.de'})
{'username': 'testuser', 'domain': 'example.com', 'email': 'test@abc.de'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
self.assertTrue('password' in reply.json()['errors'])
@ -336,7 +338,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_fail7(self):
reply = self.client.post('/auth/register/',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com',
'email': ''})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
@ -345,7 +347,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_fail8(self):
reply = self.client.post('/auth/register/',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost'})
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
self.assertTrue('email' in reply.json()['errors'])
@ -353,7 +355,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_existing_user(self):
reply = self.client.post('/auth/register/',
{'username': 'testuser2', 'password': 'testpassword2', 'domain': 'localhost',
{'username': 'testuser2', 'password': 'testpassword2', 'domain': 'example.com',
'email': 'test3@abc.de'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())
@ -371,7 +373,7 @@ class RegistrationApiTestCase(TestCase):
def test_registration_reuse_email(self):
reply = self.client.post('/auth/register/',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost',
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com',
'email': 'test2@abc.de'})
self.assertEqual(reply.status_code, 400)
self.assertTrue('errors' in reply.json())

View file

@ -47,6 +47,7 @@ INSTALLED_APPS = [
'corsheaders',
'drf_yasg',
'authentication',
'hostadmin',
]
REST_FRAMEWORK = {

View file

@ -31,5 +31,6 @@ schema_view = get_schema_view(
urlpatterns = [
path('djangoadmin/', admin.site.urls),
path('auth/', include('authentication.api')),
path('admin/', include('hostadmin.api')),
path('docs/', schema_view.with_ui('swagger', cache_timeout=0), name='api-docs'),
]

View file

View file

@ -0,0 +1,11 @@
from django.contrib import admin
from .models import Domain
class DomainAdmin(admin.ModelAdmin):
list_display = ('name', 'owner', 'open_registration')
list_filter = ('name', 'owner', 'open_registration')
admin.site.register(Domain, DomainAdmin)

27
backend/hostadmin/api.py Normal file
View file

@ -0,0 +1,27 @@
from rest_framework import routers, serializers, viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from hostadmin.models import Domain
router = routers.SimpleRouter()
class DomainSerializer(serializers.ModelSerializer):
class Meta:
model = Domain
fields = '__all__'
class DomainViewSet(viewsets.ModelViewSet):
queryset = Domain.objects.all()
serializer_class = DomainSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
router.register(r'domains', DomainViewSet, basename='domains')
urlpatterns = [
*router.urls,
]

View file

@ -0,0 +1,26 @@
# Generated by Django 4.1.7 on 2023-06-07 20:59
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Domain',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('open_registration', models.BooleanField(default=False)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domains', to=settings.AUTH_USER_MODEL)),
],
),
]

View file

View file

@ -0,0 +1,10 @@
from django.db import models
class Domain(models.Model):
name = models.CharField(max_length=255, unique=True)
owner = models.ForeignKey('authentication.ToolshedUser', on_delete=models.CASCADE, related_name='domains')
open_registration = models.BooleanField(default=False)
def __str__(self):
return self.name

View file

@ -0,0 +1,20 @@
from django.test import TestCase
from authentication.models import ToolshedUser
from hostadmin.models import Domain
class DomainTestCase(TestCase):
def setUp(self):
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
admin.set_password('testpassword')
admin.save()
example_com = Domain.objects.create(name='example.com', owner=admin, open_registration=True)
example_com.save()
def test_domain(self):
example_com = Domain.objects.get(name='example.com')
self.assertEqual(example_com.name, 'example.com')
self.assertEqual(example_com.owner.username, 'admin')
self.assertEqual(example_com.open_registration, True)
self.assertEqual(str(example_com), 'example.com')