Update from Git Manager GUI
This commit is contained in:
@@ -43,23 +43,46 @@ class WBF_Ajax {
|
||||
// ── Auth ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public static function handle_login() {
|
||||
// Brute-Force-Schutz: max. 10 Versuche pro IP in 15 Minuten
|
||||
$ip_key = 'wbf_login_fail_' . md5( $_SERVER['REMOTE_ADDR'] ?? 'unknown' );
|
||||
$fails = (int) get_transient( $ip_key );
|
||||
if ( $fails >= 10 ) {
|
||||
wp_send_json_error([
|
||||
'message' => 'Zu viele fehlgeschlagene Loginversuche. Bitte warte 15 Minuten.',
|
||||
'locked' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
// Login braucht keinen Nonce — Credentials sind die Authentifizierung
|
||||
$result = WBF_Auth::login(
|
||||
sanitize_text_field($_POST['username'] ?? ''),
|
||||
$_POST['password'] ?? ''
|
||||
);
|
||||
if ($result['success']) {
|
||||
// Erfolgreicher Login: Fehlzähler löschen
|
||||
delete_transient( $ip_key );
|
||||
$u = $result['user'];
|
||||
if ( ! empty($_POST['remember_me']) ) {
|
||||
WBF_Auth::set_remember_cookie($u->id);
|
||||
}
|
||||
wp_send_json_success(['display_name'=>$u->display_name,'avatar_url'=>$u->avatar_url,'user_id'=>$u->id]);
|
||||
} else {
|
||||
// Fehlversuch zählen — außer bei gesperrten Konten (kein Passwortfehler)
|
||||
if ( empty($result['banned']) ) {
|
||||
set_transient( $ip_key, $fails + 1, 15 * MINUTE_IN_SECONDS );
|
||||
}
|
||||
wp_send_json_error($result);
|
||||
}
|
||||
}
|
||||
|
||||
public static function handle_register() {
|
||||
// Brute-Force/Spam-Schutz: max. 5 Registrierungen pro IP pro Stunde
|
||||
$reg_ip_key = 'wbf_reg_ip_' . md5( $_SERVER['REMOTE_ADDR'] ?? 'unknown' );
|
||||
$reg_fails = (int) get_transient( $reg_ip_key );
|
||||
if ( $reg_fails >= 5 ) {
|
||||
wp_send_json_error(['message' => 'Zu viele Registrierungsversuche von dieser IP. Bitte warte eine Stunde.']);
|
||||
}
|
||||
|
||||
// Spam-Schutz: Honeypot + Zeitlimit
|
||||
if ( ! empty($_POST['wbf_website']) ) {
|
||||
wp_send_json_error(['message' => 'Spam erkannt.']);
|
||||
@@ -98,6 +121,8 @@ class WBF_Ajax {
|
||||
sanitize_text_field($_POST['display_name'] ?? '')
|
||||
);
|
||||
if ($result['success']) {
|
||||
// Registrierungs-Zähler für IP erhöhen
|
||||
set_transient( $reg_ip_key, $reg_fails + 1, HOUR_IN_SECONDS );
|
||||
$u = $result['user'];
|
||||
// Einladungscode einlösen
|
||||
$reg_mode2 = wbf_get_settings()['registration_mode'] ?? 'open';
|
||||
@@ -226,9 +251,11 @@ class WBF_Ajax {
|
||||
}
|
||||
// Thread-Abonnenten benachrichtigen
|
||||
$subscribers = WBF_DB::get_thread_subscribers($thread_id);
|
||||
// $notif_users is a flat array of IDs (from get_col) — cast to int for comparison
|
||||
$notif_ids = array_map('intval', $notif_users);
|
||||
foreach ($subscribers as $sub) {
|
||||
if ((int)$sub->id === (int)$user->id) continue; // nicht sich selbst
|
||||
if (in_array($sub->id, array_column($notif_users, 'id') ?: [])) continue; // schon benachrichtigt
|
||||
if (in_array((int)$sub->id, $notif_ids, true)) continue; // schon benachrichtigt
|
||||
self::send_notification_email($sub, 'reply', $user->display_name, [
|
||||
'thread_id' => $thread_id,
|
||||
'thread_title' => $thread->title,
|
||||
@@ -372,6 +399,19 @@ class WBF_Ajax {
|
||||
|
||||
if (!empty($_POST['new_password'])) {
|
||||
if (strlen($_POST['new_password']) < 6) wp_send_json_error(['message'=>'Passwort mindestens 6 Zeichen.']);
|
||||
// Sicherheit: aktuelles Passwort muss zur Bestätigung angegeben werden
|
||||
$current_pw = $_POST['current_password'] ?? '';
|
||||
if ( empty($current_pw) ) {
|
||||
wp_send_json_error(['message'=>'Bitte aktuelles Passwort zur Bestätigung eingeben.']);
|
||||
}
|
||||
if ( ! password_verify($current_pw, $user->password) ) {
|
||||
wp_send_json_error(['message'=>'Aktuelles Passwort ist falsch.']);
|
||||
}
|
||||
// Bestätigungsfeld server-seitig prüfen
|
||||
$new_pw2 = $_POST['new_password2'] ?? '';
|
||||
if ( ! empty($new_pw2) && $new_pw2 !== $_POST['new_password'] ) {
|
||||
wp_send_json_error(['message'=>'Die Passwörter stimmen nicht überein.']);
|
||||
}
|
||||
$update['password'] = password_hash($_POST['new_password'], PASSWORD_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -397,6 +437,15 @@ class WBF_Ajax {
|
||||
$value = sanitize_textarea_field( $raw );
|
||||
} elseif ( $def['type'] === 'number' ) {
|
||||
$value = is_numeric($raw) ? (string)(float)$raw : '';
|
||||
} elseif ( $def['type'] === 'date' ) {
|
||||
// Datum validieren — nur YYYY-MM-DD, nicht in der Zukunft
|
||||
$raw_date = sanitize_text_field( trim($raw) );
|
||||
if ( preg_match('/^\d{4}-\d{2}-\d{2}$/', $raw_date) ) {
|
||||
$ts = strtotime($raw_date);
|
||||
$value = ($ts && $ts <= time()) ? $raw_date : '';
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
} else {
|
||||
$value = sanitize_text_field( $raw );
|
||||
}
|
||||
@@ -594,7 +643,8 @@ class WBF_Ajax {
|
||||
self::verify();
|
||||
$query = sanitize_text_field( $_POST['query'] ?? '' );
|
||||
if ( mb_strlen( $query ) < 2 ) wp_send_json_error(['message' => 'Suchbegriff zu kurz.']);
|
||||
$results = WBF_DB::search( $query, 40 );
|
||||
$current_search = WBF_Auth::get_current_user();
|
||||
$results = WBF_DB::search( $query, 40, $current_search );
|
||||
wp_send_json_success(['results' => $results, 'query' => $query]);
|
||||
}
|
||||
|
||||
@@ -1141,6 +1191,12 @@ class WBF_Ajax {
|
||||
self::verify();
|
||||
$user = WBF_Auth::get_current_user();
|
||||
if (!$user) wp_send_json_error(['message'=>'Nicht eingeloggt.']);
|
||||
// Sicherstellen dass Spalte existiert (Schutz für bestehende Installs)
|
||||
global $wpdb;
|
||||
$cols = $wpdb->get_col( "DESCRIBE {$wpdb->prefix}forum_users" );
|
||||
if ( ! in_array( 'profile_public', $cols ) ) {
|
||||
$wpdb->query( "ALTER TABLE {$wpdb->prefix}forum_users ADD COLUMN profile_public TINYINT(1) NOT NULL DEFAULT 1" );
|
||||
}
|
||||
$current = (int)($user->profile_public ?? 1);
|
||||
$new = $current ? 0 : 1;
|
||||
WBF_DB::update_user($user->id, ['profile_public'=>$new]);
|
||||
|
||||
Reference in New Issue
Block a user