Contenido del Servicio
Comando de generacion
ng g s firebase/auth
Injección de dependencias:
private router = inject(Router); Se usa para enrutar luego de la autenticación con Google.
private instancias = inject(Instancias); Se usa para acceder a las instancias de firebase.
Interfaces:
// Interfaz para el perfil público del usuario
export interface PublicUserProfile {
uid: string;
username: string;
email: string;
displayName?: string;
photoURL?: string;
bio?: string;
lastActive?: string;
createdAt: string;
userType?: 'leads' | 'clientes' | 'admin' | 'soporte'; // <--- ¡DEFINE EL TIPO DE USUARIO!
}
Creamos una interface dentro del servicio pra simplificar la estructura aunque podriamos colocarla en la carpeta de interfaces e importarla.
Estas Signals se encargan de que puedas entrar a la app con Google
// 1. La Signal privada:
Solo se usa para ESCRITURA (modificar el valor).
private userEscritura = signal<User | null | undefined>(undefined);
// 2. La Signal pública:
Solo se usa para LECTURA (consumir el valor reactivo).
public userLectura: Signal<User | null | undefined> = this.userEscritura.asReadonly();
Estas Signals se encargan de saber quien eres y que rol cumples de dentro la app según los roles identificados en el enum de Roles de la app.
Signals del usuario:
La necesidad de declarar dos Signals (userPrivate y userPublic) para el estado de autenticación en tu servicio Auth se fundamenta en un principio de diseño clave llamado Encapsulación. Esto garantiza la integridad del estado de tus clientes usuarios, asegurando que solo el servicio de autenticación pueda modificar sus credenciales.
La variable private userPrivate es la única fuente de verdad y el único punto en la aplicación donde el valor del usuario puede ser cambiado.
Responsabilidad: Su misión es la Escritura. Solo los métodos internos del servicio Auth (como loginWithGoogle o logout) pueden acceder a ella y usar las funciones de modificación (.set(), .update()).
Seguridad: Al ser private, blindamos el estado. Esto significa que si un componente o un servicio externo tuviera un error de lógica, no podría alterar ni borrar la sesión del usuario. El control total sobre cuándo y cómo cambia el usuario reside exclusivamente en el servicio Auth.
La variable public userPublic es la interfaz de consumo. Es la versión del estado que se expone al resto de la aplicación, pero con los permisos de modificación eliminados.
Mecanismo: Se crea a partir de la Signal privada utilizando el método clave .asReadonly(). Este método esencialmente elimina las funciones de escritura (.set(), .update()) de la copia pública.
Consumo: Componentes como la cabecera o las vistas de perfil solo la utilizan para la Lectura. Simplemente consultan su valor (this.auth.userPublic()) para mostrar la foto del cliente, su nombre o decidir si debe aparecer el botón "Mis Viajes con Mascota".
Reacción: Aunque no puede modificar el estado, sigue siendo una Signal y, por lo tanto, es reactiva. Cuando la userPrivate cambia, la userPublic se actualiza automáticamente, permitiendo que la interfaz reaccione a los cambios de sesión.
En resumen, la razón para tener dos Signals es separar claramente la responsabilidad:
Escribes en la privada (userPrivate): Controlas la lógica de autenticación en un lugar seguro.
Lees de la pública (userPublic): Permites que la interfaz consuma el estado de forma segura, sin riesgo de romper accidentalmente la sesión de un cliente.
Este patrón de "privado de escritura, público de lectura" es una mejor práctica que asegura la escalabilidad y la fiabilidad de tu aplicación, lo cual es vital al manejar datos sensibles de tus clientes.