Merge pull request #740 from nofusscomputing/feature-next-release

This commit is contained in:
Jon
2025-05-16 19:46:31 +09:30
committed by GitHub
515 changed files with 14364 additions and 3071 deletions

View File

@ -33,6 +33,8 @@ Describe in detail the following:
- [ ] 🛠️ Migrations added - [ ] 🛠️ Migrations added
- [ ] ♻️ Serializer Created
- [ ] 🔄 [ViewSet Created](https://nofusscomputing.com/projects/centurion_erp/development/views/) - [ ] 🔄 [ViewSet Created](https://nofusscomputing.com/projects/centurion_erp/development/views/)
- [ ] 🔗 URL Route Added - [ ] 🔗 URL Route Added
@ -52,9 +54,9 @@ Describe in detail the following:
- Sub-Models **_ONLY_** - Sub-Models **_ONLY_**
- [ ] Model class variable `history_app_label` set to correct application label - [ ] Model class variable [`history_app_label`](https://nofusscomputing.com/projects/centurion_erp/development/models/#history) set to correct application label
- [ ] Model class variable `history_model_name` set to correct model label - [ ] Model class variable [`history_model_name`](https://nofusscomputing.com/projects/centurion_erp/development/models/#history) set to correct model label
- [ ] 📓 New [Notes model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_notes/) created - [ ] 📓 New [Notes model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_notes/) created
- [ ] 🆕 Model Created - [ ] 🆕 Model Created
@ -77,16 +79,17 @@ Describe in detail the following:
### 🧪 Tests ### 🧪 Tests
- Unit Tests - Unit Tests
- [ ] API Render (fields)
- [ ] [Model](https://nofusscomputing.com/projects/centurion_erp/development/models/#tests) - [ ] [Model](https://nofusscomputing.com/projects/centurion_erp/development/models/#tests)
- [ ] Serializer
- [ ] ViewSet - [ ] ViewSet
- Function Test - Function Test
- [ ] ViewSet - [ ] History API Render (fields)
- [ ] History Entries
- [ ] API Metadata - [ ] API Metadata
- [ ] API Permissions - [ ] API Permissions
- [ ] API Render (fields) - [ ] Model
- [ ] History Entries - [ ] Serializer
- [ ] History API Render (fields) - [ ] ViewSet
## ✅ Requirements ## ✅ Requirements
@ -95,6 +98,24 @@ A Requirement is a must have. In addition will also be tested.
- [ ] Must have a [model_tag](https://nofusscomputing.com/projects/centurion_erp/user/core/markdown/#model-reference) - [ ] Must have a [model_tag](https://nofusscomputing.com/projects/centurion_erp/user/core/markdown/#model-reference)
<!--
When detailing requirements the following must be taken into account:
- what the user should be able to do
- what the user should not be able to do
- what should occur when a user performs an action
-->
- Functional Requirements
- Non-Functional Requirements
--- ---
<!-- Add additional requirement here and as a check box list --> <!-- Add additional requirement here and as a check box list -->

4
.gitignore vendored
View File

@ -1,9 +1,10 @@
venv/** venv/**
*/static/** */static/**
__pycache__ __pycache__
**.sqlite3 **.sqlite*
**.sqlite **.sqlite
**.coverage **.coverage
.coverage*
artifacts/ artifacts/
**.tmp.* **.tmp.*
volumes/ volumes/
@ -19,3 +20,4 @@ package.json
feature_flags.json feature_flags.json
coverage_*.json coverage_*.json
*-coverage.xml *-coverage.xml
log/

View File

@ -23,4 +23,5 @@
"yellow": 60, "yellow": 60,
"green": 90 "green": 90
}, },
"telemetry.feedback.enabled": false,
} }

View File

@ -1,3 +1,26 @@
## Version 1.17.0
- Added setting for log files.
Enables user to specify a default path for centurion's logging. Add the following to your settings file `/etc/itsm/settings.py`
``` py
LOG_FILES = {
"centurion": "/var/log/centurion.log", # Normal Centurion Operations
"weblog": "/var/log/weblog.log", # All web requests made to Centurion
"rest_api": "/var/log/rest_api.log", # Rest API
"catch_all":"/var/log/catch-all.log" # A catch all log. Note: does not log anything that has already been logged.
}
```
With this new setting, the previous setting `LOGGING` will no longer function.
- Renamed `Organization` model to `Tenant` so as to reflect what is actually is.
- `robots.txt` file now being served from the API container at path `/robots.txt` with `User-agent: *` and `Disallow: /`
## Version 1.16.0 ## Version 1.16.0
- Employees model added behind feature flag `2025-00002` and will remain behind this flag until production ready. - Employees model added behind feature flag `2025-00002` and will remain behind this flag until production ready.

View File

@ -1,12 +1,15 @@
import django
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
User = django.contrib.auth.get_user_model()
admin.site.unregister(Group) admin.site.unregister(Group)
class TeamInline(admin.TabularInline): class TeamInline(admin.TabularInline):

View File

@ -3,7 +3,7 @@ from django.db.models import Q
from app import settings from app import settings
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from core.forms.common import CommonModelForm from core.forms.common import CommonModelForm

View File

@ -9,6 +9,7 @@ def permission_queryset():
apps = [ apps = [
'access', 'access',
'accounting',
'assistance', 'assistance',
'config_management', 'config_management',
'core', 'core',
@ -36,14 +37,17 @@ def permission_queryset():
'add_history', 'add_history',
'add_organization', 'add_organization',
'add_taskresult', 'add_taskresult',
'add_ticketcommentaction',
'change_checkin', 'change_checkin',
'change_history', 'change_history',
'change_organization', 'change_organization',
'change_taskresult', 'change_taskresult',
'change_ticketcommentaction',
'delete_checkin', 'delete_checkin',
'delete_history', 'delete_history',
'delete_organization', 'delete_organization',
'delete_taskresult', 'delete_taskresult',
'delete_ticketcommentaction',
'view_checkin', 'view_checkin',
'view_history', 'view_history',
] ]

View File

@ -1,18 +1,22 @@
import django
from django.contrib.auth.middleware import ( from django.contrib.auth.middleware import (
AuthenticationMiddleware, AuthenticationMiddleware,
SimpleLazyObject, SimpleLazyObject,
partial, partial,
) )
from django.contrib.auth.models import User, Group from django.contrib.auth.models import Group
from django.utils.deprecation import MiddlewareMixin from django.utils.deprecation import MiddlewareMixin
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from settings.models.app_settings import AppSettings from settings.models.app_settings import AppSettings
User = django.contrib.auth.get_user_model()
class RequestTenancy(MiddlewareMixin): class RequestTenancy(MiddlewareMixin):
"""Access Middleware """Access Middleware

View File

@ -0,0 +1,25 @@
# Generated by Django 5.1.9 on 2025-05-14 11:06
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('access', '0005_entity_person_entityhistory_entitynotes_role_and_more'),
('assistance', '0005_knowledgebasecategoryhistory_knowledgebasehistory'),
('config_management', '0007_configgroupshistory_configgrouphostshistory_and_more'),
('core', '0022_ticketcommentbase_ticketbase_ticketcommentsolution_and_more'),
('devops', '0011_alter_gitgroup_unique_together_and_more'),
('itam', '0010_alter_software_organization'),
('itim', '0009_slmticket_requestticket'),
('project_management', '0005_projecthistory_projectmilestonehistory_and_more'),
('settings', '0011_appsettingshistory_externallinkhistory'),
]
operations = [
migrations.RenameModel(
old_name = 'Organization',
new_name = 'Tenant'
),
]

View File

@ -0,0 +1,47 @@
# Generated by Django 5.1.9 on 2025-05-14 13:48
import access.models.team
import access.models.tenancy
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0007_rename_organization_tenant'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterModelOptions(
name='tenant',
options={'ordering': ['name'], 'verbose_name': 'Tenant', 'verbose_name_plural': 'Tenants'},
),
migrations.AlterField(
model_name='entity',
name='organization',
field=models.ForeignKey(help_text='Tenancy this belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='+', to='access.tenant', validators=[access.models.tenancy.TenancyObject.validatate_organization_exists], verbose_name='Tenant'),
),
migrations.AlterField(
model_name='role',
name='organization',
field=models.ForeignKey(help_text='Tenancy this belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='+', to='access.tenant', validators=[access.models.tenancy.TenancyObject.validatate_organization_exists], verbose_name='Tenant'),
),
migrations.AlterField(
model_name='team',
name='organization',
field=models.ForeignKey(help_text='Tenant this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.tenant', validators=[access.models.team.Team.validatate_organization_exists], verbose_name='Tenant'),
),
migrations.AlterField(
model_name='tenant',
name='manager',
field=models.ForeignKey(help_text='Manager for this Tenancy', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Manager'),
),
migrations.AlterField(
model_name='tenant',
name='name',
field=models.CharField(help_text='Name of this Tenancy', max_length=50, unique=True, verbose_name='Name'),
),
]

View File

@ -0,0 +1,135 @@
from django.contrib.auth.models import ContentType, Permission
from django.db import migrations
from access.models.team import Team
ContentType.DoesNotExist
def add_tenancy_permissions(apps, schema_editor):
print('')
print(f"Begin permission migration for rename of Organization to Tenant.")
try:
add_permission = Permission.objects.get(
codename = 'add_tenant',
content_type = ContentType.objects.get(
app_label = 'access',
model = 'tenant',
)
)
change_permission = Permission.objects.get(
codename = 'change_tenant',
content_type = ContentType.objects.get(
app_label = 'access',
model = 'tenant',
)
)
delete_permission = Permission.objects.get(
codename = 'delete_tenant',
content_type = ContentType.objects.get(
app_label = 'access',
model = 'tenant',
)
)
view_permission = Permission.objects.get(
codename = 'view_tenant',
content_type = ContentType.objects.get(
app_label = 'access',
model = 'tenant',
)
)
print(f' Searching for Teams.')
teams = Team.objects.select_related('group_ptr__permissions')
print(f'Found {str(len(teams))} Teams.')
for team in teams:
print(f' Processing Team {str(team.team_name)}.')
permissions = team.group_ptr.permissions.all()
print(f' Searching for Organization Permissions.')
print(f' Found {str(len(permissions))} Permissions.')
for permission in permissions:
if '_organization' not in permission.codename:
continue
action = str(permission.codename).split('_')[0]
print(f' Found Organization Permission {str(action)}')
if action == 'add':
team.group_ptr.permissions.add( add_permission )
print(f' Add Tenant Permission {str(action)}')
team.group_ptr.permissions.remove( permission )
print(f' Remove Organization Permission {str(action)}')
elif action == 'change':
team.group_ptr.permissions.add( change_permission )
print(f' Add Tenant Permission {str(action)}')
team.group_ptr.permissions.remove( permission )
print(f' Remove Organization Permission {str(action)}')
elif action == 'delete':
team.group_ptr.permissions.add( delete_permission )
print(f' Add Tenant Permission {str(action)}')
team.group_ptr.permissions.remove( permission )
print(f' Remove Organization Permission {str(action)}')
elif action == 'view':
team.group_ptr.permissions.add( view_permission )
print(f' Add Tenant Permission {str(action)}')
team.group_ptr.permissions.remove( permission )
print(f' Remove Organization Permission {str(action)}')
print(f' Completed Team {str(team.team_name)}.')
except ContentType.DoesNotExist:
# DB is new so no content types. no migration to be done.
pass
print(' Permission Migration Actions Complete.')
class Migration(migrations.Migration):
dependencies = [
('access', '0008_alter_tenant_options_alter_entity_organization_and_more'),
]
operations = [
migrations.RunPython(add_tenancy_permissions),
]

View File

@ -0,0 +1,43 @@
# Generated by Django 5.1.9 on 2025-05-16 09:58
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0009_migrate_organization_permission_tenant'),
]
operations = [
migrations.CreateModel(
name='Company',
fields=[
('entity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='access.entity')),
('name', models.CharField(help_text='The name of this entity', max_length=80, verbose_name='Name')),
],
options={
'verbose_name': 'Company',
'verbose_name_plural': 'Companies',
'ordering': ['name'],
'sub_model_type': 'company',
},
bases=('access.entity',),
),
migrations.AlterField(
model_name='entity',
name='entity_type',
field=models.CharField(help_text='Type this entity is', max_length=30, verbose_name='Entity Type'),
),
migrations.AlterField(
model_name='person',
name='dob',
field=models.DateField(blank=True, help_text='The Persons Date of Birth (DOB)', null=True, verbose_name='DOB'),
),
migrations.AlterField(
model_name='person',
name='m_name',
field=models.CharField(blank=True, help_text='The persons middle name(s)', max_length=100, null=True, verbose_name='Middle Name(s)'),
),
]

View File

@ -4,7 +4,7 @@ from django.contrib.auth.models import Group
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.utils.functional import cached_property from django.utils.functional import cached_property
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
@ -260,7 +260,7 @@ class OrganizationMixin():
self.permission_required = permissions_required self.permission_required = permissions_required
organization_manager_models = [ organization_manager_models = [
'access.organization', 'access.tenant',
'access.team', 'access.team',
'access.teamusers', 'access.teamusers',
] ]
@ -326,7 +326,7 @@ class OrganizationMixin():
if required_permission.replace( if required_permission.replace(
'view_', '' 'view_', ''
) == 'access.organization' and len(self.kwargs) == 0: ) == 'access.tenant' and len(self.kwargs) == 0:
return True return True

View File

@ -1,9 +1,13 @@
from django.contrib.auth.models import User, Group import django
from django.contrib.auth.models import Group
from django.db import models from django.db import models
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
User = django.contrib.auth.get_user_model()
class OrganizationMixin: class OrganizationMixin:
@ -89,7 +93,7 @@ class OrganizationMixin:
self._obj_organization = obj.organization self._obj_organization = obj.organization
elif str(self.model._meta.verbose_name).lower() == 'organization': elif str(self.model._meta.verbose_name).lower() == 'tenant':
self._obj_organization = obj self._obj_organization = obj
@ -130,7 +134,7 @@ class OrganizationMixin:
parent_model (Model): with PK from kwargs['pk'] parent_model (Model): with PK from kwargs['pk']
""" """
return self.parent_model.objects.get(pk=self.kwargs[self.parent_model_pk_kwarg]) return self.get_parent_model().objects.get(pk=self.kwargs[self.parent_model_pk_kwarg])

View File

@ -5,7 +5,7 @@ from django.core.exceptions import ObjectDoesNotExist
from rest_framework import exceptions from rest_framework import exceptions
from rest_framework.permissions import DjangoObjectPermissions from rest_framework.permissions import DjangoObjectPermissions
from access.models.tenancy import Organization, TenancyObject from access.models.tenancy import Tenant, TenancyObject
from core import exceptions as centurion_exceptions from core import exceptions as centurion_exceptions
@ -14,10 +14,10 @@ from core import exceptions as centurion_exceptions
class OrganizationPermissionMixin( class OrganizationPermissionMixin(
DjangoObjectPermissions, DjangoObjectPermissions,
): ):
"""Organization Permission Mixin """Tenant Permission Mixin
This class is to be used as the permission class for API `Views`/`ViewSets`. This class is to be used as the permission class for API `Views`/`ViewSets`.
In combination with the `OrganizationPermissionsMixin`, permission checking In combination with the `TenantPermissionsMixin`, permission checking
will be done to ensure the user has the correct permissions to perform the will be done to ensure the user has the correct permissions to perform the
CRUD operation. CRUD operation.
@ -166,7 +166,7 @@ class OrganizationPermissionMixin(
raise centurion_exceptions.PermissionDenied() raise centurion_exceptions.PermissionDenied()
obj_organization: Organization = view.get_obj_organization( obj_organization: Tenant = view.get_obj_organization(
request = request request = request
) )

View File

@ -1,2 +1,4 @@
from . import contact from . import contact
from . import company_base
from . import person from . import person
from . import role

View File

@ -0,0 +1,102 @@
from django.db import models
from access.models.entity import Entity
class Company(
Entity
):
# This model is intended to be called `Organization`, however at the time of
# creation this was not possible as Tenant (ne Organization) still has
# references in code to `organization` witch clashes with the intended name of
# this model.
class Meta:
ordering = [
'name',
]
sub_model_type = 'company'
verbose_name = 'Company'
verbose_name_plural = 'Companies'
name = models.CharField(
blank = False,
help_text = 'The name of this entity',
max_length = 80,
unique = False,
verbose_name = 'Name'
)
def __str__(self) -> str:
return self.name
documentation = ''
history_model_name = 'company'
page_layout: dict = [
{
"name": "Details",
"slug": "details",
"sections": [
{
"layout": "double",
"left": [
'organization',
'name',
],
"right": [
'model_notes',
'created',
'modified',
]
}
]
},
{
"name": "Knowledge Base",
"slug": "kb_articles",
"sections": [
{
"layout": "table",
"field": "knowledge_base",
}
]
},
{
"name": "Tickets",
"slug": "tickets",
"sections": [
{
"layout": "table",
"field": "tickets",
}
]
},
{
"name": "Notes",
"slug": "notes",
"sections": []
},
]
table_fields: list = [
'name',
'organization',
'created',
]
def clean(self):
super().clean()

View File

@ -37,9 +37,9 @@ class Entity(
verbose_name = 'ID' verbose_name = 'ID'
) )
entity_type = models.CharField( entity_type = models.CharField(
blank = False, blank = False,
default = Meta.verbose_name.lower(),
help_text = 'Type this entity is', help_text = 'Type this entity is',
max_length = 30, max_length = 30,
unique = False, unique = False,

View File

@ -1,155 +1 @@
from django.db import models from .tenant import Tenant as Organization
from django.contrib.auth.models import User
from rest_framework.reverse import reverse
from access.fields import (
AutoCreatedField,
AutoLastModifiedField,
AutoSlugField
)
from core.mixin.history_save import SaveHistory
class Organization(SaveHistory):
class Meta:
verbose_name = "Organization"
verbose_name_plural = "Organizations"
ordering = ['name']
def save(self, *args, **kwargs):
if self.slug == '_':
self.slug = self.name.lower().replace(' ', '_')
super().save(*args, **kwargs)
id = models.AutoField(
blank=False,
help_text = 'ID of this item',
primary_key=True,
unique=True,
verbose_name = 'ID'
)
name = models.CharField(
blank = False,
help_text = 'Name of this Organization',
max_length = 50,
unique = True,
verbose_name = 'Name'
)
manager = models.ForeignKey(
User,
blank = False,
help_text = 'Manager for this organization',
null = True,
on_delete=models.SET_NULL,
verbose_name = 'Manager'
)
model_notes = models.TextField(
blank = True,
default = None,
help_text = 'Tid bits of information',
null= True,
verbose_name = 'Notes',
)
slug = AutoSlugField()
created = AutoCreatedField()
modified = AutoLastModifiedField()
def get_organization(self):
return self
def __int__(self):
return self.id
def __str__(self):
return self.name
table_fields: list = [
'nbsp',
'name',
'created',
'modified',
'nbsp'
]
page_layout: list = [
{
"name": "Details",
"slug": "details",
"sections": [
{
"layout": "double",
"left": [
'name',
'manager',
'created',
'modified',
],
"right": [
'model_notes',
]
}
]
},
{
"name": "Teams",
"slug": "teams",
"sections": [
{
"layout": "table",
"field": "teams"
}
]
},
{
"name": "Knowledge Base",
"slug": "kb_articles",
"sections": [
{
"layout": "table",
"field": "knowledge_base",
}
]
},
{
"name": "Notes",
"slug": "notes",
"sections": []
}
]
def get_url( self, request = None ) -> str:
if request:
return reverse("v2:_api_v2_organization-detail", request=request, kwargs={'pk': self.id})
return reverse("v2:_api_v2_organization-detail", kwargs={'pk': self.id})
def save_history(self, before: dict, after: dict) -> bool:
from access.models.organization_history import OrganizationHistory
history = super().save_history(
before = before,
after = after,
history_model = OrganizationHistory
)
return history

View File

@ -2,7 +2,7 @@ from django.db import models
from core.models.model_history import ModelHistory from core.models.model_history import ModelHistory
from access.models.organization import Organization from access.models.tenant import Tenant
@ -23,7 +23,7 @@ class OrganizationHistory(
model = models.ForeignKey( model = models.ForeignKey(
Organization, Tenant,
blank = False, blank = False,
help_text = 'Model this note belongs to', help_text = 'Model this note belongs to',
null = False, null = False,
@ -46,8 +46,8 @@ class OrganizationHistory(
model = None model = None
from access.serializers.organization import OrganizationBaseSerializer from access.serializers.organization import TenantBaseSerializer
model = OrganizationBaseSerializer(self.model, context = serializer_context) model = TenantBaseSerializer(self.model, context = serializer_context)
return model return model

View File

@ -1,6 +1,6 @@
from django.db import models from django.db import models
from access.models.organization import Organization from access.models.tenant import Tenant
from core.models.model_notes import ModelNotes from core.models.model_notes import ModelNotes
@ -23,7 +23,7 @@ class OrganizationNotes(
model = models.ForeignKey( model = models.ForeignKey(
Organization, Tenant,
blank = False, blank = False,
help_text = 'Model this note belongs to', help_text = 'Model this note belongs to',
null = False, null = False,

View File

@ -36,7 +36,6 @@ class Person(
m_name = models.CharField( m_name = models.CharField(
blank = True, blank = True,
default = None,
help_text = 'The persons middle name(s)', help_text = 'The persons middle name(s)',
max_length = 100, max_length = 100,
null = True, null = True,
@ -54,7 +53,6 @@ class Person(
dob = models.DateField( dob = models.DateField(
blank = True, blank = True,
default = None,
help_text = 'The Persons Date of Birth (DOB)', help_text = 'The Persons Date of Birth (DOB)',
null = True, null = True,
unique = False, unique = False,

View File

@ -8,7 +8,7 @@ from access.fields import (
AutoLastModifiedField AutoLastModifiedField
) )
from access.models.organization import Organization from access.models.tenant import Tenant
from access.models.tenancy import TenancyObject from access.models.tenancy import TenancyObject
from core import exceptions as centurion_exceptions from core import exceptions as centurion_exceptions
@ -55,13 +55,13 @@ class Team(Group, TenancyObject):
) )
organization = models.ForeignKey( organization = models.ForeignKey(
Organization, Tenant,
blank = False, blank = False,
help_text = 'Organization this belongs to', help_text = 'Tenant this belongs to',
null = False, null = False,
on_delete = models.CASCADE, on_delete = models.CASCADE,
validators = [validatate_organization_exists], validators = [validatate_organization_exists],
verbose_name = 'Organization' verbose_name = 'Tenant'
) )
created = AutoCreatedField() created = AutoCreatedField()

View File

@ -1,6 +1,8 @@
import django
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from django.contrib.auth.models import User, Group from django.contrib.auth.models import Group
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
@ -9,12 +11,14 @@ from access.fields import (
AutoLastModifiedField AutoLastModifiedField
) )
from access.models.organization import Organization from access.models.tenant import Tenant
from access.models.team import Team from access.models.team import Team
from core.lib.feature_not_used import FeatureNotUsed from core.lib.feature_not_used import FeatureNotUsed
from core.mixin.history_save import SaveHistory from core.mixin.history_save import SaveHistory
User = django.contrib.auth.get_user_model()
class TeamUsers(SaveHistory): class TeamUsers(SaveHistory):
@ -95,7 +99,7 @@ class TeamUsers(SaveHistory):
user.groups.remove(group) user.groups.remove(group)
def get_organization(self) -> Organization: def get_organization(self) -> Tenant:
return self.team.organization return self.team.organization

View File

@ -1,12 +1,11 @@
# from django.conf import settings import django
import logging
from django.db import models from django.db import models
# from django.contrib.auth.models import User, Group
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
# from .fields import * from access.models.tenant import Tenant
from access.models.organization import Organization
from core import exceptions as centurion_exceptions from core import exceptions as centurion_exceptions
from core.middleware.get_request import get_request from core.middleware.get_request import get_request
@ -137,14 +136,14 @@ class TenancyObject(SaveHistory):
) )
organization = models.ForeignKey( organization = models.ForeignKey(
Organization, Tenant,
blank = False, blank = False,
help_text = 'Organization this belongs to', help_text = 'Tenancy this belongs to',
null = False, null = False,
on_delete = models.CASCADE, on_delete = models.CASCADE,
related_name = '+', related_name = '+',
validators = [validatate_organization_exists], validators = [validatate_organization_exists],
verbose_name = 'Organization' verbose_name = 'Tenant'
) )
is_global = models.BooleanField( is_global = models.BooleanField(
@ -162,7 +161,7 @@ class TenancyObject(SaveHistory):
verbose_name = 'Notes', verbose_name = 'Notes',
) )
def get_organization(self) -> Organization: def get_organization(self) -> Tenant:
return self.organization return self.organization
app_namespace: str = None app_namespace: str = None
@ -193,6 +192,16 @@ class TenancyObject(SaveHistory):
only be used when there is model inheritence. only be used when there is model inheritence.
""" """
_log: logging.Logger = None
def get_log(self):
if self._log is None:
self._log = logging.getLogger('centurion.' + self._meta.app_label)
return self._log
page_layout: list = None page_layout: list = None
note_basename: str = None note_basename: str = None
@ -282,7 +291,7 @@ class TenancyObject(SaveHistory):
raise centurion_exceptions.ValidationError( raise centurion_exceptions.ValidationError(
detail = { detail = {
'organization': 'Organization is required' 'organization': 'Tenant is required'
}, },
code = 'required' code = 'required'
) )

161
app/access/models/tenant.py Normal file
View File

@ -0,0 +1,161 @@
import django
from django.conf import settings
from django.db import models
from rest_framework.reverse import reverse
from access.fields import (
AutoCreatedField,
AutoLastModifiedField,
AutoSlugField
)
from core.mixin.history_save import SaveHistory
User = django.contrib.auth.get_user_model()
class Tenant(SaveHistory):
class Meta:
verbose_name = "Tenant"
verbose_name_plural = "Tenants"
ordering = ['name']
def save(self, *args, **kwargs):
if self.slug == '_':
self.slug = self.name.lower().replace(' ', '_')
super().save(*args, **kwargs)
id = models.AutoField(
blank=False,
help_text = 'ID of this item',
primary_key=True,
unique=True,
verbose_name = 'ID'
)
name = models.CharField(
blank = False,
help_text = 'Name of this Tenancy',
max_length = 50,
unique = True,
verbose_name = 'Name'
)
manager = models.ForeignKey(
settings.AUTH_USER_MODEL,
blank = False,
help_text = 'Manager for this Tenancy',
null = True,
on_delete=models.SET_NULL,
verbose_name = 'Manager'
)
model_notes = models.TextField(
blank = True,
default = None,
help_text = 'Tid bits of information',
null= True,
verbose_name = 'Notes',
)
slug = AutoSlugField()
created = AutoCreatedField()
modified = AutoLastModifiedField()
def get_organization(self):
return self
def __int__(self):
return self.id
def __str__(self):
return self.name
table_fields: list = [
'nbsp',
'name',
'created',
'modified',
'nbsp'
]
page_layout: list = [
{
"name": "Details",
"slug": "details",
"sections": [
{
"layout": "double",
"left": [
'name',
'manager',
'created',
'modified',
],
"right": [
'model_notes',
]
}
]
},
{
"name": "Teams",
"slug": "teams",
"sections": [
{
"layout": "table",
"field": "teams"
}
]
},
{
"name": "Knowledge Base",
"slug": "kb_articles",
"sections": [
{
"layout": "table",
"field": "knowledge_base",
}
]
},
{
"name": "Notes",
"slug": "notes",
"sections": []
}
]
def get_url( self, request = None ) -> str:
if request:
return reverse("v2:_api_v2_organization-detail", request=request, kwargs={'pk': self.id})
return reverse("v2:_api_v2_organization-detail", kwargs={'pk': self.id})
def save_history(self, before: dict, after: dict) -> bool:
from access.models.organization_history import OrganizationHistory
history = super().save_history(
before = before,
after = after,
history_model = OrganizationHistory
)
return history
Organization = Tenant

View File

@ -6,7 +6,7 @@ from access.models.entity import Entity
from api.serializers import common from api.serializers import common
from access.serializers.organization import OrganizationBaseSerializer from access.serializers.organization import TenantBaseSerializer
@ -87,4 +87,4 @@ class ModelSerializer(
class ViewSerializer(ModelSerializer): class ViewSerializer(ModelSerializer):
"""Entity Base View Model""" """Entity Base View Model"""
organization = OrganizationBaseSerializer(many=False, read_only=True) organization = TenantBaseSerializer(many=False, read_only=True)

View File

@ -0,0 +1,70 @@
from drf_spectacular.utils import extend_schema_serializer
from access.models.company_base import Company
from access.serializers.entity import (
BaseSerializer as BaseBaseSerializer,
ModelSerializer as BaseModelSerializer,
)
from access.serializers.organization import TenantBaseSerializer
class BaseSerializer(
BaseBaseSerializer,
):
pass
@extend_schema_serializer(component_name = 'CompanyEntityModelSerializer')
class ModelSerializer(
BaseSerializer,
BaseModelSerializer,
):
"""Company Model
This model inherits from the Entity base model.
"""
class Meta:
model = Company
fields = [
'id',
'entity_ptr_id',
'organization',
'entity_type',
'display_name',
'name',
'model_notes',
'is_global',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'entity_type',
'created',
'modified',
'_urls',
]
@extend_schema_serializer(component_name = 'CompanyEntityViewSerializer')
class ViewSerializer(
ModelSerializer,
):
"""Company View Model
This model inherits from the Entity base model.
"""
organization = TenantBaseSerializer(many=False, read_only=True)

View File

@ -6,7 +6,7 @@ from access.serializers.entity_person import (
BaseSerializer as BaseBaseSerializer, BaseSerializer as BaseBaseSerializer,
ModelSerializer as BaseModelSerializer, ModelSerializer as BaseModelSerializer,
) )
from access.serializers.organization import OrganizationBaseSerializer from access.serializers.organization import TenantBaseSerializer
@ -72,4 +72,4 @@ class ViewSerializer(
This model inherits from the Person model. This model inherits from the Person model.
""" """
organization = OrganizationBaseSerializer(many=False, read_only=True) organization = TenantBaseSerializer(many=False, read_only=True)

View File

@ -6,7 +6,7 @@ from access.serializers.entity import (
BaseSerializer as BaseBaseSerializer, BaseSerializer as BaseBaseSerializer,
ModelSerializer as BaseModelSerializer, ModelSerializer as BaseModelSerializer,
) )
from access.serializers.organization import OrganizationBaseSerializer from access.serializers.organization import TenantBaseSerializer
@ -70,4 +70,4 @@ class ViewSerializer(
This model inherits from the Entity base model. This model inherits from the Entity base model.
""" """
organization = OrganizationBaseSerializer(many=False, read_only=True) organization = TenantBaseSerializer(many=False, read_only=True)

View File

@ -2,15 +2,16 @@ from rest_framework.reverse import reverse
from rest_framework import serializers from rest_framework import serializers
from access.models.organization import Organization from access.models.tenant import Tenant
from app.serializers.user import UserBaseSerializer from app.serializers.user import UserBaseSerializer
from core import fields as centurion_field from core import fields as centurion_field
Organization = Tenant
class OrganizationBaseSerializer(serializers.ModelSerializer): class TenantBaseSerializer(serializers.ModelSerializer):
display_name = serializers.SerializerMethodField('get_display_name') display_name = serializers.SerializerMethodField('get_display_name')
@ -24,7 +25,7 @@ class OrganizationBaseSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Organization model = Tenant
fields = [ fields = [
'id', 'id',
@ -42,8 +43,8 @@ class OrganizationBaseSerializer(serializers.ModelSerializer):
class OrganizationModelSerializer( class TenantModelSerializer(
OrganizationBaseSerializer TenantBaseSerializer
): ):
_urls = serializers.SerializerMethodField('get_url') _urls = serializers.SerializerMethodField('get_url')
@ -74,7 +75,7 @@ class OrganizationModelSerializer(
class Meta: class Meta:
model = Organization model = Tenant
fields = '__all__' fields = '__all__'
@ -98,7 +99,7 @@ class OrganizationModelSerializer(
] ]
class OrganizationViewSerializer(OrganizationModelSerializer): class TenantViewSerializer(TenantModelSerializer):
pass pass
manager = UserBaseSerializer(many=False, read_only = True) manager = UserBaseSerializer(many=False, read_only = True)

View File

@ -5,7 +5,7 @@ from drf_spectacular.utils import extend_schema_serializer
from access.functions.permissions import permission_queryset from access.functions.permissions import permission_queryset
from access.models.role import Role from access.models.role import Role
from access.serializers.organization import OrganizationBaseSerializer from access.serializers.organization import TenantBaseSerializer
from api.serializers import common from api.serializers import common
@ -109,6 +109,6 @@ class ModelSerializer(
class ViewSerializer(ModelSerializer): class ViewSerializer(ModelSerializer):
"""Role Base View Model""" """Role Base View Model"""
organization = OrganizationBaseSerializer( many=False, read_only=True ) organization = TenantBaseSerializer( many=False, read_only=True )
permissions = PermissionBaseSerializer( many=True, read_only=True ) permissions = PermissionBaseSerializer( many=True, read_only=True )

View File

@ -7,7 +7,7 @@ from access.models.team import Team
from api.serializers import common from api.serializers import common
from access.functions.permissions import permission_queryset from access.functions.permissions import permission_queryset
from access.serializers.organization import OrganizationBaseSerializer from access.serializers.organization import TenantBaseSerializer
from app.serializers.permission import Permission, PermissionBaseSerializer from app.serializers.permission import Permission, PermissionBaseSerializer
@ -127,6 +127,6 @@ class TeamModelSerializer(
class TeamViewSerializer(TeamModelSerializer): class TeamViewSerializer(TeamModelSerializer):
organization = OrganizationBaseSerializer(many=False, read_only=True) organization = TenantBaseSerializer(many=False, read_only=True)
permissions = PermissionBaseSerializer(many = True) permissions = PermissionBaseSerializer(many = True)

View File

@ -0,0 +1,24 @@
import pytest
from access.models.company_base import Company
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Company
yield request.cls.model
del request.cls.model
@pytest.fixture(scope='function')
def create_serializer():
from access.serializers.entity_company import ModelSerializer
yield ModelSerializer

View File

@ -0,0 +1,72 @@
from django.test import TestCase
from access.models.company_base import Company
from access.tests.functional.entity.test_functional_entity_metadata import (
EntityMetadataInheritedCases
)
class CompanyMetadataTestCases(
EntityMetadataInheritedCases,
):
add_data: dict = {
'name': 'Ian1'
}
kwargs_create_item: dict = {
'name': 'Ian2',
}
kwargs_create_item_diff_org: dict = {
'name': 'Ian3',
}
model = Company
class CompanyMetadataInheritedCases(
CompanyMetadataTestCases,
):
model = None
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
# self.url_kwargs = {
# 'entity_model': self.model._meta.sub_model_type
# }
# self.url_view_kwargs = {
# 'entity_model': self.model._meta.sub_model_type
# }
super().setUpTestData()
class CompanyMetadataTest(
CompanyMetadataTestCases,
TestCase,
):
pass

View File

@ -0,0 +1,43 @@
import pytest
from access.tests.functional.entity.test_functional_entity_permission import (
EntityPermissionsAPIInheritedCases
)
class CompanyPermissionsAPITestCases(
EntityPermissionsAPIInheritedCases,
):
add_data: dict = {
'name': 'Ian1',
}
kwargs_create_item: dict = {
'name': 'Ian2',
}
kwargs_create_item_diff_org: dict = {
'name': 'Ian3',
}
class CompanyPermissionsAPIInheritedCases(
CompanyPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
class CompanyPermissionsAPIPyTest(
CompanyPermissionsAPITestCases,
):
pass

View File

@ -0,0 +1,46 @@
import pytest
from rest_framework.exceptions import ValidationError
from access.tests.functional.entity.test_functional_entity_serializer import (
MockView,
EntitySerializerInheritedCases
)
class CompanySerializerTestCases(
EntitySerializerInheritedCases
):
parameterized_test_data: dict = {
"name": {
'will_create': False,
'exception_key': 'required'
},
}
valid_data: dict = {
'name': 'Ian',
}
"""Valid data used by serializer to create object"""
class CompanySerializerInheritedCases(
CompanySerializerTestCases,
):
parameterized_test_data: dict = None
valid_data: dict = None
"""Valid data used by serializer to create object"""
class CompanySerializerPyTest(
CompanySerializerTestCases,
):
parameterized_test_data: dict = None

View File

@ -0,0 +1,58 @@
from django.test import TestCase
from access.models.company_base import Company
from access.tests.functional.entity.test_functional_entity_viewset import (
EntityViewSetInheritedCases
)
class ViewSetTestCases(
EntityViewSetInheritedCases,
):
add_data: dict = {
'name': 'Ian',
}
kwargs_create_item: dict = {
'name': 'Ian2',
}
kwargs_create_item_diff_org: dict = {
'name': 'Ian3',
}
model = Company
class CompanyViewSetInheritedCases(
ViewSetTestCases,
):
model = None
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
super().setUpTestData()
class CompanyViewSetTest(
ViewSetTestCases,
TestCase,
):
pass

View File

@ -0,0 +1,24 @@
import pytest
from access.models.contact import Contact
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Contact
yield request.cls.model
del request.cls.model
@pytest.fixture(scope='function')
def create_serializer():
from access.serializers.entity_contact import ModelSerializer
yield ModelSerializer

View File

@ -0,0 +1,65 @@
from django.test import TestCase
from access.models.contact import Contact
from access.tests.functional.person.test_functional_person_metadata import (
PersonMetadataInheritedCases
)
class ContactMetadataTestCases(
PersonMetadataInheritedCases,
):
add_data: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item: dict = {
'email': 'ipweird@unit.test',
}
kwargs_create_item_diff_org: dict = {
'email': 'ipstrange@unit.test',
}
model = Contact
class ContactMetadataInheritedCases(
ContactMetadataTestCases,
):
model = None
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
super().setUpTestData()
class ContactMetadataTest(
ContactMetadataTestCases,
TestCase,
):
pass

View File

@ -0,0 +1,70 @@
import pytest
from access.tests.functional.person.test_functional_person_permission import (
PersonPermissionsAPIInheritedCases
)
class ContactPermissionsAPITestCases(
PersonPermissionsAPIInheritedCases,
):
add_data: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item: dict = {
'email': 'ipweird@unit.test',
}
kwargs_create_item_diff_org: dict = {
'email': 'ipstrange@unit.test',
}
class ContactPermissionsAPIInheritedCases(
ContactPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
# url_name = '_api_v2_entity_sub'
# @pytest.fixture(scope='class')
# def inherited_var_setup(self, request):
# request.cls.url_kwargs.update({
# 'entity_model': self.model._meta.sub_model_type
# })
# request.cls.url_view_kwargs.update({
# 'entity_model': self.model._meta.sub_model_type
# })
# @pytest.fixture(scope='class', autouse = True)
# def class_setup(self, request, django_db_blocker,
# model,
# var_setup,
# prepare,
# inherited_var_setup,
# diff_org_model,
# create_model,
# ):
# pass
class ContactPermissionsAPIPyTest(
ContactPermissionsAPITestCases,
):
pass

View File

@ -1,129 +1,46 @@
import pytest import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from access.serializers.entity_contact import (
Contact,
ModelSerializer
)
from access.tests.functional.person.test_functional_person_serializer import ( from access.tests.functional.person.test_functional_person_serializer import (
MockView,
PersonSerializerInheritedCases PersonSerializerInheritedCases
) )
class SerializerTestCases( class ContactSerializerTestCases(
PersonSerializerInheritedCases, PersonSerializerInheritedCases
): ):
duplicate_f_name_l_name_dob = {
'email': 'contactentityduplicateone@unit.test', parameterized_test_data: dict = {
"email": {
'will_create': False,
'exception_key': 'required'
}
} }
kwargs_create_item: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item_duplicate_f_name_l_name_dob = {
'email': 'contactentityduplicatetwo@unit.test',
}
model = Contact
"""Model to test"""
create_model_serializer = ModelSerializer
"""Serializer to test"""
valid_data: dict = { valid_data: dict = {
'email': 'ipweird@unit.test', 'email': 'contactentityduplicatetwo@unit.test',
} }
"""Valid data used by serializer to create object"""
def test_serializer_validation_no_email_exception(self):
"""Serializer Validation Check
Ensure that when creating with valid data and field email is missing
a validation error occurs.
"""
data = self.valid_data.copy()
del data['email']
with pytest.raises(ValidationError) as err:
serializer = self.create_model_serializer(
data = data
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['email'][0] == 'required'
class ContactSerializerInheritedCases( class ContactSerializerInheritedCases(
SerializerTestCases, ContactSerializerTestCases,
): ):
create_model_serializer = None parameterized_test_data: dict = None
"""Serializer to test"""
duplicate_f_name_l_name_dob: dict = None
""" Duplicate model serializer dict
used for testing for duplicate f_name, l_name and dob fields.
"""
kwargs_create_item: dict = None
""" Model kwargs to create item"""
kwargs_create_item_duplicate_f_name_l_name_dob: dict = None
"""model kwargs to create object
**None:** Ensure that the fields of sub-model to person do not match
`self.duplicate_f_name_l_name_dob`. if they do the wrong exception will be thrown.
used for testing for duplicate f_name, l_name and dob fields.
"""
model = None
"""Model to test"""
valid_data: dict = None valid_data: dict = None
"""Valid data used by serializer to create object""" """Valid data used by serializer to create object"""
@classmethod
def setUpTestData(self):
"""Setup Test"""
self.duplicate_f_name_l_name_dob.update( class ContactSerializerPyTest(
super().duplicate_f_name_l_name_dob ContactSerializerTestCases,
)
self.kwargs_create_item_duplicate_f_name_l_name_dob.update(
super().kwargs_create_item_duplicate_f_name_l_name_dob
)
self.kwargs_create_item.update(
super().kwargs_create_item
)
self.valid_data.update(
super().valid_data
)
super().setUpTestData()
class ContactSerializerTest(
SerializerTestCases,
TestCase,
): ):
pass parameterized_test_data: dict = None

View File

@ -2,91 +2,28 @@ from django.test import TestCase
from access.models.contact import Contact from access.models.contact import Contact
from access.tests.functional.person.test_functional_person_viewset import ( from access.tests.functional.person.test_functional_person_viewset import (
PersonMetadataInheritedCases,
PersonPermissionsAPIInheritedCases,
PersonViewSetInheritedCases PersonViewSetInheritedCases
) )
class ViewSetBase:
add_data = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item_diff_org = {
'email': 'ipstrange@unit.test',
}
kwargs_create_item = {
'email': 'ipweird@unit.test',
}
model = Contact
url_kwargs: dict = {}
url_view_kwargs: dict = {}
class PermissionsAPITestCases(
ViewSetBase,
PersonPermissionsAPIInheritedCases,
):
pass
class ContactPermissionsAPIInheritedCases(
PermissionsAPITestCases,
):
add_data: dict = None
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@classmethod
def setUpTestData(self):
self.add_data.update(
super().add_data
)
self.kwargs_create_item.update(
super().kwargs_create_item
)
self.kwargs_create_item_diff_org.update(
super().kwargs_create_item_diff_org
)
super().setUpTestData()
class ContactPermissionsAPITest(
PermissionsAPITestCases,
TestCase,
):
pass
class ViewSetTestCases( class ViewSetTestCases(
ViewSetBase,
PersonViewSetInheritedCases, PersonViewSetInheritedCases,
): ):
pass add_data: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item: dict = {
'email': 'ipweird@unit.test',
}
kwargs_create_item_diff_org: dict = {
'email': 'ipstrange@unit.test',
}
model = Contact
@ -96,21 +33,19 @@ class ContactViewSetInheritedCases(
model = None model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@classmethod @classmethod
def setUpTestData(self): def setUpTestData(self):
self.kwargs_create_item.update( self.kwargs_create_item = {
super().kwargs_create_item **super().kwargs_create_item,
) **self.kwargs_create_item
}
self.kwargs_create_item_diff_org.update( self.kwargs_create_item_diff_org = {
super().kwargs_create_item_diff_org **super().kwargs_create_item_diff_org,
) **self.kwargs_create_item_diff_org
}
super().setUpTestData() super().setUpTestData()
@ -120,50 +55,4 @@ class ContactViewSetTest(
ViewSetTestCases, ViewSetTestCases,
TestCase, TestCase,
): ):
pass
class MetadataTestCases(
ViewSetBase,
PersonMetadataInheritedCases,
):
pass
class ContactMetadataInheritedCases(
MetadataTestCases,
):
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@classmethod
def setUpTestData(self):
self.kwargs_create_item.update(
super().kwargs_create_item
)
self.kwargs_create_item_diff_org.update(
super().kwargs_create_item_diff_org
)
super().setUpTestData()
class ContactMetadataTest(
MetadataTestCases,
TestCase,
):
pass pass

View File

@ -0,0 +1,24 @@
import pytest
from access.models.entity import Entity
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Entity
yield request.cls.model
del request.cls.model
@pytest.fixture(scope='function')
def create_serializer():
from access.serializers.entity import ModelSerializer
yield ModelSerializer

View File

@ -0,0 +1,260 @@
import django
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from access.models.entity import Entity
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from accounting.models.asset_base import AssetBase
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
User = django.contrib.auth.get_user_model()
class EntityMetadataTestCases(
MetadataAttributesFunctional,
):
add_data: dict = {}
app_namespace = 'v2'
base_model = Entity
"""Base model for this sub model
don't change or override this value
"""
change_data = None
delete_data = {}
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
model = Entity
url_kwargs: dict = {}
url_view_kwargs: dict = {}
url_name = None
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
. create an organization that is different to item
2. Create a team
3. create teams with each permission: view, add, change, delete
4. create a user per team
"""
organization = Organization.objects.create(name='test_org')
self.organization = organization
self.different_organization = Organization.objects.create(name='test_different_organization')
self.view_user = User.objects.create_user(username="test_user_view", password="password")
self.item = self.model.objects.create(
organization = organization,
**self.kwargs_create_item
)
self.other_org_item = self.model.objects.create(
organization = self.different_organization,
**self.kwargs_create_item_diff_org
)
self.url_view_kwargs.update({ 'pk': self.item.id })
if self.add_data is not None:
self.add_data.update({
'organization': self.organization.id,
})
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = organization,
)
view_team.permissions.set([view_permissions])
add_permissions = Permission.objects.get(
codename = 'add_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
add_team = Team.objects.create(
team_name = 'add_team',
organization = organization,
)
add_team.permissions.set([add_permissions])
change_permissions = Permission.objects.get(
codename = 'change_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
change_team = Team.objects.create(
team_name = 'change_team',
organization = organization,
)
change_team.permissions.set([change_permissions])
delete_permissions = Permission.objects.get(
codename = 'delete_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
delete_team = Team.objects.create(
team_name = 'delete_team',
organization = organization,
)
delete_team.permissions.set([delete_permissions])
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
self.add_user = User.objects.create_user(username="test_user_add", password="password")
TeamUsers.objects.create(
team = add_team,
user = self.add_user
)
self.change_user = User.objects.create_user(username="test_user_change", password="password")
TeamUsers.objects.create(
team = change_team,
user = self.change_user
)
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
TeamUsers.objects.create(
team = delete_team,
user = self.delete_user
)
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
different_organization_team = Team.objects.create(
team_name = 'different_organization_team',
organization = self.different_organization,
)
different_organization_team.permissions.set([
view_permissions,
add_permissions,
change_permissions,
delete_permissions,
])
TeamUsers.objects.create(
team = different_organization_team,
user = self.different_organization_user
)
def test_sanity_is_entity_sub_model(self):
"""Sanity Test
This test ensures that the model being tested `self.model` is a
sub-model of `self.base_model`.
This test is required as the same viewset is used for all sub-models
of `AssetBase`
"""
assert issubclass(self.model, self.base_model)
class EntityMetadataInheritedCases(
EntityMetadataTestCases,
):
model = None
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
url_name = '_api_v2_entity_sub'
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
self.url_kwargs = {
'entity_model': self.model._meta.sub_model_type
}
self.url_view_kwargs = {
'entity_model': self.model._meta.sub_model_type
}
super().setUpTestData()
class EntityMetadataTest(
EntityMetadataTestCases,
TestCase,
):
url_name = '_api_v2_entity'

View File

@ -0,0 +1,89 @@
import pytest
from api.tests.functional.test_functional_api_permissions import (
APIPermissionsInheritedCases,
)
class EntityPermissionsAPITestCases(
APIPermissionsInheritedCases,
):
add_data: dict = {}
app_namespace = 'v2'
change_data = {}
delete_data = {}
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
url_kwargs: dict = {}
url_name = '_api_v2_entity'
url_view_kwargs: dict = {}
def test_returned_data_from_user_and_global_organizations_only(self):
"""Check items returned
This test case is a over-ride of a test case with the same name.
This model is not a tenancy model making this test not-applicable.
Items returned from the query Must be from the users organization and
global ONLY!
"""
pass
class EntityPermissionsAPIInheritedCases(
EntityPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
url_name = '_api_v2_entity_sub'
@pytest.fixture(scope='class')
def inherited_var_setup(self, request):
request.cls.url_kwargs.update({
'entity_model': self.model._meta.sub_model_type
})
request.cls.url_view_kwargs.update({
'entity_model': self.model._meta.sub_model_type
})
@pytest.fixture(scope='class', autouse = True)
def class_setup(self, request, django_db_blocker,
model,
var_setup,
prepare,
inherited_var_setup,
diff_org_model,
create_model,
):
pass
class EntityPermissionsAPIPyTest(
EntityPermissionsAPITestCases,
):
pass

View File

@ -1,94 +1,171 @@
import django
import pytest import pytest
from django.test import TestCase from rest_framework.exceptions import ValidationError
from access.models.organization import Organization User = django.contrib.auth.get_user_model()
from access.serializers.entity import (
Entity,
ModelSerializer
)
class SerializerTestCases: class MockView:
kwargs_create_item: dict = {} _has_import: bool = False
""" Model kwargs to create item""" """User Permission
model = Entity get_permission_required() sets this to `True` when user has import permission.
"""Model to test""" """
create_model_serializer = ModelSerializer _has_purge: bool = False
"""Serializer to test""" """User Permission
valid_data: dict = {} get_permission_required() sets this to `True` when user has purge permission.
"""
_has_triage: bool = False
"""User Permission
get_permission_required() sets this to `True` when user has triage permission.
"""
class EntitySerializerTestCases:
parameterized_test_data: dict = {
"model_notes": {
'will_create': True,
}
}
valid_data: dict = {
'model_notes': 'model notes field'
}
"""Valid data used by serializer to create object""" """Valid data used by serializer to create object"""
@classmethod
def setUpTestData(self):
"""Setup Test"""
self.organization = Organization.objects.create(name='test_org')
self.kwargs_create_item.update({ @pytest.fixture( scope = 'class')
'model_notes': 'model notes field' def setup_data(self,
}) request,
model,
django_db_blocker,
organization_one,
):
self.valid_data.update({ with django_db_blocker.unblock():
'organization': self.organization.pk,
'model_notes': 'model notes field'
})
self.item = self.model.objects.create( request.cls.organization = organization_one
organization = self.organization,
**self.kwargs_create_item, valid_data = {}
)
for base in reversed(request.cls.__mro__):
if hasattr(base, 'valid_data'):
if base.valid_data is None:
continue
valid_data.update(**base.valid_data)
if len(valid_data) > 0:
request.cls.valid_data = valid_data
if 'organization' not in request.cls.valid_data:
request.cls.valid_data.update({
'organization': request.cls.organization.pk
})
request.cls.view_user = User.objects.create_user(username="cafs_test_user_view", password="password")
yield
with django_db_blocker.unblock():
request.cls.view_user.delete()
del request.cls.valid_data
def test_serializer_valid_data(self): @pytest.fixture( scope = 'class', autouse = True)
def class_setup(self,
setup_data,
):
pass
def test_serializer_valid_data(self, create_serializer):
"""Serializer Validation Check """Serializer Validation Check
Ensure that when creating an object with valid data, no validation Ensure that when creating an object with valid data, no validation
error occurs. error occurs.
""" """
serializer = self.create_model_serializer( view_set = MockView()
serializer = create_serializer(
context = {
'view': view_set,
},
data = self.valid_data data = self.valid_data
) )
assert serializer.is_valid(raise_exception = True) assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_model_notes(self):
def test_serializer_valid_data_missing_field_is_valid(self, parameterized, param_key_test_data,
create_serializer,
param_value,
param_will_create,
):
"""Serializer Validation Check """Serializer Validation Check
Ensure that if creating and no model_notes is provided no validation Ensure that when creating an object with a user with import permission
error occurs and with valid data, no validation error occurs.
""" """
data = self.valid_data.copy() valid_data = self.valid_data.copy()
del data['model_notes']
serializer = self.create_model_serializer( del valid_data[param_value]
data = data
view_set = MockView()
view_set._has_import = True
serializer = create_serializer(
context = {
'view': view_set,
},
data = valid_data
) )
assert serializer.is_valid(raise_exception = True) is_valid = serializer.is_valid(raise_exception = False)
assert (
(
not param_will_create
and param_will_create == is_valid
)
or param_will_create == is_valid
)
class EntitySerializerInheritedCases( class EntitySerializerInheritedCases(
SerializerTestCases, EntitySerializerTestCases,
): ):
create_model_serializer = None parameterized_test_data: dict = None
"""Serializer to test"""
kwargs_create_item: dict = None
""" Model kwargs to create item"""
model = None model = None
"""Model to test""" """Model to test"""
@ -97,10 +174,40 @@ class EntitySerializerInheritedCases(
"""Valid data used by serializer to create object""" """Valid data used by serializer to create object"""
def test_serializer_valid_data_missing_field_raises_exception(self, parameterized, param_key_test_data,
create_serializer,
param_value,
param_exception_key,
):
"""Serializer Validation Check
class EntitySerializerTest( Ensure that when creating an object with a user with import permission
SerializerTestCases, and with valid data, no validation error occurs.
TestCase, """
valid_data = self.valid_data.copy()
del valid_data[param_value]
view_set = MockView()
with pytest.raises(ValidationError) as err:
serializer = create_serializer(
context = {
'view': view_set,
},
data = valid_data
)
is_valid = serializer.is_valid(raise_exception = True)
assert err.value.get_codes()[param_value][0] == param_exception_key
class EntitySerializerPyTest(
EntitySerializerTestCases,
): ):
pass parameterized_test_data: dict = None

View File

@ -1,37 +1,49 @@
from django.contrib.auth.models import Permission, User import django
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
from access.models.entity import Entity from access.models.entity import Entity
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.api_serializer_viewset import SerializersTestCases
User = django.contrib.auth.get_user_model()
class ViewSetBase: class ViewSetBase:
add_data: dict = None add_data: dict = {
'model_notes': 'added model note'
}
app_namespace = 'v2' app_namespace = 'v2'
base_model = Entity
"""Base model for this sub model
don't change or override this value
"""
change_data = None change_data = None
delete_data = {} delete_data = {}
kwargs_create_item: dict = {} kwargs_create_item: dict = {
'model_notes': 'added model note'
}
kwargs_create_item_diff_org: dict = {} kwargs_create_item_diff_org: dict = {
'model_notes': 'added model note'
}
model = None model = None
url_kwargs: dict = None url_kwargs: dict = {}
url_view_kwargs: dict = None url_view_kwargs: dict = {}
url_name = None url_name = None
@ -53,16 +65,15 @@ class ViewSetBase:
self.different_organization = Organization.objects.create(name='test_different_organization') self.different_organization = Organization.objects.create(name='test_different_organization')
self.view_user = User.objects.create_user(username="test_user_view", password="password")
self.item = self.model.objects.create( self.item = self.model.objects.create(
organization = organization, organization = organization,
model_notes = 'some notes',
**self.kwargs_create_item **self.kwargs_create_item
) )
self.other_org_item = self.model.objects.create( self.other_org_item = self.model.objects.create(
organization = self.different_organization, organization = self.different_organization,
model_notes = 'some more notes',
**self.kwargs_create_item_diff_org **self.kwargs_create_item_diff_org
) )
@ -71,7 +82,9 @@ class ViewSetBase:
if self.add_data is not None: if self.add_data is not None:
self.add_data.update({'organization': self.organization.id}) self.add_data.update({
'organization': self.organization.id,
})
view_permissions = Permission.objects.get( view_permissions = Permission.objects.get(
@ -144,7 +157,6 @@ class ViewSetBase:
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password") self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
self.view_user = User.objects.create_user(username="test_user_view", password="password")
TeamUsers.objects.create( TeamUsers.objects.create(
team = view_team, team = view_team,
user = self.view_user user = self.view_user
@ -190,98 +202,16 @@ class ViewSetBase:
) )
def test_sanity_is_asset_sub_model(self):
class PermissionsAPITestCases( """Sanity Test
ViewSetBase,
APIPermissions, This test ensures that the model being tested `self.model` is a
): sub-model of `self.base_model`.
This test is required as the same viewset is used for all sub-models
of `Entity`
add_data: dict = {}
change_data = {'model_notes': 'device'}
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
url_kwargs: dict = None
url_view_kwargs: dict = None
url_name = None
@classmethod
def setUpTestData(self):
self.add_data.update({ 'model_note': 'added model note' })
super().setUpTestData()
def test_returned_data_from_user_and_global_organizations_only(self):
"""Check items returned
This test case is a over-ride of a test case with the same name.
This model is not a tenancy model making this test not-applicable.
Items returned from the query Must be from the users organization and
global ONLY!
""" """
pass
class EntityPermissionsAPIInheritedCases(
PermissionsAPITestCases,
):
add_data: dict = None
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
url_name = '_api_v2_entity_sub'
@classmethod
def setUpTestData(self):
self.url_kwargs = {
'entity_model': self.model._meta.model_name
}
self.url_view_kwargs = {
'entity_model': self.model._meta.model_name
}
super().setUpTestData()
class EntityPermissionsAPITest(
PermissionsAPITestCases,
TestCase,
):
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
model = Entity
url_kwargs: dict = {}
url_view_kwargs: dict = {}
url_name = '_api_v2_entity'
assert issubclass(self.model, self.base_model)
@ -290,17 +220,7 @@ class ViewSetTestCases(
SerializersTestCases, SerializersTestCases,
): ):
kwargs_create_item: dict = None model = Entity
kwargs_create_item_diff_org: dict = None
model = None
url_kwargs: dict = None
url_view_kwargs: dict = None
url_name = None
@ -310,22 +230,28 @@ class EntityViewSetInheritedCases(
model = None model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
url_name = '_api_v2_entity_sub' url_name = '_api_v2_entity_sub'
@classmethod @classmethod
def setUpTestData(self): def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
self.url_kwargs = { self.url_kwargs = {
'entity_model': self.model._meta.model_name 'entity_model': self.model._meta.sub_model_type
} }
self.url_view_kwargs = { self.url_view_kwargs = {
'entity_model': self.model._meta.model_name 'entity_model': self.model._meta.sub_model_type
} }
super().setUpTestData() super().setUpTestData()
@ -337,168 +263,4 @@ class EntityViewSetTest(
TestCase, TestCase,
): ):
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
model = Entity
url_kwargs: dict = {}
url_view_kwargs: dict = {}
url_name = '_api_v2_entity' url_name = '_api_v2_entity'
class MetadataTestCases(
ViewSetBase,
MetadataAttributesFunctional,
):
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
model = None
url_kwargs: dict = None
url_view_kwargs: dict = None
url_name = None
class EntityMetadataInheritedCases(
MetadataTestCases,
):
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
url_name = '_api_v2_entity_sub'
@classmethod
def setUpTestData(self):
self.url_kwargs = {
'entity_model': self.model._meta.model_name
}
self.url_view_kwargs = {
'entity_model': self.model._meta.model_name
}
super().setUpTestData()
class EntityMetadataTest(
MetadataTestCases,
TestCase,
):
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
model = Entity
url_kwargs: dict = {}
url_view_kwargs: dict = {}
url_name = '_api_v2_entity'
# def test_method_options_request_detail_data_has_key_urls_back(self):
# """Test HTTP/Options Method
# Ensure the request data returned has key `urls.back`
# """
# client = Client()
# client.force_login(self.view_user)
# response = client.options(
# reverse(
# self.app_namespace + ':' + self.url_name + '-detail',
# kwargs=self.url_view_kwargs
# ),
# content_type='application/json'
# )
# assert 'back' in response.data['urls']
# def test_method_options_request_detail_data_key_urls_back_is_str(self):
# """Test HTTP/Options Method
# Ensure the request data key `urls.back` is str
# """
# client = Client()
# client.force_login(self.view_user)
# response = client.options(
# reverse(
# self.app_namespace + ':' + self.url_name + '-detail',
# kwargs=self.url_view_kwargs
# ),
# content_type='application/json'
# )
# assert type(response.data['urls']['back']) is str
# def test_method_options_request_list_data_has_key_urls_return_url(self):
# """Test HTTP/Options Method
# Ensure the request data returned has key `urls.return_url`
# """
# client = Client()
# client.force_login(self.view_user)
# if self.url_kwargs:
# url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
# else:
# url = reverse(self.app_namespace + ':' + self.url_name + '-list')
# response = client.options( url, content_type='application/json' )
# assert 'return_url' in response.data['urls']
# def test_method_options_request_list_data_key_urls_return_url_is_str(self):
# """Test HTTP/Options Method
# Ensure the request data key `urls.return_url` is str
# """
# client = Client()
# client.force_login(self.view_user)
# if self.url_kwargs:
# url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
# else:
# url = reverse(self.app_namespace + ':' + self.url_name + '-list')
# response = client.options( url, content_type='application/json' )
# assert type(response.data['urls']['return_url']) is str

View File

@ -1,6 +1,6 @@
from django.test import TestCase from django.test import TestCase
from access.models.organization_history import Organization, OrganizationHistory from access.models.organization_history import Tenant as Organization, OrganizationHistory
from core.tests.abstract.test_functional_history import HistoryEntriesCommon from core.tests.abstract.test_functional_history import HistoryEntriesCommon

View File

@ -1,22 +1,24 @@
import django
import pytest import pytest
from django.contrib.auth.models import User
from django.test import TestCase from django.test import TestCase
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from access.serializers.organization import ( from access.serializers.organization import (
Organization, Tenant,
OrganizationModelSerializer TenantModelSerializer
) )
User = django.contrib.auth.get_user_model()
class OrganizationValidationAPI( class OrganizationValidationAPI(
TestCase, TestCase,
): ):
model = Organization model = Tenant
@classmethod @classmethod
def setUpTestData(self): def setUpTestData(self):
@ -45,7 +47,7 @@ class OrganizationValidationAPI(
Ensure that if creating and no name is provided a validation error occurs Ensure that if creating and no name is provided a validation error occurs
""" """
serializer = OrganizationModelSerializer( serializer = TenantModelSerializer(
data = self.valid_data data = self.valid_data
) )
@ -65,7 +67,7 @@ class OrganizationValidationAPI(
with pytest.raises(ValidationError) as err: with pytest.raises(ValidationError) as err:
serializer = OrganizationModelSerializer( serializer = TenantModelSerializer(
data = data data = data
) )
@ -85,7 +87,7 @@ class OrganizationValidationAPI(
del data['manager'] del data['manager']
serializer = OrganizationModelSerializer( serializer = TenantModelSerializer(
data = data data = data
) )

View File

@ -1,15 +1,16 @@
import django
import pytest import pytest
import unittest import unittest
import requests import requests
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
@ -17,6 +18,8 @@ from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.api_serializer_viewset import SerializersTestCases
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
User = django.contrib.auth.get_user_model()
class ViewSetBase: class ViewSetBase:
@ -315,4 +318,4 @@ class OrganizationMetadata(
menu_id = 'access' menu_id = 'access'
menu_entry_id = 'organization' menu_entry_id = 'tenant'

View File

@ -3,7 +3,7 @@ from django.test import TestCase
from core.tests.abstract.model_notes_api_fields import ModelNotesNotesAPIFields from core.tests.abstract.model_notes_api_fields import ModelNotesNotesAPIFields
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.organization_notes import OrganizationNotes from access.models.organization_notes import OrganizationNotes

View File

@ -0,0 +1,24 @@
import pytest
from access.models.person import Person
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Person
yield request.cls.model
del request.cls.model
@pytest.fixture(scope='function')
def create_serializer():
from access.serializers.entity_person import ModelSerializer
yield ModelSerializer

View File

@ -0,0 +1,83 @@
from django.test import TestCase
from access.models.person import Person
from access.tests.functional.entity.test_functional_entity_metadata import (
EntityMetadataInheritedCases
)
from accounting.models.asset_base import AssetBase
class PersonMetadataTestCases(
EntityMetadataInheritedCases,
):
add_data: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Strange',
'dob': '2025-04-08',
}
kwargs_create_item: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Weird',
'dob': '2025-04-08',
}
kwargs_create_item_diff_org: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Funny',
'dob': '2025-04-08',
}
model = Person
class PersonMetadataInheritedCases(
PersonMetadataTestCases,
):
model = None
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
# self.url_kwargs = {
# 'entity_model': self.model._meta.sub_model_type
# }
# self.url_view_kwargs = {
# 'entity_model': self.model._meta.sub_model_type
# }
super().setUpTestData()
class PersonMetadataTest(
PersonMetadataTestCases,
TestCase,
):
pass

View File

@ -0,0 +1,91 @@
import pytest
from access.tests.functional.entity.test_functional_entity_permission import (
EntityPermissionsAPIInheritedCases
)
class PersonPermissionsAPITestCases(
EntityPermissionsAPIInheritedCases,
):
add_data: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Strange',
'dob': '2025-04-08',
}
# app_namespace = 'v2'
# change_data = {}
# delete_data = {}
kwargs_create_item: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Weird',
'dob': '2025-04-08',
}
kwargs_create_item_diff_org: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Funny',
'dob': '2025-04-08',
}
# url_kwargs: dict = {}
# url_name = '_api_v2_entity'
# url_view_kwargs: dict = {}
class PersonPermissionsAPIInheritedCases(
PersonPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
# url_name = '_api_v2_entity_sub'
# @pytest.fixture(scope='class')
# def inherited_var_setup(self, request):
# request.cls.url_kwargs.update({
# 'entity_model': self.model._meta.sub_model_type
# })
# request.cls.url_view_kwargs.update({
# 'entity_model': self.model._meta.sub_model_type
# })
# @pytest.fixture(scope='class', autouse = True)
# def class_setup(self, request, django_db_blocker,
# model,
# var_setup,
# prepare,
# inherited_var_setup,
# diff_org_model,
# create_model,
# ):
# pass
class PersonPermissionsAPIPyTest(
PersonPermissionsAPITestCases,
):
pass

View File

@ -1,161 +1,88 @@
import pytest import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from access.serializers.entity_person import (
Person,
ModelSerializer
)
from access.tests.functional.entity.test_functional_entity_serializer import ( from access.tests.functional.entity.test_functional_entity_serializer import (
MockView,
EntitySerializerInheritedCases EntitySerializerInheritedCases
) )
class SerializerTestCases( class PersonSerializerTestCases(
EntitySerializerInheritedCases, EntitySerializerInheritedCases
): ):
create_model_serializer = ModelSerializer
"""Serializer to test"""
duplicate_f_name_l_name_dob: dict = { parameterized_test_data: dict = {
'f_name': 'fred', "model_notes": {
'm_name': 'D', 'will_create': True,
'l_name': 'Flinstone', },
'dob': '2025-04-08', "f_name": {
'will_create': False,
'exception_key': 'required'
},
"m_name": {
'will_create': True,
},
"l_name": {
'will_create': False,
'exception_key': 'required'
},
"dob": {
'will_create': True,
}
} }
kwargs_create_item_duplicate_f_name_l_name_dob: dict = { valid_data: dict = {
'f_name': 'fred',
'm_name': 'D',
'l_name': 'Flinstone',
'dob': '2025-04-08',
}
kwargs_create_item: dict = {
'f_name': 'Ian', 'f_name': 'Ian',
'm_name': 'Peter', 'm_name': 'Peter',
'l_name': 'Funny', 'l_name': 'Funny',
'dob': '2025-04-08', 'dob': '2025-04-08',
} }
"""Valid data used by serializer to create object"""
model = Person
"""Model to test"""
valid_data: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Strange',
'dob': '2025-04-08',
}
def test_serializer_validation_duplicate_f_name_l_name_dob(self, model, create_serializer):
def test_serializer_validation_no_f_name_exception(self):
"""Serializer Validation Check
Ensure that when creating with valid data and field f_name is missing
a validation error occurs.
"""
data = self.valid_data.copy()
del data['f_name']
with pytest.raises(ValidationError) as err:
serializer = self.create_model_serializer(
data = data
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['f_name'][0] == 'required'
def test_serializer_validation_no_m_name(self):
"""Serializer Validation Check
Ensure that when creating with valid data and field f_name is missing
no validation error occurs.
"""
data = self.valid_data.copy()
del data['m_name']
serializer = self.create_model_serializer(
data = data
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_l_name_exception(self):
"""Serializer Validation Check
Ensure that when creating with valid data and field l_name is missing
a validation error occurs.
"""
data = self.valid_data.copy()
del data['l_name']
with pytest.raises(ValidationError) as err:
serializer = self.create_model_serializer(
data = data
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['l_name'][0] == 'required'
def test_serializer_validation_no_dob(self):
"""Serializer Validation Check
Ensure that when creating with valid data and field dob is missing
no validation error occurs.
"""
data = self.valid_data.copy()
del data['dob']
serializer = self.create_model_serializer(
data = data
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_duplicate_f_name_l_name_dob(self):
"""Serializer Validation Check """Serializer Validation Check
Ensure that when creating with valid data and fields f_name, l_name and Ensure that when creating with valid data and fields f_name, l_name and
dob already exists in the db a validation error occurs. dob already exists in the db a validation error occurs.
""" """
self.model.objects.create( valid_data = self.valid_data.copy()
organization = self.organization,
**self.kwargs_create_item_duplicate_f_name_l_name_dob valid_data['f_name'] = 'duplicate'
valid_data['organization'] = self.organization
obj = model.objects.create(
**valid_data
) )
data = self.duplicate_f_name_l_name_dob.copy() valid_data['organization'] = self.organization.id
if 'email' in valid_data: # Contact Entity
valid_data['email'] = 'abc@xyz.qwe'
if 'name' in valid_data: # Company Entity
valid_data['name'] = 'diff'
if 'employee_number' in valid_data: # Employee Entity
valid_data['employee_number'] = 13579
view_set = MockView()
with pytest.raises(ValidationError) as err: with pytest.raises(ValidationError) as err:
serializer = self.create_model_serializer( serializer = create_serializer(
data = data context = {
'view': view_set,
},
data = valid_data
) )
serializer.is_valid(raise_exception = True) serializer.is_valid(raise_exception = True)
@ -167,64 +94,18 @@ class SerializerTestCases(
class PersonSerializerInheritedCases( class PersonSerializerInheritedCases(
SerializerTestCases, PersonSerializerTestCases,
): ):
create_model_serializer = None parameterized_test_data: dict = None
"""Serializer to test"""
duplicate_f_name_l_name_dob: dict = None
""" Duplicate model serializer dict
used for testing for duplicate f_name, l_name and dob fields.
"""
kwargs_create_item: dict = None
""" Model kwargs to create item"""
kwargs_create_item_duplicate_f_name_l_name_dob: dict = None
"""model kwargs to create object
**None:** Ensure that the fields of sub-model to person do not match
`self.duplicate_f_name_l_name_dob`. if they do the wrong exception will be thrown.
used for testing for duplicate f_name, l_name and dob fields.
"""
model = None
"""Model to test"""
valid_data: dict = None valid_data: dict = None
"""Valid data used by serializer to create object""" """Valid data used by serializer to create object"""
@classmethod
def setUpTestData(self):
"""Setup Test"""
self.duplicate_f_name_l_name_dob.update( class PersonSerializerPyTest(
super().duplicate_f_name_l_name_dob PersonSerializerTestCases,
)
self.kwargs_create_item_duplicate_f_name_l_name_dob.update(
super().kwargs_create_item_duplicate_f_name_l_name_dob
)
self.kwargs_create_item.update(
super().kwargs_create_item
)
self.valid_data.update(
super().valid_data
)
super().setUpTestData()
class PersonSerializerTest(
SerializerTestCases,
TestCase,
): ):
pass parameterized_test_data: dict = None

View File

@ -2,101 +2,38 @@ from django.test import TestCase
from access.models.person import Person from access.models.person import Person
from access.tests.functional.entity.test_functional_entity_viewset import ( from access.tests.functional.entity.test_functional_entity_viewset import (
EntityMetadataInheritedCases,
EntityPermissionsAPIInheritedCases,
EntityViewSetInheritedCases EntityViewSetInheritedCases
) )
class ViewSetBase: class ViewSetTestCases(
EntityViewSetInheritedCases,
):
add_data = { add_data: dict = {
'f_name': 'Ian', 'f_name': 'Ian',
'm_name': 'Peter', 'm_name': 'Peter',
'l_name': 'Strange', 'l_name': 'Strange',
'dob': '2025-04-08', 'dob': '2025-04-08',
} }
kwargs_create_item_diff_org = { kwargs_create_item: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Funny',
'dob': '2025-04-08',
}
kwargs_create_item = {
'f_name': 'Ian', 'f_name': 'Ian',
'm_name': 'Peter', 'm_name': 'Peter',
'l_name': 'Weird', 'l_name': 'Weird',
'dob': '2025-04-08', 'dob': '2025-04-08',
} }
kwargs_create_item_diff_org: dict = {
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Funny',
'dob': '2025-04-08',
}
model = Person model = Person
url_kwargs: dict = {}
url_view_kwargs: dict = {}
class PermissionsAPITestCases(
ViewSetBase,
EntityPermissionsAPIInheritedCases,
):
pass
class PersonPermissionsAPIInheritedCases(
PermissionsAPITestCases,
):
add_data: dict = None
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@classmethod
def setUpTestData(self):
self.add_data.update(
super().add_data
)
self.kwargs_create_item.update(
super().kwargs_create_item
)
self.kwargs_create_item_diff_org.update(
super().kwargs_create_item_diff_org
)
super().setUpTestData()
class PersonPermissionsAPITest(
PermissionsAPITestCases,
TestCase,
):
pass
class ViewSetTestCases(
ViewSetBase,
EntityViewSetInheritedCases,
):
pass
class PersonViewSetInheritedCases( class PersonViewSetInheritedCases(
@ -105,21 +42,19 @@ class PersonViewSetInheritedCases(
model = None model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@classmethod @classmethod
def setUpTestData(self): def setUpTestData(self):
self.kwargs_create_item.update( self.kwargs_create_item = {
super().kwargs_create_item **super().kwargs_create_item,
) **self.kwargs_create_item
}
self.kwargs_create_item_diff_org.update( self.kwargs_create_item_diff_org = {
super().kwargs_create_item_diff_org **super().kwargs_create_item_diff_org,
) **self.kwargs_create_item_diff_org
}
super().setUpTestData() super().setUpTestData()
@ -129,50 +64,4 @@ class PersonViewSetTest(
ViewSetTestCases, ViewSetTestCases,
TestCase, TestCase,
): ):
pass
class MetadataTestCases(
ViewSetBase,
EntityMetadataInheritedCases,
):
pass
class PersonMetadataInheritedCases(
MetadataTestCases,
):
model = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@classmethod
def setUpTestData(self):
self.kwargs_create_item.update(
super().kwargs_create_item
)
self.kwargs_create_item_diff_org.update(
super().kwargs_create_item_diff_org
)
super().setUpTestData()
class PersonMetadataTest(
MetadataTestCases,
TestCase,
):
pass pass

View File

@ -5,7 +5,7 @@ from django.test import TestCase
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.serializers.role import Role, ModelSerializer from access.serializers.role import Role, ModelSerializer

View File

@ -1,11 +1,12 @@
from django.contrib.auth.models import Permission, User import django
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from access.models.role import Role from access.models.role import Role
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
@ -15,6 +16,8 @@ from api.tests.abstract.api_serializer_viewset import SerializersTestCases
from settings.models.app_settings import AppSettings from settings.models.app_settings import AppSettings
User = django.contrib.auth.get_user_model()
class ViewSetBase: class ViewSetBase:

View File

@ -1,16 +1,17 @@
import django
import pytest import pytest
import unittest import unittest
import requests import requests
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
@ -19,6 +20,8 @@ from api.tests.abstract.test_metadata_functional import MetadataAttributesFuncti
from api.tests.abstract.api_permissions_viewset import APIPermissions from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.api_serializer_viewset import SerializersTestCases
User = django.contrib.auth.get_user_model()
class ViewSetBase: class ViewSetBase:

View File

@ -1,6 +1,7 @@
import django
import pytest import pytest
from django.contrib.auth.models import Permission, User from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
@ -8,7 +9,7 @@ from rest_framework.exceptions import ValidationError
from access.middleware.request import Tenancy from access.middleware.request import Tenancy
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.serializers.teams import ( from access.serializers.teams import (
Team, Team,
@ -17,6 +18,8 @@ from access.serializers.teams import (
from settings.models.app_settings import AppSettings from settings.models.app_settings import AppSettings
User = django.contrib.auth.get_user_model()
class MockView: class MockView:

View File

@ -1,16 +1,17 @@
import django
import pytest import pytest
import unittest import unittest
import requests import requests
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
@ -18,6 +19,8 @@ from api.tests.abstract.test_metadata_functional import MetadataAttributesFuncti
from api.tests.abstract.api_permissions_viewset import APIPermissions from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.api_serializer_viewset import SerializersTestCases
User = django.contrib.auth.get_user_model()
class ViewSetBase: class ViewSetBase:

View File

@ -1,12 +1,13 @@
import django
import pytest import pytest
from django.contrib.auth.models import Permission, User from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.serializers.team_user import ( from access.serializers.team_user import (
@ -14,6 +15,8 @@ from access.serializers.team_user import (
TeamUserModelSerializer TeamUserModelSerializer
) )
User = django.contrib.auth.get_user_model()
class MockView: class MockView:

View File

@ -0,0 +1,14 @@
import pytest
from access.models.company_base import Company
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Company
yield request.cls.model
del request.cls.model

View File

@ -0,0 +1,37 @@
from access.tests.unit.entity.test_unit_entity_api_fields import (
EntityAPIInheritedCases
)
class CompanyAPITestCases(
EntityAPIInheritedCases,
):
parameterized_test_data = {
'name': {
'expected': str
}
}
kwargs_create_item: dict = {
'name': 'Ian'
}
class CompanyAPIInheritedCases(
CompanyAPITestCases,
):
kwargs_create_item: dict = None
model = None
class CompanyAPIPyTest(
CompanyAPITestCases,
):
pass

View File

@ -0,0 +1,105 @@
import pytest
from django.db import models
from access.models.company_base import Company
from access.tests.unit.entity.test_unit_entity_model import (
EntityModelInheritedCases
)
class CompanyModelTestCases(
EntityModelInheritedCases,
):
kwargs_create_item: dict = {
'name': 'Ian',
}
sub_model_type = 'company'
"""Sub Model Type
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
"""
parameterized_fields: dict = {
"name": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
}
}
def test_class_inherits_company(self):
""" Class inheritence
TenancyObject must inherit SaveHistory
"""
assert issubclass(self.model, Company)
def test_attribute_value_history_app_label(self):
"""Attribute Type
history_app_label has been set, override this test case with the value
of attribute `history_app_label`
"""
assert self.model.history_app_label == 'access'
def test_attribute_value_history_model_name(self):
"""Attribute Type
history_model_name has been set, override this test case with the value
of attribute `history_model_name`
"""
assert self.model.history_model_name == 'company'
def test_function_value_get_url(self):
assert self.item.get_url() == '/api/v2/access/entity/company/' + str(self.item.id)
class CompanyModelInheritedCases(
CompanyModelTestCases,
):
"""Sub-Ticket Test Cases
Test Cases for Ticket models that inherit from model Entity
"""
kwargs_create_item: dict = {}
model = None
sub_model_type = None
"""Ticket Sub Model Type
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
"""
class CompanyModelPyTest(
CompanyModelTestCases,
):
def test_function_value_get_related_model(self):
"""Function test
Confirm function `get_related_model` is None for base model
"""
assert self.item.get_related_model() is None

View File

@ -0,0 +1,36 @@
from django.test import TestCase
from access.models.company_base import Company
from access.tests.unit.entity.test_unit_entity_viewset import (
EntityViewsetInheritedCases
)
class ViewsetTestCases(
EntityViewsetInheritedCases,
):
model: str = Company
class CompanyViewsetInheritedCases(
ViewsetTestCases,
):
"""Sub-Entity Test Cases
Test Cases for Entity models that inherit from model Company
"""
model: str = None
"""name of the model to test"""
class CompanyViewsetTest(
ViewsetTestCases,
TestCase,
):
pass

View File

@ -0,0 +1,14 @@
import pytest
from access.models.contact import Contact
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Contact
yield request.cls.model
del request.cls.model

View File

@ -0,0 +1,40 @@
from access.tests.unit.person.test_unit_person_api_fields import (
PersonAPIInheritedCases
)
class ContactAPITestCases(
PersonAPIInheritedCases,
):
parameterized_test_data = {
'email': {
'expected': str
},
'directory': {
'expected': bool
}
}
kwargs_create_item: dict = {
'email': 'ipfunny@unit.test',
}
class ContactAPIInheritedCases(
ContactAPITestCases,
):
kwargs_create_item: dict = None
model = None
class ContactAPIPyTest(
ContactAPITestCases,
):
pass

View File

@ -1,90 +0,0 @@
from django.test import TestCase
from access.models.contact import Contact
from access.tests.unit.person.test_unit_person_api_v2 import (
PersonAPIInheritedCases,
)
class APITestCases(
PersonAPIInheritedCases,
):
model = Contact
kwargs_item_create: dict = {
'email': 'ipfunny@unit.test',
}
url_ns_name = '_api_v2_entity_sub'
def test_api_field_exists_email(self):
""" Test for existance of API Field
email field must exist
"""
assert 'email' in self.api_data
def test_api_field_type_email(self):
""" Test for type for API Field
email field must be str
"""
assert type(self.api_data['email']) is str
def test_api_field_exists_directory(self):
""" Test for existance of API Field
directory field must exist
"""
assert 'directory' in self.api_data
def test_api_field_type_directory(self):
""" Test for type for API Field
directory field must be bool
"""
assert type(self.api_data['directory']) is bool
class ContactAPIInheritedCases(
APITestCases,
):
"""Sub-Entity Test Cases
Test Cases for Entity models that inherit from model Contact
"""
kwargs_item_create: dict = None
model = None
@classmethod
def setUpTestData(self):
self.kwargs_item_create.update(
super().kwargs_item_create
)
super().setUpTestData()
class ContactAPITest(
APITestCases,
TestCase,
):
pass

View File

@ -1,100 +1,110 @@
from django.db.models.fields import NOT_PROVIDED import pytest
from django.test import TestCase
from django.db import models
from access.models.contact import Contact from access.models.contact import Contact
from access.tests.unit.person.test_unit_person_model import ( from access.tests.unit.person.test_unit_person_model import (
Person,
PersonModelInheritedCases PersonModelInheritedCases
) )
class ModelTestCases( class ContactModelTestCases(
PersonModelInheritedCases, PersonModelInheritedCases,
): ):
model = Contact kwargs_create_item: dict = {
kwargs_item_create: dict = {
'email': 'ipweird@unit.test', 'email': 'ipweird@unit.test',
} }
sub_model_type = 'contact'
"""Sub Model Type
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
"""
parameterized_fields: dict = {
"email": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"directory": {
'field_type': models.fields.BooleanField,
'field_parameter_default_exists': True,
'field_parameter_default_value': True,
'field_parameter_verbose_name_type': str,
}
}
def test_model_field_directory_optional(self): def test_class_inherits_contact(self):
"""Test Field """ Class inheritence
Field `dob` must be an optional field TenancyObject must inherit SaveHistory
""" """
assert self.model._meta.get_field('directory').blank assert issubclass(self.model, Contact)
def test_model_field_directory_optional_default(self): # def test_attribute_value_history_app_label(self):
"""Test Field # """Attribute Type
Field `directory` default value is `True` # history_app_label has been set, override this test case with the value
# of attribute `history_app_label`
# """
# assert self.model.history_app_label == 'access'
def test_attribute_value_history_model_name(self):
"""Attribute Type
history_model_name has been set, override this test case with the value
of attribute `history_model_name`
""" """
assert ( assert self.model.history_model_name == 'contact'
self.model._meta.get_field('directory').default is True
and self.model._meta.get_field('directory').null is False
)
def test_model_field_email_mandatory(self):
"""Test Field
Field `email` must be a mandatory field def test_function_value_get_url(self):
"""
assert(
not (
self.model._meta.get_field('email').blank
and self.model._meta.get_field('email').null
)
and self.model._meta.get_field('email').default is NOT_PROVIDED
)
def test_model_inherits_person(self):
"""Test model inheritence
model must inherit from Entity sub-model `Person`
"""
assert issubclass(self.model, Person)
assert self.item.get_url() == '/api/v2/access/entity/contact/' + str(self.item.id)
class ContactModelInheritedCases( class ContactModelInheritedCases(
ModelTestCases, ContactModelTestCases,
): ):
"""Sub-Entity Test Cases """Sub-Ticket Test Cases
Test Cases for Entity models that inherit from model Contact Test Cases for Ticket models that inherit from model Entity
""" """
kwargs_item_create: dict = None kwargs_create_item: dict = {}
model = None model = None
sub_model_type = None
@classmethod """Ticket Sub Model Type
def setUpTestData(self):
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
self.kwargs_item_create.update( """
super().kwargs_item_create
)
super().setUpTestData()
class ContactModelTest( class ContactModelPyTest(
ModelTestCases, ContactModelTestCases,
TestCase,
): ):
pass
def test_function_value_get_related_model(self):
"""Function test
Confirm function `get_related_model` is None for base model
"""
assert self.item.get_related_model() is None

View File

@ -0,0 +1,14 @@
import pytest
from access.models.entity import Entity
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Entity
yield request.cls.model
del request.cls.model

View File

@ -0,0 +1,78 @@
import pytest
from access.models.entity import Entity
from api.tests.unit.test_unit_api_fields import (
APIFieldsInheritedCases,
)
class EntityAPITestCases(
APIFieldsInheritedCases,
):
base_model = Entity
@pytest.fixture( scope = 'class')
def setup_model(self, request,
model,
):
if model != self.base_model:
request.cls.url_view_kwargs.update({
'entity_model': model._meta.sub_model_type,
})
@pytest.fixture( scope = 'class', autouse = True)
def class_setup(self,
setup_pre,
setup_model,
create_model,
setup_post,
):
pass
parameterized_test_data = {
'entity_type': {
'expected': str
},
'_urls.history': {
'expected': str
},
'_urls.knowledge_base': {
'expected': str
}
}
kwargs_create_item: dict = {
'entity_type': 'entity',
}
url_ns_name = '_api_v2_entity'
"""Url namespace (optional, if not required) and url name"""
class EntityAPIInheritedCases(
EntityAPITestCases,
):
kwargs_create_item: dict = None
model = None
url_ns_name = '_api_v2_entity_sub'
class EntityAPIPyTest(
EntityAPITestCases,
):
pass

View File

@ -1,215 +0,0 @@
from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse
from django.test import Client, TestCase
# from rest_framework.relations import Hyperlink
from access.models.entity import Entity
from access.models.organization import Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject
class APITestCases(
APITenancyObject,
):
model = None
kwargs_item_create: dict = None
url_ns_name = None
"""Url namespace (optional, if not required) and url name"""
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
2. Create an item
"""
self.organization = Organization.objects.create(name='test_org')
self.item = self.model.objects.create(
organization = self.organization,
model_notes = 'random notes',
**self.kwargs_item_create
)
self.url_view_kwargs = {
'pk': self.item.id
}
if self.model._meta.model_name != 'entity':
self.url_view_kwargs.update({
'entity_model': self.item.entity_type,
})
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = self.organization,
)
view_team.permissions.set([view_permissions])
self.view_user = User.objects.create_user(username="test_user_view", password="password")
TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
client = Client()
url = reverse('v2:' + self.url_ns_name + '-detail', kwargs=self.url_view_kwargs)
client.force_login(self.view_user)
response = client.get(url)
self.api_data = response.data
def test_api_field_exists_entity_type(self):
""" Test for existance of API Field
entity_type field must exist
"""
assert 'entity_type' in self.api_data
def test_api_field_type_entity_type(self):
""" Test for type for API Field
entity_type field must be str
"""
assert type(self.api_data['entity_type']) is str
def test_api_field_exists_url_history(self):
""" Test for existance of API Field
_urls.history field must exist
"""
assert 'history' in self.api_data['_urls']
def test_api_field_type_url_history(self):
""" Test for type for API Field
_urls.history field must be str
"""
assert type(self.api_data['_urls']['history']) is str
def test_api_field_type_url_history_value(self):
""" Test for url value
_urls.history field must use the endpoint for entity model
"""
assert str(self.api_data['_urls']['history']).endswith('/' + str(self.item._meta.app_label) + '/' + str(self.item._meta.model_name) + '/' + str(self.item.pk) + '/history')
def test_api_field_exists_url_knowledge_base(self):
""" Test for existance of API Field
_urls.knowledge_base field must exist
"""
assert 'knowledge_base' in self.api_data['_urls']
def test_api_field_type_url_knowledge_base(self):
""" Test for type for API Field
_urls.knowledge_base field must be str
"""
assert type(self.api_data['_urls']['knowledge_base']) is str
def test_api_field_type_url_knowledge_base_value(self):
""" Test for url value
_urls.knowledge_base field must use the endpoint for entity model
"""
assert str(self.api_data['_urls']['knowledge_base']).endswith('/assistance/entity/' + str(self.item.pk) + '/knowledge_base')
class EntityAPIInheritedCases(
APITestCases,
):
kwargs_item_create: dict = None
model = None
url_ns_name = '_api_v2_entity_sub'
@classmethod
def setUpTestData(self):
self.kwargs_item_create.update({
'entity_type': self.model._meta.model_name
})
super().setUpTestData()
def test_api_field_exists_entity_value(self):
""" Test for value of API Field
entity_type field must match model name
"""
assert self.api_data['entity_type'] == self.model._meta.model_name
class EntityAPITest(
APITestCases,
TestCase,
):
kwargs_item_create: dict = None
model = Entity
url_ns_name = '_api_v2_entity'
@classmethod
def setUpTestData(self):
self.kwargs_item_create = {
'entity_type': 'entity'
}
super().setUpTestData()

View File

@ -1,27 +1,117 @@
from django.test import TestCase import pytest
from django.db import models
from access.models.entity import Entity from access.models.entity import Entity
from app.tests.unit.test_unit_models import ( from app.tests.unit.test_unit_models import (
TenancyObjectInheritedCases PyTestTenancyObjectInheritedCases,
) )
class EntityModelTestCases( class EntityModelTestCases(
TenancyObjectInheritedCases, PyTestTenancyObjectInheritedCases,
): ):
model = Entity base_model = Entity
kwargs_item_create: dict = {} kwargs_create_item: dict = {}
sub_model_type = 'entity'
"""Sub Model Type
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
"""
parameterized_fields: dict = {
"entity_type": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
# 'field_parameter_default_value': 'entity',
'field_parameter_verbose_name_type': str
},
# "asset_number": {
# 'field_type': models.fields.CharField,
# 'field_parameter_default_exists': False,
# 'field_parameter_verbose_name_type': str,
# },
# "serial_number": {
# 'field_type': models.fields.CharField,
# 'field_parameter_default_exists': False,
# 'field_parameter_verbose_name_type': str,
# }
}
@pytest.fixture( scope = 'class')
def setup_model(self,
request,
model,
django_db_blocker,
organization_one,
organization_two
):
with django_db_blocker.unblock():
request.cls.organization = organization_one
request.cls.different_organization = organization_two
kwargs_create_item = {}
for base in reversed(request.cls.__mro__):
if hasattr(base, 'kwargs_create_item'):
if base.kwargs_create_item is None:
continue
kwargs_create_item.update(**base.kwargs_create_item)
if len(kwargs_create_item) > 0:
request.cls.kwargs_create_item = kwargs_create_item
if 'organization' not in request.cls.kwargs_create_item:
request.cls.kwargs_create_item.update({
'organization': request.cls.organization
})
yield
@pytest.fixture( scope = 'class', autouse = True)
def class_setup(self,
setup_model,
create_model,
):
pass
def test_class_inherits_entity(self):
""" Class inheritence
TenancyObject must inherit SaveHistory
"""
assert issubclass(self.model, Entity)
def test_attribute_type_history_app_label(self): def test_attribute_type_history_app_label(self):
"""Attribute Type """Attribute Type
history_app_name is of type str history_app_label is of type str
""" """
assert type(self.model.history_app_label) is str assert type(self.model.history_app_label) is str
@ -30,11 +120,11 @@ class EntityModelTestCases(
def test_attribute_value_history_app_label(self): def test_attribute_value_history_app_label(self):
"""Attribute Type """Attribute Type
history_app_name is of type str history_app_label has been set, override this test case with the value
of attribute `history_app_label`
""" """
assert self.model.history_app_label == self.model._meta.app_label assert self.model.history_app_label == 'access'
@ -50,10 +140,11 @@ class EntityModelTestCases(
def test_attribute_value_history_model_name(self): def test_attribute_value_history_model_name(self):
"""Attribute Type """Attribute Type
history_model_name is of type str history_model_name has been set, override this test case with the value
of attribute `history_model_name`
""" """
assert self.model.history_model_name == self.model._meta.model_name assert self.model.history_model_name == 'entity'
@ -69,7 +160,8 @@ class EntityModelTestCases(
def test_attribute_value_kb_model_name(self): def test_attribute_value_kb_model_name(self):
"""Attribute Type """Attribute Type
kb_model_name is of type str kb_model_name has been set, override this test case with the value
of attribute `kb_model_name`
""" """
assert self.model.kb_model_name == 'entity' assert self.model.kb_model_name == 'entity'
@ -88,40 +180,95 @@ class EntityModelTestCases(
def test_attribute_value_note_basename(self): def test_attribute_value_note_basename(self):
"""Attribute Type """Attribute Type
note_basename is of type str note_basename has been set, override this test case with the value
of attribute `note_basename`
""" """
assert self.model.note_basename == '_api_v2_entity_note' assert self.model.note_basename == '_api_v2_entity_note'
# def test_function_is_property_get_model_type(self):
# """Function test
# Confirm function `get_model_type` is a property
# """
# assert type(self.model.get_model_type) is property
# def test_function_value_get_model_type(self):
# """Function test
# Confirm function `get_model_type` does not have a value of None
# value should be equaul to Meta.sub_model_type
# """
# assert self.item.get_model_type == self.item._meta.sub_model_type
def test_function_value_get_related_model(self):
"""Function test
Confirm function `get_related_model` is of the sub-model type
"""
assert type(self.item.get_related_model()) == self.model
def test_function_value_get_url(self):
assert self.item.get_url() == '/api/v2/access/entity/' + str(self.item.id)
class EntityModelInheritedCases( class EntityModelInheritedCases(
EntityModelTestCases, EntityModelTestCases,
): ):
"""Sub-Entity Test Cases """Sub-Ticket Test Cases
Test Cases for Entity models that inherit from model Entity Test Cases for Ticket models that inherit from model Entity
""" """
kwargs_item_create: dict = None kwargs_create_item: dict = {}
model = None model = None
@classmethod sub_model_type = None
def setUpTestData(self): """Ticket Sub Model Type
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
"""
self.kwargs_item_create.update(
super().kwargs_item_create
)
super().setUpTestData() # def test_function_value_get_model_type(self):
# """Function test
# Confirm function `get_model_type` does not have a value of None
# value should be equaul to Meta.sub_model_type
# """
# assert self.item.get_model_type == self.item._meta.sub_model_type
class EntityModelTest( class EntityModelPyTest(
EntityModelTestCases, EntityModelTestCases,
TestCase,
): ):
pass
def test_function_value_get_related_model(self):
"""Function test
Confirm function `get_related_model` is None for base model
"""
assert self.item.get_related_model() is None

View File

@ -1,7 +1,9 @@
import django
import pytest import pytest
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from django.contrib.auth.models import User, Permission, AnonymousUser from django.contrib.auth.models import Permission, AnonymousUser
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
@ -13,7 +15,7 @@ from api.viewsets.common import ModelViewSet
from access.mixins.organization import OrganizationMixin from access.mixins.organization import OrganizationMixin
from access.mixins.permissions import OrganizationPermissionMixin from access.mixins.permissions import OrganizationPermissionMixin
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
@ -23,6 +25,8 @@ from core.models.manufacturer import Manufacturer
from settings.models.app_settings import AppSettings from settings.models.app_settings import AppSettings
User = django.contrib.auth.get_user_model()
class MyMockView( class MyMockView(

View File

@ -1,18 +1,21 @@
import django
import pytest import pytest
import unittest import unittest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.relations import Hyperlink from rest_framework.relations import Hyperlink
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
User = django.contrib.auth.get_user_model()

View File

@ -1,21 +1,24 @@
import django
import pytest import pytest
import unittest import unittest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.relations import Hyperlink from rest_framework.relations import Hyperlink
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APICommonFields from api.tests.abstract.api_fields import APICommonFields
User = django.contrib.auth.get_user_model()
class OrganizationAPI( class OrganizationAPI(
TestCase, TestCase,

View File

@ -1,6 +1,7 @@
# from django.conf import settings import django
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import TestCase, Client from django.test import TestCase, Client
@ -9,15 +10,17 @@ import pytest
import unittest import unittest
import requests import requests
from access.models.organization import Organization from access.models.tenant import Tenant
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from access.tests.abstract.model_permissions_organization_manager import OrganizationManagerModelPermissionChange, OrganizationManagerModelPermissionView from access.tests.abstract.model_permissions_organization_manager import OrganizationManagerModelPermissionChange, OrganizationManagerModelPermissionView
from app.tests.abstract.model_permissions import ModelPermissionsView, ModelPermissionsChange from app.tests.abstract.model_permissions import ModelPermissionsView, ModelPermissionsChange
User = django.contrib.auth.get_user_model()
class OrganizationPermissions(
class TenantPermissions(
TestCase, TestCase,
ModelPermissionsView, ModelPermissionsView,
ModelPermissionsChange, ModelPermissionsChange,
@ -25,7 +28,7 @@ class OrganizationPermissions(
OrganizationManagerModelPermissionView, OrganizationManagerModelPermissionView,
): ):
model = Organization model = Tenant
app_namespace = 'Access' app_namespace = 'Access'
@ -50,11 +53,11 @@ class OrganizationPermissions(
4. create a user per team 4. create a user per team
""" """
organization = Organization.objects.create(name='test_org') organization = Tenant.objects.create(name='test_org')
self.organization = organization self.organization = organization
different_organization = Organization.objects.create( different_organization = Tenant.objects.create(
name='test_different_organization' name='test_different_organization'
) )

View File

@ -1,18 +1,21 @@
import django
import pytest import pytest
import unittest import unittest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_permissions import APIPermissionChange, APIPermissionView from api.tests.abstract.api_permissions import APIPermissionChange, APIPermissionView
User = django.contrib.auth.get_user_model()
class OrganizationPermissionsAPI(TestCase, APIPermissionChange, APIPermissionView): class OrganizationPermissionsAPI(TestCase, APIPermissionChange, APIPermissionView):

View File

@ -7,7 +7,7 @@ import unittest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team

View File

@ -3,7 +3,7 @@ from django.test import TestCase
from core.tests.abstract.test_unit_model_history_api_v2 import PrimaryModelHistoryAPI from core.tests.abstract.test_unit_model_history_api_v2 import PrimaryModelHistoryAPI
from access.models.organization_history import Organization, OrganizationHistory from access.models.organization_history import Tenant as Organization, OrganizationHistory

View File

@ -0,0 +1,14 @@
import pytest
from access.models.person import Person
@pytest.fixture( scope = 'class')
def model(request):
request.cls.model = Person
yield request.cls.model
del request.cls.model

View File

@ -0,0 +1,50 @@
from access.tests.unit.entity.test_unit_entity_api_fields import (
EntityAPIInheritedCases
)
class PersonAPITestCases(
EntityAPIInheritedCases,
):
parameterized_test_data = {
'f_name': {
'expected': str
},
'm_name': {
'expected': str
},
'l_name': {
'expected': str
},
'dob': {
'expected': str
}
}
kwargs_create_item: dict = {
'entity_type': 'person',
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Funny',
'dob': '2025-04-08',
}
class PersonAPIInheritedCases(
PersonAPITestCases,
):
kwargs_create_item: dict = None
model = None
class PersonAPIPyTest(
PersonAPITestCases,
):
pass

View File

@ -1,127 +0,0 @@
from django.test import TestCase
from access.models.person import Person
from access.tests.unit.entity.test_unit_entity_api_v2 import (
EntityAPIInheritedCases,
)
class APITestCases(
EntityAPIInheritedCases,
):
model = Person
kwargs_item_create: dict = {}
url_ns_name = '_api_v2_entity_sub'
@classmethod
def setUpTestData(self):
self.kwargs_item_create.update({
'f_name': 'Ian',
'm_name': 'Peter',
'l_name': 'Funny',
'dob': '2025-04-08',
})
super().setUpTestData()
def test_api_field_exists_f_name(self):
""" Test for existance of API Field
f_name field must exist
"""
assert 'f_name' in self.api_data
def test_api_field_type_f_name(self):
""" Test for type for API Field
f_name field must be str
"""
assert type(self.api_data['f_name']) is str
def test_api_field_exists_m_name(self):
""" Test for existance of API Field
m_name field must exist
"""
assert 'm_name' in self.api_data
def test_api_field_type_f_name(self):
""" Test for type for API Field
m_name field must be str
"""
assert type(self.api_data['m_name']) is str
def test_api_field_exists_l_name(self):
""" Test for existance of API Field
l_name field must exist
"""
assert 'l_name' in self.api_data
def test_api_field_type_f_name(self):
""" Test for type for API Field
l_name field must be str
"""
assert type(self.api_data['l_name']) is str
def test_api_field_exists_dob(self):
""" Test for existance of API Field
dob field must exist
"""
assert 'dob' in self.api_data
def test_api_field_type_dob(self):
""" Test for type for API Field
dob field must be str
"""
assert type(self.api_data['dob']) is str
class PersonAPIInheritedCases(
APITestCases,
):
"""Sub-Entity Test Cases
Test Cases for Entity models that inherit from model Person
"""
kwargs_item_create: dict = None
model = None
class PersonAPITest(
APITestCases,
TestCase,
):
pass

View File

@ -1,5 +1,6 @@
from django.db.models.fields import NOT_PROVIDED import pytest
from django.test import TestCase
from django.db import models
from access.models.person import Person from access.models.person import Person
from access.tests.unit.entity.test_unit_entity_model import ( from access.tests.unit.entity.test_unit_entity_model import (
@ -8,88 +9,114 @@ from access.tests.unit.entity.test_unit_entity_model import (
class ModelTestCases( class PersonModelTestCases(
EntityModelInheritedCases, EntityModelInheritedCases,
): ):
model = Person kwargs_create_item: dict = {
kwargs_item_create: dict = {
'f_name': 'Ian', 'f_name': 'Ian',
'm_name': 'Peter', 'm_name': 'Peter',
'l_name': 'Funny', 'l_name': 'Funny',
'dob': '2025-04-08', 'dob': '2025-04-08',
} }
sub_model_type = 'person'
"""Sub Model Type
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
"""
def test_model_field_dob_optional(self): parameterized_fields: dict = {
"""Test Field "f_name": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"m_name": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"l_name": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"dob": {
'field_type': models.fields.DateField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
}
Field `dob` must be an optional field
def test_class_inherits_person(self):
""" Class inheritence
TenancyObject must inherit SaveHistory
""" """
assert self.model._meta.get_field('dob').blank assert issubclass(self.model, Person)
def test_model_field_f_name_mandatory(self): def test_attribute_value_history_app_label(self):
"""Test Field """Attribute Type
Field `f_name` must be a mandatory field history_app_label has been set, override this test case with the value
of attribute `history_app_label`
""" """
assert( assert self.model.history_app_label == 'access'
not (
self.model._meta.get_field('f_name').blank
and self.model._meta.get_field('f_name').null
)
and self.model._meta.get_field('f_name').default is NOT_PROVIDED
)
def test_model_field_l_name_mandatory(self): def test_attribute_value_history_model_name(self):
"""Test Field """Attribute Type
Field `l_name` must be a mandatory field history_model_name has been set, override this test case with the value
of attribute `history_model_name`
""" """
assert ( assert self.model.history_model_name == 'person'
not (
self.model._meta.get_field('l_name').blank
and self.model._meta.get_field('l_name').null
) def test_function_value_get_url(self):
and self.model._meta.get_field('l_name').default is NOT_PROVIDED
) assert self.item.get_url() == '/api/v2/access/entity/person/' + str(self.item.id)
class PersonModelInheritedCases( class PersonModelInheritedCases(
ModelTestCases, PersonModelTestCases,
): ):
"""Sub-Entity Test Cases """Sub-Ticket Test Cases
Test Cases for Entity models that inherit from model Person Test Cases for Ticket models that inherit from model Entity
""" """
kwargs_item_create: dict = None kwargs_create_item: dict = {}
model = None model = None
sub_model_type = None
@classmethod """Ticket Sub Model Type
def setUpTestData(self):
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
self.kwargs_item_create.update( """
super().kwargs_item_create
)
super().setUpTestData()
class PersonModelTest( class PersonModelPyTest(
ModelTestCases, PersonModelTestCases,
TestCase,
): ):
pass
def test_function_value_get_related_model(self):
"""Function test
Confirm function `get_related_model` is None for base model
"""
assert self.item.get_related_model() is None

View File

@ -1,4 +1,6 @@
from django.contrib.auth.models import Permission, User import django
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
@ -6,12 +8,14 @@ from django.test import Client, TestCase
# from rest_framework.relations import Hyperlink # from rest_framework.relations import Hyperlink
from access.models.role import Role from access.models.role import Role
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject from api.tests.abstract.api_fields import APITenancyObject
User = django.contrib.auth.get_user_model()
class APITestCases( class APITestCases(

View File

@ -1,22 +1,25 @@
import django
import pytest import pytest
import unittest import unittest
import requests import requests
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.relations import Hyperlink from rest_framework.relations import Hyperlink
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
# from api.tests.abstract.api_permissions import APIPermissions # from api.tests.abstract.api_permissions import APIPermissions
User = django.contrib.auth.get_user_model()
class TeamAPI(TestCase): class TeamAPI(TestCase):

View File

@ -1,18 +1,21 @@
import django
import pytest import pytest
from django.contrib.auth.models import Permission, User from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.relations import Hyperlink from rest_framework.relations import Hyperlink
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject from api.tests.abstract.api_fields import APITenancyObject
User = django.contrib.auth.get_user_model()
class TeamAPI( class TeamAPI(

View File

@ -1,6 +1,6 @@
# from django.conf import settings import django
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import TestCase, Client from django.test import TestCase, Client
@ -9,13 +9,15 @@ import pytest
import unittest import unittest
import requests import requests
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from access.tests.abstract.model_permissions_organization_manager import OrganizationManagerModelPermissions from access.tests.abstract.model_permissions_organization_manager import OrganizationManagerModelPermissions
from app.tests.abstract.model_permissions import ModelPermissions from app.tests.abstract.model_permissions import ModelPermissions
User = django.contrib.auth.get_user_model()
class TeamPermissions( class TeamPermissions(

View File

@ -1,19 +1,22 @@
import django
import pytest import pytest
import unittest import unittest
import requests import requests
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_permissions import APIPermissions from api.tests.abstract.api_permissions import APIPermissions
User = django.contrib.auth.get_user_model()
class TeamPermissionsAPI(TestCase, APIPermissions): class TeamPermissionsAPI(TestCase, APIPermissions):

View File

@ -1,18 +1,21 @@
import django
import pytest import pytest
from django.contrib.auth.models import Permission, User from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework.relations import Hyperlink from rest_framework.relations import Hyperlink
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APICommonFields from api.tests.abstract.api_fields import APICommonFields
User = django.contrib.auth.get_user_model()
class TeamUserAPI( class TeamUserAPI(

View File

@ -7,7 +7,7 @@ import unittest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team

View File

@ -1,6 +1,6 @@
# from django.conf import settings import django
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission, User from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import TestCase, Client from django.test import TestCase, Client
@ -9,7 +9,7 @@ import pytest
import unittest import unittest
import requests import requests
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
@ -17,6 +17,8 @@ from access.tests.abstract.model_permissions_organization_manager import Organiz
from app.tests.abstract.model_permissions import ModelPermissionsAdd, ModelPermissionsChange, ModelPermissionsDelete from app.tests.abstract.model_permissions import ModelPermissionsAdd, ModelPermissionsChange, ModelPermissionsDelete
User = django.contrib.auth.get_user_model()
class TeamUserPermissions( class TeamUserPermissions(

View File

@ -1,12 +1,14 @@
import django
from django.test import TestCase from django.test import TestCase
from django.contrib.auth.models import User
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from app.tests.unit.test_unit_models import NonTenancyObjectInheritedCases from app.tests.unit.test_unit_models import NonTenancyObjectInheritedCases
User = django.contrib.auth.get_user_model()
class TeamUsersModel( class TeamUsersModel(

View File

@ -7,7 +7,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.test import TestCase from django.test import TestCase
from django.urls.exceptions import NoReverseMatch from django.urls.exceptions import NoReverseMatch
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.tenancy import TenancyManager from access.models.tenancy import TenancyManager
from access.models.tenancy import ( from access.models.tenancy import (
TenancyObject, TenancyObject,

View File

@ -4,7 +4,7 @@ from django.utils.decorators import method_decorator
from django.views import generic from django.views import generic
from access.mixin import * from access.mixin import *
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.forms.organization import OrganizationForm from access.forms.organization import OrganizationForm
@ -15,7 +15,7 @@ class IndexView(IndexView):
model = Organization model = Organization
permission_required = [ permission_required = [
'access.view_organization' 'access.view_tenant'
] ]
template_name = 'access/index.html.j2' template_name = 'access/index.html.j2'
context_object_name = "organization_list" context_object_name = "organization_list"
@ -61,7 +61,7 @@ class View(ChangeView):
return self.handle_no_permission() return self.handle_no_permission()
if not self.permission_check(request, [ 'access.view_organization' ]): if not self.permission_check(request, [ 'access.view_tenant' ]):
raise PermissionDenied('You are not part of this organization') raise PermissionDenied('You are not part of this organization')
@ -97,7 +97,7 @@ class View(ChangeView):
return self.handle_no_permission() return self.handle_no_permission()
if not self.permission_check(request, [ 'access.change_organization' ]): if not self.permission_check(request, [ 'access.change_tenant' ]):
raise PermissionDenied('You are not part of this organization') raise PermissionDenied('You are not part of this organization')

View File

@ -5,7 +5,7 @@ from django.urls import reverse
from access.forms.team import TeamForm, TeamFormAdd from access.forms.team import TeamForm, TeamFormAdd
from access.mixin import * from access.mixin import *
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers

View File

@ -3,9 +3,9 @@ from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiResp
# THis import only exists so that the migrations can be created # THis import only exists so that the migrations can be created
from access.models.organization_history import OrganizationHistory # pylint: disable=W0611:unused-import from access.models.organization_history import OrganizationHistory # pylint: disable=W0611:unused-import
from access.serializers.organization import ( from access.serializers.organization import (
Organization, Tenant,
OrganizationModelSerializer, TenantModelSerializer,
OrganizationViewSerializer TenantViewSerializer
) )
from api.viewsets.common import ModelViewSet from api.viewsets.common import ModelViewSet
@ -19,7 +19,7 @@ from api.viewsets.common import ModelViewSet
description='', description='',
responses = { responses = {
# 200: OpenApiResponse(description='Allready exists', response=OrganizationViewSerializer), # 200: OpenApiResponse(description='Allready exists', response=OrganizationViewSerializer),
201: OpenApiResponse(description='Created', response=OrganizationViewSerializer), 201: OpenApiResponse(description='Created', response=TenantViewSerializer),
# 400: OpenApiResponse(description='Validation failed.'), # 400: OpenApiResponse(description='Validation failed.'),
403: OpenApiResponse(description='User is missing add permissions'), 403: OpenApiResponse(description='User is missing add permissions'),
} }
@ -36,7 +36,7 @@ from api.viewsets.common import ModelViewSet
summary = 'Fetch all orgnaizations', summary = 'Fetch all orgnaizations',
description='', description='',
responses = { responses = {
200: OpenApiResponse(description='', response=OrganizationViewSerializer), 200: OpenApiResponse(description='', response=TenantViewSerializer),
403: OpenApiResponse(description='User is missing view permissions'), 403: OpenApiResponse(description='User is missing view permissions'),
} }
), ),
@ -44,7 +44,7 @@ from api.viewsets.common import ModelViewSet
summary = 'Fetch a single orgnaization', summary = 'Fetch a single orgnaization',
description='', description='',
responses = { responses = {
200: OpenApiResponse(description='', response=OrganizationViewSerializer), 200: OpenApiResponse(description='', response=TenantViewSerializer),
403: OpenApiResponse(description='User is missing view permissions'), 403: OpenApiResponse(description='User is missing view permissions'),
} }
), ),
@ -53,7 +53,7 @@ from api.viewsets.common import ModelViewSet
summary = 'Update an orgnaization', summary = 'Update an orgnaization',
description = '', description = '',
responses = { responses = {
200: OpenApiResponse(description='', response=OrganizationViewSerializer), 200: OpenApiResponse(description='', response=TenantViewSerializer),
# 201: OpenApiResponse(description='Created', response=OrganizationViewSerializer), # 201: OpenApiResponse(description='Created', response=OrganizationViewSerializer),
# # 400: OpenApiResponse(description='Validation failed.'), # # 400: OpenApiResponse(description='Validation failed.'),
403: OpenApiResponse(description='User is missing change permissions'), 403: OpenApiResponse(description='User is missing change permissions'),
@ -71,9 +71,9 @@ class ViewSet( ModelViewSet ):
'name', 'name',
] ]
model = Organization model = Tenant
view_description = 'Centurion Organizations' view_description = 'Centurion Tenants'
def get_serializer_class(self): def get_serializer_class(self):

View File

@ -1,6 +1,6 @@
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse
from access.models.organization import Organization from access.models.tenant import Tenant as Organization
# THis import only exists so that the migrations can be created # THis import only exists so that the migrations can be created
from access.models.team_history import TeamHistory # pylint: disable=W0611:unused-import from access.models.team_history import TeamHistory # pylint: disable=W0611:unused-import
from access.serializers.teams import ( from access.serializers.teams import (

Some files were not shown because too many files have changed in this diff Show More