Deduplicate artifact bytes and deliver files by authenticated hash
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { authenticateAgent } from '$lib/server/hosts/http.js';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
|
||||
export function GET({ request, params }: { request: Request; params: { sha256: string } }) {
|
||||
const host = authenticateAgent(request);
|
||||
if (!/^[a-f0-9]{64}$/.test(params.sha256)) error(404, 'File not found.');
|
||||
const row = db().prepare(`SELECT b.content,b.size FROM file_blobs b WHERE b.sha256=? AND EXISTS (
|
||||
SELECT 1 FROM file_blob_references r JOIN ec_host_operations o ON o.id=r.owner_id
|
||||
WHERE r.sha256=b.sha256 AND r.owner_type='operation' AND o.host_id=?)`).get(params.sha256, host.id) as
|
||||
{ content: Buffer; size: number } | undefined;
|
||||
if (!row) error(404, 'File not found.');
|
||||
return new Response(new Uint8Array(row.content), { headers: {
|
||||
'Content-Type': 'application/octet-stream', 'Content-Length': String(row.size),
|
||||
'Cache-Control': 'private, no-store', ETag: `"${params.sha256}"`
|
||||
} });
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { blobContent } from '$lib/server/db/file-blobs.js';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
|
||||
/** Current files can be reviewed before the first revision is archived. */
|
||||
@@ -5,12 +6,12 @@ export async function GET({ params }: { params: { id: string; revision: string;
|
||||
const values = [params.id, params.revision, params.scriptId].map(Number);
|
||||
if (values.some(value => !Number.isSafeInteger(value) || value < 1)) return new Response('Invalid file', { status: 400 });
|
||||
const [id, revision, scriptId] = values;
|
||||
const file = db().prepare('SELECT content FROM beta_revision_files WHERE beta_id = ? AND revision = ? AND script_id = ?')
|
||||
const file = db().prepare(`SELECT ${blobContent('content_hash')} AS content FROM beta_revision_files WHERE beta_id = ? AND revision = ? AND script_id = ?`)
|
||||
.get(id, revision, scriptId) as { content: Buffer } | undefined
|
||||
?? (revision === 1 ? db().prepare(`SELECT v.content FROM beta_scripts bs JOIN script_versions v ON v.id = bs.script_version_id
|
||||
?? (revision === 1 ? db().prepare(`SELECT ${blobContent('v.content_hash')} AS content FROM beta_scripts bs JOIN script_versions v ON v.id = bs.script_version_id
|
||||
WHERE bs.beta_id = ? AND bs.script_id = ? AND NOT EXISTS (SELECT 1 FROM beta_revisions WHERE beta_id = ?)`)
|
||||
.get(id, scriptId, id) as { content: Buffer } | undefined : undefined);
|
||||
if (!file) return new Response('File not found', { status: 404 });
|
||||
if (!file?.content) return new Response('File not found', { status: 404 });
|
||||
return new Response(new Uint8Array(file.content), { headers: { 'Content-Type': 'application/octet-stream',
|
||||
'Content-Disposition': 'attachment', 'Cache-Control': 'no-store' } });
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { blobSize } from '$lib/server/db/file-blobs.js';
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
|
||||
@@ -16,8 +17,8 @@ export async function GET({ params }: { params: { id: string } }) {
|
||||
const files = db()
|
||||
.prepare(
|
||||
`SELECT id, server, verb, rel_path, sha256_before, sha256_after, snapshot_pending,
|
||||
LENGTH(content_before) AS size_before,
|
||||
LENGTH(content_after) AS size_after,
|
||||
${blobSize('content_before_hash')} AS size_before,
|
||||
${blobSize('content_after_hash')} AS size_after,
|
||||
COALESCE((SELECT state FROM staged_file_changes WHERE deployment_file_id = deployment_files.id), 'applied') AS apply_state
|
||||
FROM deployment_files
|
||||
WHERE deployment_id = ?
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { blobContent } from '$lib/server/db/file-blobs.js';
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
|
||||
@@ -10,7 +11,7 @@ export async function GET({ params }: { params: { id: string; fileId: string } }
|
||||
}
|
||||
const row = db()
|
||||
.prepare(
|
||||
`SELECT verb, rel_path, sha256_before, sha256_after, content_before, content_after, snapshot_pending
|
||||
`SELECT verb, rel_path, sha256_before, sha256_after, ${blobContent('content_before_hash')} AS content_before, ${blobContent('content_after_hash')} AS content_after, snapshot_pending
|
||||
FROM deployment_files
|
||||
WHERE deployment_id = ? AND id = ?`
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { blobSize } from '$lib/server/db/file-blobs.js';
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
import { getDeployment } from '$lib/server/provisioning/index.js';
|
||||
@@ -19,8 +20,8 @@ export async function GET({ params, url }: { params: { id: string }; url?: URL }
|
||||
const files = db()
|
||||
.prepare(
|
||||
`SELECT id, server, verb, rel_path, sha256_before, sha256_after,
|
||||
LENGTH(content_before) AS size_before,
|
||||
LENGTH(content_after) AS size_after
|
||||
${blobSize('content_before_hash')} AS size_before,
|
||||
${blobSize('content_after_hash')} AS size_after
|
||||
FROM deployment_files
|
||||
WHERE deployment_id = ?
|
||||
ORDER BY server, rel_path`
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { blobContent } from '$lib/server/db/file-blobs.js';
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
|
||||
@@ -7,7 +8,7 @@ import { db } from '$lib/server/db/index.js';
|
||||
export async function GET({ params }: { params: { id: string; fileId: string } }) {
|
||||
const row = db()
|
||||
.prepare(
|
||||
`SELECT verb, rel_path, sha256_before, sha256_after, content_before, content_after
|
||||
`SELECT verb, rel_path, sha256_before, sha256_after, ${blobContent('content_before_hash')} AS content_before, ${blobContent('content_after_hash')} AS content_after
|
||||
FROM deployment_files
|
||||
WHERE deployment_id = ? AND id = ?`
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user