aiwaf 0.1.8.8__py3-none-any.whl → 0.1.9.0__py3-none-any.whl
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.
- aiwaf/__init__.py +18 -0
- aiwaf/management/commands/aiwaf_diagnose.py +127 -0
- aiwaf/storage.py +74 -33
- {aiwaf-0.1.8.8.dist-info → aiwaf-0.1.9.0.dist-info}/METADATA +64 -1
- {aiwaf-0.1.8.8.dist-info → aiwaf-0.1.9.0.dist-info}/RECORD +8 -7
- {aiwaf-0.1.8.8.dist-info → aiwaf-0.1.9.0.dist-info}/WHEEL +0 -0
- {aiwaf-0.1.8.8.dist-info → aiwaf-0.1.9.0.dist-info}/licenses/LICENSE +0 -0
- {aiwaf-0.1.8.8.dist-info → aiwaf-0.1.9.0.dist-info}/top_level.txt +0 -0
aiwaf/__init__.py
CHANGED
|
@@ -1 +1,19 @@
|
|
|
1
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")
|
aiwaf/storage.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
aiwaf/__init__.py,sha256=
|
|
1
|
+
aiwaf/__init__.py,sha256=XzdZPG3k3A6cA_FfVC397hcb_di2dW2LV6iULGLbZ5w,653
|
|
2
2
|
aiwaf/apps.py,sha256=nCez-Ptlv2kaEk5HenA8b1pATz1VfhrHP1344gwcY1A,142
|
|
3
3
|
aiwaf/blacklist_manager.py,sha256=92ltIrFfv8WOC4CXwvNVZYfivkRZHGNg3E2QAbHQipQ,550
|
|
4
4
|
aiwaf/decorators.py,sha256=IUKOdM_gdroffImRZep1g1wT6gNqD10zGwcp28hsJCs,825
|
|
5
5
|
aiwaf/middleware.py,sha256=1JPrc0npI_a5bnB-thN0ME1ehfTbWBl1j9wTndZwRdQ,9505
|
|
6
6
|
aiwaf/middleware_logger.py,sha256=uTYTvIc4Mv1pjY50aXaqQ5cWAO9qqquijAyVMs1KWlM,6517
|
|
7
7
|
aiwaf/models.py,sha256=XaG1pd_oZu3y-fw66u4wblGlWcUY9gvsTNKGD0kQk7Y,1672
|
|
8
|
-
aiwaf/storage.py,sha256=
|
|
8
|
+
aiwaf/storage.py,sha256=oI9ZuTCrLwLSOE3I3_tDTFs6jiile7Vr4e7jacf2B6Y,13218
|
|
9
9
|
aiwaf/trainer.py,sha256=bgVoBewnNVMJdgxcNchfhsPOnFXxStoBOqNhFYnpsqs,9244
|
|
10
10
|
aiwaf/utils.py,sha256=BJk5vJCYdGPl_4QQiknjhCbkzv5HZCXgFcBJDMJpHok,3390
|
|
11
11
|
aiwaf/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
aiwaf/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
aiwaf/management/commands/add_ipexemption.py,sha256=srgdVPDJtF7G9GGIqaZ7L3qTuNheoS_uwlhlRO4W2bc,945
|
|
14
|
+
aiwaf/management/commands/aiwaf_diagnose.py,sha256=W2OQbPJ2xXTD4OTJw2VnqJTo4QR3N9acPst3SKXy0E0,5705
|
|
14
15
|
aiwaf/management/commands/aiwaf_logging.py,sha256=FCIqULn2tii2vD9VxL7vk3PV4k4vr7kaA00KyaCExYY,7692
|
|
15
16
|
aiwaf/management/commands/aiwaf_reset.py,sha256=0FIBqpZS8xgFFvAKJ-0zAC_-QNQwRkOHpXb8N-OdFr8,3740
|
|
16
17
|
aiwaf/management/commands/detect_and_train.py,sha256=-o-LZ7QZ5GeJPCekryox1DGXKMmFEkwwrcDsiM166K0,269
|
|
17
18
|
aiwaf/resources/model.pkl,sha256=5t6h9BX8yoh2xct85MXOO60jdlWyg1APskUOW0jZE1Y,1288265
|
|
18
19
|
aiwaf/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
20
|
aiwaf/templatetags/aiwaf_tags.py,sha256=XXfb7Tl4DjU3Sc40GbqdaqOEtKTUKELBEk58u83wBNw,357
|
|
20
|
-
aiwaf-0.1.
|
|
21
|
-
aiwaf-0.1.
|
|
22
|
-
aiwaf-0.1.
|
|
23
|
-
aiwaf-0.1.
|
|
24
|
-
aiwaf-0.1.
|
|
21
|
+
aiwaf-0.1.9.0.dist-info/licenses/LICENSE,sha256=Ir8PX4dxgAcdB0wqNPIkw84fzIIRKE75NoUil9RX0QU,1069
|
|
22
|
+
aiwaf-0.1.9.0.dist-info/METADATA,sha256=xZRQCE6zKCkNtE54rrWaxBllGdslHApII1CCC1JQE0I,12903
|
|
23
|
+
aiwaf-0.1.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
aiwaf-0.1.9.0.dist-info/top_level.txt,sha256=kU6EyjobT6UPCxuWpI_BvcHDG0I2tMgKaPlWzVxe2xI,6
|
|
25
|
+
aiwaf-0.1.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|