From 7febb137e990447d7d3f5f396727d9787b48659a Mon Sep 17 00:00:00 2001 From: soufiane Date: Fri, 21 Nov 2025 01:23:50 +0100 Subject: [PATCH] feat: add SonarQube integration, cookie consent, and authentication improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add SonarQube configuration for code quality analysis - sonar-project.properties with TypeScript/Next.js settings - .sonarignore to exclude build artifacts and dependencies - npm run sonar script - Jenkins pipeline stages for SonarQube analysis and quality gate - Implement cookie consent banner - New CookieConsent component with matching site colors - localStorage persistence for user choice - Accept/Reject buttons with proper styling - Link to cookies policy page - Add strict authentication protection for game page - Redirect unauthenticated users to login from /jeux - Clean up redundant auth checks and UI elements - Preserve redirect parameter for post-login navigation - Implement smart navigation with auth-aware redirects - "Jouer maintenant" button redirects based on auth status - "Participer au jeu" footer link with conditional routing - Authenticated users go to /jeux, others to /register - UI improvements and cleanup - Remove "Voir les lots" button from homepage - Remove "Gestion des cookies" from footer - Remove "À propos" from footer navigation - Consistent design across components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .sonarignore | 50 ++++++++++++++++++++++ Jenkinsfile | 26 ++++++++++++ app/jeux/page.tsx | 65 +++++++++-------------------- app/layout-client.tsx | 2 + app/login/page.tsx | 9 ++-- app/page.tsx | 5 ++- app/register/page.tsx | 9 ++-- components/AboutContest.tsx | 81 ++++++++++++++---------------------- components/CookieConsent.tsx | 65 +++++++++++++++++++++++++++++ components/Footer.tsx | 20 ++------- components/Header.tsx | 18 ++++---- package.json | 3 +- sonar-project.properties | 33 +++++++++++++++ 13 files changed, 255 insertions(+), 131 deletions(-) create mode 100644 .sonarignore create mode 100644 components/CookieConsent.tsx create mode 100644 sonar-project.properties diff --git a/.sonarignore b/.sonarignore new file mode 100644 index 0000000..06f4bd5 --- /dev/null +++ b/.sonarignore @@ -0,0 +1,50 @@ +# Dependencies +node_modules/ +**/node_modules/** + +# Build outputs +.next/ +out/ +dist/ +build/ + +# Testing +coverage/ +.nyc_output/ + +# Static files +public/ + +# Configuration files +*.config.js +*.config.ts +next.config.js +tailwind.config.js +postcss.config.js +jest.config.js +jest.setup.js + +# Environment files +.env* +!.env.example + +# Logs +logs/ +*.log +npm-debug.log* + +# IDE +.vscode/ +.idea/ + +# Docker +Dockerfile +docker-compose*.yml + +# CI/CD +Jenkinsfile +.github/ + +# Backups +*.backup +*.bak diff --git a/Jenkinsfile b/Jenkinsfile index c446770..bd1d3c1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -79,6 +79,32 @@ pipeline { } } + stage('SonarQube Analysis') { + agent { + docker { + image 'sonarsource/sonar-scanner-cli:latest' + args '-u root' + } + } + steps { + echo "🔍 Analyse de la qualité du code avec SonarQube..." + script { + withSonarQubeEnv('SonarQube') { + sh 'sonar-scanner' + } + } + } + } + + stage('Quality Gate') { + steps { + echo "🚦 Vérification du Quality Gate SonarQube..." + timeout(time: 5, unit: 'MINUTES') { + waitForQualityGate abortPipeline: true + } + } + } + stage('Build Frontend') { agent { docker { diff --git a/app/jeux/page.tsx b/app/jeux/page.tsx index aa4b0b2..aca3fc7 100644 --- a/app/jeux/page.tsx +++ b/app/jeux/page.tsx @@ -34,6 +34,13 @@ export default function JeuxPage() { const [currentPrizeIndex, setCurrentPrizeIndex] = useState(0); const [isSpinning, setIsSpinning] = useState(false); + // Protection stricte: redirection si non connecté + useEffect(() => { + if (!isAuthenticated) { + router.push(`${ROUTES.LOGIN}?redirect=/jeux`); + } + }, [isAuthenticated, router]); + const { register, handleSubmit, @@ -58,12 +65,6 @@ export default function JeuxPage() { // Réinitialiser le message d'erreur setErrorMessage(""); - // Si non connecté, rediriger vers login - if (!isAuthenticated) { - router.push(`${ROUTES.LOGIN}?redirect=/jeux`); - return; - } - // Afficher la modal de roulette et démarrer l'animation setShowRouletteModal(true); setIsSpinning(true); @@ -122,21 +123,10 @@ export default function JeuxPage() {
- {isAuthenticated ? ( -

- Bonjour {user?.firstName}, - entrez le code de 10 caractères présent sur votre ticket de caisse -

- ) : ( -
-

- 💡 Vous devez être connecté pour valider votre code. - - Connectez-vous - -

-
- )} +

+ Bonjour {user?.firstName}, + entrez le code de 10 caractères présent sur votre ticket de caisse +

@@ -184,30 +174,15 @@ export default function JeuxPage() {
- {!isAuthenticated && ( -
-

- Pas encore de compte ? -

- - - -
- )} - - {isAuthenticated && ( -
-

- 💡 Bon à savoir : -

-
    -
  • Chaque code ne peut être utilisé qu'une seule fois
  • -
  • Consultez vos tickets sur la page Mes gains
  • -
-
- )} +
+

+ 💡 Bon à savoir : +

+
    +
  • Chaque code ne peut être utilisé qu'une seule fois
  • +
  • Consultez vos tickets sur la page Mes gains
  • +
+
diff --git a/app/layout-client.tsx b/app/layout-client.tsx index eaca7b4..d94851b 100644 --- a/app/layout-client.tsx +++ b/app/layout-client.tsx @@ -3,6 +3,7 @@ import { usePathname } from "next/navigation"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; +import CookieConsent from "@/components/CookieConsent"; export default function LayoutClient({ children }: { children: React.ReactNode }) { const pathname = usePathname(); @@ -23,6 +24,7 @@ export default function LayoutClient({ children }: { children: React.ReactNode } {children}