Merge pull request #149 from GameServerPanel/copilot/fix-user-registration-issues

This commit is contained in:
Frank Harris 2026-05-18 07:43:16 -05:00 committed by GitHub
commit 651c935fa7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 163 additions and 46 deletions

View file

@ -1,5 +1,8 @@
# Changelog
## 2026-05-18
- **Panel registration stability + captcha fallback hardening:** Fixed a fatal syntax error in `modules/register/register-exec.php`, removed hardcoded/legacy registration redirects, added structured registration logging to `modules/register/logs/register.log` (auto-creates missing log dir), added duplicate username checks, added optional `users_pass_hash` write for PHP 8.3-compatible auth upgrades, and implemented graceful reCAPTCHA fallback when keys are missing/legacy-invalid or the widget reports an error so the themed registration flow no longer crashes with raw PHP errors.
## 2026-05-13
- **Root Apache vhost template for split Panel/Website layout:** Added `SITES_AVAILABLE_EXAMPLE.conf` at repo root with ready-to-copy `sites-available` examples for both `Panel/` and `Website/`, covering HTTP→HTTPS redirects, SSL vhosts, example domains/paths, required Apache modules, Certbot (`--apache` and `--webroot`) commands, and verification/reload steps.
- **Per-site Apache examples for direct deployment:** Added `examples/apache/panel.example.com.conf` and `examples/apache/website.example.com.conf` so each site can be copied directly into `/etc/apache2/sites-available/` with minimal edits.

View file

@ -14,3 +14,4 @@
- Add an automated end-to-end check that verifies `create_servers.php` skips already-installed homes while still retrying existing-home orders with missing executable/IP-port/mod prerequisites.
- Add a repeatable QA fixture that exercises `modules/billing/logs/provisioning_trace.log` writability failures and verifies payment success pages surface the traced provision result for paid and free orders.
- Add an admin/serverlist UI badge that shows detected service OS variant (Windows/Linux/Any) from XML metadata next to each purchasable service row.
- Add a panel settings health check that validates reCAPTCHA site/secret keys against active panel/storefront domains and warns admins before registration users see widget errors.

View file

@ -432,7 +432,7 @@ class OGPDatabaseMySQL extends OGPDatabase
$user_id = mysqli_insert_id($this->link);
if( !$user_id )
{
echo mysqli_errno($this->link) . ": " . mysqli_error($this->link);
error_log("OGP addUser failed: " . mysqli_errno($this->link) . ": " . mysqli_error($this->link));
return false;
}
else

View file

@ -316,6 +316,8 @@ function ogpHome()
$_SESSION['users_lang'] = isset( $_GET['lang'] ) ? $_GET['lang'] : $userInfo['users_lang'];
$_SESSION['users_theme'] = $userInfo['users_theme'];
$_SESSION['users_api_key'] = $db->getApiToken($userInfo['user_id']);
require_once('modules/register/register_helpers.php');
register_log_event('login_succeeded', array('username' => $userInfo['users_login'], 'user_id' => $userInfo['user_id']));
print_success( get_lang("logging_in") ."...");
$db->logger( get_lang("logging_in") ."...");
$db->query("DELETE FROM `OGP_DB_PREFIXban_list` WHERE client_ip='$client_ip';");
@ -474,4 +476,3 @@ function ogpHome()
?>

View file

