* [MOD] Improved LDAP import

* [ADD] Groups import from LDAP
* [MOD] Improved LDAP auth behavior
* [MOD] Config data is always cloned on every request
* [MOD] Improved non RSA encrypted data detection
* [MOD] Code refactoring
This commit is contained in:
nuxsmin
2018-03-01 00:49:00 +01:00
parent bfefa194ef
commit 3504e66c9c
41 changed files with 1726 additions and 947 deletions

View File

@@ -46,7 +46,7 @@ class ConfigAccountController extends SimpleControllerBase
*/
public function saveAction()
{
$configData = clone $this->config->getConfigData();
$configData = $this->config->getConfigData();
$eventMessage = EventMessage::factory();

View File

@@ -54,8 +54,7 @@ class ConfigBackupController extends SimpleControllerBase
}
try {
$backupService = new FileBackupService();
$backupService->doBackup();
$this->dic->get(FileBackupService::class)->doBackup();
$this->eventDispatcher->notifyEvent('run.backup.end',
new Event($this, EventMessage::factory()

View File

@@ -46,7 +46,7 @@ class ConfigGeneralController extends SimpleControllerBase
*/
public function saveAction()
{
$configData = clone $this->config->getConfigData();
$configData = $this->config->getConfigData();
$eventMessage = EventMessage::factory();
// General

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -28,9 +28,15 @@ use SP\Core\Acl\ActionsInterface;
use SP\Core\Acl\UnauthorizedPageException;
use SP\Core\Events\Event;
use SP\Core\Events\EventMessage;
use SP\Core\Exceptions\SPException;
use SP\Core\Exceptions\ValidationException;
use SP\Http\JsonResponse;
use SP\Http\Request;
use SP\Modules\Web\Controllers\Traits\ConfigTrait;
use SP\Providers\Auth\Ldap\LdapParams;
use SP\Services\Ldap\LdapCheckService;
use SP\Services\Ldap\LdapImportParams;
use SP\Services\Ldap\LdapImportService;
/**
* Class ConfigLdapController
@@ -46,48 +52,168 @@ class ConfigLdapController extends SimpleControllerBase
*/
public function saveAction()
{
$eventMessage = EventMessage::factory();
$configData = clone $this->config->getConfigData();
try {
$eventMessage = EventMessage::factory();
$configData = $this->config->getConfigData();
// LDAP
$ldapEnabled = Request::analyze('ldap_enabled', false, false, true);
$ldapADSEnabled = Request::analyze('ldap_ads', false, false, true);
$ldapServer = Request::analyze('ldap_server');
$ldapBase = Request::analyze('ldap_base');
$ldapGroup = Request::analyze('ldap_group');
$ldapDefaultGroup = Request::analyze('ldap_defaultgroup', 0);
$ldapDefaultProfile = Request::analyze('ldap_defaultprofile', 0);
$ldapBindUser = Request::analyze('ldap_binduser');
$ldapBindPass = Request::analyzeEncrypted('ldap_bindpass');
// LDAP
$ldapEnabled = Request::analyze('ldap_enabled', false, false, true);
$ldapDefaultGroup = Request::analyze('ldap_defaultgroup', 0);
$ldapDefaultProfile = Request::analyze('ldap_defaultprofile', 0);
// Valores para la configuración de LDAP
if ($ldapEnabled && (!$ldapServer || !$ldapBase || !$ldapBindUser)) {
$this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Faltan parámetros de LDAP'));
}
$ldapParams = $this->getLdapParamsFromRequest();
if ($ldapEnabled) {
$configData->setLdapEnabled(true);
$configData->setLdapAds($ldapADSEnabled);
$configData->setLdapServer($ldapServer);
$configData->setLdapBase($ldapBase);
$configData->setLdapGroup($ldapGroup);
$configData->setLdapDefaultGroup($ldapDefaultGroup);
$configData->setLdapDefaultProfile($ldapDefaultProfile);
$configData->setLdapBindUser($ldapBindUser);
$configData->setLdapBindPass($ldapBindPass);
if ($configData->isLdapEnabled() === false) {
$eventMessage->addDescription(__u('LDAP habiltado'));
// Valores para la configuración de LDAP
if ($ldapEnabled && !($ldapParams->getServer() || $ldapParams->getSearchBase() || $ldapParams->getBindDn())) {
$this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Faltan parámetros de LDAP'));
}
} elseif ($ldapEnabled === false && $configData->isLdapEnabled()) {
$configData->setLdapEnabled(false);
$eventMessage->addDescription(__u('LDAP deshabilitado'));
if ($ldapEnabled) {
$configData->setLdapEnabled(true);
$configData->setLdapAds($ldapParams->isAds());
$configData->setLdapServer($ldapParams->getServer());
$configData->setLdapBase($ldapParams->getSearchBase());
$configData->setLdapGroup($ldapParams->getGroup());
$configData->setLdapDefaultGroup($ldapDefaultGroup);
$configData->setLdapDefaultProfile($ldapDefaultProfile);
$configData->setLdapBindUser($ldapParams->getBindDn());
$configData->setLdapBindPass($ldapParams->getBindPass());
if ($configData->isLdapEnabled() === false) {
$eventMessage->addDescription(__u('LDAP habiltado'));
}
} elseif ($ldapEnabled === false && $configData->isLdapEnabled()) {
$configData->setLdapEnabled(false);
$eventMessage->addDescription(__u('LDAP deshabilitado'));
}
$this->saveConfig($configData, $this->config, function () use ($eventMessage) {
$this->eventDispatcher->notifyEvent('save.config.ldap', new Event($this, $eventMessage));
});
} catch (ValidationException $e) {
$this->returnJsonResponseException($e);
}
}
/**
* @return LdapParams
* @throws ValidationException
*/
protected function getLdapParamsFromRequest()
{
$data = LdapParams::getServerAndPort(Request::analyze('ldap_server'));
if ($data === false) {
throw new ValidationException(__u('Parámetros de LDAP incorrectos'));
}
$this->saveConfig($configData, $this->config, function () use ($eventMessage) {
$this->eventDispatcher->notifyEvent('save.config.ldap', new Event($this, $eventMessage));
});
return (new LdapParams())
->setServer($data['server'])
->setPort(isset($data['port']) ? $data['port'] : 389)
->setSearchBase(Request::analyze('ldap_base'))
->setGroup(Request::analyze('ldap_group'))
->setBindDn(Request::analyze('ldap_binduser'))
->setBindPass(Request::analyzeEncrypted('ldap_bindpass'))
->setAds(Request::analyze('ldap_ads', false, false, true));
}
/**
* checkAction
*/
public function checkAction()
{
try {
$ldapParams = $this->getLdapParamsFromRequest();
// Valores para la configuración de LDAP
if (!($ldapParams->getServer() || $ldapParams->getSearchBase() || $ldapParams->getBindDn())) {
$this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Faltan parámetros de LDAP'));
}
$ldapCheckService = $this->dic->get(LdapCheckService::class);
$ldapCheckService->checkConnection($ldapParams);
$results = $ldapCheckService->getUsersAndGroups();
$this->returnJsonResponseData(
$results,
JsonResponse::JSON_SUCCESS,
__u('Conexión a LDAP correcta'),
[sprintf(__('Objetos encontrados: %d'), $results['count'])]
);
} catch (\Exception $e) {
processException($e);
$this->returnJsonResponseException($e);
// $this->JsonResponse->addMessage(__('Revise el registro de eventos para más detalles', false));
}
}
/**
* importAction
*
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function importAction()
{
try {
$ldapImportParams = new LdapImportParams();
$ldapImportParams->loginAttribute = Request::analyze('ldap_login_attribute');
$ldapImportParams->userNameAttribute = Request::analyze('ldap_username_attribute');
$ldapImportParams->userGroupNameAttribute = Request::analyze('ldap_groupname_attribute');
$ldapImportParams->defaultUserGroup = Request::analyze('ldap_defaultgroup', 0);
$ldapImportParams->defaultUserProfile = Request::analyze('ldap_defaultprofile', 0);
$checkImportGroups = Request::analyze('ldap_group_import', false, false, true);
if ((empty($ldapImportParams->loginAttribute)
|| empty($ldapImportParams->userNameAttribute)
|| empty($ldapImportParams->defaultUserGroup)
|| empty($ldapImportParams->defaultUserProfile))
&& ($checkImportGroups === true && empty($ldapImportParams->userGroupNameAttribute))
) {
throw new ValidationException(__u('Parámetros de LDAP incorrectos'));
}
$ldapParams = $this->getLdapParamsFromRequest();
$userLdapService = $this->dic->get(LdapImportService::class);
$this->eventDispatcher->notifyEvent('import.ldap.start',
new Event($this, EventMessage::factory()->addDescription(__u('Importación LDAP')))
);
$userLdapService->importUsers($ldapParams, $ldapImportParams);
if ($checkImportGroups === true) {
$userLdapService->importGroups($ldapParams, $ldapImportParams);
}
$this->eventDispatcher->notifyEvent('import.ldap.end',
new Event($this, EventMessage::factory()->addDescription(__u('Importación finalizada')))
);
if ($userLdapService->getTotalObjects() === 0) {
throw new SPException(__u('No se encontraron objetos para sincronizar'));
}
$this->returnJsonResponse(
JsonResponse::JSON_SUCCESS,
__u('Importación de usuarios de LDAP realizada'),
[
sprintf(__('Usuarios importados: %d/%d'), $userLdapService->getSyncedObjects(), $userLdapService->getTotalObjects()),
sprintf(__('Errores: %d'), $userLdapService->getErrorObjects())
]
);
} catch (\Exception $e) {
processException($e);
$this->returnJsonResponseException($e);
}
}
protected function initialize()

View File

@@ -47,7 +47,7 @@ class ConfigMailController extends SimpleControllerBase
public function saveAction()
{
$eventMessage = EventMessage::factory();
$configData = clone $this->config->getConfigData();
$configData = $this->config->getConfigData();
// Mail
$mailEnabled = Request::analyze('mail_enabled', false, false, true);

View File

@@ -47,7 +47,7 @@ class ConfigWikiController extends SimpleControllerBase
public function saveAction()
{
$eventMessage = EventMessage::factory();
$configData = clone $this->config->getConfigData();
$configData = $this->config->getConfigData();
// Wiki
$wikiEnabled = Request::analyze('wiki_enabled', false, false, true);

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -38,9 +38,9 @@ trait JsonTrait
/**
* Returns JSON response
*
* @param int $status Status code
* @param string $description Untranslated description string
* @param array|null $messages Untranslated massages array of strings
* @param int $status Status code
* @param string $description Untranslated description string
* @param array|null $messages Untranslated massages array of strings
*/
protected function returnJsonResponse($status, $description, array $messages = null)
{
@@ -58,11 +58,12 @@ trait JsonTrait
/**
* Returns JSON response
*
* @param mixed $data
* @param int $status Status code
* @param null $description Untranslated description string
* @param mixed $data
* @param int $status Status code
* @param string $description Untranslated description string
* @param array $messages
*/
protected function returnJsonResponseData($data, $status = JsonResponse::JSON_SUCCESS, $description = null)
protected function returnJsonResponseData($data, $status = JsonResponse::JSON_SUCCESS, $description = null, array $messages = null)
{
$jsonResponse = new JsonResponse();
$jsonResponse->setStatus($status);
@@ -72,6 +73,9 @@ trait JsonTrait
$jsonResponse->setDescription($description);
}
if (null !== $messages) {
$jsonResponse->setMessages($messages);
}
Json::returnJson($jsonResponse);
}
@@ -80,7 +84,7 @@ trait JsonTrait
* Returns JSON response
*
* @param \Exception $exception
* @param int $status Status code
* @param int $status Status code
*/
protected function returnJsonResponseException(\Exception $exception, $status = JsonResponse::JSON_ERROR)
{

View File

@@ -479,27 +479,21 @@ sysPass.Theme = function (Common) {
/**
* Elementos HTML del tema
*
* @type {{getList: html.getList}}
*/
var html = {
const html = {
getList: function (items, icon) {
var $ul = $("<ul class=\"ldap-list-item mdl-list\"></ul>");
var $li = $("<li class=\"mdl-list__item\"></li>");
var $span = $("<span class=\"mdl-list__item-primary-content\"></span>");
const $ul = $("<ul class=\"ldap-list-item mdl-list\"></ul>");
const $li = $("<li class=\"mdl-list__item\"></li>");
const $span = $("<span class=\"mdl-list__item-primary-content\"></span>");
if (icon === undefined) {
icon = "<i class=\"material-icons mdl-list__item-icon\">person</i>";
} else {
icon = "<i class=\"material-icons mdl-list__item-icon\">" + icon + "</i>";
}
const i = "<i class=\"material-icons mdl-list__item-icon\">" + (icon === undefined ? "person" : icon) + "</i>";
items.forEach(function (value) {
var $spanClone = $span.clone();
$spanClone.append(icon);
const $spanClone = $span.clone();
$spanClone.append(i);
$spanClone.append(value);
var $item = $li.clone().append($spanClone);
const $item = $li.clone().append($spanClone);
$ul.append($item);
});
@@ -507,15 +501,15 @@ sysPass.Theme = function (Common) {
},
tabs: {
add: function (header, index, title, isActive) {
var $header = $(header);
var active = "";
const $header = $(header);
let active;
if (isActive === 1) {
$header.parent().find("#tabs-" + index).addClass("is-active");
active = "is-active";
}
var tab = "<a href=\"#tabs-" + index + "\" class=\"mdl-tabs__tab " + active + "\">" + title + "</a>";
const tab = "<a href=\"#tabs-" + index + "\" class=\"mdl-tabs__tab " + active + "\">" + title + "</a>";
$header.append(tab);
}

View File

@@ -1,20 +1,20 @@
var $jscomp={scope:{},findInternal:function(a,e,c){a instanceof String&&(a=String(a));for(var g=a.length,k=0;k<g;k++){var l=a[k];if(e.call(c,l,k,a))return{i:k,v:l}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(a,e,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[e]=c.value)};
$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(a,e,c,g){if(e){c=$jscomp.global;a=a.split(".");for(g=0;g<a.length-1;g++){var k=a[g];k in c||(c[k]={});c=c[k]}a=a[a.length-1];g=c[a];e=e(g);e!=g&&null!=e&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:e})}};
var $jscomp={scope:{},findInternal:function(a,f,c){a instanceof String&&(a=String(a));for(var h=a.length,k=0;k<h;k++){var l=a[k];if(f.call(c,l,k,a))return{i:k,v:l}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(a,f,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[f]=c.value)};
$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(a,f,c,h){if(f){c=$jscomp.global;a=a.split(".");for(h=0;h<a.length-1;h++){var k=a[h];k in c||(c[k]={});c=c[k]}a=a[a.length-1];h=c[a];f=f(h);f!=h&&null!=f&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:f})}};
$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(a,c){return $jscomp.findInternal(this,a,c).v}},"es6-impl","es3");
sysPass.Theme=function(a){var e=a.log,c={elems:{$wrap:$("#wrap-loading"),$loading:$("#loading")},show:function(a){void 0!==a&&!0===a&&c.elems.$wrap.addClass("overlay-full");c.elems.$wrap.show();c.elems.$loading.addClass("is-active")},hide:function(){c.elems.$wrap.removeClass("overlay-full").hide();c.elems.$loading.removeClass("is-active")},upgradeFull:function(){c.elems.$wrap.addClass("overlay-full")}},g=function(b){var f=0,d="",h="";a.passwordData.complexity.symbols&&(d+="!\"\\\u00b7@|#$~%&/()=?'\u00bf\u00a1^*[]\u00b7;,_-{}<>");
a.passwordData.complexity.numbers&&(d+="1234567890");a.passwordData.complexity.chars&&(d+="abcdefghijklmnopqrstuvwxyz",a.passwordData.complexity.uppercase&&(d+="ABCDEFGHIJKLMNOPQRSTUVWXYZ"));for(;f++<a.passwordData.complexity.numlength;)h+=d.charAt(Math.floor(Math.random()*(d.length-1)+0));$("#viewPass").attr("title",h);var c=zxcvbn(h);a.passwordData.passLength=h.length;b?(f=b.parent(),d=$("#"+b.attr("id")+"R"),a.outputResult(c,b),b=new MaterialTextfield,f.find("input:password").val(h),f.addClass(b.CssClasses_.IS_DIRTY).removeClass(b.CssClasses_.IS_INVALID),
0<d.length&&(d.val(h).parent().addClass(b.CssClasses_.IS_DIRTY).removeClass(b.CssClasses_.IS_INVALID),a.encryptFormValue(d)),f.find("#passLevel").show(500)):(a.outputResult(c),$("input:password, input.password").val(h),$("#passLevel").show(500))},k=function(){var b='<div id="box-complexity"><div><label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-chars"><input type="checkbox" id="checkbox-chars" class="mdl-checkbox__input" name="checkbox-chars" checked/><span class="mdl-checkbox__label">'+
sysPass.Theme=function(a){var f=a.log,c={elems:{$wrap:$("#wrap-loading"),$loading:$("#loading")},show:function(a){void 0!==a&&!0===a&&c.elems.$wrap.addClass("overlay-full");c.elems.$wrap.show();c.elems.$loading.addClass("is-active")},hide:function(){c.elems.$wrap.removeClass("overlay-full").hide();c.elems.$loading.removeClass("is-active")},upgradeFull:function(){c.elems.$wrap.addClass("overlay-full")}},h=function(b){var m=0,d="",e="";a.passwordData.complexity.symbols&&(d+="!\"\\\u00b7@|#$~%&/()=?'\u00bf\u00a1^*[]\u00b7;,_-{}<>");
a.passwordData.complexity.numbers&&(d+="1234567890");a.passwordData.complexity.chars&&(d+="abcdefghijklmnopqrstuvwxyz",a.passwordData.complexity.uppercase&&(d+="ABCDEFGHIJKLMNOPQRSTUVWXYZ"));for(;m++<a.passwordData.complexity.numlength;)e+=d.charAt(Math.floor(Math.random()*(d.length-1)+0));$("#viewPass").attr("title",e);var c=zxcvbn(e);a.passwordData.passLength=e.length;b?(m=b.parent(),d=$("#"+b.attr("id")+"R"),a.outputResult(c,b),b=new MaterialTextfield,m.find("input:password").val(e),m.addClass(b.CssClasses_.IS_DIRTY).removeClass(b.CssClasses_.IS_INVALID),
0<d.length&&(d.val(e).parent().addClass(b.CssClasses_.IS_DIRTY).removeClass(b.CssClasses_.IS_INVALID),a.encryptFormValue(d)),m.find("#passLevel").show(500)):(a.outputResult(c),$("input:password, input.password").val(e),$("#passLevel").show(500))},k=function(){var b='<div id="box-complexity"><div><label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-chars"><input type="checkbox" id="checkbox-chars" class="mdl-checkbox__input" name="checkbox-chars" checked/><span class="mdl-checkbox__label">'+
a.config().LANG[63]+'</span></label><label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-numbers"><input type="checkbox" id="checkbox-numbers" class="mdl-checkbox__input" name="checkbox-numbers" checked/><span class="mdl-checkbox__label">'+a.config().LANG[35]+'</span></label><label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-uppercase"><input type="checkbox" id="checkbox-uppercase" class="mdl-checkbox__input" name="checkbox-uppercase"/><span class="mdl-checkbox__label">'+
a.config().LANG[36]+'</span></label><label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-symbols"><input type="checkbox" id="checkbox-symbols" class="mdl-checkbox__input" name="checkbox-symbols"/><span class="mdl-checkbox__label">'+a.config().LANG[37]+'</span></label><div class="mdl-textfield mdl-js-textfield textfield-passlength"><input class="mdl-textfield__input" type="number" pattern="[0-9]*" id="passlength" /><label class="mdl-textfield__label" for="passlength">'+a.config().LANG[38]+
"</label></div></div></div>";mdlDialog().show({title:a.config().LANG[29],text:b,negative:{title:a.config().LANG[44]},positive:{title:a.config().LANG[43],onClick:function(f){f.preventDefault();a.passwordData.complexity.chars=$("#checkbox-chars").is(":checked");a.passwordData.complexity.numbers=$("#checkbox-numbers").is(":checked");a.passwordData.complexity.uppercase=$("#checkbox-uppercase").is(":checked");a.passwordData.complexity.symbols=$("#checkbox-symbols").is(":checked");a.passwordData.complexity.numlength=
parseInt($("#passlength").val())}},cancelable:!0,contentStyle:{"max-width":"300px"},onLoaded:function(){$("#checkbox-chars").prop("checked",a.passwordData.complexity.chars);$("#checkbox-numbers").prop("checked",a.passwordData.complexity.numbers);$("#checkbox-uppercase").prop("checked",a.passwordData.complexity.uppercase);$("#checkbox-symbols").prop("checked",a.passwordData.complexity.symbols);$("#passlength").val(a.passwordData.complexity.numlength)}})},l=function(b){b.find(".passwordfield__input").each(function(){var f=
$(this);if("true"!==f.attr("data-pass-upgraded")){var d=f.parent(),b=f.attr("id"),c='<button id="menu-speed-'+b+'" class="mdl-button mdl-js-button mdl-button--icon" type="button" title="'+a.config().LANG[27]+'"><i class="material-icons">more_vert</i></button>',c=c+('<ul class="mdl-menu mdl-js-menu" for="menu-speed-'+b+'">')+('<li class="mdl-menu__item passGen"><i class="material-icons">settings</i>'+a.config().LANG[28]+"</li>"),c=c+('<li class="mdl-menu__item passComplexity"><i class="material-icons">vpn_key</i>'+
a.config().LANG[29]+"</li>"),c=c+('<li class="mdl-menu__item reset"><i class="material-icons">refresh</i>'+a.config().LANG[30]+"</li>");d.after('<div class="password-actions" />');d.next(".password-actions").prepend('<span class="passLevel passLevel-'+b+' fullround" title="'+a.config().LANG[31]+'"></span>').prepend('<i class="showpass material-icons" title="'+a.config().LANG[32]+'">remove_red_eye</i>').prepend(c);f.on("keyup",function(){a.checkPassLevel(f)});d=f.parent().next();d.find(".passGen").on("click",
function(){g(f);f.focus()});d.find(".passComplexity").on("click",function(){k()});d.find(".showpass").on("mouseover",function(){$(this).attr("title",f.val())});d.find(".reset").on("click",function(){f.val("");var a=$("#"+b+"R");0<a.length&&a.val("");componentHandler.upgradeDom()});f.attr("data-pass-upgraded","true")}});b.find(".passwordfield__input-show").each(function(){var b=$(this),d=$('<i class="showpass material-icons" title="'+a.config().LANG[32]+'">remove_red_eye</i>');if(1===b.data("clipboard")){var c=
$('<i class="clip-pass-icon material-icons" title="'+a.config().LANG[34]+'" data-clipboard-target="#'+b.attr("id")+'">content_paste</i>');b.parent().after(c).after(d)}else b.parent().after(d);d.on("mouseover",function(){d.attr("title",b.val())})})},m=function(b){e.info("setupDatePicker");var c={format:"YYYY-MM-DD",lang:a.config().LOCALE.substr(0,2),time:!1,cancelText:a.config().LANG[44],okText:a.config().LANG[43],clearText:a.config().LANG[30],nowText:a.config().LANG[56],minDate:new Date,triggerEvent:"dateIconClick"};
b.find(".password-datefield__input").each(function(){var b=$(this);b.bootstrapMaterialDatePicker(c);b.parent().append("<input type='hidden' name='passworddatechange_unix' value='"+moment.tz(b.val(),a.config().TIMEZONE).format("X")+"' />");b.parent().next("i").on("click",function(){b.trigger("dateIconClick")});b.on("change",function(){var c;c=moment.tz(b.val(),a.config().TIMEZONE).format("X");b.parent().find("input[name='passworddatechange_unix']").val(c)})})};return{passwordDetect:l,password:g,viewsTriggers:{main:function(){var a=
"</label></div></div></div>";mdlDialog().show({title:a.config().LANG[29],text:b,negative:{title:a.config().LANG[44]},positive:{title:a.config().LANG[43],onClick:function(b){b.preventDefault();a.passwordData.complexity.chars=$("#checkbox-chars").is(":checked");a.passwordData.complexity.numbers=$("#checkbox-numbers").is(":checked");a.passwordData.complexity.uppercase=$("#checkbox-uppercase").is(":checked");a.passwordData.complexity.symbols=$("#checkbox-symbols").is(":checked");a.passwordData.complexity.numlength=
parseInt($("#passlength").val())}},cancelable:!0,contentStyle:{"max-width":"300px"},onLoaded:function(){$("#checkbox-chars").prop("checked",a.passwordData.complexity.chars);$("#checkbox-numbers").prop("checked",a.passwordData.complexity.numbers);$("#checkbox-uppercase").prop("checked",a.passwordData.complexity.uppercase);$("#checkbox-symbols").prop("checked",a.passwordData.complexity.symbols);$("#passlength").val(a.passwordData.complexity.numlength)}})},l=function(b){b.find(".passwordfield__input").each(function(){var b=
$(this);if("true"!==b.attr("data-pass-upgraded")){var d=b.parent(),c=b.attr("id"),g='<button id="menu-speed-'+c+'" class="mdl-button mdl-js-button mdl-button--icon" type="button" title="'+a.config().LANG[27]+'"><i class="material-icons">more_vert</i></button>',g=g+('<ul class="mdl-menu mdl-js-menu" for="menu-speed-'+c+'">')+('<li class="mdl-menu__item passGen"><i class="material-icons">settings</i>'+a.config().LANG[28]+"</li>"),g=g+('<li class="mdl-menu__item passComplexity"><i class="material-icons">vpn_key</i>'+
a.config().LANG[29]+"</li>"),g=g+('<li class="mdl-menu__item reset"><i class="material-icons">refresh</i>'+a.config().LANG[30]+"</li>");d.after('<div class="password-actions" />');d.next(".password-actions").prepend('<span class="passLevel passLevel-'+c+' fullround" title="'+a.config().LANG[31]+'"></span>').prepend('<i class="showpass material-icons" title="'+a.config().LANG[32]+'">remove_red_eye</i>').prepend(g);b.on("keyup",function(){a.checkPassLevel(b)});d=b.parent().next();d.find(".passGen").on("click",
function(){h(b);b.focus()});d.find(".passComplexity").on("click",function(){k()});d.find(".showpass").on("mouseover",function(){$(this).attr("title",b.val())});d.find(".reset").on("click",function(){b.val("");var a=$("#"+c+"R");0<a.length&&a.val("");componentHandler.upgradeDom()});b.attr("data-pass-upgraded","true")}});b.find(".passwordfield__input-show").each(function(){var b=$(this),d=$('<i class="showpass material-icons" title="'+a.config().LANG[32]+'">remove_red_eye</i>');if(1===b.data("clipboard")){var c=
$('<i class="clip-pass-icon material-icons" title="'+a.config().LANG[34]+'" data-clipboard-target="#'+b.attr("id")+'">content_paste</i>');b.parent().after(c).after(d)}else b.parent().after(d);d.on("mouseover",function(){d.attr("title",b.val())})})},n=function(b){f.info("setupDatePicker");var c={format:"YYYY-MM-DD",lang:a.config().LOCALE.substr(0,2),time:!1,cancelText:a.config().LANG[44],okText:a.config().LANG[43],clearText:a.config().LANG[30],nowText:a.config().LANG[56],minDate:new Date,triggerEvent:"dateIconClick"};
b.find(".password-datefield__input").each(function(){var b=$(this);b.bootstrapMaterialDatePicker(c);b.parent().append("<input type='hidden' name='passworddatechange_unix' value='"+moment.tz(b.val(),a.config().TIMEZONE).format("X")+"' />");b.parent().next("i").on("click",function(){b.trigger("dateIconClick")});b.on("change",function(){var c;c=moment.tz(b.val(),a.config().TIMEZONE).format("X");b.parent().find("input[name='passworddatechange_unix']").val(c)})})};return{passwordDetect:l,password:h,viewsTriggers:{main:function(){var a=
document.querySelector(".mdl-layout");$(".mdl-layout__drawer").find("a").click(function(){a.MaterialLayout.toggleDrawer()})},search:function(){var b=$("#frmSearch"),c=$("#res-content");b.find("button.btn-clear").on("click",function(a){$(".icon-searchfav").find("i").removeClass("mdl-color-text--amber-A200")});b.find(".icon-searchfav").on("click",function(){var c=$(this).find("i"),d=b.find("input[name='searchfav']");0==d.val()?(c.addClass("mdl-color-text--amber-A200"),c.attr("title",a.config().LANG[53]),
d.val(1)):(c.removeClass("mdl-color-text--amber-A200"),c.attr("title",a.config().LANG[52]),d.val(0));b.submit()});var d=b.find("#tags")[0],h=b.find(".search-filters-tags"),e=b.find("i.show-filter");c.on("click","#data-search-header .sort-down,#data-search-header .sort-up",function(){var b=$(this);b.parent().find("a").addClass("filterOn");a.appActions().account.sort(b)}).on("click","#search-rows i.icon-favorite",function(){var b=$(this);a.appActions().account.saveFavorite(b,function(){"on"===b.data("status")?
(b.addClass("mdl-color-text--amber-A100"),b.attr("title",a.config().LANG[50]),b.html("star")):(b.removeClass("mdl-color-text--amber-A100"),b.attr("title",a.config().LANG[49]),b.html("star_border"))})}).on("click","#search-rows span.tag",function(){h.is(":hidden")&&e.trigger("click");d.selectize.addItem($(this).data("tag-id"),!1)});e.on("click",function(){var a=$(this);h.is(":hidden")?(h.slideDown("slow"),a.html(a.data("icon-up"))):(h.slideUp("slow"),a.html(a.data("icon-down")))});0<d.selectedIndex&&
e.trigger("click")},common:function(a){l(a);m(a)}},loading:c,ajax:{complete:function(){e.info("ajax:complete");componentHandler.upgradeDom()}},html:{getList:function(a,c){var b=$('<ul class="ldap-list-item mdl-list"></ul>'),f=$('<li class="mdl-list__item"></li>'),e=$('<span class="mdl-list__item-primary-content"></span>');c=void 0===c?'<i class="material-icons mdl-list__item-icon">person</i>':'<i class="material-icons mdl-list__item-icon">'+c+"</i>";a.forEach(function(a){var d=e.clone();d.append(c);
d.append(a);a=f.clone().append(d);b.append(a)});return b},tabs:{add:function(a,c,d,e){a=$(a);var b="";1===e&&(a.parent().find("#tabs-"+c).addClass("is-active"),b="is-active");a.append('<a href="#tabs-'+c+'" class="mdl-tabs__tab '+b+'">'+d+"</a>")}}}}};
d.val(1)):(c.removeClass("mdl-color-text--amber-A200"),c.attr("title",a.config().LANG[52]),d.val(0));b.submit()});var d=b.find("#tags")[0],e=b.find(".search-filters-tags"),g=b.find("i.show-filter");c.on("click","#data-search-header .sort-down,#data-search-header .sort-up",function(){var b=$(this);b.parent().find("a").addClass("filterOn");a.appActions().account.sort(b)}).on("click","#search-rows i.icon-favorite",function(){var b=$(this);a.appActions().account.saveFavorite(b,function(){"on"===b.data("status")?
(b.addClass("mdl-color-text--amber-A100"),b.attr("title",a.config().LANG[50]),b.html("star")):(b.removeClass("mdl-color-text--amber-A100"),b.attr("title",a.config().LANG[49]),b.html("star_border"))})}).on("click","#search-rows span.tag",function(){e.is(":hidden")&&g.trigger("click");d.selectize.addItem($(this).data("tag-id"),!1)});g.on("click",function(){var a=$(this);e.is(":hidden")?(e.slideDown("slow"),a.html(a.data("icon-up"))):(e.slideUp("slow"),a.html(a.data("icon-down")))});0<d.selectedIndex&&
g.trigger("click")},common:function(a){l(a);n(a)}},loading:c,ajax:{complete:function(){f.info("ajax:complete");componentHandler.upgradeDom()}},html:{getList:function(a,c){var b=$('<ul class="ldap-list-item mdl-list"></ul>'),e=$('<li class="mdl-list__item"></li>'),g=$('<span class="mdl-list__item-primary-content"></span>'),f='<i class="material-icons mdl-list__item-icon">'+(void 0===c?"person":c)+"</i>";a.forEach(function(a){var c=g.clone();c.append(f);c.append(a);a=e.clone().append(c);b.append(a)});
return b},tabs:{add:function(a,c,d,e){a=$(a);var b;1===e&&(a.parent().find("#tabs-"+c).addClass("is-active"),b="is-active");a.append('<a href="#tabs-'+c+'" class="mdl-tabs__tab '+b+'">'+d+"</a>")}}}}};

View File

@@ -1,7 +1,7 @@
<?php /** @var $icons \Theme\Icons */ ?>
<div id="title" class="midroundup titleNormal">
<?php echo __('LDAP'); ?>
<?php echo __('Configuración'); ?>
</div>
<form method="post" name="frmLdap" id="frmLdap" class="form-action"
@@ -249,12 +249,66 @@
</select>
</td>
</tr>
<tr id="ldap-results" style="display: none;">
<td class="descField">
<?php echo __('Resultados'); ?>
</td>
<td class="valField">
<div class="lowres-title"><?php echo __('Resultados'); ?></div>
<div class="list-wrap"></div>
</td>
</tr>
<?php else: ?>
<tr>
<td class="option-disabled">
<?php echo __('Módulo no disponible'); ?>
</td>
</tr>
<?php endif; ?>
</table>
<div class="tab-actions">
<ul>
<li>
<button id="btnBack" type="button"
class="btn-back mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconBack()->getClassButton(); ?>"
title="<?php echo __('Atrás'); ?>">
<i class="material-icons"><?php echo $icons->getIconBack()->getIcon(); ?></i>
</button>
</li>
<li>
<button type="button"
class="btn-action mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconCheck()->getClassButton(); ?>"
data-onclick="ldap/check"
data-action-route="configLdap/check"
data-src="#frmLdap"
title="<?php echo $icons->getIconCheck()->getTitle(); ?>">
<i class="material-icons"><?php echo $icons->getIconCheck()->getIcon(); ?></i>
</button>
</li>
<li>
<button form="frmLdap"
class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconSave()->getClassButton(); ?>"
title="<?php echo $icons->getIconSave()->getTitle(); ?>">
<i class="material-icons"><?php echo $icons->getIconSave()->getIcon(); ?></i>
</button>
</li>
</ul>
</div>
<div id="title" class="midroundup titleNormal">
<?php echo __('Importación'); ?>
</div>
<table id="tblLdap" class="data tblConfig round">
<?php if ($ldapIsAvailable || $isDemoMode): ?>
<tr>
<td class="descField">
<?php echo __('Atributo Login'); ?>
<div id="help-ldap_loginattribute"
<div id="help-ldap_login_attribute"
class="icon material-icons <?php echo $icons->getIconHelp()->getClass(); ?>"><?php echo $icons->getIconHelp()->getIcon(); ?></div>
<div class="mdl-tooltip mdl-tooltip--large" for="help-ldap_loginattribute">
<div class="mdl-tooltip mdl-tooltip--large" for="help-ldap_login_attribute">
<p>
<?php echo __('Define el atributo a utilizar para el login del usuario en la importación.'); ?>
</p>
@@ -263,7 +317,7 @@
<td class="valField">
<div class="lowres-title"><?php echo __('Atributo Login'); ?></div>
<select id="ldap_loginattribute" name="ldap_loginattribute"
<select id="ldap_login_attribute" name="ldap_login_attribute"
class="select-box" required>
<option value="samaccountname" selected>sAMAccountName</option>
<option value="userprincipalname">userPrincipalName</option>
@@ -275,9 +329,9 @@
<tr>
<td class="descField">
<?php echo __('Atributo Nombre'); ?>
<div id="help-ldap_nameattribute"
<div id="help-ldap_username_attribute"
class="icon material-icons <?php echo $icons->getIconHelp()->getClass(); ?>"><?php echo $icons->getIconHelp()->getIcon(); ?></div>
<div class="mdl-tooltip mdl-tooltip--large" for="help-ldap_nameattribute">
<div class="mdl-tooltip mdl-tooltip--large" for="help-ldap_username_attribute">
<p>
<?php echo __('Define el atributo a utilizar para el nombre del usuario en la importación.'); ?>
</p>
@@ -286,7 +340,7 @@
<td class="valField">
<div class="lowres-title"><?php echo __('Atributo Nombre'); ?></div>
<select id="ldap_nameattribute" name="ldap_nameattribute"
<select id="ldap_username_attribute" name="ldap_username_attribute"
class="select-box" required>
<option value="displayname" selected>displayName</option>
<option value="fullname">fullName</option>
@@ -295,6 +349,38 @@
</select>
</td>
</tr>
<tr>
<td class="descField"></td>
<td class="valField">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="ldap_import_groups">
<input type="checkbox" id="ldap_import_groups"
class="mdl-switch__input mdl-color-text--indigo-400"
name="ldap_import_groups"/>
<span class="mdl-switch__label"><?php echo __('Importar Grupos'); ?></span>
</label>
</td>
</tr>
<tr>
<td class="descField">
<?php echo __('Atributo Nombre Grupo'); ?>
<div id="help-ldap_groupname_attribute"
class="icon material-icons <?php echo $icons->getIconHelp()->getClass(); ?>"><?php echo $icons->getIconHelp()->getIcon(); ?></div>
<div class="mdl-tooltip mdl-tooltip--large" for="help-ldap_groupname_attribute">
<p>
<?php echo __('Define el atributo a utilizar para el nombre del grupo en la importación.'); ?>
</p>
</div>
</td>
<td class="valField">
<div class="lowres-title"><?php echo __('Atributo Nombre Grupo'); ?></div>
<select id="ldap_groupname_attribute" name="ldap_groupname_attribute"
class="select-box" required>
<option value="cn">cn</option>
<option value="name">name</option>
</select>
</td>
</tr>
<tr id="ldap-results" style="display: none;">
<td class="descField">
<?php echo __('Resultados'); ?>
@@ -312,42 +398,25 @@
</tr>
<?php endif; ?>
</table>
</form>
<div class="tab-actions">
<ul>
<li>
<button id="btnBack" type="button"
class="btn-back mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconBack()->getClassButton(); ?>"
title="<?php echo __('Atrás'); ?>">
<i class="material-icons"><?php echo $icons->getIconBack()->getIcon(); ?></i>
</button>
</li>
<li>
<button type="button"
class="btn-action mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored"
data-onclick="appMgmt/ldapSync"
data-action-route="configLdap/sync"
title="<?php echo __('Importar usuarios de LDAP'); ?>">
<i class="material-icons">get_app</i>
</button>
</li>
<li>
<button type="button"
class="btn-action mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconCheck()->getClassButton(); ?>"
data-onclick="checks/ldap"
data-action-route="configLdap/check"
data-src="#frmLdap"
title="<?php echo $icons->getIconCheck()->getTitle(); ?>">
<i class="material-icons"><?php echo $icons->getIconCheck()->getIcon(); ?></i>
</button>
</li>
<li>
<button form="frmLdap"
class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconSave()->getClassButton(); ?>"
title="<?php echo $icons->getIconSave()->getTitle(); ?>">
<i class="material-icons"><?php echo $icons->getIconSave()->getIcon(); ?></i>
</button>
</li>
</ul>
</div>
<div class="tab-actions">
<ul>
<li>
<button id="btnBack" type="button"
class="btn-back mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored <?php echo $icons->getIconBack()->getClassButton(); ?>"
title="<?php echo __('Atrás'); ?>">
<i class="material-icons"><?php echo $icons->getIconBack()->getIcon(); ?></i>
</button>
</li>
<li>
<button type="button"
class="btn-action mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored"
data-onclick="ldap/import"
data-action-route="configLdap/import"
data-src="#frmLdap"
title="<?php echo __('Importar usuarios de LDAP'); ?>">
<i class="material-icons">get_app</i>
</button>
</li>
</div>
</form>

View File

@@ -30,7 +30,7 @@ return [
\SP\Core\Session\Session::class => object(\SP\Core\Session\Session::class),
\SP\Config\Config::class => object(\SP\Config\Config::class)
->constructor(object(\SP\Storage\XmlHandler::class)
->constructor(CONFIG_FILE)),
->constructor(CONFIG_FILE), get(\SP\Core\Session\Session::class)),
\SP\Core\Language::class => object(\SP\Core\Language::class),
\SP\Config\ConfigData::class => function (\SP\Config\Config $config) {
return $config->getConfigData();

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,10 +24,11 @@
namespace SP\Config;
use DI\Container;
use ReflectionObject;
use SP\Core\Exceptions\ConfigException;
use SP\Core\Session\Session;
use SP\Core\Traits\InjectableTrait;
use SP\Services\Config\ConfigBackupService;
use SP\Storage\XmlFileStorageInterface;
use SP\Storage\XmlHandler;
@@ -38,8 +39,6 @@ defined('APP_ROOT') || die();
*/
class Config
{
use InjectableTrait;
/**
* @var bool
*/
@@ -56,18 +55,24 @@ class Config
* @var Session
*/
private $session;
/**
* @var Container
*/
private $dic;
/**
* Config constructor.
*
* @param XmlFileStorageInterface $fileStorage
* @throws \SP\Core\Exceptions\ConfigException
* @throws \SP\Core\Dic\ContainerException
* @param Session $session
* @param Container $dic
* @throws ConfigException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function __construct(XmlFileStorageInterface $fileStorage)
public function __construct(XmlFileStorageInterface $fileStorage, Session $session, Container $dic)
{
$this->injectDependencies();
$this->session = $session;
$this->fileStorage = $fileStorage;
if (!self::$configLoaded) {
@@ -77,6 +82,7 @@ class Config
self::$configLoaded = true;
}
$this->dic = $dic;
}
/**
@@ -90,11 +96,11 @@ class Config
ConfigUtil::checkConfigDir();
try {
// Mapear el array de elementos de configuración con las propieades de la clase configData
// Mapear el array de elementos de configuración con las propiedades de la clase configData
$items = $this->fileStorage->load('config')->getItems();
$Reflection = new ReflectionObject($this->configData);
$reflectionObject = new ReflectionObject($this->configData);
foreach ($Reflection->getProperties() as $property) {
foreach ($reflectionObject->getProperties() as $property) {
$property->setAccessible(true);
if (isset($items[$property->getName()])) {
@@ -112,16 +118,6 @@ class Config
return $this->configData;
}
/**
* Obtener la configuración o devolver una nueva
*
* @return void
* @deprecated
*/
public static function getConfig()
{
}
/**
* Cargar la configuración desde el archivo
*
@@ -156,29 +152,21 @@ class Config
*
* @param ConfigData $configData
* @param bool $backup
* @throws \DI\DependencyException
* @throws \DI\NotFoundException
*/
public function saveConfig(ConfigData $configData = null, $backup = true)
public function saveConfig(ConfigData $configData, $backup = true)
{
$configData = null === $configData ? $this->configData : $configData;
if ($backup) {
$this->dic->get(ConfigBackupService::class)->backup();
}
$configData->setConfigDate(time());
$configData->setConfigSaver($this->session->getUserData()->getLogin());
$configData->setConfigHash();
$this->fileStorage->setItems($configData);
$this->fileStorage->save('config');
// if ($backup) {
// $this->backupToDB();
// }
}
/**
* Realizar un backup de la configuración en la BD
*/
private function backupToDB()
{
ConfigDB::setValue('config_backup', json_encode($this->configData), true, true);
ConfigDB::setValue('config_backupdate', time());
}
/**
@@ -186,26 +174,6 @@ class Config
*/
public function getConfigData()
{
return $this->configData;
}
/**
* @param Session $session
*/
public function inject(Session $session)
{
$this->session = $session;
}
/**
* Restaurar la configuración desde la BD
*
* @return array
*/
private function restoreBackupFromDB()
{
$configBackup = ConfigDB::getValue('config_backup');
return json_decode($configBackup);
return clone $this->configData;
}
}

View File

@@ -81,7 +81,7 @@ class ConfigUtil
throw new ConfigException(
__u('Los permisos del directorio "/config" son incorrectos'),
ConfigException::ERROR,
sprintf(__u('Actual: %s - Necesario: 750'), $configPerms));
sprintf(__('Actual: %s - Necesario: 750'), $configPerms));
}
}
}

View File

@@ -30,7 +30,6 @@ use phpseclib\Crypt\RSA;
use SP\Core\Exceptions\FileNotFoundException;
use SP\Core\Exceptions\SPException;
use SP\Core\Traits\InjectableTrait;
use SP\Log\Log;
/**
* Class CryptPKI para el manejo de las funciones para PKI
@@ -130,8 +129,6 @@ class CryptPKI
$file = $this->getPublicKeyFile();
if (!file_exists($file)) {
Log::writeNewLog(__FUNCTION__, __('El archivo de clave no existe', false), Log::NOTICE);
throw new FileNotFoundException(SPException::ERROR, __('El archivo de clave no existe'));
}
@@ -150,7 +147,7 @@ class CryptPKI
$this->rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
$this->rsa->loadKey($this->getPrivateKey());
return $this->rsa->decrypt($data);
return @$this->rsa->decrypt($data);
}
/**
@@ -164,8 +161,6 @@ class CryptPKI
$file = $this->getPrivateKeyFile();
if (!file_exists($file)) {
Log::writeNewLog(__FUNCTION__, __('El archivo de clave no existe', false), Log::NOTICE);
throw new FileNotFoundException(SPException::ERROR, __('El archivo de clave no existe'));
}

View File

@@ -36,23 +36,23 @@ class UserData extends UserPassData implements DataModelInterface
/**
* @var string
*/
public $login = '';
public $login;
/**
* @var string
*/
public $ssoLogin = '';
public $ssoLogin;
/**
* @var string
*/
public $name = '';
public $name;
/**
* @var string
*/
public $email = '';
public $email;
/**
* @var string
*/
public $notes = '';
public $notes;
/**
* @var int
*/
@@ -92,11 +92,11 @@ class UserData extends UserPassData implements DataModelInterface
/**
* @var string
*/
public $lastLogin = '';
public $lastLogin;
/**
* @var string
*/
public $lastUpdate = '';
public $lastUpdate;
/**
* @var bool
*/
@@ -108,7 +108,7 @@ class UserData extends UserPassData implements DataModelInterface
/**
* @var string
*/
public $userGroupName = '';
public $userGroupName;
/**
* @return int

View File

@@ -38,19 +38,19 @@ class UserPassData extends DataModelBase
/**
* @var string
*/
public $pass = '';
public $pass;
/**
* @var string
*/
public $hashSalt = '';
public $hashSalt;
/**
* @var string
*/
public $mPass = '';
public $mPass;
/**
* @var string
*/
public $mKey = '';
public $mKey;
/**
* @var int
*/

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -118,10 +118,14 @@ class Request
try {
// Desencriptar con la clave RSA
$CryptPKI = new CryptPKI();
$clearData = $CryptPKI->decryptRSA(base64_decode($encryptedData));
if (($clearData = (new CryptPKI())->decryptRSA(base64_decode($encryptedData))) === false) {
debugLog('No RSA encrypted data from request');
return $encryptedData;
}
} catch (\Exception $e) {
debugLog($e->getMessage());
processException($e);
return $encryptedData;
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -25,7 +25,6 @@
namespace SP\Providers\Auth;
use SP\Config\ConfigData;
use SP\Core\Exceptions\SPException;
use SP\DataModel\UserLoginData;
use SP\Providers\Auth\Browser\Browser;
use SP\Providers\Auth\Browser\BrowserAuthData;
@@ -33,7 +32,12 @@ use SP\Providers\Auth\Database\Database;
use SP\Providers\Auth\Database\DatabaseAuthData;
use SP\Providers\Auth\Ldap\LdapAuthData;
use SP\Providers\Auth\Ldap\LdapMsAds;
use SP\Providers\Auth\Ldap\LdapParams;
use SP\Providers\Auth\Ldap\LdapStd;
use SP\Providers\Provider;
use SP\Services\Auth\AuthException;
use SP\Services\User\UserPassService;
use SP\Services\User\UserService;
defined('APP_ROOT') || die();
@@ -44,7 +48,7 @@ defined('APP_ROOT') || die();
*
* @package SP\Providers\Auth
*/
class Auth
class Auth extends Provider
{
/**
* @var array
@@ -59,55 +63,16 @@ class Auth
*/
protected $configData;
/**
* Auth constructor.
*
* @param UserLoginData $userLoginData
* @param ConfigData $configData
* @throws SPException
*/
public function __construct(UserLoginData $userLoginData, ConfigData $configData)
{
$this->userLoginData = $userLoginData;
$this->configData = $configData;
if ($this->configData->isAuthBasicEnabled()) {
$this->registerAuth('authBrowser');
}
if ($this->configData->isLdapEnabled()) {
$this->registerAuth('authLdap');
}
$this->registerAuth('authDatabase');
}
/**
* Registrar un método de autentificación primarios
*
* @param string $auth Función de autentificación
* @throws SPException
*/
protected function registerAuth($auth)
{
if (array_key_exists($auth, $this->auths)) {
throw new SPException(__u('Método ya inicializado'), SPException::ERROR, __FUNCTION__);
}
if (!method_exists($this, $auth)) {
throw new SPException(__u('Método no disponible'), SPException::ERROR, __FUNCTION__);
}
$this->auths[$auth] = $auth;
}
/**
* Probar los métodos de autentificación
*
* @param UserLoginData $userLoginData
* @return bool|array
*/
public function doAuth()
public function doAuth(UserLoginData $userLoginData)
{
$this->userLoginData = $userLoginData;
$auths = [];
/** @var AuthDataBase $pAuth */
@@ -129,7 +94,18 @@ class Auth
*/
public function authLdap()
{
$ldap = $this->configData->isLdapAds() ? new LdapMsAds() : new LdapStd();
$ldapParams = (new LdapParams())
->setServer($this->configData->getLdapServer())
->setBindDn($this->configData->getLdapBindUser())
->setBindPass($this->configData->getLdapBindPass())
->setSearchBase($this->configData->getLdapBase())
->setAds($this->configData->isLdapAds());
if ($this->configData->isLdapAds()) {
$ldap = new LdapMsAds($ldapParams, $this->eventDispatcher, $this->configData->isDebug());
} else {
$ldap = new LdapStd($ldapParams, $this->eventDispatcher, $this->configData->isDebug());
}
$ldapAuthData = $ldap->getLdapAuthData();
@@ -156,12 +132,13 @@ class Auth
* se ejecuta el proceso para actualizar la clave.
*
* @return DatabaseAuthData
* @throws \ReflectionException
* @throws \SP\Core\Dic\ContainerException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function authDatabase()
{
return (new Database())->authenticate($this->userLoginData);
return (new Database($this->dic->get(UserService::class), $this->dic->get(UserPassService::class)))
->authenticate($this->userLoginData);
}
/**
@@ -171,6 +148,45 @@ class Auth
*/
public function authBrowser()
{
return (new Browser())->authenticate($this->userLoginData);
return (new Browser($this->configData))->authenticate($this->userLoginData);
}
/**
* Auth constructor.
*
* @throws AuthException
*/
protected function initialize()
{
$this->configData = $this->config->getConfigData();
if ($this->configData->isAuthBasicEnabled()) {
$this->registerAuth('authBrowser');
}
if ($this->configData->isLdapEnabled()) {
$this->registerAuth('authLdap');
}
$this->registerAuth('authDatabase');
}
/**
* Registrar un método de autentificación primarios
*
* @param string $auth Función de autentificación
* @throws AuthException
*/
protected function registerAuth($auth)
{
if (array_key_exists($auth, $this->auths)) {
throw new AuthException(__u('Método ya inicializado'), AuthException::ERROR, __FUNCTION__);
}
if (!method_exists($this, $auth)) {
throw new AuthException(__u('Método no disponible'), AuthException::ERROR, __FUNCTION__);
}
$this->auths[$auth] = $auth;
}
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,9 +24,7 @@
namespace SP\Providers\Auth\Browser;
use SP\Config\Config;
use SP\Config\ConfigData;
use SP\Core\Traits\InjectableTrait;
use SP\DataModel\UserLoginData;
use SP\Providers\Auth\AuthInterface;
@@ -39,25 +37,19 @@ use SP\Providers\Auth\AuthInterface;
*/
class Browser implements AuthInterface
{
use InjectableTrait;
/** @var ConfigData */
protected $configData;
/**
* @var ConfigData
*/
private $configData;
/**
* Browser constructor.
*
* @param ConfigData $configData
*/
public function __construct()
public function __construct(ConfigData $configData)
{
$this->injectDependencies();
}
/**
* @param Config $config
*/
public function inject(Config $config)
{
$this->configData = $config->getConfigData();
$this->configData = $configData;
}
/**

View File

@@ -25,9 +25,9 @@
namespace SP\Providers\Auth\Database;
use SP\Core\Crypt\Hash;
use SP\Core\Exceptions\SPException;
use SP\DataModel\UserLoginData;
use SP\Providers\Auth\AuthInterface;
use SP\Services\User\UserLoginResponse;
use SP\Services\User\UserPassService;
use SP\Services\User\UserService;
@@ -44,14 +44,33 @@ class Database implements AuthInterface
* @var UserLoginData $userLoginData
*/
protected $userLoginData;
/**
* @var UserService
*/
private $userService;
/**
* @var UserPassService
*/
private $userPassService;
/**
* Database constructor.
*
* @param UserService $userService
* @param UserPassService $userPassService
*/
public function __construct(UserService $userService, UserPassService $userPassService)
{
$this->userService = $userService;
$this->userPassService = $userPassService;
}
/**
* Autentificar al usuario
*
* @param UserLoginData $userLoginData Datos del usuario
* @return DatabaseAuthData
* @throws \SP\Core\Dic\ContainerException
* @throws \ReflectionException
*/
public function authenticate(UserLoginData $userLoginData)
{
@@ -81,23 +100,22 @@ class Database implements AuthInterface
* se ejecuta el proceso para actualizar la clave.
*
* @return bool
* @throws \SP\Core\Dic\ContainerException
* @throws \ReflectionException
*/
protected function authUser()
{
try {
$userLoginResponse = (new UserService())->getByLogin($this->userLoginData->getLoginUser());
$userLoginResponse = $this->userService->getByLogin($this->userLoginData->getLoginUser());
$this->userLoginData->setUserLoginResponse($userLoginResponse);
if ($userLoginResponse->getIsMigrate() && $this->checkMigrateUser()) {
return (new UserPassService())->migrateUserPassById($userLoginResponse->getId(), $this->userLoginData->getLoginPass());
if ($userLoginResponse->getIsMigrate() && $this->checkMigrateUser($userLoginResponse)) {
return $this->userPassService->migrateUserPassById($userLoginResponse->getId(), $this->userLoginData->getLoginPass());
}
return Hash::checkHashKey($this->userLoginData->getLoginPass(), $userLoginResponse->getPass());
} catch (SPException $e) {
} catch (\Exception $e) {
processException($e);
// $Log = new Log();
// $LogMessage = $Log->getLogMessage();
// $LogMessage->setAction(__FUNCTION__);
@@ -110,12 +128,11 @@ class Database implements AuthInterface
}
/**
* @param UserLoginResponse $userLoginResponse
* @return bool
*/
protected function checkMigrateUser()
protected function checkMigrateUser(UserLoginResponse $userLoginResponse)
{
$userLoginResponse = $this->userLoginData->getUserLoginResponse();
return ($userLoginResponse->getPass() === sha1($userLoginResponse->getHashSalt() . $this->userLoginData->getLoginPass())
|| $userLoginResponse->getPass() === md5($this->userLoginData->getLoginPass())
|| hash_equals($userLoginResponse->getPass(), crypt($this->userLoginData->getLoginPass(), $userLoginResponse->getHashSalt()))

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,13 +24,10 @@
namespace SP\Providers\Auth\Ldap;
use SP\Config\Config;
use SP\Config\ConfigData;
use SP\Core\Exceptions\SPException;
use SP\Core\Messages\LogMessage;
use SP\Core\Traits\InjectableTrait;
use SP\Core\Events\Event;
use SP\Core\Events\EventDispatcher;
use SP\Core\Events\EventMessage;
use SP\DataModel\UserLoginData;
use SP\Log\Log;
use SP\Providers\Auth\AuthInterface;
/**
@@ -62,34 +59,6 @@ abstract class LdapBase implements LdapInterface, AuthInterface
* @var resource
*/
protected $ldapHandler;
/**
* @var string
*/
protected $server;
/**
* @var int
*/
protected $serverPort;
/**
* @var string
*/
protected $searchBase;
/**
* @var string
*/
protected $bindDn;
/**
* @var string
*/
protected $bindPass;
/**
* @var string
*/
protected $group;
/**
* @var array
*/
protected $searchData;
/**
* @var string
*/
@@ -97,237 +66,194 @@ abstract class LdapBase implements LdapInterface, AuthInterface
/**
* @var LdapAuthData
*/
protected $LdapAuthData;
protected $ldapAuthData;
/**
* @var LogMessage
* @var LdapParams
*/
protected $LogMessage;
use InjectableTrait;
/** @var ConfigData */
protected $ConfigData;
protected $ldapParams;
/**
* @var EventDispatcher
*/
protected $eventDispatcher;
/**
* @var string
*/
protected $server;
/**
* @var bool
*/
protected $isConnected = false;
/**
* @var bool
*/
protected $isBound = false;
/**
* @var bool
*/
private $debug;
/**
* LdapBase constructor.
*/
public function __construct()
{
$this->injectDependencies();
$this->LdapAuthData = new LdapAuthData();
$this->LogMessage = new LogMessage();
}
/**
* @param Config $config
*/
public function inject(Config $config)
{
$this->Config = $config;
$this->ConfigData = $config->getConfigData();
}
/**
* Indica si es requerida para acceder a la aplicación
*
* @return boolean
* @param LdapParams $ldapParams
* @param EventDispatcher $eventDispatcher
* @param bool $debug
*/
public function isAuthGranted()
public function __construct(LdapParams $ldapParams, EventDispatcher $eventDispatcher, $debug = false)
{
return true;
$this->ldapParams = $ldapParams;
$this->eventDispatcher = $eventDispatcher;
$this->debug = (bool)$debug;
$this->ldapAuthData = new LdapAuthData();
}
/**
* Comprobar la conexión al servidor de LDAP.
*
* @return false|array Con el número de entradas encontradas
* @throws \SP\Core\Exceptions\SPException
* @throws LdapException
*/
public function checkConnection()
{
$this->LogMessage->setAction(__FUNCTION__);
if (!$this->searchBase || !$this->server || !$this->bindDn || !$this->bindPass) {
$this->LogMessage->addDescription(__('Los parámetros de LDAP no están configurados', false));
$this->writeLog();
return false;
}
try {
$this->connect();
$this->bind();
$results = $this->searchBase();
} catch (SPException $e) {
$this->connectAndBind();
$this->eventDispatcher->notifyEvent('ldap.check.connection',
new Event($this, EventMessage::factory()
->addDescription(__u('Conexión a LDAP correcta')))
);
} catch (LdapException $e) {
throw $e;
}
$this->LogMessage->addDescription(__('Conexión a LDAP correcta', false));
$this->LogMessage->addDetails(__('Objetos encontrados', false), (int)$results['count']);
$this->writeLog(Log::INFO);
return $results;
}
/**
* Escribir en el registro de eventos
*
* @param string $level
* @throws LdapException
*/
protected function writeLog($level = Log::ERROR)
protected function connectAndBind()
{
$Log = new Log($this->LogMessage);
$Log->setLogLevel($level);
$Log->writeLog();
if (!$this->isConnected && !$this->isBound) {
$this->connect();
$this->bind();
}
}
/**
* Realizar la conexión al servidor de LDAP.
*
* @throws SPException
* @throws LdapException
* @return bool
*/
protected function connect()
{
$this->checkParams();
// Habilitar la traza si el modo debug está habilitado
if ($this->ConfigData->isDebug()) {
if ($this->debug) {
@ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
}
$this->ldapHandler = @ldap_connect($this->server, $this->serverPort);
$this->ldapHandler = @ldap_connect($this->server, $this->ldapParams->getPort());
// Conexión al servidor LDAP
if (!is_resource($this->ldapHandler)) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('No es posible conectar con el servidor de LDAP', false));
$this->LogMessage->addDetails(__('Servidor'), $this->server);
$this->LogMessage->addDetails('LDAP ERROR', $this->ldapError());
$this->writeLog();
$this->eventDispatcher->notifyEvent('ldap.connection',
new Event($this, EventMessage::factory()
->addDescription(__u('No es posible conectar con el servidor de LDAP'))
->addDetail(__('Servidor'), $this->server)
->addDetail('LDAP ERROR', $this->getLdapErrorMessage()))
);
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR, $this->LogMessage->getDetails());
throw new LdapException(__u('No es posible conectar con el servidor de LDAP'));
}
@ldap_set_option($this->ldapHandler, LDAP_OPT_NETWORK_TIMEOUT, 10);
@ldap_set_option($this->ldapHandler, LDAP_OPT_PROTOCOL_VERSION, 3);
$this->isConnected = true;
return true;
}
/**
* Comprobar si los parámetros necesario de LDAP están establecidos.
*
* @throws LdapException
*/
public function checkParams()
{
if (!$this->ldapParams->getSearchBase()
|| !$this->ldapParams->getServer()
|| !$this->ldapParams->getBindDn()
) {
$this->eventDispatcher->notifyEvent('ldap.check.params',
new Event($this, EventMessage::factory()
->addDescription(__u('Los parámetros de LDAP no están configurados')))
);
throw new LdapException(__u('Los parámetros de LDAP no están configurados'));
}
$this->server = $this->pickServer();
$this->ldapAuthData->setServer($this->server);
}
/**
* Obtener el servidor de LDAP a utilizar
*
* @return mixed
*/
protected abstract function pickServer();
/**
* Registrar error de LDAP y devolver el mensaje de error
*
* @return string
*/
protected function ldapError()
protected function getLdapErrorMessage()
{
$error = ldap_error($this->ldapHandler);
$errno = ldap_errno($this->ldapHandler);
$this->ldapAuthData->setStatusCode(ldap_errno($this->ldapHandler));
$this->LdapAuthData->setStatusCode($errno);
return sprintf('%s (%d)', $error, $errno);
return sprintf('%s (%d)', ldap_error($this->ldapHandler), $this->ldapAuthData->getStatusCode());
}
/**
* Realizar la autentificación con el servidor de LDAP.
*
* @param string $bindDn con el DN del usuario
* @param string $bindDn con el DN del usuario
* @param string $bindPass con la clave del usuario
* @throws SPException
* @throws LdapException
* @return bool
*/
protected function bind($bindDn = '', $bindPass = '')
protected function bind($bindDn = null, $bindPass = null)
{
if ($bindDn && $bindPass) {
$this->LdapAuthData->setAuthenticated(1);
$this->ldapAuthData->setAuthenticated($bindDn && $bindPass);
$dn = $bindDn ?: $this->ldapParams->getBindDn();
$pass = $bindPass ?: $this->ldapParams->getBindPass();
if (@ldap_bind($this->ldapHandler, $dn, $pass) === false) {
$this->eventDispatcher->notifyEvent('ldap.bind',
new Event($this, EventMessage::factory()
->addDescription(__u('Error al conectar (BIND)'))
->addDetail('LDAP ERROR', $this->getLdapErrorMessage())
->addDetail('LDAP DN', $dn))
);
throw new LdapException(__u('Error al conectar (BIND)'));
}
$dn = $bindDn ?: $this->bindDn;
$pass = $bindPass ?: $this->bindPass;
if (!@ldap_bind($this->ldapHandler, $dn, $pass)) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('Error al conectar (BIND)', false));
$this->LogMessage->addDetails('LDAP ERROR', $this->ldapError());
$this->LogMessage->addDetails('LDAP DN', $dn);
$this->writeLog();
throw new SPException(__($this->LogMessage->getDescription()), SPException::ERROR);
}
$this->isBound = true;
return true;
}
/**
* Realizar una búsqueda de objetos en la ruta indicada.
*
* @throws SPException
* @return array Con los resultados de la búsqueda
*/
protected function searchBase()
{
$searchResults = $this->getResults($this->getGroupDnFilter(), ['dn']);
if ($searchResults === false) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('Error al buscar objetos en DN base', false));
$this->LogMessage->addDetails('LDAP ERROR', $this->ldapError());
$this->LogMessage->addDetails('LDAP FILTER', $this->getGroupDnFilter());
$this->writeLog();
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR);
}
return $searchResults;
}
/**
* Devolver los resultados de una paginación
*
* @param string $filter Filtro a utilizar
* @param array $attributes Atributos a devolver
* @return bool|array
*/
protected function getResults($filter, array $attributes = null)
{
$cookie = '';
$results = [];
do {
ldap_control_paged_result($this->ldapHandler, 1000, false, $cookie);
if (!$searchRes = @ldap_search($this->ldapHandler, $this->searchBase, $filter, $attributes)) {
return false;
}
if (@ldap_count_entries($this->ldapHandler, $searchRes) === 0
|| !$entries = @ldap_get_entries($this->ldapHandler, $searchRes)
) {
return false;
}
$results = array_merge($results, $entries);
ldap_control_paged_result_response($this->ldapHandler, $searchRes, $cookie);
} while (!empty($cookie));
return $results;
}
/**
* Devolver el filtro para comprobar la pertenecia al grupo
*
* @return mixed
*/
protected abstract function getGroupDnFilter();
/**
* @return LdapAuthData
*/
public function getLdapAuthData()
{
return $this->LdapAuthData;
return $this->ldapAuthData;
}
/**
@@ -340,97 +266,6 @@ abstract class LdapBase implements LdapInterface, AuthInterface
return is_resource($this->ldapHandler) ? $this->ldapHandler : false;
}
/**
* @return string
*/
public function getServer()
{
return $this->server;
}
/**
* @param string $server
*/
public function setServer($server)
{
$this->server = $server;
$this->serverPort = $this->getServerPort();
}
/**
* Devolver el puerto del servidor si está establecido
*
* @return int
*/
protected function getServerPort()
{
return preg_match('/[\d\.]+:(\d+)/', $this->server, $port) ? $port[1] : 389;
}
/**
* @return string
*/
public function getSearchBase()
{
return $this->searchBase;
}
/**
* @param string $searchBase
*/
public function setSearchBase($searchBase)
{
$this->searchBase = $searchBase;
}
/**
* @return string
*/
public function getBindDn()
{
return $this->bindDn;
}
/**
* @param string $bindDn
*/
public function setBindDn($bindDn)
{
$this->bindDn = $bindDn;
}
/**
* @return string
*/
public function getBindPass()
{
return $this->bindPass;
}
/**
* @param string $bindPass
*/
public function setBindPass($bindPass)
{
$this->bindPass = $bindPass;
}
/**
* @return string
*/
public function getGroup()
{
return $this->group;
}
/**
* @param string $group
*/
public function setGroup($group)
{
$this->group = $group;
}
/**
* @return string
*/
@@ -450,25 +285,22 @@ abstract class LdapBase implements LdapInterface, AuthInterface
/**
* Autentificar al usuario
*
* @param UserLoginData $UserData Datos del usuario
* @param UserLoginData $userLoginData Datos del usuario
* @return bool
*/
public function authenticate(UserLoginData $UserData)
public function authenticate(UserLoginData $userLoginData)
{
if (!$this->checkParams()) {
return false;
}
$this->LdapAuthData->setAuthGranted($this->isAuthGranted());
try {
$this->setUserLogin($UserData->getLoginUser());
$this->ldapAuthData->setAuthGranted($this->isAuthGranted());
$this->setUserLogin($userLoginData->getLoginUser());
$this->connect();
$this->bind();
$this->connectAndBind();
$this->getAttributes();
$this->bind($this->LdapAuthData->getDn(), $UserData->getLoginPass());
} catch (SPException $e) {
$this->bind($this->ldapAuthData->getDn(), $userLoginData->getLoginPass());
} catch (LdapException $e) {
processException($e);
return false;
}
@@ -476,44 +308,20 @@ abstract class LdapBase implements LdapInterface, AuthInterface
}
/**
* Comprobar si los parámetros necesario de LDAP están establecidos.
* Indica si es requerida para acceder a la aplicación
*
* @return bool
* @return boolean
*/
public function checkParams()
public function isAuthGranted()
{
$this->searchBase = $this->ConfigData->getLdapBase();
$this->server = $this->pickServer();
$this->serverPort = $this->getServerPort();
$this->bindDn = $this->ConfigData->getLdapBindUser();
$this->bindPass = $this->ConfigData->getLdapBindPass();
$this->group = $this->ConfigData->getLdapGroup();
if (!$this->searchBase || !$this->server || !$this->bindDn || !$this->bindPass) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('Los parámetros de LDAP no están configurados', false));
$this->writeLog();
return false;
}
$this->LdapAuthData->setServer($this->server);
return true;
}
/**
* Obtener el servidor de LDAP a utilizar
*
* @return mixed
*/
protected abstract function pickServer();
/**
* Obtener los atributos del usuario.
*
* @return LdapAuthData con los atributos disponibles y sus valores
* @throws SPException
* @throws LdapException
*/
public function getAttributes()
{
@@ -560,44 +368,45 @@ abstract class LdapBase implements LdapInterface, AuthInterface
}
if (!empty($res['fullname'])) {
$this->LdapAuthData->setName($res['fullname']);
$this->ldapAuthData->setName($res['fullname']);
} else {
$this->LdapAuthData->setName($res['name'] . ' ' . $res['sn']);
$this->ldapAuthData->setName($res['name'] . ' ' . $res['sn']);
}
$this->LdapAuthData->setDn($searchResults[0]['dn']);
$this->LdapAuthData->setEmail($res['mail']);
$this->LdapAuthData->setExpire($res['expire']);
$this->LdapAuthData->setGroups($res['group']);
$this->ldapAuthData->setDn($searchResults[0]['dn']);
$this->ldapAuthData->setEmail($res['mail']);
$this->ldapAuthData->setExpire($res['expire']);
$this->ldapAuthData->setGroups($res['group']);
if (!empty($this->group) && $this->group !== '*') {
$this->LdapAuthData->setGroupDn($this->searchGroupDN());
$this->ldapAuthData->setGroupDn($this->searchGroupDN());
}
$this->LdapAuthData->setInGroup($this->searchUserInGroup());
$this->ldapAuthData->setInGroup($this->searchUserInGroup());
return $this->LdapAuthData;
return $this->ldapAuthData;
}
/**
* Obtener el RDN del usuario que realiza el login.
*
* @return array
* @throws SPException
* @throws LdapException
*/
protected function getUserAttributes()
{
$searchResults = $this->getResults($this->getUserDnFilter(), self::SEARCH_ATTRIBUTES);
if ($searchResults === false || $searchResults['count'] > 1) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('Error al localizar el usuario en LDAP', false));
$this->LogMessage->addDetails(__('Usuario', false), $this->userLogin);
$this->LogMessage->addDetails('LDAP ERROR', $this->ldapError());
$this->LogMessage->addDetails('LDAP FILTER', $this->getUserDnFilter());
$this->writeLog();
$this->eventDispatcher->notifyEvent('ldap.getAttributes',
new Event($this, EventMessage::factory()
->addDescription(__u('Error al localizar el usuario en LDAP'))
->addDetail(__u('Usuario'), $this->userLogin)
->addDetail('LDAP ERROR', $this->getLdapErrorMessage())
->addDetail('LDAP DN', $this->getGroupMembershipFilter()))
);
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR);
throw new LdapException(__u('Error al localizar el usuario en LDAP'));
}
return $searchResults;
@@ -613,25 +422,26 @@ abstract class LdapBase implements LdapInterface, AuthInterface
/**
* Obtener el RDN del grupo.
*
* @throws SPException
* @throws LdapException
* @return string con el RDN del grupo
*/
protected function searchGroupDN()
{
$group = $this->getGroupName() ?: $this->group;
$group = $this->getGroupName() ?: $this->ldapParams->getGroup();
$filter = '(cn=' . ldap_escape($group) . ')';
$searchResults = $this->getResults($filter, ['dn', 'cn']);
if ($searchResults === false || $searchResults['count'] > 1) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('Error al buscar RDN de grupo', false));
$this->LogMessage->addDetails(__('Grupo', false), $filter);
$this->LogMessage->addDetails('LDAP ERROR', $this->ldapError());
$this->LogMessage->addDetails('LDAP FILTER', $filter);
$this->writeLog();
$this->eventDispatcher->notifyEvent('ldap.search.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Error al buscar RDN de grupo'))
->addDetail(__u('Grupo'), $filter)
->addDetail('LDAP ERROR', $this->getLdapErrorMessage())
->addDetail('LDAP FILTER', $filter))
);
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR);
throw new LdapException(__u('Error al buscar RDN de grupo'));
}
return $searchResults[0]['dn'];
@@ -644,10 +454,10 @@ abstract class LdapBase implements LdapInterface, AuthInterface
*/
protected function getGroupName()
{
if (null !== $this->group
&& preg_match('/^cn=([\w\s-]+)(,.*)?/i', $this->group, $groupName)
if ($this->ldapParams->getGroup()
&& preg_match('/^cn=(?P<groupname>[\w\s-]+)(?:,.*)?/i', $this->ldapParams->getGroup(), $matches)
) {
return $groupName[1];
return $matches['groupname'];
}
return false;
@@ -656,7 +466,6 @@ abstract class LdapBase implements LdapInterface, AuthInterface
/**
* Buscar al usuario en un grupo.
*
* @throws SPException
* @return bool
*/
protected abstract function searchUserInGroup();
@@ -664,46 +473,118 @@ abstract class LdapBase implements LdapInterface, AuthInterface
/**
* Devolver los objetos disponibles
*
* @param array $attributes
* @return array|bool
* @throws LdapException
*/
public function findObjects()
public function findUsersByGroupFilter(array $attributes = self::SEARCH_ATTRIBUTES)
{
if (!$this->checkParams()) {
return false;
}
$this->connectAndBind();
try {
$this->connect();
$this->bind();
return $this->getObjects();
} catch (SPException $e) {
return false;
}
return $this->getObjects($this->getGroupMembershipFilter(), $attributes);
}
/**
* Obtener los objetos que se pertenecen al grupo filtrado
* Obtener los objetos según el filtro indicado
*
* @return int
* @throws SPException
* @param string $filter
* @param array $attributes
* @return array
* @throws LdapException
*/
protected function getObjects()
protected function getObjects($filter, array $attributes = self::SEARCH_ATTRIBUTES)
{
$searchResults = $this->getResults($this->getGroupDnFilter(), self::SEARCH_ATTRIBUTES);
if (($searchResults = $this->getResults($filter, $attributes)) === false) {
$this->eventDispatcher->notifyEvent('ldap.search',
new Event($this, EventMessage::factory()
->addDescription(__u('Error al buscar objetos en DN base'))
->addDetail('LDAP ERROR', $this->getLdapErrorMessage())
->addDetail('LDAP FILTER', $this->getGroupMembershipFilter()))
);
if ($searchResults === false) {
$this->LogMessage->setAction(__FUNCTION__);
$this->LogMessage->addDescription(__('Error al buscar objetos en DN base', false));
$this->LogMessage->addDetails('LDAP ERROR', $this->ldapError());
$this->LogMessage->addDetails('LDAP FILTER', $this->getGroupDnFilter());
$this->writeLog();
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR);
throw new LdapException(__u('Error al buscar objetos en DN base'));
}
return $searchResults;
}
/**
* Devolver los objetos disponibles
*
* @param array $attributes
* @return array|bool
* @throws LdapException
*/
public function findGroups($attributes = self::SEARCH_ATTRIBUTES)
{
$this->connectAndBind();
return $this->getObjects($this->getGroupObjectFilter(), $attributes);
}
/**
* Devolver el filtro para objetos del tipo grupo
*
* @return mixed
*/
protected abstract function getGroupObjectFilter();
/**
* @return bool
*/
public function isConnected()
{
return $this->isConnected;
}
/**
* @return bool
*/
public function isBound()
{
return $this->isBound;
}
/**
* Devolver los resultados de una paginación
*
* @param string $filter Filtro a utilizar
* @param array $attributes Atributos a devolver
* @return bool|array
*/
protected function getResults($filter, array $attributes = null)
{
$cookie = '';
$results = [];
do {
ldap_control_paged_result($this->ldapHandler, 1000, false, $cookie);
if (!$searchRes = @ldap_search($this->ldapHandler, $this->ldapParams->getSearchBase(), $filter, $attributes)) {
return false;
}
if (@ldap_count_entries($this->ldapHandler, $searchRes) === 0
|| !$entries = @ldap_get_entries($this->ldapHandler, $searchRes)
) {
return false;
}
$results = array_merge($results, $entries);
ldap_control_paged_result_response($this->ldapHandler, $searchRes, $cookie);
} while (!empty($cookie));
return $results;
}
/**
* Devolver el filtro para comprobar la pertenecia al grupo
*
* @return mixed
*/
protected abstract function getGroupMembershipFilter();
/**
* Realizar la desconexión del servidor de LDAP.
*/

View File

@@ -0,0 +1,37 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Providers\Auth\Ldap;
use SP\Core\Exceptions\SPException;
/**
* Class LdapException
*
* @package SP\Providers\Auth\Ldap
*/
class LdapException extends SPException
{
}

View File

@@ -33,8 +33,6 @@ interface LdapInterface
{
/**
* Comprobar la conexión al servidor de LDAP.
*
* @return bool
*/
public function checkConnection();

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,8 +24,8 @@
namespace SP\Providers\Auth\Ldap;
use SP\Core\Exceptions\SPException;
use SP\Log\Log;
use SP\Core\Events\Event;
use SP\Core\Events\EventMessage;
/**
* Class LdapAds
@@ -36,6 +36,8 @@ use SP\Log\Log;
*/
class LdapMsAds extends LdapBase
{
const userObjectFilter = '(|(objectCategory=person)(objectClass=user))';
const groupObjectFilter = '(objectCategory=group)';
/**
* Devolver el filtro para comprobar la pertenecia al grupo
@@ -43,15 +45,15 @@ class LdapMsAds extends LdapBase
* @return mixed
* @throws \SP\Core\Exceptions\SPException
*/
protected function getGroupDnFilter()
protected function getGroupMembershipFilter()
{
if (empty($this->group)) {
return '(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject))';
if (empty($this->ldapParams->getGroup())) {
return self::userObjectFilter;
}
$groupDN = ldap_escape($this->searchGroupDN());
return '(&(|(memberOf=' . $groupDN . ')(groupMembership=' . $groupDN . ')(memberof:1.2.840.113556.1.4.1941:=' . $groupDN . '))(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject)))';
return '(&(|(memberOf=' . $groupDN . ')(groupMembership=' . $groupDN . ')(memberof:1.2.840.113556.1.4.1941:=' . $groupDN . '))' . self::userObjectFilter . ')';
}
/**
@@ -61,7 +63,7 @@ class LdapMsAds extends LdapBase
*/
protected function pickServer()
{
$server = $this->ConfigData->getLdapServer();
$server = $this->ldapParams->getServer();
if (preg_match('/[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}/', $server)) {
return $server;
@@ -101,62 +103,68 @@ class LdapMsAds extends LdapBase
{
$userLogin = ldap_escape($this->userLogin);
return '(&(|(samaccountname=' . $userLogin . ')(cn=' . $userLogin . ')(uid=' . $userLogin . '))(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject))(objectCategory=person))';
return '(&(|(samaccountname=' . $userLogin . ')(cn=' . $userLogin . ')(uid=' . $userLogin . '))' . self::userObjectFilter . ')';
}
/**
* Buscar al usuario en un grupo.
*
* @throws SPException
* @throws LdapException
* @return bool
*/
protected function searchUserInGroup()
{
$this->LogMessage->setAction(__FUNCTION__);
// Comprobar si está establecido el filtro de grupo o el grupo coincide con
// los grupos del usuario
if (!$this->group
|| $this->group === '*'
|| in_array($this->LdapAuthData->getGroupDn(), $this->LdapAuthData->getGroups())
if (!$this->ldapParams->getGroup()
|| $this->ldapParams->getGroup() === '*'
|| in_array($this->ldapAuthData->getGroupDn(), $this->ldapAuthData->getGroups())
) {
$this->LogMessage->addDescription(__('Usuario verificado en grupo', false));
$this->writeLog(Log::INFO);
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Usuario verificado en grupo')))
);
return true;
}
$groupDN = $this->LdapAuthData->getGroupDn();
$groupDN = $this->ldapAuthData->getGroupDn();
$filter = '(memberof:1.2.840.113556.1.4.1941:=' . ldap_escape($groupDN) . ')';
$searchResults = $this->getResults($filter, ['sAMAccountName']);
if ($searchResults === false) {
$this->LogMessage->addDescription(__('Error al buscar el grupo de usuarios', false));
$this->LogMessage->addDetails(__('Grupo', false), $groupDN);
$this->LogMessage->addDetails('LDAP ERROR', sprintf('%s (%d)', ldap_error($this->ldapHandler), ldap_errno($this->ldapHandler)));
$this->LogMessage->addDetails('LDAP FILTER', $filter);
$this->writeLog();
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Error al buscar el grupo de usuarios'))
->addDetail(__u('Grupo'), $groupDN)
->addDetail('LDAP ERROR', $this->getLdapErrorMessage())
->addDetail('LDAP FILTER', $filter))
);
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR);
throw new LdapException(__u('Error al buscar el grupo de usuarios'));
}
foreach ($searchResults as $entry) {
if (is_array($entry)) {
if ($this->userLogin === strtolower($entry['samaccountname'][0])) {
$this->LogMessage->addDescription(__('Usuario verificado en grupo', false));
$this->LogMessage->addDetails(__('Grupo', false), $groupDN);
$this->writeLog(Log::INFO);
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Usuario verificado en grupo'))
->addDetail(__u('Grupo'), $groupDN))
);
return true;
}
}
}
$this->LogMessage->addDescription(__('Usuario no pertenece al grupo', false));
$this->LogMessage->addDetails(__('Usuario', false), $this->LdapAuthData->getDn());
$this->LogMessage->addDetails(__('Grupo', false), $groupDN);
$this->writeLog();
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Usuario no pertenece al grupo'))
->addDetail(__u('Usuario'), $this->ldapAuthData->getDn())
->addDetail(__u('Grupo'), $groupDN))
);
return false;
}
@@ -173,4 +181,14 @@ class LdapMsAds extends LdapBase
return true;
}
/**
* Devolver el filtro para objetos del tipo grupo
*
* @return mixed
*/
protected function getGroupObjectFilter()
{
return self::groupObjectFilter;
}
}

