Files
Eric Allam 07f7c65054 v3 queue system (#903)
* Introducing Modular Asynchronous Reliable Queueing System (MarQS). Works in dev

* Convert MarQS to using lua and dealing with concurrency

* Simplified the timeout queue and current concurrency is now a set instead of a flat value (to support idempotency)

* Implement task heartbeating and reconnect the background workers CLI when the websocket connection reconnects

* Start adding internal telemetry support for the server

* Get env vars to work in dev and implement prisma tracing in webapp

* Cleanup telemetry and implement it in the consumer

* Implement dequeuing a message from a parent shared queue

* Implement a custom logger exporter instead of using console log exporter

* Use node instead of shell for generating protocol buffer code

* Propogate trace context into debug logs, and allow turning off logger exporter through env vars

* Switch to using baselime for internal otel data

* Make orgMember optional to fix type issues

* Provide the CLI dev env vars through the CLI, don’t build dotenv into facade

* Removed the logger import

* Address Matt’s comments

* Addressing more of Matt’s comments

* Handle sending an execution after a websocket connection closes

* Remove auth from the env attributes to prevent obfuscation
2024-02-20 12:16:41 +00:00

95 lines
2.4 KiB
TypeScript

import { Prettify } from "@trigger.dev/core";
import { z } from "zod";
import {
findEnvironmentByApiKey,
findEnvironmentByPublicApiKey,
} from "~/models/runtimeEnvironment.server";
type Optional<T, K extends keyof T> = Prettify<Omit<T, K> & Partial<Pick<T, K>>>;
const AuthorizationHeaderSchema = z.string().regex(/^Bearer .+$/);
export type AuthenticatedEnvironment = Optional<
NonNullable<Awaited<ReturnType<typeof findEnvironmentByApiKey>>>,
"orgMember"
>;
type ApiAuthenticationResult = {
apiKey: string;
type: "PUBLIC" | "PRIVATE";
environment: AuthenticatedEnvironment;
};
export async function authenticateApiRequest(
request: Request,
{ allowPublicKey = false }: { allowPublicKey?: boolean } = {}
): Promise<ApiAuthenticationResult | undefined> {
const apiKey = getApiKeyFromRequest(request);
if (!apiKey) {
return;
}
return authenticateApiKey(apiKey, { allowPublicKey });
}
export async function authenticateApiKey(
apiKey: string,
{ allowPublicKey = false }: { allowPublicKey?: boolean } = {}
): Promise<ApiAuthenticationResult | undefined> {
const result = getApiKeyResult(apiKey);
if (!result) {
return;
}
//if it's a public API key and we don't allow public keys, return
if (!allowPublicKey) {
const environment = await findEnvironmentByApiKey(result.apiKey);
if (!environment) return;
return {
...result,
environment,
};
}
switch (result.type) {
case "PUBLIC": {
const environment = await findEnvironmentByPublicApiKey(result.apiKey);
if (!environment) return;
return {
...result,
environment,
};
}
case "PRIVATE": {
const environment = await findEnvironmentByApiKey(result.apiKey);
if (!environment) return;
return {
...result,
environment,
};
}
}
}
export function isPublicApiKey(key: string) {
return key.startsWith("pk_");
}
export function getApiKeyFromRequest(request: Request) {
const rawAuthorization = request.headers.get("Authorization");
const authorization = AuthorizationHeaderSchema.safeParse(rawAuthorization);
if (!authorization.success) {
return;
}
const apiKey = authorization.data.replace(/^Bearer /, "");
return apiKey;
}
export function getApiKeyResult(apiKey: string) {
const type = isPublicApiKey(apiKey) ? ("PUBLIC" as const) : ("PRIVATE" as const);
return { apiKey, type };
}