UNPKG

bb-inspired

Version:

Core library for BB-inspired NestJS backend

198 lines 7.56 kB
"use strict"; 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