bb-inspired
Version:
Core library for BB-inspired NestJS backend
198 lines • 7.56 kB
JavaScript
;
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 __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var JwtService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.JwtService = void 0;
const common_1 = require("@nestjs/common");
const jwt_1 = require("@nestjs/jwt");
const logger_1 = require("../../utils/logger");
const fs = require("fs");
const path = require("path");
let JwtService = JwtService_1 = class JwtService {
constructor(options, jwtService) {
this.options = options;
this.jwtService = jwtService;
this.logger = new logger_1.AppLogger(JwtService_1.name);
}
async generateToken(payload) {
return this.jwtService.sign(payload);
}
async generateRefreshToken(payload) {
return this.jwtService.sign({ ...payload, type: 'refresh' }, {
expiresIn: this.options.jwt.refreshExpiresIn || '7d',
});
}
async generateTokenResponse(payload) {
const accessToken = await this.generateToken({
...payload,
type: 'access',
sub: payload.sub
});
const refreshToken = await this.generateRefreshToken(payload);
let expiresIn;
if (typeof this.options.jwt.expiresIn === 'string') {
const match = this.options.jwt.expiresIn.match(/^(\d+)([smhd])$/);
if (match) {
const value = parseInt(match[1], 10);
const unit = match[2];
switch (unit) {
case 's':
expiresIn = value;
break;
case 'm':
expiresIn = value * 60;
break;
case 'h':
expiresIn = value * 60 * 60;
break;
case 'd':
expiresIn = value * 60 * 60 * 24;
break;
default: expiresIn = 3600;
}
}
else {
expiresIn = 3600;
}
}
else {
expiresIn = typeof this.options.jwt.expiresIn === 'number'
? this.options.jwt.expiresIn
: 3600;
}
return {
accessToken,
refreshToken,
expiresIn,
tokenType: 'Bearer',
};
}
async verifyToken(token) {
try {
return this.jwtService.verify(token);
}
catch (error) {
this.logger.error(`Token verification failed: ${error.message}`);
throw error;
}
}
decodeToken(token) {
return this.jwtService.decode(token);
}
async refreshAccessToken(refreshToken) {
try {
const payload = await this.verifyToken(refreshToken);
if (payload.type !== 'refresh') {
throw new Error('Invalid token type');
}
const { type, exp, iat, ...newPayload } = payload;
return this.generateTokenResponse(newPayload);
}
catch (error) {
this.logger.error(`Token refresh failed: ${error.message}`);
throw error;
}
}
async exportUserTokens(userId, exportPath) {
this.logger.verbose(`Exporting tokens for user ${userId}`);
const userTokens = await this.getUserTokens(userId);
const exportData = {
accessTokens: userTokens.accessTokens || [],
refreshTokens: userTokens.refreshTokens || [],
metadata: {
exportedAt: new Date().toISOString(),
version: '1.0'
}
};
if (exportPath) {
try {
const dirPath = path.dirname(exportPath);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
fs.writeFileSync(exportPath, JSON.stringify(exportData, null, 2));
this.logger.verbose(`Tokens successfully exported to ${exportPath}`);
}
catch (error) {
this.logger.error(`Failed to export tokens to file: ${error.message}`, error.stack);
}
}
return exportData;
}
async importUserTokens(importData) {
var _a;
try {
let tokenData;
if (typeof importData === 'string') {
if (!fs.existsSync(importData)) {
this.logger.error(`Import file not found: ${importData}`);
return false;
}
const fileContent = fs.readFileSync(importData, 'utf8');
tokenData = JSON.parse(fileContent);
}
else {
tokenData = importData;
}
if (!tokenData.accessTokens || !Array.isArray(tokenData.accessTokens)) {
this.logger.error('Invalid import data: accessTokens missing or not an array');
return false;
}
this.logger.verbose(`Imported ${tokenData.accessTokens.length} access tokens and ${((_a = tokenData.refreshTokens) === null || _a === void 0 ? void 0 : _a.length) || 0} refresh tokens`);
return true;
}
catch (error) {
this.logger.error(`Failed to import tokens: ${error.message}`, error.stack);
return false;
}
}
async getUserTokens(userId) {
return {
accessTokens: [],
refreshTokens: []
};
}
async generateWsToken(payload) {
const jwtPayload = {
sub: payload.userId,
connectionId: payload.connectionId,
type: 'websocket'
};
const wsTokenOptions = {
expiresIn: this.options.jwt.expiresIn || '1h',
subject: `ws:${payload.userId}`
};
return this.jwtService.sign(jwtPayload, wsTokenOptions);
}
async verifyWsToken(token) {
try {
const payload = await this.jwtService.verify(token);
if (payload.type !== 'websocket') {
throw new Error('Invalid token type for WebSocket authentication');
}
return payload;
}
catch (error) {
this.logger.error(`WebSocket token verification failed: ${error.message}`, error.stack);
throw error;
}
}
};
exports.JwtService = JwtService;
exports.JwtService = JwtService = JwtService_1 = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, common_1.Inject)('AUTH_OPTIONS')),
__metadata("design:paramtypes", [Object, jwt_1.JwtService])
], JwtService);
//# sourceMappingURL=jwt.service.js.map