Skip to content

Commit ba993e0

Browse files
committed
Set enforcedWhereClause
1 parent 6b74ca6 commit ba993e0

File tree

4 files changed

+28
-24
lines changed

4 files changed

+28
-24
lines changed

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/route.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import { QueryHelpSidebar } from "./QueryHelpSidebar";
7373
import { QueryHistoryPopover } from "./QueryHistoryPopover";
7474
import type { AITimeFilter } from "./types";
7575
import { formatQueryStats } from "./utils";
76+
import { getLimit } from "~/services/platform.v3.server";
7677

7778
/** Convert a Date or ISO string to ISO string format */
7879
function toISOString(value: Date | string): string {
@@ -289,6 +290,16 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
289290
triggeredAtFallback = { op: "gte", value: new Date(Date.now() - periodMs) };
290291
}
291292

293+
const maxQueryPeriod = await getLimit(project.organizationId, "queryPeriodDays", 5);
294+
295+
// Force tenant isolation and time period limits
296+
const enforcedWhereClause = {
297+
organization_id: { op: "eq", value: project.organizationId },
298+
project_id: scope === "project" || scope === "environment" ? { op: "eq", value: project.id } : undefined,
299+
environment_id: scope === "environment" ? { op: "eq", value: environment.id } : undefined,
300+
triggered_at: { op: "gte", value: new Date(Date.now() - maxQueryPeriod * 24 * 60 * 60 * 1000) }
301+
} satisfies Record<string, WhereClauseCondition | undefined>;
302+
292303
try {
293304
const [error, result, queryId] = await executeQuery({
294305
name: "query-page",
@@ -301,6 +312,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
301312
projectId: project.id,
302313
environmentId: environment.id,
303314
explain,
315+
enforcedWhereClause,
304316
whereClauseFallback: {
305317
triggered_at: triggeredAtFallback,
306318
},

apps/webapp/app/services/queryService.server.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,14 @@ function getDefaultClickhouseSettings(): ClickHouseSettings {
5656

5757
export type ExecuteQueryOptions<TOut extends z.ZodSchema> = Omit<
5858
ExecuteTSQLOptions<TOut>,
59-
"tableSchema" | "organizationId" | "projectId" | "environmentId" | "fieldMappings" | "enforcedWhereClause"
59+
"tableSchema" | "fieldMappings"
6060
> & {
61+
organizationId: string;
62+
projectId?: string;
63+
environmentId?: string;
6164
tableSchema: TableSchema[];
6265
/** The scope of the query - determines tenant isolation */
6366
scope: QueryScope;
64-
/** Organization ID (required) */
65-
organizationId: string;
66-
/** Project ID (required for project/environment scope) */
67-
projectId: string;
68-
/** Environment ID (required for environment scope) */
69-
environmentId: string;
7067
/** History options for saving query to billing/audit */
7168
history?: {
7269
/** Where the query originated from */
@@ -109,6 +106,7 @@ export async function executeQuery<TOut extends z.ZodSchema>(
109106
organizationId,
110107
projectId,
111108
environmentId,
109+
enforcedWhereClause,
112110
history,
113111
customOrgConcurrencyLimit,
114112
whereClauseFallback,
@@ -136,18 +134,6 @@ export async function executeQuery<TOut extends z.ZodSchema>(
136134
}
137135

138136
try {
139-
// Build tenant IDs based on scope
140-
const enforcedWhereClause: {
141-
organization_id: WhereClauseCondition;
142-
project_id?: WhereClauseCondition;
143-
environment_id?: WhereClauseCondition;
144-
} = {
145-
organization_id: { op: "eq", value: organizationId },
146-
project_id: scope === "project" || scope === "environment" ? { op: "eq", value: projectId } : undefined,
147-
environment_id: scope === "environment" ? { op: "eq", value: environmentId } : undefined,
148-
//todo add plan-based time limit
149-
};
150-
151137
// Build field mappings for project_ref → project_id and environment_id → slug translation
152138
const projects = await prisma.project.findMany({
153139
where: { organizationId },

internal-packages/clickhouse/src/client/tsql.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export interface ExecuteTSQLOptions<TOut extends z.ZodSchema> {
5656
* }
5757
* ```
5858
*/
59-
enforcedWhereClause: Record<string, WhereClauseCondition>;
59+
enforcedWhereClause: Record<string, WhereClauseCondition | undefined>;
6060
/** Optional ClickHouse query settings */
6161
clickhouseSettings?: ClickHouseSettings;
6262
/** Optional TSQL query settings (maxRows, timezone, etc.) */

internal-packages/tsql/src/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ export interface CompileTSQLOptions {
467467
* }
468468
* ```
469469
*/
470-
enforcedWhereClause: Record<string, WhereClauseCondition>;
470+
enforcedWhereClause: Record<string, WhereClauseCondition | undefined>;
471471
/** Optional query settings */
472472
settings?: Partial<QuerySettings>;
473473
/**
@@ -547,14 +547,20 @@ export function compileTSQL(query: string, options: CompileTSQLOptions): PrintRe
547547
// 3. Create schema registry from table schemas
548548
const schemaRegistry = createSchemaRegistry(options.tableSchema);
549549

550-
// 4. Create printer context with enforced WHERE clause and field mappings
550+
551+
// 4. Strip undefined values from enforcedWhereClause
552+
const enforcedWhereClause = Object.fromEntries(
553+
Object.entries(options.enforcedWhereClause).filter(([_, value]) => value !== undefined)
554+
) as Record<string, WhereClauseCondition>;
555+
556+
// 5. Create printer context with enforced WHERE clause and field mappings
551557
const context = createPrinterContext({
552558
schema: schemaRegistry,
553559
settings: options.settings,
554560
fieldMappings: options.fieldMappings,
555-
enforcedWhereClause: options.enforcedWhereClause,
561+
enforcedWhereClause,
556562
});
557563

558-
// 5. Print the AST to ClickHouse SQL (enforced conditions applied at printer level)
564+
// 6. Print the AST to ClickHouse SQL (enforced conditions applied at printer level)
559565
return printToClickHouse(ast, context);
560566
}

0 commit comments

Comments
 (0)