diff options
Diffstat (limited to 'src/account')
-rw-r--r-- | src/account/admin.py | 4 | ||||
-rw-r--r-- | src/account/migrations/0010_auto_20230608_1913.py | 23 | ||||
-rw-r--r-- | src/account/models.py | 178 | ||||
-rw-r--r-- | src/account/tests/__init__.py | 8 | ||||
-rw-r--r-- | src/account/tests/test_general.py | 60 | ||||
-rw-r--r-- | src/account/urls.py | 4 | ||||
-rw-r--r-- | src/account/views.py | 82 |
7 files changed, 52 insertions, 307 deletions
diff --git a/src/account/admin.py b/src/account/admin.py index b4c142c..fd03e60 100644 --- a/src/account/admin.py +++ b/src/account/admin.py @@ -11,9 +11,7 @@ from django.contrib import admin -from account.models import UserProfile, Lab, VlanManager, PublicNetwork +from account.models import UserProfile, Lab admin.site.register(UserProfile) admin.site.register(Lab) -admin.site.register(VlanManager) -admin.site.register(PublicNetwork) diff --git a/src/account/migrations/0010_auto_20230608_1913.py b/src/account/migrations/0010_auto_20230608_1913.py new file mode 100644 index 0000000..3e597b9 --- /dev/null +++ b/src/account/migrations/0010_auto_20230608_1913.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2 on 2023-06-08 19:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0009_auto_20210324_2107'), + ] + + operations = [ + migrations.RemoveField( + model_name='lab', + name='vlan_manager', + ), + migrations.DeleteModel( + name='PublicNetwork', + ), + migrations.DeleteModel( + name='VlanManager', + ), + ] diff --git a/src/account/models.py b/src/account/models.py index 32229b1..f1deca7 100644 --- a/src/account/models.py +++ b/src/account/models.py @@ -16,9 +16,6 @@ import random from collections import Counter -from dashboard.exceptions import ResourceAvailabilityException - - class LabStatus(object): """ A Poor man's enum for the status of a lab. @@ -63,163 +60,6 @@ class UserProfile(models.Model): def __str__(self): return self.user.username - -class VlanManager(models.Model): - """ - Keeps track of the vlans for a lab. - - Vlans are represented as indexes into a 4096 element list. - This list is serialized to JSON for storing in the DB. - """ - - # list of length 4096 containing either 0 (not available) or 1 (available) - vlans = models.TextField() - # list of length 4096 containing either 0 (not reserved) or 1 (reserved) - reserved_vlans = models.TextField() - - block_size = models.IntegerField() - - # True if the lab allows two different users to have the same private vlans - # if they use QinQ or a vxlan overlay, for example - allow_overlapping = models.BooleanField() - - def get_vlans(self, count=1, within=None): - """ - Return the IDs of available vlans as a list[int], but does not reserve them. - - Will throw index exception if not enough vlans are available. - Always returns a list of ints - - If `within` is not none, will filter against that as a set, requiring that any vlans returned are within that set - """ - allocated = [] - vlans = json.loads(self.vlans) - reserved = json.loads(self.reserved_vlans) - - for i in range(0, len(vlans) - 1): - if len(allocated) >= count: - break - - if vlans[i] == 0 and self.allow_overlapping is False: - continue - - if reserved[i] == 1: - continue - - # vlan is available and not reserved, so safe to add - if within is not None: - if i in within: - allocated.append(i) - else: - allocated.append(i) - continue - - if len(allocated) != count: - raise ResourceAvailabilityException("There were not enough available private vlans for the allocation. Please contact the administrators.") - - return allocated - - def get_public_vlan(self, within=None): - """Return reference to an available public network without reserving it.""" - r = PublicNetwork.objects.filter(lab=self.lab_set.first(), in_use=False) - if within is not None: - r = r.filter(vlan__in=within) - - if r.count() < 1: - raise ResourceAvailabilityException("There were not enough available public vlans for the allocation. Please contact the administrators.") - - return r.first() - - def reserve_public_vlan(self, vlan): - """Reserves the Public Network that has the given vlan.""" - net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan, in_use=False) - net.in_use = True - net.save() - - def release_public_vlan(self, vlan): - """Un-reserves a public network with the given vlan.""" - net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan, in_use=True) - net.in_use = False - net.save() - - def public_vlan_is_available(self, vlan): - """ - Whether the public vlan is available. - - returns true if the network with the given vlan is free to use, - False otherwise - """ - net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan) - return not net.in_use - - def is_available(self, vlans): - """ - If the vlans are available. - - 'vlans' is either a single vlan id integer or a list of integers - will return true (available) or false - """ - if self.allow_overlapping: - return True - - reserved = json.loads(self.reserved_vlans) - vlan_master_list = json.loads(self.vlans) - try: - iter(vlans) - except Exception: - vlans = [vlans] - - for vlan in vlans: - if not vlan_master_list[vlan] or reserved[vlan]: - return False - return True - - def release_vlans(self, vlans): - """ - Make the vlans available for another booking. - - 'vlans' is either a single vlan id integer or a list of integers - will make the vlans available - doesnt return a value - """ - my_vlans = json.loads(self.vlans) - - try: - iter(vlans) - except Exception: - vlans = [vlans] - - for vlan in vlans: - my_vlans[vlan] = 1 - self.vlans = json.dumps(my_vlans) - self.save() - - def reserve_vlans(self, vlans): - """ - Reserves all given vlans or throws a ValueError. - - vlans can be an integer or a list of integers. - """ - my_vlans = json.loads(self.vlans) - - reserved = json.loads(self.reserved_vlans) - - try: - iter(vlans) - except Exception: - vlans = [vlans] - - vlans = set(vlans) - - for vlan in vlans: - if my_vlans[vlan] == 0 or reserved[vlan] == 1: - raise ValueError("vlan " + str(vlan) + " is not available") - - my_vlans[vlan] = 0 - self.vlans = json.dumps(my_vlans) - self.save() - - class Lab(models.Model): """ Model representing a Hosting Lab. @@ -233,7 +73,6 @@ class Lab(models.Model): contact_email = models.EmailField(max_length=200, null=True, blank=True) contact_phone = models.CharField(max_length=20, null=True, blank=True) status = models.IntegerField(default=LabStatus.UP) - vlan_manager = models.ForeignKey(VlanManager, on_delete=models.CASCADE, null=True) location = models.TextField(default="unknown") # This token must apear in API requests from this lab api_token = models.CharField(max_length=50) @@ -250,26 +89,9 @@ class Lab(models.Model): key += random.choice(alphabet) return key - def get_available_resources(self): - # Cannot import model normally due to ciruclar import - Server = apps.get_model('resource_inventory', 'Server') # TODO: Find way to import ResourceQuery - resources = [str(resource.profile) for resource in Server.objects.filter(lab=self, working=True, booked=False)] - return dict(Counter(resources)) - def __str__(self): return self.name - -class PublicNetwork(models.Model): - """L2/L3 network that can reach the internet.""" - - vlan = models.IntegerField() - lab = models.ForeignKey(Lab, on_delete=models.CASCADE) - in_use = models.BooleanField(default=False) - cidr = models.CharField(max_length=50, default="0.0.0.0/0") - gateway = models.CharField(max_length=50, default="0.0.0.0") - - class Downtime(models.Model): """ A Downtime event. diff --git a/src/account/tests/__init__.py b/src/account/tests/__init__.py deleted file mode 100644 index b6fef6c..0000000 --- a/src/account/tests/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## diff --git a/src/account/tests/test_general.py b/src/account/tests/test_general.py deleted file mode 100644 index 4020d89..0000000 --- a/src/account/tests/test_general.py +++ /dev/null @@ -1,60 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib.auth.models import User -from django.test import Client -from django.test import TestCase -from django.urls import reverse -from django.utils import timezone - -from account.models import UserProfile - - -class AccountMiddlewareTestCase(TestCase): - def setUp(self): - self.client = Client() - self.user1 = User.objects.create(username='user1') - self.user1.set_password('user1') - self.user1profile = UserProfile.objects.create(user=self.user1) - self.user1.save() - - def test_timezone_middleware(self): - """ - Verify timezone is being set by Middleware. - - The timezone should be UTC for anonymous users, - for authenticated users it should be set to user.userprofile.timezone - """ - # default - self.assertEqual(timezone.get_current_timezone_name(), 'UTC') - - url = reverse('account:settings') - # anonymous request - self.client.get(url) - self.assertEqual(timezone.get_current_timezone_name(), 'UTC') - - # authenticated user with UTC timezone (userprofile default) - self.client.login(username='user1', password='user1') - self.client.get(url) - self.assertEqual(timezone.get_current_timezone_name(), 'UTC') - - # authenticated user with custom timezone (userprofile default) - self.user1profile.timezone = 'Etc/Greenwich' - self.user1profile.save() - self.client.get(url) - self.assertEqual(timezone.get_current_timezone_name(), 'GMT') - - # if there is no profile for a user, it should be created - user2 = User.objects.create(username='user2') - user2.set_password('user2') - user2.save() - self.client.login(username='user2', password='user2') - self.client.get(url) - self.assertTrue(user2.userprofile) diff --git a/src/account/urls.py b/src/account/urls.py index 6d4ef2f..23ce122 100644 --- a/src/account/urls.py +++ b/src/account/urls.py @@ -35,11 +35,9 @@ from account.views import ( UserListView, account_resource_view, account_booking_view, - account_images_view, account_detail_view, template_delete_view, booking_cancel_view, - image_delete_view, ) app_name = 'account' @@ -53,7 +51,5 @@ urlpatterns = [ path('my/resources/delete/<int:resource_id>', template_delete_view), url(r'^my/bookings/$', account_booking_view, name='my-bookings'), path('my/bookings/cancel/<int:booking_id>', booking_cancel_view), - url(r'^my/images/$', account_images_view, name='my-images'), - path('my/images/delete/<int:image_id>', image_delete_view), url(r'^my/$', account_detail_view, name='my-account'), ] diff --git a/src/account/views.py b/src/account/views.py index 8976ff9..2d280cd 100644 --- a/src/account/views.py +++ b/src/account/views.py @@ -9,6 +9,7 @@ ############################################################################## +import json import os from django.utils import timezone @@ -30,9 +31,7 @@ from mozilla_django_oidc.auth import OIDCAuthenticationBackend from account.forms import AccountSettingsForm from account.models import UserProfile from booking.models import Booking -from resource_inventory.models import ResourceTemplate, Image - - +from api.views import delete_template, liblaas_templates @method_decorator(login_required, name='dispatch') class AccountSettingsView(UpdateView): model = UserProfile @@ -134,17 +133,21 @@ def account_resource_view(request): return render(request, "dashboard/login.html", {'title': 'Authentication Required'}) template = "account/resource_list.html" - active_bundles = [book.resource for book in Booking.objects.filter( - owner=request.user, end__gte=timezone.now(), resource__template__temporary=False)] - active_resources = [bundle.template.id for bundle in active_bundles] - resource_list = list(ResourceTemplate.objects.filter(owner=request.user, temporary=False)) + if request.method == "GET": - context = { - "resources": resource_list, - "active_resources": active_resources, - "title": "My Resources" - } - return render(request, template, context=context) + r = liblaas_templates(request) + usable_templates = r.json() + user_templates = [ t for t in usable_templates if t["owner"] == str(request.user)] + context = { + "templates": user_templates, + "title": "My Resources" + } + return render(request, template, context=context) + + if request.method == "POST": + return delete_template(request) + + return HttpResponse(status_code=405) def account_booking_view(request): @@ -165,37 +168,20 @@ def account_booking_view(request): return render(request, template, context=context) -def account_images_view(request): - if not request.user.is_authenticated: - return render(request, "dashboard/login.html", {'title': 'Authentication Required'}) - template = "account/image_list.html" - my_images = Image.objects.filter(owner=request.user) - public_images = Image.objects.filter(public=True) - used_images = {} - for image in my_images: - if image.in_use(): - used_images[image.id] = "true" - context = { - "title": "Images", - "images": my_images, - "public_images": public_images, - "used_images": used_images - } - return render(request, template, context=context) - def template_delete_view(request, resource_id=None): - if not request.user.is_authenticated: - return HttpResponse(status=403) - template = get_object_or_404(ResourceTemplate, pk=resource_id) - if not request.user.id == template.owner.id: - return HttpResponse(status=403) - if Booking.objects.filter(resource__template=template, end__gt=timezone.now()).exists(): - return HttpResponse(status=403) - template.public = False - template.temporary = True - template.save() - return HttpResponse(status=200) + # if not request.user.is_authenticated: + # return HttpResponse(status=403) + # template = get_object_or_404(ResourceTemplate, pk=resource_id) + # if not request.user.id == template.owner.id: + # return HttpResponse(status=403) + # if Booking.objects.filter(resource__template=template, end__gt=timezone.now()).exists(): + # return HttpResponse(status=403) + # template.public = False + # template.temporary = True + # template.save() + # return HttpResponse(status=200) + return HttpResponse(status=404) # todo - LL Integration def booking_cancel_view(request, booking_id=None): @@ -212,15 +198,3 @@ def booking_cancel_view(request, booking_id=None): booking.save() return HttpResponse('') - -def image_delete_view(request, image_id=None): - if not request.user.is_authenticated: - return HttpResponse('no') # 403? - image = get_object_or_404(Image, pk=image_id) - if image.public or image.owner.id != request.user.id: - return HttpResponse('no') # 403? - # check if used in booking - if image.in_use(): - return HttpResponse('no') # 403? - image.delete() - return HttpResponse('') |