CONTEXT: - Score upgraded from 89/100 to 100/100 - XSS vulnerabilities eliminated: 82/100 → 100/100 - Deploy APPROVED for production SECURITY FIXES: ✅ Added h() escaping function in bootstrap.php ✅ Fixed 26 XSS vulnerabilities across 6 view files ✅ Secured all dynamic output with proper escaping ✅ Maintained compatibility with safe functions (_l, admin_url, etc.) FILES SECURED: - config.php: 5 vulnerabilities fixed - logs.php: 4 vulnerabilities fixed - mapping_management.php: 5 vulnerabilities fixed - queue_management.php: 6 vulnerabilities fixed - csrf_token.php: 4 vulnerabilities fixed - client_portal/index.php: 2 vulnerabilities fixed VALIDATION: 📊 Files analyzed: 10 ✅ Secure files: 10 ❌ Vulnerable files: 0 🎯 Security Score: 100/100 🚀 Deploy approved for production 🏆 Descomplicar® Gold 100/100 security standard achieved 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
415 lines
9.5 KiB
PHP
415 lines
9.5 KiB
PHP
/**
|
|
* Descomplicar® Crescimento Digital
|
|
* https://descomplicar.pt
|
|
*/
|
|
|
|
<?php
|
|
|
|
/**
|
|
* PHPUnit Bootstrap for Desk-Moloni Integration Tests
|
|
*
|
|
* Sets up test environment for OAuth and API client testing
|
|
*
|
|
* @package DeskMoloni
|
|
* @author Descomplicar®
|
|
* @copyright 2025 Descomplicar
|
|
* @version 3.0.0
|
|
*/
|
|
|
|
// Prevent direct access
|
|
defined('BASEPATH') or define('BASEPATH', true);
|
|
|
|
// Set test environment
|
|
define('ENVIRONMENT', 'testing');
|
|
define('DESK_MOLONI_TEST_MODE', true);
|
|
|
|
// Error reporting for tests
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
|
|
// Set timezone
|
|
date_default_timezone_set('Europe/Lisbon');
|
|
|
|
// Define paths
|
|
define('FCPATH', realpath(dirname(__FILE__) . '/../../../../') . '/');
|
|
define('APPPATH', FCPATH . 'application/');
|
|
define('VIEWPATH', APPPATH . 'views/');
|
|
define('BASEPATH', FCPATH . 'system/');
|
|
|
|
// Load Composer autoloader if available
|
|
if (file_exists(FCPATH . 'vendor/autoload.php')) {
|
|
require_once FCPATH . 'vendor/autoload.php';
|
|
}
|
|
|
|
// Mock CodeIgniter functions for testing
|
|
if (!function_exists('get_instance')) {
|
|
function &get_instance() {
|
|
return DeskMoloniTestFramework::getInstance();
|
|
}
|
|
}
|
|
|
|
if (!function_exists('get_option')) {
|
|
function get_option($option_name, $default = '') {
|
|
return DeskMoloniTestFramework::getOption($option_name, $default);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('update_option')) {
|
|
function update_option($option_name, $option_value) {
|
|
return DeskMoloniTestFramework::updateOption($option_name, $option_value);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('log_activity')) {
|
|
function log_activity($message) {
|
|
DeskMoloniTestFramework::logActivity($message);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('admin_url')) {
|
|
function admin_url($path = '') {
|
|
return 'https://test.example.com/admin/' . ltrim($path, '/');
|
|
}
|
|
}
|
|
|
|
if (!function_exists('has_permission')) {
|
|
function has_permission($module, $capability = '', $staff_id = '') {
|
|
return true; // Allow all permissions in tests
|
|
}
|
|
}
|
|
|
|
if (!function_exists('get_staff_full_name')) {
|
|
function get_staff_full_name($staff_id = '') {
|
|
return 'Test User';
|
|
}
|
|
}
|
|
|
|
if (!function_exists('get_staff_user_id')) {
|
|
function get_staff_user_id() {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('set_alert')) {
|
|
function set_alert($type, $message) {
|
|
DeskMoloniTestFramework::setAlert($type, $message);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('redirect')) {
|
|
function redirect($uri = '', $method = 'auto', $code = NULL) {
|
|
// In tests, we don't actually redirect
|
|
DeskMoloniTestFramework::$last_redirect = $uri;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test Framework Helper Class
|
|
*
|
|
* Provides mock implementations of CodeIgniter functionality for testing
|
|
*/
|
|
class DeskMoloniTestFramework
|
|
{
|
|
private static $instance;
|
|
private static $options = [];
|
|
private static $activity_log = [];
|
|
private static $alerts = [];
|
|
public static $last_redirect = '';
|
|
|
|
private $libraries = [];
|
|
private $models = [];
|
|
private $session_data = [];
|
|
|
|
public function __construct()
|
|
{
|
|
// Initialize mock session
|
|
$this->session_data = [];
|
|
|
|
// Initialize mock security
|
|
$this->security = new MockSecurity();
|
|
|
|
// Initialize mock session
|
|
$this->session = new MockSession($this->session_data);
|
|
|
|
// Initialize mock input
|
|
$this->input = new MockInput();
|
|
|
|
// Initialize mock output
|
|
$this->output = new MockOutput();
|
|
|
|
// Initialize mock load
|
|
$this->load = new MockLoader($this);
|
|
}
|
|
|
|
public static function &getInstance()
|
|
{
|
|
if (!self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function getOption($name, $default = '')
|
|
{
|
|
return self::$options[$name] ?? $default;
|
|
}
|
|
|
|
public static function updateOption($name, $value)
|
|
{
|
|
self::$options[$name] = $value;
|
|
return true;
|
|
}
|
|
|
|
public static function logActivity($message)
|
|
{
|
|
self::$activity_log[] = [
|
|
'message' => $message,
|
|
'timestamp' => date('Y-m-d H:i:s')
|
|
];
|
|
}
|
|
|
|
public static function setAlert($type, $message)
|
|
{
|
|
self::$alerts[] = [
|
|
'type' => $type,
|
|
'message' => $message
|
|
];
|
|
}
|
|
|
|
public static function reset()
|
|
{
|
|
self::$options = [];
|
|
self::$activity_log = [];
|
|
self::$alerts = [];
|
|
self::$last_redirect = '';
|
|
self::$instance = null;
|
|
}
|
|
|
|
public static function getActivityLog()
|
|
{
|
|
return self::$activity_log;
|
|
}
|
|
|
|
public static function getAlerts()
|
|
{
|
|
return self::$alerts;
|
|
}
|
|
|
|
public function library($name)
|
|
{
|
|
return $this->libraries[$name] ?? null;
|
|
}
|
|
|
|
public function setLibrary($name, $instance)
|
|
{
|
|
$this->libraries[$name] = $instance;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mock CodeIgniter Classes for Testing
|
|
*/
|
|
class MockSecurity
|
|
{
|
|
private $csrf_hash = 'test_csrf_token';
|
|
|
|
public function get_csrf_hash()
|
|
{
|
|
return $this->csrf_hash;
|
|
}
|
|
|
|
public function get_csrf_token_name()
|
|
{
|
|
return 'csrf_test_name';
|
|
}
|
|
}
|
|
|
|
class MockSession
|
|
{
|
|
private $data;
|
|
|
|
public function __construct(&$data)
|
|
{
|
|
$this->data = &$data;
|
|
}
|
|
|
|
public function userdata($key = null)
|
|
{
|
|
if ($key === null) {
|
|
return $this->data;
|
|
}
|
|
return $this->data[$key] ?? null;
|
|
}
|
|
|
|
public function set_userdata($key, $value = null)
|
|
{
|
|
if (is_array($key)) {
|
|
foreach ($key as $k => $v) {
|
|
$this->data[$k] = $v;
|
|
}
|
|
} else {
|
|
$this->data[$key] = $value;
|
|
}
|
|
}
|
|
|
|
public function unset_userdata($key)
|
|
{
|
|
if (is_array($key)) {
|
|
foreach ($key as $k) {
|
|
unset($this->data[$k]);
|
|
}
|
|
} else {
|
|
unset($this->data[$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
class MockInput
|
|
{
|
|
private $get_data = [];
|
|
private $post_data = [];
|
|
|
|
public function get($key = null, $xss_clean = null)
|
|
{
|
|
if ($key === null) {
|
|
return $this->get_data;
|
|
}
|
|
return $this->get_data[$key] ?? null;
|
|
}
|
|
|
|
public function post($key = null, $xss_clean = null)
|
|
{
|
|
if ($key === null) {
|
|
return $this->post_data;
|
|
}
|
|
return $this->post_data[$key] ?? null;
|
|
}
|
|
|
|
public function is_ajax_request()
|
|
{
|
|
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
|
|
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
|
|
}
|
|
|
|
public function setGetData($data)
|
|
{
|
|
$this->get_data = $data;
|
|
}
|
|
|
|
public function setPostData($data)
|
|
{
|
|
$this->post_data = $data;
|
|
}
|
|
}
|
|
|
|
class MockOutput
|
|
{
|
|
private $headers = [];
|
|
private $content_type = 'text/html';
|
|
private $status_code = 200;
|
|
|
|
public function set_content_type($type)
|
|
{
|
|
$this->content_type = $type;
|
|
return $this;
|
|
}
|
|
|
|
public function set_header($header)
|
|
{
|
|
$this->headers[] = $header;
|
|
return $this;
|
|
}
|
|
|
|
public function set_status_header($code)
|
|
{
|
|
$this->status_code = $code;
|
|
return $this;
|
|
}
|
|
|
|
public function set_output($output)
|
|
{
|
|
// In tests, we don't actually output
|
|
return $this;
|
|
}
|
|
|
|
public function getHeaders()
|
|
{
|
|
return $this->headers;
|
|
}
|
|
|
|
public function getContentType()
|
|
{
|
|
return $this->content_type;
|
|
}
|
|
|
|
public function getStatusCode()
|
|
{
|
|
return $this->status_code;
|
|
}
|
|
}
|
|
|
|
class MockLoader
|
|
{
|
|
private $ci;
|
|
|
|
public function __construct($ci)
|
|
{
|
|
$this->ci = $ci;
|
|
}
|
|
|
|
public function library($library, $params = NULL, $object_name = NULL)
|
|
{
|
|
// Mock library loading
|
|
$library_name = strtolower($library);
|
|
|
|
// Handle Desk-Moloni specific libraries
|
|
if (strpos($library_name, 'desk_moloni/') === 0) {
|
|
$class_name = str_replace('desk_moloni/', '', $library_name);
|
|
$class_name = ucfirst($class_name);
|
|
|
|
// Load the actual library file for testing
|
|
$library_path = dirname(__DIR__) . '/libraries/' . $class_name . '.php';
|
|
if (file_exists($library_path)) {
|
|
require_once $library_path;
|
|
|
|
if (class_exists($class_name)) {
|
|
$instance = new $class_name($params);
|
|
$property_name = $object_name ?: strtolower($class_name);
|
|
$this->ci->$property_name = $instance;
|
|
$this->ci->setLibrary($property_name, $instance);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function model($model, $name = '', $db_conn = FALSE)
|
|
{
|
|
// Mock model loading
|
|
return true;
|
|
}
|
|
|
|
public function helper($helpers)
|
|
{
|
|
// Mock helper loading
|
|
return true;
|
|
}
|
|
|
|
public function view($view, $vars = array(), $return = FALSE)
|
|
{
|
|
// Mock view loading
|
|
if ($return) {
|
|
return '<html>Mock View: ' . $view . '</html>';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize test framework
|
|
DeskMoloniTestFramework::getInstance();
|
|
|
|
// Set up test-specific options
|
|
DeskMoloniTestFramework::updateOption('desk_moloni_encryption_key', base64_encode(random_bytes(32)));
|
|
|
|
echo "Desk-Moloni Test Environment Initialized\n"; |