View File

@@ -0,0 +1,200 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Providers\Auth\Ldap;
/**
* Class LdapParams
*
* @package SP\Providers\Auth\Ldap
*/
class LdapParams
{
/**
* @var string
*/
protected $server;
/**
* @var int
*/
protected $port;
/**
* @var string
*/
protected $searchBase;
/**
* @var string
*/
protected $bindDn;
/**
* @var string
*/
protected $bindPass;
/**
* @var string
*/
protected $group;
/**
* @var bool
*/
protected $ads;
/**
* Devolver el puerto del servidor si está establecido
*
* @param $server
* @return array|false
*/
public static function getServerAndPort($server)
{
return preg_match('/(?P<server>[\w\.]+)(:(?P<port>\d+))?/', $server, $matches) ? $matches : false;
}
/**
* @return int
*/
public function getPort()
{
return $this->port;
}
/**
* @param int $port
* @return LdapParams
*/
public function setPort($port)
{
$this->port = $port;
return $this;
}
/**
* @return string
*/
public function getSearchBase()
{
return $this->searchBase;
}
/**
* @param string $searchBase
* @return LdapParams
*/
public function setSearchBase($searchBase)
{
$this->searchBase = $searchBase;
return $this;
}
/**
* @return string
*/
public function getBindDn()
{
return $this->bindDn;
}
/**
* @param string $bindDn
* @return LdapParams
*/
public function setBindDn($bindDn)
{
$this->bindDn = $bindDn;
return $this;
}
/**
* @return string
*/
public function getBindPass()
{
return $this->bindPass;
}
/**
* @param string $bindPass
* @return LdapParams
*/
public function setBindPass($bindPass)
{
$this->bindPass = $bindPass;
return $this;
}
/**
* @return string
*/
public function getGroup()
{
return $this->group;
}
/**
* @param string $group
* @return LdapParams
*/
public function setGroup($group)
{
$this->group = $group;
return $this;
}
/**
* @return string
*/
public function getServer()
{
return $this->server;
}
/**
* @param string $server
* @return LdapParams
*/
public function setServer($server)
{
$this->server = $server;
return $this;
}
/**
* @return bool
*/
public function isAds()
{
return $this->ads;
}
/**
* @param bool $ads
* @return LdapParams
*/
public function setAds($ads)
{
$this->ads = (bool)$ads;
return $this;
}
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,8 +24,8 @@
namespace SP\Providers\Auth\Ldap;
use SP\Core\Exceptions\SPException;
use SP\Log\Log;
use SP\Core\Events\Event;
use SP\Core\Events\EventMessage;
/**
* Class LdapStd
@@ -36,21 +36,24 @@ use SP\Log\Log;
*/
class LdapStd extends LdapBase
{
const userObjectFilter = '(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject))';
const groupObjectFilter = '(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)(objectClass=group))';
/**
* Devolver el filtro para comprobar la pertenecia al grupo
*
* @return mixed
* @throws \SP\Core\Exceptions\SPException
*/
protected function getGroupDnFilter()
protected function getGroupMembershipFilter()
{
if (empty($this->group)) {
return '(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject))';
if (empty($this->ldapParams->getGroup())) {
return self::userObjectFilter;
}
$groupDN = ldap_escape($this->searchGroupDN());
return '(&(|(memberOf=' . $groupDN . ')(groupMembership=' . $groupDN . '))(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject)))';
return '(&(|(memberOf=' . $groupDN . ')(groupMembership=' . $groupDN . '))' . self::userObjectFilter . ')';
}
/**
@@ -60,7 +63,7 @@ class LdapStd extends LdapBase
*/
protected function pickServer()
{
return $this->ConfigData->getLdapServer();
return $this->ldapParams->getServer();
}
/**
@@ -72,52 +75,57 @@ class LdapStd extends LdapBase
{
$userLogin = ldap_escape($this->userLogin);
return '(&(|(samaccountname=' . $userLogin . ')(cn=' . $userLogin . ')(uid=' . $userLogin . '))(|(objectClass=inetOrgPerson)(objectClass=person)(objectClass=simpleSecurityObject)))';
return '(&(|(samaccountname=' . $userLogin . ')(cn=' . $userLogin . ')(uid=' . $userLogin . '))' . self::userObjectFilter . ')';
}
/**
* Buscar al usuario en un grupo.
*
* @throws SPException
* @throws LdapException
* @return bool
*/
protected function searchUserInGroup()
{
$this->LogMessage->setAction(__FUNCTION__);
// Comprobar si está establecido el filtro de grupo o el grupo coincide con
// los grupos del usuario
if (!$this->group
|| $this->group === '*'
|| in_array($this->LdapAuthData->getGroupDn(), $this->LdapAuthData->getGroups())
if (!$this->ldapParams->getGroup()
|| $this->ldapParams->getGroup() === '*'
|| in_array($this->ldapAuthData->getGroupDn(), $this->ldapAuthData->getGroups())
) {
$this->LogMessage->addDescription(__('Usuario verificado en grupo', false));
$this->writeLog(Log::INFO);
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Usuario verificado en grupo')))
);
return true;
}
$userDN = $this->LdapAuthData->getDn();
$groupName = $this->getGroupName() ?: $this->group;
$userDN = ldap_escape($this->ldapAuthData->getDn());
$groupName = $this->getGroupName() ?: $this->ldapParams->getGroup();
$filter = '(&(cn=' . ldap_escape($groupName) . ')(|(member=' . ldap_escape($userDN) . ')(uniqueMember=' . ldap_escape($userDN) . '))(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)(objectClass=group)))';
$filter = '(&(cn=' . ldap_escape($groupName) . ')(|(member=' . $userDN . ')(uniqueMember=' . $userDN . '))' . self::groupObjectFilter . ')';
$searchResults = $this->getResults($filter, ['member', 'uniqueMember']);
if ($searchResults === false) {
$this->LogMessage->addDescription(__('Error al buscar el grupo de usuarios', false));
$this->LogMessage->addDetails(__('Grupo', false), $groupName);
$this->LogMessage->addDetails(__('Usuario', false), $userDN);
$this->LogMessage->addDetails('LDAP ERROR', sprintf('%s (%d)', ldap_error($this->ldapHandler), ldap_errno($this->ldapHandler)));
$this->LogMessage->addDetails('LDAP FILTER', $filter);
$this->writeLog();
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Error al buscar el grupo de usuarios'))
->addDetail(__u('Usuario'), $this->ldapAuthData->getDn())
->addDetail(__u('Grupo'), $groupName)
->addDetail('LDAP ERROR', $this->getLdapErrorMessage())
->addDetail('LDAP FILTER', $filter))
);
throw new SPException($this->LogMessage->getDescription(), SPException::ERROR);
throw new LdapException(__u('Error al buscar el grupo de usuarios'));
}
$this->LogMessage->addDescription(__('Usuario verificado en grupo', false));
$this->LogMessage->addDescription($groupName);
$this->writeLog(Log::INFO);
$this->eventDispatcher->notifyEvent('ldap.check.group',
new Event($this, EventMessage::factory()
->addDescription(__u('Usuario no pertenece al grupo'))
->addDetail(__u('Usuario'), $this->ldapAuthData->getDn())
->addDetail(__u('Grupo'), $groupName))
);
return true;
}
@@ -134,4 +142,14 @@ class LdapStd extends LdapBase
return true;
}
/**
* Devolver el filtro para objetos del tipo grupo
*
* @return mixed
*/
protected function getGroupObjectFilter()
{
return self::groupObjectFilter;
}
}

