mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-05-25 00:44:03 -04:00
Compare commits
9 Commits
unstable
...
fix/4554-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
629de65e73 | ||
|
|
bf5af2f2dc | ||
|
|
71c164ad18 | ||
|
|
f7280ea83e | ||
|
|
26e8d9d80c | ||
|
|
403180db7b | ||
|
|
6d970953b6 | ||
|
|
b2c2d350a7 | ||
|
|
9dc58a2c1f |
@@ -106,4 +106,54 @@ class Encryption extends BaseConfig
|
||||
* by CI3 Encryption default configuration.
|
||||
*/
|
||||
public string $cipher = 'AES-256-CTR';
|
||||
|
||||
/**
|
||||
* Constructor - loads encryption key from fallback location if not set.
|
||||
*
|
||||
* This supports Docker/container environments where ROOTPATH/.env may be
|
||||
* read-only or ephemeral. The fallback key file is stored in WRITEPATH/config/.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// If key not set from .env or environment, try WRITEPATH fallback
|
||||
if (empty($this->key) || strlen($this->key) < 64) {
|
||||
$fallbackKey = $this->loadKeyFromWritable();
|
||||
if ($fallbackKey !== null) {
|
||||
$this->key = $fallbackKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads encryption key from WRITEPATH/config/encryption.key.
|
||||
*
|
||||
* @return string|null The encryption key if found, null otherwise
|
||||
*/
|
||||
private function loadKeyFromWritable(): ?string
|
||||
{
|
||||
$keyFile = WRITEPATH . 'config' . DIRECTORY_SEPARATOR . 'encryption.key';
|
||||
|
||||
if (!file_exists($keyFile) || !is_readable($keyFile)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$content = file_get_contents($keyFile);
|
||||
if ($content === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($content, true);
|
||||
if (
|
||||
!is_array($data)
|
||||
|| !isset($data['key'])
|
||||
|| !is_string($data['key'])
|
||||
|| strlen($data['key']) < 64
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data['key'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,9 @@ use App\Models\Enums\Rounding_mode;
|
||||
use App\Models\Stock_location;
|
||||
use App\Models\Tax;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Config\Database;
|
||||
use Config\OSPOS;
|
||||
use Config\Services;
|
||||
use DirectoryIterator;
|
||||
use NumberFormatter;
|
||||
use ReflectionException;
|
||||
@@ -30,7 +28,6 @@ class Config extends Secure_Controller
|
||||
{
|
||||
protected $helpers = ['security'];
|
||||
private BaseConnection $db;
|
||||
private EncrypterInterface $encrypter;
|
||||
private Barcode_lib $barcode_lib;
|
||||
private Sale_lib $sale_lib;
|
||||
private Receiving_lib $receiving_lib;
|
||||
@@ -62,13 +59,6 @@ class Config extends Secure_Controller
|
||||
$this->tax = model(Tax::class);
|
||||
$this->config = config(OSPOS::class)->settings;
|
||||
$this->db = Database::connect();
|
||||
|
||||
helper('security');
|
||||
if (check_encryption()) {
|
||||
$this->encrypter = Services::encrypter();
|
||||
} else {
|
||||
log_message('alert', 'Error preparing encryption key');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,25 +246,11 @@ class Config extends Secure_Controller
|
||||
// Integrations Related fields
|
||||
$data['mailchimp'] = [];
|
||||
|
||||
if (check_encryption()) { // TODO: Hungarian notation
|
||||
if (!isset($this->encrypter)) {
|
||||
helper('security');
|
||||
$this->encrypter = Services::encrypter();
|
||||
}
|
||||
$data['mailchimp']['api_key'] = decrypt_value($this->config['mailchimp_api_key'] ?? null);
|
||||
$data['mailchimp']['list_id'] = decrypt_value($this->config['mailchimp_list_id'] ?? null);
|
||||
|
||||
$data['mailchimp']['api_key'] = (isset($this->config['mailchimp_api_key']) && !empty($this->config['mailchimp_api_key']))
|
||||
? $this->encrypter->decrypt($this->config['mailchimp_api_key'])
|
||||
: '';
|
||||
|
||||
$data['mailchimp']['list_id'] = (isset($this->config['mailchimp_list_id']) && !empty($this->config['mailchimp_list_id']))
|
||||
? $this->encrypter->decrypt($this->config['mailchimp_list_id'])
|
||||
: '';
|
||||
|
||||
// Remove any backup of .env created by check_encryption()
|
||||
if (check_encryption()) {
|
||||
remove_backup();
|
||||
} else {
|
||||
$data['mailchimp']['api_key'] = '';
|
||||
$data['mailchimp']['list_id'] = '';
|
||||
}
|
||||
|
||||
$data['mailchimp']['lists'] = $this->_mailchimp();
|
||||
@@ -512,15 +488,23 @@ class Config extends Secure_Controller
|
||||
public function postSaveEmail(): ResponseInterface
|
||||
{
|
||||
$password = '';
|
||||
$passwordInput = $this->request->getPost('smtp_pass');
|
||||
|
||||
if (check_encryption() && !empty($this->request->getPost('smtp_pass'))) {
|
||||
$password = $this->encrypter->encrypt($this->request->getPost('smtp_pass'));
|
||||
if (!empty($passwordInput)) {
|
||||
$password = encrypt_value($passwordInput);
|
||||
if (empty($password)) {
|
||||
log_message('error', 'SMTP password encryption failed - credentials not saved');
|
||||
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => lang('Config.encryption_failed'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$protocol = $this->request->getPost('protocol');
|
||||
$mailpath = $this->request->getPost('mailpath');
|
||||
|
||||
// Validate mailpath: required for sendmail, optional for others but must be safe if provided
|
||||
$isMailpathRequired = ($protocol === 'sendmail');
|
||||
$isMailpathProvided = !empty($mailpath);
|
||||
$isMailpathValid = $isMailpathProvided && preg_match('/^[a-zA-Z0-9_\-\/.]+$/', $mailpath);
|
||||
@@ -528,7 +512,7 @@ class Config extends Secure_Controller
|
||||
if (($isMailpathRequired && !$isMailpathProvided) || ($isMailpathProvided && !$isMailpathValid)) {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => lang('Config.mailpath_invalid')
|
||||
'message' => lang('Config.mailpath_invalid'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -540,7 +524,7 @@ class Config extends Secure_Controller
|
||||
'smtp_pass' => $password,
|
||||
'smtp_port' => $this->request->getPost('smtp_port', FILTER_SANITIZE_NUMBER_INT),
|
||||
'smtp_timeout' => $this->request->getPost('smtp_timeout', FILTER_SANITIZE_NUMBER_INT),
|
||||
'smtp_crypto' => $this->request->getPost('smtp_crypto')
|
||||
'smtp_crypto' => $this->request->getPost('smtp_crypto'),
|
||||
];
|
||||
|
||||
$success = $this->appconfig->batch_save($batch_save_data);
|
||||
@@ -558,16 +542,25 @@ class Config extends Secure_Controller
|
||||
public function postSaveMessage(): ResponseInterface
|
||||
{
|
||||
$password = '';
|
||||
$passwordInput = $this->request->getPost('msg_pwd');
|
||||
|
||||
if (check_encryption() && !empty($this->request->getPost('msg_pwd'))) {
|
||||
$password = $this->encrypter->encrypt($this->request->getPost('msg_pwd'));
|
||||
if (!empty($passwordInput)) {
|
||||
$password = encrypt_value($passwordInput);
|
||||
if (empty($password)) {
|
||||
log_message('error', 'SMS password encryption failed');
|
||||
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => lang('Config.encryption_failed'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$batch_save_data = [
|
||||
'msg_msg' => $this->request->getPost('msg_msg'),
|
||||
'msg_uid' => $this->request->getPost('msg_uid'),
|
||||
'msg_pwd' => $password,
|
||||
'msg_src' => $this->request->getPost('msg_src')
|
||||
'msg_src' => $this->request->getPost('msg_src'),
|
||||
];
|
||||
|
||||
$success = $this->appconfig->batch_save($batch_save_data);
|
||||
@@ -626,15 +619,29 @@ class Config extends Secure_Controller
|
||||
$api_key = '';
|
||||
$list_id = '';
|
||||
|
||||
if (check_encryption()) {
|
||||
$api_key_unencrypted = $this->request->getPost('mailchimp_api_key');
|
||||
if (!empty($api_key_unencrypted)) {
|
||||
$api_key = $this->encrypter->encrypt($api_key_unencrypted);
|
||||
}
|
||||
$api_key_input = $this->request->getPost('mailchimp_api_key');
|
||||
if (!empty($api_key_input)) {
|
||||
$api_key = encrypt_value($api_key_input);
|
||||
if (empty($api_key)) {
|
||||
log_message('error', 'Mailchimp API key encryption failed');
|
||||
|
||||
$list_id_unencrypted = $this->request->getPost('mailchimp_list_id');
|
||||
if (!empty($list_id_unencrypted)) {
|
||||
$list_id = $this->encrypter->encrypt($list_id_unencrypted);
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => lang('Config.encryption_failed'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$list_id_input = $this->request->getPost('mailchimp_list_id');
|
||||
if (!empty($list_id_input)) {
|
||||
$list_id = encrypt_value($list_id_input);
|
||||
if (empty($list_id)) {
|
||||
log_message('error', 'Mailchimp list ID encryption failed');
|
||||
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => lang('Config.encryption_failed'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,7 @@ class Customers extends Persons
|
||||
$this->tax_code = model(Tax_code::class);
|
||||
$this->config = config(OSPOS::class)->settings;
|
||||
|
||||
$encrypter = Services::encrypter();
|
||||
|
||||
if (!empty($this->config['mailchimp_list_id'])) {
|
||||
$this->_list_id = $encrypter->decrypt($this->config['mailchimp_list_id']);
|
||||
} else {
|
||||
$this->_list_id = '';
|
||||
}
|
||||
$this->_list_id = decrypt_value($this->config['mailchimp_list_id'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,67 +4,227 @@ use CodeIgniter\Encryption\Encryption;
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* Checks and initializes encryption key.
|
||||
*
|
||||
* This function ensures a valid encryption key exists for the application.
|
||||
* It tries multiple storage locations to support different deployment scenarios:
|
||||
* 1. ROOTPATH/.env - Standard location for non-containerized deployments
|
||||
* 2. WRITEPATH/config/encryption.key - Fallback for Docker/container environments where .env is read-only
|
||||
*
|
||||
* @return bool True if encryption key is available, false if key generation/persistence failed
|
||||
*/
|
||||
function check_encryption(): bool
|
||||
{
|
||||
$old_key = config('Encryption')->key;
|
||||
|
||||
if ((empty($old_key)) || (strlen($old_key) < 64)) {
|
||||
$encryption = new Encryption();
|
||||
$key = bin2hex($encryption->createKey());
|
||||
config('Encryption')->key = $key;
|
||||
// Key already exists and is valid (64+ hex chars = 32+ bytes)
|
||||
if (!empty($old_key) && strlen($old_key) >= 64) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$config_path = ROOTPATH . '.env';
|
||||
$backup_path = WRITEPATH . '/backup/.env.bak';
|
||||
$backup_folder = WRITEPATH . '/backup';
|
||||
// Generate a new key
|
||||
$encryption = new Encryption();
|
||||
$key = bin2hex($encryption->createKey());
|
||||
config('Encryption')->key = $key;
|
||||
|
||||
if (!file_exists($backup_folder)) {
|
||||
@mkdir($backup_folder, 0750, true);
|
||||
}
|
||||
// Try to persist the key - attempt multiple locations
|
||||
// Write both locations when possible. The writable copy is the durable one
|
||||
// in containerized deployments where .env may be ephemeral.
|
||||
$envPersisted = write_encryption_key_to_env($key, $old_key);
|
||||
$writablePersisted = write_encryption_key_to_writable($key, $old_key);
|
||||
$persisted = $envPersisted || $writablePersisted;
|
||||
|
||||
if (!file_exists($config_path)) {
|
||||
$example_path = ROOTPATH . '.env.example';
|
||||
if (file_exists($example_path)) {
|
||||
@copy($example_path, $config_path);
|
||||
} else {
|
||||
@file_put_contents($config_path, "# OSPOS Configuration\n\n");
|
||||
}
|
||||
@chmod($config_path, 0640);
|
||||
}
|
||||
if ($persisted) {
|
||||
log_message('info', 'Encryption key initialized successfully');
|
||||
} else {
|
||||
log_message('error', 'Failed to persist encryption key to any location. Encryption may not survive container restarts.');
|
||||
}
|
||||
|
||||
if (file_exists($config_path)) {
|
||||
@copy($config_path, $backup_path);
|
||||
@chmod($backup_path, 0640);
|
||||
@chmod($config_path, 0640);
|
||||
return $persisted;
|
||||
}
|
||||
|
||||
$config_file = file_get_contents($config_path);
|
||||
/**
|
||||
* Writes encryption key to ROOTPATH/.env file.
|
||||
*
|
||||
* @param string $key The new encryption key (hex-encoded)
|
||||
* @param string|null $old_key The previous key to preserve for key rotation
|
||||
*
|
||||
* @return bool True if key was written successfully, false otherwise
|
||||
*/
|
||||
function write_encryption_key_to_env(string $key, ?string $old_key = null): bool
|
||||
{
|
||||
$config_path = ROOTPATH . '.env';
|
||||
$backup_path = WRITEPATH . 'backup' . DIRECTORY_SEPARATOR . '.env.bak';
|
||||
$backup_folder = WRITEPATH . 'backup';
|
||||
|
||||
if (strpos($config_file, 'encryption.key') !== false) {
|
||||
$config_file = preg_replace("/(encryption\.key.*=.*)('.*')/", "$1'$key'", $config_file);
|
||||
} else {
|
||||
$config_file .= "\nencryption.key = '$key'\n";
|
||||
}
|
||||
|
||||
if (!empty($old_key)) {
|
||||
$old_line = "# encryption.key = '$old_key' REMOVE IF UNNEEDED\r\n";
|
||||
$insertion_point = stripos($config_file, 'encryption.key');
|
||||
if ($insertion_point !== false) {
|
||||
$config_file = substr_replace($config_file, $old_line, $insertion_point, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@file_put_contents($config_path, $config_file);
|
||||
@chmod($config_path, 0640);
|
||||
|
||||
log_message('info', "Updated encryption key in $config_path");
|
||||
// Ensure backup directory exists
|
||||
if (!file_exists($backup_folder)) {
|
||||
if (!@mkdir($backup_folder, 0750, true)) {
|
||||
log_message('debug', 'Could not create backup directory');
|
||||
}
|
||||
}
|
||||
|
||||
// Create .env if it doesn't exist
|
||||
if (!file_exists($config_path)) {
|
||||
$example_path = ROOTPATH . '.env.example';
|
||||
if (file_exists($example_path)) {
|
||||
if (!@copy($example_path, $config_path)) {
|
||||
log_message('debug', 'Could not copy .env.example to .env');
|
||||
}
|
||||
} else {
|
||||
if (!@file_put_contents($config_path, "# OSPOS Configuration\n\n") !== false) {
|
||||
log_message('debug', 'Could not create .env file');
|
||||
}
|
||||
}
|
||||
@chmod($config_path, 0640);
|
||||
}
|
||||
|
||||
// Check if .env is writable
|
||||
if (!is_writable($config_path)) {
|
||||
log_message('debug', '.env file is not writable');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Backup existing .env
|
||||
if (file_exists($config_path)) {
|
||||
@copy($config_path, $backup_path);
|
||||
@chmod($backup_path, 0640);
|
||||
}
|
||||
|
||||
// Read current content
|
||||
$config_file = file_get_contents($config_path);
|
||||
if ($config_file === false) {
|
||||
log_message('debug', 'Could not read .env file');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strpos($config_file, 'encryption.key') !== false) {
|
||||
$config_file = preg_replace("/(encryption\.key.*=.*)(['\"])([^'\"]*)\\2/", "$1'$key'", $config_file);
|
||||
} else {
|
||||
$config_file .= "\nencryption.key = '$key'\n";
|
||||
}
|
||||
|
||||
// Preserve old key for rotation if present
|
||||
if (!empty($old_key)) {
|
||||
$old_line = "# encryption.key = '$old_key' REMOVE IF UNNEEDED\r\n";
|
||||
$insertion_point = stripos($config_file, 'encryption.key');
|
||||
if ($insertion_point !== false) {
|
||||
$config_file = substr_replace($config_file, $old_line, $insertion_point, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Write updated content
|
||||
$result = file_put_contents($config_path, $config_file);
|
||||
if ($result === false) {
|
||||
log_message('debug', 'Could not write to .env file');
|
||||
return false;
|
||||
}
|
||||
|
||||
@chmod($config_path, 0640);
|
||||
log_message('info', "Updated encryption key in $config_path");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes encryption key to WRITEPATH/config/encryption.key file.
|
||||
*
|
||||
* This is the fallback location for Docker/container environments where
|
||||
* the ROOTPATH/.env file may be read-only or ephemeral.
|
||||
*
|
||||
* @param string $key The new encryption key (hex-encoded)
|
||||
* @param string|null $old_key The previous key to preserve for key rotation
|
||||
*
|
||||
* @return bool True if key was written successfully, false otherwise
|
||||
*/
|
||||
function write_encryption_key_to_writable(string $key, ?string $old_key = null): bool
|
||||
{
|
||||
$key_file = WRITEPATH . 'config' . DIRECTORY_SEPARATOR . 'encryption.key';
|
||||
$key_dir = dirname($key_file);
|
||||
|
||||
// Ensure directory exists
|
||||
if (!is_dir($key_dir)) {
|
||||
if (!@mkdir($key_dir, 0750, true)) {
|
||||
log_message('error', 'Could not create config directory: ' . $key_dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if directory is writable
|
||||
if (!is_writable($key_dir)) {
|
||||
log_message('error', 'Config directory is not writable: ' . $key_dir);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build key data structure
|
||||
$data = [
|
||||
'key' => $key,
|
||||
'previous_keys' => [],
|
||||
'generated_at' => date('c'),
|
||||
'generated_by' => 'check_encryption()',
|
||||
];
|
||||
|
||||
if (!empty($old_key)) {
|
||||
$data['previous_keys'][] = $old_key;
|
||||
}
|
||||
|
||||
// Write key file
|
||||
$content = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
$result = file_put_contents($key_file, $content);
|
||||
|
||||
if ($result === false) {
|
||||
log_message('error', 'Could not write encryption key file');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set restrictive permissions
|
||||
@chmod($key_file, 0640);
|
||||
|
||||
log_message('info', "Stored encryption key in $key_file");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads encryption key from WRITEPATH/config/encryption.key file.
|
||||
*
|
||||
* This is the fallback key loader for Docker/container environments.
|
||||
*
|
||||
* @return string|null The encryption key if found, null otherwise
|
||||
*/
|
||||
function load_encryption_key_from_writable(): ?string
|
||||
{
|
||||
$key_file = WRITEPATH . 'config' . DIRECTORY_SEPARATOR . 'encryption.key';
|
||||
|
||||
if (!file_exists($key_file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_readable($key_file)) {
|
||||
log_message('error', 'Encryption key file exists but is not readable: ' . $key_file);
|
||||
return null;
|
||||
}
|
||||
|
||||
$content = file_get_contents($key_file);
|
||||
if ($content === false) {
|
||||
log_message('error', 'Could not read encryption key file');
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($content, true);
|
||||
if (!is_array($data) || empty($data['key'])) {
|
||||
log_message('error', 'Encryption key file has invalid format');
|
||||
return null;
|
||||
}
|
||||
|
||||
log_message('info', 'Loaded encryption key from WRITEPATH config');
|
||||
|
||||
return $data['key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores .env from backup (used by migration rollback).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function abort_encryption_conversion(): void
|
||||
@@ -83,14 +243,77 @@ function abort_encryption_conversion(): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes backup file (used after successful migration).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function remove_backup(): void
|
||||
{
|
||||
$backup_path = WRITEPATH . '/backup/.env.bak';
|
||||
if (!file_exists($backup_path)) {
|
||||
return;
|
||||
|
||||
if (file_exists($backup_path)) {
|
||||
unlink($backup_path);
|
||||
}
|
||||
@unlink($backup_path);
|
||||
log_message('info', "Removed $backup_path");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts an encrypted value with proper error handling.
|
||||
*
|
||||
* This function provides a consistent decryption pattern across the codebase,
|
||||
* handling cases where encryption key may not be available or decryption fails.
|
||||
*
|
||||
* @param string|null $encrypted_value The encrypted value to decrypt
|
||||
* @param string $default Default value to return if decryption fails
|
||||
*
|
||||
* @return string The decrypted value, or default if decryption fails
|
||||
*/
|
||||
function decrypt_value(?string $encrypted_value, string $default = ''): string
|
||||
{
|
||||
if (empty($encrypted_value)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (!check_encryption()) {
|
||||
log_message('warning', 'Cannot decrypt value: encryption key not available');
|
||||
return $default;
|
||||
}
|
||||
|
||||
try {
|
||||
$encrypter = Services::encrypter();
|
||||
return $encrypter->decrypt($encrypted_value);
|
||||
} catch (\CodeIgniter\Encryption\Exceptions\EncryptionException $e) {
|
||||
log_message('error', 'Decryption failed: ' . $e->getMessage());
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a value with proper error handling.
|
||||
*
|
||||
* This function provides a consistent encryption pattern across the codebase,
|
||||
* handling cases where encryption key may not be available.
|
||||
*
|
||||
* @param string|null $value The value to encrypt
|
||||
* @param bool $require If true, return empty string on failure instead of plaintext fallback
|
||||
*
|
||||
* @return string The encrypted value, or empty string if encryption fails when required
|
||||
*/
|
||||
function encrypt_value(?string $value, bool $require = true): string
|
||||
{
|
||||
if ($value === null || $value === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!check_encryption()) {
|
||||
log_message('error', 'Cannot encrypt value: encryption key not available');
|
||||
return $require ? '' : $value;
|
||||
}
|
||||
|
||||
try {
|
||||
$encrypter = Services::encrypter();
|
||||
return $encrypter->encrypt($value);
|
||||
} catch (\CodeIgniter\Encryption\Exceptions\EncryptionException $e) {
|
||||
log_message('error', 'Encryption failed: ' . $e->getMessage());
|
||||
return $require ? '' : $value;
|
||||
}
|
||||
}
|
||||
@@ -122,6 +122,7 @@ return [
|
||||
"email_smtp_port" => "SMTP Port",
|
||||
"email_smtp_timeout" => "SMTP Timeout (s)",
|
||||
"email_smtp_user" => "SMTP Username",
|
||||
"encryption_failed" => "Failed to encrypt data. Please check encryption configuration.",
|
||||
"enable_avatar" => "",
|
||||
"enable_avatar_tooltip" => "",
|
||||
"enable_dropdown_tooltip" => "",
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
namespace app\Libraries;
|
||||
|
||||
use CodeIgniter\Email\Email;
|
||||
use CodeIgniter\Encryption\Encryption;
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use CodeIgniter\Encryption\Exceptions\EncryptionException;
|
||||
use Config\OSPOS;
|
||||
use Config\Services;
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,19 +22,7 @@ class Email_lib
|
||||
$this->email = new Email();
|
||||
$this->config = config(OSPOS::class)->settings;
|
||||
|
||||
$encrypter = Services::encrypter();
|
||||
|
||||
$smtp_pass = $this->config['smtp_pass'];
|
||||
if (!empty($smtp_pass) && check_encryption()) {
|
||||
try {
|
||||
$smtp_pass = $encrypter->decrypt($smtp_pass);
|
||||
} catch (\EncryptionException $e) {
|
||||
// Decryption failed, use the original value
|
||||
log_message('error', 'SMTP password decryption failed: ' . $e->getMessage());
|
||||
$smtp_pass = '';
|
||||
}
|
||||
|
||||
}
|
||||
$smtp_pass = decrypt_value($this->config['smtp_pass'] ?? null);
|
||||
|
||||
$email_config = [
|
||||
'mailType' => 'html',
|
||||
@@ -51,7 +35,7 @@ class Email_lib
|
||||
'SMTPPass' => $smtp_pass,
|
||||
'SMTPPort' => (int)$this->config['smtp_port'],
|
||||
'SMTPTimeout' => (int)$this->config['smtp_timeout'],
|
||||
'SMTPCrypto' => $this->config['smtp_crypto']
|
||||
'SMTPCrypto' => $this->config['smtp_crypto'],
|
||||
];
|
||||
$this->email->initialize($email_config);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
namespace app\Libraries;
|
||||
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use Config\OSPOS;
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* MailChimp API v3 REST client Connector
|
||||
@@ -14,8 +12,6 @@ use Config\Services;
|
||||
* Inspired by the work of:
|
||||
* - Rajitha Bandara: https://github.com/rajitha-bandara/ci-mailchimp-v3-rest-client
|
||||
* - Stefan Ashwell: https://github.com/stef686/codeigniter-mailchimp-api-v3
|
||||
*
|
||||
* @property encrypterinterface encrypter
|
||||
*/
|
||||
class MailchimpConnector
|
||||
{
|
||||
@@ -40,23 +36,19 @@ class MailchimpConnector
|
||||
{
|
||||
$config = config(OSPOS::class)->settings;
|
||||
|
||||
$encrypter = Services::encrypter();
|
||||
|
||||
$mailchimp_api_key = (isset($this->config['mailchimp_api_key']) && !empty($this->config['mailchimp_api_key']))
|
||||
? $this->config['mailchimp_api_key']
|
||||
: '';
|
||||
$mailchimp_api_key = $config['mailchimp_api_key'] ?? '';
|
||||
|
||||
if (!empty($mailchimp_api_key)) {
|
||||
$this->_api_key = empty($api_key)
|
||||
? $encrypter->decrypt($mailchimp_api_key) // TODO: Hungarian notation
|
||||
: $api_key; // TODO: Hungarian notation
|
||||
? decrypt_value($mailchimp_api_key)
|
||||
: $api_key;
|
||||
}
|
||||
|
||||
if (!empty($this->_api_key)) { // TODO: Hungarian notation
|
||||
if (!empty($this->_api_key)) {
|
||||
// Replace <dc> with correct datacenter obtained from the last part of the api key
|
||||
$strings = explode('-', $this->_api_key); // TODO: Hungarian notation
|
||||
$strings = explode('-', $this->_api_key);
|
||||
if (is_array($strings) && !empty($strings[1])) {
|
||||
$this->_api_endpoint = str_replace('<dc>', $strings[1], $this->_api_endpoint); // TODO: Hungarian notation
|
||||
$this->_api_endpoint = str_replace('<dc>', $strings[1], $this->_api_endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
namespace app\Libraries;
|
||||
|
||||
use CodeIgniter\Encryption\Encryption;
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use Config\OSPOS;
|
||||
use Config\Services;
|
||||
|
||||
|
||||
/**
|
||||
@@ -24,12 +21,7 @@ class Sms_lib
|
||||
{
|
||||
$config = config(OSPOS::class)->settings;
|
||||
|
||||
$encrypter = Services::encrypter();
|
||||
|
||||
$password = $config['msg_pwd'];
|
||||
if (!empty($password)) {
|
||||
$password = $encrypter->decrypt($password);
|
||||
}
|
||||
$password = decrypt_value($config['msg_pwd'] ?? null);
|
||||
|
||||
$username = $config['msg_uid'];
|
||||
$originator = $config['msg_src'];
|
||||
|
||||
Reference in New Issue
Block a user