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/
|
||||
|
||||
staticfiles/
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -47,6 +47,7 @@ INSTALLED_APPS = [
|
|||
'corsheaders',
|
||||
'drf_yasg',
|
||||
'authentication',
|
||||
'hostadmin',
|
||||
]
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
|
|
|
@ -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'),
|
||||
]
|
||||
|
|
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