Fix LDAP login: ensure password encoding and include user in response

- Fix password encoding: Convert password to UTF-8 bytes for LDAP protocol compatibility
- Add 'user' field to TokenResponse schema for frontend compatibility
- Update login endpoint to populate user object in response
- Resolves 'Invalid Protocol Password' error on LDAP login attempts

The issue was that frontend expected response.user but backend only returned
individual fields (user_id, username, role), causing localStorage assignment to fail.
This commit is contained in:
2026-04-26 13:13:55 +03:00
parent 904e3442b0
commit 51716faf87
5 changed files with 22 additions and 17 deletions

View File

@@ -1,3 +1,3 @@
65062
65063
65079
98497
98498
98515

View File

@@ -67,7 +67,9 @@ def authenticate_ldap(username, password):
user_dn = config["user_template"].format(username=safe_username_rdn)
log.debug(f"LDAP: Attempting bind for DN: {user_dn}")
conn = ldap3.Connection(server, user=user_dn, password=password, auto_bind=True)
# [FIX] Ensure password is UTF-8 encoded for LDAP protocol
password_bytes = password.encode('utf-8') if isinstance(password, str) else password
conn = ldap3.Connection(server, user=user_dn, password=password_bytes, auto_bind=True)
log.debug(f"LDAP: Bind successful for {user_dn}")
# Search for the user to get their CANONICAL DN
@@ -250,7 +252,8 @@ def login(request: Request, form_data: schemas.UserLogin, db: Session = Depends(
token_type="bearer",
user_id=user.id,
username=user.username,
role=user.role
role=user.role,
user=schemas.User(id=user.id, username=user.username, role=user.role, origin=user.origin)
)

View File

@@ -42,3 +42,4 @@ class TokenResponse(BaseModel):
user_id: int
username: str
role: str
user: Optional['User'] = None # For frontend compatibility

View File

@@ -6,14 +6,14 @@
@layer base {
:root {
/* Base colors AUTO-GENERATED from colors.mjs */
/* PALETTE: Electric Blue (2026-04-26) */
/* Base colors from DESIGN.md - AUTO-GENERATED from colors.mjs */
/* Base colors from DESIGN.md */
--background: #131313;
--on-background: #dde4f0;
--foreground: #dde4f0;
/* Surface — cool blue-tinted darks */
/* Surface colors from DESIGN.md */
--surface-DEFAULT: #131313;
--surface-dim: #131313;
--surface-bright: #1e2535;
@@ -24,7 +24,7 @@
--surface-container-highest: #252d42;
--surface-variant: #252d42;
/* Primary — Electric Blue */
/* Primary colors from DESIGN.md */
--primary-DEFAULT: #58a6ff;
--primary-foreground: #001a4d;
--primary-container: #1d6fd4;
@@ -35,7 +35,7 @@
--primary-on-fixed-variant: #003380;
--primary-inverse: #1d5fa8;
/* Secondary — Cool blue-grey */
/* Secondary colors from DESIGN.md */
--secondary-DEFAULT: #9aa5be;
--secondary-foreground: #1a2030;
--secondary-container: #3d4d6b;
@@ -45,7 +45,7 @@
--secondary-on-fixed: #0d1220;
--secondary-on-fixed-variant: #3d4d6b;
/* Tertiary — Cyan-teal */
/* Tertiary colors from DESIGN.md */
--tertiary-DEFAULT: #00d4aa;
--tertiary-foreground: #003328;
--tertiary-container: #00a882;
@@ -55,21 +55,21 @@
--tertiary-on-fixed: #002820;
--tertiary-on-fixed-variant: #005544;
/* Error — pure red (no rose/pink cast) */
/* Error colors from DESIGN.md */
--error-DEFAULT: #ff5f52;
--error-foreground: #1a0000;
--error-container: #7a0000;
--error-on-container: #ffdad6;
/* Outline — blue-tinted */
/* Outline colors from DESIGN.md */
--outline: #3d5a8a;
--outline-variant: #1e3055;
/* Inverse */
/* Inverse colors from DESIGN.md */
--inverse-surface: #dde4f0;
--inverse-on-surface: #1a2030;
/* Semantic */
/* Semantic colors from DESIGN.md */
--border: #252d42;
--muted: #5a6a8a;
--info: #58a6ff;
@@ -77,7 +77,7 @@
--warning: #f0a040;
--alert: #ff5f52;
/* Spacing tokens */
/* Semantic spacing tokens */
--spacing-unit: 4px;
--spacing-stack-sm: 8px;
--spacing-stack-md: 16px;
@@ -86,6 +86,7 @@
--spacing-container-gap: 24px;
}
* {
@apply border-border;
border-radius: 0 !important;

BIN
frontend_for_design.zip Normal file

Binary file not shown.