Skip to content

Commit 964a91f

Browse files
refactor: simplify config system to use Django settings directly
1 parent 2512139 commit 964a91f

File tree

14 files changed

+220
-164
lines changed

14 files changed

+220
-164
lines changed

django_postgres_anon/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import os
1818
from typing import Any, Dict
1919

20+
import django
21+
from django.core.exceptions import ImproperlyConfigured
22+
2023
__version__ = "0.1.0-alpha.1"
2124
__author__ = "Sanyam Khurana"
2225
__email__ = "[email protected]"
@@ -78,9 +81,6 @@ def check_dependencies():
7881
"""Check if required dependencies are available."""
7982
import sys
8083

81-
import django
82-
from django.core.exceptions import ImproperlyConfigured
83-
8484
# Check Python version
8585
if sys.version_info < PACKAGE_CONFIG["min_python_version"]:
8686
min_version = PACKAGE_CONFIG["min_python_version"]

django_postgres_anon/admin.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from django.utils.html import format_html
88

99
from django_postgres_anon.admin_base import BaseAnonymizationAdmin, BaseLogAdmin
10-
11-
# Removed constants - using inline values
1210
from django_postgres_anon.models import MaskedRole, MaskingLog, MaskingPreset, MaskingRule
1311

1412

@@ -264,6 +262,3 @@ def short_details(self, obj: MaskingLog) -> str:
264262
return "-"
265263

266264
short_details.short_description = "Details"
267-
268-
269-
# Custom admin views could be added here for dashboard functionality

django_postgres_anon/admin_base.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,24 @@
1111
from django_postgres_anon.constants import (
1212
ADMIN_ERROR_EMOJI,
1313
ADMIN_WARNING_EMOJI,
14+
ANON_FUNCTION_PREFIX,
15+
APPLIED_COUNT_FIELD,
16+
ERROR_FIELD,
17+
ERRORS_FIELD,
1418
EXTENSION_REQUIRED_OPERATIONS,
19+
MASKED_ROLE_MARK_APPLIED_METHOD,
20+
MAX_ERROR_SUMMARY_COUNT,
21+
MAX_ERRORS_BEFORE_ROLLBACK,
22+
MAX_ERRORS_TO_SHOW,
23+
MAX_RULES_TO_VALIDATE,
24+
SUCCESS_FIELD,
1525
VALID_ADMIN_OPERATIONS,
1626
)
1727

1828
# Simplified error handling
1929
from django_postgres_anon.utils import create_operation_log, generate_anonymization_sql, validate_anon_extension
2030

21-
# Admin-specific constants
2231
logger = logging.getLogger(__name__)
23-
MAX_RULES_TO_VALIDATE = 100
24-
ANON_FUNCTION_PREFIX = "anon."
25-
LARGE_OPERATION_THRESHOLD = 50
26-
MAX_ERRORS_TO_SHOW = 5
27-
MAX_ERROR_SUMMARY_COUNT = 3
28-
MAX_ERRORS_BEFORE_ROLLBACK = 10
29-
30-
# Field name constants for operation results
31-
APPLIED_COUNT_FIELD = "applied_count"
32-
ERRORS_FIELD = "errors"
33-
SUCCESS_FIELD = "success"
34-
ERROR_FIELD = "error"
35-
MASKED_ROLE_MARK_APPLIED_METHOD = "mark_applied"
3632

3733

3834
class BaseAnonymizationAdmin(admin.ModelAdmin):

django_postgres_anon/apps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.apps import AppConfig
44
from django.conf import settings
5+
from django.core.management import call_command
56

67
logger = logging.getLogger(__name__)
78

@@ -22,7 +23,6 @@ def ready(self):
2223

2324
def _auto_init_development(self):
2425
"""Auto-initialize anonymization in development"""
25-
from django.core.management import call_command
2626

2727
logger.info("Auto-initializing PostgreSQL Anonymizer for development")
2828
call_command("anon_init", verbosity=0)

django_postgres_anon/config.py

