Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/lib/server/actions/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IAmWrapper } from '../aws/iamwrapper';
import { prisma } from '../prisma';
import { Utils } from '../utils';
import { Project } from '$lib/server/models/project';
import { trimStrings } from '$lib/valibot';

export class ProjectUpdateOperation {
private id;
Expand Down Expand Up @@ -66,11 +67,14 @@ export class ProjectUpdateOperation {
const url = this.adjustUrl(project.url!, publicKeyId!);
await prisma.project.update({
where: { id: project.id },
data: {
user_id,
publishing_key,
url
}
data: trimStrings(
{
user_id,
publishing_key,
url
},
'project'
)
});
}
private adjustUrl(url: string, newPublicKeyId: string) {
Expand Down
47 changes: 30 additions & 17 deletions src/lib/server/job-executors/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CodeCommit } from '../aws/codecommit';
import { BullMQ, getQueues } from '../bullmq';
import { Build } from '../models/build';
import { prisma } from '../prisma';
import { trimStrings } from '$lib/valibot';

export async function product(job: Job<BullMQ.Build.Product>): Promise<unknown> {
try {
Expand Down Expand Up @@ -65,12 +66,16 @@ export async function product(job: Job<BullMQ.Build.Product>): Promise<unknown>
if (lastBuildGuid) {
await prisma.build.update({
where: { id: build.id },
data: {
build_guid: lastBuildGuid,
codebuild_url: CodeBuild.getCodeBuildUrl('build_app', lastBuildGuid),
console_text_url: CodeBuild.getConsoleTextUrl('build_app', lastBuildGuid),
status: Build.Status.Active
}
data: trimStrings(
{
build_guid: lastBuildGuid,
codebuild_url: CodeBuild.getCodeBuildUrl('build_app', lastBuildGuid),
console_text_url: CodeBuild.getConsoleTextUrl('build_app', lastBuildGuid),
status: Build.Status.Active
},
'build',
job.log
)
});
}
job.updateProgress(100);
Expand Down Expand Up @@ -102,12 +107,16 @@ export async function product(job: Job<BullMQ.Build.Product>): Promise<unknown>
if (lastBuildGuid) {
await prisma.build.update({
where: { id: build.id },
data: {
build_guid: lastBuildGuid,
codebuild_url: CodeBuild.getCodeBuildUrl('build_app', lastBuildGuid),
console_text_url: CodeBuild.getConsoleTextUrl('build_app', lastBuildGuid),
status: Build.Status.Active
}
data: trimStrings(
{
build_guid: lastBuildGuid,
codebuild_url: CodeBuild.getCodeBuildUrl('build_app', lastBuildGuid),
console_text_url: CodeBuild.getConsoleTextUrl('build_app', lastBuildGuid),
status: Build.Status.Active
},
'build',
job.log
)
});
}
const name = `Check status of Build #${build.id}`;
Expand All @@ -128,11 +137,15 @@ export async function product(job: Job<BullMQ.Build.Product>): Promise<unknown>
job.log(`${e}`);
await prisma.build.update({
where: { id: job.data.buildId },
data: {
result: Build.Result.Failure,
status: Build.Status.Completed,
error: String(e)
}
data: trimStrings(
{
result: Build.Result.Failure,
status: Build.Status.Completed,
error: String(e)
},
'build',
job.log
)
});
}
}
Expand Down
27 changes: 17 additions & 10 deletions src/lib/server/job-executors/polling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { BullMQ, getQueues } from '../bullmq';
import { Build } from '../models/build';
import { prisma } from '../prisma';
import { Release } from '$lib/server/models/release';
import type { Logger } from '$lib/utils';
import { trimStrings } from '$lib/valibot';

export async function build(job: Job<BullMQ.Polling.Build>): Promise<unknown> {
try {
Expand Down Expand Up @@ -56,7 +58,7 @@ export async function build(job: Job<BullMQ.Polling.Build>): Promise<unknown> {
}
await prisma.build.update({
where: { id: build.id },
data: { ...build, job: undefined }
data: trimStrings({ ...build, job: undefined }, 'build', job.log)
});
job.updateProgress(100);
return {
Expand All @@ -71,11 +73,15 @@ export async function build(job: Job<BullMQ.Polling.Build>): Promise<unknown> {
job.log(`${e}`);
await prisma.build.update({
where: { id: job.data.buildId },
data: {
result: Build.Result.Failure,
status: Build.Status.Completed,
error: String(e)
}
data: trimStrings(
{
result: Build.Result.Failure,
status: Build.Status.Completed,
error: String(e)
},
'build',
job.log
)
});
}
}
Expand Down Expand Up @@ -122,11 +128,11 @@ export async function release(job: Job<BullMQ.Polling.Release>): Promise<unknown
case CodeBuild.Status.Fault:
case CodeBuild.Status.TimedOut:
release.result = Build.Result.Failure;
await handleReleaseFailure(release);
await handleReleaseFailure(release, job.log);
break;
case CodeBuild.Status.Stopped:
release.result = Build.Result.Aborted;
await handleReleaseFailure(release);
await handleReleaseFailure(release, job.log);
break;
case CodeBuild.Status.Succeeded:
release.result = Build.Result.Success;
Expand Down Expand Up @@ -163,11 +169,12 @@ export async function release(job: Job<BullMQ.Polling.Release>): Promise<unknown
}

async function handleReleaseFailure(
release: Prisma.releaseGetPayload<{ select: { id: true; console_text_url: true } }>
release: Prisma.releaseGetPayload<{ select: { id: true; console_text_url: true } }>,
log: Logger
) {
await prisma.release.update({
where: { id: release.id },
data: { error: release.console_text_url }
data: trimStrings({ error: release.console_text_url }, 'release', log)
});
await getQueues().S3.add(`Save Errors for Release ${release.id} to S3`, {
type: BullMQ.JobType.S3_CopyError,
Expand Down
31 changes: 20 additions & 11 deletions src/lib/server/job-executors/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { BullMQ } from '../bullmq';
import { prisma } from '../prisma';
import { Build } from '$lib/server/models/build';
import { Release } from '$lib/server/models/release';
import { trimStrings } from '$lib/valibot';

export async function product(job: Job<BullMQ.Release.Product>): Promise<unknown> {
try {
Expand Down Expand Up @@ -32,12 +33,16 @@ export async function product(job: Job<BullMQ.Release.Product>): Promise<unknown
if (lastBuildGuid) {
await prisma.release.update({
where: { id: job.data.releaseId },
data: {
build_guid: lastBuildGuid,
codebuild_url: CodeBuild.getCodeBuildUrl('publish_app', lastBuildGuid),
console_text_url: CodeBuild.getConsoleTextUrl('publish_app', lastBuildGuid),
status: Release.Status.Active
}
data: trimStrings(
{
build_guid: lastBuildGuid,
codebuild_url: CodeBuild.getCodeBuildUrl('publish_app', lastBuildGuid),
console_text_url: CodeBuild.getConsoleTextUrl('publish_app', lastBuildGuid),
status: Release.Status.Active
},
'release',
job.log
)
});
}
job.updateProgress(100);
Expand All @@ -46,11 +51,15 @@ export async function product(job: Job<BullMQ.Release.Product>): Promise<unknown
job.log(`${e}`);
await prisma.release.update({
where: { id: job.data.releaseId },
data: {
result: Build.Result.Failure,
status: Release.Status.Completed,
error: String(e)
}
data: trimStrings(
{
result: Build.Result.Failure,
status: Release.Status.Completed,
error: String(e)
},
'release',
job.log
)
});
}
}
17 changes: 11 additions & 6 deletions src/lib/server/job-executors/s3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { BuildForPrefix } from '$lib/server/models/artifacts';
import { Build } from '$lib/server/models/build';
import { Release } from '$lib/server/models/release';
import { prisma } from '$lib/server/prisma';
import { trimStrings } from '$lib/valibot';

export async function save(job: Job<BullMQ.S3.CopyArtifacts>): Promise<unknown> {
const id = job.data.id;
Expand Down Expand Up @@ -106,12 +107,16 @@ export async function save(job: Job<BullMQ.S3.CopyArtifacts>): Promise<unknown>
}
await prisma.build.update({
where: { id },
data: {
...build,
status: Build.Status.Completed,
result: Build.Result.Success,
job: undefined
}
data: trimStrings(
{
...build,
status: Build.Status.Completed,
result: Build.Result.Success,
job: undefined
},
'build',
job.log
)
});
await s3.removeCodeBuildFolder(build);
job.updateProgress(100);
Expand Down
3 changes: 3 additions & 0 deletions src/lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export function ErrorResponse(status: number, message: string, headers?: HeadersInit) {
return new Response(JSON.stringify({ status, message }), { status, headers });
}

export type Logger = (msg: string) => void;
export const defaultLogger: Logger = (msg) => console.log(msg);
81 changes: 79 additions & 2 deletions src/lib/valibot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as v from 'valibot';
import { type Logger, defaultLogger } from './utils';

export const idSchema = v.pipe(v.number(), v.minValue(0), v.integer());

Expand All @@ -7,14 +8,14 @@ export const paramNumber = v.pipe(
v.transform((s) => parseInt(s))
);

export function convertEmptyStrToNull() {
export function convertEmptyStrToNull(limit?: number) {
return v.nullable(
v.union([
v.pipe(
v.literal(''),
v.transform(() => null)
),
v.string()
limit ? v.pipe(v.string(), v.maxBytes(limit)) : v.string()
])
);
}
Expand Down Expand Up @@ -42,3 +43,79 @@ export const tableSchema = v.object({
})
)
});

export const stringLimits = {
build: {
status: 255,
result: 255,
error: 2083,
channel: 255,
artifact_url_base: 2083,
artifact_files: 4096,
build_guid: 255,
console_text_url: 255,
codebuild_url: 255,
targets: 255
},
client: {
access_token: 255,
prefix: 4
},
job: {
request_id: 255,
git_url: 2083,
app_id: 255,
publisher_id: 255,
jenkins_build_url: 1024,
jenkins_publish_url: 1024
},
project: {
status: 255,
result: 255,
error: 2083,
url: 1024,
user_id: 255,
group_id: 255,
app_id: 255,
project_name: 255,
language_code: 255,
publishing_key: 1024
},
release: {
status: 255,
result: 255,
error: 2083,
channel: 255,
title: 30,
defaultLanguage: 255,
promote_from: 255,
build_guid: 255,
console_text_url: 255,
codebuild_url: 255,
targets: 255,
artifact_url_base: 255,
artifact_files: 255
}
} as const;

export function trimStrings<T extends Record<string, unknown>>(
obj: T,
scope: keyof typeof stringLimits,
log: Logger = defaultLogger
) {
for (const [key, limit] of Object.entries(stringLimits[scope])) {
const raw = obj[key];
if (raw) {
let val = (raw as string).trim().substring(0, limit);
while (new Blob([val]).size < limit) {
val = val.substring(0, val.length - 1);
}
if (raw !== val) {
log(`trimStrings ${scope}: "${raw}" => "${val}"`);
//@ts-expect-error this should be fine...
obj[key] = val;
}
}
}
return obj;
}
8 changes: 4 additions & 4 deletions src/routes/(api)/job/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import * as v from 'valibot';
import type { RequestHandler } from './$types';
import { prisma } from '$lib/server/prisma';
import { ErrorResponse } from '$lib/utils';
import { stringIdSchema } from '$lib/valibot';
import { stringIdSchema, stringLimits } from '$lib/valibot';

const jobSchema = v.strictObject({
request_id: stringIdSchema,
git_url: v.pipe(v.string(), v.url()),
app_id: v.string(),
publisher_id: v.string()
git_url: v.pipe(v.string(), v.url(), v.maxBytes(stringLimits.job.git_url)),
app_id: v.pipe(v.string(), v.maxBytes(stringLimits.job.app_id)),
publisher_id: v.pipe(v.string(), v.maxBytes(stringLimits.job.publisher_id))
});

// POST /job
Expand Down
3 changes: 2 additions & 1 deletion src/routes/(api)/job/[jobId=idNumber]/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as v from 'valibot';
import type { RequestHandler } from './$types';
import { prisma } from '$lib/server/prisma';
import { ErrorResponse } from '$lib/utils';
import { stringLimits } from '$lib/valibot';

// GET /job/[id]
export const GET: RequestHandler = async ({ params }) => {
Expand Down Expand Up @@ -33,7 +34,7 @@ export const GET: RequestHandler = async ({ params }) => {
};

const updateSchema = v.strictObject({
publisher_id: v.string()
publisher_id: v.pipe(v.string(), v.maxBytes(stringLimits.job.publisher_id))
});

// PUT /job/[id]
Expand Down
Loading
Loading