@wikiccu/nest-auth
Version:
A comprehensive authentication package for NestJS applications with Prisma and PostgreSQL
253 lines • 9.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenService = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const prisma_service_1 = require("./prisma.service");
const jwt_1 = require("@nestjs/jwt");
const crypto = __importStar(require("crypto"));
let TokenService = class TokenService {
prisma;
jwtService;
configService;
constructor(prisma, jwtService, configService) {
this.prisma = prisma;
this.jwtService = jwtService;
this.configService = configService;
}
async generateRefreshToken(userId, rememberMe = false) {
const token = crypto.randomBytes(32).toString('hex');
const expiresIn = rememberMe
? this.configService.get('REFRESH_TOKEN_EXPIRES_IN_REMEMBER', '30d')
: this.configService.get('REFRESH_TOKEN_EXPIRES_IN', '7d');
const expiresAt = this.calculateExpirationDate(expiresIn);
await this.prisma.refreshToken.create({
data: {
userId,
token,
expiresAt,
},
});
return token;
}
async verifyRefreshToken(token) {
const refreshToken = await this.prisma.refreshToken.findUnique({
where: { token },
});
if (!refreshToken || refreshToken.isRevoked || refreshToken.expiresAt < new Date()) {
return null;
}
return { userId: refreshToken.userId };
}
async rotateRefreshToken(oldToken, userId) {
await this.revokeRefreshToken(oldToken);
return this.generateRefreshToken(userId);
}
async revokeRefreshToken(token) {
await this.prisma.refreshToken.updateMany({
where: { token },
data: { isRevoked: true },
});
}
async revokeAllRefreshTokens(userId) {
await this.prisma.refreshToken.updateMany({
where: { userId },
data: { isRevoked: true },
});
}
async generatePasswordResetToken(userId) {
const token = crypto.randomBytes(32).toString('hex');
const expiresIn = this.configService.get('PASSWORD_RESET_TOKEN_EXPIRES_IN', '1h');
const expiresAt = this.calculateExpirationDate(expiresIn);
await this.prisma.passwordResetToken.updateMany({
where: { userId },
data: { isUsed: true },
});
await this.prisma.passwordResetToken.create({
data: {
userId,
token,
expiresAt,
},
});
return token;
}
async verifyPasswordResetToken(token) {
const resetToken = await this.prisma.passwordResetToken.findUnique({
where: { token },
});
if (!resetToken || resetToken.isUsed || resetToken.expiresAt < new Date()) {
return null;
}
return { userId: resetToken.userId };
}
async generateEmailVerificationToken(userId) {
const token = crypto.randomBytes(32).toString('hex');
const expiresIn = this.configService.get('EMAIL_VERIFICATION_TOKEN_EXPIRES_IN', '24h');
const expiresAt = this.calculateExpirationDate(expiresIn);
await this.prisma.emailVerificationToken.updateMany({
where: { userId },
data: { isUsed: true },
});
await this.prisma.emailVerificationToken.create({
data: {
userId,
token,
expiresAt,
},
});
return token;
}
async verifyEmailVerificationToken(token) {
const verificationToken = await this.prisma.emailVerificationToken.findUnique({
where: { token },
});
if (!verificationToken || verificationToken.isUsed || verificationToken.expiresAt < new Date()) {
return null;
}
return { userId: verificationToken.userId };
}
async createSession(userId, token, sessionInfo) {
const expiresIn = this.configService.get('SESSION_EXPIRES_IN', '24h');
const expiresAt = this.calculateExpirationDate(expiresIn);
await this.prisma.session.create({
data: {
userId,
token,
ipAddress: sessionInfo.ipAddress,
userAgent: sessionInfo.userAgent,
expiresAt,
},
});
}
async getUserSessions(userId) {
return this.prisma.session.findMany({
where: {
userId,
isActive: true,
expiresAt: {
gt: new Date(),
},
},
orderBy: { createdAt: 'desc' },
});
}
async revokeSession(sessionId) {
await this.prisma.session.update({
where: { id: sessionId },
data: { isActive: false },
});
}
async revokeAllSessions(userId) {
await this.prisma.session.updateMany({
where: { userId },
data: { isActive: false },
});
}
async cleanupExpiredTokens() {
const now = new Date();
await Promise.all([
this.prisma.refreshToken.deleteMany({
where: {
OR: [
{ expiresAt: { lt: now } },
{ isRevoked: true },
],
},
}),
this.prisma.passwordResetToken.deleteMany({
where: {
OR: [
{ expiresAt: { lt: now } },
{ isUsed: true },
],
},
}),
this.prisma.emailVerificationToken.deleteMany({
where: {
OR: [
{ expiresAt: { lt: now } },
{ isUsed: true },
],
},
}),
this.prisma.session.deleteMany({
where: {
OR: [
{ expiresAt: { lt: now } },
{ isActive: false },
],
},
}),
]);
}
calculateExpirationDate(duration) {
const match = duration.match(/^(\d+)([mhd])$/);
if (!match) {
throw new Error(`Invalid duration format: ${duration}`);
}
const [, value, unit] = match;
const numValue = parseInt(value, 10);
const now = new Date();
switch (unit) {
case 'm':
return new Date(now.getTime() + numValue * 60 * 1000);
case 'h':
return new Date(now.getTime() + numValue * 60 * 60 * 1000);
case 'd':
return new Date(now.getTime() + numValue * 24 * 60 * 60 * 1000);
default:
throw new Error(`Invalid duration unit: ${unit}`);
}
}
};
exports.TokenService = TokenService;
exports.TokenService = TokenService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
jwt_1.JwtService,
config_1.ConfigService])
], TokenService);
//# sourceMappingURL=token.service.js.map