ef72e221be
Implemented a comprehensive authentication system requiring all users to be logged in to access the web interface. Features include: Backend: - JWT-based authentication with 7-day token expiration - bcrypt password hashing with 72-byte limit handling - User management with JSON file storage (config/users.json) - Pydantic models for validation (UserCreate, UserLogin, User, Token) - Authentication endpoints: register, login, me, logout - Protected route dependency with HTTPBearer security Frontend: - Login/register page with dual-tab interface (/login) - Client-side authentication check with automatic redirect - All content hidden by default, shown only after auth validation - User info display with logout button - Main content and tabs hidden when not authenticated - Auto-redirect to /login if token missing or invalid Security: - Password truncation to 72 bytes (bcrypt limitation) - Token verification on each page load - Automatic logout and redirect on token expiry - Username-to-SHA256 user ID generation Dependencies: - passlib[bcrypt]==1.7.4 - python-jose[cryptography]==3.3.0 - bcrypt<4.0 Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
121 lines
5.1 KiB
HTML
121 lines
5.1 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block content %}
|
|
{% include "components/header.html" %}
|
|
|
|
<!-- Main content - Hidden by default, shown only when authenticated -->
|
|
<div id="main-content" style="display: none;">
|
|
|
|
{% include "components/home_section.html" %}
|
|
|
|
<!-- Nouveaux onglets -->
|
|
<div id="tab-anime" class="tab-content">
|
|
<!-- Anime Search Section -->
|
|
<div class="section-header">
|
|
<h2>🎬 Rechercher un Anime</h2>
|
|
</div>
|
|
<div class="url-form">
|
|
<div class="input-group">
|
|
<input
|
|
type="text"
|
|
id="animeSearchInput"
|
|
placeholder="Rechercher un anime (ex: Frieren, One Piece, Naruto...)"
|
|
>
|
|
<button type="button" class="btn-primary" onclick="handleAnimeSearch()">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
</svg>
|
|
Rechercher
|
|
</button>
|
|
</div>
|
|
<div style="margin-top: 10px; padding: 10px; background: rgba(0, 217, 255, 0.1); border-radius: 8px; font-size: 12px; color: #aaa;">
|
|
💡 <strong>Info:</strong> La recherche utilise MyAnimeList pour afficher la fiche complète (synopsis, saisons, etc.)
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Anime search results -->
|
|
<div id="animeSearchResults" style="margin-bottom: 40px;"></div>
|
|
|
|
<hr style="border: none; border-top: 1px solid rgba(255,255,255,0.1); margin: 40px 0;">
|
|
|
|
<!-- Latest Releases Section -->
|
|
<div class="section-header">
|
|
<h2>🔥 Dernières sorties Anime</h2>
|
|
<button class="btn-small btn-secondary" onclick="loadAnimeReleases()">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" style="width:14px;height:14px;">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
|
</svg>
|
|
Dernières sorties
|
|
</button>
|
|
</div>
|
|
<div id="animeReleasesList" class="recommendations-carousel"></div>
|
|
</div>
|
|
|
|
<div id="tab-series" class="tab-content">
|
|
<!-- Series Search Section -->
|
|
<div class="section-header">
|
|
<h2>📺 Rechercher une Série TV</h2>
|
|
</div>
|
|
<div class="url-form">
|
|
<div class="input-group">
|
|
<input
|
|
type="text"
|
|
id="seriesSearchInput"
|
|
placeholder="Rechercher une série (ex: Breaking Bad, Game of Thrones...)"
|
|
>
|
|
<button type="button" class="btn-primary" onclick="handleSeriesSearch()">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
</svg>
|
|
Rechercher
|
|
</button>
|
|
</div>
|
|
<div style="margin-top: 10px; padding: 10px; background: rgba(255, 107, 107, 0.1); border-radius: 8px; font-size: 12px; color: #aaa;">
|
|
💡 <strong>Info:</strong> La recherche utilise FS7 pour trouver des séries TV américaines et européennes
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Series search results -->
|
|
<div id="seriesSearchResults" style="margin-bottom: 40px;"></div>
|
|
|
|
<hr style="border: none; border-top: 1px solid rgba(255,255,255,0.1); margin: 40px 0;">
|
|
|
|
<!-- Recommendations Section -->
|
|
<div class="section-header">
|
|
<h2>🎯 Recommandé pour vous</h2>
|
|
<button class="btn-small btn-secondary" onclick="loadSeriesRecommendations()">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" style="width:14px;height:14px;">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
|
</svg>
|
|
Actualiser
|
|
</button>
|
|
</div>
|
|
<div id="seriesRecommendationsList" class="recommendations-carousel" style="margin-bottom: 40px;"></div>
|
|
|
|
<!-- Latest Releases Section -->
|
|
<div class="section-header" style="margin-top: 40px;">
|
|
<h2>🔥 Dernières sorties Séries TV</h2>
|
|
<button class="btn-small btn-secondary" onclick="loadSeriesReleases()">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" style="width:14px;height:14px;">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
|
</svg>
|
|
Dernières sorties
|
|
</button>
|
|
</div>
|
|
<div id="seriesReleasesList" class="releases-carousel"></div>
|
|
</div>
|
|
|
|
<div id="tab-providers" class="tab-content">
|
|
<div class="section-header">
|
|
<h2>📦 Fournisseurs de Streaming</h2>
|
|
</div>
|
|
<div id="providersGrid" class="search-results"></div>
|
|
</div>
|
|
|
|
{% include "components/downloads_section.html" %}
|
|
|
|
</div>
|
|
<!-- End of main-content -->
|
|
|
|
{% endblock %}
|