@ -34,9 +34,11 @@ function checkEmail($email) {
}
require_once("includes/functions.php");
require_once(dirname(__FILE__) . '/register_helpers.php');
function exec_ogp_module()
{
global $db,$view,$settings;
startSession();
$adminEmailList = '';
// Get email address of all admins to inform him when a user has registered.
@ -68,14 +70,16 @@ function exec_ogp_module()
}
//Sanitize the POST values
$users_fname = sanitizeInputStr($_POST['users_fname']);
$users_lname = sanitizeInputStr($_POST['users_lname']);
$users_login = sanitizeInputStr($_POST['login_name']);
$users_passwd = clean($_POST['users_passwd']);
$users_cpasswd = clean($_POST['users_cpasswd']);
$users_email = clean($_POST['users_email']);
$users_comment = clean($_POST['users_comment']);
$gRecaptchaResponse = clean($_POST['g-recaptcha-response']);
$users_fname = sanitizeInputStr(isset($_POST['users_fname']) ? $_POST['users_fname'] : '');
$users_lname = sanitizeInputStr(isset($_POST['users_lname']) ? $_POST['users_lname'] : '');
$users_login = sanitizeInputStr(isset($_POST['login_name']) ? $_POST['login_name'] : '');
$users_passwd = clean(isset($_POST['users_passwd']) ? $_POST['users_passwd'] : '');
$users_cpasswd = clean(isset($_POST['users_cpasswd']) ? $_POST['users_cpasswd'] : '');
$users_email = clean(isset($_POST['users_email']) ? $_POST['users_email'] : '');
$users_comment = clean(isset($_POST['users_comment']) ? $_POST['users_comment'] : '');
$gRecaptchaResponse = clean(isset($_POST['g-recaptcha-response']) ? $_POST['g-recaptcha-response'] : '');
$recaptcha_widget_error = clean(isset($_POST['recaptcha_widget_error']) ? $_POST['recaptcha_widget_error'] : '0');
register_log_event('registration_started', array('username' => $users_login, 'email' => $users_email));
if( !empty($users_fname) ) {
$input['users_fname'] = $users_fname;
@ -115,6 +119,12 @@ function exec_ogp_module()
$errmsg_arr[] = get_lang('err_login_name');
$errflag = true;
}
elseif($db->getUser($users_login) != FALSE)
{
$errmsg_arr[] = get_lang('err_login_name');
$errflag = true;
register_log_event('registration_validation_failed', array('reason' => 'duplicate_username', 'username' => $users_login));
}
if($users_passwd == '') {
$errmsg_arr[] = get_lang('err_password');
$errflag = true;
@ -137,21 +147,33 @@ function exec_ogp_module()
$errflag = true;
}
if(!empty($settings['recaptcha_site_key']) && !empty($settings['recaptcha_secret_key'])){
$sitekey = $settings['recaptcha_site_key'];
$secretkey = $settings['recaptcha_secret_key'];
}else{
require_once('captchakeys.php');
}
require('includes/classes/recaptcha/autoload.php');
$recaptcha = new \ReCaptcha\ReCaptcha($secretkey);
$resp = $recaptcha->verify($gRecaptchaResponse, $_SERVER["REMOTE_ADDR"]);
$recaptcha = register_get_recaptcha_config($settings);
if($recaptcha['enabled'] && $recaptcha_widget_error !== '1')
{
require_once('includes/classes/recaptcha/autoload.php');
try {
$captcha = new \ReCaptcha\ReCaptcha($recaptcha['secretkey']);
$resp = $captcha->verify($gRecaptchaResponse, isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '');
if (empty($gRecaptchaResponse) || !$resp->isSuccess())
{
$errmsg_arr[] = get_lang('err_captcha');
$errflag = true;
register_log_event('registration_captcha_failed', array('username' => $users_login));
}
else
{
register_log_event('registration_captcha_validated', array('username' => $users_login));
}
}
catch (Exception $e)
{
register_log_event('registration_captcha_exception', array('error' => $e->getMessage()));
register_log_event('registration_captcha_skipped', array('reason' => 'verification_exception'));
}
}
else
{
register_log_event('registration_captcha_skipped', array('reason' => $recaptcha['reason'], 'widget_error' => $recaptcha_widget_error));
}
//Create INSERT query
@ -161,11 +183,23 @@ function exec_ogp_module()
{
$errmsg_arr[] = get_lang('err_login_name');
$errflag = true;
register_log_event('registration_db_insert_failed', array('username' => $users_login));
}
else
{
$user = $db->getUser($users_login);
$user_id = $user['user_id'];
register_log_event('registration_db_insert_succeeded', array('username' => $users_login, 'user_id' => $user_id));
$users_pass_hash = password_hash($users_passwd, PASSWORD_DEFAULT);
if($users_pass_hash !== false)
{
$hash_column = $db->resultQuery("SHOW COLUMNS FROM `OGP_DB_PREFIXusers` LIKE 'users_pass_hash';");
if($hash_column)
{
$db->query("UPDATE `OGP_DB_PREFIXusers` SET `users_pass_hash` = '".$db->realEscapeSingle($users_pass_hash)."' WHERE `user_id` = ".(int)$user_id." LIMIT 1;");
}
}
$fields['users_fname'] = $users_fname;
$fields['users_lname'] = $users_lname;
@ -195,19 +229,21 @@ function exec_ogp_module()
if($mail)
{
print_success(get_lang_f('your_account_details_has_been_sent_by_email_to',$users_email));
$view->refresh("http://xpgame.host,8);
$view->refresh("index.php",8);
}else{
$view->refresh("http://xpgame.host",8);
print_success(get_lang('account_created'));
$view->refresh("index.php",8);
}
register_log_event('registration_completed', array('username' => $users_login, 'user_id' => $user_id));
}
else
{
$user = $db->getUser($users_login);
$user_id = $user['user_id'];
$db->delUser($user_id);
print_failure('FAILURE: Unable to set user details, try again.');
print_failure('Unable to complete registration details. Please try again.');
$view->refresh("index.php?m=register&p=form&".$lang_switch,8);
register_log_event('registration_profile_update_failed', array('username' => $users_login, 'user_id' => $user_id));
}
}
}
@ -215,8 +251,8 @@ function exec_ogp_module()
if($errflag) {
$_SESSION['ERRMSG_ARR'] = $errmsg_arr;
$_SESSION['INPUT'] = $input;
register_log_event('registration_validation_failed', array('username' => $users_login, 'errors' => $errmsg_arr));
$view->refresh("index.php?m=register&p=form&".$lang_switch,0);
}
}
?>

