aiwaf 0.1.9.1.7__tar.gz → 0.1.9.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiwaf might be problematic. Click here for more details.

Files changed (41) hide show
  1. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/PKG-INFO +1 -1
  2. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/__init__.py +1 -1
  3. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/aiwaf_reset.py +58 -17
  4. aiwaf-0.1.9.1.8/aiwaf/management/commands/clear_blacklist.py +66 -0
  5. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/storage.py +39 -0
  6. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf.egg-info/PKG-INFO +1 -1
  7. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf.egg-info/SOURCES.txt +1 -0
  8. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/pyproject.toml +1 -1
  9. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/setup.py +1 -1
  10. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/LICENSE +0 -0
  11. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/README.md +0 -0
  12. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/apps.py +0 -0
  13. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/blacklist_manager.py +0 -0
  14. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/decorators.py +0 -0
  15. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/__init__.py +0 -0
  16. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/__init__.py +0 -0
  17. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/add_exemption.py +0 -0
  18. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/add_ipexemption.py +0 -0
  19. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/aiwaf_diagnose.py +0 -0
  20. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/aiwaf_logging.py +0 -0
  21. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/check_dependencies.py +0 -0
  22. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/clear_cache.py +0 -0
  23. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/debug_csv.py +0 -0
  24. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/detect_and_train.py +0 -0
  25. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/diagnose_blocking.py +0 -0
  26. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/regenerate_model.py +0 -0
  27. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/setup_models.py +0 -0
  28. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/test_exemption.py +0 -0
  29. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/management/commands/test_exemption_fix.py +0 -0
  30. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/middleware.py +0 -0
  31. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/middleware_logger.py +0 -0
  32. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/models.py +0 -0
  33. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/resources/model.pkl +0 -0
  34. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/templatetags/__init__.py +0 -0
  35. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/templatetags/aiwaf_tags.py +0 -0
  36. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/trainer.py +0 -0
  37. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf/utils.py +0 -0
  38. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf.egg-info/dependency_links.txt +0 -0
  39. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf.egg-info/requires.txt +0 -0
  40. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/aiwaf.egg-info/top_level.txt +0 -0
  41. {aiwaf-0.1.9.1.7 → aiwaf-0.1.9.1.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.9.1.7
3
+ Version: 0.1.9.1.8
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -1,6 +1,6 @@
1
1
  default_app_config = "aiwaf.apps.AiwafConfig"
2
2
 
3
- __version__ = "0.1.9.1.7"
3
+ __version__ = "0.1.9.1.8"
4
4
 
5
5
  # Note: Middleware classes are available from aiwaf.middleware
6
6
  # Import them only when needed to avoid circular imports during Django app loading
@@ -1,5 +1,6 @@
1
1
  from django.core.management.base import BaseCommand
2
2
  from aiwaf.storage import get_blacklist_store, get_exemption_store
3
+ import sys
3
4
 
4
5
  class Command(BaseCommand):
5
6
  help = 'Reset AI-WAF by clearing all blacklist and exemption (whitelist) entries'
@@ -26,12 +27,29 @@ class Command(BaseCommand):
26
27
  exemptions_only = options['exemptions_only']
27
28
  confirm = options['confirm']
28
29
 
29
- blacklist_store = get_blacklist_store()
30
- exemption_store = get_exemption_store()
30
+ try:
31
+ blacklist_store = get_blacklist_store()
32
+ exemption_store = get_exemption_store()
33
+ except Exception as e:
34
+ self.stdout.write(self.style.ERROR(f'Error initializing stores: {e}'))
35
+ return
31
36
 
32
- # Count current entries
33
- blacklist_count = len(blacklist_store.get_all())
34
- exemption_count = len(exemption_store.get_all())
37
+ # Count current entries safely
38
+ try:
39
+ blacklist_entries = blacklist_store.get_all()
40
+ blacklist_count = len(blacklist_entries)
41
+ except Exception as e:
42
+ self.stdout.write(self.style.WARNING(f'Warning: Could not count blacklist entries: {e}'))
43
+ blacklist_count = 0
44
+ blacklist_entries = []
45
+
46
+ try:
47
+ exemption_entries = exemption_store.get_all()
48
+ exemption_count = len(exemption_entries)
49
+ except Exception as e:
50
+ self.stdout.write(self.style.WARNING(f'Warning: Could not count exemption entries: {e}'))
51
+ exemption_count = 0
52
+ exemption_entries = []
35
53
 
36
54
  if blacklist_only and exemptions_only:
37
55
  self.stdout.write(self.style.ERROR('Cannot use both --blacklist-only and --exemptions-only flags'))
@@ -55,29 +73,47 @@ class Command(BaseCommand):
55
73
  self.stdout.write(f"AI-WAF Reset: {action}")
56
74
 
57
75
  if not confirm:
58
- response = input("Are you sure you want to proceed? [y/N]: ")
59
- if response.lower() not in ['y', 'yes']:
60
- self.stdout.write(self.style.WARNING('Operation cancelled'))
76
+ try:
77
+ response = input("Are you sure you want to proceed? [y/N]: ")
78
+ if response.lower() not in ['y', 'yes']:
79
+ self.stdout.write(self.style.WARNING('Operation cancelled'))
80
+ return
81
+ except (EOFError, KeyboardInterrupt):
82
+ self.stdout.write(self.style.WARNING('\nOperation cancelled'))
61
83
  return
62
84
 
63
85
  # Perform the reset
64
- deleted_counts = {'blacklist': 0, 'exemptions': 0}
86
+ deleted_counts = {'blacklist': 0, 'exemptions': 0, 'errors': []}
65
87
 
66
88
  if clear_blacklist:
67
89
  # Clear blacklist entries
68
- blacklist_entries = blacklist_store.get_all()
69
- for entry in blacklist_entries:
70
- blacklist_store.remove_ip(entry['ip_address'])
71
- deleted_counts['blacklist'] = len(blacklist_entries)
90
+ try:
91
+ for entry in blacklist_entries:
92
+ try:
93
+ blacklist_store.remove_ip(entry['ip_address'])
94
+ deleted_counts['blacklist'] += 1
95
+ except Exception as e:
96
+ deleted_counts['errors'].append(f"Error removing blacklist IP {entry.get('ip_address', 'unknown')}: {e}")
97
+ except Exception as e:
98
+ deleted_counts['errors'].append(f"Error clearing blacklist: {e}")
72
99
 
73
100
  if clear_exemptions:
74
101
  # Clear exemption entries
75
- exemption_entries = exemption_store.get_all()
76
- for entry in exemption_entries:
77
- exemption_store.remove_ip(entry['ip_address'])
78
- deleted_counts['exemptions'] = len(exemption_entries)
102
+ try:
103
+ for entry in exemption_entries:
104
+ try:
105
+ exemption_store.remove_ip(entry['ip_address'])
106
+ deleted_counts['exemptions'] += 1
107
+ except Exception as e:
108
+ deleted_counts['errors'].append(f"Error removing exemption IP {entry.get('ip_address', 'unknown')}: {e}")
109
+ except Exception as e:
110
+ deleted_counts['errors'].append(f"Error clearing exemptions: {e}")
79
111
 
80
112
  # Report results
113
+ if deleted_counts['errors']:
114
+ for error in deleted_counts['errors']:
115
+ self.stdout.write(self.style.WARNING(f"⚠️ {error}"))
116
+
81
117
  if clear_blacklist and clear_exemptions:
82
118
  self.stdout.write(
83
119
  self.style.SUCCESS(
@@ -93,3 +129,8 @@ class Command(BaseCommand):
93
129
  self.stdout.write(
94
130
  self.style.SUCCESS(f"✅ Exemptions cleared: Deleted {deleted_counts['exemptions']} entries")
95
131
  )
132
+
133
+ if deleted_counts['errors']:
134
+ self.stdout.write(
135
+ self.style.WARNING(f"⚠️ Completed with {len(deleted_counts['errors'])} errors (see above)")
136
+ )
@@ -0,0 +1,66 @@
1
+ from django.core.management.base import BaseCommand
2
+ from aiwaf.storage import get_blacklist_store
3
+
4
+ class Command(BaseCommand):
5
+ help = 'Clear all blacklist entries (fast method)'
6
+
7
+ def add_arguments(self, parser):
8
+ parser.add_argument(
9
+ '--confirm',
10
+ action='store_true',
11
+ help='Skip confirmation prompt'
12
+ )
13
+
14
+ def handle(self, *args, **options):
15
+ confirm = options['confirm']
16
+
17
+ try:
18
+ blacklist_store = get_blacklist_store()
19
+ except Exception as e:
20
+ self.stdout.write(self.style.ERROR(f'Error initializing blacklist store: {e}'))
21
+ return
22
+
23
+ # Count current entries safely
24
+ try:
25
+ blacklist_entries = blacklist_store.get_all()
26
+ blacklist_count = len(blacklist_entries)
27
+ except Exception as e:
28
+ self.stdout.write(self.style.WARNING(f'Warning: Could not count blacklist entries: {e}'))
29
+ # Try to get count using clear_all method which returns count
30
+ blacklist_count = "unknown number of"
31
+
32
+ # Show what will be cleared
33
+ self.stdout.write(f"Clear Blacklist: Will remove {blacklist_count} blacklist entries")
34
+
35
+ if not confirm:
36
+ try:
37
+ response = input("Are you sure you want to proceed? [y/N]: ")
38
+ if response.lower() not in ['y', 'yes']:
39
+ self.stdout.write(self.style.WARNING('Operation cancelled'))
40
+ return
41
+ except (EOFError, KeyboardInterrupt):
42
+ self.stdout.write(self.style.WARNING('\nOperation cancelled'))
43
+ return
44
+
45
+ # Perform the reset using clear_all for better performance
46
+ try:
47
+ if hasattr(blacklist_store, 'clear_all'):
48
+ deleted_count = blacklist_store.clear_all()
49
+ self.stdout.write(
50
+ self.style.SUCCESS(f"✅ Blacklist cleared: Deleted {deleted_count} entries")
51
+ )
52
+ else:
53
+ # Fallback to individual deletion
54
+ deleted_count = 0
55
+ for entry in blacklist_entries:
56
+ try:
57
+ blacklist_store.remove_ip(entry['ip_address'])
58
+ deleted_count += 1
59
+ except Exception as e:
60
+ self.stdout.write(self.style.WARNING(f"⚠️ Error removing IP {entry.get('ip_address', 'unknown')}: {e}"))
61
+
62
+ self.stdout.write(
63
+ self.style.SUCCESS(f"✅ Blacklist cleared: Deleted {deleted_count} entries")
64
+ )
65
+ except Exception as e:
66
+ self.stdout.write(self.style.ERROR(f'Error clearing blacklist: {e}'))
@@ -132,6 +132,31 @@ class ModelBlacklistStore:
132
132
  except Exception:
133
133
  return []
134
134
 
135
+ @staticmethod
136
+ def get_all():
137
+ """Get all blacklist entries as dictionaries"""
138
+ _import_models()
139
+ if BlacklistEntry is None:
140
+ return []
141
+ try:
142
+ return list(BlacklistEntry.objects.values('ip_address', 'reason', 'created_at'))
143
+ except Exception:
144
+ return []
145
+
146
+ @staticmethod
147
+ def clear_all():
148
+ """Clear all blacklist entries"""
149
+ _import_models()
150
+ if BlacklistEntry is None:
151
+ return 0
152
+ try:
153
+ count = BlacklistEntry.objects.count()
154
+ BlacklistEntry.objects.all().delete()
155
+ return count
156
+ except Exception as e:
157
+ print(f"Error clearing all blacklist entries: {e}")
158
+ return 0
159
+
135
160
  class ModelExemptionStore:
136
161
  @staticmethod
137
162
  def is_exempted(ip):
@@ -192,6 +217,20 @@ class ModelExemptionStore:
192
217
  except Exception:
193
218
  return []
194
219
 
220
+ @staticmethod
221
+ def clear_all():
222
+ """Clear all exemption entries"""
223
+ _import_models()
224
+ if IPExemption is None:
225
+ return 0
226
+ try:
227
+ count = IPExemption.objects.count()
228
+ IPExemption.objects.all().delete()
229
+ return count
230
+ except Exception as e:
231
+ print(f"Error clearing all exemption entries: {e}")
232
+ return 0
233
+
195
234
  class ModelKeywordStore:
196
235
  @staticmethod
197
236
  def add_keyword(keyword, count=1):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.9.1.7
3
+ Version: 0.1.9.1.8
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -25,6 +25,7 @@ aiwaf/management/commands/aiwaf_diagnose.py
25
25
  aiwaf/management/commands/aiwaf_logging.py
26
26
  aiwaf/management/commands/aiwaf_reset.py
27
27
  aiwaf/management/commands/check_dependencies.py
28
+ aiwaf/management/commands/clear_blacklist.py
28
29
  aiwaf/management/commands/clear_cache.py
29
30
  aiwaf/management/commands/debug_csv.py
30
31
  aiwaf/management/commands/detect_and_train.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aiwaf"
3
- version = "0.1.9.1.7"
3
+ version = "0.1.9.1.8"
4
4
  description = "AI-powered Web Application Firewall"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.8"
@@ -9,7 +9,7 @@ long_description = (HERE / "README.md").read_text(encoding="utf-8")
9
9
 
10
10
  setup(
11
11
  name="aiwaf",
12
- version="0.1.9.1.7",
12
+ version="0.1.9.1.8",
13
13
  description="AI‑driven, self‑learning Web Application Firewall for Django",
14
14
  long_description=long_description,
15
15
  long_description_content_type="text/markdown",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes