113 lines
3.7 KiB
PHP
113 lines
3.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
final class PrivacyController
|
||
{
|
||
private static function admin(): void
|
||
{
|
||
if (!Auth::is('admin')) {
|
||
http_response_code(403);
|
||
echo h(t('settings.admin_only'));
|
||
exit();
|
||
}
|
||
}
|
||
public static function index(): void
|
||
{
|
||
self::admin();
|
||
$settings = AppSettings::all();
|
||
$years = max(1, (int) ($settings['privacy_retention_years'] ?? 5));
|
||
render('settings_privacy.php', [
|
||
'title' => t('privacy.title'),
|
||
'settings' => $settings,
|
||
'review' => PrivacyService::retentionReview($years),
|
||
'accesses' => PrivacyService::accessLog(),
|
||
'saved' => isset($_GET['saved']),
|
||
'error' => (string) ($_GET['error'] ?? ''),
|
||
]);
|
||
}
|
||
public static function save(): void
|
||
{
|
||
self::admin();
|
||
self::postOnly();
|
||
$values = [];
|
||
foreach (
|
||
[
|
||
'privacy_retention_years' => 5,
|
||
'privacy_retention_adopter_years' => 5,
|
||
'privacy_retention_foster_years' => 5,
|
||
'privacy_retention_volunteer_years' => 5,
|
||
]
|
||
as $key => $default
|
||
) {
|
||
$values[$key] = (string) max(1, min(30, (int) ($_POST[$key] ?? $default)));
|
||
}
|
||
$values['privacy_access_log_months'] = (string) max(
|
||
1,
|
||
min(120, (int) ($_POST['privacy_access_log_months'] ?? 24)),
|
||
);
|
||
AppSettings::save($values, Auth::id());
|
||
AuditService::log(
|
||
'privacy_settings_saved',
|
||
'/settings/privacy/save',
|
||
'Politique de conservation modifiée',
|
||
null,
|
||
null,
|
||
$values,
|
||
);
|
||
header('Location: /settings/privacy?saved=1');
|
||
exit();
|
||
}
|
||
public static function export(): void
|
||
{
|
||
self::admin();
|
||
$id = (int) ($_GET['id'] ?? 0);
|
||
try {
|
||
$path = PrivacyService::exportContact($id);
|
||
PrivacyService::logAccess('contact_export', $id, null, 'contact-' . $id . '.zip', 'download');
|
||
AuditService::log(
|
||
'contact_exported',
|
||
'/settings/privacy/export',
|
||
'Export RGPD d’un contact',
|
||
'contact',
|
||
$id,
|
||
);
|
||
header('Content-Type: application/zip');
|
||
header('Content-Disposition: attachment; filename="contact-' . $id . '-globinours.zip"');
|
||
header('Content-Length: ' . filesize($path));
|
||
header('Cache-Control: private,no-store');
|
||
readfile($path);
|
||
@unlink($path);
|
||
} catch (RuntimeException $e) {
|
||
http_response_code(404);
|
||
echo h($e->getMessage());
|
||
} catch (Throwable $e) {
|
||
http_response_code(500);
|
||
echo h(SecurityService::publicError($e));
|
||
}
|
||
}
|
||
public static function anonymize(): void
|
||
{
|
||
self::admin();
|
||
self::postOnly();
|
||
$id = (int) ($_POST['id'] ?? 0);
|
||
try {
|
||
if (!isset($_POST['confirm_reviewed'])) {
|
||
throw new RuntimeException(t('privacy.review_required'));
|
||
}
|
||
PrivacyService::anonymize($id, (string) ($_POST['reason'] ?? ''));
|
||
header('Location: /settings/privacy?saved=1');
|
||
} catch (Throwable $e) {
|
||
header('Location: /settings/privacy?error=' . rawurlencode($e->getMessage()));
|
||
}
|
||
exit();
|
||
}
|
||
private static function postOnly(): void
|
||
{
|
||
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
|
||
http_response_code(405);
|
||
header('Allow: POST');
|
||
exit();
|
||
}
|
||
}
|
||
}
|