Compare commits

...
2 Commits
Author SHA1 Message Date
Jeroen SchweitzerandClaude Opus 4.5 3516376d92 chore: cleanup auth code after debugging session
Build and Push / build (release) Successful in 50s
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 21:41:10 +01:00
Jeroen SchweitzerandClaude Opus 4.5 ffa984e271 fix: separate httpx and SQLAlchemy async contexts in bulk sync
Build and Push / build (release) Successful in 50s
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 21:34:34 +01:00
3 changed files with 78 additions and 63 deletions
+12
View File
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.4.6] - 2026-01-01
### Changed
- Code cleanup: move inline `re` import to top of auth/service.py
## [1.4.5] - 2026-01-01
### Fixed
- Separate httpx and SQLAlchemy async contexts in bulk sync (fixes greenlet error)
## [1.4.4] - 2026-01-01 ## [1.4.4] - 2026-01-01
### Fixed ### Fixed
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "core-api" name = "core-api"
version = "1.4.4" version = "1.4.6"
description = "Core Code API - Infrastructure management and tools API" description = "Core Code API - Infrastructure management and tools API"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
+9 -6
View File
@@ -3,6 +3,7 @@ Authentication Service
Business logic for user synchronization from Authentik. Business logic for user synchronization from Authentik.
""" """
import re
import uuid import uuid
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Optional from typing import Optional
@@ -251,7 +252,6 @@ class AuthService:
def _extract_cookie(self, headers: httpx.Headers, cookie_name: str) -> str: def _extract_cookie(self, headers: httpx.Headers, cookie_name: str) -> str:
"""Extract a specific cookie value from Set-Cookie headers""" """Extract a specific cookie value from Set-Cookie headers"""
import re
for header in headers.get_list('set-cookie'): for header in headers.get_list('set-cookie'):
if header.startswith(f'{cookie_name}='): if header.startswith(f'{cookie_name}='):
match = re.match(rf'{cookie_name}=([^;]+)', header) match = re.match(rf'{cookie_name}=([^;]+)', header)
@@ -369,6 +369,8 @@ class AuthService:
errors = [] errors = []
total_in_authentik = 0 total_in_authentik = 0
# Step 1: Fetch all user data from Authentik API
authentik_users = []
try: try:
async with httpx.AsyncClient(timeout=30.0, follow_redirects=True) as client: async with httpx.AsyncClient(timeout=30.0, follow_redirects=True) as client:
# Authenticate with Authentik to get session cookie # Authenticate with Authentik to get session cookie
@@ -393,6 +395,12 @@ class AuthService:
authentik_users = data.get("results", []) authentik_users = data.get("results", [])
total_in_authentik = data.get("pagination", {}).get("count", len(authentik_users)) total_in_authentik = data.get("pagination", {}).get("count", len(authentik_users))
except httpx.HTTPStatusError as e:
raise ValueError(f"Authentik API error: {e.response.status_code}")
except httpx.RequestError as e:
raise ValueError(f"Failed to connect to Authentik: {str(e)}")
# Step 2: Sync users to database (outside of httpx context to avoid greenlet issues)
for auth_user in authentik_users: for auth_user in authentik_users:
try: try:
# Skip service accounts and inactive users # Skip service accounts and inactive users
@@ -454,11 +462,6 @@ class AuthService:
# Commit all changes # Commit all changes
await self.session.commit() await self.session.commit()
except httpx.HTTPStatusError as e:
raise ValueError(f"Authentik API error: {e.response.status_code}")
except httpx.RequestError as e:
raise ValueError(f"Failed to connect to Authentik: {str(e)}")
return BulkSyncResultSchema( return BulkSyncResultSchema(
created=created, created=created,
updated=updated, updated=updated,