0
app/api/serializers/__init__.py
Normal file
0
app/api/serializers/__init__.py
Normal file
168
app/api/serializers/inventory.py
Normal file
168
app/api/serializers/inventory.py
Normal file
@ -0,0 +1,168 @@
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.html import escape
|
||||
|
||||
class Inventory:
|
||||
""" Inventory Object
|
||||
|
||||
Pass in an Inventory dict that a device has provided and sanitize ready for use.
|
||||
|
||||
Raises:
|
||||
ValidationError: Malformed inventory data.
|
||||
"""
|
||||
|
||||
|
||||
class Details:
|
||||
|
||||
_name: str
|
||||
|
||||
_serial_number: str
|
||||
|
||||
_uuid: str
|
||||
|
||||
|
||||
def __init__(self, details: dict):
|
||||
|
||||
self._name = escape(details['name'])
|
||||
|
||||
self._serial_number = escape(details['serial_number'])
|
||||
|
||||
self._uuid = escape(details['uuid'])
|
||||
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
||||
return str(self._name)
|
||||
|
||||
|
||||
@property
|
||||
def serial_number(self) -> str:
|
||||
|
||||
return str(self._serial_number)
|
||||
|
||||
|
||||
@property
|
||||
def uuid(self) -> str:
|
||||
|
||||
return str(self._uuid)
|
||||
|
||||
|
||||
|
||||
class OperatingSystem:
|
||||
|
||||
_name: str
|
||||
|
||||
_version_major: str
|
||||
|
||||
_version: str
|
||||
|
||||
|
||||
def __init__(self, operating_system: dict):
|
||||
|
||||
self._name = escape(operating_system['name'])
|
||||
|
||||
self._version_major = escape(operating_system['version_major'])
|
||||
|
||||
self._version = escape(operating_system['version'])
|
||||
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
||||
return str(self._name)
|
||||
|
||||
|
||||
@property
|
||||
def version_major(self) -> str:
|
||||
|
||||
return str(self._version_major)
|
||||
|
||||
|
||||
@property
|
||||
def version(self) -> str:
|
||||
|
||||
return str(self._version)
|
||||
|
||||
|
||||
|
||||
class Software:
|
||||
|
||||
_name: str
|
||||
|
||||
_category: str
|
||||
|
||||
_version: str
|
||||
|
||||
|
||||
def __init__(self, software: dict):
|
||||
|
||||
self._name = escape(software['name'])
|
||||
|
||||
self._category = escape(software['category'])
|
||||
|
||||
self._version = escape(software['version'])
|
||||
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
||||
return str(self._name)
|
||||
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
|
||||
return str(self._category)
|
||||
|
||||
|
||||
@property
|
||||
def version(self) -> str:
|
||||
|
||||
return str(self._version)
|
||||
|
||||
|
||||
|
||||
_details: Details = None
|
||||
|
||||
_operating_system: OperatingSystem = None
|
||||
|
||||
_software: list[Software] = []
|
||||
|
||||
|
||||
def __init__(self, inventory: dict):
|
||||
|
||||
if (
|
||||
type(inventory['details']) is dict and
|
||||
type(inventory['os']) is dict and
|
||||
type(inventory['software']) is list
|
||||
):
|
||||
|
||||
self._details = self.Details(inventory['details'])
|
||||
|
||||
self._operating_system = self.OperatingSystem(inventory['os'])
|
||||
|
||||
for software in inventory['software']:
|
||||
|
||||
self._software += [ self.Software(software) ]
|
||||
|
||||
else:
|
||||
|
||||
raise ValidationError('Inventory File is invalid')
|
||||
|
||||
|
||||
@property
|
||||
def details(self) -> Details:
|
||||
|
||||
return self._details
|
||||
|
||||
|
||||
@property
|
||||
def operating_system(self) -> OperatingSystem:
|
||||
|
||||
return self._operating_system
|
||||
|
||||
|
||||
@property
|
||||
def software(self) -> list[Software]:
|
||||
|
||||
return list(self._software)
|
@ -2,6 +2,7 @@
|
||||
import json
|
||||
import re
|
||||
|
||||
from django.core.exceptions import ValidationError, PermissionDenied
|
||||
from django.http import Http404, JsonResponse
|
||||
from django.utils import timezone
|
||||
|
||||
@ -15,6 +16,7 @@ from access.models import Organization
|
||||
|
||||
from api.views.mixin import OrganizationPermissionAPI
|
||||
from api.serializers.itam.inventory import InventorySerializer
|
||||
from api.serializers.inventory import Inventory
|
||||
|
||||
from core.http.common import Http
|
||||
|
||||
@ -33,7 +35,7 @@ class InventoryPermissions(OrganizationPermissionAPI):
|
||||
|
||||
data = view.request.data
|
||||
|
||||
self.obj = Device.objects.get(slug=str(data['details']['name']).lower())
|
||||
self.obj = Device.objects.get(slug=str(data.details.name).lower())
|
||||
|
||||
return super().permission_check(request, view, obj=None)
|
||||
|
||||
@ -76,68 +78,69 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
)
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
||||
|
||||
data = json.loads(request.body)
|
||||
|
||||
device = None
|
||||
|
||||
self.default_organization = UserSettings.objects.get(user=request.user).default_organization
|
||||
|
||||
if Device.objects.filter(slug=str(data['details']['name']).lower()).exists():
|
||||
|
||||
self.obj = Device.objects.get(slug=str(data['details']['name']).lower())
|
||||
|
||||
device = self.obj
|
||||
|
||||
|
||||
if not self.permission_check(request=request, view=self, obj=device):
|
||||
|
||||
raise Http404
|
||||
|
||||
|
||||
|
||||
status = Http.Status.BAD_REQUEST
|
||||
|
||||
device_operating_system = None
|
||||
operating_system = None
|
||||
operating_system_version = None
|
||||
status = Http.Status.OK
|
||||
response_data = 'OK'
|
||||
|
||||
try:
|
||||
|
||||
data = json.loads(request.body)
|
||||
data = Inventory(data)
|
||||
|
||||
device = None
|
||||
|
||||
|
||||
self.default_organization = UserSettings.objects.get(user=request.user).default_organization
|
||||
|
||||
if Device.objects.filter(slug=str(data.details.name).lower()).exists():
|
||||
|
||||
self.obj = Device.objects.get(slug=str(data.details.name).lower())
|
||||
|
||||
device = self.obj
|
||||
|
||||
|
||||
if not self.permission_check(request=request, view=self, obj=device):
|
||||
|
||||
raise Http404
|
||||
|
||||
device_operating_system = None
|
||||
operating_system = None
|
||||
operating_system_version = None
|
||||
|
||||
|
||||
app_settings = AppSettings.objects.get(owner_organization = None)
|
||||
|
||||
if not device: # Create the device
|
||||
|
||||
device = Device.objects.create(
|
||||
name = data['details']['name'],
|
||||
name = data.details.name,
|
||||
device_type = None,
|
||||
serial_number = data['details']['serial_number'],
|
||||
uuid = data['details']['uuid'],
|
||||
serial_number = data.details.serial_number,
|
||||
uuid = data.details.uuid,
|
||||
organization = self.default_organization,
|
||||
)
|
||||
|
||||
status = Http.Status.CREATED
|
||||
|
||||
|
||||
if OperatingSystem.objects.filter( slug=data['os']['name'] ).exists():
|
||||
if OperatingSystem.objects.filter( slug=data.operating_system.name ).exists():
|
||||
|
||||
operating_system = OperatingSystem.objects.get( slug=data['os']['name'] )
|
||||
operating_system = OperatingSystem.objects.get( slug=data.operating_system.name )
|
||||
|
||||
else: # Create Operating System
|
||||
|
||||
operating_system = OperatingSystem.objects.create(
|
||||
name = data['os']['name'],
|
||||
name = data.operating_system.name,
|
||||
organization = self.default_organization,
|
||||
is_global = True
|
||||
)
|
||||
|
||||
|
||||
if OperatingSystemVersion.objects.filter( name=data['os']['version_major'], operating_system=operating_system ).exists():
|
||||
if OperatingSystemVersion.objects.filter( name=data.operating_system.version_major, operating_system=operating_system ).exists():
|
||||
|
||||
operating_system_version = OperatingSystemVersion.objects.get(
|
||||
organization = self.default_organization,
|
||||
is_global = True,
|
||||
name = data['os']['version_major'],
|
||||
name = data.operating_system.version_major,
|
||||
operating_system = operating_system
|
||||
)
|
||||
|
||||
@ -146,16 +149,16 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
operating_system_version = OperatingSystemVersion.objects.create(
|
||||
organization = self.default_organization,
|
||||
is_global = True,
|
||||
name = data['os']['version_major'],
|
||||
name = data.operating_system.version_major,
|
||||
operating_system = operating_system,
|
||||
)
|
||||
|
||||
|
||||
if DeviceOperatingSystem.objects.filter( version=data['os']['version'], device=device, operating_system_version=operating_system_version ).exists():
|
||||
if DeviceOperatingSystem.objects.filter( version=data.operating_system.version, device=device, operating_system_version=operating_system_version ).exists():
|
||||
|
||||
device_operating_system = DeviceOperatingSystem.objects.get(
|
||||
device=device,
|
||||
version = data['os']['version'],
|
||||
version = data.operating_system.version,
|
||||
operating_system_version = operating_system_version,
|
||||
)
|
||||
|
||||
@ -170,7 +173,7 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
device_operating_system = DeviceOperatingSystem.objects.create(
|
||||
organization = self.default_organization,
|
||||
device=device,
|
||||
version = data['os']['version'],
|
||||
version = data.operating_system.version,
|
||||
operating_system_version = operating_system_version,
|
||||
installdate = timezone.now()
|
||||
)
|
||||
@ -195,7 +198,7 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
|
||||
|
||||
|
||||
for inventory in list(data['software']):
|
||||
for inventory in list(data.software):
|
||||
|
||||
software = None
|
||||
software_category = None
|
||||
@ -204,10 +207,10 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
device_software = None
|
||||
|
||||
|
||||
if SoftwareCategory.objects.filter( name = inventory['category'] ).exists():
|
||||
if SoftwareCategory.objects.filter( name = inventory.category ).exists():
|
||||
|
||||
software_category = SoftwareCategory.objects.get(
|
||||
name = inventory['category']
|
||||
name = inventory.category
|
||||
)
|
||||
|
||||
else: # Create Software Category
|
||||
@ -215,14 +218,14 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
software_category = SoftwareCategory.objects.create(
|
||||
organization = software_category_organization,
|
||||
is_global = True,
|
||||
name = inventory['category'],
|
||||
name = inventory.category,
|
||||
)
|
||||
|
||||
|
||||
if Software.objects.filter( name = inventory['name'] ).exists():
|
||||
if Software.objects.filter( name = inventory.name ).exists():
|
||||
|
||||
software = Software.objects.get(
|
||||
name = inventory['name']
|
||||
name = inventory.name
|
||||
)
|
||||
|
||||
if not software.category:
|
||||
@ -235,14 +238,14 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
software = Software.objects.create(
|
||||
organization = software_organization,
|
||||
is_global = True,
|
||||
name = inventory['name'],
|
||||
name = inventory.name,
|
||||
category = software_category,
|
||||
)
|
||||
|
||||
|
||||
pattern = r"^(\d+:)?(?P<semver>\d+\.\d+(\.\d+)?)"
|
||||
|
||||
semver = re.search(pattern, str(inventory['version']), re.DOTALL)
|
||||
semver = re.search(pattern, str(inventory.version), re.DOTALL)
|
||||
|
||||
|
||||
if semver:
|
||||
@ -250,7 +253,7 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
semver = semver['semver']
|
||||
|
||||
else:
|
||||
semver = inventory['version']
|
||||
semver = inventory.version
|
||||
|
||||
|
||||
if SoftwareVersion.objects.filter( name = semver, software = software ).exists():
|
||||
@ -328,15 +331,25 @@ this setting populated, no device will be created and the endpoint will return H
|
||||
|
||||
status = Http.Status.OK
|
||||
|
||||
except PermissionDenied as e:
|
||||
|
||||
status = Http.Status.FORBIDDEN
|
||||
response_data = ''
|
||||
|
||||
except ValidationError as e:
|
||||
|
||||
status = Http.Status.BAD_REQUEST
|
||||
response_data = e.message
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print(f'An error occured{e}')
|
||||
|
||||
status = Http.Status.SERVER_ERROR
|
||||
response_data = 'Unknown Server Error occured'
|
||||
|
||||
|
||||
return Response(data='OK',status=status)
|
||||
return Response(data=response_data,status=status)
|
||||
|
||||
|
||||
|
||||
|
@ -10,8 +10,11 @@ class Http():
|
||||
"""HTTP server status codes."""
|
||||
|
||||
OK = 200
|
||||
|
||||
CREATED = 201
|
||||
|
||||
BAD_REQUEST = 400
|
||||
|
||||
FORBIDDEN = 403
|
||||
|
||||
SERVER_ERROR = 500
|
||||
|
@ -8,6 +8,9 @@ about: https://gitlab.com/nofusscomputing/infrastructure/configuration-managemen
|
||||
|
||||
This section contains the application API documentation to assist in application development. The target audience is anyone whom would be developing the application.
|
||||
|
||||
|
||||
- [Models](./models/index.md)
|
||||
|
||||
- [Serializers](./serializer/index.md)
|
||||
|
||||
- [Unit Testing](./tests/index.md)
|
||||
|
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Serializers
|
||||
description: No Fuss Computings Django ITSM API Documentation for Serializers
|
||||
date: 2024-06-19
|
||||
template: project.html
|
||||
about: https://gitlab.com/nofusscomputing/infrastructure/configuration-management/django_app
|
||||
---
|
||||
|
||||
This section contains the application API documentation for Serializers to assist in application development. The target audience is anyone whom would be developing the application.
|
||||
|
||||
|
||||
- [Inventory](./inventory.md)
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Inventory
|
||||
description: No Fuss Computings django ITSM Inventory serializer
|
||||
date: 2024-06-19
|
||||
template: project.html
|
||||
about: https://gitlab.com/nofusscomputing/infrastructure/configuration-management/django_app
|
||||
---
|
||||
|
||||
::: app.api.serializers.inventory.Inventory
|
||||
options:
|
||||
inherited_members: true
|
@ -76,6 +76,12 @@ nav:
|
||||
|
||||
- projects/django-template/development/api/models/access_organization_permission_checking.md
|
||||
|
||||
- Serializers:
|
||||
|
||||
- projects/django-template/development/api/serializer/index.md
|
||||
|
||||
- projects/django-template/development/api/serializer/inventory.md
|
||||
|
||||
- Unit Testing:
|
||||
|
||||
- projects/django-template/development/api/tests/index.md
|
||||
|
Reference in New Issue
Block a user