mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
feat(video-assets): add full video asset system (uploads, downloads, @mentions, and cleanup/billing integration)
This commit is contained in:
@@ -3,6 +3,7 @@ import { db } from '@/lib/db';
|
||||
import { auth, checkProjectAccess } from '@/lib/auth';
|
||||
import { rateLimit } from '@/lib/rate-limit';
|
||||
import { cleanupProjectMediaFiles } from '@/lib/r2-cleanup';
|
||||
import { cleanupBunnyStreamVideos } from '@/lib/bunny-stream-cleanup';
|
||||
import { apiErrors, successResponse, withCacheControl } from '@/lib/api-response';
|
||||
|
||||
type RouteParams = { params: Promise<{ projectId: string }> };
|
||||
@@ -157,6 +158,36 @@ export async function DELETE(request: NextRequest, { params }: RouteParams) {
|
||||
return apiErrors.forbidden('Only the project owner can delete it');
|
||||
}
|
||||
|
||||
const [projectVersionRefs, projectAssetRefs] = await Promise.all([
|
||||
db.videoVersion.findMany({
|
||||
where: {
|
||||
video: { projectId },
|
||||
},
|
||||
select: {
|
||||
providerId: true,
|
||||
videoId: true,
|
||||
},
|
||||
}),
|
||||
db.videoAsset.findMany({
|
||||
where: {
|
||||
video: { projectId },
|
||||
provider: 'BUNNY',
|
||||
providerVideoId: { not: null },
|
||||
},
|
||||
select: {
|
||||
providerVideoId: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
await cleanupBunnyStreamVideos([
|
||||
...projectVersionRefs,
|
||||
...projectAssetRefs.map((asset) => ({
|
||||
providerId: 'bunny',
|
||||
videoId: asset.providerVideoId as string,
|
||||
})),
|
||||
]);
|
||||
|
||||
// Clean up voice files from R2 before cascade delete removes comment rows
|
||||
await cleanupProjectMediaFiles(projectId);
|
||||
|
||||
|
||||
@@ -126,6 +126,9 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
||||
canManageTags: access.canEdit,
|
||||
canResolveComments: access.canEdit,
|
||||
canRequestApproval: access.canEdit,
|
||||
canShareVideo: access.canEdit,
|
||||
canUploadAssets: access.hasAccess,
|
||||
canDownloadAssets: !!session?.user?.id && access.hasAccess,
|
||||
});
|
||||
|
||||
return withCacheControl(response, 'private, no-cache');
|
||||
@@ -212,6 +215,12 @@ export async function DELETE(request: NextRequest, { params }: RouteParams) {
|
||||
videoId: true,
|
||||
},
|
||||
},
|
||||
assets: {
|
||||
select: {
|
||||
provider: true,
|
||||
providerVideoId: true,
|
||||
},
|
||||
},
|
||||
project: true,
|
||||
},
|
||||
});
|
||||
@@ -226,7 +235,15 @@ export async function DELETE(request: NextRequest, { params }: RouteParams) {
|
||||
}
|
||||
|
||||
// Delete Bunny provider videos first to avoid orphaned assets.
|
||||
await cleanupBunnyStreamVideos(video.versions);
|
||||
await cleanupBunnyStreamVideos([
|
||||
...video.versions,
|
||||
...video.assets
|
||||
.filter((asset) => asset.provider === 'BUNNY' && !!asset.providerVideoId)
|
||||
.map((asset) => ({
|
||||
providerId: 'bunny',
|
||||
videoId: asset.providerVideoId as string,
|
||||
})),
|
||||
]);
|
||||
|
||||
// Clean up voice files from R2 before cascade delete removes comment rows
|
||||
await cleanupVideoMediaFiles(videoId);
|
||||
|
||||
Reference in New Issue
Block a user