feat: implement full authentication system with CSRF protection and email verification flow
All checks were successful
Build and Push App / build (push) Successful in 5m59s

This commit is contained in:
2026-04-30 23:46:34 +02:00
parent 4e881bcbe6
commit 9c003d1b7d
21 changed files with 762 additions and 19 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react';
import Link from 'next/link';
import { notFound } from 'next/navigation';
import { ArrowLeft, Share2, Play, Calendar, User, Building2, MapPin, ArrowRight } from 'lucide-react';
import { sanitizeHTML } from '../../../lib/sanitize';
import { prisma } from '../../../lib/prisma';
import { InterviewType } from '@prisma/client';
@@ -158,10 +159,10 @@ export default async function AfroLifeDetailPage({ params }: Props) {
{/* Description / Article Content / Event Content */}
<div className="prose prose-lg prose-orange max-w-none mx-auto text-gray-600 break-words overflow-hidden">
{isEvent ? (
<div dangerouslySetInnerHTML={{ __html: (event as any).description }} />
<div dangerouslySetInnerHTML={{ __html: sanitizeHTML((event as any).description) }} />
) : (
!isVideo && (interview as any).content ? (
<div dangerouslySetInnerHTML={{ __html: (interview as any).content }} />
<div dangerouslySetInnerHTML={{ __html: sanitizeHTML((interview as any).content) }} />
) : (
<p className="text-xl font-serif italic text-gray-500 border-l-4 border-brand-500 pl-6 py-2">
{(interview as any).excerpt}

View File

@@ -1,6 +1,7 @@
import React from 'react';
import Link from 'next/link';
import { Play, FileText, Clock, Mic, Calendar } from 'lucide-react';
import { sanitizeHTML } from '../../lib/sanitize';
import { prisma } from '../../lib/prisma';
import { InterviewType } from '@prisma/client';
import EventTimeline from '../../components/EventTimeline';
@@ -169,7 +170,7 @@ export default async function AfroLifePage({ searchParams }: Props) {
<h3 className={`text-xl font-serif font-bold mb-2 transition-colors leading-tight line-clamp-2 ${isPastEvent ? 'text-gray-500' : 'text-gray-900 group-hover:text-brand-600'}`}>
{item.title}
</h3>
<div className="text-gray-600 text-sm line-clamp-2 prose-sm" dangerouslySetInnerHTML={{ __html: item.excerpt }} />
<div className="text-gray-600 text-sm line-clamp-2 prose-sm" dangerouslySetInnerHTML={{ __html: sanitizeHTML(item.excerpt) }} />
</div>
</Link>
);