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.
Files changed (16) hide show
  1. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/PKG-INFO +1 -1
  2. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/pyproject.toml +1 -1
  3. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/endpoints.py +19 -16
  4. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/.gitignore +0 -0
  5. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/LICENSE +0 -0
  6. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/README.md +0 -0
  7. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/examples/users.yaml +0 -0
  8. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/__init__.py +0 -0
  9. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/cli.py +0 -0
  10. {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
  11. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/password.py +0 -0
  12. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/policy.py +0 -0
  13. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/static/styles.css +0 -0
  14. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/templates/login.html +0 -0
  15. {airflow_file_auth_manager-0.1.3 → airflow_file_auth_manager-0.1.5}/src/airflow_file_auth_manager/user.py +0 -0
  16. {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
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,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "airflow-file-auth-manager"
7
- version = "0.1.3"
7
+ version = "0.1.5"
8
8
  description = "YAML file-based lightweight Auth Manager for Apache Airflow 3.x"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -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, Annotated
7
+ from typing import TYPE_CHECKING
8
8
 
9
- from fastapi import FastAPI, Form, Request, Response
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 JSON request
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
- from airflow.api_fastapi.auth.tokens import create_jwt_token
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 = await request.form()
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="airflow_jwt",
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="airflow_jwt")
174
+ redirect_response.delete_cookie(key="_token")
172
175
  return redirect_response
173
176
 
174
177
  return app