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 98497
65063 98498
65079 98515

View File

@@ -67,7 +67,9 @@ def authenticate_ldap(username, password):
user_dn = config["user_template"].format(username=safe_username_rdn) user_dn = config["user_template"].format(username=safe_username_rdn)
log.debug(f"LDAP: Attempting bind for DN: {user_dn}") 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}") log.debug(f"LDAP: Bind successful for {user_dn}")
# Search for the user to get their CANONICAL 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", token_type="bearer",
user_id=user.id, user_id=user.id,
username=user.username, 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 user_id: int
username: str username: str
role: str role: str
user: Optional['User'] = None # For frontend compatibility

View File

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

BIN
frontend_for_design.zip Normal file

Binary file not shown.