feat: rewrite AuthService to use ROLAC auth API with in-memory token storage

- Replace GET /api/Token/Create (Basic Auth) with POST /api/Auth/login
- Add refresh() method using HttpOnly cookie (POST /api/Auth/refresh)
- Add initializeFromRefreshToken() for APP_INITIALIZER support
- logout() now fires POST /api/Auth/logout (fire-and-forget)
- Rename User interface to UserInfo (matches C# DTO: id, email, roles, languagePreference)
- All auth state is in-memory only (no localStorage)
- Fix downstream consumers: app.ts, header components, mfa-dialog, token-verification
- Fix tsconfig.spec.json: exclude legacy src/components and src/directives
- Add stub enums.model.ts and fix models/index.ts for pre-existing build errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-05-26 20:47:43 -07:00
parent 4874f2a0a3
commit 62428cd2d4
12 changed files with 199 additions and 365 deletions
@@ -8,7 +8,7 @@ import { InputsModule } from '@progress/kendo-angular-inputs';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { IconsModule } from '@progress/kendo-angular-icons';
import { SVGIcon, bellIcon, menuIcon, searchIcon, userIcon, logoutIcon } from '@progress/kendo-svg-icons';
import { AuthService, User } from '../../../../shared/services/auth.service';
import { AuthService, UserInfo } from '../../../../shared/services/auth.service';
import { LayoutService } from '../../../../layout/services/layout.service';
import { Subject, takeUntil } from 'rxjs';
@@ -35,7 +35,7 @@ export class UserHeaderComponent implements OnInit, OnDestroy {
public logoutIcon: SVGIcon = logoutIcon;
public userMenuItems: any[] = [];
public currentUser: User | null = null;
public currentUser: UserInfo | null = null;
public badgeAlign = {
vertical: 'top' as const,
@@ -81,11 +81,7 @@ export class UserHeaderComponent implements OnInit, OnDestroy {
}
public getDisplayName(): string {
if (this.currentUser) {
const fullName = `${this.currentUser.firstName} ${this.currentUser.lastName}`.trim();
return fullName || this.currentUser.email;
}
return '';
return this.currentUser?.email || '';
}
private updateUserMenu(): void {
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AuthService, User } from '../../../../shared/services/auth.service';
import { AuthService, UserInfo } from '../../../../shared/services/auth.service';
interface Transaction {
id: string;
@@ -20,7 +20,7 @@ interface Transaction {
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
currentUser: User | null = null;
currentUser: UserInfo | null = null;
activeTransactions = 5;
pendingTasks = 12;
@@ -66,10 +66,6 @@ export class DashboardComponent implements OnInit {
}
getDisplayName(): string {
if (this.currentUser) {
const fullName = `${this.currentUser.firstName} ${this.currentUser.lastName}`.trim();
return fullName || this.currentUser.email;
}
return '';
return this.currentUser?.email || '';
}
}
@@ -2,7 +2,7 @@ import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, NavigationEnd, RouterModule, RouterLink, RouterLinkActive } from '@angular/router';
import { RouterOutlet } from '@angular/router';
import { AuthService, User } from '../../shared/services/auth.service';
import { AuthService, UserInfo } from '../../shared/services/auth.service';
import { Subject, takeUntil, filter } from 'rxjs';
@Component({
@@ -21,7 +21,7 @@ import { Subject, takeUntil, filter } from 'rxjs';
export class UserPortalComponent implements OnInit, OnDestroy {
sidebarCollapsed = false;
isMobile = false;
currentUser: User | null = null;
currentUser: UserInfo | null = null;
currentPageTitle = 'Dashboard';
unreadMessages = 3;
unreadNotifications = 2;
@@ -130,10 +130,6 @@ export class UserPortalComponent implements OnInit, OnDestroy {
}
getDisplayName(): string {
if (this.currentUser) {
const fullName = `${this.currentUser.firstName} ${this.currentUser.lastName}`.trim();
return fullName || this.currentUser.email;
}
return '';
return this.currentUser?.email || '';
}
}