feat: admin-endpunkt zum direkten download des release-ZIP (fuer n8n/CI)
GET /api/v1/releases/:product/download (X-Admin-Token) streamt das aktuelle release-ZIP; optional ?version=1.2.3 fuer eine bestimmte version. Kein lizenz- key/token noetig - gedacht fuer automatisierung (n8n, CI). Antwort: application/zip + header X-Release-Version. Integrationstest ergaenzt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -632,6 +632,25 @@ app.get('/api/v1/releases/:product', adminOnly, (req, res) => {
|
||||
return res.json({ ok: true, product: product.slug, releases: rows });
|
||||
});
|
||||
|
||||
// Download a release ZIP directly with the admin token (no license needed) —
|
||||
// handy for n8n/CI. Defaults to the latest version; ?version=1.2.3 for a
|
||||
// specific one. Returns the raw application/zip stream.
|
||||
app.get('/api/v1/releases/:product/download', adminOnly, (req, res) => {
|
||||
const product = Q.productBySlug.get(req.params.product);
|
||||
if (!product) return fail(res, 404, 'unknown product');
|
||||
|
||||
const version = String(req.query.version || '').trim();
|
||||
const rel = version ? Q.releaseByVersion.get(product.id, version) : latestRelease(product.id);
|
||||
if (!rel) return fail(res, 404, version ? 'version not found' : 'no release yet');
|
||||
if (!existsSync(rel.zip_path)) return fail(res, 404, 'release file missing on disk');
|
||||
|
||||
res.setHeader('Content-Type', 'application/zip');
|
||||
res.setHeader('Content-Length', statSync(rel.zip_path).size);
|
||||
res.setHeader('X-Release-Version', rel.version);
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${product.slug}-${rel.version}.zip"`);
|
||||
createReadStream(rel.zip_path).pipe(res);
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Generate a license key. This is the endpoint the n8n workflow calls.
|
||||
|
||||
Reference in New Issue
Block a user