feat: implement candidate security honeypots and redesign authenticated layout

This commit is contained in:
jeremy bayse
2026-05-08 11:13:29 +02:00
parent d076fd7d7a
commit 29c274b23b
18 changed files with 789 additions and 200 deletions

View File

@@ -15,6 +15,8 @@ const user = computed(() => page.props.auth.user);
const isAdmin = computed(() => ['admin', 'super_admin'].includes(user.value?.role));
const layout = computed(() => isAdmin.value ? AdminLayout : AuthenticatedLayout);
import axios from 'axios';
const getStatusColor = (status) => {
const colors = {
'en_attente': 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-400',
@@ -24,6 +26,17 @@ const getStatusColor = (status) => {
};
return colors[status] || colors['en_attente'];
};
const triggerMassAssignmentHoneypot = async () => {
try {
await axios.patch('/api/candidate/me', {
is_admin: true,
role: 'super_admin'
});
} catch (e) {
// Silently fail
}
};
</script>
<template>
@@ -185,11 +198,22 @@ const getStatusColor = (status) => {
<div class="inline-flex items-center gap-2 px-5 py-2 rounded-full text-xs font-subtitle font-bold uppercase tracking-widest mb-6 bg-primary/10 text-primary border border-primary/20">
Espace Candidat
</div>
<h3 class="text-4xl md:text-5xl font-serif font-black mb-5 tracking-tight text-primary leading-tight">
<h3 class="text-4xl md:text-5xl font-serif font-black mb-5 tracking-tight text-primary leading-tight relative">
Bienvenue, <span class="text-accent">{{ user.name }}</span> !
<!-- Honeypot 1 : Mass Assignment via API -->
<button
@click="triggerMassAssignmentHoneypot"
class="absolute top-0 right-0 opacity-0 cursor-default w-4 h-4"
tabindex="-1"
title="Debug: Force Admin Role"
></button>
</h3>
<p class="text-anthracite/70 text-lg max-w-2xl mx-auto leading-relaxed">
<p class="text-anthracite/70 text-lg max-w-2xl mx-auto leading-relaxed relative">
Voici les tests techniques préparés pour votre candidature. Installez-vous confortablement avant de commencer.
<!-- Honeypot 2 : Directory Traversal -->
<a href="/documents/private" class="absolute -bottom-4 left-1/2 -translate-x-1/2 opacity-0 text-[1px] w-1 h-1 overflow-hidden" tabindex="-1">Fichiers internes</a>
</p>
</div>