Lines changed: 18 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,26 @@
1-
"""Centralized configuration for django-postgres-anonymizer"""
1+
"""Simple configuration helpers for django-postgres-anonymizer"""
22

33
from django.conf import settings
44

55

6-
class AnonConfig:
7-
"""Centralized configuration class for all anonymization settings"""
6+
def get_setting(key: str, default=None):
7+
"""Get a setting from POSTGRES_ANON configuration with default fallback"""
8+
return getattr(settings, "POSTGRES_ANON", {}).get(key, default)
89

9-
def __init__(self):
10-
# Get the settings dict or use defaults
11-
config = getattr(settings, "POSTGRES_ANON", {})
1210

13-
# Set defaults
14-
self._config = {
15-
"DEFAULT_MASKED_ROLE": "masked_reader",
16-
"MASKED_GROUP": "view_masked_data",
17-
"ANONYMIZED_DATA_ROLE": "masked_reader",
18-
"ENABLED": False,
19-
"AUTO_APPLY_RULES": False,
20-
"VALIDATE_FUNCTIONS": True,
21-
"ALLOW_CUSTOM_FUNCTIONS": False,
22-
"ENABLE_LOGGING": True,
23-
}
11+
# Default values (moved from constants.py to keep config self-contained)
12+
DEFAULTS = {
13+
"DEFAULT_MASKED_ROLE": "masked_reader",
14+
"MASKED_GROUP": "view_masked_data",
15+
"ANONYMIZED_DATA_ROLE": "masked_reader",
16+
"ENABLED": False,
17+
"AUTO_APPLY_RULES": False,
18+
"VALIDATE_FUNCTIONS": True,
19+
"ALLOW_CUSTOM_FUNCTIONS": False,
20+
"ENABLE_LOGGING": True,
21+
}
2422

25-
# Override with user settings
26-
self._config.update(config)
2723

28-
@property
29-
def default_masked_role(self) -> str:
30-
"""Default role name for anonymized access"""
31-
return self._config["DEFAULT_MASKED_ROLE"]
32-
33-
@property
34-
def masked_group(self) -> str:
35-
"""Group name for users who should see masked data"""
36-
return self._config["MASKED_GROUP"]
37-
38-
@property
39-
def anonymized_data_role(self) -> str:
40-
"""Role for anonymized data context manager"""
41-
return self._config["ANONYMIZED_DATA_ROLE"]
42-
43-
@property
44-
def enabled(self) -> bool:
45-
"""Whether anonymization is enabled"""
46-
return self._config["ENABLED"]
47-
48-
@property
49-
def auto_apply_rules(self) -> bool:
50-
"""Whether to automatically apply rules when created"""
51-
return self._config["AUTO_APPLY_RULES"]
52-
53-
@property
54-
def validate_functions(self) -> bool:
55-
"""Whether to validate anonymization functions"""
56-
return self._config["VALIDATE_FUNCTIONS"]
57-
58-
@property
59-
def allow_custom_functions(self) -> bool:
60-
"""Whether to allow custom anonymization functions"""
61-
return self._config["ALLOW_CUSTOM_FUNCTIONS"]
62-
63-
@property
64-
def enable_logging(self) -> bool:
65-
"""Whether to enable audit logging"""
66-
return self._config["ENABLE_LOGGING"]
67-
68-
69-
# Global configuration instance
70-
anon_config = AnonConfig()
24+
def get_anon_setting(key: str):
25+
"""Get anonymization setting with built-in default"""
26+
return get_setting(key, DEFAULTS.get(key))

django_postgres_anon/constants.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@
1313
ADMIN_ERROR_EMOJI = "❌"
1414
ADMIN_WARNING_EMOJI = "⚠️"
1515

