Files
stack/apps/api/src/federation/query.controller.ts
Jason Woltje 72c64d2eeb
All checks were successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
fix(api): add global /api prefix to resolve frontend route mismatch (#507)
Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
2026-02-26 01:13:48 +00:00

92 lines
2.6 KiB
TypeScript

/**
* Query Controller
*
* API endpoints for federated query messages.
*/
import { Controller, Post, Get, Body, Param, Query, UseGuards, Req, Logger } from "@nestjs/common";
import { QueryService } from "./query.service";
import { AuthGuard } from "../auth/guards/auth.guard";
import { SendQueryDto, IncomingQueryDto } from "./dto/query.dto";
import type { AuthenticatedRequest } from "../common/types/user.types";
import type { QueryMessageDetails, QueryResponse } from "./types/message.types";
import type { FederationMessageStatus } from "@prisma/client";
@Controller("v1/federation")
export class QueryController {
private readonly logger = new Logger(QueryController.name);
constructor(private readonly queryService: QueryService) {}
/**
* Send a query to a remote instance
* Requires authentication
*/
@Post("query")
@UseGuards(AuthGuard)
async sendQuery(
@Req() req: AuthenticatedRequest,
@Body() dto: SendQueryDto
): Promise<QueryMessageDetails> {
if (!req.user?.workspaceId) {
throw new Error("Workspace ID not found in request");
}
this.logger.log(
`User ${req.user.id} sending query to connection ${dto.connectionId} in workspace ${req.user.workspaceId}`
);
return this.queryService.sendQuery(
req.user.workspaceId,
dto.connectionId,
dto.query,
dto.context
);
}
/**
* Handle incoming query from remote instance
* Public endpoint - no authentication required (signature-based verification)
*/
@Post("incoming/query")
async handleIncomingQuery(@Body() dto: IncomingQueryDto): Promise<QueryResponse> {
this.logger.log(`Received query from ${dto.instanceId}: ${dto.messageId}`);
return this.queryService.handleIncomingQuery(dto);
}
/**
* Get all query messages for the workspace
* Requires authentication
*/
@Get("queries")
@UseGuards(AuthGuard)
async getQueries(
@Req() req: AuthenticatedRequest,
@Query("status") status?: FederationMessageStatus
): Promise<QueryMessageDetails[]> {
if (!req.user?.workspaceId) {
throw new Error("Workspace ID not found in request");
}
return this.queryService.getQueryMessages(req.user.workspaceId, status);
}
/**
* Get a single query message
* Requires authentication
*/
@Get("queries/:id")
@UseGuards(AuthGuard)
async getQuery(
@Req() req: AuthenticatedRequest,
@Param("id") messageId: string
): Promise<QueryMessageDetails> {
if (!req.user?.workspaceId) {
throw new Error("Workspace ID not found in request");
}
return this.queryService.getQueryMessage(req.user.workspaceId, messageId);
}
}