Skip to content

Commit

Permalink
Merge pull request #118 from MEHRSHAD-MIRSHEKARY/feat/log-iboard-view
Browse files Browse the repository at this point in the history
✨ Feat/log iboard view
  • Loading branch information
ARYAN-NIKNEZHAD authored Oct 11, 2024
2 parents d86b6ff + e21d839 commit 4a415b4
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 5 deletions.
1 change: 1 addition & 0 deletions django_logging/constants/default_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class DefaultLoggingSettings:
auto_initialization_enable: bool = True
initialization_message_enable: bool = True
log_sql_queries_enable: bool = False
include_log_iboard: bool = False
log_file_formats: LogFileFormats = field(
default_factory=lambda: cast(
LogFileFormats,
Expand Down
4 changes: 4 additions & 0 deletions django_logging/settings/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django_logging.utils.get_conf import (
get_config,
get_log_dir_size_limit,
include_log_iboard,
is_auto_initialization_enabled,
is_initialization_message_enabled,
is_log_sql_queries_enabled,
Expand Down Expand Up @@ -156,6 +157,9 @@ def check_logging_settings(app_configs: Dict[str, Any], **kwargs: Any) -> List[E
log_date_format = log_settings.get("log_date_format")
errors.extend(validate_date_format(log_date_format, "LOG_DATE_FORMAT")) # type: ignore

# Validate INCLUDE_LOG_iBOARD
errors.extend(validate_boolean_setting(include_log_iboard(), "INCLUDE_LOG_iBOARD"))

# Validate AUTO_INITIALIZATION_ENABLE
errors.extend(
validate_boolean_setting(
Expand Down
6 changes: 3 additions & 3 deletions django_logging/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django_logging.tests.setup import configure_django_settings
from django_logging.tests.fixtures import (
admin_email_mock_settings,
colored_formatter,
Expand All @@ -24,7 +25,6 @@
temp_log_directory,
temp_xml_log_directory,
xml_formatter,
setup_users,
client
)
from django_logging.tests.setup import configure_django_settings

configure_django_settings()
1 change: 1 addition & 0 deletions django_logging/tests/fixtures/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
request_middleware,
)
from .settings_fixture import mock_settings, reset_settings
from .views_fixture import setup_users, client
28 changes: 28 additions & 0 deletions django_logging/tests/fixtures/views_fixture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Dict

import pytest
from django.contrib.auth.models import User
from django.test import Client


@pytest.fixture
def setup_users(db) -> Dict[str, User]:
"""
Fixture to create a superuser and a normal user for testing purposes.
Returns a dictionary with `superuser` and `non_superuser` keys.
"""
superuser = User.objects.create_superuser(
username="admin", password="adminpassword", email="[email protected]"
)
non_superuser = User.objects.create_user(
username="user", password="userpassword", email="[email protected]"
)
return {"superuser": superuser, "non_superuser": non_superuser}


@pytest.fixture
def client() -> Client:
"""
Fixture to provide a test client.
"""
return Client()
37 changes: 35 additions & 2 deletions django_logging/tests/setup.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,51 @@
import django
from django.conf import settings
import string
import random


def generate_secret_key(length: int = 50) -> str:
"""
Generates a random secret key for Django settings.
Args:
length (int): The length of the secret key. Default is 50 characters.
Returns:
str: A randomly generated secret key.
"""
characters = string.ascii_letters + string.digits + string.punctuation
return "".join(random.choice(characters) for _ in range(length))


def configure_django_settings() -> None:
if not settings.configured:
settings.configure(
DEBUG=True,
SECRET_KEY=generate_secret_key(), # Add a secret key for testing
DATABASES={
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
}
},
INSTALLED_APPS=[
"django.contrib.contenttypes",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django_logging",
],
MIDDLEWARE=[],
MIDDLEWARE=[
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
],
TEMPLATES=[
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
Expand All @@ -34,6 +62,7 @@ def configure_django_settings() -> None:
},
],
DJANGO_LOGGING={
"INCLUDE_LOG_iBOARD": True,
"AUTO_INITIALIZATION_ENABLE": True,
"INITIALIZATION_MESSAGE_ENABLE": True,
"LOG_FILE_LEVELS": ["DEBUG", "INFO"],
Expand Down Expand Up @@ -72,5 +101,9 @@ def configure_django_settings() -> None:
TIME_ZONE="UTC",
USE_I18N=True,
USE_TZ=True,
ROOT_URLCONF="django_logging.urls",
STATIC_URL="static/"
)
django.setup()

configure_django_settings()
Empty file.
59 changes: 59 additions & 0 deletions django_logging/tests/views/test_log_iboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import sys

import pytest
from django.urls import reverse
from django.test import Client
from django.contrib.auth.models import User
from typing import Dict

from django_logging.tests.constants import PYTHON_VERSION, PYTHON_VERSION_REASON

pytestmark = [
pytest.mark.views,
pytest.mark.views_log_iboard,
pytest.mark.skipif(sys.version_info < PYTHON_VERSION, reason=PYTHON_VERSION_REASON),
]


@pytest.mark.django_db
class TestLogiBoardView:
"""
Test suite for the `LogiBoardView` class-based view.
This test suite covers:
- Access control for superuser and non-superuser.
- Rendering the correct template for superuser.
- Correct response and content type for non-superuser.
Methods:
- test_superuser_access: Ensures superusers can access the LogiBoard page.
- test_non_superuser_access: Ensures non-superusers are forbidden from accessing the LogiBoard page.
"""

def test_superuser_access(
self, client: Client, setup_users: Dict[str, User]
) -> None:
"""
Test that a superuser can access the `LogiBoardView` and the correct template is rendered.
"""
client.login(username="admin", password="adminpassword")
response = client.get(reverse("log-iboard"))
assert response.status_code == 200, "Superuser should have access to the page."
assert (
"log_iboard.html" in response.template_name
), "Should render the correct template for superuser."

def test_non_superuser_access(
self, client: Client, setup_users: Dict[str, User]
) -> None:
"""
Test that a non-superuser receives a 403 Forbidden response when accessing the `LogiBoardView`.
"""
client.login(username="user", password="userpassword")
response = client.get(reverse("log-iboard"))
assert (
response.status_code == 403
), "Non-superuser should not have access to the page."
assert (
"text/html" in response["Content-Type"]
), "'text/html' should be in Content type for forbidden access."
9 changes: 9 additions & 0 deletions django_logging/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import path

from django_logging.utils.get_conf import include_log_iboard
from django_logging.views.log_iboard import LogiBoardView

urlpatterns = []

if include_log_iboard():
urlpatterns.append(path("log-iboard/", LogiBoardView.as_view(), name="log-iboard"))
15 changes: 15 additions & 0 deletions django_logging/utils/get_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,18 @@ def get_log_dir_size_limit() -> int:
defaults = DefaultLoggingSettings()

return log_settings.get("LOG_DIR_SIZE_LIMIT", defaults.log_dir_size_limit)


def include_log_iboard() -> bool:
"""Check if the INCLUDE_LOG_iBOARD for the logging system is set to True in
Django settings.
Returns:
bool: True if INCLUDE_LOG_iBOARD, False otherwise.
Defaults to False if not specified.
"""
log_settings = getattr(settings, "DJANGO_LOGGING", {})
defaults = DefaultLoggingSettings()

return log_settings.get("INCLUDE_LOG_iBOARD", defaults.include_log_iboard)
Empty file.
44 changes: 44 additions & 0 deletions django_logging/views/log_iboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import Any, Dict

from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from django.views.generic import TemplateView


class LogiBoardView(TemplateView):
"""View to render the LogiBoard page for superusers.
Non-superusers are denied access and shown an error response page
with a 403 status code.
"""

template_name = "log_iboard.html"

def get(
self, request: HttpRequest, *args: Any, **kwargs: Dict[str, Any]
) -> HttpResponse:
"""Handles GET requests. Renders the LogiBoard page for superusers,
otherwise returns a 403 error response for non-superusers.
Args:
request (HttpRequest): The HTTP request object.
*args (Any): Additional positional arguments.
**kwargs (Dict[str, Any]): Additional keyword arguments.
Returns:
HttpResponse: The rendered LogiBoard page for superusers or an error response page for non-superusers.
"""
if request.user.is_superuser:
return super().get(request, *args, **kwargs)

return render(
request,
"error_response.html",
{
"title": "Access Denied",
"message": "You do not have permission to view this page.",
},
status=403,
)
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ markers = [
"decorators_execution_tracking: Tests specifically for the execution_tracking module.",
"contextvar: Tests for context variable handling in the logging package.",
"contextvar_manager: Tests for managing context variables across different log contexts.",
"views: Tests for MVT views in the django logging package.",
"views_log_iboard: Tests specially for the log_iboard view.",
]
asyncio_default_fixture_loop_scope = [ "function" ]

Expand Down

0 comments on commit 4a415b4

Please sign in to comment.