Skip to content

Commit

Permalink
Merge branch 'feat-43-config-group-software' into 'development'
Browse files Browse the repository at this point in the history
feat: config group software

Closes #43 and #53

See merge request nofusscomputing/projects/django_template!22
  • Loading branch information
jon-nfc committed Jun 9, 2024
2 parents 07e9324 + 193dbf1 commit f05e515
Show file tree
Hide file tree
Showing 31 changed files with 2,124 additions and 89 deletions.
31 changes: 24 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ _example structure for the device model that relies upon access app model organi
``` text
├── tests
│   ├── device
│   │   ├── test_device_access_organization.py
│   │   ├── test_device_api_permission.py
│   │   ├── test_device_core_history.py
│   │   ├── test_device_core_notes.py
│   │   ├── test_device_permission.py
│   ├── <model name>
│   │   ├── test_<model name>_access_organization.py
│   │   ├── test_<model name>_api_permission.py
│   │   ├── test_<model name>_core_history.py
│   │   ├── test_<model name>_core_notes.py
│   │   ├── test_<model name>_permission.py
│   │   └── test_device.py
Expand All @@ -71,7 +71,24 @@ Items to test include but are not limited to:

- can access global object (still to require model CRUD permission)

- parent models
- model

- history

- saves history with parent pk and parent class

add to model class the following
``` py
@property
def parent_object(self):
""" Fetch the parent object """
return self.<item that is the parent>
```

history should now be auto saved as long as class `core.mixin.history_save.SaveHistory` is inherited by model.

- history is deleted when item deleted if `parent_pk=None` or if has `parent_pk` deletes history on parent pk being deleted.


### Running Tests
Expand Down
1 change: 1 addition & 0 deletions app/access/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def object_organization(self) -> int:

id = int(self.request.POST.get("organization", ""))


return id


Expand Down
14 changes: 14 additions & 0 deletions app/access/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ def save(self, *args, **kwargs):
modified = AutoLastModifiedField()


@property
def parent_object(self):
""" Fetch the parent object """

return self.organization


def permission_list(self) -> list:

permission_list = []
Expand Down Expand Up @@ -190,3 +197,10 @@ def save(self, *args, **kwargs):

user.groups.add(group)


@property
def parent_object(self):
""" Fetch the parent object """

return self.team

47 changes: 47 additions & 0 deletions app/access/tests/team/test_team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import pytest
import unittest

from django.test import TestCase, Client

from access.models import Organization, Team, TeamUsers, Permission



class TeamModel(TestCase):

model = Team



@classmethod
def setUpTestData(self):
""" Setup Test
"""

self.parent_item = Organization.objects.create(name='test_org')

different_organization = Organization.objects.create(name='test_different_organization')

self.item = self.model.objects.create(
organization=self.parent_item,
name = 'teamone'
)


def test_model_has_property_parent_object(self):
""" Check if model contains 'parent_object'
This is a required property for all models that have a parent
"""

assert hasattr(self.model, 'parent_object')


def test_model_property_parent_object_returns_object(self):
""" Check if model contains 'parent_object'
This is a required property for all models that have a parent
"""

assert self.item.parent_object is self.parent_item
56 changes: 56 additions & 0 deletions app/access/tests/team_user/test_team_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import pytest
import unittest

from django.test import TestCase, Client
from django.contrib.auth.models import User

from access.models import Organization, Team, TeamUsers, Permission



class TeamUsersModel(TestCase):

model = TeamUsers



@classmethod
def setUpTestData(self):
""" Setup Test
"""

organization = Organization.objects.create(name='test_org')

different_organization = Organization.objects.create(name='test_different_organization')

self.parent_item = Team.objects.create(
team_name = 'test_team',
organization = organization,
)

team_user = User.objects.create_user(username="test_self.team_user", password="password")

self.item = self.model.objects.create(
team = self.parent_item,
user = team_user
)



def test_model_has_property_parent_object(self):
""" Check if model contains 'parent_object'
This is a required property for all models that have a parent
"""

assert hasattr(self.model, 'parent_object')


def test_model_property_parent_object_returns_object(self):
""" Check if model contains 'parent_object'
This is a required property for all models that have a parent
"""

assert self.item.parent_object == self.parent_item
33 changes: 33 additions & 0 deletions app/app/helpers/merge_software.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

def merge_software(software: list, new_software: list) -> list:
""" Merge two lists of software actions
Args:
software (list(dict)): Original list to merge over
new_software (list(dict)): new list to use to merge over
Returns:
list(dict): merged list of software actions
"""

merge_software = []

merge: dict = {}

for original in software:

merge.update({
original['name']: original
})

for new in new_software:

merge.update({
new['name']: new
})

for key, value in merge.items():

merge_software = merge_software + [ value ]

return merge_software
88 changes: 88 additions & 0 deletions app/app/tests/test_helpers_merge_software.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from django.conf import settings as django_settings
from django.shortcuts import reverse
from django.test import TestCase, Client

from app.helpers.merge_software import merge_software


import pytest
import unittest


class MergeSoftwareHelper(TestCase):
""" tests for function `merge_software` """

@classmethod
def setUpTestData(self):
self.data: dict = {
'first_list': [
{
'name': 'software_1',
'state': 'install'
},
{
'name': 'software_2',
'state': 'install'
}
],
'second_list': [
{
'name': 'software_1',
'state': 'absent'
},
{
'name': 'software_2',
'state': 'absent'
}
],
'third_list': [
{
'name': 'software_1',
'state': 'other'
},
{
'name': 'software_2',
'state': 'other'
},
{
'name': 'software_3',
'state': 'install'
}
]
}

self.software_list_one = merge_software(self.data['first_list'], self.data['second_list'])

self.software_list_two = merge_software(self.software_list_one, self.data['third_list'])


def test_merging_0_0(self):
""" ensure Second list overwrites the first app1 """

assert self.software_list_one[0]['state'] == 'absent'


def test_merging_0_1(self):
""" ensure Second list overwrites the first app2 """

assert self.software_list_one[1]['state'] == 'absent'



def test_merging_1_0(self):
""" ensure Second list overwrites the first app1 again """

assert self.software_list_two[0]['state'] == 'other'


def test_merging_1_1(self):
""" ensure Second list overwrites the first app2 again """

assert self.software_list_two[1]['state'] == 'other'


def test_merging_1_new_list_item(self):
""" ensure Second list overwrites the first app2 again """

assert len(self.software_list_two) == 3

21 changes: 21 additions & 0 deletions app/config_management/forms/group/add_software.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from django import forms
from django.db.models import Q

from config_management.models.groups import ConfigGroupSoftware
from itam.models.software import Software


class SoftwareAdd(forms.ModelForm):

class Meta:
model = ConfigGroupSoftware
fields = [
'software',
'action'
]

def __init__(self, *args, **kwargs):
organizations = kwargs.pop('organizations')
super().__init__(*args, **kwargs)

self.fields['software'].queryset = Software.objects.filter(Q(organization_id__in=organizations) | Q(is_global = True))
22 changes: 22 additions & 0 deletions app/config_management/forms/group/change_software.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django import forms
from django.db.models import Q

from config_management.models.groups import ConfigGroupSoftware
from itam.models.software import Software, SoftwareVersion


class SoftwareUpdate(forms.ModelForm):

class Meta:
model = ConfigGroupSoftware
fields = [
'action',
'version',
]

def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)

self.fields['version'].queryset = SoftwareVersion.objects.filter(software_id=self.instance.software.id)

36 changes: 36 additions & 0 deletions app/config_management/migrations/0004_configgroupsoftware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 5.0.6 on 2024-06-07 21:43

import access.fields
import access.models
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('access', '0003_alter_team_organization'),
('config_management', '0003_alter_configgrouphosts_organization_and_more'),
('itam', '0013_alter_device_organization_and_more'),
]

operations = [
migrations.CreateModel(
name='ConfigGroupSoftware',
fields=[
('is_global', models.BooleanField(default=False)),
('id', models.AutoField(primary_key=True, serialize=False, unique=True)),
('created', access.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False)),
('modified', access.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False)),
('action', models.CharField(blank=True, choices=[('1', 'Install'), ('0', 'Remove')], default=None, max_length=1, null=True)),
('config_group', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='config_management.configgroups')),
('organization', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists])),
('software', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='itam.software')),
('version', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='itam.softwareversion')),
],
options={
'ordering': ['-action', 'software'],
},
),
]
Loading

0 comments on commit f05e515

Please sign in to comment.