Skip to content
Snippets Groups Projects
Commit c699e53f authored by migudel's avatar migudel :speech_balloon:
Browse files

Nueva estructura

parent a9fd392e
Branches
No related tags found
2 merge requests!36Develop,!31Dev/refactor hotels booking
Showing
with 153 additions and 166 deletions
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { NavigationComponent } from './core/navigation/navigation.component';
import { NavigationComponent } from '@shared';
@Component({
selector: 'app-root',
......
......@@ -9,7 +9,7 @@ import {
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { ReactiveFormsModule } from '@angular/forms'; // Added import for ReactiveFormsModule
import { provideNativeDateAdapter } from '@angular/material/core';
import { authRequest } from './security/auth.interceptor';
import { authRequest } from '@core/interceptors';
export const appConfig: ApplicationConfig = {
providers: [
......
import { Route, Routes } from '@angular/router';
import { HotelListComponent } from './core/features/hotel/hotel-list/hotel-list.component';
import { BookingComponent } from './core/features/bookings/booking/booking.component';
import { HotelRegisterComponent } from './core/features/hotel/hotel-register/hotel-register.component';
import { MainPageComponent } from './core/features/user/main-page/main-page.component';
import { BookingListComponent } from './core/features/bookings/booking-list/booking-list.component';
import { UserBookingListComponent } from './core/features/user/user-booking-list/user-booking-list.component';
import { UserFormComponent } from './core/features/user/user-form/user-form.component';
import { HotelListComponent } from './features/hotels/hotel-list/hotel-list.component';
import { BookingComponent } from './features/bookings/booking/booking.component';
import { HotelRegisterComponent } from './features/hotels/hotel-register/hotel-register.component';
import { MainPageComponent } from './features/users/main-page/main-page.component';
import { UserBookingListComponent } from './features/bookings/user-booking-list/user-booking-list.component';
import { UserFormComponent } from './features/users/user-form/user-form.component';
import { UnauthorizedComponent } from './page/unauthorized/unauthorized.component';
import { rolGuard } from './security/rol.guard';
import { UserRol, UserRolesArray } from './types';
interface RouteData {
expectedRole: UserRol | UserRol[];
}
type AppRoute = Omit<Route, 'data'> & {
data?: RouteData;
};
import { AppRoute, UserRolesArray } from './core/models';
import { rolGuard, rolGuardChild } from '@core/guards';
export const routes: AppRoute[] = [
// Auth
{
path: 'login',
component: UserFormComponent,
},
{
path: 'register',
component: UserFormComponent,
path: '',
loadChildren: () => import('./features/auth').then((m) => m.AUTH_ROUTES),
},
// Hoteles
{
path: 'hotels', // Ruta para la lista de hoteles
component: HotelListComponent,
},
{
path: 'hotels/register', // Registrar nuevo hotel
component: HotelRegisterComponent,
canActivate: [rolGuard],
data: { expectedRole: 'HOTEL_ADMIN' },
},
{
path: 'hotels/:id', // Hotel concreto
component: HotelRegisterComponent,
path: 'hotels',
loadChildren: () =>
import('./features/hotels').then((m) => m.HOTELS_ROUTES),
},
// Usuario
{
path: 'me', // Main
canActivate: [rolGuard],
data: { expectedRole: UserRolesArray },
component: UserFormComponent,
},
{
path: 'me/edit', // Main
component: UserFormComponent,
canActivate: [rolGuard],
data: { expectedRole: UserRolesArray },
},
{
path: 'me/change-passwd', // Main
component: UserFormComponent,
canActivate: [rolGuard],
data: { expectedRole: UserRolesArray },
},
// Usuario HOTEL admin
{
path: 'me/hotels',
component: HotelListComponent,
canActivate: [rolGuard],
data: { expectedRole: 'HOTEL_ADMIN' },
},
{
path: 'me/hotels/:id',
component: HotelRegisterComponent,
canActivate: [rolGuard],
data: { expectedRole: 'HOTEL_ADMIN' },
},
// {
// path: 'me/hotels/:id/bookings',
// component: BookingListComponent,
// },
// {
// path: 'me/hotels/:id/rooms/:id/bookings',
// component: BookingListComponent,
// },
// Usuario Cliente
{
path: 'me/bookings',
component: UserBookingListComponent,
canActivate: [rolGuard],
data: { expectedRole: 'CLIENT' },
},
{
path: 'me/bookings/:id',
component: BookingComponent,
path: 'me',
canActivate: [rolGuard],
data: { expectedRole: 'CLIENT' },
canActivateChild: [rolGuardChild],
loadChildren: () => import('./features/users').then((m) => m.USERS_ROUTES),
},
{
path: 'me/bookings/new',
component: BookingComponent,
canActivate: [rolGuard],
data: { expectedRole: 'CLIENT' },
},
// Administrador
{
path: 'admin', // Main
component: UserFormComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
{
path: 'admin/users', // Main
component: MainPageComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
{
path: 'admin/users/:id', // Main
component: UserFormComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
{
path: 'admin/users/:id/edit', // Main
component: UserFormComponent,
path: 'admin',
canActivate: [rolGuard],
canActivateChild: [rolGuardChild],
data: { expectedRole: 'ADMIN' },
loadChildren: () => import('./features/admin').then((m) => m.ADMIN_ROUTES),
},
{
path: 'admin/users/:id/change-passwd', // Main
component: UserFormComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
{
path: 'admin/users/:id/bookings',
component: UserBookingListComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
// {
// path: 'admin/users/:id/bookings/:bookingId',
// component: BookingComponent,
// },
{
path: 'admin/users/:id/hotels',
component: HotelListComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
{
path: 'admin/users/:userId/hotels/:id',
component: HotelRegisterComponent,
canActivate: [rolGuard],
data: { expectedRole: 'ADMIN' },
},
// {
// path: 'admin/users/:userId/hotels/:id/bookings',
// component: BookingListComponent,
// canActivate: [rolGuard],
// data: { expectedRole: 'ADMIN' },
// },
// {
// path: 'admin/users/:userId/hotels/:hotelId/rooms/:id/bookings',
// component: BookingListComponent,
// canActivate: [rolGuard],
// data: { expectedRole: 'ADMIN' },
// },
// Página no autorizada
{
path: 'unauthorized',
component: UnauthorizedComponent,
......
export * from './rol.guard';
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { SessionService } from '../shared/session.service';
import { UserRol, Session } from '../types';
import {
ActivatedRouteSnapshot,
CanActivateChildFn,
CanActivateFn,
Router,
} from '@angular/router';
import { Session, UserRol } from '@core/models';
import { SessionService } from '@core/services';
import { map } from 'rxjs';
export const rolGuard: CanActivateFn = (route, state) => {
/**
* Obtiene el rol de la ruta padre si el hijo no define uno.
* Navega hacia los ancestros buscando un rol especificado en `data`.
*/
function getInheritedRole(route: ActivatedRouteSnapshot): string | undefined {
let parent = route.parent; // Comenzar desde el padre inmediato
while (parent) {
if (parent.data && parent.data['rol']) {
return parent.data['rol']; // Retorna el primer rol encontrado
}
parent = parent.parent; // Continuar hacia arriba en el árbol
}
return undefined; // No se encontró un rol definido en los ancestros
}
function verifyRol(expectedRole: UserRol) {
const sessionService = inject(SessionService);
const router = inject(Router);
// Obtén el rol esperado desde los datos de la ruta
const expectedRole = route.data?.['expectedRole'];
// Verifica si el usuario tiene sesión activa
const session = sessionService.isValid();
......@@ -18,7 +36,6 @@ export const rolGuard: CanActivateFn = (route, state) => {
router.navigate(['/login']);
return false;
}
return sessionService.getSession().pipe(
map((session: Session | null) => {
if (!session) return false;
......@@ -40,4 +57,22 @@ export const rolGuard: CanActivateFn = (route, state) => {
return false;
})
);
}
export const rolGuard: CanActivateFn = (route, state) => {
// Obtén el rol esperado desde los datos de la ruta
const expectedRole = route.data?.['expectedRole'];
return verifyRol(expectedRole);
};
export const rolGuardChild: CanActivateChildFn = (childRoute, state) => {
// Obtener el rol de la ruta hija si está especificado y en caso
// de no especificarse se busca en el/los padres
let requiredRol = childRoute.data['rol'] ?? getInheritedRole(childRoute);
// Si no hay rol especificado se supone libre de verificación
if (!requiredRol) return true;
// Verificar si el usuario tiene el rol requerido
return verifyRol(requiredRol);
};
import { TestBed } from '@angular/core/testing';
import { HttpInterceptorFn } from '@angular/common/http';
import { authInterceptor } from './auth.interceptor';
describe('authInterceptor', () => {
const interceptor: HttpInterceptorFn = (req, next) =>
TestBed.runInInjectionContext(() => authInterceptor(req, next));
beforeEach(() => {
TestBed.configureTestingModule({});
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
});
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { LocalStorageService } from '../shared/local-storage.service';
import { SessionService } from '../shared/session.service';
import { SessionService } from '@core/services/session/session.service';
const excluded = ['/login', '/register'];
......
export * from './auth.interceptor';
import { Room } from './Room';
import { User } from './User';
import { Room } from './Room.interface';
import { User } from './User.interface';
export interface Booking {
id: number;
......
import { Address } from './Address';
import { Room } from './Room';
import { Address } from './Address.interface';
import { Room } from './Room.interface';
export interface Hotel {
id: number;
......
export type RoomType = 'SINGLE' | 'DOUBLE' | 'SUITE';
export const roomTypeArray: RoomType[] = ['SINGLE', 'DOUBLE', 'SUITE'];
export interface Room {
id: number;
roomNumber: String;
......
import { Route } from '@angular/router';
import { UserRol } from './User.interface';
interface RouteData {
expectedRole: UserRol | UserRol[];
}
export type AppRoute = Omit<Route, 'data'> & {
data?: RouteData;
};
import { UserRol } from './User.interface';
export interface Session {
id: number;
name: string;
......@@ -5,7 +7,7 @@ export interface Session {
rol: UserRol;
}
interface PersistenToken {
export interface PersistenToken {
token: string;
session?: Session;
}
......@@ -15,6 +15,7 @@ export interface HotelAdmin extends User {
}
export type UserRol = 'ADMIN' | 'CLIENT' | 'HOTEL_ADMIN';
export const UserRolesArray: UserRol[] = ['CLIENT', 'HOTEL_ADMIN', 'ADMIN'];
export type UserStateFilter = 'All' | UserState;
......
export * from './User.interface';
export * from './Address.interface';
export * from './Hotel.interface';
export * from './Room.interface';
export * from './Room.interface';
export * from './Booking.interface';
export * from './User.interface';
export * from './Session.interface';
export * from './Route.interface';
import { TestBed } from '@angular/core/testing';
import { AuthClientService } from './auth-client.service';
import { Session } from '@core/models';
describe('AuthClientService', () => {
let service: AuthClientService;
let s: Session;
beforeEach(() => {
TestBed.configureTestingModule({});
......
import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import { environment } from '../../../../../environments/environment';
import { HttpClient } from '@angular/common/http';
@Injectable({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment