stratakit
Version:
stratakit - Meta-framework React puro con Auto Router automático, file-based routing, SEO automático y performance superior
274 lines (273 loc) • 8.03 kB
JavaScript
export class GuardManager {
guards = new Map();
/**
* Registrar guard
*/
register(name, guard) {
this.guards.set(name, guard);
}
/**
* Ejecutar guards para una ruta
*/
async execute(route, context) {
const guardNames = route.guards || [];
for (const guardName of guardNames) {
const guard = this.guards.get(guardName);
if (!guard) {
console.warn(`Guard '${guardName}' not found for route '${route.path}'`);
continue;
}
try {
const result = await guard(context);
if (!result.canActivate) {
return result;
}
}
catch (error) {
console.error(`Error executing guard '${guardName}':`, error);
return {
canActivate: false,
reason: `Guard error: ${error instanceof Error ? error.message : 'Unknown error'}`
};
}
}
return { canActivate: true };
}
/**
* Obtener guard por nombre
*/
get(name) {
return this.guards.get(name);
}
/**
* Listar todos los guards
*/
list() {
return Array.from(this.guards.keys());
}
/**
* Eliminar guard
*/
remove(name) {
return this.guards.delete(name);
}
}
// Instancia global del manager
export const guardManager = new GuardManager();
// ============================================================================
// GUARDS PREDEFINIDOS
// ============================================================================
/**
* Guard de autenticación
*/
export const authGuard = async (context) => {
if (!context.isAuthenticated) {
return {
canActivate: false,
redirect: '/login',
reason: 'Authentication required'
};
}
return { canActivate: true };
};
/**
* Guard de autorización
*/
export const createPermissionGuard = (requiredPermissions) => {
return async (context) => {
const hasPermission = requiredPermissions.every(permission => context.permissions.includes(permission));
if (!hasPermission) {
return {
canActivate: false,
redirect: '/unauthorized',
reason: 'Insufficient permissions'
};
}
return { canActivate: true };
};
};
/**
* Guard de roles
*/
export const createRoleGuard = (requiredRoles) => {
return async (context) => {
const userRoles = context.user?.roles || [];
const hasRole = requiredRoles.some(role => userRoles.includes(role));
if (!hasRole) {
return {
canActivate: false,
redirect: '/unauthorized',
reason: 'Insufficient role privileges'
};
}
return { canActivate: true };
};
};
/**
* Guard de verificación de email
*/
export const emailVerificationGuard = async (context) => {
if (context.user && !context.user.emailVerified) {
return {
canActivate: false,
redirect: '/verify-email',
reason: 'Email verification required'
};
}
return { canActivate: true };
};
/**
* Guard de términos y condiciones
*/
export const termsGuard = async (context) => {
if (context.user && !context.user.termsAccepted) {
return {
canActivate: false,
redirect: '/terms',
reason: 'Terms and conditions must be accepted'
};
}
return { canActivate: true };
};
/**
* Guard de mantenimiento
*/
export const maintenanceGuard = async (context) => {
const isMaintenanceMode = false; // Simplified for browser environment
if (isMaintenanceMode && !context.user?.isAdmin) {
return {
canActivate: false,
redirect: '/maintenance',
reason: 'Site is under maintenance'
};
}
return { canActivate: true };
};
/**
* Guard de país/región
*/
export const createCountryGuard = (allowedCountries) => {
return async (context) => {
const userCountry = context.user?.country || context.headers['cf-ipcountry'] || 'US';
if (!allowedCountries.includes(userCountry)) {
return {
canActivate: false,
redirect: '/unavailable',
reason: 'Service not available in your country'
};
}
return { canActivate: true };
};
};
/**
* Guard de horario
*/
export const createTimeGuard = (startHour, endHour) => {
return async (context) => {
const now = new Date();
const currentHour = now.getHours();
if (currentHour < startHour || currentHour >= endHour) {
return {
canActivate: false,
redirect: '/unavailable',
reason: 'Service not available at this time'
};
}
return { canActivate: true };
};
};
/**
* Guard de dispositivo
*/
export const createDeviceGuard = (allowedDevices) => {
return async (context) => {
const userAgent = context.headers['user-agent'] || '';
let deviceType = 'desktop';
if (/Mobile|Android|iPhone/i.test(userAgent)) {
deviceType = 'mobile';
}
else if (/Tablet|iPad/i.test(userAgent)) {
deviceType = 'tablet';
}
if (!allowedDevices.includes(deviceType)) {
return {
canActivate: false,
redirect: '/unsupported-device',
reason: 'Device not supported'
};
}
return { canActivate: true };
};
};
/**
* Guard de versión de app
*/
export const createVersionGuard = (minVersion) => {
return async (context) => {
const appVersion = context.headers['x-app-version'] || '1.0.0';
if (compareVersions(appVersion, minVersion) < 0) {
return {
canActivate: false,
redirect: '/update-required',
reason: 'App update required'
};
}
return { canActivate: true };
};
};
/**
* Guard de datos de usuario
*/
export const userDataGuard = async (context) => {
if (context.user && !context.user.profileComplete) {
return {
canActivate: false,
redirect: '/complete-profile',
reason: 'Profile completion required'
};
}
return { canActivate: true };
};
/**
* Guard de suscripción
*/
export const createSubscriptionGuard = (requiredPlan) => {
return async (context) => {
const userPlan = context.user?.subscription?.plan;
if (!userPlan || userPlan !== requiredPlan) {
return {
canActivate: false,
redirect: '/upgrade',
reason: 'Subscription upgrade required'
};
}
return { canActivate: true };
};
};
// ============================================================================
// UTILIDADES
// ============================================================================
/**
* Comparar versiones
*/
function compareVersions(version1, version2) {
const v1Parts = version1.split('.').map(Number);
const v2Parts = version2.split('.').map(Number);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
for (let i = 0; i < maxLength; i++) {
const v1Part = v1Parts[i] || 0;
const v2Part = v2Parts[i] || 0;
if (v1Part > v2Part)
return 1;
if (v1Part < v2Part)
return -1;
}
return 0;
}
// Registrar guards predefinidos
guardManager.register('auth', authGuard);
guardManager.register('emailVerification', emailVerificationGuard);
guardManager.register('terms', termsGuard);
guardManager.register('maintenance', maintenanceGuard);
guardManager.register('userData', userDataGuard);
export default guardManager;