qwen_2.5_model / src /modules /search /search.controller.ts
Muhammad Noman
Deploy OpenWA to Hugging Face Spaces
46252cd
Raw
History Blame Contribute Delete
2.74 kB
import { Controller, Get, Query, BadRequestException } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiQuery } from '@nestjs/swagger';
import { RequireRole, CurrentApiKey } from '../auth/decorators/auth.decorators';
import { ApiKey, ApiKeyRole } from '../auth/entities/api-key.entity';
import { SearchService } from './search.service';
import { SearchQueryDto } from './dto/search-query.dto';
import type { SearchResults } from './search.types';
@ApiTags('search')
@Controller('search')
export class SearchController {
constructor(private readonly searchService: SearchService) {}
@Get()
@RequireRole(ApiKeyRole.OPERATOR)
@ApiOperation({ summary: 'Search messages across sessions (active search provider)' })
@ApiResponse({ status: 200, description: 'Search results from the active provider' })
@ApiResponse({ status: 400, description: 'Empty or whitespace-only "q"' })
@ApiResponse({ status: 501, description: 'No search provider configured' })
@ApiQuery({ name: 'q', required: true, description: 'Search term (required, non-empty)' })
@ApiQuery({ name: 'sessionId', required: false, description: 'Restrict to a single session' })
@ApiQuery({ name: 'chatId', required: false, description: 'Restrict to a single chat id' })
@ApiQuery({ name: 'direction', required: false, description: 'incoming | outgoing' })
@ApiQuery({ name: 'type', required: false, description: 'Message type filter' })
@ApiQuery({ name: 'from', required: false, description: 'Sender filter' })
@ApiQuery({ name: 'dateFrom', required: false, description: 'Epoch-ms lower bound (inclusive)' })
@ApiQuery({ name: 'dateTo', required: false, description: 'Epoch-ms upper bound (inclusive)' })
@ApiQuery({ name: 'limit', required: false, type: Number, description: 'Max hits to return' })
@ApiQuery({ name: 'offset', required: false, type: Number, description: 'Pagination offset' })
async search(@Query() dto: SearchQueryDto, @CurrentApiKey() apiKey?: ApiKey): Promise<SearchResults> {
if (!dto.q || !dto.q.trim()) {
throw new BadRequestException('Query parameter "q" is required and must be non-empty.');
}
// callerSessionIds comes ONLY from the authenticated key's allowedSessions — never from the
// query/body — so a scoped key cannot broaden its reach. A null/empty allowlist (e.g. ADMIN)
// resolves to undefined → searches all sessions, mirroring GET /webhooks. The DTO carries no
// `sessionIds` field (the global ValidationPipe's forbidNonWhitelisted would reject it anyway),
// and SearchService makes scope authoritative by overwriting sessionIds at the provider boundary.
return this.searchService.search(dto, apiKey?.allowedSessions ?? undefined);
}
}