fix 401 loop hell

This commit is contained in:
Chris Chen
2026-05-27 15:09:05 -07:00
parent e83fa4c2e9
commit d79b1faa8f
13 changed files with 196 additions and 90 deletions
@@ -36,14 +36,20 @@
</button>
</div>
<!-- Administration (role-guarded) -->
<div class="nav-section" *ngIf="showAdminSection">
<div class="nav-section" *ngIf="showMemberAdminSection || showUserAdminSection">
<h4>Administration</h4>
<button *ngFor="let item of adminNavItems" kendoButton
<button *ngFor="let item of memberAdminNavItems" kendoButton
[fillMode]="item.active ? 'solid' : 'flat'" [themeColor]="item.active ? 'primary' : 'base'"
[svgIcon]="item.icon" class="nav-button" (click)="navigateTo(item.path)">
{{ item.text }}
</button>
<ng-container *ngIf="showUserAdminSection">
<button *ngFor="let item of userAdminNavItems" kendoButton
[fillMode]="item.active ? 'solid' : 'flat'" [themeColor]="item.active ? 'primary' : 'base'"
[svgIcon]="item.icon" class="nav-button" (click)="navigateTo(item.path)">
{{ item.text }}
</button>
</ng-container>
</div>
</nav>
</div>
@@ -60,12 +60,16 @@ export class UserNavbarComponent implements OnInit, OnDestroy {
{ text: 'Support', icon: this.supportIcon, path: '/user-portal/support' }
];
public adminNavItems: NavItem[] = [
public memberAdminNavItems: NavItem[] = [
{ text: 'Members', icon: groupIcon, path: '/user-portal/admin/members' },
{ text: 'Users', icon: userIcon, path: '/user-portal/admin/users' },
];
public showAdminSection = false;
public userAdminNavItems: NavItem[] = [
{ text: 'User Management', icon: userIcon, path: '/user-portal/admin/users' },
];
public showMemberAdminSection = false;
public showUserAdminSection = false;
private destroy$ = new Subject<void>();
@@ -89,9 +93,10 @@ export class UserNavbarComponent implements OnInit, OnDestroy {
// Set initial active state
this.updateActiveStates(this.router.url);
// Show Administration section for super_admin or secretary
this.authService.currentUser$.pipe(takeUntil(this.destroy$)).subscribe(user => {
this.showAdminSection = !!user?.roles?.some(r => r === 'super_admin' || r === 'secretary');
const roles = user?.roles ?? [];
this.showMemberAdminSection = roles.some(r => r === 'super_admin' || r === 'secretary');
this.showUserAdminSection = roles.includes('super_admin');
});
}
@@ -107,11 +112,13 @@ export class UserNavbarComponent implements OnInit, OnDestroy {
private updateActiveStates(currentUrl: string): void {
// Reset all active states
[...this.mainNavItems, ...this.managementNavItems, ...this.supportNavItems, ...this.adminNavItems]
[...this.mainNavItems, ...this.managementNavItems, ...this.supportNavItems,
...this.memberAdminNavItems, ...this.userAdminNavItems]
.forEach(item => item.active = false);
// Set active state for current route
const activeItem = [...this.mainNavItems, ...this.managementNavItems, ...this.supportNavItems, ...this.adminNavItems]
const activeItem = [...this.mainNavItems, ...this.managementNavItems, ...this.supportNavItems,
...this.memberAdminNavItems, ...this.userAdminNavItems]
.find(item => currentUrl.startsWith(item.path));
if (activeItem) {
@@ -47,6 +47,22 @@
<span *ngIf="!sidebarCollapsed">Dashboard</span>
</a>
</div>
<div class="nav-section" *ngIf="showAdminSection">
<h4 *ngIf="!sidebarCollapsed">Administration</h4>
<a routerLink="/user-portal/admin/users" routerLinkActive="active" class="nav-item"
(click)="onNavigationClick()">
<div class="nav-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M22 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
</div>
<span *ngIf="!sidebarCollapsed">User Management</span>
</a>
</div>
</nav>
<div class="sidebar-footer" *ngIf="!sidebarCollapsed">
@@ -23,6 +23,7 @@ export class UserPortalComponent implements OnInit, OnDestroy {
isMobile = false;
currentUser: UserInfo | null = null;
currentPageTitle = 'Dashboard';
showAdminSection = false;
unreadMessages = 3;
unreadNotifications = 2;
@@ -64,6 +65,7 @@ export class UserPortalComponent implements OnInit, OnDestroy {
.pipe(takeUntil(this.destroy$))
.subscribe(user => {
this.currentUser = user;
this.showAdminSection = !!user?.roles?.includes('super_admin');
});
}
@@ -76,6 +78,8 @@ export class UserPortalComponent implements OnInit, OnDestroy {
.subscribe(() => {
this.updatePageTitle();
});
this.updatePageTitle();
}
private updatePageTitle(): void {