Skip to content

Güvenlik ve Optimizasyon

Video güvenliği (Bunny CDN imzalı URL), Cloudflare Zero Trust ile admin güvenliği, dinamik robots.txt ve sitemap üretimi.

Bu sayfa Coursio’da video güvenliği (Bunny CDN imzalı URL), Cloudflare Zero Trust ile admin panelinin güvenliğe alınması ve SEO için dinamik robots.txt ile sitemap üretimini açıklar.

Video Güvenliği — Bunny CDN İmzalı (Signed) URL

Section titled “Video Güvenliği — Bunny CDN İmzalı (Signed) URL”

Videolar Bunny.net Stream üzerinden sunulur. Doğrudan indirmeyi ve yetkisiz erişimi engellemek için imzalı (signed) URL kullanılır.

  • Dosya: app/lib/video-security.ts
  • Fonksiyon: generateSignedVideoUrl(videoId, libraryId, securityKey, expirationSeconds?)
  • Algoritma: Bunny’nin beklediği formatta token üretilir:
    • expires = now + expirationSeconds (varsayılan 3600 saniye = 1 saat)
    • tokenData = securityKey + videoId + expires
    • SHA-256 hash alınır → hex string = token
    • URL: https://iframe.mediadelivery.net/embed/{libraryId}/{videoId}?token={token}&expires={expires}

Bunny CDN, gelen istekteki token ve expires değerini aynı mantıkla doğrular; süre dolmuş veya token yanlışsa içerik verilmez.

DeğişkenAçıklama
BUNNY_LIBRARY_IDBunny Stream Library ID
BUNNY_VIDEO_SECURITY_KEYBunny panelinden alınan Pull Zone → Remote Auth / Security Key (imza için kullanılır)
  • Öğrenme sayfası: app/routes/learn.$slug.tsx — kayıtlı derslerde sadece erişim hakkı olan kullanıcılara signedVideoUrl üretilir (preview dersler + enroll edilmiş kullanıcılar).
  • Kurs detay sayfası: app/routes/course.$id.tsx — önizleme (preview) dersler için signedPreviewUrl üretilir.

BUNNY_VIDEO_SECURITY_KEY tanımlı değilse imzalı URL üretilmez; eski embed URL’i (token olmadan) kullanılır — bu durumda videolar doğrudan paylaşılabilir ve indirilebilir, production’da güvenlik anahtarı kullanılması önerilir.


Cloudflare Zero Trust — Admin Panelinin Güvenliğe Alınması

Section titled “Cloudflare Zero Trust — Admin Panelinin Güvenliğe Alınması”

