Add direct file download links to completed requests

Embeds a signed JWT download token (30-day expiry) in the requests API
response so users can download completed audiobook/ebook files directly
from the UI or by sharing the URL to apps like BookPlayer — no session
cookie required.

- jwt.ts: add generateDownloadToken / verifyDownloadToken helpers
- api/requests: append downloadUrl to completed requests with a filePath
- api/requests/[id]/download: new token-authenticated streaming endpoint;
  serves single files directly or zips multi-file audiobooks with adm-zip
- RequestCard: add Download link in the actions area for completed requests
This commit is contained in:
razzamatazm
2026-02-26 11:21:06 -08:00
parent 547af71de8
commit 1006a04337
4 changed files with 201 additions and 2 deletions
+29
View File
@@ -78,6 +78,35 @@ export function verifyRefreshToken(token: string): RefreshTokenPayload | null {
}
}
const DOWNLOAD_TOKEN_EXPIRY = '30d';
export interface DownloadTokenPayload {
sub: string; // userId
requestId: string;
type: 'download';
}
/**
* Generate download token (30-day, stateless, URL-embeddable)
*/
export function generateDownloadToken(userId: string, requestId: string): string {
const payload: DownloadTokenPayload = { sub: userId, requestId, type: 'download' };
return jwt.sign(payload, JWT_SECRET, { expiresIn: DOWNLOAD_TOKEN_EXPIRY });
}
/**
* Verify download token
*/
export function verifyDownloadToken(token: string): DownloadTokenPayload | null {
try {
const decoded = jwt.verify(token, JWT_SECRET) as DownloadTokenPayload;
if (decoded.type !== 'download') return null;
return decoded;
} catch {
return null;
}
}
/**
* Decode token without verification (for debugging)
*/