feature: authorization - add role guard and protect products route
This commit is contained in:
parent
617053c0ee
commit
8b1b831ea2
@ -1,6 +1,7 @@
|
|||||||
import { Routes } from "@angular/router";
|
import { Routes } from "@angular/router";
|
||||||
import { Home } from "./features/home/home";
|
import { Home } from "./features/home/home";
|
||||||
import { authGuard } from "./core/guards/auth-guard";
|
import { authGuard } from "./core/guards/auth-guard";
|
||||||
|
import { roleGuard } from "./core/guards/role-guard";
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -16,6 +17,7 @@ export const routes: Routes = [
|
|||||||
path: "products",
|
path: "products",
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import("./features/product/product.routes").then((routes) => routes.productRoutes),
|
import("./features/product/product.routes").then((routes) => routes.productRoutes),
|
||||||
// canActivate: [authGuard]
|
canActivate: [authGuard, roleGuard],
|
||||||
|
data: { roles: ["broker"] },
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
17
src/app/core/guards/role-guard.spec.ts
Normal file
17
src/app/core/guards/role-guard.spec.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { TestBed } from "@angular/core/testing";
|
||||||
|
import { CanActivateFn } from "@angular/router";
|
||||||
|
|
||||||
|
import { roleGuard } from "./role-guard";
|
||||||
|
|
||||||
|
describe("roleGuard", () => {
|
||||||
|
const executeGuard: CanActivateFn = (...guardParameters) =>
|
||||||
|
TestBed.runInInjectionContext(() => roleGuard(...guardParameters));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be created", () => {
|
||||||
|
expect(executeGuard).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
12
src/app/core/guards/role-guard.ts
Normal file
12
src/app/core/guards/role-guard.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { CanActivateFn } from "@angular/router";
|
||||||
|
import { inject } from "@angular/core";
|
||||||
|
import { AuthService } from "../../features/auth/services/auth-service";
|
||||||
|
|
||||||
|
export const roleGuard: CanActivateFn = (route, state) => {
|
||||||
|
const authService = inject(AuthService);
|
||||||
|
|
||||||
|
// get role from route data passed in route config.
|
||||||
|
const roles = route.data["roles"] as string[];
|
||||||
|
|
||||||
|
return roles && authService.hasRoles(roles);
|
||||||
|
};
|
||||||
@ -13,4 +13,5 @@ export interface User {
|
|||||||
email: string;
|
email: string;
|
||||||
mobileNumber: string;
|
mobileNumber: string;
|
||||||
city: string;
|
city: string;
|
||||||
|
role: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export class AuthService {
|
|||||||
// User states
|
// User states
|
||||||
readonly authState: WritableSignal<AuthState>;
|
readonly authState: WritableSignal<AuthState>;
|
||||||
readonly user: WritableSignal<User | null>;
|
readonly user: WritableSignal<User | null>;
|
||||||
|
readonly userRole: Signal<string | null>;
|
||||||
|
|
||||||
// Computed state for easy checking
|
// Computed state for easy checking
|
||||||
readonly isAuthenticated: Signal<boolean>;
|
readonly isAuthenticated: Signal<boolean>;
|
||||||
@ -45,6 +46,7 @@ export class AuthService {
|
|||||||
);
|
);
|
||||||
this.user = signal<User | null>(cachedUser);
|
this.user = signal<User | null>(cachedUser);
|
||||||
this.isAuthenticated = computed(() => !!this.user());
|
this.isAuthenticated = computed(() => !!this.user());
|
||||||
|
this.userRole = computed(() => this.user()?.role || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
register(userRequest: RegisterUserRequest) {
|
register(userRequest: RegisterUserRequest) {
|
||||||
@ -74,6 +76,16 @@ export class AuthService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if current user has the role.
|
||||||
|
* Mostly used in role guard.
|
||||||
|
*/
|
||||||
|
hasRoles(roles: string[]) {
|
||||||
|
const role = this.userRole();
|
||||||
|
if (!role) return false;
|
||||||
|
return roles.includes(role);
|
||||||
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
return this.http.post(`${this.backendURL}/logout`, {}).pipe(
|
return this.http.post(`${this.backendURL}/logout`, {}).pipe(
|
||||||
tap({
|
tap({
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user