ulinzilogs 0.1.1__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.
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: ulinzilogs
3
+ Version: 0.1.1
4
+ Summary: Security logging middleware for FastAPI, Flask, and Django
5
+ Author-email: PashyGeek <codyypashy@gmail.com>
6
+ Project-URL: Homepage, https://github.com/PashyGeek/ulinzilogs
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.28.0
10
+ Provides-Extra: fastapi
11
+ Requires-Dist: starlette>=0.20.0; extra == "fastapi"
12
+ Provides-Extra: flask
13
+ Requires-Dist: flask>=2.0.0; extra == "flask"
14
+ Provides-Extra: django
15
+ Requires-Dist: django>=3.2; extra == "django"
16
+ Provides-Extra: all
17
+ Requires-Dist: starlette>=0.20.0; extra == "all"
18
+ Requires-Dist: flask>=2.0.0; extra == "all"
19
+ Requires-Dist: django>=3.2; extra == "all"
20
+
21
+ # Ulinzilogs πŸ›‘οΈ
22
+
23
+ > **Lightweight, non‑blocking security logging middleware for Python web apps**
24
+ > Built for developers who want **visibility without performance pain**.
25
+
26
+ ---
27
+
28
+ ## 🌍 What is Ulinzilogs?
29
+
30
+ **Ulinzilogs** is a security‑focused middleware that silently watches incoming HTTP requests in your Python web application, **redacts sensitive data**, and **ships sanitized logs** to the Ulinzi Security API for **AI‑powered threat analysis**.
31
+
32
+ Think of it as:
33
+
34
+ > πŸ” *A security camera for your API β€” always on, never in the way.*
35
+
36
+ ---
37
+
38
+ ## ✨ Key Features
39
+
40
+ * πŸš€ **Non‑Blocking by Design** β€” Uses background threads so your request/response cycle stays fast.
41
+ * πŸ”’ **Automatic Data Redaction** β€” Sensitive fields are replaced with `[REDACTED]` before leaving your server.
42
+ * 🌐 **Multi‑Framework Support** β€” Works out of the box with FastAPI, Flask, and Django.
43
+ * 🧹 **Clean & Safe Headers** β€” Excludes `Authorization` and `Cookie` headers automatically.
44
+
45
+ ---
46
+
47
+ ## πŸ“¦ Installation
48
+
49
+ Install only what your stack needs:
50
+
51
+ ```bash
52
+ # FastAPI / Starlette
53
+ pip install ulinzilogs[fastapi]
54
+
55
+ # Flask
56
+ pip install ulinzilogs[flask]
57
+
58
+ # Django
59
+ pip install ulinzilogs[django]
60
+
61
+ # All frameworks
62
+ pip install ulinzilogs[all]
63
+ ```
64
+
65
+ ---
66
+
67
+ ## πŸ”‘ Getting Your Project Key
68
+
69
+ After installing, run:
70
+
71
+ ```bash
72
+ ulinzi-init
73
+ ```
74
+
75
+ This generates a **unique Project Key** for your app and prints setup instructions.
76
+
77
+ > ⚠️ **Important:** This key is generated locally on your machine.
78
+ > To activate it, copy the key and register it at **[ulinzilogs.com](https://ulinzilogs.com)**.
79
+ > Once registered, your dashboard will start receiving logs from your app.
80
+
81
+ ---
82
+
83
+ ## βš™οΈ Setup & Usage
84
+
85
+ ### 🟒 FastAPI
86
+
87
+ ```python
88
+ from fastapi import FastAPI
89
+ from ulinzilogs import UlinziFastAPIMiddleware
90
+
91
+ app = FastAPI()
92
+
93
+ app.add_middleware(
94
+ UlinziFastAPIMiddleware,
95
+ api_key="YOUR_ULINZI_KEY"
96
+ )
97
+
98
+ @app.get("/")
99
+ async def root():
100
+ return {"message": "Protected by Ulinzi"}
101
+ ```
102
+
103
+ ---
104
+
105
+ ### πŸ”΅ Flask
106
+
107
+ ```python
108
+ from flask import Flask
109
+ from ulinzilogs import UlinziFlaskMiddleware
110
+
111
+ app = Flask(__name__)
112
+ UlinziFlaskMiddleware(app, api_key="YOUR_ULINZI_KEY")
113
+
114
+ @app.route("/")
115
+ def hello():
116
+ return "Protected by Ulinzi"
117
+ ```
118
+
119
+ ---
120
+
121
+ ### 🟣 Django
122
+
123
+ In `settings.py`:
124
+
125
+ ```python
126
+ MIDDLEWARE = [
127
+ # ... other middleware
128
+ 'ulinzilogs.UlinziDjangoMiddleware',
129
+ ]
130
+
131
+ ULINZI_API_KEY = "YOUR_ULINZI_KEY"
132
+ ULINZI_APP_NAME = "MyDjangoApp" # optional label shown in dashboard
133
+ ```
134
+
135
+ ---
136
+
137
+ ## 🧠 How Ulinzilogs Works
138
+ Client Request
139
+ β”‚
140
+ β–Ό
141
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
142
+ β”‚ Middleware β”‚
143
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
144
+ β”‚
145
+ β–Ό
146
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
147
+ β”‚ Redact Sensitive β”‚
148
+ β”‚ Fields & Headers β”‚
149
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
150
+ β”‚
151
+ β–Ό (Background Thread)
152
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
153
+ β”‚ Send to Ulinzi β”‚
154
+ β”‚ Security API β”‚
155
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
156
+ β”‚
157
+ β–Ό
158
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
159
+ β”‚ AI Threat Analysis β”‚
160
+ β”‚ (SQLi, XSS, etc.) β”‚
161
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
162
+
163
+ 1. **Intercept** β€” Captures request metadata (IP, URL, method, body).
164
+ 2. **Redact** β€” Removes secrets before transmission.
165
+ 3. **Dispatch** β€” Sends logs asynchronously in a background thread.
166
+ 4. **Analyze** β€” Central AI scans for malicious patterns.
167
+
168
+ ---
169
+
170
+ ## πŸ” Sensitive Data Protection
171
+
172
+ The following keys are **automatically redacted**:
173
+
174
+ | Field | Redacted? |
175
+ |-------|-----------|
176
+ | `password` | βœ… Yes |
177
+ | `secret` | βœ… Yes |
178
+ | `token` | βœ… Yes |
179
+ | `key` | βœ… Yes |
180
+ | `cvv` | βœ… Yes |
181
+ | `api_key` | βœ… Yes |
182
+
183
+ Example:
184
+
185
+ ```json
186
+ {
187
+ "email": "user@mail.com",
188
+ "password": "[REDACTED]"
189
+ }
190
+ ```
191
+
192
+ Your users' secrets **never leave your server in plaintext**.
193
+
194
+ ---
195
+
196
+ ## ⚑ Performance Philosophy
197
+
198
+ * No request blocking
199
+ * No database writes on your server
200
+ * No logging delays
201
+
202
+ Ulinzilogs runs **beside** your app β€” not **inside** its critical path.
203
+
204
+ ---
205
+
206
+ ## 🧩 Package Structure
207
+ ulinzilogs/
208
+ β”œβ”€β”€ init.py
209
+ β”œβ”€β”€ middleware.py
210
+ β”œβ”€β”€ utils.py
211
+ β”œβ”€β”€ cli.py
212
+ β”œβ”€β”€ pyproject.toml
213
+ └── README.md
214
+
215
+ ---
216
+
217
+ ## πŸ“œ License
218
+
219
+ Copyright (c) 2026 PashyGeek. Licensed under the MIT License β€” see the LICENSE file for details.
@@ -0,0 +1,199 @@
1
+ # Ulinzilogs πŸ›‘οΈ
2
+
3
+ > **Lightweight, non‑blocking security logging middleware for Python web apps**
4
+ > Built for developers who want **visibility without performance pain**.
5
+
6
+ ---
7
+
8
+ ## 🌍 What is Ulinzilogs?
9
+
10
+ **Ulinzilogs** is a security‑focused middleware that silently watches incoming HTTP requests in your Python web application, **redacts sensitive data**, and **ships sanitized logs** to the Ulinzi Security API for **AI‑powered threat analysis**.
11
+
12
+ Think of it as:
13
+
14
+ > πŸ” *A security camera for your API β€” always on, never in the way.*
15
+
16
+ ---
17
+
18
+ ## ✨ Key Features
19
+
20
+ * πŸš€ **Non‑Blocking by Design** β€” Uses background threads so your request/response cycle stays fast.
21
+ * πŸ”’ **Automatic Data Redaction** β€” Sensitive fields are replaced with `[REDACTED]` before leaving your server.
22
+ * 🌐 **Multi‑Framework Support** β€” Works out of the box with FastAPI, Flask, and Django.
23
+ * 🧹 **Clean & Safe Headers** β€” Excludes `Authorization` and `Cookie` headers automatically.
24
+
25
+ ---
26
+
27
+ ## πŸ“¦ Installation
28
+
29
+ Install only what your stack needs:
30
+
31
+ ```bash
32
+ # FastAPI / Starlette
33
+ pip install ulinzilogs[fastapi]
34
+
35
+ # Flask
36
+ pip install ulinzilogs[flask]
37
+
38
+ # Django
39
+ pip install ulinzilogs[django]
40
+
41
+ # All frameworks
42
+ pip install ulinzilogs[all]
43
+ ```
44
+
45
+ ---
46
+
47
+ ## πŸ”‘ Getting Your Project Key
48
+
49
+ After installing, run:
50
+
51
+ ```bash
52
+ ulinzi-init
53
+ ```
54
+
55
+ This generates a **unique Project Key** for your app and prints setup instructions.
56
+
57
+ > ⚠️ **Important:** This key is generated locally on your machine.
58
+ > To activate it, copy the key and register it at **[ulinzilogs.com](https://ulinzilogs.com)**.
59
+ > Once registered, your dashboard will start receiving logs from your app.
60
+
61
+ ---
62
+
63
+ ## βš™οΈ Setup & Usage
64
+
65
+ ### 🟒 FastAPI
66
+
67
+ ```python
68
+ from fastapi import FastAPI
69
+ from ulinzilogs import UlinziFastAPIMiddleware
70
+
71
+ app = FastAPI()
72
+
73
+ app.add_middleware(
74
+ UlinziFastAPIMiddleware,
75
+ api_key="YOUR_ULINZI_KEY"
76
+ )
77
+
78
+ @app.get("/")
79
+ async def root():
80
+ return {"message": "Protected by Ulinzi"}
81
+ ```
82
+
83
+ ---
84
+
85
+ ### πŸ”΅ Flask
86
+
87
+ ```python
88
+ from flask import Flask
89
+ from ulinzilogs import UlinziFlaskMiddleware
90
+
91
+ app = Flask(__name__)
92
+ UlinziFlaskMiddleware(app, api_key="YOUR_ULINZI_KEY")
93
+
94
+ @app.route("/")
95
+ def hello():
96
+ return "Protected by Ulinzi"
97
+ ```
98
+
99
+ ---
100
+
101
+ ### 🟣 Django
102
+
103
+ In `settings.py`:
104
+
105
+ ```python
106
+ MIDDLEWARE = [
107
+ # ... other middleware
108
+ 'ulinzilogs.UlinziDjangoMiddleware',
109
+ ]
110
+
111
+ ULINZI_API_KEY = "YOUR_ULINZI_KEY"
112
+ ULINZI_APP_NAME = "MyDjangoApp" # optional label shown in dashboard
113
+ ```
114
+
115
+ ---
116
+
117
+ ## 🧠 How Ulinzilogs Works
118
+ Client Request
119
+ β”‚
120
+ β–Ό
121
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
122
+ β”‚ Middleware β”‚
123
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
124
+ β”‚
125
+ β–Ό
126
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
127
+ β”‚ Redact Sensitive β”‚
128
+ β”‚ Fields & Headers β”‚
129
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
130
+ β”‚
131
+ β–Ό (Background Thread)
132
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
133
+ β”‚ Send to Ulinzi β”‚
134
+ β”‚ Security API β”‚
135
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
136
+ β”‚
137
+ β–Ό
138
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
139
+ β”‚ AI Threat Analysis β”‚
140
+ β”‚ (SQLi, XSS, etc.) β”‚
141
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
142
+
143
+ 1. **Intercept** β€” Captures request metadata (IP, URL, method, body).
144
+ 2. **Redact** β€” Removes secrets before transmission.
145
+ 3. **Dispatch** β€” Sends logs asynchronously in a background thread.
146
+ 4. **Analyze** β€” Central AI scans for malicious patterns.
147
+
148
+ ---
149
+
150
+ ## πŸ” Sensitive Data Protection
151
+
152
+ The following keys are **automatically redacted**:
153
+
154
+ | Field | Redacted? |
155
+ |-------|-----------|
156
+ | `password` | βœ… Yes |
157
+ | `secret` | βœ… Yes |
158
+ | `token` | βœ… Yes |
159
+ | `key` | βœ… Yes |
160
+ | `cvv` | βœ… Yes |
161
+ | `api_key` | βœ… Yes |
162
+
163
+ Example:
164
+
165
+ ```json
166
+ {
167
+ "email": "user@mail.com",
168
+ "password": "[REDACTED]"
169
+ }
170
+ ```
171
+
172
+ Your users' secrets **never leave your server in plaintext**.
173
+
174
+ ---
175
+
176
+ ## ⚑ Performance Philosophy
177
+
178
+ * No request blocking
179
+ * No database writes on your server
180
+ * No logging delays
181
+
182
+ Ulinzilogs runs **beside** your app β€” not **inside** its critical path.
183
+
184
+ ---
185
+
186
+ ## 🧩 Package Structure
187
+ ulinzilogs/
188
+ β”œβ”€β”€ init.py
189
+ β”œβ”€β”€ middleware.py
190
+ β”œβ”€β”€ utils.py
191
+ β”œβ”€β”€ cli.py
192
+ β”œβ”€β”€ pyproject.toml
193
+ └── README.md
194
+
195
+ ---
196
+
197
+ ## πŸ“œ License
198
+
199
+ Copyright (c) 2026 PashyGeek. Licensed under the MIT License β€” see the LICENSE file for details.
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ulinzilogs"
7
+ version = "0.1.1"
8
+ authors = [
9
+ { name="PashyGeek", email="codyypashy@gmail.com" },
10
+ ]
11
+ description = "Security logging middleware for FastAPI, Flask, and Django"
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+ dependencies = [
15
+ "requests>=2.28.0",
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ fastapi = ["starlette>=0.20.0"]
20
+ flask = ["flask>=2.0.0"]
21
+ django = ["django>=3.2"]
22
+ all = ["starlette>=0.20.0", "flask>=2.0.0", "django>=3.2"]
23
+
24
+ [project.scripts]
25
+ ulinzi-init = "ulinzilogs.cli:main"
26
+
27
+ [project.urls]
28
+ "Homepage" = "https://github.com/PashyGeek/ulinzilogs"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ from .middleware import UlinziFastAPIMiddleware, UlinziFlaskMiddleware, UlinziDjangoMiddleware
2
+
3
+ # Alias for general use
4
+ UlinziMiddleware = UlinziFastAPIMiddleware
@@ -0,0 +1,39 @@
1
+ import uuid
2
+ import sys
3
+
4
+ def main():
5
+ """
6
+ Generates a unique project key and prints setup instructions.
7
+ """
8
+ project_key = str(uuid.uuid4())
9
+
10
+ print("\n" + "="*60)
11
+ print(" πŸ›‘οΈ ULINZI LOGS PACKAGED INSTALLED SUCCESSFULLY! πŸ›‘οΈ")
12
+ print("="*60)
13
+ print(f"\nπŸ”‘ YOUR UNIQUE PROJECT KEY: {project_key}\n")
14
+ print("PLEASE SAVE THIS KEY! You will need it to configure your app.")
15
+ print("-" * 60)
16
+
17
+ print("\nπŸ“‹ NEXT STEPS:\n")
18
+
19
+ print("1️⃣ Django Configuration (settings.py):")
20
+ print(f" ULINZI_API_KEY = '{project_key}'")
21
+ print(" MIDDLEWARE = [")
22
+ print(" ...,")
23
+ print(" 'ulinzilogs.middleware.UlinziDjangoMiddleware',")
24
+ print(" ]")
25
+
26
+ print("\n2️⃣ FastAPI Configuration:")
27
+ print(" from ulinzilogs.middleware import UlinziFastAPIMiddleware")
28
+ print(" app = FastAPI()")
29
+ print(f" app.add_middleware(UlinziFastAPIMiddleware, api_key='{project_key}')")
30
+
31
+ print("\n3️⃣ Flask Configuration:")
32
+ print(" from ulinzilogs.middleware import UlinziFlaskMiddleware")
33
+ print(" app = Flask(__name__)")
34
+ print(f" UlinziFlaskMiddleware(app, api_key='{project_key}')")
35
+
36
+ print("\n" + "="*60 + "\n")
37
+
38
+ if __name__ == "__main__":
39
+ main()
@@ -0,0 +1,136 @@
1
+ import json
2
+ import threading
3
+ import requests
4
+ from .utils import redact_sensitive_data
5
+
6
+ # --- The "Universal" Core ---
7
+ class UlinziLogger:
8
+ def __init__(self, api_key: str, app_name: str = "Unknown App", ingest_url: str = None):
9
+ self.api_key = api_key
10
+ self.app_name = app_name
11
+ self.ingest_url = ingest_url or "https://api.ulinzilogs.com/v1/ingest"
12
+
13
+ def send_logs(self, payload: dict):
14
+ if not self.api_key:
15
+ return
16
+ payload["app_name"] = self.app_name
17
+ try:
18
+ headers = {
19
+ "X-API-KEY": self.api_key,
20
+ "Content-Type": "application/json"
21
+ }
22
+ requests.post(self.ingest_url, json=payload, headers=headers, timeout=5)
23
+ except:
24
+ pass
25
+
26
+ # --- 1. FastAPI / Starlette Flavor ---
27
+ try:
28
+ from starlette.middleware.base import BaseHTTPMiddleware
29
+ HAS_STARLETTE = True
30
+ except ImportError:
31
+ BaseHTTPMiddleware = object
32
+ HAS_STARLETTE = False
33
+
34
+ class UlinziFastAPIMiddleware(BaseHTTPMiddleware):
35
+ def __init__(self, app, api_key: str, app_name: str = None):
36
+ if not HAS_STARLETTE:
37
+ raise ImportError(
38
+ "UlinziFastAPIMiddleware requires Starlette. "
39
+ "Install it with: pip install ulinzilogs[fastapi]"
40
+ )
41
+ super().__init__(app)
42
+ self.logger = UlinziLogger(api_key, app_name or "FastAPI-App")
43
+
44
+ async def dispatch(self, request, call_next):
45
+ log_data = {
46
+ "ip": request.client.host,
47
+ "method": request.method,
48
+ "url": str(request.url),
49
+ "host": request.headers.get("host"),
50
+ "user_agent": request.headers.get("user-agent"),
51
+ "headers": {k: v for k, v in request.headers.items() if k.lower() not in ("authorization", "cookie")}
52
+ }
53
+ try:
54
+ body = await request.body()
55
+ if body:
56
+ request._body = body
57
+ log_data["body"] = redact_sensitive_data(json.loads(body))
58
+ except:
59
+ log_data["body"] = None
60
+
61
+ response = await call_next(request)
62
+ log_data["status_code"] = response.status_code
63
+ threading.Thread(target=self.logger.send_logs, args=(log_data,)).start()
64
+ return response
65
+
66
+ # --- 2. Flask Flavor ---
67
+ try:
68
+ from flask import request as flask_request
69
+ HAS_FLASK = True
70
+ except ImportError:
71
+ HAS_FLASK = False
72
+
73
+ class UlinziFlaskMiddleware:
74
+ def __init__(self, app, api_key: str, app_name: str = None):
75
+ if not HAS_FLASK:
76
+ raise ImportError(
77
+ "UlinziFlaskMiddleware requires Flask. "
78
+ "Install it with: pip install ulinzilogs[flask]"
79
+ )
80
+ self.app = app
81
+ self.logger = UlinziLogger(api_key, app_name or "Flask-App")
82
+
83
+ @app.after_request
84
+ def after_request(response):
85
+ log_data = {
86
+ "ip": flask_request.remote_addr,
87
+ "method": flask_request.method,
88
+ "url": flask_request.url,
89
+ "host": flask_request.host,
90
+ "user_agent": flask_request.headers.get("User-Agent"),
91
+ "headers": {k: v for k, v in flask_request.headers.items() if k.lower() not in ("authorization", "cookie")},
92
+ "status_code": response.status_code
93
+ }
94
+ if flask_request.is_json:
95
+ try:
96
+ log_data["body"] = redact_sensitive_data(flask_request.get_json())
97
+ except:
98
+ log_data["body"] = None
99
+ threading.Thread(target=self.logger.send_logs, args=(log_data,)).start()
100
+ return response
101
+
102
+ # --- 3. Django Flavor ---
103
+ class UlinziDjangoMiddleware:
104
+ def __init__(self, get_response):
105
+ self.get_response = get_response
106
+ try:
107
+ from django.conf import settings
108
+ self.api_key = getattr(settings, "ULINZI_API_KEY", None)
109
+ self.app_name = getattr(settings, "ULINZI_APP_NAME", "Django-App")
110
+ self.ingest_url = getattr(settings, "ULINZI_INGEST_URL", None) # FOR TESTING PURPOSES ONLY
111
+ except ImportError:
112
+ raise ImportError(
113
+ "UlinziDjangoMiddleware requires Django. "
114
+ "Install it with: pip install ulinzilogs[django]"
115
+ )
116
+ self.logger = UlinziLogger(self.api_key, self.app_name, self.ingest_url)
117
+
118
+ def __call__(self, request):
119
+ log_data = {
120
+ "ip": request.META.get('REMOTE_ADDR'),
121
+ "method": request.method,
122
+ "url": request.build_absolute_uri(),
123
+ "host": request.get_host(),
124
+ "user_agent": request.META.get('HTTP_USER_AGENT'),
125
+ "headers": {k: v for k, v in request.headers.items() if k.lower() not in ("authorization", "cookie")}
126
+ }
127
+ if request.body:
128
+ try:
129
+ log_data["body"] = redact_sensitive_data(json.loads(request.body))
130
+ except:
131
+ log_data["body"] = None
132
+
133
+ response = self.get_response(request)
134
+ log_data["status_code"] = response.status_code
135
+ threading.Thread(target=self.logger.send_logs, args=(log_data,)).start()
136
+ return response
@@ -0,0 +1,19 @@
1
+ import json
2
+ from typing import Any
3
+
4
+ def redact_sensitive_data(data: Any) -> Any:
5
+ """
6
+ Recursively scans dictionaries/lists and replaces sensitive
7
+ values with [REDACTED].
8
+ """
9
+ sensitive_keys = {'password', 'secret', 'token', 'key', 'cvv', 'api_key'}
10
+
11
+ if isinstance(data, dict):
12
+ return {
13
+ k: ("[REDACTED]" if k.lower() in sensitive_keys else redact_sensitive_data(v))
14
+ for k, v in data.items()
15
+ }
16
+ elif isinstance(data, list):
17
+ return [redact_sensitive_data(item) for item in data]
18
+
19
+ return data
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: ulinzilogs
3
+ Version: 0.1.1
4
+ Summary: Security logging middleware for FastAPI, Flask, and Django
5
+ Author-email: PashyGeek <codyypashy@gmail.com>
6
+ Project-URL: Homepage, https://github.com/PashyGeek/ulinzilogs
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.28.0
10
+ Provides-Extra: fastapi
11
+ Requires-Dist: starlette>=0.20.0; extra == "fastapi"
12
+ Provides-Extra: flask
13
+ Requires-Dist: flask>=2.0.0; extra == "flask"
14
+ Provides-Extra: django
15
+ Requires-Dist: django>=3.2; extra == "django"
16
+ Provides-Extra: all
17
+ Requires-Dist: starlette>=0.20.0; extra == "all"
18
+ Requires-Dist: flask>=2.0.0; extra == "all"
19
+ Requires-Dist: django>=3.2; extra == "all"
20
+
21
+ # Ulinzilogs πŸ›‘οΈ
22
+
23
+ > **Lightweight, non‑blocking security logging middleware for Python web apps**
24
+ > Built for developers who want **visibility without performance pain**.
25
+
26
+ ---
27
+
28
+ ## 🌍 What is Ulinzilogs?
29
+
30
+ **Ulinzilogs** is a security‑focused middleware that silently watches incoming HTTP requests in your Python web application, **redacts sensitive data**, and **ships sanitized logs** to the Ulinzi Security API for **AI‑powered threat analysis**.
31
+
32
+ Think of it as:
33
+
34
+ > πŸ” *A security camera for your API β€” always on, never in the way.*
35
+
36
+ ---
37
+
38
+ ## ✨ Key Features
39
+
40
+ * πŸš€ **Non‑Blocking by Design** β€” Uses background threads so your request/response cycle stays fast.
41
+ * πŸ”’ **Automatic Data Redaction** β€” Sensitive fields are replaced with `[REDACTED]` before leaving your server.
42
+ * 🌐 **Multi‑Framework Support** β€” Works out of the box with FastAPI, Flask, and Django.
43
+ * 🧹 **Clean & Safe Headers** β€” Excludes `Authorization` and `Cookie` headers automatically.
44
+
45
+ ---
46
+
47
+ ## πŸ“¦ Installation
48
+
49
+ Install only what your stack needs:
50
+
51
+ ```bash
52
+ # FastAPI / Starlette
53
+ pip install ulinzilogs[fastapi]
54
+
55
+ # Flask
56
+ pip install ulinzilogs[flask]
57
+
58
+ # Django
59
+ pip install ulinzilogs[django]
60
+
61
+ # All frameworks
62
+ pip install ulinzilogs[all]
63
+ ```
64
+
65
+ ---
66
+
67
+ ## πŸ”‘ Getting Your Project Key
68
+
69
+ After installing, run:
70
+
71
+ ```bash
72
+ ulinzi-init
73
+ ```
74
+
75
+ This generates a **unique Project Key** for your app and prints setup instructions.
76
+
77
+ > ⚠️ **Important:** This key is generated locally on your machine.
78
+ > To activate it, copy the key and register it at **[ulinzilogs.com](https://ulinzilogs.com)**.
79
+ > Once registered, your dashboard will start receiving logs from your app.
80
+
81
+ ---
82
+
83
+ ## βš™οΈ Setup & Usage
84
+
85
+ ### 🟒 FastAPI
86
+
87
+ ```python
88
+ from fastapi import FastAPI
89
+ from ulinzilogs import UlinziFastAPIMiddleware
90
+
91
+ app = FastAPI()
92
+
93
+ app.add_middleware(
94
+ UlinziFastAPIMiddleware,
95
+ api_key="YOUR_ULINZI_KEY"
96
+ )
97
+
98
+ @app.get("/")
99
+ async def root():
100
+ return {"message": "Protected by Ulinzi"}
101
+ ```
102
+
103
+ ---
104
+
105
+ ### πŸ”΅ Flask
106
+
107
+ ```python
108
+ from flask import Flask
109
+ from ulinzilogs import UlinziFlaskMiddleware
110
+
111
+ app = Flask(__name__)
112
+ UlinziFlaskMiddleware(app, api_key="YOUR_ULINZI_KEY")
113
+
114
+ @app.route("/")
115
+ def hello():
116
+ return "Protected by Ulinzi"
117
+ ```
118
+
119
+ ---
120
+
121
+ ### 🟣 Django
122
+
123
+ In `settings.py`:
124
+
125
+ ```python
126
+ MIDDLEWARE = [
127
+ # ... other middleware
128
+ 'ulinzilogs.UlinziDjangoMiddleware',
129
+ ]
130
+
131
+ ULINZI_API_KEY = "YOUR_ULINZI_KEY"
132
+ ULINZI_APP_NAME = "MyDjangoApp" # optional label shown in dashboard
133
+ ```
134
+
135
+ ---
136
+
137
+ ## 🧠 How Ulinzilogs Works
138
+ Client Request
139
+ β”‚
140
+ β–Ό
141
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
142
+ β”‚ Middleware β”‚
143
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
144
+ β”‚
145
+ β–Ό
146
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
147
+ β”‚ Redact Sensitive β”‚
148
+ β”‚ Fields & Headers β”‚
149
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
150
+ β”‚
151
+ β–Ό (Background Thread)
152
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
153
+ β”‚ Send to Ulinzi β”‚
154
+ β”‚ Security API β”‚
155
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
156
+ β”‚
157
+ β–Ό
158
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
159
+ β”‚ AI Threat Analysis β”‚
160
+ β”‚ (SQLi, XSS, etc.) β”‚
161
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
162
+
163
+ 1. **Intercept** β€” Captures request metadata (IP, URL, method, body).
164
+ 2. **Redact** β€” Removes secrets before transmission.
165
+ 3. **Dispatch** β€” Sends logs asynchronously in a background thread.
166
+ 4. **Analyze** β€” Central AI scans for malicious patterns.
167
+
168
+ ---
169
+
170
+ ## πŸ” Sensitive Data Protection
171
+
172
+ The following keys are **automatically redacted**:
173
+
174
+ | Field | Redacted? |
175
+ |-------|-----------|
176
+ | `password` | βœ… Yes |
177
+ | `secret` | βœ… Yes |
178
+ | `token` | βœ… Yes |
179
+ | `key` | βœ… Yes |
180
+ | `cvv` | βœ… Yes |
181
+ | `api_key` | βœ… Yes |
182
+
183
+ Example:
184
+
185
+ ```json
186
+ {
187
+ "email": "user@mail.com",
188
+ "password": "[REDACTED]"
189
+ }
190
+ ```
191
+
192
+ Your users' secrets **never leave your server in plaintext**.
193
+
194
+ ---
195
+
196
+ ## ⚑ Performance Philosophy
197
+
198
+ * No request blocking
199
+ * No database writes on your server
200
+ * No logging delays
201
+
202
+ Ulinzilogs runs **beside** your app β€” not **inside** its critical path.
203
+
204
+ ---
205
+
206
+ ## 🧩 Package Structure
207
+ ulinzilogs/
208
+ β”œβ”€β”€ init.py
209
+ β”œβ”€β”€ middleware.py
210
+ β”œβ”€β”€ utils.py
211
+ β”œβ”€β”€ cli.py
212
+ β”œβ”€β”€ pyproject.toml
213
+ └── README.md
214
+
215
+ ---
216
+
217
+ ## πŸ“œ License
218
+
219
+ Copyright (c) 2026 PashyGeek. Licensed under the MIT License β€” see the LICENSE file for details.
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ ulinzilogs/__init__.py
4
+ ulinzilogs/cli.py
5
+ ulinzilogs/middleware.py
6
+ ulinzilogs/utils.py
7
+ ulinzilogs.egg-info/PKG-INFO
8
+ ulinzilogs.egg-info/SOURCES.txt
9
+ ulinzilogs.egg-info/dependency_links.txt
10
+ ulinzilogs.egg-info/entry_points.txt
11
+ ulinzilogs.egg-info/requires.txt
12
+ ulinzilogs.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ulinzi-init = ulinzilogs.cli:main
@@ -0,0 +1,15 @@
1
+ requests>=2.28.0
2
+
3
+ [all]
4
+ starlette>=0.20.0
5
+ flask>=2.0.0
6
+ django>=3.2
7
+
8
+ [django]
9
+ django>=3.2
10
+
11
+ [fastapi]
12
+ starlette>=0.20.0
13
+
14
+ [flask]
15
+ flask>=2.0.0
@@ -0,0 +1 @@
1
+ ulinzilogs