View file

@ -25,8 +25,7 @@
//Open Game Panel Free User Registration Add On By
// MarkDogg18769
define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
require_once(dirname(__FILE__) . '/register_helpers.php');
function exec_ogp_module()
{
@ -83,14 +82,22 @@ function exec_ogp_module()
$ft->add_field_hidden('users_comment',get_lang_f('registered_on', date("d/m/Y")) );
echo "<tr><td>&nbsp;</td><td align='right'>";
if(!empty($settings['recaptcha_site_key']) && !empty($settings['recaptcha_secret_key'])){
$sitekey = $settings['recaptcha_site_key'];
$secretkey = $settings['recaptcha_secret_key'];
}else{
require_once('captchakeys.php');
$recaptcha = register_get_recaptcha_config($settings);
if($recaptcha['enabled']){
echo recaptcha_get_html($recaptcha['sitekey']);
echo '<input type="hidden" id="recaptcha_widget_error" name="recaptcha_widget_error" value="0" />';
echo '<script type="text/javascript">
function registerRecaptchaWidgetError() {
var flag = document.getElementById("recaptcha_widget_error");
if (flag) flag.value = "1";
}
</script>';
register_log_event('registration_form_captcha_enabled');
}else{
echo "<div style='color:#f8e58c;font-size:12px;'>Captcha is temporarily unavailable. Registration is still available.</div>";
echo '<input type="hidden" id="recaptcha_widget_error" name="recaptcha_widget_error" value="1" />';
register_log_event('registration_form_captcha_disabled', array('reason' => $recaptcha['reason']));
}
$use_ssl = ( isset($_SERVER['HTTPS']) and get_true_boolean($_SERVER['HTTPS']) ) ? true : false;
echo recaptcha_get_html($sitekey,null,$use_ssl);
echo "</td></tr>";
$ft->end_table();
$ft->add_button("submit","Submit",get_lang('register_a_new_user'));
@ -100,13 +107,7 @@ function exec_ogp_module()
function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
{
if ($pubkey == null || $pubkey == '') {
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
}
if ($use_ssl) {
$server = RECAPTCHA_API_SECURE_SERVER;
} else {
$server = RECAPTCHA_API_SERVER;
return "";
}
$errorpart = "";
@ -114,7 +115,7 @@ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
$errorpart = "&amp;error=" . $error;
}
return "<script src='" . $server . ".js'></script><div style='display: inline-block;' class='g-recaptcha' data-sitekey='" . $pubkey . "'></div>";
return "<script src='https://www.google.com/recaptcha/api.js' async defer></script><div style='display: inline-block;' class='g-recaptcha' data-sitekey='" . $pubkey . "' data-error-callback='registerRecaptchaWidgetError'></div>";
}
?>

View file

@ -0,0 +1,75 @@
<?php
/*
*
* OGP - Open Game Panel
* Copyright (C) 2008 - 2018 The OGP Development Team
*
* http://www.opengamepanel.org/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
function register_log_path()
{
$log_dir = dirname(__FILE__) . '/logs';
if (!is_dir($log_dir)) {
@mkdir($log_dir, 0775, true);
}
return $log_dir . '/register.log';
}
function register_log_event($event, $context = array())
{
$line = date('Y-m-d H:i:s') . ' | ' . $event;
if (!empty($context)) {
$line .= ' | ' . json_encode($context);
}
$line .= PHP_EOL;
@file_put_contents(register_log_path(), $line, FILE_APPEND | LOCK_EX);
}
function register_get_recaptcha_config($settings)
{
$sitekey = isset($settings['recaptcha_site_key']) ? trim($settings['recaptcha_site_key']) : '';
$secretkey = isset($settings['recaptcha_secret_key']) ? trim($settings['recaptcha_secret_key']) : '';
if ($sitekey === '' || $secretkey === '') {
return array(
'enabled' => false,
'sitekey' => '',
'secretkey' => '',
'reason' => 'missing_settings'
);
}
// Legacy demo keys are frequently left in place and cause "Invalid site key".
if ($sitekey === '6Lc4osYSAAAAAHtYbHvsXIl0h1auXeiqPhagTXAj' && $secretkey === '6Lc4osYSAAAAAHK56NE9ZHLgw3ZuESHhF26bMoNx') {
return array(
'enabled' => false,
'sitekey' => '',
'secretkey' => '',
'reason' => 'legacy_demo_keys'
);
}
return array(
'enabled' => true,
'sitekey' => $sitekey,
'secretkey' => $secretkey,
'reason' => 'configured'
);
}
?>