View File

@@ -24,7 +24,6 @@
namespace SP\Providers\Auth\Ldap;
/**
* Class LdapUtil
*
@@ -32,27 +31,5 @@ namespace SP\Providers\Auth\Ldap;
*/
class LdapUtil
{
/**
* Obtener los datos de una búsqueda de LDAP de un atributo
*
* @param array $results
* @param string $attribute
* @return array
*/
public static function getResultsData(array &$results, $attribute)
{
$out = [];
foreach ($results as $result) {
if (is_array($result)) {
foreach ($result as $ldapAttribute => $value) {
if (strtolower($ldapAttribute) === $attribute) {
$out[] = $value;
}
}
}
}
return $out;
}
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,8 +24,8 @@
namespace SP\Providers;
use DI\Container;
use Psr\Container\ContainerInterface;
use SP\Bootstrap;
use SP\Config\Config;
use SP\Core\Events\EventDispatcher;
use SP\Core\Session\Session;
@@ -57,18 +57,19 @@ abstract class Provider
protected $dic;
/**
* Service constructor.
* Provider constructor.
*
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
* @param Container $dic
* @param Config $config
* @param Session $session
* @param EventDispatcher $eventDispatcher
*/
final public function __construct()
final public function __construct(Container $dic, Config $config, Session $session, EventDispatcher $eventDispatcher)
{
$this->dic = Bootstrap::getContainer();
$this->config = $this->dic->get(Config::class);
$this->session = $this->dic->get(Session::class);
$this->eventDispatcher = $this->dic->get(EventDispatcher::class);
$this->dic = $dic;
$this->config = $config;
$this->session = $session;
$this->eventDispatcher = $eventDispatcher;
if (method_exists($this, 'initialize')) {
$this->initialize();

View File

@@ -46,17 +46,18 @@ class ConfigRepository extends Repository
*/
public function update(ConfigData $configData)
{
$Data = new QueryData();
$Data->setQuery('UPDATE Config SET value = ? WHERE parameter = ?');
$Data->addParam($configData->getValue());
$Data->addParam($configData->getParam());
$queryData = new QueryData();
$queryData->setQuery('UPDATE Config SET value = ? WHERE parameter = ?');
$queryData->addParam($configData->getValue());
$queryData->addParam($configData->getParam());
return DbWrapper::getQuery($Data, $this->db);
return DbWrapper::getQuery($queryData, $this->db);
}
/**
* @param ConfigData[] $data
* @return bool
* @throws \SP\Core\Exceptions\SPException
*/
public function updateBatch(array $data)
{
@@ -64,12 +65,12 @@ class ConfigRepository extends Repository
try {
foreach ($data as $configData) {
$Data = new QueryData();
$Data->setQuery('UPDATE Config SET value = ? WHERE parameter = ?');
$Data->addParam($configData->getValue());
$Data->addParam($configData->getParam());
$queryData = new QueryData();
$queryData->setQuery('UPDATE Config SET value = ? WHERE parameter = ?');
$queryData->addParam($configData->getValue());
$queryData->addParam($configData->getParam());
DbWrapper::getQuery($Data, $this->db);
DbWrapper::getQuery($queryData, $this->db);
}
} catch (QueryException $e) {
debugLog($e->getMessage());
@@ -88,15 +89,12 @@ class ConfigRepository extends Repository
*/
public function create(ConfigData $configData)
{
$query = /** @lang SQL */
'INSERT INTO Config SET parameter = ?, value = ?';
$queryData = new QueryData();
$queryData->setQuery('INSERT INTO Config SET parameter = ?, value = ?');
$queryData->addParam($configData->getParam());
$queryData->addParam($configData->getValue());
$Data = new QueryData();
$Data->setQuery($query);
$Data->addParam($configData->getParam());
$Data->addParam($configData->getValue());
return DbWrapper::getQuery($Data, $this->db);
return DbWrapper::getQuery($queryData, $this->db);
}
/**
@@ -106,10 +104,10 @@ class ConfigRepository extends Repository
*/
public function getAll()
{
$Data = new QueryData();
$Data->setQuery('SELECT parameter, value FROM Config');
$queryData = new QueryData();
$queryData->setQuery('SELECT parameter, value FROM Config');
return DbWrapper::getResults($Data);
return DbWrapper::getResults($queryData);
}
/**
@@ -118,11 +116,11 @@ class ConfigRepository extends Repository
*/
public function getByParam($param)
{
$Data = new QueryData();
$Data->setQuery('SELECT value FROM Config WHERE parameter = ? LIMIT 1');
$Data->addParam($param);
$queryData = new QueryData();
$queryData->setQuery('SELECT value FROM Config WHERE parameter = ? LIMIT 1');
$queryData->addParam($param);
return DbWrapper::getResults($Data, $this->db);
return DbWrapper::getResults($queryData, $this->db);
}
/**
@@ -133,11 +131,11 @@ class ConfigRepository extends Repository
*/
public function has($param)
{
$Data = new QueryData();
$Data->setQuery('SELECT parameter FROM Config WHERE parameter = ? LIMIT 1');
$Data->addParam($param);
$queryData = new QueryData();
$queryData->setQuery('SELECT parameter FROM Config WHERE parameter = ? LIMIT 1');
$queryData->addParam($param);
DbWrapper::getQuery($Data, $this->db);
DbWrapper::getQuery($queryData, $this->db);
return $this->db->getNumRows() === 1;
}
@@ -150,10 +148,10 @@ class ConfigRepository extends Repository
*/
public function deleteByParam($param)
{
$Data = new QueryData();
$Data->setQuery('DELETE FROM Config WHERE parameter = ? LIMIT 1');
$Data->addParam($param);
$queryData = new QueryData();
$queryData->setQuery('DELETE FROM Config WHERE parameter = ? LIMIT 1');
$queryData->addParam($param);
return DbWrapper::getQuery($Data, $this->db);
return DbWrapper::getQuery($queryData, $this->db);
}
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,8 +24,8 @@
namespace SP\Repositories;
use SP\Bootstrap;
use SP\Config\Config;
use SP\Core\Dic\Container;
use SP\Core\Events\EventDispatcher;
use SP\Core\Session\Session;
use SP\Storage\Database;
@@ -38,29 +38,45 @@ use SP\Storage\DatabaseInterface;
*/
abstract class Repository
{
/** @var Config */
/**
* @var Config
*/
protected $config;
/** @var Session */
/**
* @var Session
*/
protected $session;
/** @var EventDispatcher */
/**
* @var EventDispatcher
*/
protected $eventDispatcher;
/** @var DatabaseInterface */
/**
* @var DatabaseInterface
*/
protected $db;
/**
* @var Container
*/
private $dic;
/**
* Repository constructor.
*
* @param Container $dic
* @param Config $config
* @param Database $database
* @param Session $session
* @param EventDispatcher $eventDispatcher
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
final public function __construct()
final public function __construct(Container $dic, Config $config, Database $database, Session $session, EventDispatcher $eventDispatcher)
{
$dic = Bootstrap::getContainer();
$this->config = $dic->get(Config::class);
$this->db = $dic->get(Database::class);
$this->session = $dic->get(Session::class);
$this->eventDispatcher = $dic->get(EventDispatcher::class);
$this->dic = $dic;
$this->config = $config;
$this->db = $database;
$this->session = $session;
$this->eventDispatcher = $eventDispatcher;
if (method_exists($this, 'initialize')) {
$this->initialize();

View File

@@ -480,8 +480,8 @@ class UserRepository extends Repository implements RepositoryItemInterface
'SELECT login, email
FROM User
WHERE UPPER(login) = UPPER(?)
OR UPPER(ssoLogin) = UPPER(?)
OR UPPER(email) = UPPER(?)';
OR UPPER(?) IN (SELECT ssoLogin FROM User WHERE ssoLogin IS NOT NULL OR ssoLogin <> \'\')
OR UPPER(?) IN (SELECT email FROM User WHERE email IS NOT NULL OR email <> \'\')';
$queryData = new QueryData();
$queryData->setQuery($query);

View File

@@ -147,9 +147,7 @@ class LoginService extends Service
);
}
$auth = new Auth($this->userLoginData, $this->configData);
if (($result = $auth->doAuth()) !== false) {
if (($result = $this->dic->get(Auth::class)->doAuth($this->userLoginData)) !== false) {
// Ejecutar la acción asociada al tipo de autentificación
foreach ($result as $authResult) {
/** @var AuthResult $authResult */

View File

@@ -67,7 +67,7 @@ class FileBackupService extends Service
// Generar hash unico para evitar descargas no permitidas
$backupUniqueHash = sha1(uniqid('sysPassBackup', true));
$this->configData->setBackupHash($backupUniqueHash);
$this->config->saveConfig();
$this->config->saveConfig($this->configData);
$bakFileApp = BACKUP_PATH . DIRECTORY_SEPARATOR . $siteName . '-' . $backupUniqueHash . '.tar';
$bakFileDB = BACKUP_PATH . DIRECTORY_SEPARATOR . $siteName . '_db-' . $backupUniqueHash . '.sql';
@@ -130,11 +130,8 @@ class FileBackupService extends Service
* Utilizar '*' para toda la BBDD o 'table1 table2 table3...'
*
* @param string|array $tables
* @param FileHandler $fileHandler
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws SPException
* @throws \SP\Core\Dic\ContainerException
* @param FileHandler $fileHandler
* @throws \Exception
* @throws \SP\Storage\FileException
*/
private function backupTables($tables = '*', FileHandler $fileHandler)

View File

@@ -0,0 +1,67 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Services\Config;
use SP\Services\Service;
use SP\Services\ServiceException;
/**
* Class ConfigBackupService
*
* @package SP\Services\Config
*/
class ConfigBackupService extends Service
{
/**
* @var ConfigService
*/
protected $configService;
/**
* Backups the config data into the database
*/
public function backup()
{
try {
$this->configService->save('config_backup', json_encode($this->config->getConfigData()));
$this->configService->save('config_backup_date', time());
} catch (\Exception $e) {
processException($e);
}
}
/**
* @throws ServiceException
*/
public function restore()
{
throw new ServiceException('Not implemented');
}
protected function initialize()
{
$this->configService = $this->dic->get(ConfigService::class);
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Services\Ldap;
use SP\Providers\Auth\Ldap\LdapBase;
use SP\Providers\Auth\Ldap\LdapMsAds;
use SP\Providers\Auth\Ldap\LdapParams;
use SP\Providers\Auth\Ldap\LdapStd;
use SP\Services\Service;
/**
* Class LdapCheckService
*
* @package SP\Services\Ldap
*/
class LdapCheckService extends Service
{
/**
* @var LdapBase
*/
protected $ldap;
/**
* @param LdapParams $ldapParams
* @throws \SP\Providers\Auth\Ldap\LdapException
*/
public function checkConnection(LdapParams $ldapParams)
{
if ($ldapParams->isAds()) {
$this->ldap = new LdapMsAds($ldapParams, $this->eventDispatcher, true);
} else {
$this->ldap = new LdapStd($ldapParams, $this->eventDispatcher, true);
}
$this->ldap->checkConnection();
}
/**
* @return array
* @throws \SP\Providers\Auth\Ldap\LdapException
*/
public function getUsersAndGroups()
{
$users = $this->ldapResultsMapper($this->ldap->findUsersByGroupFilter(['dn']));
$groups = $this->ldapResultsMapper($this->ldap->findGroups(['dn']));
return [
'count' => count($users) + count($groups),
'users' => $users,
'groups' => $groups
];
}
/**
* Obtener los datos de una búsqueda de LDAP de un atributo
*
* @param array $data
* @param string $attribute
* @return array
*/
public function ldapResultsMapper($data, $attribute = 'dn')
{
$out = [];
foreach ($data as $result) {
if (is_array($result)) {
foreach ($result as $ldapAttribute => $value) {
if (strtolower($ldapAttribute) === $attribute) {
$out[] = $value;
}
}
}
}
return $out;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Services\Ldap;
/**
* Class LdapImportParams
*
* @package SP\Services\Ldap
*/
class LdapImportParams
{
/**
* @var int
*/
public $defaultUserGroup;
/**
* @var int
*/
public $defaultUserProfile;
/**
* @var string
*/
public $loginAttribute;
/**
* @var string
*/
public $userNameAttribute;
/**
* @var string
*/
public $userGroupNameAttribute;
}

View File

@@ -0,0 +1,232 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Services\Ldap;
use SP\Core\Events\Event;
use SP\Core\Events\EventMessage;
use SP\DataModel\UserData;
use SP\DataModel\UserGroupData;
use SP\Providers\Auth\Ldap\LdapBase;
use SP\Providers\Auth\Ldap\LdapException;
use SP\Providers\Auth\Ldap\LdapMsAds;
use SP\Providers\Auth\Ldap\LdapParams;
use SP\Providers\Auth\Ldap\LdapStd;
use SP\Services\Service;
use SP\Services\User\UserService;
use SP\Services\UserGroup\UserGroupService;
/**
* Class UserLdapService
*
* @package SP\Services\User
*/
class LdapImportService extends Service
{
/**
* @var int
*/
protected $totalObjects = 0;
/**
* @var int
*/
protected $syncedObjects = 0;
/**
* @var int
*/
protected $errorObjects = 0;
/**
* @return int
*/
public function getTotalObjects()
{
return $this->totalObjects;
}
/**
* @return int
*/
public function getSyncedObjects()
{
return $this->syncedObjects;
}
/**
* @return int
*/
public function getErrorObjects()
{
return $this->errorObjects;
}
/**
* Sincronizar usuarios de LDAP
*
* @param LdapParams $ldapParams
* @param LdapImportParams $ldapImportParams
* @throws LdapException
*/
public function importGroups(LdapParams $ldapParams, LdapImportParams $ldapImportParams)
{
$objects = $this->getLdap($ldapParams)->findGroups();
$numObjects = (int)$objects['count'];
$this->eventDispatcher->notifyEvent('import.ldap.groups',
new Event($this, EventMessage::factory()
->addDetail(__u('Objetos encontrados'), $numObjects))
);
$this->totalObjects += $numObjects;
if ($numObjects > 0) {
$userGroupService = $this->dic->get(UserGroupService::class);
foreach ($objects as $result) {
if (is_array($result)) {
$userGroupData = new UserGroupData();
foreach ($result as $attribute => $values) {
$value = $values[0];
switch (strtolower($attribute)) {
case $ldapImportParams->userGroupNameAttribute:
$userGroupData->setName($value);
break;
}
}
if (!empty($userGroupData->getName())) {
try {
$userGroupData->setDescription(__('Importado desde LDAP'));
$userGroupService->create($userGroupData);
$this->eventDispatcher->notifyEvent('import.ldap.progress.groups',
new Event($this, EventMessage::factory()
->addDetail(__u('Grupo'), sprintf('%s', $userGroupData->getName())))
);
$this->syncedObjects++;
} catch (\Exception $e) {
processException($e);
$this->eventDispatcher->notifyEvent('exception', new Event($e));
$this->errorObjects++;
}
}
}
}
}
}
/**
* @param LdapParams $ldapParams
*
* @return LdapBase
*/
protected function getLdap(LdapParams $ldapParams)
{
if ($ldapParams->isAds()) {
return new LdapMsAds($ldapParams, $this->eventDispatcher, true);
} else {
return new LdapStd($ldapParams, $this->eventDispatcher, true);
}
}
/**
* @param LdapParams $ldapParams
* @param LdapImportParams $ldapImportParams
* @throws LdapException
*/
public function importUsers(LdapParams $ldapParams, LdapImportParams $ldapImportParams)
{
$objects = $this->getLdap($ldapParams)->findUsersByGroupFilter();
$numObjects = (int)$objects['count'];
$this->eventDispatcher->notifyEvent('import.ldap.users',
new Event($this, EventMessage::factory()
->addDetail(__u('Objetos encontrados'), $numObjects))
);
$this->totalObjects += $numObjects;
if ($numObjects > 0) {
$userService = $this->dic->get(UserService::class);
foreach ($objects as $result) {
if (is_array($result)) {
$userData = new UserData();
foreach ($result as $attribute => $values) {
$value = $values[0];
switch (strtolower($attribute)) {
case $ldapImportParams->userNameAttribute:
$userData->setName($value);
break;
case $ldapImportParams->loginAttribute:
$userData->setLogin($value);
break;
case 'mail':
$userData->setEmail($value);
break;
}
}
if (!empty($userData->getName())
&& !empty($userData->getLogin())
) {
try {
$userData->setNotes(__('Importado desde LDAP'));
$userData->setUserGroupId($ldapImportParams->defaultUserGroup);
$userData->setUserProfileId($ldapImportParams->defaultUserProfile);
$userData->setIsLdap(true);
$userService->create($userData);
$this->eventDispatcher->notifyEvent('import.ldap.progress.users',
new Event($this, EventMessage::factory()
->addDetail(__u('Usuario'), sprintf('%s (%s)', $userData->getName(), $userData->getLogin())))
);
$this->syncedObjects++;
} catch (\Exception $e) {
processException($e);
$this->eventDispatcher->notifyEvent('exception', new Event($e));
$this->errorObjects++;
}
}
}
}
}
}
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -24,8 +24,8 @@
namespace SP\Services;
use DI\Container;
use Psr\Container\ContainerInterface;
use SP\Bootstrap;
use SP\Config\Config;
use SP\Core\Events\EventDispatcher;
use SP\Core\Session\Session;
@@ -59,16 +59,17 @@ abstract class Service
/**
* Service constructor.
*
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
* @param Container $dic
* @param Config $config
* @param Session $session
* @param EventDispatcher $eventDispatcher
*/
final public function __construct()
final public function __construct(Container $dic, Config $config, Session $session, EventDispatcher $eventDispatcher)
{
$this->dic = Bootstrap::getContainer();
$this->config = $this->dic->get(Config::class);
$this->session = $this->dic->get(Session::class);
$this->eventDispatcher = $this->dic->get(EventDispatcher::class);
$this->dic = $dic;
$this->config = $config;
$this->session = $session;
$this->eventDispatcher = $eventDispatcher;
if (method_exists($this, 'initialize')) {
$this->initialize();

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -100,14 +100,14 @@ class UserGroupService extends Service
}
/**
* @param $itemData
* @param array $users
* @param UserGroupData $itemData
* @param array $users
* @return int
* @throws SPException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public function create($itemData, array $users)
public function create($itemData, array $users = [])
{
$userGroupId = $this->userGroupRepository->create($itemData);

View File

@@ -729,24 +729,6 @@ sysPass.Actions = function (Common) {
* @type {{ldap: checks.ldap, wiki: checks.wiki}}
*/
const checks = {
ldap: function ($obj) {
log.info("checks:ldap");
const $form = $($obj.data("src"));
$form.find("[name='sk']").val(Common.sk.get());
const opts = Common.appRequests().getRequestOpts();
opts.url = ajaxUrl.entrypoint;
opts.data = $form.serialize();
Common.appRequests().getActionCall(opts, function (json) {
Common.msg.out(json);
var $results = $("#ldap-results");
$results.find(".list-wrap").html(Common.appTheme().html.getList(json.data));
$results.show("slow");
});
},
wiki: function ($obj) {
log.info("checks:wiki");
@@ -1190,42 +1172,6 @@ sysPass.Actions = function (Common) {
log.info("appMgmt:nav");
grid.nav($obj);
},
ldapSync: function ($obj) {
log.info("appMgmt:ldapSync");
var atext = "<div id=\"alert\"><p id=\"alert-text\">" + Common.config().LANG[57] + "</p></div>";
mdlDialog().show({
text: atext,
negative: {
title: Common.config().LANG[44],
onClick: function (e) {
e.preventDefault();
Common.msg.error(Common.config().LANG[44]);
}
},
positive: {
title: Common.config().LANG[43],
onClick: function (e) {
var opts = Common.appRequests().getRequestOpts();
opts.url = ajaxUrl.entrypoint;
opts.data = {
actionId: $obj.data("action-id"),
sk: Common.sk.get(),
isAjax: 1,
ldap_loginattribute: $("#ldap_loginattribute").val(),
ldap_nameattribute: $("#ldap_nameattribute").val(),
ldap_ads: $("#ldap_ads").prop("checked")
};
Common.appRequests().getActionCall(opts, function (json) {
Common.msg.out(json);
});
}
}
});
}
};
@@ -1559,6 +1505,62 @@ sysPass.Actions = function (Common) {
}
};
const ldap = {
check: function ($obj) {
log.info("checks:ldap");
const $form = $($obj.data("src"));
$form.find("[name='sk']").val(Common.sk.get());
const opts = Common.appRequests().getRequestOpts();
opts.url = ajaxUrl.entrypoint + '?r=' + $obj.data("action-route");
opts.data = $form.serialize();
Common.appRequests().getActionCall(opts, function (json) {
Common.msg.out(json);
const $results = $("#ldap-results");
$results.find(".list-wrap")
.empty()
.append(Common.appTheme().html.getList(json.data.users))
.append(Common.appTheme().html.getList(json.data.groups, 'group'));
$results.show("slow");
});
},
import: function ($obj) {
log.info("appMgmt:ldapSync");
const atext = "<div id=\"alert\"><p id=\"alert-text\">" + Common.config().LANG[57] + "</p></div>";
mdlDialog().show({
text: atext,
negative: {
title: Common.config().LANG[44],
onClick: function (e) {
e.preventDefault();
Common.msg.error(Common.config().LANG[44]);
}
},
positive: {
title: Common.config().LANG[43],
onClick: function (e) {
const $form = $($obj.data("src"));
$form.find("[name='sk']").val(Common.sk.get());
const opts = Common.appRequests().getRequestOpts();
opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("action-route");
opts.data = $form.serialize();
Common.appRequests().getActionCall(opts, function (json) {
Common.msg.out(json);
});
}
}
});
}
};
return {
doAction: doAction,
appMgmt: appMgmt,
@@ -1574,6 +1576,7 @@ sysPass.Actions = function (Common) {
plugin: plugin,
notification: notification,
wiki: wiki,
items: items
items: items,
ldap: ldap
};
};

View File

@@ -1,45 +1,45 @@
var $jscomp={scope:{},findInternal:function(c,e,l){c instanceof String&&(c=String(c));for(var f=c.length,g=0;g<f;g++){var n=c[g];if(e.call(l,n,g,c))return{i:g,v:n}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(c,e,l){if(l.get||l.set)throw new TypeError("ES3 does not support getters and setters.");c!=Array.prototype&&c!=Object.prototype&&(c[e]=l.value)};
$jscomp.getGlobal=function(c){return"undefined"!=typeof window&&window===c?c:"undefined"!=typeof global?global:c};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(c,e,l,f){if(e){l=$jscomp.global;c=c.split(".");for(f=0;f<c.length-1;f++){var g=c[f];g in l||(l[g]={});l=l[g]}c=c[c.length-1];f=l[c];e=e(f);e!=f&&null!=e&&$jscomp.defineProperty(l,c,{configurable:!0,writable:!0,value:e})}};
$jscomp.polyfill("Array.prototype.find",function(c){return c?c:function(c,l){return $jscomp.findInternal(this,c,l).v}},"es6-impl","es3");
sysPass.Actions=function(c){var e=c.log,l=0,f={entrypoint:"/index.php"};Object.freeze(f);var g=function(a,b){e.info("getContent");a.isAjax=1;var d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.type="html";d.addHistory=!0;d.data=a;c.appRequests().getActionCall(d,function(a){var d=$("#content");d.empty().html(a);a=c.triggers().views;a.common(d);if(void 0!==b&&"function"===typeof a[b])a[b]();d=$(".mdl-layout__content");0<d.scrollTop()&&d.animate({scrollTop:0},1E3)})},n=function(a,
b){$.magnificPopup.open({items:{src:a||"",type:"inline"},callbacks:{open:function(){var a=$("#box-popup");c.appTriggers().views.common(a);a.find(":input:text:visible:first").focus();void 0!==b&&"function"===typeof b.open&&b.open()},close:function(){void 0!==b&&"function"===typeof b.close&&b.close()}},showCloseBtn:!1})},v=function(a,b){var d=$('<div id="box-popup" class="image">'+b+"</div>"),h=d.find("img");if(0===h.length)return n(b);h.hide();$.magnificPopup.open({items:{src:d,type:"inline"},callbacks:{open:function(){var a=
this;h.on("click",function(){a.close()});setTimeout(function(){var a=c.resizeImage(h);d.css({backgroundColor:"#fff",width:a.width,height:"auto"});h.show("slow")},500)}}})},p={view:function(a){e.info("account:show");g(c.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},viewHistory:function(a){e.info("account:showHistory");g(c.appRequests().getRouteForQuery(a.data("action-route"),a.val()),"account")},edit:function(a){e.info("account:edit");g(c.appRequests().getRouteForQuery(a.data("action-route"),
a.data("item-id")),"account")},"delete":function(a){e.info("account:delete");var b='<div id="alert"><p id="alert-text">'+c.config().LANG[3]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(d){d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:"account/saveDelete/"+a.data("item-id"),sk:c.sk.get()};c.appRequests().getActionCall(d,function(a){c.msg.out(a);
p.search()})}}})},viewPass:function(a){e.info("account:showpass");var b=a.data("parent-id")||0,b=0===b?a.data("item-id"):b,d=a.data("history")||0,h=c.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+b+"/"+d,sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(h,function(a){0!==a.status?c.msg.out(a):(a=$(a.data.html),n(a),l=setTimeout(function(){$.magnificPopup.close()},3E4),a.on("mouseleave",function(){clearTimeout(l);l=setTimeout(function(){$.magnificPopup.close()},
3E4)}).on("mouseenter",function(){0!==l&&clearTimeout(l)}))})},copyPass:function(a){e.info("account:copypass");var b=a.data("parent-id"),b=0===b?a.data("item-id"):b,d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.async=!1;d.data={r:a.data("action-route")+"/"+b+"/"+a.data("history"),sk:c.sk.get(),isAjax:1};return c.appRequests().getActionCall(d)},copy:function(a){e.info("account:copy");g(c.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},saveFavorite:function(a,
b){e.info("account:saveFavorite");var d="on"===a.data("status"),h=d?a.data("action-route-off"):a.data("action-route-on"),q=c.appRequests().getRequestOpts();q.url=f.entrypoint;q.data={r:h+"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(q,function(h){c.msg.out(h);0===h.status&&(a.data("status",d?"off":"on"),"function"===typeof b&&b())})},request:function(a){e.info("account:request");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.data=a.serialize();c.appRequests().getActionCall(b,
function(a){c.msg.out(a)})},menu:function(a){a.hide();a.parent().children(".actions-optional").show(250)},sort:function(a){e.info("account:sort");var c=$("#frmSearch");c.find('input[name="skey"]').val(a.data("key"));c.find('input[name="sorder"]').val(a.data("dir"));c.find('input[name="start"]').val(a.data("start"));p.search()},editPass:function(a){e.info("account:editpass");var b=a.data("parent-id"),b=void 0===b?a.data("item-id"):b;g(c.appRequests().getRouteForQuery(a.data("action-route"),b),"account")},
saveEditRestore:function(a){e.info("account:restore");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("history-id")+"/"+a.data("item-id");b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(c.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId),"account")})},listFiles:function(a){e.info("account:getfiles");var b=c.appRequests().getRequestOpts();b.method="get";
b.type="html";b.url=f.entrypoint;b.data={r:a.data("action-route")+"/"+a.data("item-id"),del:a.data("delete"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(c){a.html(c)})},search:function(a){e.info("account:search");var b=$("#frmSearch");b.find("input[name='sk']").val(c.sk.get());b.find("input[name='skey']").val();b.find("input[name='sorder']").val();void 0!==a&&b.find("input[name='start']").val(0);var d=c.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.method=
"get";d.data=b.serialize();c.appRequests().getActionCall(d,function(a){10===a.status&&c.msg.out(a);c.sk.set(a.data.sk);$("#res-content").empty().html(a.data.html)})},save:function(a){e.info("account:save");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("item-id");b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(c.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId),
"account")})}},r={get:function(a){e.info("items:get");var b=a[0].selectize;b.clearOptions();b.load(function(d){var h=c.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};c.appRequests().getActionCall(h,function(h){d(h.data);b.setValue(a.data("selected-id"),!0);c.appTriggers().updateFormHash()})})},update:function(a){e.info("items:update");var b=$("#"+a.data("item-dst"))[0].selectize;b.clearOptions();b.load(function(d){var b=
c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.data={r:a.data("item-route"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(a){d(a)})})}},t={logout:function(){c.redirect("index.php?r=login/logout")},login:function(a){e.info("main:login");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("route");b.method="get";b.data=a.serialize();c.appRequests().getActionCall(b,function(d){var b=$(".extra-hidden");switch(d.status){case 0:c.redirect(d.data.url);break;
case 2:c.msg.out(d);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();0<b.length&&b.hide();$("#mpass").prop("disabled",!1).val("");$("#smpass").show();break;case 5:c.msg.out(d);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();0<b.length&&b.hide();$("#oldpass").prop("disabled",!1).val("");$("#soldpass").show();break;default:c.msg.out(d),a.find("input[type='text'],input[type='password']").val(""),a.find("input:first").focus()}})},
install:function(a){e.info("main:install");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("route");b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&setTimeout(function(){c.redirect("index.php?r=login/index")},1E3)})},upgrade:function(a){e.info("main:upgrade");var b='<div id="alert"><p id="alert-text">'+c.config().LANG[59]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();
c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(c.config().LANG[62]);if(0<b.length&&1==b.val()){b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.data={source:a.find("input[name='lock']").val(),taskId:a.find("input[name='taskId']").val()};var e=c.appRequests().getActionEvent(b,function(a){a=a.task+" - "+a.message+" - "+a.time+" - "+a.progress+"%";a+="<br>"+c.config().LANG[62];d.empty().html(a)})}b=
c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.useFullLoading=!0;b.data=a.serialize();c.appRequests().getActionCall(b,function(b){c.msg.out(b);0!==b.status?a.find(":input[name=h]").val(""):(void 0!==e&&e.close(),setTimeout(function(){c.redirect("index.php")},5E3))})}}})},getUpdates:function(){e.info("main:getUpdates");var a=c.appRequests().getRequestOpts();a.url=f.entrypoint;a.type="html";a.method="get";a.timeout=1E4;a.useLoading=!1;a.data={isAjax:1};c.appRequests().getActionCall(a,
function(a){$("#updates").html(a);void 0!==componentHandler&&componentHandler.upgradeDom()},function(){$("#updates").html("!")})}},k={state:{tab:{index:0,refresh:!0,route:""},itemId:0,update:function(a){var c=$("#content").find("[id^='tabs-'].is-active");0<c.length&&(k.state.tab.refresh=!!a.data("item-dst"),k.state.tab.index=c.data("tab-index"),k.state.tab.route=c.data("tab-route"),k.state.itemId=a.data("item-id"))}},save:function(a,b){e.info("tabs:save");k.state.update(a);var d=c.appRequests().getRequestOpts();
d.url=f.entrypoint+"?r="+a.data("action-route");d.data=a.serialize();c.appRequests().getActionCall(d,function(d){c.msg.out(d);0===d.status&&("function"===typeof b&&b(),!0===k.state.tab.refresh?g({r:k.state.tab.route,tabIndex:k.state.tab.index}):void 0!==a.data("reload")&&(e.info("reload"),setTimeout(function(){c.redirect("index.php")},2E3)))})}},u={show:function(a){e.info("appMgmt:show");k.state.update(a);var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.data={r:a.data("action-route")+
"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(b){if(0!==b.status)c.msg.out(b);else{var d=a.data("item-dst");n(b.data.html,{open:function(){d&&(k.state.tab.refresh=!1)},close:function(){d&&r.update(a)}})}})},"delete":function(a){e.info("appMgmt:delete");k.state.update(a);m["delete"](a,function(b){var d=a.data("item-id"),e=c.appRequests().getRequestOpts();e.url=f.entrypoint;e.method="get";e.data={r:a.data("action-route")+(d?"/"+d:""),items:b,sk:c.sk.get(),isAjax:1};
c.appRequests().getActionCall(e,function(a){c.msg.out(a);g({r:k.state.tab.route,tabIndex:k.state.tab.index})})})},save:function(a){e.info("appMgmt:save");k.save(a,function(){$.magnificPopup.close()})},search:function(a){e.info("appMgmt:search");m.search(a)},nav:function(a){e.info("appMgmt:nav");m.nav(a)},ldapSync:function(a){e.info("appMgmt:ldapSync");var b='<div id="alert"><p id="alert-text">'+c.config().LANG[57]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();
c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.data={actionId:a.data("action-id"),sk:c.sk.get(),isAjax:1,ldap_loginattribute:$("#ldap_loginattribute").val(),ldap_nameattribute:$("#ldap_nameattribute").val(),ldap_ads:$("#ldap_ads").prop("checked")};c.appRequests().getActionCall(b,function(a){c.msg.out(a)})}}})}},m={search:function(a){e.info("grid:search");var b=$(a.data("target")),d=c.appRequests().getRequestOpts();
d.url=f.entrypoint+"?r="+a.data("action-route");d.method="get";d.data=a.serialize();c.appRequests().getActionCall(d,function(a){0===a.status?b.html(a.data.html):b.html(c.msg.html.error(a.description));c.sk.set(a.csrf)})},nav:function(a,b){e.info("grid:nav");var d=$("#"+a.data("action-form"));d.find("[name='start']").val(a.data("start"));d.find("[name='count']").val(a.data("count"));d.find("[name='sk']").val(c.sk.get());"function"===typeof b?b(d):m.search(d)},"delete":function(a,b){var d='<div id="alert"><p id="alert-text">'+
c.config().LANG[12]+"</p></div>",e=a.data("selection"),f=[];if(e&&($(e).find(".is-selected").each(function(){f.push($(this).data("item-id"))}),0===f.length))return;mdlDialog().show({text:d,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(a){a.preventDefault();"function"===typeof b&&b(f)}}})}};return{doAction:function(a,b){var d={r:a.r+(void 0!==a.itemId?"/"+a.itemId:""),isAjax:1},e=c.appRequests().getRequestOpts();
e.url=f.entrypoint;e.method="get";e.type="html";e.addHistory=!0;e.data=d;c.appRequests().getActionCall(e,function(a){var d=$("#content");d.empty().html(a);a=c.triggers().views;a.common(d);if(void 0!==b&&"function"===typeof a[b])a[b]();d=$(".mdl-layout__content");0<d.scrollTop()&&d.animate({scrollTop:0},1E3)})},appMgmt:u,account:p,file:{view:function(a){e.info("file:view");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),
sk:c.sk.get()};c.appRequests().getActionCall(b,function(b){if(1===b.status)return c.msg.out(b);v(a,b.data.html)})},download:function(a){e.info("file:download");a={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get()};$.fileDownload(f.entrypoint,{httpMethod:"GET",data:a})},"delete":function(a){e.info("file:delete");var b='<div id="alert"><p id="alert-text">'+c.config().LANG[15]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();
c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&p.listFiles($("#list-account-files"))})}}})}},checks:{ldap:function(a){e.info("checks:ldap");a=$(a.data("src"));a.find("[name='sk']").val(c.sk.get());var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;
b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);var b=$("#ldap-results");b.find(".list-wrap").html(c.appTheme().html.getList(a.data));b.show("slow")})},wiki:function(a){e.info("checks:wiki");a=$(a.data("src"));a.find("[name='sk']").val(c.sk.get());var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&$("#dokuWikiResCheck").html(a.data)})}},config:{save:function(a){e.info("config:save");
k.save(a)},masterpass:function(a){var b='<div id="alert"><p id="alert-text">'+c.config().LANG[59]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(b){b.preventDefault();c.msg.error(c.config().LANG[44]);a.find(":input[type=password]").val("")}},positive:{title:c.config().LANG[43],onClick:function(b){b=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(c.config().LANG[62]);0<b.length&&1==b.val()&&(b=c.appRequests().getRequestOpts(),b.url=
f.entrypoint,b.data={source:a.find("input[name='lock']").val(),taskId:a.find("input[name='taskId']").val()},c.appRequests().getActionEvent(b,function(a){a=a.task+" - "+a.message+" - "+a.time+" - "+a.progress+"%";a+="<br>"+c.config().LANG[62];d.empty().html(a)}));b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.useFullLoading=!0;b.data=a.serialize();c.appRequests().getActionCall(b,function(b){c.msg.out(b);a.find(":input[type=password]").val("");void 0!==task&&task.close()})}}})},backup:function(a){e.info("config:backup");
k.state.update(a);var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("action-route");b.useFullLoading=!0;b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&g({r:k.state.tab.route,tabIndex:k.state.tab.index})})},"export":function(a){e.info("config:export");k.save(a)},"import":function(a){e.info("config:import");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("action-route");b.data=a.serialize();c.appRequests().getActionCall(b,
function(a){c.msg.out(a)})},refreshMpass:function(a){e.info("config:import");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("action-route");b.data={sk:a.data("sk"),isAjax:1};c.appRequests().getActionCall(b,function(a){c.msg.out(a)})}},main:t,user:{showSettings:function(a){e.info("user:showSettings");g({r:a.data("action-route")},"userSettings")},saveSettings:function(a){e.info("user:saveSettings");k.save(a)},password:function(a){e.info("user:password");var b=c.appRequests().getRequestOpts();
b.type="html";b.method="get";b.url=f.entrypoint;b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(a){0===a.length?t.logout():n(a)})},passreset:function(a){e.info("user:passreset");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"/?r="+a.data("action-route");b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&setTimeout(function(){c.redirect("index.php")},2E3)})}},link:{save:function(a){e.info("link:save");
var b=a.data("item-id"),d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:a.data("action-route"),accountId:b,notify:0,sk:c.sk.get(),isAjax:1};var h='<div id="alert"><p id="alert-text">'+c.config().LANG[48]+"</p></div>";mdlDialog().show({text:h,negative:{title:c.config().LANG[44],onClick:function(e){e.preventDefault();c.appRequests().getActionCall(d,function(d){c.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+b})})}},positive:{title:c.config().LANG[43],onClick:function(e){e.preventDefault();
d.data.notify=1;c.appRequests().getActionCall(d,function(d){c.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+b})})}}})},refresh:function(a){e.info("link:refresh");k.state.update(a);var b=a.data("item-id"),d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:a.data("action-route")+"/"+b,sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(d,function(d){c.msg.out(d);0===d.status&&((d=a.data("action-next"))?g({r:d+"/"+b}):g({r:k.state.tab.route,tabIndex:k.state.tab.index}))})}},
eventlog:{search:function(a){e.info("eventlog:search");m.search(a)},nav:function(a){e.info("eventlog:nav");m.nav(a)},clear:function(a){var b='<div id="alert"><p id="alert-text">'+c.config().LANG[20]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b.preventDefault();b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("action-route");
b.method="get";b.data={sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(b){c.msg.out(b);0===b.status&&g({r:a.data("nextaction")});c.sk.set(b.csrf)})}}})}},ajaxUrl:f,plugin:{toggle:function(a){e.info("plugin:enable");a={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:c.sk.get(),activeTab:a.data("activetab")};var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.data=a;c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&setTimeout(function(){c.redirect("index.php")},
2E3)})},reset:function(a){e.info("plugin:reset");var b='<div id="alert"><p id="alert-text">'+c.config().LANG[58]+"</p></div>";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b.preventDefault();b={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:c.sk.get(),activeTab:a.data("activetab")};var d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.data=
b;c.appRequests().getActionCall(d,function(a){c.msg.out(a)})}}})}},notification:{check:function(a){e.info("notification:check");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(b){c.msg.out(b);0===b.status&&g({r:a.data("nextaction")});c.sk.set(b.csrf)})},search:function(a){e.info("notification:search");m.search(a)},show:function(a){e.info("notification:show");
u.show(a)},save:function(a){e.info("notification:save");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("route");b.data=a.serialize();c.appRequests().getActionCall(b,function(b){c.msg.out(b);0===b.status&&(g({r:a.data("nextaction")}),$.magnificPopup.close())})},"delete":function(a){e.info("notification:delete");m["delete"](a,function(b){0<b.length?b.join(","):b=a.data("item-id");var d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.data={r:a.data("action-route")+
"/"+b,sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(d,function(b){c.msg.out(b);g({r:a.data("nextaction")})})})},getActive:function(){e.info("notification:getActive");var a=c.appRequests().getRequestOpts();a.url=f.entrypoint;a.method="get";a.data={r:"items/notifications",sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(a,function(a){return a})},nav:function(a){e.info("eventlog:nav");m.nav(a)}},wiki:{show:function(a){e.info("wiki:show");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint;
b.method="get";b.data={pageName:a.data("pagename"),actionId:a.data("action-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(a){0!==a.status?c.msg.out(a):n(a.data.html)})}},items:r}};
var $jscomp={scope:{},findInternal:function(b,e,l){b instanceof String&&(b=String(b));for(var f=b.length,g=0;g<f;g++){var n=b[g];if(e.call(l,n,g,b))return{i:g,v:n}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,e,l){if(l.get||l.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[e]=l.value)};
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,e,l,f){if(e){l=$jscomp.global;b=b.split(".");for(f=0;f<b.length-1;f++){var g=b[f];g in l||(l[g]={});l=l[g]}b=b[b.length-1];f=l[b];e=e(f);e!=f&&null!=e&&$jscomp.defineProperty(l,b,{configurable:!0,writable:!0,value:e})}};
$jscomp.polyfill("Array.prototype.find",function(b){return b?b:function(b,l){return $jscomp.findInternal(this,b,l).v}},"es6-impl","es3");
sysPass.Actions=function(b){var e=b.log,l=0,f={entrypoint:"/index.php"};Object.freeze(f);var g=function(a,c){e.info("getContent");a.isAjax=1;var d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.type="html";d.addHistory=!0;d.data=a;b.appRequests().getActionCall(d,function(a){var d=$("#content");d.empty().html(a);a=b.triggers().views;a.common(d);if(void 0!==c&&"function"===typeof a[c])a[c]();d=$(".mdl-layout__content");0<d.scrollTop()&&d.animate({scrollTop:0},1E3)})},n=function(a,
c){$.magnificPopup.open({items:{src:a||"",type:"inline"},callbacks:{open:function(){var a=$("#box-popup");b.appTriggers().views.common(a);a.find(":input:text:visible:first").focus();void 0!==c&&"function"===typeof c.open&&c.open()},close:function(){void 0!==c&&"function"===typeof c.close&&c.close()}},showCloseBtn:!1})},v=function(a,c){var d=$('<div id="box-popup" class="image">'+c+"</div>"),h=d.find("img");if(0===h.length)return n(c);h.hide();$.magnificPopup.open({items:{src:d,type:"inline"},callbacks:{open:function(){var a=
this;h.on("click",function(){a.close()});setTimeout(function(){var a=b.resizeImage(h);d.css({backgroundColor:"#fff",width:a.width,height:"auto"});h.show("slow")},500)}}})},p={view:function(a){e.info("account:show");g(b.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},viewHistory:function(a){e.info("account:showHistory");g(b.appRequests().getRouteForQuery(a.data("action-route"),a.val()),"account")},edit:function(a){e.info("account:edit");g(b.appRequests().getRouteForQuery(a.data("action-route"),
a.data("item-id")),"account")},"delete":function(a){e.info("account:delete");var c='<div id="alert"><p id="alert-text">'+b.config().LANG[3]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(d){d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:"account/saveDelete/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(d,function(a){b.msg.out(a);
p.search()})}}})},viewPass:function(a){e.info("account:showpass");var c=a.data("parent-id")||0,c=0===c?a.data("item-id"):c,d=a.data("history")||0,h=b.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+c+"/"+d,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(h,function(a){0!==a.status?b.msg.out(a):(a=$(a.data.html),n(a),l=setTimeout(function(){$.magnificPopup.close()},3E4),a.on("mouseleave",function(){clearTimeout(l);l=setTimeout(function(){$.magnificPopup.close()},
3E4)}).on("mouseenter",function(){0!==l&&clearTimeout(l)}))})},copyPass:function(a){e.info("account:copypass");var c=a.data("parent-id"),c=0===c?a.data("item-id"):c,d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.async=!1;d.data={r:a.data("action-route")+"/"+c+"/"+a.data("history"),sk:b.sk.get(),isAjax:1};return b.appRequests().getActionCall(d)},copy:function(a){e.info("account:copy");g(b.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},saveFavorite:function(a,
c){e.info("account:saveFavorite");var d="on"===a.data("status"),h=d?a.data("action-route-off"):a.data("action-route-on"),q=b.appRequests().getRequestOpts();q.url=f.entrypoint;q.data={r:h+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(q,function(h){b.msg.out(h);0===h.status&&(a.data("status",d?"off":"on"),"function"===typeof c&&c())})},request:function(a){e.info("account:request");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a.serialize();b.appRequests().getActionCall(c,
function(a){b.msg.out(a)})},menu:function(a){a.hide();a.parent().children(".actions-optional").show(250)},sort:function(a){e.info("account:sort");var b=$("#frmSearch");b.find('input[name="skey"]').val(a.data("key"));b.find('input[name="sorder"]').val(a.data("dir"));b.find('input[name="start"]').val(a.data("start"));p.search()},editPass:function(a){e.info("account:editpass");var c=a.data("parent-id"),c=void 0===c?a.data("item-id"):c;g(b.appRequests().getRouteForQuery(a.data("action-route"),c),"account")},
saveEditRestore:function(a){e.info("account:restore");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("history-id")+"/"+a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(b.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId),"account")})},listFiles:function(a){e.info("account:getfiles");var c=b.appRequests().getRequestOpts();c.method="get";
c.type="html";c.url=f.entrypoint;c.data={r:a.data("action-route")+"/"+a.data("item-id"),del:a.data("delete"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(b){a.html(b)})},search:function(a){e.info("account:search");var c=$("#frmSearch");c.find("input[name='sk']").val(b.sk.get());c.find("input[name='skey']").val();c.find("input[name='sorder']").val();void 0!==a&&c.find("input[name='start']").val(0);var d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.method=
"get";d.data=c.serialize();b.appRequests().getActionCall(d,function(a){10===a.status&&b.msg.out(a);b.sk.set(a.data.sk);$("#res-content").empty().html(a.data.html)})},save:function(a){e.info("account:save");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(b.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId),
"account")})}},r={get:function(a){e.info("items:get");var c=a[0].selectize;c.clearOptions();c.load(function(d){var h=b.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};b.appRequests().getActionCall(h,function(h){d(h.data);c.setValue(a.data("selected-id"),!0);b.appTriggers().updateFormHash()})})},update:function(a){e.info("items:update");var c=$("#"+a.data("item-dst"))[0].selectize;c.clearOptions();c.load(function(d){var c=
b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("item-route"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(a){d(a)})})}},t={logout:function(){b.redirect("index.php?r=login/logout")},login:function(a){e.info("main:login");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.method="get";c.data=a.serialize();b.appRequests().getActionCall(c,function(d){var c=$(".extra-hidden");switch(d.status){case 0:b.redirect(d.data.url);break;
case 2:b.msg.out(d);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();0<c.length&&c.hide();$("#mpass").prop("disabled",!1).val("");$("#smpass").show();break;case 5:b.msg.out(d);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();0<c.length&&c.hide();$("#oldpass").prop("disabled",!1).val("");$("#soldpass").show();break;default:b.msg.out(d),a.find("input[type='text'],input[type='password']").val(""),a.find("input:first").focus()}})},
install:function(a){e.info("main:install");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&setTimeout(function(){b.redirect("index.php?r=login/index")},1E3)})},upgrade:function(a){e.info("main:upgrade");var c='<div id="alert"><p id="alert-text">'+b.config().LANG[59]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();
b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(b.config().LANG[62]);if(0<c.length&&1==c.val()){c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data={source:a.find("input[name='lock']").val(),taskId:a.find("input[name='taskId']").val()};var e=b.appRequests().getActionEvent(c,function(a){a=a.task+" - "+a.message+" - "+a.time+" - "+a.progress+"%";a+="<br>"+b.config().LANG[62];d.empty().html(a)})}c=
b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.useFullLoading=!0;c.data=a.serialize();b.appRequests().getActionCall(c,function(c){b.msg.out(c);0!==c.status?a.find(":input[name=h]").val(""):(void 0!==e&&e.close(),setTimeout(function(){b.redirect("index.php")},5E3))})}}})},getUpdates:function(){e.info("main:getUpdates");var a=b.appRequests().getRequestOpts();a.url=f.entrypoint;a.type="html";a.method="get";a.timeout=1E4;a.useLoading=!1;a.data={isAjax:1};b.appRequests().getActionCall(a,
function(a){$("#updates").html(a);void 0!==componentHandler&&componentHandler.upgradeDom()},function(){$("#updates").html("!")})}},k={state:{tab:{index:0,refresh:!0,route:""},itemId:0,update:function(a){var b=$("#content").find("[id^='tabs-'].is-active");0<b.length&&(k.state.tab.refresh=!!a.data("item-dst"),k.state.tab.index=b.data("tab-index"),k.state.tab.route=b.data("tab-route"),k.state.itemId=a.data("item-id"))}},save:function(a,c){e.info("tabs:save");k.state.update(a);var d=b.appRequests().getRequestOpts();
d.url=f.entrypoint+"?r="+a.data("action-route");d.data=a.serialize();b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&("function"===typeof c&&c(),!0===k.state.tab.refresh?g({r:k.state.tab.route,tabIndex:k.state.tab.index}):void 0!==a.data("reload")&&(e.info("reload"),setTimeout(function(){b.redirect("index.php")},2E3)))})}},u={show:function(a){e.info("appMgmt:show");k.state.update(a);var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("action-route")+
"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(c){if(0!==c.status)b.msg.out(c);else{var d=a.data("item-dst");n(c.data.html,{open:function(){d&&(k.state.tab.refresh=!1)},close:function(){d&&r.update(a)}})}})},"delete":function(a){e.info("appMgmt:delete");k.state.update(a);m["delete"](a,function(c){var d=a.data("item-id"),e=b.appRequests().getRequestOpts();e.url=f.entrypoint;e.method="get";e.data={r:a.data("action-route")+(d?"/"+d:""),items:c,sk:b.sk.get(),isAjax:1};
b.appRequests().getActionCall(e,function(a){b.msg.out(a);g({r:k.state.tab.route,tabIndex:k.state.tab.index})})})},save:function(a){e.info("appMgmt:save");k.save(a,function(){$.magnificPopup.close()})},search:function(a){e.info("appMgmt:search");m.search(a)},nav:function(a){e.info("appMgmt:nav");m.nav(a)}},m={search:function(a){e.info("grid:search");var c=$(a.data("target")),d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.method="get";d.data=a.serialize();b.appRequests().getActionCall(d,
function(a){0===a.status?c.html(a.data.html):c.html(b.msg.html.error(a.description));b.sk.set(a.csrf)})},nav:function(a,c){e.info("grid:nav");var d=$("#"+a.data("action-form"));d.find("[name='start']").val(a.data("start"));d.find("[name='count']").val(a.data("count"));d.find("[name='sk']").val(b.sk.get());"function"===typeof c?c(d):m.search(d)},"delete":function(a,c){var d='<div id="alert"><p id="alert-text">'+b.config().LANG[12]+"</p></div>",e=a.data("selection"),f=[];if(e&&($(e).find(".is-selected").each(function(){f.push($(this).data("item-id"))}),
0===f.length))return;mdlDialog().show({text:d,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(a){a.preventDefault();"function"===typeof c&&c(f)}}})}};return{doAction:function(a,c){var d={r:a.r+(void 0!==a.itemId?"/"+a.itemId:""),isAjax:1},e=b.appRequests().getRequestOpts();e.url=f.entrypoint;e.method="get";e.type="html";e.addHistory=!0;e.data=d;b.appRequests().getActionCall(e,function(a){var d=
$("#content");d.empty().html(a);a=b.triggers().views;a.common(d);if(void 0!==c&&"function"===typeof a[c])a[c]();d=$(".mdl-layout__content");0<d.scrollTop()&&d.animate({scrollTop:0},1E3)})},appMgmt:u,account:p,file:{view:function(a){e.info("file:view");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(c){if(1===c.status)return b.msg.out(c);v(a,c.data.html)})},download:function(a){e.info("file:download");
a={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get()};$.fileDownload(f.entrypoint,{httpMethod:"GET",data:a})},"delete":function(a){e.info("file:delete");var c='<div id="alert"><p id="alert-text">'+b.config().LANG[15]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";
c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&p.listFiles($("#list-account-files"))})}}})}},checks:{wiki:function(a){e.info("checks:wiki");a=$(a.data("src"));a.find("[name='sk']").val(b.sk.get());var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&$("#dokuWikiResCheck").html(a.data)})}},config:{save:function(a){e.info("config:save");
k.save(a)},masterpass:function(a){var c='<div id="alert"><p id="alert-text">'+b.config().LANG[59]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(c){c.preventDefault();b.msg.error(b.config().LANG[44]);a.find(":input[type=password]").val("")}},positive:{title:b.config().LANG[43],onClick:function(c){c=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(b.config().LANG[62]);0<c.length&&1==c.val()&&(c=b.appRequests().getRequestOpts(),c.url=
f.entrypoint,c.data={source:a.find("input[name='lock']").val(),taskId:a.find("input[name='taskId']").val()},b.appRequests().getActionEvent(c,function(a){a=a.task+" - "+a.message+" - "+a.time+" - "+a.progress+"%";a+="<br>"+b.config().LANG[62];d.empty().html(a)}));c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.useFullLoading=!0;c.data=a.serialize();b.appRequests().getActionCall(c,function(c){b.msg.out(c);a.find(":input[type=password]").val("");void 0!==task&&task.close()})}}})},backup:function(a){e.info("config:backup");
k.state.update(a);var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route");c.useFullLoading=!0;c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&g({r:k.state.tab.route,tabIndex:k.state.tab.index})})},"export":function(a){e.info("config:export");k.save(a)},"import":function(a){e.info("config:import");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route");c.data=a.serialize();b.appRequests().getActionCall(c,
function(a){b.msg.out(a)})},refreshMpass:function(a){e.info("config:import");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route");c.data={sk:a.data("sk"),isAjax:1};b.appRequests().getActionCall(c,function(a){b.msg.out(a)})}},main:t,user:{showSettings:function(a){e.info("user:showSettings");g({r:a.data("action-route")},"userSettings")},saveSettings:function(a){e.info("user:saveSettings");k.save(a)},password:function(a){e.info("user:password");var c=b.appRequests().getRequestOpts();
c.type="html";c.method="get";c.url=f.entrypoint;c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(a){0===a.length?t.logout():n(a)})},passreset:function(a){e.info("user:passreset");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"/?r="+a.data("action-route");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&setTimeout(function(){b.redirect("index.php")},2E3)})}},link:{save:function(a){e.info("link:save");
var c=a.data("item-id"),d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:a.data("action-route"),accountId:c,notify:0,sk:b.sk.get(),isAjax:1};var h='<div id="alert"><p id="alert-text">'+b.config().LANG[48]+"</p></div>";mdlDialog().show({text:h,negative:{title:b.config().LANG[44],onClick:function(e){e.preventDefault();b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+c})})}},positive:{title:b.config().LANG[43],onClick:function(e){e.preventDefault();
d.data.notify=1;b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+c})})}}})},refresh:function(a){e.info("link:refresh");k.state.update(a);var c=a.data("item-id"),d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:a.data("action-route")+"/"+c,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&((d=a.data("action-next"))?g({r:d+"/"+c}):g({r:k.state.tab.route,tabIndex:k.state.tab.index}))})}},
eventlog:{search:function(a){e.info("eventlog:search");m.search(a)},nav:function(a){e.info("eventlog:nav");m.nav(a)},clear:function(a){var c='<div id="alert"><p id="alert-text">'+b.config().LANG[20]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c.preventDefault();c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route");
c.method="get";c.data={sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&g({r:a.data("nextaction")});b.sk.set(c.csrf)})}}})}},ajaxUrl:f,plugin:{toggle:function(a){e.info("plugin:enable");a={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:b.sk.get(),activeTab:a.data("activetab")};var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a;b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&setTimeout(function(){b.redirect("index.php")},
2E3)})},reset:function(a){e.info("plugin:reset");var c='<div id="alert"><p id="alert-text">'+b.config().LANG[58]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c.preventDefault();c={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:b.sk.get(),activeTab:a.data("activetab")};var d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data=
c;b.appRequests().getActionCall(d,function(a){b.msg.out(a)})}}})}},notification:{check:function(a){e.info("notification:check");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&g({r:a.data("nextaction")});b.sk.set(c.csrf)})},search:function(a){e.info("notification:search");m.search(a)},show:function(a){e.info("notification:show");
u.show(a)},save:function(a){e.info("notification:save");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.data=a.serialize();b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&(g({r:a.data("nextaction")}),$.magnificPopup.close())})},"delete":function(a){e.info("notification:delete");m["delete"](a,function(c){0<c.length?c.join(","):c=a.data("item-id");var d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.data={r:a.data("action-route")+
"/"+c,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(d,function(c){b.msg.out(c);g({r:a.data("nextaction")})})})},getActive:function(){e.info("notification:getActive");var a=b.appRequests().getRequestOpts();a.url=f.entrypoint;a.method="get";a.data={r:"items/notifications",sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(a,function(a){return a})},nav:function(a){e.info("eventlog:nav");m.nav(a)}},wiki:{show:function(a){e.info("wiki:show");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;
c.method="get";c.data={pageName:a.data("pagename"),actionId:a.data("action-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(a){0!==a.status?b.msg.out(a):n(a.data.html)})}},items:r,ldap:{check:function(a){e.info("checks:ldap");var c=$(a.data("src"));c.find("[name='sk']").val(b.sk.get());var d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.data=c.serialize();b.appRequests().getActionCall(d,function(a){b.msg.out(a);var c=$("#ldap-results");c.find(".list-wrap").empty().append(b.appTheme().html.getList(a.data.users)).append(b.appTheme().html.getList(a.data.groups,
"group"));c.show("slow")})},"import":function(a){e.info("appMgmt:ldapSync");var c='<div id="alert"><p id="alert-text">'+b.config().LANG[57]+"</p></div>";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=$(a.data("src"));c.find("[name='sk']").val(b.sk.get());var d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.data=c.serialize();
b.appRequests().getActionCall(d,function(a){b.msg.out(a)})}}})}}}};