Skip to content

Commit 9ac39e0

Browse files
docs: Update docs + ensure core functionality
1 parent bad3f94 commit 9ac39e0

File tree

28 files changed

+220
-588
lines changed

28 files changed

+220
-588
lines changed

CHANGELOG.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,21 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
2020
**Changed**
2121

2222
* Improved documentation structure and clarity
23-
* Refined compliance messaging - positions as compliance support tool
23+
* Contributing and changelog docs use RST include directives for single source of truth
24+
25+
**Fixed**
26+
27+
* ``ALLOW_CUSTOM_FUNCTIONS`` setting now properly controls validation
28+
* ``ENABLE_LOGGING`` setting now properly controls operation logging
29+
* ``VALIDATE_FUNCTIONS`` setting now properly controls function validation in management commands
30+
* API reference now documents only public-facing functions (``get_anon_setting``, ``validate_anon_extension``)
2431

2532
**Removed**
2633

2734
* ``database_role()`` context manager - unsafe arbitrary role switching
2835
* ``@database_role_required()`` decorator - potential security risk
2936
* Direct role manipulation utilities - use ``anonymized_data()`` instead
37+
* ``AUTO_APPLY_RULES`` setting - feature was never implemented, removed to avoid confusion
3038

3139
0.1.0-alpha.1 - 2025-09-20
3240
--------------------------

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ Before submitting a PR, ensure your code passes all quality checks:
117117
- Follow the existing code style
118118
- Add tests for new functionality
119119
- Update documentation as needed
120-
- Add your changes to ``CHANGELOG.md`` under ``[Unreleased]``
120+
- Add your changes to ``CHANGELOG.rst`` or ``docs/changelog.rst``
121121

122122
3. **Test your changes**
123123

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def sensitive_report(request):
105105
### Privacy & Compliance
106106

107107
- **🔒 Privacy by Design** - Reduce risk of data exposure in non-production environments
108-
- **📋 Compliance Support** - Tool to help with data protection requirements (consult legal counsel for compliance certification)
108+
- **📋 Compliance Support** - Tool to help with data protection requirements
109109
- **🛡️ Data Minimization** - Limit exposure of sensitive data to development teams
110110

111111
## 🤔 Why Not Just...?

README.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ Privacy & Compliance
134134
- **🔒 Privacy by Design** - Reduce risk of data exposure in
135135
non-production environments
136136
- **📋 Compliance Support** - Tool to help with data protection
137-
requirements (consult legal counsel for compliance certification)
137+
requirements
138138
- **🛡️ Data Minimization** - Limit exposure of sensitive data to
139139
development teams
140140

@@ -169,11 +169,13 @@ automatic, middleware-based anonymization that just works.
169169
C --> D[Anonymized Views]
170170
D --> E[Masked Data]
171171
172-
**Core Components:** - **Middleware** - Automatic anonymization for user
173-
groups - **Context Managers** - Manual anonymized data access -
174-
**Decorators** - View-level anonymization - **Admin Interface** - Rule
175-
management and monitoring - **Management Commands** - CLI operations and
176-
automation
172+
**Core Components:**
173+
174+
- **Middleware** - Automatic anonymization for user groups
175+
- **Context Managers** - Manual anonymized data access
176+
- **Decorators** - View-level anonymization
177+
- **Admin Interface** - Rule management and monitoring
178+
- **Management Commands** - CLI operations and automation
177179

178180
🛡️ Security Features
179181
--------------------