Admin paneli uygulama seviyesinde şu şekilde korunur:

  • Dosya: app/routes/admin.tsx (layout loader)
  • Kontrol: Better Auth session alınır; session?.user?.id yoksa veya veritabanındaki kullanıcı role !== "admin" ise 404’e yönlendirilir.
  • Tüm admin alt sayfaları bu layout’tan geçer; yani sadece role = admin olan kullanıcılar /admin/* sayfalarına erişebilir.

Production’da admin panelini ek bir katmanla korumak için Cloudflare Zero Trust (Access) kullanılabilir:

  1. Cloudflare Dashboard → Zero Trust → Access → Applications ile yeni bir uygulama tanımlanır.
  2. Protected hostname: admin.yourdomain.com veya yourdomain.com/admin (path bazlı kural ile).
  3. Policy: Örneğin sadece belirli e-posta alanları, GitHub/Google SSO veya One-time PIN ile giriş zorunlu tutulur.
  4. Böylece sunucuya istek ulaşmadan önce Cloudflare, kimlik doğrulamayı yapar; yetkisiz kullanıcılar login sayfasına yönlendirilir.

Dökümantasyon: Cloudflare Zero Trust — Application Access ve Protect a self-hosted application resmi dokümanlarından path/host bazlı kurulum yapılabilir.

Özet: Uygulama içi koruma (session + admin role) şu an tek katman; Cloudflare Access ile /admin (veya admin subdomain’i) ikinci katman olarak kilitlenebilir.


SEO & Sitemap — Dinamik robots.txt ve Sitemap Üretimi

Section titled “SEO & Sitemap — Dinamik robots.txt ve Sitemap Üretimi”
  • Route: GET /robots.txt (dil prefix’i yok)
  • Dosya: app/routes/robots[.]txt.ts
  • İçerik: Loader içinde request.url ile host ve protocol alınır; baseUrl dinamik oluşturulur. Aynı kod Cloudflare Workers veya farklı domain’de çalışır.

Kurallar özeti:

  • User-agent: * — Genel kurallar: public sayfalar (ana sayfa, /tr/, /en/, /de/, pricing, teaching, courses, course) Allow; admin, instructor, account, my-courses, cart, payment, login, register, onboarding, learn, verify, api, 404/500 Disallow.
  • Googlebot / Bingbot / Yandex — Aynı public sayfalar Allow; isteğe bağlı Crawl-delay (bazı botlar için).
  • Sitemap: Response’ta Sitemap: ${baseUrl}/sitemap.xml ve dil bazlı sitemap-tr.xml, sitemap-en.xml, sitemap-de.xml referansları yer alır.

Not: Dil bazlı sitemap URL’leri (sitemap-tr.xml vb.) robots.txt’te belirtilmiş olabilir; şu an routes.ts içinde yalnızca tek sitemap.xml route’u vardır. Dil bazlı ayrı sitemap’ler istenirse ek route’lar eklenebilir.

  • Route: GET /sitemap.xml
  • Dosya: app/routes/sitemap[.]xml.ts
  • Veri: getDb(env.DATABASE_URL) ile veritabanına bağlanılır; courses tablosundan status = 'published' olan kursların slug değerleri alınır.
  • URL’ler:
    • Statik sayfalar: baseUrl/{lang}{page} — diller: tr, en, de, es; sayfalar: "", /courses, /pricing, /teaching, /terms/privacy. Her biri için changefreq: weekly, priority: ana sayfa 1.0, diğerleri 0.8.
    • Kurs sayfaları: baseUrl/{lang}/course/{slug} — sadece yayında olan kurslar; changefreq: daily, priority: 0.9.
  • Response: Content-Type: application/xml, Cache-Control: public, max-age=3600.

Base URL: Sitemap içinde base URL sabit veya env’den okunabilir. Production’da canlı adres https://lms.techsider.co kullanılmalıdır; kodda örnek olarak coursio.co geçiyorsa env (örn. SITE_URL) ile lms.techsider.co yapılabilir. Bkz. Ortam Değişkenleri — Production URL.

  • Route: /:lang/sitemap (ör. /tr/sitemap)
  • Dosya: app/routes/$lang.sitemap.tsx
  • İçerik: HTML sitemap sayfası — platform bölümü (ana sayfa, tüm kurslar, fiyatlandırma, eğitmen ol), popüler kurslar (ör. kategori bazlı linkler), yasal (gizlilik, kullanım şartları, çerez politikası) linkleri. Arama motorları için ek bilgi; XML sitemap’in yerine geçmez.

KonuAçıklama
Video güvenliğiapp/lib/video-security.tsgenerateSignedVideoUrl ile Bunny CDN imzalı URL (SHA-256 token + expires). learn ve course sayfalarında kullanılır. Env: BUNNY_LIBRARY_ID, BUNNY_VIDEO_SECURITY_KEY.
Admin güvenliğiUygulama: session + user.role === "admin" (admin.tsx loader). Önerilen ek katman: Cloudflare Zero Trust (Access) ile /admin veya admin hostname koruması.
robots.txtDinamik, request.url ile baseUrl. Allow/Disallow + Sitemap referansları; dil bazlı sitemap URL’leri isteğe bağlı.
sitemap.xmlDinamik; DB’den yayındaki kurslar + statik sayfalar; diller (tr, en, de, es); XML; cache 1 saat.
/:lang/sitemapHTML sitemap sayfası (kullanıcı ve SEO için).

İlgili: Ortam Değişkenleri (Bunny ve diğer env), Admin Console (panel yetkilendirmesi), Eğitmen ve Kurs Yönetimi (video yükleme ve Bunny kullanımı).

  • app/lib/video-security.tsgenerateSignedVideoUrl; Bunny CDN imzalı URL.
  • app/routes/robots[.]txt.ts — Dinamik robots.txt.
  • app/routes/sitemap[.]xml.ts — Dinamik sitemap XML.
  • app/routes/$lang.sitemap.tsx — HTML sitemap sayfası.
  • app/routes/admin.tsx — Admin layout; session ve role kontrolü.