feat(setting): Enable super admin to set ALL software as global
sets is_global=true and creates software in global organization !11 closes #27
This commit is contained in:
31
app/settings/migrations/0004_appsettings.py
Normal file
31
app/settings/migrations/0004_appsettings.py
Normal file
@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.0.6 on 2024-05-25 02:42
|
||||
|
||||
import access.fields
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0002_alter_team_organization'),
|
||||
('settings', '0003_create_settings_for_all_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AppSettings',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False, unique=True)),
|
||||
('created', access.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False)),
|
||||
('modified', access.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False)),
|
||||
('software_is_global', models.BooleanField(default=False, verbose_name='All Software is global')),
|
||||
('global_organization', models.ForeignKey(blank=True, default=None, help_text='Organization global items will be created in', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='global_organization', to='access.organization')),
|
||||
('owner_organization', models.ForeignKey(blank=True, default=None, help_text='Organization the settings belong to', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owner_organization', to='access.organization')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
35
app/settings/migrations/0005_create_settings_for_app.py
Normal file
35
app/settings/migrations/0005_create_settings_for_app.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Generated by Django 5.0.6 on 2024-05-24 23:19
|
||||
|
||||
import access.fields
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
def add_app_settings(apps, schema_editor):
|
||||
|
||||
app = apps.get_model('settings', 'appsettings')
|
||||
|
||||
if not app.objects.filter(owner_organization=None).exists():
|
||||
|
||||
setting = app.objects.create(
|
||||
owner_organization=None
|
||||
)
|
||||
|
||||
setting.save()
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0002_alter_team_organization'),
|
||||
('settings', '0004_appsettings'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_app_settings),
|
||||
]
|
68
app/settings/models/app_settings.py
Normal file
68
app/settings/models/app_settings.py
Normal file
@ -0,0 +1,68 @@
|
||||
from django.db import models
|
||||
|
||||
from access.fields import *
|
||||
from access.models import Organization
|
||||
|
||||
from core.mixin.history_save import SaveHistory
|
||||
|
||||
|
||||
class AppSettingsCommonFields(models.Model):
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
id = models.AutoField(
|
||||
primary_key=True,
|
||||
unique=True,
|
||||
blank=False
|
||||
)
|
||||
|
||||
slug = None
|
||||
|
||||
created = AutoCreatedField()
|
||||
|
||||
modified = AutoLastModifiedField()
|
||||
|
||||
|
||||
|
||||
class AppSettings(AppSettingsCommonFields, SaveHistory):
|
||||
|
||||
|
||||
owner_organization = models.ForeignKey(
|
||||
Organization,
|
||||
on_delete=models.CASCADE,
|
||||
blank= True,
|
||||
default = None,
|
||||
null = True,
|
||||
help_text = 'Organization the settings belong to',
|
||||
related_name = 'owner_organization'
|
||||
)
|
||||
|
||||
software_is_global = models.BooleanField (
|
||||
verbose_name = 'All Software is global',
|
||||
blank= False,
|
||||
default = False,
|
||||
)
|
||||
|
||||
global_organization = models.ForeignKey(
|
||||
Organization,
|
||||
on_delete=models.CASCADE,
|
||||
blank= True,
|
||||
default = None,
|
||||
null = True,
|
||||
help_text = 'Organization global items will be created in',
|
||||
related_name = 'global_organization'
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
if self.software_is_global and self.global_organization is None:
|
||||
|
||||
raise ValidationError("Global Software must have a global organization")
|
||||
|
||||
__all__ = [
|
||||
'software_is_global',
|
||||
'global_organization',
|
||||
]
|
||||
|
@ -2,9 +2,7 @@ from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
|
||||
from access.fields import *
|
||||
from access.models import TenancyObject, Organization
|
||||
|
||||
from core.mixin.history_save import SaveHistory
|
||||
from access.models import Organization
|
||||
|
||||
|
||||
class UserSettingsCommonFields(models.Model):
|
||||
|
@ -12,11 +12,14 @@ div#content {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-wrap:wrap;
|
||||
}
|
||||
|
||||
div#content article {
|
||||
/*background-color: brown;*/
|
||||
width: 47%;
|
||||
width: auto;
|
||||
min-width: 30%;
|
||||
max-width: 47%;
|
||||
display: flexbox;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
@ -32,6 +35,13 @@ div#content article h3 {
|
||||
</style>
|
||||
|
||||
<div id="content" style="">
|
||||
<article style="">
|
||||
<h3>Application</h3>
|
||||
<ul>
|
||||
<li><a href="{% url 'Settings:_settings_application' %}">Settings</a></li>
|
||||
</ul>
|
||||
</article>
|
||||
|
||||
<article style="">
|
||||
<h3>Common</h3>
|
||||
<ul>
|
||||
|
28
app/settings/tests/app_settings/test_app_settings.py
Normal file
28
app/settings/tests/app_settings/test_app_settings.py
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
from django.test import TestCase, Client
|
||||
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="to be written")
|
||||
def test_app_settings_only_super_admin_can_access():
|
||||
""" Only super admin can access app settings """
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="to be written")
|
||||
def test_app_settings_software_is_global_organization_must_be_set():
|
||||
""" If field software_is_global=true an organization must be set """
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="to be written")
|
||||
def test_app_settings_software_is_global_create_software():
|
||||
""" If field software_is_global=true on software creation regardless of user settings
|
||||
software is created in global organization with global=true
|
||||
"""
|
||||
pass
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import home, device_models, device_types, manufacturer, software_categories
|
||||
from .views import app_settings, home, device_models, device_types, manufacturer, software_categories
|
||||
|
||||
from itam.views import device_type, device_model, software_category
|
||||
|
||||
@ -9,6 +9,9 @@ urlpatterns = [
|
||||
|
||||
path("", home.View.as_view(), name="Settings"),
|
||||
|
||||
path('application', app_settings.View.as_view(), name="_settings_application"),
|
||||
|
||||
|
||||
path("device_models", device_models.Index.as_view(), name="_device_models"),
|
||||
path("device_model/<int:pk>", device_model.View.as_view(), name="_device_model_view"),
|
||||
path("device_model/add/", device_model.Add.as_view(), name="_device_model_add"),
|
||||
|
63
app/settings/views/app_settings.py
Normal file
63
app/settings/views/app_settings.py
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
from django.core.exceptions import EmptyResultSet, PermissionDenied, ValidationError
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from settings.models.app_settings import AppSettings
|
||||
|
||||
|
||||
|
||||
class View(generic.UpdateView):
|
||||
|
||||
model = AppSettings
|
||||
|
||||
context_object_name = "settings"
|
||||
|
||||
fields = model.__all__
|
||||
|
||||
template_name = 'form.html.j2'
|
||||
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
|
||||
obj = self.model.objects.get(owner_organization=None)
|
||||
|
||||
if obj:
|
||||
|
||||
return obj
|
||||
|
||||
raise EmptyResultSet('No Application Settings found')
|
||||
|
||||
|
||||
def form_valid(self, form):
|
||||
|
||||
form.instance.id = self.object.pk
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
raise PermissionDenied()
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_settings_application')
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['model_pk'] = self.object.pk
|
||||
context['model_name'] = self.model._meta.verbose_name.replace(' ', '')
|
||||
|
||||
context['content_title'] = 'Application Settings'
|
||||
|
||||
return context
|
||||
|
||||
raise PermissionDenied()
|
Reference in New Issue
Block a user