SECURITY.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ except Exception as e:
101101
# settings.py - Production configuration
102102
POSTGRES_ANON = {
103103
'ENABLED': True,
104-
'AUTO_APPLY_RULES': False, # Never auto-apply in production
105104
'VALIDATE_FUNCTIONS': True, # Always validate functions
106105
'ALLOW_CUSTOM_FUNCTIONS': False, # Restrict to anon namespace
107106
'ENABLE_LOGGING': True, # Full audit trail
@@ -216,11 +215,10 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = True
216215
``` bash
217216
# Development
218217
export POSTGRES_ANON_ALLOW_CUSTOM_FUNCTIONS=true
219-
export POSTGRES_ANON_AUTO_APPLY_RULES=true
220218

221219
# Production
222220
export POSTGRES_ANON_ALLOW_CUSTOM_FUNCTIONS=false
223-
export POSTGRES_ANON_AUTO_APPLY_RULES=false
221+
export POSTGRES_ANON_VALIDATE_FUNCTIONS=true
224222
```
225223

226224
**2. Access Control:**

django_postgres_anon/config.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ def get_setting(key: str, default=None):
1616
"MASKED_GROUPS": ["view_masked_data"],
1717
"ANONYMIZED_DATA_ROLE": "masked_reader",
1818
"ENABLED": False,
19-
"AUTO_APPLY_RULES": False,
2019
"VALIDATE_FUNCTIONS": True,
2120
"ALLOW_CUSTOM_FUNCTIONS": False,
2221
"ENABLE_LOGGING": True,
@@ -28,7 +27,6 @@ def get_setting(key: str, default=None):
2827
"MASKED_GROUPS": "POSTGRES_ANON_MASKED_GROUPS",
2928
"ANONYMIZED_DATA_ROLE": "POSTGRES_ANON_ANONYMIZED_DATA_ROLE",
3029
"ENABLED": "POSTGRES_ANON_ENABLED",
31-
"AUTO_APPLY_RULES": "POSTGRES_ANON_AUTO_APPLY_RULES",
3230
"VALIDATE_FUNCTIONS": "POSTGRES_ANON_VALIDATE_FUNCTIONS",
3331
"ALLOW_CUSTOM_FUNCTIONS": "POSTGRES_ANON_ALLOW_CUSTOM_FUNCTIONS",
3432
"ENABLE_LOGGING": "POSTGRES_ANON_ENABLE_LOGGING",
@@ -47,7 +45,7 @@ def get_anon_setting(key: str):
4745
if env_var and env_var in os.environ:
4846
env_value = os.environ[env_var]
4947
# Handle boolean conversion for known boolean settings
50-
if key in ["ENABLED", "AUTO_APPLY_RULES", "VALIDATE_FUNCTIONS", "ALLOW_CUSTOM_FUNCTIONS", "ENABLE_LOGGING"]:
48+
if key in ["ENABLED", "VALIDATE_FUNCTIONS", "ALLOW_CUSTOM_FUNCTIONS", "ENABLE_LOGGING"]:
5149
return _parse_env_bool(env_value)
5250
# Handle comma-separated groups
5351
if key == "MASKED_GROUPS":

django_postgres_anon/management/commands/anon_load_yaml.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import yaml
66
from django.core.management.base import BaseCommand, CommandError
77

8+
from django_postgres_anon.config import get_anon_setting
89
from django_postgres_anon.models import MaskingPreset, MaskingRule
910
from django_postgres_anon.utils import create_operation_log, validate_function_syntax
1011

@@ -154,8 +155,9 @@ def _validate_yaml_structure(self, rules_data, options):
154155
)
155156
continue
156157

157-
# Validate function syntax if enabled
158-
if options["validate"]:
158+
# Validate function syntax if enabled (command option or global setting)
159+
should_validate = options["validate"] or get_anon_setting("VALIDATE_FUNCTIONS")
160+
if should_validate:
159161
if not validate_function_syntax(function_expr):
160162
errors.append(f"Rule {i + 1}: Invalid function syntax: {function_expr}")
161163
continue

django_postgres_anon/management/commands/anon_validate.py

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

33
from django.core.management.base import BaseCommand, CommandError
44