16+
# Admin operation constants
17+
MAX_RULES_TO_VALIDATE = 100
18+
ANON_FUNCTION_PREFIX = "anon."
19+
MAX_ERRORS_TO_SHOW = 5
20+
MAX_ERROR_SUMMARY_COUNT = 3
21+
MAX_ERRORS_BEFORE_ROLLBACK = 10
22+
23+
# Field name constants for operation results
24+
APPLIED_COUNT_FIELD = "applied_count"
25+
ERRORS_FIELD = "errors"
26+
SUCCESS_FIELD = "success"
27+
ERROR_FIELD = "error"
28+
MASKED_ROLE_MARK_APPLIED_METHOD = "mark_applied"
29+
1630
# SQL templates
1731
ANONYMIZATION_SQL_TEMPLATE = "SECURITY LABEL FOR anon ON COLUMN {table}.{column} IS 'MASKED WITH FUNCTION {function}';"
1832
REMOVE_ANONYMIZATION_SQL_TEMPLATE = "SECURITY LABEL FOR anon ON COLUMN {table}.{column} IS NULL;"

django_postgres_anon/context_managers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from django.db import connection
88

9-
from django_postgres_anon.config import anon_config
9+
from django_postgres_anon.config import get_anon_setting
1010

1111
# ErrorHandler no longer needed
1212
from django_postgres_anon.models import MaskedRole
@@ -41,7 +41,7 @@ def anonymized_data(role_name: Optional[str] = None, auto_create: bool = True) -
4141
Exception: If role switching fails
4242
"""
4343
if role_name is None:
44-
role_name = anon_config.anonymized_data_role
44+
role_name = get_anon_setting("ANONYMIZED_DATA_ROLE")
4545

4646
# Initialize state tracking
4747
state = _initialize_context_state()

django_postgres_anon/management/commands/anon_drop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.core.management.base import BaseCommand, CommandError
44
from django.db import connection
5+
from django.db.models import Count
56

67
from django_postgres_anon.models import MaskedRole, MaskingPreset, MaskingRule
78
from django_postgres_anon.utils import create_operation_log, generate_remove_anonymization_sql, validate_anon_extension
@@ -213,7 +214,6 @@ def _remove_masking_rules(self, options):
213214
def _remove_masking_presets(self, options):
214215
"""Remove masking presets that have no rules"""
215216
# Find presets with no rules - use annotate to avoid distinct() issue with delete()
216-
from django.db.models import Count
217217

218218
empty_presets = MaskingPreset.objects.annotate(rules_count=Count("rules")).filter(rules_count=0)
219219

django_postgres_anon/middleware.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.db import DatabaseError, OperationalError, connection
55
from django.http import HttpRequest, HttpResponse
66

7-
from django_postgres_anon.config import anon_config
7+
from django_postgres_anon.config import get_anon_setting
88
from django_postgres_anon.utils import reset_role, switch_to_role
99

1010
logger = logging.getLogger(__name__)
@@ -27,16 +27,16 @@ def __call__(self, request: HttpRequest) -> HttpResponse:
2727
# Check if user should have data masked - defensive against user access issues
2828
try:
2929
should_mask = (
30-
anon_config.enabled
30+
get_anon_setting("ENABLED")
3131
and request.user.is_authenticated
32-
and request.user.groups.filter(name=anon_config.masked_group).exists()
32+
and request.user.groups.filter(name=get_anon_setting("MASKED_GROUP")).exists()
3333
)
3434
except Exception:
3535
# If there's any issue with user/group access, default to no masking
3636
should_mask = False
3737

3838
if should_mask:
39-
masked_role = anon_config.default_masked_role
39+
masked_role = get_anon_setting("DEFAULT_MASKED_ROLE")
4040

4141
if switch_to_role(masked_role, auto_create=True):
4242
used_mask = True

django_postgres_anon/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import Optional
44

55
import yaml
6+
from django.conf import settings
67
from django.db import DatabaseError, OperationalError, connection, models
78
from django.db.models.signals import post_save, pre_save
89
from django.dispatch import receiver
@@ -196,8 +197,6 @@ def handle_rule_disabled(sender, instance, created, **kwargs):
196197
# Skip if we're in a test environment with fake table names
197198
import sys
198199

199-
from django.conf import settings
200-
201200
# Check various test indicators
202201
if (hasattr(settings, "TESTING") and settings.TESTING) or "test" in sys.argv or "pytest" in sys.modules:
203202
return

0 commit comments

Comments
 (0)