add license models
This commit is contained in:
parent
c885ab4ac7
commit
ba61934b6b
|
@ -12,7 +12,8 @@ from .models import (Backup, BackupMethod, TargetDevice, Device, RamType, Ram,
|
|||
DeviceManufacturer, AdGroup, MailGroup, Location,
|
||||
MailAlias, IpStatus, Notification, NotificationType,
|
||||
SoftwareArchitecture, SoftwareCategory, Software, User,
|
||||
UserInAdGroup, UserInMailGroup)
|
||||
UserInAdGroup, UserInMailGroup, UserLicense,
|
||||
ComputerLicense, LicenseWithComputer, LicenseWithUser)
|
||||
|
||||
|
||||
class CustomerAdmin(GuardedModelAdmin):
|
||||
|
@ -75,6 +76,22 @@ class IpStatusAdmin(admin.ModelAdmin):
|
|||
return {}
|
||||
|
||||
|
||||
class LicenseWithComputerAdmin(admin.ModelAdmin):
|
||||
def get_model_perms(self, request):
|
||||
"""
|
||||
Return empty perms dict thus hiding the model from admin index.
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
class LicenseWithUserAdmin(admin.ModelAdmin):
|
||||
def get_model_perms(self, request):
|
||||
"""
|
||||
Return empty perms dict thus hiding the model from admin index.
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
class MailAliasAdmin(admin.ModelAdmin):
|
||||
def get_model_perms(self, request):
|
||||
"""
|
||||
|
@ -238,10 +255,16 @@ class DeviceInNetInline(nested_admin.NestedStackedInline):
|
|||
verbose_name_plural = 'Nets'
|
||||
|
||||
|
||||
class LicenseWithComputerInLine(nested_admin.NestedStackedInline):
|
||||
model = LicenseWithComputer
|
||||
extra = 0
|
||||
verbose_name_plural = 'Licenses'
|
||||
|
||||
|
||||
class ComputerAdmin(nested_admin.NestedModelAdmin):
|
||||
list_display = ('name', 'host')
|
||||
inlines = (SoftwareInLine, CpusInLine, RamInLine, DiskInLine, RaidInLine,
|
||||
DeviceInNetInline)
|
||||
DeviceInNetInline, LicenseWithComputerInLine)
|
||||
|
||||
|
||||
class AdGroupInLine(admin.StackedInline):
|
||||
|
@ -250,6 +273,12 @@ class AdGroupInLine(admin.StackedInline):
|
|||
verbose_name_plural = 'AD Groups'
|
||||
|
||||
|
||||
class LicenseWithUserInLine(admin.StackedInline):
|
||||
model = LicenseWithUser
|
||||
extra = 0
|
||||
verbose_name_plural = 'Licenses'
|
||||
|
||||
|
||||
class MailGroupInLine(admin.StackedInline):
|
||||
model = UserInMailGroup
|
||||
extra = 0
|
||||
|
@ -264,7 +293,7 @@ class MailAliasInLine(admin.StackedInline):
|
|||
|
||||
class UserAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'customer', 'enabled')
|
||||
inlines = (AdGroupInLine, MailGroupInLine, MailAliasInLine)
|
||||
inlines = (AdGroupInLine, MailGroupInLine, MailAliasInLine, LicenseWithUserInLine)
|
||||
|
||||
|
||||
class TargetDeviceInLine(admin.StackedInline):
|
||||
|
@ -277,10 +306,23 @@ class BackupAdmin(admin.ModelAdmin):
|
|||
inlines = (TargetDeviceInLine,)
|
||||
|
||||
|
||||
class UserLicenseAdmin(admin.ModelAdmin):
|
||||
model = UserLicense
|
||||
extra = 0
|
||||
verbose_name_plural = 'User Licenses'
|
||||
|
||||
|
||||
class ComputerLicenseAdmin(admin.ModelAdmin):
|
||||
model = ComputerLicense
|
||||
extra = 0
|
||||
verbose_name_plural = 'Computer Licenses'
|
||||
|
||||
|
||||
admin.site.register(AdGroup)
|
||||
admin.site.register(Backup, BackupAdmin)
|
||||
admin.site.register(BackupMethod, BackupMethodAdmin)
|
||||
admin.site.register(Computer, ComputerAdmin)
|
||||
admin.site.register(ComputerLicense, ComputerLicenseAdmin)
|
||||
admin.site.register(ConnectedDevice)
|
||||
admin.site.register(Cpu, CpuAdmin)
|
||||
admin.site.register(CpuArchitecture, CpuArchitectureAdmin)
|
||||
|
@ -293,6 +335,8 @@ admin.site.register(DeviceManufacturer, DeviceManufacturerAdmin)
|
|||
admin.site.register(Disk)
|
||||
admin.site.register(DiskType, DiskTypeAdmin)
|
||||
admin.site.register(IpStatus, IpStatusAdmin)
|
||||
admin.site.register(LicenseWithComputer, LicenseWithComputerAdmin)
|
||||
admin.site.register(LicenseWithUser, LicenseWithUserAdmin)
|
||||
admin.site.register(Location)
|
||||
admin.site.register(MailAlias, MailAliasAdmin)
|
||||
admin.site.register(MailGroup)
|
||||
|
@ -311,6 +355,7 @@ admin.site.register(TargetDevice, TargetDeviceAdmin)
|
|||
admin.site.register(User, UserAdmin)
|
||||
admin.site.register(UserInAdGroup, UserInAdGroupAdmin)
|
||||
admin.site.register(UserInMailGroup, UserInMailGroupAdmin)
|
||||
admin.site.register(UserLicense, UserLicenseAdmin)
|
||||
admin.site.register(Warranty)
|
||||
admin.site.register(WarrantyType, WarrantyTypeAdmin)
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ from .cpu import CpuArchitecture, CpuManufacturer, Cpu
|
|||
from .devices import (DeviceCategory, Device, ConnectedDevice, DeviceInNet)
|
||||
from .disk import DiskType, Disk
|
||||
from .groups import Group, AdGroup, MailGroup
|
||||
from .license import (License, ComputerLicense, UserLicense,
|
||||
LicenseWithComputer, LicenseWithUser)
|
||||
from .location import Location
|
||||
from .mailalias import MailAlias
|
||||
from .net import Net, IpStatus
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
from django.db import models
|
||||
from .companies import Customer
|
||||
from .computer import Computer
|
||||
from .user import User
|
||||
from .software import Software
|
||||
|
||||
|
||||
class License(models.Model):
|
||||
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
|
||||
key = models.CharField(max_length=50, null=True, blank=True)
|
||||
software = models.ForeignKey(Software,
|
||||
null=True,
|
||||
on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.customer) + ": " + str(self.software)
|
||||
|
||||
def get_absolute_url(self):
|
||||
from django.urls import reverse
|
||||
return reverse('license', args=[str(self.id)])
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class UserLicense(License):
|
||||
max_allowed_users = models.IntegerField(null=True, blank=True)
|
||||
user = models.ManyToManyField(User, through="LicenseWithUser")
|
||||
|
||||
@property
|
||||
def used_licenses(self):
|
||||
return LicenseWithUser.objects.filter(pk=self.id).count()
|
||||
|
||||
|
||||
class ComputerLicense(License):
|
||||
max_allowed_computers = models.IntegerField(null=True, blank=True)
|
||||
computer = models.ManyToManyField(Computer, through="LicenseWithComputer")
|
||||
|
||||
@property
|
||||
def used_licenses(self):
|
||||
return LicenseWithComputer.objects.filter(license=self).count()
|
||||
|
||||
|
||||
class LicenseWithUser(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
license = models.ForeignKey(UserLicense, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class LicenseWithComputer(models.Model):
|
||||
computer = models.ForeignKey(Computer, on_delete=models.CASCADE)
|
||||
license = models.ForeignKey(ComputerLicense, on_delete=models.CASCADE)
|
|
@ -1,5 +1,5 @@
|
|||
import django_tables2 as tables
|
||||
from .models import Net, Device, Backup, DeviceInNet
|
||||
from .models import Net, Device, Backup, DeviceInNet, ComputerLicense, UserLicense
|
||||
from django_tables2.utils import A
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@ class CustomersTable(tables.Table):
|
|||
computers = tables.LinkColumn('computers', text='Computers', args=[A('pk')])
|
||||
devices = tables.LinkColumn('devices', text='Devices', args=[A('pk')])
|
||||
backups = tables.LinkColumn('backups', text='Backups', args=[A('pk')])
|
||||
licenses = tables.LinkColumn('licenses', text='Licenses', args=[A('pk')])
|
||||
|
||||
class Meta:
|
||||
template_name = 'django_tables2/semantic.html'
|
||||
|
@ -64,3 +65,25 @@ class NetDetailTable(tables.Table):
|
|||
class Meta:
|
||||
template_name = 'django_tables2/semantic.html'
|
||||
model = DeviceInNet
|
||||
|
||||
|
||||
class UserLicensesTable(tables.Table):
|
||||
id = tables.Column(visible=False)
|
||||
license_ptr = tables.Column(visible=False)
|
||||
customer = tables.Column('Customer', linkify=True)
|
||||
used_licenses = tables.Column()
|
||||
|
||||
class Meta:
|
||||
template_name = 'django_tables2/semantic.html'
|
||||
model = UserLicense
|
||||
|
||||
|
||||
class ComputerLicensesTable(tables.Table):
|
||||
id = tables.Column(visible=False)
|
||||
license_ptr = tables.Column(visible=False)
|
||||
customer = tables.Column('Customer', linkify=True)
|
||||
used_licenses = tables.Column()
|
||||
|
||||
class Meta:
|
||||
template_name = 'django_tables2/semantic.html'
|
||||
model = ComputerLicense
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "inventory/base.html" %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% block section_title %}Licenses{% endblock %}
|
||||
{% block content %}
|
||||
<h3>User Licenses</h3>
|
||||
{% render_table user_licenses %}
|
||||
<h3>Computer Licenses</h3>
|
||||
{% render_table computer_licenses %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,73 @@
|
|||
import pytest
|
||||
|
||||
from django.test import Client
|
||||
from mixer.backend.django import mixer
|
||||
|
||||
import helper
|
||||
from inventory.models import Customer
|
||||
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_customer_license_table_not_logged_in():
|
||||
response = Client().get('/customer/1/licenses/')
|
||||
assert response.status_code == 302 and 'login' in response.url
|
||||
|
||||
|
||||
def test_customer_license_table(create_admin_user):
|
||||
fixture = create_admin_user()
|
||||
customer = fixture['customer']
|
||||
client = Client()
|
||||
client.login(username="novartis-admin", password="password")
|
||||
license = mixer.blend('inventory.UserLicense', customer=customer,
|
||||
software=mixer.SELECT, key=mixer.RANDOM,
|
||||
max_allowed_users=mixer.RANDOM)
|
||||
response = client.get('/customer/' + str(customer.id) + '/licenses/')
|
||||
assert (response.status_code == 200
|
||||
and helper.in_content(response, license.software)
|
||||
and helper.in_content(response, license.key)
|
||||
and helper.in_content(response, license.max_allowed_users))
|
||||
|
||||
|
||||
def test_customer_license_table_no_license(create_admin_user):
|
||||
fixture = create_admin_user()
|
||||
customer = fixture['customer']
|
||||
client = Client()
|
||||
client.login(username="novartis-admin", password="password")
|
||||
response = client.get('/customer/' + str(customer.id) + '/licenses/')
|
||||
assert (response.status_code == 200
|
||||
and helper.not_in_content(response, customer))
|
||||
|
||||
|
||||
def test_customer_license_table_no_permission(create_admin_user):
|
||||
create_admin_user()
|
||||
customer = Customer.objects.create(name='Nestle')
|
||||
client = Client()
|
||||
client.login(username="novartis-admin", password="password")
|
||||
mixer.blend('inventory.UserLicense', customer=customer)
|
||||
response = client.get('/customer/' + str(customer.id) + '/licenses/')
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_customer_license_table_multiple_licenses(create_admin_user):
|
||||
fixture = create_admin_user()
|
||||
customer = fixture['customer']
|
||||
user = mixer.blend('inventory.User')
|
||||
client = Client()
|
||||
client.login(username="novartis-admin", password="password")
|
||||
license1 = mixer.blend('inventory.UserLicense', customer=customer,
|
||||
software=mixer.SELECT, key=mixer.RANDOM,
|
||||
max_allowed_users=mixer.RANDOM)
|
||||
license2 = mixer.blend('inventory.UserLicense', customer=customer,
|
||||
software=mixer.SELECT, key=mixer.RANDOM,
|
||||
max_allowed_users=mixer.RANDOM)
|
||||
mixer.blend('inventory.LicenseWithUser', user=user, license=mixer.SELECT)
|
||||
response = client.get('/customer/' + str(customer.id) + '/licenses/')
|
||||
assert (response.status_code == 200
|
||||
and helper.in_content(response, license1.software)
|
||||
and helper.in_content(response, license1.key)
|
||||
and helper.in_content(response, license1.max_allowed_users)
|
||||
and helper.in_content(response, license2.software)
|
||||
and helper.in_content(response, license2.key)
|
||||
and helper.in_content(response, license2.max_allowed_users))
|
|
@ -21,5 +21,7 @@ urlpatterns = [
|
|||
path('net/<int:pk>/', views.net_detail_view, name='net'),
|
||||
path('backup/<int:pk>/', views.backup_detail_view, name='backup'),
|
||||
path('computers/all/', views.ComputersFilterView.as_view(),
|
||||
name='all_computers')
|
||||
name='all_computers'),
|
||||
path('customer/<int:pk>/licenses/', views.licenses_table_view,
|
||||
name='licenses'),
|
||||
]
|
||||
|
|
|
@ -17,9 +17,9 @@ from .decorators import (computer_view_permission, customer_view_permission,
|
|||
from .models import (Device, Computer, ComputerRamRelation,
|
||||
ComputerDiskRelation, ComputerCpuRelation,
|
||||
ComputerSoftwareRelation, Customer, Net, Raid,
|
||||
Backup, DeviceInNet, TargetDevice)
|
||||
Backup, DeviceInNet, TargetDevice, UserLicense, ComputerLicense)
|
||||
from .tables import (CustomersTable, ComputersTable, DevicesTable, NetsTable,
|
||||
BackupsTable, NetDetailTable)
|
||||
BackupsTable, NetDetailTable, UserLicensesTable, ComputerLicensesTable)
|
||||
from .filters import ComputerFilter
|
||||
|
||||
|
||||
|
@ -135,3 +135,14 @@ class ComputersFilterView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||
klass=Customer)
|
||||
results = Computer.objects.filter(customer__in=customers)
|
||||
return results
|
||||
|
||||
|
||||
@login_required
|
||||
@customer_view_permission
|
||||
def licenses_table_view(request, pk):
|
||||
user_licenses = UserLicensesTable(UserLicense.objects.filter(customer=pk))
|
||||
computer_licenses = ComputerLicensesTable(ComputerLicense.objects.filter(customer=pk))
|
||||
RequestConfig(request).configure(user_licenses)
|
||||
RequestConfig(request).configure(computer_licenses)
|
||||
return render(request, 'inventory/license_list.html', {'user_licenses': user_licenses,
|
||||
'computer_licenses': computer_licenses})
|
||||
|
|
Loading…
Reference in New Issue