- Fix: Notifiable-Trait zum User-Model hinzugefuegt (behebt notify()-500er) - Installer: SMTP-Verbindungstest mit EsmtpTransport + Ueberspringen-Link - Admin: Neuer E-Mail-Tab mit SMTP-Konfiguration + Verbindungstest - Admin: Lazy Quill-Initialisierung (nur sichtbare Locale wird geladen) - Uebersetzungen: 17 neue Mail-Keys in allen 6 Sprachen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
208 lines
6.5 KiB
PHP
Executable File
208 lines
6.5 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Enums\UserRole;
|
|
use App\Models\ActivityLog;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\View\View;
|
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
|
|
class ProfileController extends Controller
|
|
{
|
|
public function edit(): View
|
|
{
|
|
$user = auth()->user();
|
|
$user->load('children.team');
|
|
|
|
return view('profile.edit', compact('user'));
|
|
}
|
|
|
|
public function update(Request $request): RedirectResponse
|
|
{
|
|
$supported = \App\Http\Middleware\SetLocaleMiddleware::supportedLocales();
|
|
|
|
$request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'phone' => ['nullable', 'string', 'max:30'],
|
|
'locale' => ['nullable', 'string', 'in:' . implode(',', $supported)],
|
|
'profile_picture' => ['nullable', 'image', 'max:2048', 'mimes:jpg,jpeg,png,gif,webp'],
|
|
]);
|
|
|
|
$user = auth()->user();
|
|
|
|
// Handle profile picture upload
|
|
if ($request->hasFile('profile_picture')) {
|
|
// Delete old picture
|
|
if ($user->profile_picture) {
|
|
Storage::disk('public')->delete($user->profile_picture);
|
|
}
|
|
|
|
$file = $request->file('profile_picture');
|
|
$storedName = 'avatars/' . Str::uuid() . '.' . $file->guessExtension();
|
|
Storage::disk('public')->putFileAs('', $file, $storedName);
|
|
|
|
$user->profile_picture = $storedName;
|
|
}
|
|
|
|
$user->update([
|
|
'name' => $request->name,
|
|
'phone' => $request->input('phone'),
|
|
'locale' => $request->input('locale', 'de'),
|
|
'profile_picture' => $user->profile_picture,
|
|
]);
|
|
|
|
return back()->with('success', __('profile.updated'));
|
|
}
|
|
|
|
public function removePicture(): RedirectResponse
|
|
{
|
|
$user = auth()->user();
|
|
|
|
if ($user->profile_picture) {
|
|
Storage::disk('public')->delete($user->profile_picture);
|
|
$user->update(['profile_picture' => null]);
|
|
}
|
|
|
|
return back()->with('success', __('admin.picture_removed'));
|
|
}
|
|
|
|
public function uploadDsgvoConsent(Request $request): RedirectResponse
|
|
{
|
|
$request->validate([
|
|
'dsgvo_consent_file' => ['required', 'file', 'max:10240', 'mimes:pdf,jpg,jpeg,png,gif,webp'],
|
|
]);
|
|
|
|
$user = auth()->user();
|
|
|
|
// Alte Datei löschen falls vorhanden
|
|
if ($user->dsgvo_consent_file) {
|
|
Storage::disk('local')->delete($user->dsgvo_consent_file);
|
|
}
|
|
|
|
$file = $request->file('dsgvo_consent_file');
|
|
$storedName = 'dsgvo/' . Str::uuid() . '.' . $file->guessExtension();
|
|
Storage::disk('local')->putFileAs('', $file, $storedName);
|
|
|
|
// Bei Re-Upload: Bestätigung zurücksetzen
|
|
$user->dsgvo_consent_file = $storedName;
|
|
$user->dsgvo_accepted_at = null;
|
|
$user->dsgvo_accepted_by = null;
|
|
$user->save();
|
|
|
|
ActivityLog::log(
|
|
'dsgvo_consent_uploaded',
|
|
__('admin.log_dsgvo_consent_uploaded', ['name' => $user->name]),
|
|
'User',
|
|
$user->id
|
|
);
|
|
|
|
return back()->with('success', __('profile.dsgvo_uploaded'));
|
|
}
|
|
|
|
public function removeDsgvoConsent(): RedirectResponse
|
|
{
|
|
$user = auth()->user();
|
|
|
|
if ($user->dsgvo_consent_file) {
|
|
Storage::disk('local')->delete($user->dsgvo_consent_file);
|
|
$user->dsgvo_consent_file = null;
|
|
$user->dsgvo_accepted_at = null;
|
|
$user->dsgvo_accepted_by = null;
|
|
$user->save();
|
|
|
|
ActivityLog::log(
|
|
'dsgvo_consent_removed',
|
|
__('admin.log_dsgvo_consent_removed', ['name' => $user->name]),
|
|
'User',
|
|
$user->id
|
|
);
|
|
}
|
|
|
|
return back()->with('success', __('profile.dsgvo_removed'));
|
|
}
|
|
|
|
public function downloadDsgvoConsent(): BinaryFileResponse
|
|
{
|
|
$user = auth()->user();
|
|
|
|
if (!$user->dsgvo_consent_file || !str_starts_with($user->dsgvo_consent_file, 'dsgvo/') || !Storage::disk('local')->exists($user->dsgvo_consent_file)) {
|
|
abort(404);
|
|
}
|
|
|
|
$mimeType = Storage::disk('local')->mimeType($user->dsgvo_consent_file);
|
|
|
|
return response()->file(
|
|
Storage::disk('local')->path($user->dsgvo_consent_file),
|
|
['Content-Type' => $mimeType]
|
|
);
|
|
}
|
|
|
|
public function destroy(Request $request): RedirectResponse
|
|
{
|
|
$request->validate([
|
|
'password' => ['required', 'current_password'],
|
|
]);
|
|
|
|
$user = auth()->user();
|
|
|
|
// Admin (ID 1) kann nicht selbst löschen
|
|
if ($user->id === 1) {
|
|
return back()->with('error', __('profile.cannot_delete_admin'));
|
|
}
|
|
|
|
// Staff (Admin/Trainer) können sich nicht über die Profilseite löschen
|
|
if ($user->isStaff()) {
|
|
return back()->with('error', __('profile.cannot_delete_staff'));
|
|
}
|
|
|
|
// Verwaiste Kinder ermitteln und deaktivieren
|
|
$orphanedChildren = $user->getOrphanedChildren();
|
|
$orphanedChildNames = [];
|
|
|
|
foreach ($orphanedChildren as $child) {
|
|
$child->delete();
|
|
$orphanedChildNames[] = $child->full_name;
|
|
|
|
ActivityLog::log(
|
|
'child_auto_deactivated',
|
|
__('admin.log_child_auto_deactivated', [
|
|
'child' => $child->full_name,
|
|
'parent' => $user->name,
|
|
]),
|
|
'Player',
|
|
$child->id,
|
|
['parent_user_id' => $user->id, 'reason' => 'sole_parent_self_deleted']
|
|
);
|
|
}
|
|
|
|
// Selbstlöschung loggen
|
|
ActivityLog::logWithChanges(
|
|
'account_self_deleted',
|
|
__('admin.log_account_self_deleted', ['name' => $user->name]),
|
|
'User',
|
|
$user->id,
|
|
[
|
|
'name' => $user->name,
|
|
'email' => $user->email,
|
|
'role' => $user->role->value,
|
|
'orphaned_children' => $orphanedChildNames,
|
|
],
|
|
null
|
|
);
|
|
|
|
// Logout + Session invalidieren
|
|
auth()->logout();
|
|
$request->session()->invalidate();
|
|
$request->session()->regenerateToken();
|
|
|
|
// User soft-deleten
|
|
$user->delete();
|
|
|
|
return redirect()->route('login')->with('success', __('profile.account_deleted'));
|
|
}
|
|
}
|