UNPKG

tryaii-mcp-server

Version:

TryAII MCP Server - 15+ AI models with comparison, cost tracking, and collective intelligence

106 lines 4.33 kB
import * as bcrypt from 'bcryptjs'; import { logger } from '../utils/logger.js'; import { databaseService } from './database.js'; import { UserApiKeySchema, UserSchema } from '../models/existing/ExistingModels.js'; export class AuthenticationService { static instance; UserApiKeyModel; UserModel; constructor() { } static getInstance() { if (!AuthenticationService.instance) { AuthenticationService.instance = new AuthenticationService(); } return AuthenticationService.instance; } async initialize() { try { const mainConnection = databaseService.getMainConnection(); this.UserApiKeyModel = mainConnection.model('UserApiKey', UserApiKeySchema); this.UserModel = mainConnection.model('User', UserSchema); logger.info('Authentication Service initialized successfully'); } catch (error) { logger.error('Failed to initialize Authentication Service', { error }); throw error; } } async authenticateApiKey(apiKey) { try { const startTime = Date.now(); // Extract key prefix for faster lookup const keyPrefix = apiKey.substring(0, 8); // Find API key by prefix first (indexed field) const apiKeyDoc = await this.UserApiKeyModel.findOne({ keyPrefix, isActive: true }).lean(); if (!apiKeyDoc) { logger.warn('API key not found or inactive', { keyPrefix }); return null; } // Verify the full key hash const isValidKey = await bcrypt.compare(apiKey, apiKeyDoc.keyHash); if (!isValidKey) { logger.warn('Invalid API key hash', { keyPrefix, userId: apiKeyDoc.userId }); return null; } // Get user details const user = await this.UserModel.findById(apiKeyDoc.userId).lean(); if (!user || !user.isActive) { logger.warn('User not found or inactive', { userId: apiKeyDoc.userId }); return null; } // Update last used timestamp (fire and forget) this.UserApiKeyModel.updateOne({ _id: apiKeyDoc._id }, { lastUsed: new Date() }).exec().catch((error) => logger.warn('Failed to update API key last used', { error })); const authTime = Date.now() - startTime; logger.debug('API key authenticated successfully', { userId: user._id, keyPrefix, authTime: `${authTime}ms` }); return { userId: user._id, apiKeyId: apiKeyDoc.keyId, keyPrefix: apiKeyDoc.keyPrefix, permissions: apiKeyDoc.permissions, user: { email: user.email, name: user.name, balance: { currentAmount: user.balance?.currentAmount || 0, currency: user.balance?.currency || 'USD' } } }; } catch (error) { logger.error('Authentication error', { error }); return null; } } async hasPermission(user, requiredPermission) { return user.permissions.includes(requiredPermission); } async validatePermissions(user, requiredPermissions) { return requiredPermissions.every(permission => user.permissions.includes(permission)); } // Utility method to get fresh user balance async getUserBalance(userId) { try { const user = await this.UserModel.findById(userId).lean(); return user?.balance?.currentAmount || 0; } catch (error) { logger.error('Failed to get user balance', { userId, error }); return 0; } } // Utility method to check if user has sufficient balance async hasSufficientBalance(userId, requiredAmount) { const currentBalance = await this.getUserBalance(userId); return currentBalance >= requiredAmount; } } export const authenticationService = AuthenticationService.getInstance(); //# sourceMappingURL=AuthenticationService.js.map