fix login redirect

This commit is contained in:
2026-03-15 22:54:52 +01:00
parent 2406d41dcb
commit e3203d0c38
8 changed files with 110 additions and 28 deletions

View File

@@ -89,4 +89,42 @@ describe('RoleGuard', () => {
done();
});
});
it('should redirect members to shows instead of new-user', done => {
TestBed.resetTestingModule();
routerSpy = jasmine.createSpyObj<Router>('Router', ['createUrlTree']);
routerSpy.createUrlTree.and.returnValue({redirect: ['shows']} as never);
TestBed.configureTestingModule({
providers: [
{provide: Router, useValue: routerSpy},
{provide: UserService, useValue: {user$: of({role: 'member'})}},
],
});
guard = TestBed.inject(RoleGuard);
guard.canActivate({data: {requiredRoles: ['user']}} as never).subscribe(result => {
expect(routerSpy.createUrlTree).toHaveBeenCalledWith(['shows']);
expect(result).toEqual({redirect: ['shows']} as never);
done();
});
});
it('should choose a matching default route from all assigned roles', done => {
TestBed.resetTestingModule();
routerSpy = jasmine.createSpyObj<Router>('Router', ['createUrlTree']);
routerSpy.createUrlTree.and.callFake(commands => ({redirect: commands}) as never);
TestBed.configureTestingModule({
providers: [
{provide: Router, useValue: routerSpy},
{provide: UserService, useValue: {user$: of({role: ' none ; leader '})}},
],
});
guard = TestBed.inject(RoleGuard);
guard.canActivate({data: {requiredRoles: ['presenter']}} as never).subscribe(result => {
expect(routerSpy.createUrlTree).toHaveBeenCalledWith(['shows']);
expect(result).toEqual({redirect: ['shows']} as never);
done();
});
});
});

View File

@@ -3,6 +3,7 @@ import {ActivatedRouteSnapshot, Router, UrlTree} from '@angular/router';
import {Observable} from 'rxjs';
import {UserService} from '../../services/user/user.service';
import {map, take} from 'rxjs/operators';
import {roles} from '../../services/user/roles';
@Injectable({
providedIn: 'root',
@@ -23,30 +24,45 @@ export class RoleGuard {
if (!user) {
return this.router.createUrlTree(['brand', 'new-user']);
}
const roles = user.role?.split(';') ?? [];
if (roles.indexOf('admin') !== -1) {
const userRoles = this.parseRoles(user.role);
if (userRoles.includes('admin')) {
return true;
}
const allowed = roles.some(s => requiredRoles.indexOf(s) !== -1);
const allowed = userRoles.some(role => requiredRoles.includes(role));
return allowed || this.router.createUrlTree(this.defaultRoute(roles));
return allowed || this.router.createUrlTree(this.defaultRoute(userRoles));
})
);
}
private defaultRoute(roles: string[]): string[] {
if (!roles || roles.length === 0) {
private defaultRoute(userRoles: roles[]): string[] {
if (userRoles.length === 0) {
return ['brand', 'new-user'];
}
switch (roles[0]) {
case 'user':
return ['songs'];
case 'presenter':
return ['presentation'];
case 'leader':
return ['shows'];
if (userRoles.includes('user') || userRoles.includes('contributor')) {
return ['songs'];
}
return ['brand', 'new-user'];
if (userRoles.includes('leader') || userRoles.includes('member')) {
return ['shows'];
}
if (userRoles.includes('presenter')) {
return ['presentation'];
}
return ['user', 'info'];
}
private parseRoles(role: string | null | undefined): roles[] {
if (!role) {
return [];
}
return role
.split(';')
.map(value => value.trim())
.filter((value): value is roles => value.length > 0 && value !== 'none');
}
}

View File

@@ -4,15 +4,15 @@ import {Pipe, PipeTransform} from '@angular/core';
name: 'sortBy',
})
export class SortByPipe implements PipeTransform {
public transform(value: unknown[] | null, order: 'asc' | 'desc' = 'asc', column = ''): unknown[] | null {
public transform<T>(value: T[] | null, order: 'asc' | 'desc' = 'asc', column = ''): T[] | null {
if (!value || !order) {
return value;
} // no array
if (!column || column === '') {
if (order === 'asc') {
return value.sort();
return [...value].sort();
} else {
return value.sort().reverse();
return [...value].sort().reverse();
}
} // sort 1d array
if (value.length <= 1) {
@@ -26,7 +26,7 @@ export class SortByPipe implements PipeTransform {
});
}
private getComparableValue(item: unknown, column: string): string | number {
private getComparableValue<T>(item: T, column: string): string | number {
const value = (item as Record<string, unknown>)[column];
if (value instanceof Date) {
return value.getTime();