5+
from django_postgres_anon.config import get_anon_setting
56
from django_postgres_anon.models import MaskingLog, MaskingRule
67
from django_postgres_anon.utils import (
78
check_table_exists,
@@ -116,13 +117,16 @@ def _validate_rule(self, rule, options, fixes_applied):
116117
else:
117118
self.stdout.write(" ✅ Table and column exist")
118119

119-
# Validate function syntax
120-
if not validate_function_syntax(rule.function_expr):
121-
error = f"Invalid function syntax: '{rule.function_expr}'"
122-
errors.append(error)
123-
self.stdout.write(f" ❌ {error}")
120+
# Validate function syntax if enabled
121+
if get_anon_setting("VALIDATE_FUNCTIONS"):
122+
if not validate_function_syntax(rule.function_expr):
123+
error = f"Invalid function syntax: '{rule.function_expr}'"
124+
errors.append(error)
125+
self.stdout.write(f" ❌ {error}")
126+
else:
127+
self.stdout.write(" ✅ Function syntax valid")
124128
else:
125-
self.stdout.write(" Function syntax valid")
129+
self.stdout.write(" ⚠️ Function validation disabled (VALIDATE_FUNCTIONS=False)")
126130

127131
# Check for potential issues
128132
try:

django_postgres_anon/utils.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django.conf import settings
55
from django.db import DatabaseError, OperationalError, connection
66

7+
from django_postgres_anon.config import get_anon_setting
78
from django_postgres_anon.constants import DEFAULT_POSTGRES_PORT
89

910
logger = logging.getLogger(__name__)
@@ -53,8 +54,9 @@ def validate_function_syntax(function_expr: str) -> bool:
5354

5455
function_expr = function_expr.strip()
5556

56-
# Must start with anon. namespace
57-
if not function_expr.startswith("anon."):
57+
# Must start with anon. namespace (unless ALLOW_CUSTOM_FUNCTIONS is enabled)
58+
allow_custom = get_anon_setting("ALLOW_CUSTOM_FUNCTIONS")
59+
if not allow_custom and not function_expr.startswith("anon."):
5860
return False
5961

6062
# Must have parentheses
@@ -344,6 +346,10 @@ def create_operation_log(operation, user=None, **kwargs):
344346
"""Standardized logging for all operations"""
345347
from django_postgres_anon.models import MaskingLog
346348

349+
# Check if logging is enabled
350+
if not get_anon_setting("ENABLE_LOGGING"):
351+
return None
352+
347353
# Extract common fields
348354
details = kwargs.pop("details", {})
349355
success = kwargs.pop("success", True)

docs/changelog.rst

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1 @@
1-
Changelog
2-
=========
3-
4-
All notable changes to this project will be documented in this file.
5-
6-
The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_,
7-
and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
8-
9-
0.1.0b1 - 2025-01-XX
10-
--------------------
11-
12-
⚠️ **Beta Release** - Feature complete, ready for testing. API may still change before 1.0.
13-
14-
**Added**
15-
16-
* Multiple user groups support via ``MASKED_GROUPS`` configuration
17-
* Environment variable configuration following 12-factor principles
18-
* Comprehensive documentation with examples and deployment guides
19-
20-
**Changed**
21-
22-
* Improved documentation structure and clarity
23-
* Refined compliance messaging - positions as compliance support tool
24-
25-
**Removed**
26-
27-
* ``database_role()`` context manager - unsafe arbitrary role switching
28-
* ``@database_role_required()`` decorator - potential security risk
29-
* Direct role manipulation utilities - use ``anonymized_data()`` instead
30-
31-
0.1.0-alpha.1 - 2025-09-20
32-
--------------------------
33-
34-
⚠️ **Alpha Release** - Initial preview release.
35-
36-
**Core Features**
37-
38-
* Django models: ``MaskingRule``, ``MaskingPreset``, ``MaskedRole``, ``MaskingLog``
39-
* Management commands: ``anon_init``, ``anon_apply``, ``anon_status``, ``anon_dump``, ``anon_validate``, ``anon_load_yaml``, ``anon_drop``, ``anon_fix_permissions``
40-
* Middleware (``AnonRoleMiddleware``) for automatic role switching based on user groups
41-
* Context managers (``anonymized_data``) for manual control
42-
* Decorators (``@use_anonymized_data``) for view-level anonymization
43-
* Class-based view mixins (``AnonymizedDataMixin``)
44-
* Django admin integration with bulk actions
45-
46-
**Pre-built Presets**
47-
48-
* Django Auth, E-commerce, Healthcare, Finance, Social Media, Education
49-
50-
**Security**
51-
52-
* SQL injection prevention with function validation
53-
* Role-based access control
54-
* Audit logging
55-
* Parameterized queries
56-
57-
**Requirements**
58-
59-
* Python 3.8+
60-
* Django 3.2+
61-
* PostgreSQL 12+ with Anonymizer extension
1+
.. include:: ../CHANGELOG.rst

0 commit comments

Comments
 (0)