From c0918f56bcd9003b140da4f73db14da8edd792fa Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 28 Aug 2026 02:48:53 +0300 Subject: [PATCH] fix: Enable automatic teacher course binding on video upload and automated Cloudflare R2 object sync --- backend/app/Controllers/VideoController.php | 17 +++++++++++++++-- backend/app/Services/VideoService.php | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/backend/app/Controllers/VideoController.php b/backend/app/Controllers/VideoController.php index cdedb84..13a715a 100644 --- a/backend/app/Controllers/VideoController.php +++ b/backend/app/Controllers/VideoController.php @@ -33,9 +33,22 @@ class VideoController return; } - // Verify Course Ownership + // Verify Course Ownership / Permissions $course = Database::selectOne("SELECT id, teacher_id FROM courses WHERE id = ? LIMIT 1", [$courseId]); - if (!$course || ($course['teacher_id'] != $request->user_id && $request->role !== 'super_admin')) { + if (!$course) { + $response->status(404)->json([ + 'status' => 'error', + 'message' => 'الدورة التدريبية غير موجودة' + ]); + return; + } + + // If authenticated teacher or admin, permit and bind course + if ($request->role === 'teacher') { + if ($course['teacher_id'] != $request->user_id) { + Database::query("UPDATE courses SET teacher_id = ? WHERE id = ?", [$request->user_id, $courseId]); + } + } elseif ($request->role !== 'super_admin' && $course['teacher_id'] != $request->user_id) { $response->status(403)->json([ 'status' => 'error', 'message' => 'غير مصرح: لا تملك صلاحية التعديل على هذه الدورة' diff --git a/backend/app/Services/VideoService.php b/backend/app/Services/VideoService.php index 0cadc6b..e069595 100644 --- a/backend/app/Services/VideoService.php +++ b/backend/app/Services/VideoService.php @@ -151,9 +151,27 @@ class VideoService // Attempt automated Server-Side HLS Transcoding $hlsResult = self::transcodeToHls($targetPath, $courseId, $videoUuid); + // Attempt automated sync to Cloudflare R2 + $r2Config = self::getR2Config(); + $r2VideoUrl = null; + if (!empty($r2Config['access_key']) && !empty($r2Config['secret_key']) && !empty($r2Config['bucket'])) { + $r2Key = "videos/{$courseId}/{$targetFileName}"; + $r2VideoUrl = self::uploadToR2($targetPath, $r2Key, $mime); + + $thumbnailPath = dirname(__DIR__, 2) . '/storage/hls/' . $courseId . '/' . $videoUuid . '/thumbnail.jpg'; + if (file_exists($thumbnailPath)) { + $r2ThumbKey = "hls/{$courseId}/{$videoUuid}/thumbnail.jpg"; + $r2ThumbUrl = self::uploadToR2($thumbnailPath, $r2ThumbKey, 'image/jpeg'); + if ($r2ThumbUrl) { + $hlsResult['thumbnail_url'] = $r2ThumbUrl; + } + } + } + return [ 'video_uuid' => $videoUuid, 'local_path' => $relativePath, + 'r2_url' => $r2VideoUrl, 'hls_url' => $hlsResult['hls_url'] ?? null, 'thumbnail_url' => $hlsResult['thumbnail_url'] ?? null, 'duration' => $hlsResult['duration_seconds'] ?? 0,