diff --git a/fastcgi-server/man/llng-fastcgi-server.1p b/fastcgi-server/man/llng-fastcgi-server.1p index bf310522e..1ee4e440e 100644 --- a/fastcgi-server/man/llng-fastcgi-server.1p +++ b/fastcgi-server/man/llng-fastcgi-server.1p @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "llng-fastcgi-server 1" -.TH llng-fastcgi-server 1 "2019-03-05" "perl v5.28.1" "User Contributed Perl Documentation" +.TH llng-fastcgi-server 1 "2019-04-08" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/lemonldap-ng-common/lemonldap-ng.ini b/lemonldap-ng-common/lemonldap-ng.ini index b7a384718..99fbd6b97 100644 --- a/lemonldap-ng-common/lemonldap-ng.ini +++ b/lemonldap-ng-common/lemonldap-ng.ini @@ -183,7 +183,7 @@ staticPrefix = __PORTALSTATICDIR__ templateDir = __PORTALTEMPLATESDIR__ ; languages: available languages for portal interface -languages = en, fr, vi, it, ar +languages = en, fr, vi, it, ar, de, fi ; II - Optional parameters (overwrite configuration) @@ -354,7 +354,7 @@ staticPrefix = __MANAGERSTATICDIR__ templateDir = __MANAGERTEMPLATESDIR__ ; languages: available languages for manager interface -languages = fr, en, vi, ar +languages = fr, en, it, vi, ar ; Manager modules enabled ; Set here the list of modules you want to see in manager interface diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Backends/YAMLFile.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Backends/YAMLFile.pm index 54b5da741..14ce26927 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Backends/YAMLFile.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Backends/YAMLFile.pm @@ -113,6 +113,11 @@ sub load { $Lemonldap::NG::Common::Conf::msg .= "YAML fails to read file: $@ \n"; return undef; } + foreach (keys $ret) { + if($_ =~ $boolKeys) { + $ret->{$_} = $ret->{$_} ? 1 : 0; + } + } return $ret; } diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Constants.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Constants.pm index e9d0d45eb..8491340bd 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Constants.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Constants.pm @@ -24,6 +24,7 @@ use constant MANAGERSECTION => "manager"; use constant SESSIONSEXPLORERSECTION => "sessionsExplorer"; use constant APPLYSECTION => "apply"; our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/; +our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|howLanguages|slByAjax)|o(?:idc(?:ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken)|RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent))|ldNotifFormat)|p(?:ortal(?:ErrorOn(?:ExpiredSession|MailNotFound)|DisplayRe(?:setPassword|gister)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|da)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonation(?:SkipEmptyValue|MergeSSOgroup)s)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|no(?:tif(?:ication(?:Server)?|y(?:Deleted|Other))|AjaxHook)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|(?:(?:rest(?:Session|Config)|wsdl)Serv|activeTim)er|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|dbiDynamicHashEnabled|bruteForceProtection)$/; our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' ); @@ -49,6 +50,7 @@ our %EXPORT_TAGS = ( NO $hashParameters @sessionTypes + $boolKeys ) ] ); diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Init.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Init.pm index d2af0e1e8..867c62dba 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Init.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Init.pm @@ -53,6 +53,14 @@ sub logLevelInit { my $logger = $class->localConfig->{logger} ||= $class->defaultLogger; eval "require $logger"; die $@ if ($@); + unless ( + $class->localConfig->{logLevel} =~ /^(debug|info|notice|warn|error)$/ ) + { + print STDERR 'Bad logLevel value \'' + . $class->localConfig->{logLevel} + . "', switching to 'info'\n"; + $class->localConfig->{logLevel} = 'info'; + } $class->logger( $logger->new( $class->localConfig ) ); $class->logger->debug("Logger $logger loaded"); $logger = $class->localConfig->{userLogger} || $logger; diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build.pm index 92d1d4f6e..229bdff27 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build.pm @@ -28,6 +28,7 @@ my $reIgnoreKeys = qr/^$/; my $module = __PACKAGE__; my @angularScopeVars; +my @bool; my @cnodesKeys; my %cnodesRe; my @ignoreKeys; @@ -288,6 +289,11 @@ $defaultAttr} my $sessionTypes = join( "', '", @sessionTypes ); my $confConstants = "our \$hashParameters = qr/^" . $ra->as_string . "\$/;\n"; + $ra = Regexp::Assemble->new; + foreach (@bool) { + $ra->add($_); + } + $confConstants .= "our \$boolKeys = qr/^" . $ra->as_string . "\$/;\n"; open( F, ">", $self->confConstantsFile ) or die($!); print F <{get} ) { $jleaf->{get} = $prefix . $jleaf->{title}; } + if ( $attr->{type} eq 'bool' ) { + push @bool, $leaf; + } } push @$json, $jleaf; } diff --git a/lemonldap-ng-manager/site/coffee/manager.coffee b/lemonldap-ng-manager/site/coffee/manager.coffee index 1f7ebef2d..97604ec74 100644 --- a/lemonldap-ng-manager/site/coffee/manager.coffee +++ b/lemonldap-ng-manager/site/coffee/manager.coffee @@ -678,6 +678,9 @@ llapp.controller 'TreeCtrl', [ else node.data = data.value # Cast int as int (remember that booleans are int for Perl) + if node.type and node.type.match /^(bool|trool|boolOrExpr)$/ + if typeof node.data == 'string' and node.data.match /^(?:-1|0|1)$/ + node.data = parseInt(node.data, 10) if node.type and node.type.match /^int$/ node.data = parseInt(node.data, 10) # Split SAML types diff --git a/lemonldap-ng-manager/site/htdocs/static/js/manager.js b/lemonldap-ng-manager/site/htdocs/static/js/manager.js index 03751490a..3ab843da7 100644 --- a/lemonldap-ng-manager/site/htdocs/static/js/manager.js +++ b/lemonldap-ng-manager/site/htdocs/static/js/manager.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.12.8 +// Generated by CoffeeScript 1.12.7 /* LemonLDAP::NG Manager client @@ -823,6 +823,11 @@ This file contains: } else { node.data = data.value; } + if (node.type && node.type.match(/^(bool|trool|boolOrExpr)$/)) { + if (typeof node.data === 'string' && node.data.match(/^(?:-1|0|1)$/)) { + node.data = parseInt(node.data, 10); + } + } if (node.type && node.type.match(/^int$/)) { node.data = parseInt(node.data, 10); } else if (node.type && node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) && !(typeof node.data === 'object')) { diff --git a/lemonldap-ng-manager/site/htdocs/static/js/manager.min.js b/lemonldap-ng-manager/site/htdocs/static/js/manager.min.js index 97941c3a1..5d3ee67dc 100644 --- a/lemonldap-ng-manager/site/htdocs/static/js/manager.min.js +++ b/lemonldap-ng-manager/site/htdocs/static/js/manager.min.js @@ -1 +1 @@ -(function(){var llapp;llapp=angular.module("llngManager",["ui.tree","ui.bootstrap","llApp","ngCookies"]);llapp.controller("TreeCtrl",["$scope","$http","$location","$q","$uibModal","$translator","$cookies","$htmlParams",function($scope,$http,$location,$q,$uibModal,$translator,$cookies,$htmlParams){var _checkSaveResponse,_download,_getAll,_stoggle,c,id,pathEvent,readError,setDefault,setHelp;$scope.links=window.links;$scope.menu=$htmlParams.menu;$scope.menulinks=window.menulinks;$scope.staticPrefix=window.staticPrefix;$scope.formPrefix=window.formPrefix;$scope.availableLanguages=window.availableLanguages;$scope.waiting=true;$scope.showM=false;$scope.showT=false;$scope.form="home";$scope.currentCfg={};$scope.confPrefix=window.confPrefix;$scope.message={};$scope.result="";$scope.translateTitle=function(node){return $translator.translateField(node,"title")};$scope.translateP=$translator.translateP;$scope.translate=$translator.translate;$scope.helpUrl="start.html#configuration";$scope.setShowHelp=function(val){var d;if(val==null){val=!$scope.showH}$scope.showH=val;d=new Date(Date.now());d.setFullYear(d.getFullYear()+1);return $cookies.put("showhelp",val?"true":"false",{expires:d})};$scope.showH=$cookies.get("showhelp")==="false"?false:true;if($scope.showH==null){$scope.setShowHelp(true)}readError=function(response){var e,j;e=response.status;j=response.statusLine;$scope.waiting=false;if(e===403){$scope.message={title:"forbidden",message:"",items:[]}}else if(e===401){console.log("Authentication needed");$scope.message={title:"authenticationNeeded",message:"__waitOrF5__",items:[]}}else if(e===400){$scope.message={title:"badRequest",message:j,items:[]}}else if(e>0){$scope.message={title:"badRequest",message:j,items:[]}}else{$scope.message={title:"networkProblem",message:"",items:[]}}return $scope.showModal("message.html")};$scope.showModal=function(tpl,init){var d,modalInstance;modalInstance=$uibModal.open({templateUrl:tpl,controller:"ModalInstanceCtrl",size:"lg",resolve:{elem:function(){return function(s){return $scope[s]}},set:function(){return function(f,s){return $scope[f]=s}},init:function(){return init}}});d=$q.defer();modalInstance.result.then(function(msgok){$scope.message={title:"",message:"",items:[]};return d.resolve(msgok)},function(msgnok){$scope.message={title:"",message:"",items:[]};return d.reject(msgnok)});return d.promise};$scope.menuClick=function(button){if(button.popup){window.open(button.popup)}else{if(!button.action){button.action=button.title}switch(typeof button.action){case"function":button.action($scope.currentNode,$scope);break;case"string":$scope[button.action]();break;default:console.log(typeof button.action)}}return $scope.showM=false};$scope.home=function(){$scope.form="home";return $scope.showM=false};_checkSaveResponse=function(data){var m;$scope.message={title:"",message:"",items:[]};if(data.needConfirm){$scope.confirmNeeded=true}if(data.message){$scope.message.message=data.message}if(data.details){for(m in data.details){if(m!=="__changes__"){if(m==="__needConfirmation__"){$scope.message.items.unshift({message:m,items:data.details[m]})}else{$scope.message.items.push({message:m,items:data.details[m]})}}}}$scope.waiting=false;if(data.result===1){$location.path("/confs/");$scope.message.title="successfullySaved"}else{$scope.message.title="saveReport"}return $scope.showModal("message.html")};$scope.downloadConf=function(){return window.open($scope.confPrefix+$scope.currentCfg.cfgNum+"?full=1")};$scope.save=function(){$scope.showModal("save.html").then(function(){$scope.waiting=true;$scope.data.push({id:"cfgLog",title:"cfgLog",data:$scope.result?$scope.result:""});return $http.post(window.confPrefix+"?cfgNum="+$scope.currentCfg.cfgNum+($scope.forceSave?"&force=1":""),$scope.data).then(function(response){$scope.data.pop();return _checkSaveResponse(response.data)},function(response){readError(response);return $scope.data.pop()})},function(){return console.log("Saving canceled")});return $scope.showM=false};$scope.saveRawConf=function($fileContent){$scope.waiting=true;return $http.post(window.confPrefix+"/raw",$fileContent).then(function(response){return _checkSaveResponse(response.data)},readError)};$scope.restore=function(){$scope.currentNode=null;return $scope.form="restore"};$scope.cancel=function(){$scope.currentNode.data=null;return $scope.getKey($scope.currentNode)};id=1;$scope._findContainer=function(){return $scope._findScopeContainer().$modelValue};$scope._findScopeContainer=function(){var cs;cs=$scope.currentScope;while(!cs.$modelValue.type.match(/Container$/)){cs=cs.$parentNodeScope}return cs};$scope._findScopeByKey=function(k){var cs;cs=$scope.currentScope;while(!(cs.$modelValue.title===k)){cs=cs.$parentNodeScope}return cs};$scope.newGrantRule=function(){var l,n,node;node=$scope._findContainer();l=node.nodes.length;n=l>0?l-1:0;return node.nodes.push({id:node.id+"/n"+id++,title:"New rule",re:"Message",comment:"New rule",data:"1",type:"grant"})};$scope.newRule=function(){var l,n,node;node=$scope._findContainer();l=node.nodes.length;n=l>0?l-1:0;return node.nodes.splice(n,0,{id:node.id+"/n"+id++,title:"New rule",re:"^/new",comment:"New rule",data:"accept",type:"rule"})};$scope.newPost=function(){var node;node=$scope._findContainer();return node.nodes.push({id:node.id+"/n"+id++,title:"/absolute/path/to/form",data:{},type:"post"})};$scope.newPostVar=function(){if($scope.currentNode.data.vars==null){$scope.currentNode.data.vars=[]}return $scope.currentNode.data.vars.push(["var1","$uid"])};$scope.newAuthChoice=function(){var node;node=$scope._findContainer();node.nodes.push({id:node.id+"/n"+id++,title:"1_Key",data:["Null","Null","Null"],type:"authChoice"});return $scope.execFilters($scope._findScopeByKey("authParams"))};$scope.newHashEntry=function(){var node;node=$scope._findContainer();return node.nodes.push({id:node.id+"/n"+id++,title:"new",data:"",type:"keyText"})};$scope.newCat=function(){var cs;cs=$scope.currentScope;if(cs.$modelValue.type==="menuApp"){cs=cs.$parentNodeScope}return cs.$modelValue.nodes.push({id:cs.$modelValue.id+"/n"+id++,title:"New category",type:"menuCat",nodes:[]})};$scope.newApp=function(){var cs;cs=$scope.currentScope;if(cs.$modelValue.type==="menuApp"){cs=cs.$parentNodeScope}return cs.$modelValue.nodes.push({id:cs.$modelValue.id+"/n"+id++,title:"New application",type:"menuApp",data:{description:"New app description",uri:"https://test.example.com/",logo:"network.png",display:"auto"}})};$scope.newCmbMod=function(){var node;node=$scope._findContainer();node.nodes.push({id:node.id+"/n"+id++,title:"new",type:"cmbModule",data:{type:"LDAP",for:"0",over:[]}});return $scope.execFilters($scope._findScopeByKey("authParams"))};$scope.newCmbOver=function(){var d;d=$scope.currentNode.data;if(!d.over){d.over=[]}return d.over.push(["new"+id++,""])};$scope.newChoiceOver=function(){var d;d=$scope.currentNode.data;console.log("data",d);if(!d[5]){d[5]=[]}return d[5].push(["new"+id++,""])};$scope.addHost=function(){var cn;cn=$scope.currentNode;if(!cn.data){cn.data=[]}return cn.data.push({k:"newHost",h:[{k:"key",v:"uid"}]})};$scope.addSamlAttribute=function(){var node;node=$scope._findContainer();return node.nodes.push({id:node.id+"/n"+id++,title:"new",type:"samlAttribute",data:["0","New","",""]})};$scope.addVhost=function(){var name;name=$scope.domain?"."+$scope.domain.data:".example.com";$scope.message={title:"virtualHostName",field:"hostname"};return $scope.showModal("prompt.html",name).then(function(){var n;n=$scope.result;if(n){return $scope.addTemplateNode(n,"virtualHost")}})};$scope.duplicateVhost=function(){var name;name=$scope.domain?"."+$scope.domain.data:".example.com";$scope.message={title:"virtualHostName",field:"hostname"};return $scope.showModal("prompt.html",name).then(function(){var n;n=$scope.result;return $scope.duplicateNode(n,"virtualHost",$scope.currentNode.title)})};$scope.addSamlIDP=function(){return $scope.newTemplateNode("samlIDPMetaDataNode","samlPartnerName","idp-example")};$scope.addSamlSP=function(){return $scope.newTemplateNode("samlSPMetaDataNode","samlPartnerName","sp-example")};$scope.addOidcOp=function(){return $scope.newTemplateNode("oidcOPMetaDataNode","oidcOPName","op-example")};$scope.addOidcRp=function(){return $scope.newTemplateNode("oidcRPMetaDataNode","oidcRPName","rp-example")};$scope.addCasSrv=function(){return $scope.newTemplateNode("casSrvMetaDataNode","casPartnerName","srv-example")};$scope.addCasApp=function(){return $scope.newTemplateNode("casAppMetaDataNode","casPartnerName","app-example")};$scope.newTemplateNode=function(type,title,init){$scope.message={title:title,field:"name"};return $scope.showModal("prompt.html",init).then(function(){var name;name=$scope.result;if(name){return $scope.addTemplateNode(name,type)}})};$scope.addTemplateNode=function(name,type){var cs,t;cs=$scope.currentScope;while(cs.$modelValue.title!==type+"s"){cs=cs.$parentNodeScope}t={id:type+"s/new__"+name,title:name,type:type,nodes:templates(type,"new__"+name)};setDefault(t.nodes);cs.$modelValue.nodes.push(t);cs.expand();return t};setDefault=function(node){var len,n,o;for(o=0,len=node.length;o0){tmp=p.nodes[ind];p.nodes[ind]=p.nodes[ind-1];p.nodes[ind-1]=tmp}return ind};$scope.inSelect=function(value){var len,n,o,ref;ref=$scope.currentNode.select;for(o=0,len=ref.length;o0?node.comment:node.re};$scope.filters={};$scope.execFilters=function(scope){var filter,func,ref;scope=scope?scope:$scope;ref=$scope.filters;for(filter in ref){func=ref[filter];if($scope.filters.hasOwnProperty(filter)){return window.filterFunctions[filter](scope,$q,func)}}return false};$scope.stoggle=function(scope){var node;node=scope.$modelValue;_stoggle(node);return scope.toggle()};_stoggle=function(node){var a,len,len1,len2,n,o,q,r,ref,ref1,ref2;ref=["nodes","nodes_cond"];for(o=0,len=ref.length;o0){$scope.message={title:"badRequest",message:j,items:[]}}else{$scope.message={title:"networkProblem",message:"",items:[]}}return $scope.showModal("message.html")};$scope.showModal=function(tpl,init){var d,modalInstance;modalInstance=$uibModal.open({templateUrl:tpl,controller:"ModalInstanceCtrl",size:"lg",resolve:{elem:function(){return function(s){return $scope[s]}},set:function(){return function(f,s){return $scope[f]=s}},init:function(){return init}}});d=$q.defer();modalInstance.result.then(function(msgok){$scope.message={title:"",message:"",items:[]};return d.resolve(msgok)},function(msgnok){$scope.message={title:"",message:"",items:[]};return d.reject(msgnok)});return d.promise};$scope.menuClick=function(button){if(button.popup){window.open(button.popup)}else{if(!button.action){button.action=button.title}switch(typeof button.action){case"function":button.action($scope.currentNode,$scope);break;case"string":$scope[button.action]();break;default:console.log(typeof button.action)}}return $scope.showM=false};$scope.home=function(){$scope.form="home";return $scope.showM=false};_checkSaveResponse=function(data){var m;$scope.message={title:"",message:"",items:[]};if(data.needConfirm){$scope.confirmNeeded=true}if(data.message){$scope.message.message=data.message}if(data.details){for(m in data.details){if(m!=="__changes__"){if(m==="__needConfirmation__"){$scope.message.items.unshift({message:m,items:data.details[m]})}else{$scope.message.items.push({message:m,items:data.details[m]})}}}}$scope.waiting=false;if(data.result===1){$location.path("/confs/");$scope.message.title="successfullySaved"}else{$scope.message.title="saveReport"}return $scope.showModal("message.html")};$scope.downloadConf=function(){return window.open($scope.confPrefix+$scope.currentCfg.cfgNum+"?full=1")};$scope.save=function(){$scope.showModal("save.html").then(function(){$scope.waiting=true;$scope.data.push({id:"cfgLog",title:"cfgLog",data:$scope.result?$scope.result:""});return $http.post(window.confPrefix+"?cfgNum="+$scope.currentCfg.cfgNum+($scope.forceSave?"&force=1":""),$scope.data).then(function(response){$scope.data.pop();return _checkSaveResponse(response.data)},function(response){readError(response);return $scope.data.pop()})},function(){return console.log("Saving canceled")});return $scope.showM=false};$scope.saveRawConf=function($fileContent){$scope.waiting=true;return $http.post(window.confPrefix+"/raw",$fileContent).then(function(response){return _checkSaveResponse(response.data)},readError)};$scope.restore=function(){$scope.currentNode=null;return $scope.form="restore"};$scope.cancel=function(){$scope.currentNode.data=null;return $scope.getKey($scope.currentNode)};id=1;$scope._findContainer=function(){return $scope._findScopeContainer().$modelValue};$scope._findScopeContainer=function(){var cs;cs=$scope.currentScope;while(!cs.$modelValue.type.match(/Container$/)){cs=cs.$parentNodeScope}return cs};$scope._findScopeByKey=function(k){var cs;cs=$scope.currentScope;while(!(cs.$modelValue.title===k)){cs=cs.$parentNodeScope}return cs};$scope.newGrantRule=function(){var l,n,node;node=$scope._findContainer();l=node.nodes.length;n=l>0?l-1:0;return node.nodes.push({id:node.id+"/n"+id++,title:"New rule",re:"Message",comment:"New rule",data:"1",type:"grant"})};$scope.newRule=function(){var l,n,node;node=$scope._findContainer();l=node.nodes.length;n=l>0?l-1:0;return node.nodes.splice(n,0,{id:node.id+"/n"+id++,title:"New rule",re:"^/new",comment:"New rule",data:"accept",type:"rule"})};$scope.newPost=function(){var node;node=$scope._findContainer();return node.nodes.push({id:node.id+"/n"+id++,title:"/absolute/path/to/form",data:{},type:"post"})};$scope.newPostVar=function(){if($scope.currentNode.data.vars==null){$scope.currentNode.data.vars=[]}return $scope.currentNode.data.vars.push(["var1","$uid"])};$scope.newAuthChoice=function(){var node;node=$scope._findContainer();node.nodes.push({id:node.id+"/n"+id++,title:"1_Key",data:["Null","Null","Null"],type:"authChoice"});return $scope.execFilters($scope._findScopeByKey("authParams"))};$scope.newHashEntry=function(){var node;node=$scope._findContainer();return node.nodes.push({id:node.id+"/n"+id++,title:"new",data:"",type:"keyText"})};$scope.newCat=function(){var cs;cs=$scope.currentScope;if(cs.$modelValue.type==="menuApp"){cs=cs.$parentNodeScope}return cs.$modelValue.nodes.push({id:cs.$modelValue.id+"/n"+id++,title:"New category",type:"menuCat",nodes:[]})};$scope.newApp=function(){var cs;cs=$scope.currentScope;if(cs.$modelValue.type==="menuApp"){cs=cs.$parentNodeScope}return cs.$modelValue.nodes.push({id:cs.$modelValue.id+"/n"+id++,title:"New application",type:"menuApp",data:{description:"New app description",uri:"https://test.example.com/",logo:"network.png",display:"auto"}})};$scope.newCmbMod=function(){var node;node=$scope._findContainer();node.nodes.push({id:node.id+"/n"+id++,title:"new",type:"cmbModule",data:{type:"LDAP",for:"0",over:[]}});return $scope.execFilters($scope._findScopeByKey("authParams"))};$scope.newCmbOver=function(){var d;d=$scope.currentNode.data;if(!d.over){d.over=[]}return d.over.push(["new"+id++,""])};$scope.newChoiceOver=function(){var d;d=$scope.currentNode.data;console.log("data",d);if(!d[5]){d[5]=[]}return d[5].push(["new"+id++,""])};$scope.addHost=function(){var cn;cn=$scope.currentNode;if(!cn.data){cn.data=[]}return cn.data.push({k:"newHost",h:[{k:"key",v:"uid"}]})};$scope.addSamlAttribute=function(){var node;node=$scope._findContainer();return node.nodes.push({id:node.id+"/n"+id++,title:"new",type:"samlAttribute",data:["0","New","",""]})};$scope.addVhost=function(){var name;name=$scope.domain?"."+$scope.domain.data:".example.com";$scope.message={title:"virtualHostName",field:"hostname"};return $scope.showModal("prompt.html",name).then(function(){var n;n=$scope.result;if(n){return $scope.addTemplateNode(n,"virtualHost")}})};$scope.duplicateVhost=function(){var name;name=$scope.domain?"."+$scope.domain.data:".example.com";$scope.message={title:"virtualHostName",field:"hostname"};return $scope.showModal("prompt.html",name).then(function(){var n;n=$scope.result;return $scope.duplicateNode(n,"virtualHost",$scope.currentNode.title)})};$scope.addSamlIDP=function(){return $scope.newTemplateNode("samlIDPMetaDataNode","samlPartnerName","idp-example")};$scope.addSamlSP=function(){return $scope.newTemplateNode("samlSPMetaDataNode","samlPartnerName","sp-example")};$scope.addOidcOp=function(){return $scope.newTemplateNode("oidcOPMetaDataNode","oidcOPName","op-example")};$scope.addOidcRp=function(){return $scope.newTemplateNode("oidcRPMetaDataNode","oidcRPName","rp-example")};$scope.addCasSrv=function(){return $scope.newTemplateNode("casSrvMetaDataNode","casPartnerName","srv-example")};$scope.addCasApp=function(){return $scope.newTemplateNode("casAppMetaDataNode","casPartnerName","app-example")};$scope.newTemplateNode=function(type,title,init){$scope.message={title:title,field:"name"};return $scope.showModal("prompt.html",init).then(function(){var name;name=$scope.result;if(name){return $scope.addTemplateNode(name,type)}})};$scope.addTemplateNode=function(name,type){var cs,t;cs=$scope.currentScope;while(cs.$modelValue.title!==type+"s"){cs=cs.$parentNodeScope}t={id:type+"s/new__"+name,title:name,type:type,nodes:templates(type,"new__"+name)};setDefault(t.nodes);cs.$modelValue.nodes.push(t);cs.expand();return t};setDefault=function(node){var len,n,o;for(o=0,len=node.length;o0){tmp=p.nodes[ind];p.nodes[ind]=p.nodes[ind-1];p.nodes[ind-1]=tmp}return ind};$scope.inSelect=function(value){var len,n,o,ref;ref=$scope.currentNode.select;for(o=0,len=ref.length;o0?node.comment:node.re};$scope.filters={};$scope.execFilters=function(scope){var filter,func,ref;scope=scope?scope:$scope;ref=$scope.filters;for(filter in ref){func=ref[filter];if($scope.filters.hasOwnProperty(filter)){return window.filterFunctions[filter](scope,$q,func)}}return false};$scope.stoggle=function(scope){var node;node=scope.$modelValue;_stoggle(node);return scope.toggle()};_stoggle=function(node){var a,len,len1,len2,n,o,q,r,ref,ref1,ref2;ref=["nodes","nodes_cond"];for(o=0,len=ref.length;o - - - - - + + + + + diff --git a/lemonldap-ng-portal/site/templates/common/mail/ar.json b/lemonldap-ng-portal/site/templates/common/mail/ar.json index f24a6ccb2..eac6cfc46 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/ar.json +++ b/lemonldap-ng-portal/site/templates/common/mail/ar.json @@ -4,7 +4,7 @@ "click2Register":"انقر هنا لتأكيد تسجيل حسابك", "click2Reset":"انقر هنا لإعادة تعيين كلمة المرور", "hello":"مرحبا ", -"mail2fSubject":"[LemonLDAP::NG] Your login code", +"mail2fSubject":"[LemonLDAP::NG] تسجيل الدخول الخاص بك هو ", "mailConfirmSubject":"تأكيد إعادة تعيين كلمة المرور[LemonLDAP::NG]", "mailSubject":"كلمة المرور الجديدة [LemonLDAP::NG]", "newPwdIs":"كلمة المرور الجديدة هي", diff --git a/lemonldap-ng-portal/site/templates/common/mail/fi.json b/lemonldap-ng-portal/site/templates/common/mail/fi.json new file mode 100644 index 000000000..2bfa99ab4 --- /dev/null +++ b/lemonldap-ng-portal/site/templates/common/mail/fi.json @@ -0,0 +1,18 @@ +{ +"accountCreated":"Tunnus on luotu, väliaikainen salasana on lähetetty sähköpostiisi.", +"autoMail":"Tämä sähköpostiviesti lähetetään automaattisesti", +"click2Register":"Klikkaa tästä vahvistaaksesi käyttäjätunnuksesi rekisteröinnin", +"click2Reset":"Klikkaa tästä nollataksesi salasanasi", +"hello":"Hei", +"mail2fSubject":"[LemonLDAP::NG] Your login code", +"mailConfirmSubject":"[LemonLDAP::NG] Salasanan nollauksen vahvistus", +"mailSubject":"[LemonLDAP::NG] Uusi salasanasi", +"newPwdIs":"Uusi salasanasi on", +"pwdChanged":"Salasanasi on vaihdettu.", +"pwdIs":"Sinun salasanasi on", +"registerConfirmSubject":"[LemonLDAP::NG] Tunnuksen rekisteröinnin vahvistus", +"registerDoneSubject":"[LemonLDAP::NG] Uusi käyttäjätunnuksesi", +"requestIssuedFromIP":"The request was issued from IP", +"yourLoginCodeIs":"Your login code is", +"yourLoginIs":"Your login is" +} \ No newline at end of file diff --git a/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-declared-apps.t b/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-declared-apps.t new file mode 100644 index 000000000..bc3ed7d44 --- /dev/null +++ b/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-declared-apps.t @@ -0,0 +1,182 @@ +use lib 'inc'; +use Test::More; # skip_all => 'CAS is in rebuild'; +use strict; +use IO::String; +use LWP::UserAgent; +use LWP::Protocol::PSGI; +use MIME::Base64; + +BEGIN { + require 't/test-lib.pm'; +} + +my $debug = 'error'; +my ( $issuer, $sp, $res ); +my %handlerOR = ( issuer => [], sp => [] ); + +# Redefine LWP methods for tests +LWP::Protocol::PSGI->register( + sub { + my $req = Plack::Request->new(@_); + ok( $req->uri =~ m#http://auth.((?:id|s)p).com([^\?]*)(?:\?(.*))?$#, + 'SOAP request' ); + my $host = $1; + my $url = $2; + my $query = $3; + my $res; + my $client = ( $host eq 'idp' ? $issuer : $sp ); + if ( $req->method eq 'POST' ) { + my $s = $req->content; + ok( + $res = $client->_post( + $url, IO::String->new($s), + length => length($s), + query => $query, + type => 'application/xml', + ), + "Execute POST request to $url" + ); + } + else { + ok( + $res = $client->_get( + $url, + type => 'application/xml', + query => $query, + ), + "Execute request to $url" + ); + } + expectOK($res); + ok( getHeader( $res, 'Content-Type' ) =~ m#xml#, 'Content is XML' ) + or explain( $res->[1], 'Content-Type => application/xml' ); + count(3); + return $res; + } +); + +ok( $issuer = issuer(), 'Issuer portal' ); +$handlerOR{issuer} = \@Lemonldap::NG::Handler::Main::_onReload; +count(1); +switch ('sp'); +&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 ); + +ok( $sp = sp(), 'SP portal' ); +count(1); +$handlerOR{sp} = \@Lemonldap::NG::Handler::Main::_onReload; + +# Simple SP access +ok( + $res = $sp->_get( + '/', accept => 'text/html', + ), + 'Unauth SP request' +); +count(1); + +# No cancel button found +ok( + $res->[2]->[0] !~ +qr%%, + 'Cancel button NOT found' +) or print STDERR Dumper( $res->[2]->[0] ); +count(1); + +# Query IdP +switch ('issuer'); +ok( + $res = $issuer->_get( + '/cas/login', + query => 'service=http://auth.sp.com/', + accept => 'text/html' + ), + 'Query CAS server' +); +count(1); +expectOK($res); +my $pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' ); + +clean_sessions(); +done_testing( count() ); + +sub switch { + my $type = shift; + @Lemonldap::NG::Handler::Main::_onReload = @{ + $handlerOR{$type}; + }; +} + +sub issuer { + return LLNG::Manager::Test->new( { + ini => { + logLevel => $debug, + templatesDir => 'site/htdocs/static', + domain => 'idp.com', + portal => 'http://auth.idp.com', + authentication => 'Demo', + userDB => 'Same', + issuerDBCASActivation => 1, + issuerDBCASRule => '$uid eq "french"', + casAttr => 'uid', + casAccessControlPolicy => 'error', + multiValuesSeparator => ';', + casAppMetaDataExportedVars => { + sp => { + cn => 'cn', + mail => 'mail', + uid => 'uid', + } + }, + casAppMetaDataOptions => { + sp => { + casAppMetaDataOptionsService => 'http://auth.sp.com', + }, + sp2 => { + casAppMetaDataOptionsService => 'http://auth.sp2.com', + }, + }, + } + } + ); +} + +sub sp { + return LLNG::Manager::Test->new( { + ini => { + logLevel => $debug, + domain => 'sp.com', + portal => 'http://auth.sp.com', + authentication => 'CAS', + userDB => 'CAS', + restSessionServer => 1, + issuerDBCASActivation => 0, + multiValuesSeparator => ';', + exportedVars => { + cn => 'cn', + }, + casSrvMetaDataExportedVars => { + idp => { + cn => 'cn', + mail => 'mail', + uid => 'uid', + }, + idp2 => { + cn => 'cn', + mail => 'mail', + uid => 'uid', + } + }, + casSrvMetaDataOptions => { + idp => { + casSrvMetaDataOptionsUrl => 'http://auth.idp.com/cas', + casSrvMetaDataOptionsGateway => 0, + }, + idp2 => { + casSrvMetaDataOptionsUrl => 'http://auth.idp.com/cas', + casSrvMetaDataOptionsGateway => 0, + } + }, + }, + } + ); +} diff --git a/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-with-choice-and-cancel.t b/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-with-choice-and-cancel.t index aa7cf5c1c..09c5e7737 100644 --- a/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-with-choice-and-cancel.t +++ b/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-with-choice-and-cancel.t @@ -11,7 +11,7 @@ BEGIN { } eval { unlink 't/userdb.db' }; -my $maintests = 13; +my $maintests = 14; my $debug = 'error'; my ( $issuer, $sp, $res ); my %handlerOR = ( issuer => [], sp => [] ); @@ -110,6 +110,13 @@ SKIP: { ok( $idp[2] eq 'idp4', '3rd = idp4' ) or print STDERR Dumper( \@idp ); ok( $idp[3] eq 'idp2', '4th= idp2' ) or print STDERR Dumper( \@idp ); + # Found Cancel button + ok( + $res->[2]->[0] =~ +qr%%, + 'Found Cancel button' + ) or print STDERR Dumper( $res->[2]->[0] ); + # Found CAS idp logo and display name ok( $res->[2]->[0] =~