Merge remote-tracking branch 'origin/main' into backend_complete
This commit is contained in:
@@ -21,6 +21,10 @@ export class UserMapper {
|
||||
fname: user.fname,
|
||||
lname: user.lname,
|
||||
code: user.token,
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
type: user.type,
|
||||
>>>>>>> origin/main
|
||||
phone: user.phone,
|
||||
state: user.state,
|
||||
};
|
||||
|
||||
@@ -24,6 +24,10 @@ export interface DetailUserDto {
|
||||
fname: string;
|
||||
lname: string;
|
||||
code: string | null;
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
type: string;
|
||||
>>>>>>> origin/main
|
||||
phone: string | null;
|
||||
state: number;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
export interface UpdateDeckCommand {
|
||||
id: string;
|
||||
<<<<<<< HEAD
|
||||
userstate?: number;
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
name?: string;
|
||||
type?: number;
|
||||
userid?: string;
|
||||
|
||||
@@ -2,13 +2,17 @@ import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
|
||||
import { UpdateDeckCommand } from './UpdateDeckCommand';
|
||||
import { ShortDeckDto } from '../../DTOs/DeckDto';
|
||||
import { DeckMapper } from '../../DTOs/Mappers/DeckMapper';
|
||||
<<<<<<< HEAD
|
||||
import { DeckAggregate } from '../../../Domain/Deck/DeckAggregate';
|
||||
import { logError } from '../../Services/Logger';
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
|
||||
export class UpdateDeckCommandHandler {
|
||||
constructor(private readonly deckRepo: IDeckRepository) {}
|
||||
|
||||
async execute(cmd: UpdateDeckCommand): Promise<ShortDeckDto | null> {
|
||||
<<<<<<< HEAD
|
||||
if(cmd.state !== undefined && cmd.userstate!==1) {
|
||||
throw new Error('Only admin users can change deck state');
|
||||
}
|
||||
@@ -46,5 +50,10 @@ export class UpdateDeckCommandHandler {
|
||||
logError(`Error updating deck: ${cmd.id}`, error);
|
||||
throw error;
|
||||
}
|
||||
=======
|
||||
const updated = await this.deckRepo.update(cmd.id, { ...cmd });
|
||||
if (!updated) return null;
|
||||
return DeckMapper.toShortDto(updated);
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
import { IDeckRepository } from '../../../Domain/IRepository/IDeckRepository';
|
||||
import { GetDeckByIdQuery } from './GetDeckByIdQuery';
|
||||
<<<<<<< HEAD
|
||||
import { DetailDeckDto } from '../../DTOs/DeckDto';
|
||||
=======
|
||||
import { ShortDeckDto } from '../../DTOs/DeckDto';
|
||||
>>>>>>> origin/main
|
||||
import { DeckMapper } from '../../DTOs/Mappers/DeckMapper';
|
||||
|
||||
export class GetDeckByIdQueryHandler {
|
||||
constructor(private readonly deckRepo: IDeckRepository) {}
|
||||
|
||||
<<<<<<< HEAD
|
||||
async execute(query: GetDeckByIdQuery): Promise<DetailDeckDto | null> {
|
||||
const deck = await this.deckRepo.findById(query.id);
|
||||
if (!deck) return null;
|
||||
return DeckMapper.toDetailDto(deck);
|
||||
=======
|
||||
async execute(query: GetDeckByIdQuery): Promise<ShortDeckDto | null> {
|
||||
const deck = await this.deckRepo.findById(query.id);
|
||||
if (!deck) return null;
|
||||
return DeckMapper.toShortDto(deck);
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ export class GeneralSearchService implements IGeneralSearchService {
|
||||
};
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Ensure limit is at least 1 to prevent database issues
|
||||
const effectiveLimit = Math.max(limit || 20, 1);
|
||||
const effectiveOffset = Math.max(offset || 0, 0);
|
||||
@@ -57,6 +58,12 @@ export class GeneralSearchService implements IGeneralSearchService {
|
||||
const { users, totalCount } = await this.userRepo.search(query.trim(), effectiveLimit, effectiveOffset);
|
||||
const results = users.map(user => UserMapper.toShortDto(user));
|
||||
const hasMore = (effectiveOffset + effectiveLimit) < totalCount;
|
||||
=======
|
||||
try {
|
||||
const { users, totalCount } = await this.userRepo.search(query.trim(), limit, offset);
|
||||
const results = users.map(user => UserMapper.toShortDto(user));
|
||||
const hasMore = (offset + limit) < totalCount;
|
||||
>>>>>>> origin/main
|
||||
|
||||
return {
|
||||
results,
|
||||
@@ -109,6 +116,7 @@ export class GeneralSearchService implements IGeneralSearchService {
|
||||
};
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Ensure limit is at least 1 to prevent database issues
|
||||
const effectiveLimit = Math.max(limit || 20, 1);
|
||||
const effectiveOffset = Math.max(offset || 0, 0);
|
||||
@@ -128,6 +136,19 @@ export class GeneralSearchService implements IGeneralSearchService {
|
||||
} catch (error) {
|
||||
throw new Error('Failed to search decks');
|
||||
}
|
||||
=======
|
||||
const { decks, totalCount } = await this.deckRepo.search(query.trim(), limit, offset);
|
||||
const results = decks.map(deck => DeckMapper.toShortDto(deck));
|
||||
const hasMore = (offset + limit) < totalCount;
|
||||
|
||||
return {
|
||||
results,
|
||||
totalCount,
|
||||
hasMore,
|
||||
searchQuery: query,
|
||||
searchType: 'decks'
|
||||
};
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
|
||||
async searchByType(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { JWTService } from './JWTService';
|
||||
<<<<<<< HEAD
|
||||
import { RedisService } from './RedisService';
|
||||
import { logAuth, logWarning } from './Logger';
|
||||
|
||||
@@ -143,4 +144,60 @@ export async function adminRequired(req: Request, res: Response, next: NextFunct
|
||||
logWarning('Admin authentication middleware error', { error: (error as Error).message }, req);
|
||||
return res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
=======
|
||||
import { logAuth, logWarning } from './Logger';
|
||||
|
||||
export const jwtService = new JWTService();
|
||||
|
||||
export function authRequired(req: Request, res: Response, next: NextFunction) {
|
||||
const payload = jwtService.verify(req);
|
||||
if (!payload) {
|
||||
logAuth('Authentication failed - No valid token', undefined, {
|
||||
ip: req.ip,
|
||||
userAgent: req.get ? req.get('User-Agent') : 'unknown',
|
||||
path: req.path
|
||||
}, req);
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
logAuth('Authentication successful', payload.userId, {
|
||||
authLevel: payload.authLevel,
|
||||
orgId: payload.orgId
|
||||
}, req);
|
||||
|
||||
const refreshed = jwtService.refreshIfNeeded(payload, res);
|
||||
if (refreshed) {
|
||||
logAuth('Token refreshed', payload.userId, undefined, req);
|
||||
}
|
||||
|
||||
(req as any).user = payload;
|
||||
next();
|
||||
}
|
||||
|
||||
export function adminRequired(req: Request, res: Response, next: NextFunction) {
|
||||
const payload = jwtService.verify(req);
|
||||
if (!payload || payload.authLevel !== 1) {
|
||||
logWarning('Admin access denied', {
|
||||
hasPayload: !!payload,
|
||||
authLevel: payload?.authLevel,
|
||||
userId: payload?.userId,
|
||||
ip: req.ip,
|
||||
path: req.path
|
||||
}, req);
|
||||
return res.status(403).json({ error: 'Forbidden' });
|
||||
}
|
||||
|
||||
logAuth('Admin authentication successful', payload.userId, {
|
||||
authLevel: payload.authLevel,
|
||||
orgId: payload.orgId
|
||||
}, req);
|
||||
|
||||
const refreshed = jwtService.refreshIfNeeded(payload, res);
|
||||
if (refreshed) {
|
||||
logAuth('Admin token refreshed', payload.userId, undefined, req);
|
||||
}
|
||||
|
||||
(req as any).user = payload;
|
||||
next();
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
Reference in New Issue
Block a user