mivita/app/Http/Controllers/Web/RegisterController.php
Kevin Adametz 4c944aa15d Spamschutz Kontakt + Registrierung: Turnstile, Rate-Limit, Honeypot; Passwort min. 8
- Kontaktformular: keine Mail mehr an die eingegebene Adresse (wurde als
  Spam-Versender missbraucht); Anfrage nur an Kontakt-Adresse + Berater (BCC),
  Reply-To = Absender; Eingaben in der Mail escaped
- Kontakt + Registrierung: Cloudflare Turnstile statt reCAPTCHA (Schluessel
  aus dem Code in die .env), Rate-Limits, Honeypot + Mindest-Ausfuellzeit,
  Namensregel (lateinische Schrift, max. 50 Zeichen), Form Requests
- Registrierung: Partner-Nummer nur fuer aktive Berater (vorher ungeprueft)
- CRM: POST /register abgeschaltet (legte ohne Captcha Benutzer an)
- Passwort-Mindestlaenge systemweit 8 Zeichen ueber Password::defaults()
- Log abgefangener Anfragen: storage/logs/form-spam-*.log
- Doku und Protokoll: dev/2026-10-09-spam/README.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:22:02 +00:00

141 lines
4.5 KiB
PHP

<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Http\Requests\Register\RegisterUserRequest;
use App\Mail\MailVerifyAccount;
use App\Models\UserLevel;
use App\Repositories\UserRepository;
use App\Services\FormSpamGuard;
use App\Services\UserService;
use App\Services\Util;
use App\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Mail;
class RegisterController extends Controller
{
protected $userRepo;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct(UserRepository $userRepo, private FormSpamGuard $spamGuard)
{
$this->userRepo = $userRepo;
}
public function index()
{
if (config('app.debug')) {
\Log::channel('domain')->debug('RegisterController: index - Session user_shop', [
'session_user_shop_id' => \Session::get('user_shop')?->id,
'session_user_shop_name' => \Session::get('user_shop')?->name,
'session_user_shop_user_id' => \Session::get('user_shop')?->user_id,
'session_id' => \Session::getId(),
'session_domain' => config('session.domain'),
'request_host' => request()->getHost(),
'all_session_keys' => array_keys(\Session::all()),
]);
}
$data = [
'turnstile_site_key' => config('services.turnstile.site_key'),
'form_token' => old(FormSpamGuard::TIMESTAMP_FIELD, $this->spamGuard->makeFormToken()),
'user_shop' => Util::getUserShop(),
'yard_instance' => 'webshop',
];
return view('web.templates.registrierung', $data);
}
public function member($member_id = false)
{
if (! $member_id) {
return redirect('/registrierung');
}
if (! $this->findActiveSponsor($member_id)) {
return redirect('/registrierung');
}
$data = [
'turnstile_site_key' => config('services.turnstile.site_key'),
'form_token' => old(FormSpamGuard::TIMESTAMP_FIELD, $this->spamGuard->makeFormToken()),
'user_shop' => Util::getUserShop(),
'from_member_id' => $member_id,
'yard_instance' => 'webshop',
];
return view('web.templates.registrierung', $data);
}
public function register(RegisterUserRequest $request): RedirectResponse
{
if ($blockReason = $this->spamGuard->blockReason($request)) {
FormSpamGuard::log($request, 'register', $blockReason);
return redirect('/registrierung/finish');
}
$user_shop = Util::getUserShop();
$data = $request->validated();
$data['lang'] = ! empty(\App::getLocale()) ? \App::getLocale() : 'de';
$user = $this->userRepo->create($data);
$confirmation_code = UserService::createConfirmationCode();
$m_sponsor_id = 1;
if ($user_shop) {
$m_sponsor_id = $user_shop->user->id;
}
if (filled($data['from_member_id'] ?? null) && $sponsor = $this->findActiveSponsor($data['from_member_id'])) {
$m_sponsor_id = $sponsor->id;
}
$user->confirmation_code = $confirmation_code;
$user->confirmation_code_to = date('Y-m-d H:i:s', strtotime('+1 week'));
$user->confirmation_code_remider = 0;
$user->m_sponsor = $m_sponsor_id;
$UserLevel = UserLevel::where('default', 1)->first();
if ($UserLevel) {
$user->m_level = $UserLevel->id;
} else {
$user->m_level = 10;
}
$user->save();
$user->account->data_protection = now();
$user->account->save();
Mail::to($user->email)->locale($user->getLocale())->send(new MailVerifyAccount($confirmation_code, User::find($user->id)));
return redirect('/registrierung/finish');
}
public function finish()
{
$data = [
'user_shop' => Util::getUserShop(),
'yard_instance' => 'webshop',
];
return view('web.templates.registrierung_finish', $data);
}
/**
* Löst eine Partner-Nummer (z. B. "m1234") zu einem aktiven Berater auf.
*/
private function findActiveSponsor(string $memberId): ?User
{
$userId = (int) str_replace('m', '', $memberId) - config('mivita.add_number_id');
$user = User::find($userId);
if (! $user || ! $user->isActive() || ! $user->isActiveAccount()) {
return null;
}
return $user;
}
}