aiwaf 0.1.8.8__tar.gz → 0.1.9.0__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.
Files changed (32) hide show
  1. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/PKG-INFO +64 -1
  2. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/README.md +63 -0
  3. aiwaf-0.1.9.0/aiwaf/__init__.py +19 -0
  4. aiwaf-0.1.9.0/aiwaf/management/commands/aiwaf_diagnose.py +127 -0
  5. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/storage.py +74 -33
  6. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf.egg-info/PKG-INFO +64 -1
  7. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf.egg-info/SOURCES.txt +1 -0
  8. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/pyproject.toml +1 -1
  9. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/setup.py +1 -1
  10. aiwaf-0.1.8.8/aiwaf/__init__.py +0 -1
  11. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/LICENSE +0 -0
  12. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/apps.py +0 -0
  13. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/blacklist_manager.py +0 -0
  14. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/decorators.py +0 -0
  15. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/management/__init__.py +0 -0
  16. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/management/commands/__init__.py +0 -0
  17. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/management/commands/add_ipexemption.py +0 -0
  18. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/management/commands/aiwaf_logging.py +0 -0
  19. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/management/commands/aiwaf_reset.py +0 -0
  20. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/management/commands/detect_and_train.py +0 -0
  21. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/middleware.py +0 -0
  22. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/middleware_logger.py +0 -0
  23. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/models.py +0 -0
  24. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/resources/model.pkl +0 -0
  25. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/templatetags/__init__.py +0 -0
  26. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/templatetags/aiwaf_tags.py +0 -0
  27. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/trainer.py +0 -0
  28. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf/utils.py +0 -0
  29. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf.egg-info/dependency_links.txt +0 -0
  30. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf.egg-info/requires.txt +0 -0
  31. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/aiwaf.egg-info/top_level.txt +0 -0
  32. {aiwaf-0.1.8.8 → aiwaf-0.1.9.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.8.8
3
+ Version: 0.1.9.0
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -27,6 +27,18 @@ Dynamic: requires-python
27
27
 
28
28
  ---
29
29
 
30
+ ## 🚀 Quick Installation
31
+
32
+ ```bash
33
+ pip install aiwaf
34
+ ```
35
+
36
+ **⚠️ Important:** Add `'aiwaf'` to your Django `INSTALLED_APPS` to avoid setup errors.
37
+
38
+ **📋 Complete Setup Guide:** See [INSTALLATION.md](INSTALLATION.md) for detailed installation instructions and troubleshooting.
39
+
40
+ ---
41
+
30
42
  ## System Requirements
31
43
 
32
44
  No GPU needed—AI-WAF runs entirely on CPU with just Python 3.8+, Django 3.2+, a single vCPU and ~512 MB RAM for small sites; for moderate production traffic you can bump to 2–4 vCPUs and 2–4 GB RAM, offload the daily detect-and-train job to a worker, and rotate logs to keep memory use bounded.
@@ -312,6 +324,57 @@ MIDDLEWARE = [
312
324
 
313
325
  > **⚠️ Order matters!** AI-WAF protection middleware should come early. The logger middleware should come near the end to capture final response data.
314
326
 
327
+ ### **Troubleshooting Middleware Errors**
328
+
329
+ **Error: `Module "aiwaf.middleware" does not define a "UUIDTamperMiddleware" attribute/class`**
330
+
331
+ **Solutions:**
332
+ 1. **Update AI-WAF to latest version:**
333
+ ```bash
334
+ pip install --upgrade aiwaf
335
+ ```
336
+
337
+ 2. **Run diagnostic commands:**
338
+ ```bash
339
+ # Quick debug script (from AI-WAF directory)
340
+ python debug_aiwaf.py
341
+
342
+ # Django management command
343
+ python manage.py aiwaf_diagnose
344
+ ```
345
+
346
+ 3. **Check available middleware classes:**
347
+ ```python
348
+ # In Django shell: python manage.py shell
349
+ import aiwaf.middleware
350
+ print(dir(aiwaf.middleware))
351
+ ```
352
+
353
+ 4. **Verify AI-WAF is in INSTALLED_APPS:**
354
+ ```python
355
+ # In settings.py
356
+ INSTALLED_APPS = [
357
+ # ... other apps ...
358
+ 'aiwaf', # Must be included
359
+ ]
360
+ ```
361
+
362
+ 5. **Use minimal middleware setup if needed:**
363
+ ```python
364
+ MIDDLEWARE = [
365
+ # ... your existing middleware ...
366
+ "aiwaf.middleware.IPAndKeywordBlockMiddleware", # Core protection
367
+ "aiwaf.middleware.RateLimitMiddleware", # Rate limiting
368
+ "aiwaf.middleware.AIAnomalyMiddleware", # AI detection
369
+ ]
370
+ ```
371
+
372
+ **Common Issues:**
373
+ - Missing Django: `pip install Django`
374
+ - Old AI-WAF version: `pip install --upgrade aiwaf`
375
+ - Missing migrations: `python manage.py migrate`
376
+ - Import errors: Check `INSTALLED_APPS` includes `'aiwaf'`
377
+
315
378
  ---
316
379
 
317
380
  ## Running Detection & Training
@@ -6,6 +6,18 @@
6
6
 
7
7
  ---
8
8
 
9
+ ## 🚀 Quick Installation
10
+
11
+ ```bash
12
+ pip install aiwaf
13
+ ```
14
+
15
+ **⚠️ Important:** Add `'aiwaf'` to your Django `INSTALLED_APPS` to avoid setup errors.
16
+
17
+ **📋 Complete Setup Guide:** See [INSTALLATION.md](INSTALLATION.md) for detailed installation instructions and troubleshooting.
18
+
19
+ ---
20
+
9
21
  ## System Requirements
10
22
 
11
23
  No GPU needed—AI-WAF runs entirely on CPU with just Python 3.8+, Django 3.2+, a single vCPU and ~512 MB RAM for small sites; for moderate production traffic you can bump to 2–4 vCPUs and 2–4 GB RAM, offload the daily detect-and-train job to a worker, and rotate logs to keep memory use bounded.
@@ -291,6 +303,57 @@ MIDDLEWARE = [
291
303
 
292
304
  > **⚠️ Order matters!** AI-WAF protection middleware should come early. The logger middleware should come near the end to capture final response data.
293
305
 
306
+ ### **Troubleshooting Middleware Errors**
307
+
308
+ **Error: `Module "aiwaf.middleware" does not define a "UUIDTamperMiddleware" attribute/class`**
309
+
310
+ **Solutions:**
311
+ 1. **Update AI-WAF to latest version:**
312
+ ```bash
313
+ pip install --upgrade aiwaf
314
+ ```
315
+
316
+ 2. **Run diagnostic commands:**
317
+ ```bash
318
+ # Quick debug script (from AI-WAF directory)
319
+ python debug_aiwaf.py
320
+
321
+ # Django management command
322
+ python manage.py aiwaf_diagnose
323
+ ```
324
+
325
+ 3. **Check available middleware classes:**
326
+ ```python
327
+ # In Django shell: python manage.py shell
328
+ import aiwaf.middleware
329
+ print(dir(aiwaf.middleware))
330
+ ```
331
+
332
+ 4. **Verify AI-WAF is in INSTALLED_APPS:**
333
+ ```python
334
+ # In settings.py
335
+ INSTALLED_APPS = [
336
+ # ... other apps ...
337
+ 'aiwaf', # Must be included
338
+ ]
339
+ ```
340
+
341
+ 5. **Use minimal middleware setup if needed:**
342
+ ```python
343
+ MIDDLEWARE = [
344
+ # ... your existing middleware ...
345
+ "aiwaf.middleware.IPAndKeywordBlockMiddleware", # Core protection
346
+ "aiwaf.middleware.RateLimitMiddleware", # Rate limiting
347
+ "aiwaf.middleware.AIAnomalyMiddleware", # AI detection
348
+ ]
349
+ ```
350
+
351
+ **Common Issues:**
352
+ - Missing Django: `pip install Django`
353
+ - Old AI-WAF version: `pip install --upgrade aiwaf`
354
+ - Missing migrations: `python manage.py migrate`
355
+ - Import errors: Check `INSTALLED_APPS` includes `'aiwaf'`
356
+
294
357
  ---
295
358
 
296
359
  ## Running Detection & Training
@@ -0,0 +1,19 @@
1
+ default_app_config = "aiwaf.apps.AiwafConfig"
2
+
3
+ __version__ = "0.1.9.0"
4
+
5
+ # Import main middleware classes for easier access
6
+ try:
7
+ from .middleware import (
8
+ IPAndKeywordBlockMiddleware,
9
+ RateLimitMiddleware,
10
+ AIAnomalyMiddleware,
11
+ HoneypotTimingMiddleware,
12
+ UUIDTamperMiddleware
13
+ )
14
+ except ImportError as e:
15
+ # Handle import errors gracefully during package installation
16
+ import sys
17
+ if 'runserver' in sys.argv or 'migrate' in sys.argv or 'shell' in sys.argv:
18
+ print(f"Warning: Could not import middleware classes: {e}")
19
+ print("Tip: Run 'python manage.py aiwaf_diagnose' to troubleshoot")
@@ -0,0 +1,127 @@
1
+ from django.core.management.base import BaseCommand
2
+ from django.conf import settings
3
+ import sys
4
+
5
+ class Command(BaseCommand):
6
+ help = 'Diagnose AI-WAF installation and middleware setup'
7
+
8
+ def handle(self, *args, **options):
9
+ self.stdout.write(self.style.HTTP_INFO("🔍 AI-WAF Installation Diagnostics"))
10
+ self.stdout.write("")
11
+
12
+ # Check AI-WAF import
13
+ try:
14
+ import aiwaf
15
+ version = getattr(aiwaf, '__version__', 'Unknown')
16
+ self.stdout.write(self.style.SUCCESS(f"✅ AI-WAF imported successfully (version: {version})"))
17
+ except ImportError as e:
18
+ self.stdout.write(self.style.ERROR(f"❌ AI-WAF import failed: {e}"))
19
+ return
20
+
21
+ # Check if aiwaf is in INSTALLED_APPS
22
+ installed_apps = getattr(settings, 'INSTALLED_APPS', [])
23
+ if 'aiwaf' in installed_apps:
24
+ self.stdout.write(self.style.SUCCESS("✅ 'aiwaf' found in INSTALLED_APPS"))
25
+ else:
26
+ self.stdout.write(self.style.ERROR("❌ 'aiwaf' NOT found in INSTALLED_APPS"))
27
+ self.stdout.write(self.style.WARNING(" Add 'aiwaf' to your INSTALLED_APPS in settings.py"))
28
+
29
+ # Check middleware availability
30
+ self.stdout.write("")
31
+ self.stdout.write(self.style.HTTP_INFO("🧱 Middleware Availability Check:"))
32
+
33
+ middleware_classes = [
34
+ 'IPAndKeywordBlockMiddleware',
35
+ 'RateLimitMiddleware',
36
+ 'AIAnomalyMiddleware',
37
+ 'HoneypotTimingMiddleware',
38
+ 'UUIDTamperMiddleware'
39
+ ]
40
+
41
+ try:
42
+ import aiwaf.middleware as mw
43
+ available_classes = dir(mw)
44
+
45
+ for middleware_class in middleware_classes:
46
+ if middleware_class in available_classes:
47
+ self.stdout.write(self.style.SUCCESS(f" ✅ {middleware_class}"))
48
+ else:
49
+ self.stdout.write(self.style.ERROR(f" ❌ {middleware_class} (missing)"))
50
+ except ImportError as e:
51
+ self.stdout.write(self.style.ERROR(f"❌ Could not import aiwaf.middleware: {e}"))
52
+
53
+ # Check configured middleware
54
+ self.stdout.write("")
55
+ self.stdout.write(self.style.HTTP_INFO("⚙️ Configured Middleware:"))
56
+
57
+ middleware_setting = getattr(settings, 'MIDDLEWARE', [])
58
+ aiwaf_middleware = [mw for mw in middleware_setting if 'aiwaf' in mw.lower()]
59
+
60
+ if aiwaf_middleware:
61
+ for mw in aiwaf_middleware:
62
+ # Test if middleware can be imported
63
+ try:
64
+ from django.utils.module_loading import import_string
65
+ import_string(mw)
66
+ self.stdout.write(self.style.SUCCESS(f" ✅ {mw}"))
67
+ except ImportError as e:
68
+ self.stdout.write(self.style.ERROR(f" ❌ {mw} - Import Error: {e}"))
69
+ except Exception as e:
70
+ self.stdout.write(self.style.WARNING(f" ⚠️ {mw} - Warning: {e}"))
71
+ else:
72
+ self.stdout.write(self.style.WARNING(" No AI-WAF middleware found in MIDDLEWARE setting"))
73
+
74
+ # Check storage configuration
75
+ self.stdout.write("")
76
+ self.stdout.write(self.style.HTTP_INFO("💾 Storage Configuration:"))
77
+
78
+ storage_mode = getattr(settings, 'AIWAF_STORAGE_MODE', 'models')
79
+ self.stdout.write(f" Storage Mode: {storage_mode}")
80
+
81
+ if storage_mode == 'csv':
82
+ csv_dir = getattr(settings, 'AIWAF_CSV_DATA_DIR', 'aiwaf_data')
83
+ self.stdout.write(f" CSV Directory: {csv_dir}")
84
+
85
+ # Check access log
86
+ access_log = getattr(settings, 'AIWAF_ACCESS_LOG', None)
87
+ if access_log:
88
+ import os
89
+ if os.path.exists(access_log):
90
+ self.stdout.write(self.style.SUCCESS(f" ✅ Access log found: {access_log}"))
91
+ else:
92
+ self.stdout.write(self.style.WARNING(f" ⚠️ Access log not found: {access_log}"))
93
+ else:
94
+ self.stdout.write(self.style.WARNING(" ⚠️ AIWAF_ACCESS_LOG not configured"))
95
+
96
+ # Check middleware logging
97
+ middleware_logging = getattr(settings, 'AIWAF_MIDDLEWARE_LOGGING', False)
98
+ if middleware_logging:
99
+ self.stdout.write(self.style.SUCCESS(" ✅ Middleware logging enabled"))
100
+ else:
101
+ self.stdout.write(self.style.WARNING(" ⚠️ Middleware logging disabled"))
102
+
103
+ # Recommendations
104
+ self.stdout.write("")
105
+ self.stdout.write(self.style.HTTP_INFO("💡 Recommendations:"))
106
+
107
+ if 'aiwaf' not in installed_apps:
108
+ self.stdout.write(" 1. Add 'aiwaf' to INSTALLED_APPS")
109
+
110
+ if not aiwaf_middleware:
111
+ self.stdout.write(" 2. Add AI-WAF middleware to MIDDLEWARE setting")
112
+
113
+ if not access_log and not middleware_logging:
114
+ self.stdout.write(" 3. Configure AIWAF_ACCESS_LOG or enable AIWAF_MIDDLEWARE_LOGGING")
115
+
116
+ # Quick fix commands
117
+ self.stdout.write("")
118
+ self.stdout.write(self.style.HTTP_INFO("🚀 Quick Fix Commands:"))
119
+ self.stdout.write("")
120
+ self.stdout.write("# Update AI-WAF to latest version:")
121
+ self.stdout.write("pip install --upgrade aiwaf")
122
+ self.stdout.write("")
123
+ self.stdout.write("# Run migrations (if using models mode):")
124
+ self.stdout.write("python manage.py migrate")
125
+ self.stdout.write("")
126
+ self.stdout.write("# Test AI-WAF commands:")
127
+ self.stdout.write("python manage.py add_ipexemption 127.0.0.1 --reason Testing")
@@ -3,7 +3,18 @@ import numpy as np
3
3
  import pandas as pd
4
4
  from django.conf import settings
5
5
  from django.utils import timezone
6
- from .models import FeatureSample, BlacklistEntry, IPExemption, DynamicKeyword
6
+
7
+ # Only import models if aiwaf is in INSTALLED_APPS
8
+ try:
9
+ from django.apps import apps
10
+ if apps.is_installed('aiwaf'):
11
+ from .models import FeatureSample, BlacklistEntry, IPExemption, DynamicKeyword
12
+ else:
13
+ # Create dummy classes to avoid import errors
14
+ FeatureSample = BlacklistEntry = IPExemption = DynamicKeyword = None
15
+ except (ImportError, RuntimeError):
16
+ # Handle cases where Django isn't fully initialized yet
17
+ FeatureSample = BlacklistEntry = IPExemption = DynamicKeyword = None
7
18
 
8
19
  # Configuration
9
20
  STORAGE_MODE = getattr(settings, "AIWAF_STORAGE_MODE", "models") # "models" or "csv"
@@ -52,22 +63,25 @@ class CsvFeatureStore:
52
63
  class DbFeatureStore:
53
64
  @staticmethod
54
65
  def persist_rows(rows):
55
- objs = []
56
- for ip,pl,kw,rt,si,bc,t404,label in rows:
57
- objs.append(FeatureSample(
58
- ip=ip, path_len=pl, kw_hits=kw,
59
- resp_time=rt, status_idx=si,
60
- burst_count=bc, total_404=t404,
61
- label=label
62
- ))
63
- FeatureSample.objects.bulk_create(objs, ignore_conflicts=True)
66
+ if FeatureSample is not None:
67
+ objs = []
68
+ for ip,pl,kw,rt,si,bc,t404,label in rows:
69
+ objs.append(FeatureSample(
70
+ ip=ip, path_len=pl, kw_hits=kw,
71
+ resp_time=rt, status_idx=si,
72
+ burst_count=bc, total_404=t404,
73
+ label=label
74
+ ))
75
+ FeatureSample.objects.bulk_create(objs, ignore_conflicts=True)
64
76
 
65
77
  @staticmethod
66
78
  def load_matrix():
67
- qs = FeatureSample.objects.all().values_list(
68
- "path_len","kw_hits","resp_time","status_idx","burst_count","total_404"
69
- )
70
- return np.array(list(qs), dtype=float)
79
+ if FeatureSample is not None:
80
+ qs = FeatureSample.objects.all().values_list(
81
+ "path_len","kw_hits","resp_time","status_idx","burst_count","total_404"
82
+ )
83
+ return np.array(list(qs), dtype=float)
84
+ return np.empty((0,6))
71
85
 
72
86
  def get_store():
73
87
  if getattr(settings, "AIWAF_FEATURE_STORE", "csv") == "db":
@@ -266,8 +280,12 @@ def get_blacklist_store():
266
280
  if STORAGE_MODE == "csv":
267
281
  return CsvBlacklistStore
268
282
  else:
269
- # Return a wrapper for Django models
270
- return ModelBlacklistStore
283
+ # Return a wrapper for Django models (only if models are available)
284
+ if BlacklistEntry is not None:
285
+ return ModelBlacklistStore
286
+ else:
287
+ # Fallback to CSV if models aren't available
288
+ return CsvBlacklistStore
271
289
 
272
290
 
273
291
  def get_exemption_store():
@@ -275,7 +293,10 @@ def get_exemption_store():
275
293
  if STORAGE_MODE == "csv":
276
294
  return CsvExemptionStore
277
295
  else:
278
- return ModelExemptionStore
296
+ if IPExemption is not None:
297
+ return ModelExemptionStore
298
+ else:
299
+ return CsvExemptionStore
279
300
 
280
301
 
281
302
  def get_keyword_store():
@@ -283,7 +304,10 @@ def get_keyword_store():
283
304
  if STORAGE_MODE == "csv":
284
305
  return CsvKeywordStore
285
306
  else:
286
- return ModelKeywordStore
307
+ if DynamicKeyword is not None:
308
+ return ModelKeywordStore
309
+ else:
310
+ return CsvKeywordStore
287
311
 
288
312
 
289
313
  # ============= Django Model Wrappers =============
@@ -293,19 +317,25 @@ class ModelBlacklistStore:
293
317
 
294
318
  @staticmethod
295
319
  def add_ip(ip_address, reason):
296
- BlacklistEntry.objects.get_or_create(ip_address=ip_address, defaults={"reason": reason})
320
+ if BlacklistEntry is not None:
321
+ BlacklistEntry.objects.get_or_create(ip_address=ip_address, defaults={"reason": reason})
297
322
 
298
323
  @staticmethod
299
324
  def is_blocked(ip_address):
300
- return BlacklistEntry.objects.filter(ip_address=ip_address).exists()
325
+ if BlacklistEntry is not None:
326
+ return BlacklistEntry.objects.filter(ip_address=ip_address).exists()
327
+ return False
301
328
 
302
329
  @staticmethod
303
330
  def get_all():
304
- return list(BlacklistEntry.objects.values("ip_address", "reason", "created_at"))
331
+ if BlacklistEntry is not None:
332
+ return list(BlacklistEntry.objects.values("ip_address", "reason", "created_at"))
333
+ return []
305
334
 
306
335
  @staticmethod
307
336
  def remove_ip(ip_address):
308
- BlacklistEntry.objects.filter(ip_address=ip_address).delete()
337
+ if BlacklistEntry is not None:
338
+ BlacklistEntry.objects.filter(ip_address=ip_address).delete()
309
339
 
310
340
 
311
341
  class ModelExemptionStore:
@@ -313,19 +343,25 @@ class ModelExemptionStore:
313
343
 
314
344
  @staticmethod
315
345
  def add_ip(ip_address, reason=""):
316
- IPExemption.objects.get_or_create(ip_address=ip_address, defaults={"reason": reason})
346
+ if IPExemption is not None:
347
+ IPExemption.objects.get_or_create(ip_address=ip_address, defaults={"reason": reason})
317
348
 
318
349
  @staticmethod
319
350
  def is_exempted(ip_address):
320
- return IPExemption.objects.filter(ip_address=ip_address).exists()
351
+ if IPExemption is not None:
352
+ return IPExemption.objects.filter(ip_address=ip_address).exists()
353
+ return False
321
354
 
322
355
  @staticmethod
323
356
  def get_all():
324
- return list(IPExemption.objects.values("ip_address", "reason", "created_at"))
357
+ if IPExemption is not None:
358
+ return list(IPExemption.objects.values("ip_address", "reason", "created_at"))
359
+ return []
325
360
 
326
361
  @staticmethod
327
362
  def remove_ip(ip_address):
328
- IPExemption.objects.filter(ip_address=ip_address).delete()
363
+ if IPExemption is not None:
364
+ IPExemption.objects.filter(ip_address=ip_address).delete()
329
365
 
330
366
 
331
367
  class ModelKeywordStore:
@@ -333,19 +369,24 @@ class ModelKeywordStore:
333
369
 
334
370
  @staticmethod
335
371
  def add_keyword(keyword, count=1):
336
- obj, created = DynamicKeyword.objects.get_or_create(keyword=keyword, defaults={"count": count})
337
- if not created:
338
- obj.count += count
339
- obj.save()
372
+ if DynamicKeyword is not None:
373
+ obj, created = DynamicKeyword.objects.get_or_create(keyword=keyword, defaults={"count": count})
374
+ if not created:
375
+ obj.count += count
376
+ obj.save()
340
377
 
341
378
  @staticmethod
342
379
  def get_top_keywords(limit=10):
343
- return list(DynamicKeyword.objects.order_by("-count").values_list("keyword", flat=True)[:limit])
380
+ if DynamicKeyword is not None:
381
+ return list(DynamicKeyword.objects.order_by("-count").values_list("keyword", flat=True)[:limit])
382
+ return []
344
383
 
345
384
  @staticmethod
346
385
  def remove_keyword(keyword):
347
- DynamicKeyword.objects.filter(keyword=keyword).delete()
386
+ if DynamicKeyword is not None:
387
+ DynamicKeyword.objects.filter(keyword=keyword).delete()
348
388
 
349
389
  @staticmethod
350
390
  def clear_all():
351
- DynamicKeyword.objects.all().delete()
391
+ if DynamicKeyword is not None:
392
+ DynamicKeyword.objects.all().delete()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiwaf
3
- Version: 0.1.8.8
3
+ Version: 0.1.9.0
4
4
  Summary: AI-powered Web Application Firewall
5
5
  Home-page: https://github.com/aayushgauba/aiwaf
6
6
  Author: Aayush Gauba
@@ -27,6 +27,18 @@ Dynamic: requires-python
27
27
 
28
28
  ---
29
29
 
30
+ ## 🚀 Quick Installation
31
+
32
+ ```bash
33
+ pip install aiwaf
34
+ ```
35
+
36
+ **⚠️ Important:** Add `'aiwaf'` to your Django `INSTALLED_APPS` to avoid setup errors.
37
+
38
+ **📋 Complete Setup Guide:** See [INSTALLATION.md](INSTALLATION.md) for detailed installation instructions and troubleshooting.
39
+
40
+ ---
41
+
30
42
  ## System Requirements
31
43
 
32
44
  No GPU needed—AI-WAF runs entirely on CPU with just Python 3.8+, Django 3.2+, a single vCPU and ~512 MB RAM for small sites; for moderate production traffic you can bump to 2–4 vCPUs and 2–4 GB RAM, offload the daily detect-and-train job to a worker, and rotate logs to keep memory use bounded.
@@ -312,6 +324,57 @@ MIDDLEWARE = [
312
324
 
313
325
  > **⚠️ Order matters!** AI-WAF protection middleware should come early. The logger middleware should come near the end to capture final response data.
314
326
 
327
+ ### **Troubleshooting Middleware Errors**
328
+
329
+ **Error: `Module "aiwaf.middleware" does not define a "UUIDTamperMiddleware" attribute/class`**
330
+
331
+ **Solutions:**
332
+ 1. **Update AI-WAF to latest version:**
333
+ ```bash
334
+ pip install --upgrade aiwaf
335
+ ```
336
+
337
+ 2. **Run diagnostic commands:**
338
+ ```bash
339
+ # Quick debug script (from AI-WAF directory)
340
+ python debug_aiwaf.py
341
+
342
+ # Django management command
343
+ python manage.py aiwaf_diagnose
344
+ ```
345
+
346
+ 3. **Check available middleware classes:**
347
+ ```python
348
+ # In Django shell: python manage.py shell
349
+ import aiwaf.middleware
350
+ print(dir(aiwaf.middleware))
351
+ ```
352
+
353
+ 4. **Verify AI-WAF is in INSTALLED_APPS:**
354
+ ```python
355
+ # In settings.py
356
+ INSTALLED_APPS = [
357
+ # ... other apps ...
358
+ 'aiwaf', # Must be included
359
+ ]
360
+ ```
361
+
362
+ 5. **Use minimal middleware setup if needed:**
363
+ ```python
364
+ MIDDLEWARE = [
365
+ # ... your existing middleware ...
366
+ "aiwaf.middleware.IPAndKeywordBlockMiddleware", # Core protection
367
+ "aiwaf.middleware.RateLimitMiddleware", # Rate limiting
368
+ "aiwaf.middleware.AIAnomalyMiddleware", # AI detection
369
+ ]
370
+ ```
371
+
372
+ **Common Issues:**
373
+ - Missing Django: `pip install Django`
374
+ - Old AI-WAF version: `pip install --upgrade aiwaf`
375
+ - Missing migrations: `python manage.py migrate`
376
+ - Import errors: Check `INSTALLED_APPS` includes `'aiwaf'`
377
+
315
378
  ---
316
379
 
317
380
  ## Running Detection & Training
@@ -20,6 +20,7 @@ aiwaf.egg-info/top_level.txt
20
20
  aiwaf/management/__init__.py
21
21
  aiwaf/management/commands/__init__.py
22
22
  aiwaf/management/commands/add_ipexemption.py
23
+ aiwaf/management/commands/aiwaf_diagnose.py
23
24
  aiwaf/management/commands/aiwaf_logging.py
24
25
  aiwaf/management/commands/aiwaf_reset.py
25
26
  aiwaf/management/commands/detect_and_train.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aiwaf"
3
- version = "0.1.8.8"
3
+ version = "0.1.9.0"
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.8.8",
12
+ version="0.1.9.0",
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",
@@ -1 +0,0 @@
1
- default_app_config = "aiwaf.apps.AiwafConfig"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes