airflow-file-auth-manager 0.1.3__tar.gz → 0.1.5__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.
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/PKG-INFO +1 -1
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/pyproject.toml +1 -1
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/endpoints.py +19 -16
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/.gitignore +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/LICENSE +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/README.md +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/examples/users.yaml +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/__init__.py +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/cli.py +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/file_auth_manager.py +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/password.py +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/policy.py +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/static/styles.css +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/templates/login.html +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/user.py +0 -0
- {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/user_store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: airflow-file-auth-manager
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: YAML file-based lightweight Auth Manager for Apache Airflow 3.x
|
|
5
5
|
Project-URL: Homepage, https://github.com/choo121600/airflow-file-auth-manager
|
|
6
6
|
Project-URL: Repository, https://github.com/choo121600/airflow-file-auth-manager
|
|
@@ -4,9 +4,9 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
|
-
from fastapi import FastAPI,
|
|
9
|
+
from fastapi import FastAPI, Request, Response
|
|
10
10
|
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
|
11
11
|
from fastapi.staticfiles import StaticFiles
|
|
12
12
|
from jinja2 import Environment, FileSystemLoader
|
|
@@ -66,8 +66,6 @@ def create_auth_app(auth_manager: FileAuthManager) -> FastAPI:
|
|
|
66
66
|
async def create_token(
|
|
67
67
|
request: Request,
|
|
68
68
|
response: Response,
|
|
69
|
-
username: Annotated[str | None, Form()] = None,
|
|
70
|
-
password: Annotated[str | None, Form()] = None,
|
|
71
69
|
) -> Response:
|
|
72
70
|
"""Authenticate user and create JWT token.
|
|
73
71
|
|
|
@@ -77,20 +75,28 @@ def create_auth_app(auth_manager: FileAuthManager) -> FastAPI:
|
|
|
77
75
|
- Browser sessions: HttpOnly cookies (protected from XSS)
|
|
78
76
|
- API clients: Bearer tokens in response body (use Authorization header)
|
|
79
77
|
"""
|
|
80
|
-
# Handle
|
|
78
|
+
# Handle request based on content type
|
|
81
79
|
content_type = request.headers.get("content-type", "")
|
|
82
80
|
is_form_submission = "application/x-www-form-urlencoded" in content_type
|
|
81
|
+
username: str | None = None
|
|
82
|
+
password: str | None = None
|
|
83
|
+
form_data = None
|
|
83
84
|
|
|
84
85
|
if "application/json" in content_type:
|
|
85
86
|
try:
|
|
86
87
|
body = await request.json()
|
|
87
88
|
username = body.get("username")
|
|
88
89
|
password = body.get("password")
|
|
89
|
-
except Exception:
|
|
90
|
+
except Exception as e:
|
|
91
|
+
logger.error("Failed to parse JSON body: %s", e)
|
|
90
92
|
return JSONResponse(
|
|
91
93
|
status_code=400,
|
|
92
|
-
content={"error": "Invalid JSON body"},
|
|
94
|
+
content={"error": f"Invalid JSON body: {e}"},
|
|
93
95
|
)
|
|
96
|
+
elif is_form_submission:
|
|
97
|
+
form_data = await request.form()
|
|
98
|
+
username = form_data.get("username")
|
|
99
|
+
password = form_data.get("password")
|
|
94
100
|
|
|
95
101
|
# Validate input
|
|
96
102
|
if not username or not password:
|
|
@@ -120,19 +126,16 @@ def create_auth_app(auth_manager: FileAuthManager) -> FastAPI:
|
|
|
120
126
|
content={"error": "Invalid username or password"},
|
|
121
127
|
)
|
|
122
128
|
|
|
123
|
-
# Create JWT token
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
token_payload = auth_manager.serialize_user(user)
|
|
127
|
-
token = create_jwt_token(token_payload, expiration_seconds=jwt_expiration)
|
|
129
|
+
# Create JWT token using auth manager's method
|
|
130
|
+
token = auth_manager.generate_jwt(user, expiration_time_in_seconds=jwt_expiration)
|
|
128
131
|
|
|
129
132
|
logger.info("AUDIT: User logged in: %s (IP: %s)",
|
|
130
133
|
username, request.client.host if request.client else "unknown")
|
|
131
134
|
|
|
132
135
|
# Form submission - set HttpOnly cookie and redirect
|
|
133
136
|
if is_form_submission:
|
|
134
|
-
form_data
|
|
135
|
-
next_url = form_data.get("next", "/")
|
|
137
|
+
# form_data was already read above
|
|
138
|
+
next_url = form_data.get("next", "/") if form_data else "/"
|
|
136
139
|
|
|
137
140
|
# Detect if using HTTPS
|
|
138
141
|
is_secure = (
|
|
@@ -142,7 +145,7 @@ def create_auth_app(auth_manager: FileAuthManager) -> FastAPI:
|
|
|
142
145
|
|
|
143
146
|
redirect_response = RedirectResponse(url=str(next_url), status_code=303)
|
|
144
147
|
redirect_response.set_cookie(
|
|
145
|
-
key="
|
|
148
|
+
key="_token",
|
|
146
149
|
value=token,
|
|
147
150
|
max_age=jwt_expiration,
|
|
148
151
|
httponly=True, # Protect from XSS attacks
|
|
@@ -168,7 +171,7 @@ def create_auth_app(auth_manager: FileAuthManager) -> FastAPI:
|
|
|
168
171
|
request.client.host if request.client else "unknown")
|
|
169
172
|
|
|
170
173
|
redirect_response = RedirectResponse(url="/auth/login", status_code=303)
|
|
171
|
-
redirect_response.delete_cookie(key="
|
|
174
|
+
redirect_response.delete_cookie(key="_token")
|
|
172
175
|
return redirect_response
|
|
173
176
|
|
|
174
177
|
return app
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|