diff --git a/App/Package/Users/Controllers/UsersController.php b/App/Package/Users/Controllers/UsersController.php index 47c38ec4..9758265c 100644 --- a/App/Package/Users/Controllers/UsersController.php +++ b/App/Package/Users/Controllers/UsersController.php @@ -369,13 +369,13 @@ private function forgotPasswordPost(): void Redirect::redirectPreviousRoute(); } // We send a verification link for this mail - if (UsersSettingsModel::getSetting('resetPasswordMethod') === '0') { + if (UsersSettingsModel::getInstance()->getSetting('resetPasswordMethod') === '0') { $this->resetPasswordMethodPasswordSendByMail($encryptedMail); Flash::send(Alert::SUCCESS, LangManager::translate('core.toaster.success'), LangManager::translate('users.toaster.password_reset', ['mail' => $mail])); - } elseif (UsersSettingsModel::getSetting('resetPasswordMethod') === '1') { + } elseif (UsersSettingsModel::getInstance()->getSetting('resetPasswordMethod') === '1') { $this->resetPasswordMethodUniqueLinkSendByMail($encryptedMail); Flash::send(Alert::SUCCESS, LangManager::translate('core.toaster.success'), LangManager::translate('users.toaster.reset_link_follow_the_link')); diff --git a/App/Package/Users/Controllers/UsersLoginController.php b/App/Package/Users/Controllers/UsersLoginController.php index b9d4d5ff..92eeb3f5 100644 --- a/App/Package/Users/Controllers/UsersLoginController.php +++ b/App/Package/Users/Controllers/UsersLoginController.php @@ -71,7 +71,7 @@ public function checkLogin(string $mail, string $password): LoginStatus $userLastConnect = $user->getLastConnectionUnformatted(); - if ((UsersSettingsModel::getSetting('securityReinforced') === '1') && $this->isUserInactiveFor90Days($userLastConnect) && !$user->get2Fa()->isEnabled() && MailModel::getInstance()->getConfig() !== null && MailModel::getInstance()->getConfig()->isEnable()) { + if ((UsersSettingsModel::getInstance()->getSetting('securityReinforced') === '1') && $this->isUserInactiveFor90Days($userLastConnect) && !$user->get2Fa()->isEnabled() && MailModel::getInstance()->getConfig() !== null && MailModel::getInstance()->getConfig()->isEnable()) { return LoginStatus::OK_LONG_DATE; } diff --git a/App/Package/Users/Controllers/UsersSettingsController.php b/App/Package/Users/Controllers/UsersSettingsController.php index 07bfdbea..8126f21c 100644 --- a/App/Package/Users/Controllers/UsersSettingsController.php +++ b/App/Package/Users/Controllers/UsersSettingsController.php @@ -2,6 +2,7 @@ namespace CMW\Controller\Users; +use CMW\Entity\Users\Settings\BulkSettingsEntity; use CMW\Entity\Users\UserSettingsEntity; use CMW\Manager\Env\EnvManager; use CMW\Manager\Filter\FilterManager; @@ -18,7 +19,6 @@ use CMW\Utils\Redirect; use CMW\Utils\Utils; use JetBrains\PhpStorm\NoReturn; -use JsonException; /** * Class: @UsersSettingsController @@ -30,7 +30,7 @@ class UsersSettingsController extends AbstractController { public static function getDefaultImageLink(): string { - $defaultImg = UsersSettingsModel::getSetting('defaultImage'); + $defaultImg = UsersSettingsModel::getInstance()->getSetting('defaultImage'); return EnvManager::getInstance()->getValue('PATH_SUBFOLDER') . 'Public/Uploads/Users/Default/' . $defaultImg; } @@ -55,12 +55,12 @@ private function settings(): void ->view(); } - #[Link('/settings/resetImg', Link::GET, [], '/cmw-admin/users')] + #[NoReturn] #[Link('/settings/resetImg', Link::GET, [], '/cmw-admin/users')] private function resetDefaultImg(): void { UsersController::redirectIfNotHavePermissions('core.dashboard', 'users.settings'); - UsersSettingsModel::updateSetting('defaultImage', 'defaultImage.jpg'); + UsersSettingsModel::getInstance()->updateSetting('defaultImage', 'defaultImage.jpg'); Flash::send(Alert::SUCCESS, LangManager::translate('core.toaster.success'), LangManager::translate('core.toaster.config.success')); @@ -78,7 +78,7 @@ private function settingsPost(): void try { $newDefaultImage = ImagesManager::convertAndUpload($defaultPicture, 'Users/Default'); - UsersSettingsModel::updateSetting('defaultImage', $newDefaultImage); + UsersSettingsModel::getInstance()->updateSetting('defaultImage', $newDefaultImage); } catch (ImagesException $e) { Flash::send(Alert::ERROR, LangManager::translate('core.toaster.error'), LangManager::translate('core.errors.upload.image') . ' => ' . $e->getMessage()); @@ -88,9 +88,17 @@ private function settingsPost(): void [$resetPasswordMethod, $profilePage, $securityReinforced] = Utils::filterInput('reset_password_method', 'profile_page', 'security_reinforced'); - UsersSettingsModel::updateSetting('resetPasswordMethod', $resetPasswordMethod); - UsersSettingsModel::updateSetting('profilePage', $profilePage); - UsersSettingsModel::updateSetting('securityReinforced', $securityReinforced); + $settingsStatus = UsersSettingsModel::getInstance()->bulkUpdateSettings( + new BulkSettingsEntity('resetPasswordMethod', $resetPasswordMethod), + new BulkSettingsEntity('profilePage', $profilePage), + new BulkSettingsEntity('securityReinforced', $securityReinforced) + ); + + if (!$settingsStatus) { + Flash::send(Alert::ERROR, LangManager::translate('core.toaster.error'), + LangManager::translate('core.toaster.config.error')); + Redirect::redirectPreviousRoute(); + } [$listEnforcedToggle] = Utils::filterInput('listEnforcedToggle'); @@ -118,7 +126,7 @@ private function settingsPost(): void } } - UsersSettingsModel::updateSetting('listEnforcedToggle', $listEnforcedToggle); + UsersSettingsModel::getInstance()->updateSetting('listEnforcedToggle', $listEnforcedToggle); Flash::send(Alert::SUCCESS, LangManager::translate('core.toaster.success'), LangManager::translate('core.toaster.config.success')); diff --git a/App/Package/Users/Entities/Settings/BulkSettingsEntity.php b/App/Package/Users/Entities/Settings/BulkSettingsEntity.php new file mode 100644 index 00000000..7cf53db5 --- /dev/null +++ b/App/Package/Users/Entities/Settings/BulkSettingsEntity.php @@ -0,0 +1,38 @@ +name = $name; + $this->value = $value; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getValue(): string + { + return $this->value; + } +} diff --git a/App/Package/Users/Entities/UserSettingsEntity.php b/App/Package/Users/Entities/UserSettingsEntity.php index 78e70d45..b6238065 100644 --- a/App/Package/Users/Entities/UserSettingsEntity.php +++ b/App/Package/Users/Entities/UserSettingsEntity.php @@ -16,9 +16,9 @@ class UserSettingsEntity extends AbstractEntity public function __construct() { - $this->defaultImage = UsersSettingsModel::getSetting('defaultImage'); - $this->profilePageStatus = (int)UsersSettingsModel::getSetting('profilePage'); - $this->resetPasswordMethod = (int)UsersSettingsModel::getSetting('resetPasswordMethod'); + $this->defaultImage = UsersSettingsModel::getInstance()->getSetting('defaultImage'); + $this->profilePageStatus = (int)UsersSettingsModel::getInstance()->getSetting('profilePage'); + $this->resetPasswordMethod = (int)UsersSettingsModel::getInstance()->getSetting('resetPasswordMethod'); } public static function getInstance(): self diff --git a/App/Package/Users/Models/UserPictureModel.php b/App/Package/Users/Models/UserPictureModel.php index 4971d66b..e0c0d4d9 100644 --- a/App/Package/Users/Models/UserPictureModel.php +++ b/App/Package/Users/Models/UserPictureModel.php @@ -57,7 +57,7 @@ public function userHasImage(int $userId): bool public function userHasDefaultImage(int $userId): bool { - return is_file(EnvManager::getInstance()->getValue('DIR') . 'Public/Uploads/Users/Default/' . UsersSettingsModel::getSetting('defaultImage')) && !$this->userHasImage($userId); + return is_file(EnvManager::getInstance()->getValue('DIR') . 'Public/Uploads/Users/Default/' . UsersSettingsModel::getInstance()->getSetting('defaultImage')) && !$this->userHasImage($userId); } /** diff --git a/App/Package/Users/Models/UsersSettingsModel.php b/App/Package/Users/Models/UsersSettingsModel.php index cc787f40..4e65c5c5 100644 --- a/App/Package/Users/Models/UsersSettingsModel.php +++ b/App/Package/Users/Models/UsersSettingsModel.php @@ -3,11 +3,14 @@ namespace CMW\Model\Users; use CMW\Entity\Users\BlacklistedPseudoEntity; +use CMW\Entity\Users\Settings\BulkSettingsEntity; use CMW\Entity\Users\UserEnforced2FaEntity; use CMW\Manager\Database\DatabaseManager; use CMW\Manager\Flash\Alert; use CMW\Manager\Flash\Flash; use CMW\Manager\Package\AbstractModel; +use Exception; +use RuntimeException; /** * Class: @UsersSettingsModel @@ -17,11 +20,11 @@ */ class UsersSettingsModel extends AbstractModel { - public static function getSetting(string $settingName): string + public function getSetting(string $settingName): string { $db = DatabaseManager::getInstance(); $req = $db->prepare('SELECT users_settings_value FROM cmw_users_settings WHERE users_settings_name = ?'); - $req->execute(array($settingName)); + $req->execute([$settingName]); $option = $req->fetch(); return $option['users_settings_value']; @@ -39,26 +42,77 @@ public function getSettings(): array return ($req->execute()) ? $req->fetchAll() : []; } - public static function updateSetting(string $settingName, string $settingValue): void + public function updateSetting(string $settingName, string $settingValue): void { $db = DatabaseManager::getInstance(); $req = $db->prepare('UPDATE cmw_users_settings SET users_settings_value=:settingValue, users_settings_updated=now() WHERE users_settings_name=:settingName'); - $req->execute(array('settingName' => $settingName, 'settingValue' => $settingValue)); + $req->execute(['settingName' => $settingName, 'settingValue' => $settingValue]); } - public static function addSetting(string $settingName, string $settingValue): void + /** + * @param BulkSettingsEntity ...$bulkSettings + * @return bool + */ + public function bulkUpdateSettings(BulkSettingsEntity ...$bulkSettings): bool + { + $db = DatabaseManager::getInstance(); + + $db->beginTransaction(); + + try { + $stmt = $db->prepare('UPDATE cmw_users_settings SET users_settings_value = :value WHERE users_settings_name = :name'); + + foreach ($bulkSettings as $bulkSetting) { + $data = ['name' => $bulkSetting->getName(), 'value' => $bulkSetting->getValue()]; + + if (!$stmt->execute($data)) { + throw new RuntimeException('Failed to execute statement'); + } + } + + $db->commit(); + return true; + } catch (Exception $e) { + $db->rollBack(); + return false; + } + } + + public function addSetting(string $settingName, string $settingValue): void { $db = DatabaseManager::getInstance(); $req = $db->prepare('INSERT INTO cmw_users_settings (users_settings_value, users_settings_updated, users_settings_name) VALUES (:settingValue, now(), :settingName)'); - $req->execute(array('settingName' => $settingName, 'settingValue' => $settingValue)); + $req->execute(['settingName' => $settingName, 'settingValue' => $settingValue]); + } + + public function bulkAddSettings(BulkSettingsEntity ...$bulkSettings): bool + { + $db = DatabaseManager::getInstance(); + + $sql = "INSERT INTO cmw_users_settings (users_settings_name, users_settings_value) VALUES "; + + $values = []; + $data = []; + foreach ($bulkSettings as $bulkSetting) { + $values[] = "(:name{$bulkSetting->getName()}, :value{$bulkSetting->getValue()})"; + + $data[] = [ + 'name' . $bulkSetting->getName() => $bulkSetting->getName(), + 'value' . $bulkSetting->getValue() => $bulkSetting->getValue(), + ]; + } + + $sql .= implode(', ', $values); + + return $db->prepare($sql)->execute($data); } - public static function deleteSetting(string $settingName): void + public function deleteSetting(string $settingName): void { $db = DatabaseManager::getInstance(); $req = $db->prepare('DELETE FROM cmw_users_settings where users_settings_name = :settingName'); - $req->execute(array('settingName' => $settingName)); + $req->execute(['settingName' => $settingName]); } /** @@ -97,7 +151,7 @@ public function removeBlacklistedPseudo(int $id): bool } /** - * @return \CMW\Entity\Users\BlacklistedPseudoEntity[] + * @return BlacklistedPseudoEntity[] */ public function getBlacklistedPseudos(): array { @@ -126,7 +180,7 @@ public function getBlacklistedPseudos(): array /** * @param int $id - * @return \CMW\Entity\Users\BlacklistedPseudoEntity|null + * @return BlacklistedPseudoEntity|null */ public function getBlacklistedPseudo(int $id): ?BlacklistedPseudoEntity { @@ -176,7 +230,7 @@ public function isPseudoBlacklisted(string $pseudo): bool } /** - * @return \CMW\Entity\Users\UserEnforced2FaEntity[] + * @return UserEnforced2FaEntity[] */ public function getEnforcedRoles(): array { @@ -203,7 +257,7 @@ public function getEnforcedRoles(): array public function updateEnforcedRoles($roleId): bool { foreach (RolesModel::getInstance()->getRoles() as $role) { - if ($role->getId() == $roleId) { + if ($role->getId() === $roleId) { if ($this->addEnforcedRoles($roleId)) { foreach (UsersModel::getInstance()->getUsers() as $user) { foreach ($user->getRoles() as $userRole) { diff --git a/App/Package/Users/Views/settings.admin.view.php b/App/Package/Users/Views/settings.admin.view.php index ea5a24f9..90af107e 100644 --- a/App/Package/Users/Views/settings.admin.view.php +++ b/App/Package/Users/Views/settings.admin.view.php @@ -67,10 +67,10 @@
@@ -81,8 +81,8 @@