diff --git a/css/toastr.min.css b/css/toastr.min.css new file mode 100644 index 00000000..c174f8f3 --- /dev/null +++ b/css/toastr.min.css @@ -0,0 +1 @@ +.toast-title{font-weight:bold}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:alpha(opacity=80);filter:alpha(opacity=80);line-height:1}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:alpha(opacity=40);filter:alpha(opacity=40)}.rtl .toast-close-button{left:-0.3em;float:left;right:.3em}button.toast-close-button{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999;pointer-events:none}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;pointer-events:auto;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8;-ms-filter:alpha(opacity=80);filter:alpha(opacity=80)}#toast-container>div.rtl{direction:rtl;padding:15px 50px 15px 15px;background-position:right 15px center}#toast-container>div:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:alpha(opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=")!important}#toast-container>.toast-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=")!important}#toast-container>.toast-success{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==")!important}#toast-container>.toast-warning{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=")!important}#toast-container.toast-top-center>div,#toast-container.toast-bottom-center>div{width:300px;margin-left:auto;margin-right:auto}#toast-container.toast-top-full-width>div,#toast-container.toast-bottom-full-width>div{width:96%;margin-left:auto;margin-right:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:alpha(opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-0.2em;top:-0.2em}#toast-container .rtl .toast-close-button{left:-0.2em;right:.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-0.2em;top:-0.2em}#toast-container .rtl .toast-close-button{left:-0.2em;right:.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}#toast-container>div.rtl{padding:15px 50px 15px 15px}} \ No newline at end of file diff --git a/inc/Plugins/Authenticator/ActionController.class.php b/inc/Plugins/Authenticator/ActionController.class.php new file mode 100644 index 00000000..0c90cba0 --- /dev/null +++ b/inc/Plugins/Authenticator/ActionController.class.php @@ -0,0 +1,117 @@ +. + */ + +namespace Plugins\Authenticator; + +use SP\Controller\ItemControllerInterface; +use SP\Controller\RequestControllerTrait; +use SP\Core\Exceptions\SPException; +use SP\Core\Plugin\PluginUtil; +use SP\Core\Session; +use SP\DataModel\PluginData; +use SP\Http\Request; +use SP\Mgmt\Plugins\Plugin; +use SP\Util\Json; + +/** + * Class ActionController + * + * @package Plugins\Authenticator + */ +class ActionController implements ItemControllerInterface +{ + const ACTION_TWOFA_SAVE = 1; + const ACTION_TWOFA_CHECK = 1; + + use RequestControllerTrait; + + /** + * @var AuthenticatorPlugin + */ + protected $Plugin; + + public function __construct() + { + $this->Plugin = PluginUtil::getPluginData('Authenticator'); + + $this->init(); + } + + /** + * Guardar los datos del plugin + */ + protected function save() + { + $pin = Request::analyze('security_pin', 0); + + $twoFa = new Authenticator($this->itemId, Session::getUserData()->getUserLogin()); + + if (!$twoFa->verifyKey($pin)) { + $this->jsonResponse->setDescription(_('Código incorrecto')); + Json::returnJson($this->jsonResponse); + } + + try { + $data = $this->Plugin->getData(); + + if (!isset($data[$this->itemId])) { + $data[$this->itemId] = new AuthenticatorData(); + } + + /** @var AuthenticatorData $AuthenticatorData */ + $AuthenticatorData = $data[$this->itemId]; + $AuthenticatorData->setUserId($this->itemId); + $AuthenticatorData->setTwofaEnabled(Request::analyze('security_2faenabled', 0, false, 1)); + + $PluginData = new PluginData(); + $PluginData->setPluginName($this->Plugin->getName()); + $PluginData->setPluginEnabled(1); + $PluginData->setPluginData(serialize($data)); + + Plugin::getItem($PluginData)->update(); + + $this->jsonResponse->setStatus(0); + $this->jsonResponse->setDescription(_('Preferencias actualizadas')); + } catch (SPException $e) { + $this->jsonResponse->setDescription($e->getMessage()); + } + + Json::returnJson($this->jsonResponse); + } + + /** + * Realizar la acción solicitada en la la petición HTTP + */ + public function doAction() + { + switch ($this->actionId) { + case ActionController::ACTION_TWOFA_SAVE: + $this->save(); + break; + case ActionController::ACTION_TWOFA_CHECK: + break; + default: + } + } +} \ No newline at end of file diff --git a/inc/Plugins/Authenticator/AuthenticatorData.class.php b/inc/Plugins/Authenticator/AuthenticatorData.class.php new file mode 100644 index 00000000..552825fd --- /dev/null +++ b/inc/Plugins/Authenticator/AuthenticatorData.class.php @@ -0,0 +1,74 @@ +. + */ + +namespace Plugins\Authenticator; + +/** + * Class AuthenticatorData + * + * @package Plugins\Authenticator + */ +class AuthenticatorData +{ + /** + * @var + */ + public $userId; + /** + * @var int + */ + public $twofaEnabled = 0; + + /** + * @return mixed + */ + public function getUserId() + { + return (int)$this->userId; + } + + /** + * @param mixed $userId + */ + public function setUserId($userId) + { + $this->userId = (int)$userId; + } + + /** + * @return bool + */ + public function isTwofaEnabled() + { + return (bool)$this->twofaEnabled; + } + + /** + * @param int $twofaEnabled + */ + public function setTwofaEnabled($twofaEnabled) + { + $this->twofaEnabled = (int)$twofaEnabled; + } +} \ No newline at end of file diff --git a/inc/Plugins/Authenticator/AuthenticatorPlugin.class.php b/inc/Plugins/Authenticator/AuthenticatorPlugin.class.php index d3061062..c696ffa7 100644 --- a/inc/Plugins/Authenticator/AuthenticatorPlugin.class.php +++ b/inc/Plugins/Authenticator/AuthenticatorPlugin.class.php @@ -35,6 +35,11 @@ use SplSubject; */ class AuthenticatorPlugin extends PluginBase { + /** + * @var AuthenticatorData[] + */ + protected $data = []; + /** * Receive update from subject * diff --git a/inc/Plugins/Authenticator/PreferencesController.class.php b/inc/Plugins/Authenticator/PreferencesController.class.php index 1a7ace4b..c1a93312 100644 --- a/inc/Plugins/Authenticator/PreferencesController.class.php +++ b/inc/Plugins/Authenticator/PreferencesController.class.php @@ -26,8 +26,8 @@ namespace Plugins\Authenticator; use InvalidArgumentException; use SP\Controller\TabControllerBase; -use SP\Core\ActionsInterface; use SP\Core\Plugin\PluginBase; +use SP\Util\ArrayUtil; /** * Class Controller @@ -49,7 +49,7 @@ class PreferencesController * Controller constructor. * * @param TabControllerBase $Controller - * @param PluginBase $Plugin + * @param PluginBase $Plugin */ public function __construct(TabControllerBase $Controller, PluginBase $Plugin) { @@ -64,19 +64,27 @@ class PreferencesController { $base = $this->Plugin->getThemeDir() . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'userpreferences'; + // Datos del plugin + $pluginData = $this->Plugin->getData(); + + // Datos del usuario de la sesión $UserData = $this->Controller->getUserData(); + // Buscar al usuario en los datos del plugin + /** @var AuthenticatorData $AuthenticatorData */ + $AuthenticatorData = ArrayUtil::searchInObject($pluginData, 'userId', $UserData->getUserId(), new AuthenticatorData()); + $this->Controller->view->addTemplate('preferences-security', $base); try { $twoFa = new Authenticator($UserData->getUserId(), $UserData->getUserLogin()); - $this->Controller->view->assign('qrCode', !$UserData->getUserPreferences()->isUse2Fa() ? $twoFa->getUserQRCode() : ''); + $this->Controller->view->assign('qrCode', !$AuthenticatorData->isTwofaEnabled() ? $twoFa->getUserQRCode() : ''); $this->Controller->view->assign('userId', $UserData->getUserId()); - $this->Controller->view->assign('chk2FAEnabled', $UserData->getUserPreferences()->isUse2Fa()); + $this->Controller->view->assign('chk2FAEnabled', $AuthenticatorData->isTwofaEnabled()); $this->Controller->view->assign('tabIndex', $this->Controller->addTab(_('Seguridad')), 'security'); - $this->Controller->view->assign('actionId', ActionsInterface::ACTION_USR_PREFERENCES_SECURITY, 'security'); + $this->Controller->view->assign('actionId', ActionController::ACTION_TWOFA_SAVE, 'security'); } catch (InvalidArgumentException $e) { } } diff --git a/inc/Plugins/Authenticator/ajax/ajax_prefsSave.php b/inc/Plugins/Authenticator/ajax/ajax_prefsSave.php new file mode 100644 index 00000000..b1099228 --- /dev/null +++ b/inc/Plugins/Authenticator/ajax/ajax_prefsSave.php @@ -0,0 +1,36 @@ +. + * + */ + +use Plugins\Authenticator\ActionController; +use SP\Http\Request; + +define('APP_ROOT', '../../../..'); + +require_once APP_ROOT . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'Base.php'; + +Request::checkReferer('POST'); + +$Controller = new ActionController(); +$Controller->doAction(); \ No newline at end of file diff --git a/inc/Plugins/Authenticator/js/plugin.js b/inc/Plugins/Authenticator/js/plugin.js index 50d094c8..7d11a866 100644 --- a/inc/Plugins/Authenticator/js/plugin.js +++ b/inc/Plugins/Authenticator/js/plugin.js @@ -27,18 +27,27 @@ sysPass.Plugin.Authenticator = function (Common) { var log = Common.log; var base = "/inc/Plugins/Authenticator"; - var twofa = function ($obj) { - log.info("Authenticator:twofa"); + var twofa = { + check: function ($obj) { + }, + save: function ($obj) { + log.info("Authenticator:twofa"); - var opts = Common.appRequests().getRequestOpts(); - opts.url = base + "/ajax/ajax_save.php"; - opts.data = $obj.serialize(); + var opts = Common.appRequests().getRequestOpts(); + opts.url = base + "/ajax/ajax_prefsSave.php"; + opts.data = $obj.serialize(); - Common.appRequests().getActionCall(opts, function (json) { - Common.msg.out(json); + Common.appRequests().getActionCall(opts, function (json) { + Common.msg.out(json); - Common.appActions().doAction({actionId: $obj.data("nextaction-id"), itemId: $obj.data("activetab")}); - }); + if (json.status === 0) { + Common.appActions().doAction({ + actionId: $obj.data("nextaction-id"), + itemId: $obj.data("activetab") + }); + } + }); + } }; var init = function () { diff --git a/inc/Plugins/Authenticator/js/plugin.min.js b/inc/Plugins/Authenticator/js/plugin.min.js index 626a9fed..f05d2d56 100644 --- a/inc/Plugins/Authenticator/js/plugin.min.js +++ b/inc/Plugins/Authenticator/js/plugin.min.js @@ -1 +1 @@ -sysPass.Plugin.Authenticator=function(a){var d=a.log;return{twofa:function(c){d.info("Authenticator:twofa");var b=a.appRequests().getRequestOpts();b.url="/inc/Plugins/Authenticator/ajax/ajax_save.php";b.data=c.serialize();a.appRequests().getActionCall(b,function(b){a.msg.out(b);a.appActions().doAction({actionId:c.data("nextaction-id"),itemId:c.data("activetab")})})}}}; +sysPass.Plugin.Authenticator=function(a){var d=a.log;return{twofa:{check:function(a){},save:function(c){d.info("Authenticator:twofa");var b=a.appRequests().getRequestOpts();b.url="/inc/Plugins/Authenticator/ajax/ajax_prefsSave.php";b.data=c.serialize();a.appRequests().getActionCall(b,function(b){a.msg.out(b);0===b.status&&a.appActions().doAction({actionId:c.data("nextaction-id"),itemId:c.data("activetab")})})}}}}; diff --git a/inc/Plugins/Authenticator/themes/material-blue/views/userpreferences/preferences-security.inc b/inc/Plugins/Authenticator/themes/material-blue/views/userpreferences/preferences-security.inc index e6f286c4..838bd4b4 100644 --- a/inc/Plugins/Authenticator/themes/material-blue/views/userpreferences/preferences-security.inc +++ b/inc/Plugins/Authenticator/themes/material-blue/views/userpreferences/preferences-security.inc @@ -8,7 +8,7 @@