mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-12 02:18:18 +00:00
feat: session lock stores IP + timestamp for debugging
- SessionService stores JSON { memberId, ip, lockedAt } instead of plain memberId
- Auth controller extracts client IP from x-forwarded-for header
- Lockout error message includes IP of blocking device
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Controller, Post, Body, Headers, Logger, HttpException } from '@nestjs/common';
|
||||
import { Controller, Post, Body, Headers, Req, Logger, HttpException } from '@nestjs/common';
|
||||
import type { Request } from 'express';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import axios from 'axios';
|
||||
import { OzonetelAgentService } from '../ozonetel/ozonetel-agent.service';
|
||||
@@ -24,7 +25,7 @@ export class AuthController {
|
||||
}
|
||||
|
||||
@Post('login')
|
||||
async login(@Body() body: { email: string; password: string }) {
|
||||
async login(@Body() body: { email: string; password: string }, @Req() req: Request) {
|
||||
this.logger.log(`Login attempt for ${body.email}`);
|
||||
|
||||
try {
|
||||
@@ -128,13 +129,15 @@ export class AuthController {
|
||||
}
|
||||
|
||||
// Check for duplicate login — strict: one device only
|
||||
const existingSession = await this.sessionService.isSessionLocked(agentConfig.ozonetelAgentId);
|
||||
const clientIp = (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim() ?? req.ip ?? 'unknown';
|
||||
const existingSession = await this.sessionService.getSession(agentConfig.ozonetelAgentId);
|
||||
if (existingSession) {
|
||||
throw new HttpException('You are already logged in on another device. Please log out there first.', 409);
|
||||
this.logger.warn(`Duplicate login blocked for ${body.email} — session held by IP ${existingSession.ip} since ${existingSession.lockedAt}`);
|
||||
throw new HttpException(`You are already logged in from another device (${existingSession.ip}). Please log out there first.`, 409);
|
||||
}
|
||||
|
||||
// Lock session in Redis
|
||||
await this.sessionService.lockSession(agentConfig.ozonetelAgentId, memberId);
|
||||
// Lock session in Redis with IP
|
||||
await this.sessionService.lockSession(agentConfig.ozonetelAgentId, memberId, clientIp);
|
||||
|
||||
// Login to Ozonetel with agent-specific credentials
|
||||
const ozAgentPassword = process.env.OZONETEL_AGENT_PASSWORD ?? 'Test123$';
|
||||
|
||||
Reference in New Issue
Block a user