add hostadmin app
This commit is contained in:
parent
12191369b7
commit
3cd89b7162
13 changed files with 143 additions and 38 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -127,3 +127,5 @@ dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
|
staticfiles/
|
||||||
|
|
|
@ -11,6 +11,7 @@ from rest_framework.response import Response
|
||||||
|
|
||||||
from authentication.models import ToolshedUser
|
from authentication.models import ToolshedUser
|
||||||
from authentication.signature_auth import SignatureAuthenticationLocal
|
from authentication.signature_auth import SignatureAuthenticationLocal
|
||||||
|
from hostadmin.models import Domain
|
||||||
|
|
||||||
router = routers.SimpleRouter()
|
router = routers.SimpleRouter()
|
||||||
|
|
||||||
|
@ -68,33 +69,35 @@ def getUserInfo(request):
|
||||||
@permission_classes([])
|
@permission_classes([])
|
||||||
@authentication_classes([])
|
@authentication_classes([])
|
||||||
def registerUser(request):
|
def registerUser(request):
|
||||||
username = request.data.get('username')
|
try:
|
||||||
domain = request.data.get('domain')
|
username = request.data.get('username')
|
||||||
password = request.data.get('password')
|
domain = request.data.get('domain')
|
||||||
email = request.data.get('email')
|
password = request.data.get('password')
|
||||||
|
email = request.data.get('email')
|
||||||
|
|
||||||
errors = {}
|
errors = {}
|
||||||
if not username:
|
if not username:
|
||||||
errors['username'] = 'Username is required'
|
errors['username'] = 'Username is required'
|
||||||
if not domain:
|
if not domain:
|
||||||
errors['domain'] = 'Domain is required'
|
errors['domain'] = 'Domain is required'
|
||||||
if not password:
|
if not password:
|
||||||
errors['password'] = 'Password is required'
|
errors['password'] = 'Password is required'
|
||||||
if not email:
|
if not email:
|
||||||
errors['email'] = 'Email is required'
|
errors['email'] = 'Email is required'
|
||||||
if ToolshedUser.objects.filter(email=email).exists():
|
if ToolshedUser.objects.filter(email=email).exists():
|
||||||
errors['email'] = 'Email already exists'
|
errors['email'] = 'Email already exists'
|
||||||
if ToolshedUser.objects.filter(username=username, domain=domain).exists():
|
if ToolshedUser.objects.filter(username=username, domain=domain).exists():
|
||||||
errors['username'] = 'Username already exists'
|
errors['username'] = 'Username already exists'
|
||||||
if errors:
|
if errors:
|
||||||
return Response({'errors': errors}, status=400)
|
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 = ToolshedUser.objects.create_user(username, email, '', domain=domain)
|
||||||
user.set_password(password)
|
user.set_password(password)
|
||||||
user.save()
|
user.save()
|
||||||
return Response({'username': user.username, 'domain': user.domain})
|
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)
|
return Response({'errors': {'domain': 'Domain does not exist or is not open for registration'}}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.test import TestCase, Client
|
||||||
from nacl.encoding import HexEncoder
|
from nacl.encoding import HexEncoder
|
||||||
|
|
||||||
from authentication.models import ToolshedUser, KnownIdentity
|
from authentication.models import ToolshedUser, KnownIdentity
|
||||||
|
from hostadmin.models import Domain
|
||||||
from nacl.signing import SigningKey
|
from nacl.signing import SigningKey
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,7 +74,8 @@ class UserTestCase(TestCase):
|
||||||
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
|
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
|
||||||
admin.set_password('testpassword')
|
admin.set_password('testpassword')
|
||||||
admin.save()
|
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 = ToolshedUser.objects.create_user('testuser', 'test@abc.de', '', domain=example_com.name)
|
||||||
self.local_user1.set_password('testpassword2')
|
self.local_user1.set_password('testpassword2')
|
||||||
self.local_user1.save()
|
self.local_user1.save()
|
||||||
|
|
|
@ -4,6 +4,7 @@ from nacl.signing import SigningKey
|
||||||
|
|
||||||
from authentication.models import ToolshedUser, KnownIdentity
|
from authentication.models import ToolshedUser, KnownIdentity
|
||||||
from authentication.tests import UserTestCase, SignatureAuthClient
|
from authentication.tests import UserTestCase, SignatureAuthClient
|
||||||
|
from hostadmin.models import Domain
|
||||||
|
|
||||||
|
|
||||||
class KnownIdentityTestCase(TestCase):
|
class KnownIdentityTestCase(TestCase):
|
||||||
|
@ -85,7 +86,7 @@ class UserModelTestCase(UserTestCase):
|
||||||
|
|
||||||
def test_create_existing_user(self):
|
def test_create_existing_user(self):
|
||||||
with self.assertRaises(ValueError):
|
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):
|
def test_create_existing_user2(self):
|
||||||
key = SigningKey.generate()
|
key = SigningKey.generate()
|
||||||
|
@ -96,17 +97,17 @@ class UserModelTestCase(UserTestCase):
|
||||||
|
|
||||||
def test_create_reuse_email(self):
|
def test_create_reuse_email(self):
|
||||||
with self.assertRaises(ValueError):
|
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):
|
def test_create_user_invalid_private_key(self):
|
||||||
with self.assertRaises(TypeError):
|
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')
|
private_key=b'0123456789abcdef0123456789abcdef')
|
||||||
with self.assertRaises(ValueError):
|
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')
|
private_key='7005c4097')
|
||||||
with self.assertRaises(ValueError):
|
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'
|
private_key='0123456789abcdef0123456789abcdef'
|
||||||
'Z123456789abcdef0123456789abcdef')
|
'Z123456789abcdef0123456789abcdef')
|
||||||
|
|
||||||
|
@ -264,7 +265,8 @@ class RegistrationApiTestCase(TestCase):
|
||||||
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
|
admin = ToolshedUser.objects.create_superuser('admin', 'admin@localhost', '')
|
||||||
admin.set_password('testpassword')
|
admin.set_password('testpassword')
|
||||||
admin.save()
|
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 = ToolshedUser.objects.create_user('testuser2', 'test2@abc.de', '', domain=example_com.name)
|
||||||
user2.set_password('testpassword3')
|
user2.set_password('testpassword3')
|
||||||
user2.save()
|
user2.save()
|
||||||
|
@ -272,20 +274,20 @@ class RegistrationApiTestCase(TestCase):
|
||||||
def test_registration(self):
|
def test_registration(self):
|
||||||
self.assertEqual(ToolshedUser.objects.all().count(), 2)
|
self.assertEqual(ToolshedUser.objects.all().count(), 2)
|
||||||
reply = self.client.post('/auth/register/',
|
reply = self.client.post('/auth/register/',
|
||||||
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost',
|
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com',
|
||||||
'email': 'test@abc.de'})
|
'email': 'test@abc.de'})
|
||||||
self.assertEqual(reply.status_code, 200)
|
self.assertEqual(reply.status_code, 200)
|
||||||
self.assertTrue('username' in reply.json())
|
self.assertTrue('username' in reply.json())
|
||||||
self.assertTrue('domain' in reply.json())
|
self.assertTrue('domain' in reply.json())
|
||||||
user = ToolshedUser.objects.get(username='testuser')
|
user = ToolshedUser.objects.get(username='testuser')
|
||||||
self.assertEqual(user.email, 'test@abc.de')
|
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.assertTrue(user.check_password('testpassword2'))
|
||||||
self.assertEqual(ToolshedUser.objects.all().count(), 3)
|
self.assertEqual(ToolshedUser.objects.all().count(), 3)
|
||||||
|
|
||||||
def test_registration_fail(self):
|
def test_registration_fail(self):
|
||||||
reply = self.client.post('/auth/register/',
|
reply = self.client.post('/auth/register/',
|
||||||
{'username': '', 'password': 'testpassword2', 'domain': 'localhost',
|
{'username': '', 'password': 'testpassword2', 'domain': 'example.com',
|
||||||
'email': 'test@abc.de'})
|
'email': 'test@abc.de'})
|
||||||
self.assertEqual(reply.status_code, 400)
|
self.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
|
@ -294,7 +296,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_fail2(self):
|
def test_registration_fail2(self):
|
||||||
reply = self.client.post('/auth/register/',
|
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.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
self.assertTrue('username' in reply.json()['errors'])
|
self.assertTrue('username' in reply.json()['errors'])
|
||||||
|
@ -302,7 +304,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_fail3(self):
|
def test_registration_fail3(self):
|
||||||
reply = self.client.post('/auth/register/',
|
reply = self.client.post('/auth/register/',
|
||||||
{'username': 'testuser', 'password': '', 'domain': 'localhost',
|
{'username': 'testuser', 'password': '', 'domain': 'example.com',
|
||||||
'email': 'test@abc.de'})
|
'email': 'test@abc.de'})
|
||||||
self.assertEqual(reply.status_code, 400)
|
self.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
|
@ -311,7 +313,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_fail4(self):
|
def test_registration_fail4(self):
|
||||||
reply = self.client.post('/auth/register/',
|
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.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
self.assertTrue('password' in reply.json()['errors'])
|
self.assertTrue('password' in reply.json()['errors'])
|
||||||
|
@ -336,7 +338,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_fail7(self):
|
def test_registration_fail7(self):
|
||||||
reply = self.client.post('/auth/register/',
|
reply = self.client.post('/auth/register/',
|
||||||
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost',
|
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com',
|
||||||
'email': ''})
|
'email': ''})
|
||||||
self.assertEqual(reply.status_code, 400)
|
self.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
|
@ -345,7 +347,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_fail8(self):
|
def test_registration_fail8(self):
|
||||||
reply = self.client.post('/auth/register/',
|
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.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
self.assertTrue('email' in reply.json()['errors'])
|
self.assertTrue('email' in reply.json()['errors'])
|
||||||
|
@ -353,7 +355,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_existing_user(self):
|
def test_registration_existing_user(self):
|
||||||
reply = self.client.post('/auth/register/',
|
reply = self.client.post('/auth/register/',
|
||||||
{'username': 'testuser2', 'password': 'testpassword2', 'domain': 'localhost',
|
{'username': 'testuser2', 'password': 'testpassword2', 'domain': 'example.com',
|
||||||
'email': 'test3@abc.de'})
|
'email': 'test3@abc.de'})
|
||||||
self.assertEqual(reply.status_code, 400)
|
self.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
|
@ -371,7 +373,7 @@ class RegistrationApiTestCase(TestCase):
|
||||||
|
|
||||||
def test_registration_reuse_email(self):
|
def test_registration_reuse_email(self):
|
||||||
reply = self.client.post('/auth/register/',
|
reply = self.client.post('/auth/register/',
|
||||||
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'localhost',
|
{'username': 'testuser', 'password': 'testpassword2', 'domain': 'example.com',
|
||||||
'email': 'test2@abc.de'})
|
'email': 'test2@abc.de'})
|
||||||
self.assertEqual(reply.status_code, 400)
|
self.assertEqual(reply.status_code, 400)
|
||||||
self.assertTrue('errors' in reply.json())
|
self.assertTrue('errors' in reply.json())
|
||||||
|
|
|
@ -47,6 +47,7 @@ INSTALLED_APPS = [
|
||||||
'corsheaders',
|
'corsheaders',
|
||||||
'drf_yasg',
|
'drf_yasg',
|
||||||
'authentication',
|
'authentication',
|
||||||
|
'hostadmin',
|
||||||
]
|
]
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
|
|
|
@ -31,5 +31,6 @@ schema_view = get_schema_view(
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('djangoadmin/', admin.site.urls),
|
path('djangoadmin/', admin.site.urls),
|
||||||
path('auth/', include('authentication.api')),
|
path('auth/', include('authentication.api')),
|
||||||
|
path('admin/', include('hostadmin.api')),
|
||||||
path('docs/', schema_view.with_ui('swagger', cache_timeout=0), name='api-docs'),
|
path('docs/', schema_view.with_ui('swagger', cache_timeout=0), name='api-docs'),
|
||||||
]
|
]
|
||||||
|
|
0
backend/hostadmin/__init__.py
Normal file
0
backend/hostadmin/__init__.py
Normal file
11
backend/hostadmin/admin.py
Normal file
11
backend/hostadmin/admin.py
Normal 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
27
backend/hostadmin/api.py
Normal 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,
|
||||||
|
]
|
26
backend/hostadmin/migrations/0001_initial.py
Normal file
26
backend/hostadmin/migrations/0001_initial.py
Normal 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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
backend/hostadmin/migrations/__init__.py
Normal file
0
backend/hostadmin/migrations/__init__.py
Normal file
10
backend/hostadmin/models.py
Normal file
10
backend/hostadmin/models.py
Normal 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
|
20
backend/hostadmin/tests.py
Normal file
20
backend/hostadmin/tests.py
Normal 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')
|
Loading…
Reference in a new issue