- 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>
141 lines
4.5 KiB
PHP
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;
|
|
}
|
|
}
|