roaming-studios-auth
v1.0.0
Published
Package compartido para funcionalidad de Firebase/Firestore (leads, usuarios, content access).
Downloads
5
Readme
roaming-studios-auth
Package compartido para funcionalidad de Firebase/Firestore (leads, usuarios, content access).
Instalación
El package se instala automáticamente como workspace dependency. Agregar en package.json de la app:
{
"dependencies": {
"roaming-studios-auth": "workspace:*"
}
}Configuración
El package usa Firebase Admin SDK en el servidor (bypass reglas de seguridad). Cada app debe configurar las credenciales del service account en .env.local.
Opción 1: Service Account Key como JSON string (Recomendado)
FIREBASE_SERVICE_ACCOUNT_KEY={"type":"service_account","project_id":"tu-project-id",...}Opción 2: Ruta al archivo del Service Account
FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account-key.jsonOpción 3: Variables individuales
FIREBASE_PROJECT_ID=tu_project_id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@tu-proyecto.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"Opción 4: Application Default Credentials (ADC) - Para cuando no puedes generar service account keys
Si las políticas de tu organización bloquean la creación de service account keys, puedes usar ADC:
Instala Google Cloud CLI (si no lo tienes):
# macOS brew install google-cloud-sdkAutentica con tu cuenta:
gcloud auth application-default loginConfigura solo el project ID en
.env.local:FIREBASE_PROJECT_ID=prana-pulse-a67dd
El código detectará automáticamente las credenciales de ADC.
Cómo obtener las credenciales
Para Service Account Keys (Opciones 1-3):
- Ve a Firebase Console
- Selecciona tu proyecto
- Ve a Project Settings → Service Accounts
- Haz clic en Generate New Private Key
- Descarga el archivo JSON
- Opción 1: Copia el contenido completo del JSON y pégalo como string en
FIREBASE_SERVICE_ACCOUNT_KEY - Opción 2: Guarda el archivo y usa su ruta en
FIREBASE_SERVICE_ACCOUNT_PATH - Opción 3: Extrae
project_id,client_emailyprivate_keydel JSON
⚠️ Importante: Nunca commitees el archivo JSON del service account. Agrégalo a .gitignore.
Si no puedes generar keys (Opción 4 - ADC):
- Usa
gcloud auth application-default login(requiere tener acceso al proyecto en Google Cloud) - Solo necesitas configurar
FIREBASE_PROJECT_ID
Uso
Firestore Server (Admin SDK)
import { getFirestoreServer } from 'roaming-studios-auth/firestoreServer';
// En API routes (server-side)
// Usa Firebase Admin SDK - bypass reglas de seguridad
const db = getFirestoreServer();Users Service (Cliente-side)
import {
createUser,
getUser,
updateUser,
updateUserSubscription,
updateUserRole
} from 'roaming-studios-auth/users/usersService';
import type { CreateUserInput, BaseUser } from 'roaming-studios-auth/users/types';
// Crear usuario (ejecutar en CLIENTE)
const { user, userData } = await createUser({
email: '[email protected]',
name: 'Juan Pérez',
password: 'password123',
source: 'contact-form',
});
// Obtener usuario
const userData = await getUser(user.uid);
// Actualizar usuario
await updateUser(user.uid, {
subscription: 'premium',
role: 'user',
});⚠️ IMPORTANTE: El servicio de usuarios debe ejecutarse en el CLIENTE (navegador), no en el servidor. Usa Firebase Client SDK que requiere autenticación.
Leads Service (Server-side con Admin SDK)
import {
createLead,
getLeads,
getLeadById,
updateLeadStatus
} from 'roaming-studios-auth/leads/leadsService';
import type { Lead, CreateLeadInput } from 'roaming-studios-auth/leads/types';
// Crear lead (ejecutar en SERVIDOR - API routes)
const lead = await createLead({
email: '[email protected]',
name: 'Juan Pérez',
source: 'contact-form',
});
// Obtener leads
const allLeads = await getLeads();
const newLeads = await getLeads({ status: 'new' });
// Actualizar estado
await updateLeadStatus(lead.id, 'contacted');API Reference
getFirestoreServer()
Obtiene la instancia de Firestore para uso en servidor. Lee las env vars automáticamente.
createLead(input: CreateLeadInput)
Crea un nuevo lead. Si ya existe un lead con el mismo email, actualiza el existente.
getLeads(filters?: LeadFilters)
Obtiene leads con filtros opcionales. Ordenados por fecha (más recientes primero).
getLeadById(leadId: string)
Obtiene un lead específico por ID.
updateLead(leadId: string, input: UpdateLeadInput)
Actualiza un lead.
updateLeadStatus(leadId: string, status: LeadStatus)
Actualiza solo el estado de un lead.
Estructura de Datos en Firestore
Colección users
users/{uid}
{
email: string (required)
name: string (required)
subscription: 'free' | 'basic' | 'premium' | 'enterprise'
role: 'lead' | 'user' | 'admin'
isActive: boolean
emailVerified: boolean
createdAt: timestamp
updatedAt: timestamp
lastLogin?: timestamp
phone?: string
avatar?: string
source?: 'signup' | 'contact-form' | 'invitation' | 'migration' | 'other'
metadata?: Record<string, any>
}Nota: Cada proyecto puede extender BaseUser con campos específicos usando TypeScript.
Colección leads (Legacy - usar users con role: 'lead' en su lugar)
leads/{leadId}
{
email: string (required, unique)
name?: string
phone?: string
source: string (default: 'contact-form')
metadata: Record<string, any>
status: 'new' | 'contacted' | 'converted' | 'archived'
createdAt: timestamp
updatedAt: timestamp
notes?: string
}Notas
Usuarios (Recomendado)
- Cliente-side: El servicio de usuarios usa Firebase Client SDK y debe ejecutarse en el navegador
- Autenticación: Crea usuarios en Firebase Auth + Firestore automáticamente
- Evolución: Los usuarios pueden evolucionar de
role: 'lead'arole: 'user'cuando compran/se registran - Reglas de Firestore: Necesitas configurar reglas que permitan escritura cuando
request.auth != null
Leads (Legacy)
- Firebase Admin SDK: El servicio de leads usa Admin SDK en servidor, que bypass las reglas de seguridad
- Seguridad: Las credenciales del service account deben estar solo en
.env.local(nunca en git) - Colección automática: Las colecciones se crean automáticamente al crear el primer documento
- Deduplicación: Los emails se normalizan a lowercase
Reglas de Firestore Recomendadas
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Usuarios: solo pueden leer/escribir su propio documento
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
// Leads: solo lectura para usuarios autenticados (si usas leads legacy)
match /leads/{leadId} {
allow read: if request.auth != null;
allow write: if false; // Solo Admin SDK puede escribir
}
}
}