diff --git a/inventory_project/settings/base.py b/inventory_project/settings/base.py
index 1cc421d..ae6fc34 100644
--- a/inventory_project/settings/base.py
+++ b/inventory_project/settings/base.py
@@ -31,6 +31,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'django.contrib.sites',
'bx_py_utils', # https://github.com/boxine/bx_py_utils
'import_export', # https://github.com/django-import-export/django-import-export
@@ -41,12 +42,14 @@ INSTALLED_APPS = [
'tagulous', # https://github.com/radiac/django-tagulous
'adminsortable2', # https://github.com/jrief/django-admin-sortable2
'axes', # https://github.com/jazzband/django-axes
+ 'django_processinfo', # https://github.com/jedie/django-processinfo/
'inventory.apps.InventoryConfig',
]
ROOT_URLCONF = 'inventory_project.urls'
WSGI_APPLICATION = 'inventory_project.wsgi.application'
+SITE_ID = 1
AUTHENTICATION_BACKENDS = [
'axes.backends.AxesBackend',
@@ -54,6 +57,8 @@ AUTHENTICATION_BACKENDS = [
]
MIDDLEWARE = [
+ 'django_processinfo.middlewares.ProcessInfoMiddleware',
+
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
@@ -109,6 +114,14 @@ STATIC_ROOT = str(__Path(BASE_PATH, 'static'))
MEDIA_URL = '/media/'
MEDIA_ROOT = str(__Path(BASE_PATH, 'media'))
+# _____________________________________________________________________________
+# django-processinfo
+
+from django_processinfo import app_settings as PROCESSINFO # noqa
+
+
+PROCESSINFO.ADD_INFO = False # Don't add info in HTML page
+
# _____________________________________________________________________________
# Django-dbbackup
diff --git a/inventory_project/tests/test_admin.py b/inventory_project/tests/test_admin.py
index 48db912..b350dd1 100644
--- a/inventory_project/tests/test_admin.py
+++ b/inventory_project/tests/test_admin.py
@@ -1,8 +1,11 @@
-import pytest
+from django.contrib.auth.models import User
from django.test import TestCase
+from django_processinfo.models import ProcessInfo, SiteStatistics
+from model_bakery import baker
+
+from inventory.permissions import get_or_create_normal_user_group
-@pytest.mark.django_db
class AdminAnonymousTests(TestCase):
"""
Anonymous will be redirected to the login page.
@@ -15,3 +18,58 @@ class AdminAnonymousTests(TestCase):
def test_login_de(self):
response = self.client.get("/admin/", HTTP_ACCEPT_LANGUAGE="de")
self.assertRedirects(response, expected_url="/admin/login/?next=/admin/")
+
+
+class ProcessinfoAdminTestCase(TestCase):
+ @classmethod
+ def setUpTestData(cls):
+ cls.superuser = baker.make(
+ User, is_staff=True, is_active=True, is_superuser=True
+ )
+ cls.normaluser = baker.make(
+ User, is_staff=True, is_active=True, is_superuser=False
+ )
+ assert cls.normaluser.user_permissions.count() == 0
+ group = get_or_create_normal_user_group()[0]
+ cls.normaluser.groups.set([group])
+
+ def test_superuser_access(self):
+ self.client.force_login(self.superuser)
+
+ assert SiteStatistics.objects.count() == 0
+ assert ProcessInfo.objects.count() == 0
+
+ response = self.client.get('/admin/django_processinfo/sitestatistics/')
+ self.assertTemplateUsed(response, 'admin/django_processinfo/change_list.html')
+
+ response = response.content.decode("utf-8")
+ self.assertInHTML('
System information
', response)
+ self.assertInHTML('Living processes (current/avg/max)', response)
+
+ assert SiteStatistics.objects.count() == 1
+ assert ProcessInfo.objects.count() == 1
+
+ response = self.client.get('/admin/django_processinfo/processinfo/')
+ self.assertTemplateUsed(response, 'admin/django_processinfo/change_list.html')
+
+ response = response.content.decode("utf-8")
+ self.assertInHTML('System information
', response)
+ self.assertInHTML('Living processes (current/avg/max)', response)
+
+ assert SiteStatistics.objects.count() == 1
+ assert ProcessInfo.objects.count() == 1
+
+ def test_normal_user_access(self):
+ self.client.force_login(self.normaluser)
+
+ assert SiteStatistics.objects.count() == 0
+ assert ProcessInfo.objects.count() == 0
+
+ response = self.client.get('/admin/django_processinfo/sitestatistics/')
+ assert response.status_code == 403
+
+ response = self.client.get('/admin/django_processinfo/processinfo/')
+ assert response.status_code == 403
+
+ assert SiteStatistics.objects.count() == 1
+ assert ProcessInfo.objects.count() == 1
diff --git a/poetry.lock b/poetry.lock
index 18aac3d..30a4522 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -324,6 +324,17 @@ category = "main"
optional = false
python-versions = "*"
+[[package]]
+name = "django-processinfo"
+version = "1.0.0"
+description = "Django application to collect information about the running server processes."
+category = "main"
+optional = false
+python-versions = ">=3.7,<4.0.0"
+
+[package.dependencies]
+Django = "*"
+
[[package]]
name = "django-reversion"
version = "3.0.8"
@@ -614,6 +625,17 @@ category = "dev"
optional = false
python-versions = "*"
+[[package]]
+name = "model-bakery"
+version = "1.2.0"
+description = "Smart object creation facility for Django."
+category = "dev"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+django = ">=1.11.0"
+
[[package]]
name = "odfpy"
version = "1.4.1"
@@ -1205,7 +1227,7 @@ postgres = ["psycopg2-binary"]
[metadata]
lock-version = "1.1"
python-versions = ">=3.7,<4.0.0"
-content-hash = "c9de646c31e5e1f0b0ff9b003d6290da61eca039c78aef8e6786894584fa37cf"
+content-hash = "745c33aa94cad303222f51896f0a9a11abdb4896cb00f87f522fe7eaa8c2325a"
[metadata.files]
appdirs = [
@@ -1414,6 +1436,10 @@ django-js-asset = [
{file = "django-js-asset-1.2.2.tar.gz", hash = "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260"},
{file = "django_js_asset-1.2.2-py2.py3-none-any.whl", hash = "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd"},
]
+django-processinfo = [
+ {file = "django-processinfo-1.0.0.tar.gz", hash = "sha256:0df4b3a011a7adb1f6b722964aca4693e79fa003b7f780025cc0d04073f00c49"},
+ {file = "django_processinfo-1.0.0-py3-none-any.whl", hash = "sha256:829e2937a9fae54ef8c0a3cb5e99a09490cf66252cee498de833377839d7e497"},
+]
django-reversion = [
{file = "django-reversion-3.0.8.tar.gz", hash = "sha256:49e9930f90322dc6a2754dd26144285cfcc1c5bd0c1c39ca95d5602c5054ae32"},
{file = "django_reversion-3.0.8-py3-none-any.whl", hash = "sha256:9cfadeec2df37cb53d795ab79f6792f9eed8e70363dcf3a275dc19a58b971a8f"},
@@ -1503,6 +1529,10 @@ mccabe = [
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
]
+model-bakery = [
+ {file = "model_bakery-1.2.0-py2.py3-none-any.whl", hash = "sha256:b25f400b392067f02d841a0ef33e861543c04b1702dc004020bdd50e1dbce05f"},
+ {file = "model_bakery-1.2.0.tar.gz", hash = "sha256:088698cdf62e5ccedeb97e55ceb966c974cc79e2514928aec9beab27a8c1faf4"},
+]
odfpy = [
{file = "odfpy-1.4.1-py2.7.egg", hash = "sha256:fc3b8d1bc098eba4a0fda865a76d9d1e577c4ceec771426bcb169a82c5e9dfe0"},
{file = "odfpy-1.4.1.tar.gz", hash = "sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec"},
diff --git a/pyproject.toml b/pyproject.toml
index 074acc5..5d2809e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -40,6 +40,7 @@ uWSGI = "*"
# https://www.djangoproject.com/download/#supported-versions
# v2.2 LTS - extended support until April 2022
django = "2.2.*"
+django-processinfo = "*" # https://github.com/jedie/django-processinfo/
django-debug-toolbar = "*" # http://django-debug-toolbar.readthedocs.io/en/stable/changes.html
django-import-export = "*" # https://github.com/django-import-export/django-import-export
django-dbbackup = "*" # https://github.com/django-dbbackup/django-dbbackup
@@ -72,6 +73,7 @@ flake8 = "*"
flynt = "*"
autopep8 = "*"
pyupgrade = "*"
+model_bakery = "*" # https://github.com/model-bakers/model_bakery
[tool.poetry.scripts]
manage = "inventory_project.manage:main"