Add reCAPTCHA support and enhance Economic configurations

Introduce reCAPTCHA integration with validation and configuration handling. Update Economic module to include layout management and dynamic configuration via API. Added traits for managing module settings and encapsulated new endpoint routes for expanded functionality.
This commit is contained in:
Jepp9350
2025-02-10 15:27:32 +01:00
parent ac657d6130
commit 172e37d3a2
19 changed files with 979 additions and 13 deletions
+17
View File
@@ -1,17 +1,26 @@
<?php
namespace classes;
require_once WD . '/modules/economic/economic_c.php';
require_once WD . '/modules/economic/endpoints/economic_orders_endpoint.php';
require_once WD . '/modules/economic/endpoints/economic_invoices_endpoint.php';
require_once WD . '/modules/economic/endpoints/economic_departments_endpoint.php';
require_once WD . '/modules/economic/endpoints/economic_layouts_endpoint.php';
use economic_c;
use endpoints\economic_departments_endpoint;
use endpoints\economic_invoices_endpoint;
use endpoints\economic_layouts_endpoint;
use endpoints\economic_orders_endpoint;
use interfaces\economic_i;
class economic implements economic_i
{
/**
* Configuration of the economic module
* @var economic_c
*/
public economic_c $config;
/**
* Any endpoints reached by the /orders endpoint
* @var economic_orders_endpoint
@@ -27,11 +36,19 @@ class economic implements economic_i
* @var economic_departments_endpoint
*/
public economic_departments_endpoint $departments;
/**
* Any endpoints reached by the /layouts endpoint
* @var economic_layouts_endpoint
*/
public economic_layouts_endpoint $layouts;
public function __construct()
{
$this->config = new economic_c();
$this->orders = new economic_orders_endpoint();
$this->invoices = new economic_invoices_endpoint();
$this->departments = new economic_departments_endpoint();
$this->layouts = new economic_layouts_endpoint();
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace classes;
require_once WD . '/modules/reCAPTCHA/reCAPTCHA_c.php';
use Exception;
use interfaces\recaptcha_i;
use reCAPTCHA\reCAPTCHA_c;
class recaptcha implements recaptcha_i
{
/**
* Configuration of the reCAPTCHA module
* @var recaptcha_c
*/
public recaptcha_c $config;
public function __construct()
{
$this->config = new recaptcha_c();
}
/**
* Validate the reCAPTCHA response
* @param string|null $response The response from the reCAPTCHA
* @return bool Whether the response is valid
* @throws Exception
*/
public function validate(string|null $response): bool
{
if (!$this->config->enabled->isTrue()) {
return true;
}
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = [
'secret' => $this->config->secret_key_v2->getVariableValue(),
'response' => $response
];
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$responseKeys = json_decode($response, true);
return $responseKeys['success'];
}
public function getPublicConfig(): array
{
return [
'enabled' => $this->config->enabled->isTrue(),
'site_key' => $this->config->site_key_v2->getVariableValue()
];
}
}
+1
View File
@@ -51,6 +51,7 @@ require_once 'classes/wordpress_bookings_remote.php';
require_once 'classes/language_packs.php';
require_once 'classes/economic.php';
require_once 'classes/statistics.php';
require_once 'classes/recaptcha.php';
/**
* Modules
@@ -0,0 +1,8 @@
<?php
namespace interfaces;
interface recaptcha_i
{
}
@@ -0,0 +1,28 @@
<?php
namespace config;
use traits\module_config_variable;
class economic_invoice_layout_c
{
use module_config_variable;
/**
* @throws \Exception
*/
public function __construct()
{
self::setupConfigVariable(
'economic',
'invoiceLayoutNumber',
'int',
true,
null,
'The layout number for the invoice',
'1',
false,
1
);
}
}
@@ -0,0 +1,21 @@
<?php
require_once WD . '/modules/economic/config/economic_invoice_layout_c.php';
use config\economic_invoice_layout_c;
use traits\module_config_t;
class economic_c
{
use module_config_t;
public economic_invoice_layout_c $invoice_layout;
public function __construct()
{
$this->setupConfig('economic');
$this->allowUpdate([
economic_invoice_layout_c::class
]);
$this->invoice_layout = new economic_invoice_layout_c();
}
}
@@ -1,7 +1,10 @@
<?php
use classes\economic;
class economic_m
{
public economic $economic;
/**
* https://secure.e-conomic.com/secure/api1/requestaccess.aspx?appPublicToken=WeG89W2Y63wLjy1lnqfpsHlfa1mBiyNKByqtGmBOoOw&redirectUrl=truckwash.dk
*/
@@ -9,13 +12,25 @@ class economic_m
private string $appAccessGrant;
private string $app_token;
private string $appAccessGrant2;
public function __construct()
{
global $ECONOMIC_API;
$this->app_token = $ECONOMIC_API['app_secret_token'];
$this->appAccessGrant = $ECONOMIC_API['app_access_grant'];
$this->appAccessGrant2 = $ECONOMIC_API['app_access_grant2'];
$this->economic = new economic();
}
/**
* Allowed search filters
* @return array
*/
public function allowed_search_filters_customers(): array
{
return [
'address', 'balance', 'barred', 'city', 'corporateIdentificationNumber', 'country', 'creditLimit', 'currency', 'customerGroup.customerGroupNumber', 'customerNumber', 'ean', 'email', 'lastUpdated', 'mobilePhone', 'name', 'publicEntryNumber', 'telephoneAndFaxNumber', 'vatNumber', 'website', 'zip'
];
}
/**
@@ -40,7 +55,7 @@ class economic_m
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => array(
'X-AppSecretToken: ' . $this->app_token,
'X-AgreementGrantToken: ' . ( $authToken2 ? $this->appAccessGrant2 : $this->appAccessGrant ),
'X-AgreementGrantToken: ' . ($authToken2 ? $this->appAccessGrant2 : $this->appAccessGrant),
'Content-Type: application/json'
),
));
@@ -53,15 +68,4 @@ class economic_m
curl_close($curl);
return $response;
}
/**
* Allowed search filters
* @return array
*/
public function allowed_search_filters_customers(): array
{
return [
'address', 'balance', 'barred', 'city', 'corporateIdentificationNumber', 'country', 'creditLimit', 'currency', 'customerGroup.customerGroupNumber', 'customerNumber', 'ean', 'email', 'lastUpdated', 'mobilePhone', 'name', 'publicEntryNumber', 'telephoneAndFaxNumber', 'vatNumber', 'website', 'zip'
];
}
}
@@ -0,0 +1,24 @@
<?php
namespace endpoints;
use traits\economic_endpoint_t;
class economic_layouts_endpoint
{
use economic_endpoint_t;
/**
* List all layouts
* @return object {collection: [layout]}
*/
public function get(): object
{
$response = $this->send_request(
'/layouts/',
'GET');
// Return the response as an object
return json_decode($response);
}
}
@@ -48,7 +48,7 @@ class economic_invoice_draft_mo extends economicInvoicesDrafts
'currency' => 'DKK',
'date' => date('Y-m-d'),
'layout' => [
'layoutNumber' => 1
'layoutNumber' => (int)$this->economic->config->invoice_layout->getVariableValue()
],
'paymentTerms' => [
'paymentTermsNumber' => 1
@@ -0,0 +1,29 @@
<?php
namespace reCAPTCHA\config;
use Exception;
use traits\module_config_variable;
class reCAPTCHA_enabled_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'reCAPTCHA',
'enabled',
'bool',
true,
null,
'Whether reCAPTCHA is enabled',
'1',
false,
'false'
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace reCAPTCHA\config;
use Exception;
use traits\module_config_variable;
class reCAPTCHA_secret_key_v2_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'reCAPTCHA',
'secret_key_v2',
'string',
false,
null,
'The secret key for reCAPTCHA v2',
'1',
true,
''
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace reCAPTCHA\config;
use Exception;
use traits\module_config_variable;
class reCAPTCHA_site_key_v2_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'reCAPTCHA',
'site_key_v2',
'string',
false,
null,
'The site key for reCAPTCHA v2',
'1',
true,
''
);
}
}
@@ -0,0 +1,45 @@
<?php
namespace reCAPTCHA;
require_once WD . '/modules/reCAPTCHA/config/reCAPTCHA_enabled_c.php';
require_once WD . '/modules/reCAPTCHA/config/reCAPTCHA_secret_key_v2_c.php';
require_once WD . '/modules/reCAPTCHA/config/reCAPTCHA_site_key_v2_c.php';
use reCAPTCHA\config\reCAPTCHA_enabled_c;
use reCAPTCHA\config\reCAPTCHA_secret_key_v2_c;
use reCAPTCHA\config\reCAPTCHA_site_key_v2_c;
use traits\module_config_t;
class reCAPTCHA_c
{
use module_config_t;
/**
* The status of reCAPTCHA, whether it is enabled or not
* @var reCAPTCHA_enabled_c
*/
public reCAPTCHA_enabled_c $enabled;
/**
* The site key for reCAPTCHA v2
* @var reCAPTCHA_site_key_v2_c
*/
public reCAPTCHA_site_key_v2_c $site_key_v2;
/**
* The secret key for reCAPTCHA v2
* @var reCAPTCHA_secret_key_v2_c
*/
public reCAPTCHA_secret_key_v2_c $secret_key_v2;
public function __construct()
{
$this->setupConfig('reCAPTCHA');
$this->allowUpdate([
reCAPTCHA_enabled_c::class,
reCAPTCHA_secret_key_v2_c::class,
reCAPTCHA_site_key_v2_c::class
]);
$this->enabled = new reCAPTCHA_enabled_c();
$this->secret_key_v2 = new reCAPTCHA_secret_key_v2_c();
$this->site_key_v2 = new reCAPTCHA_site_key_v2_c();
}
}
+21
View File
@@ -3,6 +3,7 @@
namespace routes;
use classes\authentication;
use classes\recaptcha;
use objects\logs_o;
use objects\tokens_o;
use traits\route_t;
@@ -16,6 +17,7 @@ class authRoute
$this->post('/auth/login', function () {
// Get the post data
global $response;
$this->requireRecaptcha();
$data = json_decode(file_get_contents('php://input'), true);
// Check if the customer number, and password are set
if (!isset($data['customer_number']) || empty($data['customer_number']) || !is_numeric($data['customer_number']) || $data['customer_number'] < 1) {
@@ -80,6 +82,7 @@ class authRoute
$this->post('/auth/employee/login', function () {
// Get the post data
global $response;
$this->requireRecaptcha();
$data = json_decode(file_get_contents('php://input'), true);
// Check if the employee number, and password are set
if (!isset($data['user_id'])) {
@@ -102,5 +105,23 @@ class authRoute
// Return the token
$response->success(['token' => $token]);
});
$this->get('/auth/reCAPTCHA/public', function () {
// Check if the user:
// 1. Is rate limited (future feature)
// 2. Is required to solve a reCAPTCHA
global $response;
$recaptcha = (new recaptcha())->getPublicConfig();
$response->success([
'rate_limit' => [
'enabled' => false,
'limit' => 0,
'remaining' => 0,
'reset' => 0,
'warning' => null
],
'recaptcha' => $recaptcha
]);
});
}
}
@@ -0,0 +1,38 @@
<?php
namespace routes;
use classes\authentication;
use classes\economic;
use classes\response;
use classes\router;
use objects\logs_o;
use traits\route_t;
class economicLayoutsRoute
{
use route_t;
public function run(): void
{
global /** @var response $response */
/** @var router $router */
$router, $response;
$this->get('/economic/layouts', function () {
global $response;
$this->requirePermission('economic_layouts');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('economic_layouts', 'global', 1, $user->id, 'ECONOMIC_LAYOUTS', 'Successfully fetched economic layouts');
$response->success(
(new economic())->layouts->get()->collection
);
} else {
(new logs_o())->add('economic_layouts', 'global', 1, 0, 'ECONOMIC_LAYOUTS', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
});
}
}
@@ -0,0 +1,88 @@
<?php
namespace routes;
use classes\authentication;
use classes\economic;
use classes\recaptcha;
use classes\response;
use classes\router;
use objects\logs_o;
use traits\route_t;
class moduleConfigRoute
{
use route_t;
public function run(): void
{
global /** @var response $response */
/** @var router $router */
$router, $response;
/** Economic config > GET */
$this->get('/economic/config', function () {
global $response;
$this->requirePermission('economic_config');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('economic_config', 'global', 1, $user->id, 'ECONOMIC_CONFIG', 'Successfully fetched economic config');
$response->success(
(new economic())->config->getConfigRequest()
);
} else {
(new logs_o())->add('economic_config', 'global', 1, 0, 'ECONOMIC_CONFIG', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
});
/** Economic config > POST */
$this->post('/economic/config', function () {
global $response;
$this->requirePermission('economic_config');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('economic_config', 'global', 1, $user->id, 'ECONOMIC_CONFIG', 'Successfully updated economic config');
$response->success(
(new economic())->config->postConfigRequest()
);
} else {
(new logs_o())->add('economic_config', 'global', 1, 0, 'ECONOMIC_CONFIG', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
});
/** reCAPTCHA config > GET */
$this->get('/reCAPTCHA/config', function () {
global $response;
$this->requirePermission('recaptcha_config');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('recaptcha_config', 'global', 1, $user->id, 'RECAPTCHA_CONFIG', 'Successfully fetched recaptcha config');
$response->success(
(new recaptcha())->config->getConfigRequest()
);
} else {
(new logs_o())->add('recaptcha_config', 'global', 1, 0, 'RECAPTCHA_CONFIG', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
});
/** reCAPTCHA config > POST */
$this->post('/reCAPTCHA/config', function () {
global $response;
$this->requirePermission('recaptcha_config');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('recaptcha_config', 'global', 1, $user->id, 'RECAPTCHA_CONFIG', 'Successfully updated recaptcha config');
$response->success(
(new recaptcha())->config->postConfigRequest()
);
} else {
(new logs_o())->add('recaptcha_config', 'global', 1, 0, 'RECAPTCHA_CONFIG', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
});
}
}
@@ -0,0 +1,199 @@
<?php
namespace traits;
use classes\db;
trait module_config_t
{
public string $module_name; // The name of the module
public array $config_classes; // An array of classes that contain config variables for the module, that's allowed to be updated by the user using the API
/**
* Set up the config variable
* @param string $module_name
* @return void
*/
function setupConfig(string $module_name): void
{
$this->module_name = $module_name;
}
/**
* Allow the user to update the config variables
* @param array $config_classes
* @return void
*/
function allowUpdate(array $config_classes): void
{
$this->config_classes = $config_classes;
}
/**
* Post config request
* @return bool
*/
function postConfigRequest(): bool
{
// Check if the request has a variable name and value
global $response;
if ($response->getRequestParameter('variable') === null || $response->getRequestParameter('value') === null) {
$response->error('Variable and value not set', 400);
}
// Get the variable name and value
$variable = $response->getRequestParameter('variable');
$value = $response->getRequestParameter('value');
// Sanitize the variable name and value
global /** @var db $db */
$db;
$variable = $db->escape_string($variable);
$value = $db->escape_string($value);
// Check if the variable is allowed to be updated
if (!self::isVariableAllowed($variable)) {
// Return an error message, telling the user that the variable is not allowed to be updated. With a list of allowed variables
$allowed_variables = [];
foreach ( $this->config_classes as $config_class ) {
$allowed_variables[] = (new $config_class())->getVariableName();
}
$allowed_variables = implode(', ', $allowed_variables);
echo "Variable not allowed to be updated. Allowed variables: $allowed_variables";
return false;
}
// Update the config variable using the config class that contains the variable
foreach ( $this->config_classes as $config_class ) {
// Create a new instance of the config class
$tmp = new $config_class();
// Check if the variable matches the variable name in the config class
if ($tmp->getVariableName() == $variable) {
// Update the config variable
$tmp->setVariableValue($value);
}
}
// Return the updated config variable
return true;
}
/**
* Check if the variable is allowed to be updated
* @param string $variable
* @return bool
*/
function isVariableAllowed(string $variable): bool
{
foreach ( $this->config_classes as $config_class ) {
// Create a new instance of the config class
$tmp = new $config_class();
// Check if the variable matches the variable name in the config class
if ($tmp->getVariableName() == $variable) {
return true;
}
}
return false;
}
function getConfigRequest(): array
{
// Get the config variable
global /** @var db $db */
$db;
// Check if the request has a variable name
if (!isset($_GET['variable'])) {
return self::getConfig();
}
// Get the variable name
$variable = $_GET['variable'];
// Sanitize the variable name
$variable = $db->escape_string($variable);
// Get the config variable
$sql = "SELECT * FROM module_config WHERE module = '$this->module_name' AND variable = '$variable'";
return $this->extracted($db, $sql);
}
/**
* Get all config variables for the module
* @return array
*/
function getConfig(): array
{
global $db;
$sql = "SELECT * FROM module_config WHERE module = '$this->module_name'";
return $this->extracted($db, $sql);
}
/**
* @param $db
* @param string $sql
* @return array
*/
private function extracted($db, string $sql): array
{
$result = $db->query($sql);
$config = [];
while ($row = $result->fetch_assoc()) {
$config[] = [
'module' => $row['module'],
'variable' => $row['variable'],
'type' => $row['type'],
'value' => $this->parseConfigVariableType($row['type'], $row['value'])
];
}
return $config;
}
function parseConfigVariableType($type, $value)
{
// If the variable is an int, convert it to an int
if ($type == 'integer') {
return (integer)$value;
}
// If the variable is a boolean, convert it to a boolean
if ($type == 'bool') {
return $value == 'true';
}
// If the variable is a float, convert it to a float
if ($type == 'float') {
return (float)$value;
}
// If the variable is a JSON string, convert it to an array
if ($type == 'json') {
return json_decode($value, true);
}
// If the variable is a string, convert it to a string
if ($type == 'string') {
return (string)$value;
}
// If the variable is an array, convert it to an array
if ($type == 'array') {
return explode(',', $value);
}
// If the variable is a date, convert it to a date
if ($type == 'date') {
return date('Y-m-d', strtotime($value));
}
// If the variable is a time, convert it to a time
if ($type == 'time') {
return date('H:i:s', strtotime($value));
}
// If the variable is a datetime, convert it to a datetime
if ($type == 'datetime') {
return date('Y-m-d H:i:s', strtotime($value));
}
// If the variable is a timestamp, convert it to a timestamp
if ($type == 'timestamp') {
return strtotime($value);
}
return $value;
}
/**
* Get the module name
* @return string
*/
function getModuleName(): string
{
return $this->module_name;
}
}
@@ -0,0 +1,303 @@
<?php
namespace traits;
use Exception;
trait module_config_variable
{
public string $module_name; // The name of the module
public string $config_variable; // The name of the config variable in the database (e.g. layout_id)
public string $config_variable_type; // The type of the config variable (e.g. int)
public bool $config_variable_required; // Whether the config variable is required or not
public array|null $allowed_values; // An array of allowed values for the config variable. If this is null, any value is allowed
public string $config_variable_description; // A description of the config variable
public string $config_variable_example; // An example of the config variable
public bool $config_variable_is_secret; // Whether the config variable is a secret or not
/**
* Set up the config variable
* @param string $module_name
* @param string $config_variable
* @param string $config_variable_type
* @param bool $config_variable_required
* @param array|null $allowed_values
* @param string $config_variable_description
* @param string $config_variable_example
* @param bool $config_variable_is_secret
* @param mixed $default_value
* @return void
* @throws Exception
*/
function setupConfigVariable(
string $module_name,
string $config_variable,
string $config_variable_type,
bool $config_variable_required,
array|null $allowed_values,
string $config_variable_description,
string $config_variable_example,
bool $config_variable_is_secret = false,
mixed $default_value = null
): void
{
$this->module_name = $module_name;
$this->config_variable = $config_variable;
$this->config_variable_type = $config_variable_type;
$this->config_variable_required = $config_variable_required;
$this->allowed_values = $allowed_values;
$this->config_variable_description = $config_variable_description;
$this->config_variable_example = $config_variable_example;
$this->config_variable_is_secret = $config_variable_is_secret;
// Check if the config variable is set in the database
if (!self::isVariableSet($module_name, $config_variable)) {
// If the config variable is required, throw an exception
if ($config_variable_required && $default_value === null) {
throw new Exception('Config variable not set: ' . $config_variable);
} else {
// If the config variable is not required, set the default value
self::insertVariableValue($module_name, $config_variable, $default_value);
}
}
}
/**
* Check if the config variable is set in the database
* @param string $module
* @param string $variable
* @return bool
*/
static function isVariableSet(string $module, string $variable): bool
{
global $db;
$sql = "SELECT value FROM module_config WHERE module = '$module' AND variable = '$variable'";
$result = $db->query($sql);
return $result->num_rows > 0;
}
/**
* Insert the value of the config variable in the database
* @param string $module
* @param string $variable
* @param mixed $value
*/
function insertVariableValue(string $module, string $variable, mixed $value): void
{
global $db;
$sql = "INSERT INTO module_config (module, variable, value, type) VALUES ('$module', '$variable', '$value', '" . self::getVariableType() . "')";
$db->query($sql);
}
/**
* Get the variable type
* @return string
*/
function getVariableType(): string
{
return $this->config_variable_type;
}
/**
* Is boolean variable true?
* @return bool
* @throws Exception
*/
function isTrue(): bool
{
// Make sure the variable is a boolean
if ($this->config_variable_type !== 'bool') {
throw new Exception('Config variable is not a boolean: ' . $this->config_variable . ' (' . $this->config_variable_type . ')');
}
return $this->getVariableValue() === 'true';
}
/**
* Get the value of the config variable from the database
* @return mixed
*/
function getVariableValue(): mixed
{
global $db;
$sql = "SELECT value FROM module_config WHERE module = '$this->module_name' AND variable = '$this->config_variable'";
$result = $db->query($sql);
// return the value of the config variable
return $result->fetch_assoc()['value'];
}
public function __toString(): string
{
// Return the config variable value as a string
return $this->getVariableValue();
}
/**
* Set the value of the config variable in the database
* @param mixed $value
* @throws Exception
*/
function setVariableValue(mixed $value): void
{
// Check if the variable value is valid
if (!$this->validateVariableValue($value)) {
throw new Exception('Invalid value for config variable: ' . $this->config_variable . ' (' . $value . ')');
}
// If the type is a boolean, convert the value to "true" or "false"
if ($this->config_variable_type === 'bool') {
$value = $value ? 'true' : 'false';
}
// Update the value of the config variable in the database, and insert it if it does not exist
if (self::isVariableSet($this->module_name, $this->config_variable)) {
self::updateVariableValue($this->module_name, $this->config_variable, $value);
} else {
self::insertVariableValue($this->module_name, $this->config_variable, $value);
}
}
/**
* Validate the value of the config variable
* @param mixed $value
* @return bool
*/
function validateVariableValue(mixed $value): bool
{
// Check if the value is empty and the variable is required
if ($this->config_variable_required && empty($value)) {
// If the value is empty and the type is not a boolean, return false
if ($this->config_variable_type != 'bool') {
return false;
}
}
// Check if the value is in the list of allowed values
if ($this->allowed_values && !in_array($value, $this->allowed_values)) {
return false;
}
// Check if the value is of the correct type
switch ($this->config_variable_type) {
case 'int':
if (!is_numeric($value)) {
return false;
}
break;
case 'string':
if (!is_string($value)) {
return false;
}
break;
case 'bool':
// If the value is a string, convert it to "true" or "false"
if (is_string($value)) {
$value = self::inputToBool($value);
}
if (!is_bool($value)) {
return false;
}
break;
default:
return false;
}
return true;
}
/**
* Convert a string to a boolean
* @param string $value
* @return bool
*/
static function inputToBool(string $value): bool
{
// If the value is true, 1, or "true", return true
if ($value === 'true' || $value === '1') {
return true;
}
// If the value is false, 0, or "false", return false
return false;
}
/**
* Update the value of the config variable in the database
* @param string $module
* @param string $variable
* @param mixed $value
*/
static function updateVariableValue(string $module, string $variable, mixed $value): void
{
global $db;
$sql = "UPDATE module_config SET value = '$value' WHERE module = '$module' AND variable = '$variable'";
$db->query($sql);
}
/**
* Get the config variable as a JSON string
* @return string
*/
function asJson(): string
{
return json_encode($this->asArray());
}
/**
* Get the config variable as an array
* @return array
*/
function asArray(): array
{
return [
'module' => $this->module_name,
'variable' => $this->config_variable,
'type' => $this->config_variable_type,
'required' => $this->config_variable_required,
'allowed_values' => $this->allowed_values,
'description' => $this->config_variable_description,
'example' => $this->config_variable_example,
'value' => $this->getVariableValue(),
];
}
/**
* Get the variable name
* @return string
*/
function getVariableName(): string
{
return $this->config_variable;
}
/**
* Get the variable description
* @return string
*/
function getVariableDescription(): string
{
return $this->config_variable_description;
}
/**
* Get the variable example
* @return string
*/
function getVariableExample(): string
{
return $this->config_variable_example;
}
/**
* Get the variable is secret
* @return bool
*/
function getVariableIsSecret(): bool
{
return $this->config_variable_is_secret;
}
/**
* Get the variable required
* @return bool
*/
function getVariableRequired(): bool
{
return $this->config_variable_required;
}
}
+22
View File
@@ -3,6 +3,7 @@
namespace traits;
use classes\authentication;
use classes\recaptcha;
use objects\logs_o;
trait route_t
@@ -138,6 +139,27 @@ trait route_t
return true;
}
/**
* Require reCAPTCHA for the request
* @return bool
*/
public function requireRecaptcha(): bool
{
global $response;
// Check if the reCAPTCHA is valid
try {
$recaptcha_response = $response->getRequestParameter('g_recaptcha_response');
$recaptcha = (new recaptcha())->validate($recaptcha_response);
if (!$recaptcha) {
(new logs_o())->add('global', 'global', 1, 0, 'AUTHENTICATION_FAILED', 'Authentication failed. Invalid, or missing reCAPTCHA');
$response->error('Authentication failed. Invalid or missing reCAPTCHA.', 401);
}
} catch (\Exception $e) {
$response->error($e->getMessage(), 400);
}
return true;
}
/**
* Get data from the request body or query string by name
* @param string $name