Harden auth, add subtitles, vendor all assets locally
- Session cookies are HttpOnly + SameSite=Lax (Secure on HTTPS), with strict session-ID mode; the CSRF token from GET api/auth.php must now accompany every state-changing request (X-CSRF-Token header, or a csrf body field for the sendBeacon progress save), rotated at login. - Failed sign-ins are throttled per username and IP via login_attempts (created lazily, so existing installs need no migration): 5 failures a username / 20 an IP inside 15 minutes answer 429 with Retry-After. - A video's sibling .srt now appears as a CC button in the player; captions.php converts it to WebVTT (comma timestamps, legacy encodings, and the already-VTT files with out-of-spec 6-digit fractions). - Plyr and Inter ship in assets/vendor/ instead of coming from CDNs, and anime.js is gone along with all scripted animations and the motion setting — the app now runs with no internet access at all. - .htaccess denies direct access to videos/, includes/, config.php and schema.sql, so video URLs cannot bypass login on Apache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SePf61iazhCLJBefdRLBDm
This commit is contained in:
@@ -23,10 +23,9 @@ function asset(string $path): string
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#F2F0EA">
|
||||
<title>CourseHub</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/plyr@3.7.8/dist/plyr.css" rel="stylesheet" data-boot-critical>
|
||||
<!-- All assets are local (assets/vendor/) — the app runs with no internet access. -->
|
||||
<link href="<?= asset('assets/vendor/inter.css') ?>" rel="stylesheet">
|
||||
<link href="<?= asset('assets/vendor/plyr.css') ?>" rel="stylesheet" data-boot-critical>
|
||||
<link href="<?= asset('assets/style.css') ?>" rel="stylesheet" data-boot-critical>
|
||||
|
||||
<!-- Installed before every other script so it can report failures in them
|
||||
@@ -137,8 +136,7 @@ function asset(string $path): string
|
||||
<div class="toasts" id="toasts"></div>
|
||||
<div id="overlay-root"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/plyr@3.7.8/dist/plyr.min.js" data-boot-critical></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.2/lib/anime.min.js" data-boot-critical></script>
|
||||
<script src="<?= asset('assets/vendor/plyr.min.js') ?>" data-boot-critical></script>
|
||||
<script src="<?= asset('assets/app.js') ?>" data-boot-critical></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user