aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
115 lines (112 loc) • 3.4 kB
JavaScript
import * as jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';
import { z } from 'zod';
z.object({
id: z.string(),
email: z.string().email(),
name: z.string(),
role: z.enum(['user', 'admin', 'developer']),
permissions: z.array(z.string()),
createdAt: z.date(),
lastLogin: z.date().optional(),
metadata: z.record(z.any()).optional()
});
const TokenPayloadSchema = z.object({
userId: z.string(),
email: z.string(),
role: z.enum(['user', 'admin', 'developer']),
permissions: z.array(z.string()),
iat: z.number().optional(),
exp: z.number().optional()
});
class AuthService {
constructor(config) {
this.config = {
jwtSecret: config?.jwtSecret || process.env.JWT_SECRET || 'default-secret-change-in-production',
jwtExpiresIn: config?.jwtExpiresIn || '1h',
refreshTokenExpiresIn: config?.refreshTokenExpiresIn || '7d',
bcryptRounds: config?.bcryptRounds || 10
};
}
async hashPassword(password) {
return bcrypt.hash(password, this.config.bcryptRounds);
}
async verifyPassword(password, hash) {
return bcrypt.compare(password, hash);
}
generateAccessToken(user) {
const payload = {
userId: user.id,
email: user.email,
role: user.role,
permissions: user.permissions
};
const signOptions = {
expiresIn: this.config.jwtExpiresIn
};
return jwt.sign(payload, this.config.jwtSecret, signOptions);
}
generateRefreshToken(userId) {
const opts = {
expiresIn: this.config.refreshTokenExpiresIn
};
return jwt.sign({
userId,
type: 'refresh'
}, this.config.jwtSecret, opts);
}
verifyToken(token) {
try {
const decoded = jwt.verify(token, this.config.jwtSecret);
return TokenPayloadSchema.parse(decoded);
} catch (error) {
if (error instanceof jwt.TokenExpiredError) {
throw new AuthError('Token expired', 'TOKEN_EXPIRED', 401);
}
if (error instanceof jwt.JsonWebTokenError) {
throw new AuthError('Invalid token', 'INVALID_TOKEN', 401);
}
throw error;
}
}
decodeToken(token) {
try {
const decoded = jwt.decode(token);
if (!decoded) return null;
return TokenPayloadSchema.parse(decoded);
} catch {
return null;
}
}
hasPermission(user, permission) {
if (user.role === 'admin') return true;
return user.permissions.includes(permission);
}
hasAnyPermission(user, permissions) {
if (user.role === 'admin') return true;
return permissions.some(permission => user.permissions.includes(permission));
}
hasAllPermissions(user, permissions) {
if (user.role === 'admin') return true;
return permissions.every(permission => user.permissions.includes(permission));
}
generateApiKey() {
const timestamp = Date.now().toString(36);
const randomString = Math.random().toString(36).substring(2, 15);
const randomString2 = Math.random().toString(36).substring(2, 15);
return `ak_${timestamp}${randomString}${randomString2}`;
}
validateApiKey(apiKey) {
return /^ak_[a-z0-9]{20,}$/.test(apiKey);
}
}
class AuthError extends Error {
constructor(message, code, statusCode = 401) {
super(message);
this.code = code;
this.statusCode = statusCode;
this.name = 'AuthError';
}
}
export { AuthError, AuthService, TokenPayloadSchema };
//# sourceMappingURL=auth-service.js.map