From a35215b27cbfa3ea396a101f70cd1e075ddc075c Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Tue, 15 Jan 2019 21:32:49 +0100 Subject: [PATCH 01/10] WIP - Improve e2e tests (#1600) --- e2e-tests/manager/01-generalParameters.js | 1 + e2e-tests/manager/05-form.js | 2 +- e2e-tests/manager/06-form.js | 7 +++++- e2e-tests/manager/07-authParams.js | 28 +++++++++++++++++++---- e2e-tests/manager/07-utf8.js | 4 +++- e2e-tests/manager/08-apply.js | 27 ++++++++++++++++------ e2e-tests/manager/11-oidcop-config.js | 4 ++-- e2e-tests/manager/12-oidcrp-config.js | 6 ++--- e2e-tests/manager/36-diff.js | 4 +++- e2e-tests/manager/40-sessions.js | 2 +- e2e-tests/protractor-conf.js | 8 +++---- 11 files changed, 68 insertions(+), 25 deletions(-) diff --git a/e2e-tests/manager/01-generalParameters.js b/e2e-tests/manager/01-generalParameters.js index af9e0c2c4..e83cdbaaa 100644 --- a/e2e-tests/manager/01-generalParameters.js +++ b/e2e-tests/manager/01-generalParameters.js @@ -70,6 +70,7 @@ describe('01 Lemonldap::NG Manager', function() { }); it('General Parameters > Authn. parameters > Users modules => Should have 7 modules availabled with "Same" selected', function() { element(by.id('t-userDB')).click(); + browser.sleep(1000); expect(element(by.css('option[selected="selected"]')).getAttribute('Value')).toEqual('Same'); expect(element.all(by.repeater('item in currentNode.select')).count()).toEqual(7); }); diff --git a/e2e-tests/manager/05-form.js b/e2e-tests/manager/05-form.js index 8eb3854e1..cc904bea9 100644 --- a/e2e-tests/manager/05-form.js +++ b/e2e-tests/manager/05-form.js @@ -44,7 +44,7 @@ describe('05 Lemonldap::NG Manager', function() { ['exportedVars', 'macros', 'groups'].forEach(function(type) { element(by.id('a-' + type)).click(); element(by.id('t-' + type)).click(); - element(by.css('.glyphicon-plus-sign')).click(); + element.all(by.css('.glyphicon-plus-sign')).first().click(); expect(element(by.id('t-' + type + '/n' + id)).getText()).toEqual('new'); browser.sleep(3000); id++; diff --git a/e2e-tests/manager/06-form.js b/e2e-tests/manager/06-form.js index 96e7524eb..b63b96b47 100644 --- a/e2e-tests/manager/06-form.js +++ b/e2e-tests/manager/06-form.js @@ -7,14 +7,19 @@ describe('06 Lemonldap::NG Manager', function() { describe('Form control, part 2', function() { it('should display portal skin choice', function() { - browser.get('/#/confs/1'); + browser.get('/#!/confs/lastest'); element(by.id('a-generalParameters')).click(); element(by.id('a-portalParams')).click(); element(by.id('a-portalCustomization')).click(); element(by.id('t-portalSkin')).click(); element(by.css('[ng-click="showModal(\'portalSkinChoice.html\')"]')).click(); + browser.sleep(1000); + var skinChoice = element.all(by.repeater('b in currentNode.select')); expect(skinChoice.count()).toEqual(1); + element(by.css('[trspan="cancel"]')).click(); + browser.sleep(1000); + }); }); }); diff --git a/e2e-tests/manager/07-authParams.js b/e2e-tests/manager/07-authParams.js index 88737742a..1cb4be608 100644 --- a/e2e-tests/manager/07-authParams.js +++ b/e2e-tests/manager/07-authParams.js @@ -7,37 +7,57 @@ describe('07 Lemonldap::NG Manager', function() { describe('Form control, part 3 - authParams', function() { it('should display auth modules chosen', function() { - browser.get('/#/confs/1'); + browser.get('/#!/confs/latest'); + browser.sleep(2000); + element(by.id('a-generalParameters')).click(); + browser.sleep(1000); element(by.id('a-authParams')).click(); + browser.sleep(1000); element(by.id('t-authentication')).click(); + browser.sleep(2000); + expect(element(by.id('t-demoParams')).isDisplayed()).toBeTruthy(); element(by.xpath("//option[@value='Apache']")).click(); + browser.sleep(2000); expect(element(by.id('t-apacheParams')).isDisplayed()).toBeTruthy(); }); it('should display auth modules chosen with authChoice', function() { element(by.xpath("//option[@value='Choice']")).click(); + browser.sleep(1000); expect(element(by.id('t-choiceParams')).isDisplayed()).toBeTruthy(); element(by.id('a-choiceParams')).click(); + browser.sleep(1000); element(by.id('t-authChoiceModules')).click(); - element(by.css('.glyphicon-plus-sign')).click(); + browser.sleep(2000); + + //element(by.css('.glyphicon-plus-sign')).click(); + browser.sleep(2000); element(by.id('a-authChoiceModules')).click(); + browser.sleep(2000); + element.all(by.css('.glyphicon-plus-sign')).first().click(); element(by.id('t-authChoiceModules/n1')).click(); - element(by.xpath("//option[@value='LDAP']")).click(); + browser.sleep(2000); + element.all(by.xpath("//option[@value='LDAP']")).first().click(); expect(element(by.id('t-ldapParams')).isDisplayed()).toBeTruthy(); }); it('should display auth modules chosen with authCombination', function() { element(by.id('t-authentication')).click(); + browser.sleep(1000); element(by.xpath("//option[@value='Combination']")).click(); + browser.sleep(1000); expect(element(by.id('t-combinationParams')).isDisplayed()).toBeTruthy(); element(by.id('a-combinationParams')).click(); + browser.sleep(1000); element(by.id('t-combModules')).click(); + browser.sleep(2000); + element(by.css('.glyphicon-plus-sign')).click(); element(by.xpath("//option[@value='DBI']")).click(); expect(element(by.id('t-dbiParams')).isDisplayed()).toBeTruthy(); - element(by.xpath("//option[@value='LDAP']")).click(); + element.all(by.xpath("//option[@value='LDAP']")).first().click(); expect(element(by.id('t-ldapParams')).isDisplayed()).toBeTruthy(); }); }); diff --git a/e2e-tests/manager/07-utf8.js b/e2e-tests/manager/07-utf8.js index 35b5e361b..25b5209be 100644 --- a/e2e-tests/manager/07-utf8.js +++ b/e2e-tests/manager/07-utf8.js @@ -7,7 +7,7 @@ describe('07u Lemonldap::NG Manager', function() { describe('Apply mechanism', function() { it('should be able to send UTF-8 chars', function() { - browser.get('/#/confs/latest'); + browser.get('/#!/confs/latest'); element(by.id('a-generalParameters')).click(); element(by.id('a-advancedParams')).click(); element(by.id('a-security')).click(); @@ -18,6 +18,8 @@ describe('07u Lemonldap::NG Manager', function() { element(by.id('save')).click(); element(by.id('longtextinput')).sendKeys('UTF-8 tests'); element(by.id('saveok')).click(); + browser.sleep(2000); + element(by.id('messageok')).click(); expect(element(by.id('cfgnum')).getText()).toEqual('2'); }); diff --git a/e2e-tests/manager/08-apply.js b/e2e-tests/manager/08-apply.js index a0bc1f384..773e4b811 100644 --- a/e2e-tests/manager/08-apply.js +++ b/e2e-tests/manager/08-apply.js @@ -7,25 +7,38 @@ describe('08 Lemonldap::NG Manager', function() { describe('Apply mechanism', function() { it('should be able to add reload urls', function() { - browser.get('/#/confs/latest'); + browser.get('/#!/confs/latest'); + browser.sleep(1000); element(by.id('a-generalParameters')).click(); - element(by.id('t-reloadParams')).click(); + element(by.id('a-reloadParams')).click(); element(by.id('t-reloadUrls')).click(); + element(by.id('a-reloadUrls')).click(); + + browser.sleep(1000); + //element(by.id('a-reloadUrls')).click(); element(by.css('.glyphicon-plus-sign')).click(); - element(by.id('a-reloadUrls')).click(); + browser.sleep(1000); + element(by.id('t-reloadUrls/n1')).click(); - element(by.id('hashkeyinput')).clear().sendKeys('auth.example.com:19876'); - element(by.id('hashvalueinput')).clear().sendKeys('http://auth.example.com:19876/static/nothing'); + browser.sleep(1000); + element(by.id('hashkeyinput')).clear().sendKeys('auth.example.com'); + browser.sleep(1000); + element(by.id('hashvalueinput')).clear().sendKeys('http://auth.example.com:19876/static/common/icons/ok.png'); + browser.sleep(1000); element(by.css('.glyphicon-plus-sign')).click(); element(by.id('t-reloadUrls/n2')).click(); - element(by.id('hashkeyinput')).clear().sendKeys('manager.example.com:19876'); - element(by.id('hashvalueinput')).clear().sendKeys('http://auth.example.com:19876/static/js/manager.js'); + element(by.id('hashkeyinput')).clear().sendKeys('manager.example.com'); + element(by.id('hashvalueinput')).clear().sendKeys('http://manager.example.com:19876/static/js/manager.js'); + browser.sleep(1000); + }); it('should save new configuration', function() { element(by.id('save')).click(); element(by.id('longtextinput')).sendKeys('Reload URLs test'); element(by.id('saveok')).click(); expect(element.all(by.repeater('item in item.items')).count()).toEqual(2); + browser.sleep(1000); + element(by.id('messageok')).click(); expect(element(by.id('cfgnum')).getText()).toEqual('3'); }); diff --git a/e2e-tests/manager/11-oidcop-config.js b/e2e-tests/manager/11-oidcop-config.js index aa2c6d94e..d1128e7c4 100644 --- a/e2e-tests/manager/11-oidcop-config.js +++ b/e2e-tests/manager/11-oidcop-config.js @@ -9,7 +9,7 @@ describe('11 Lemonldap::NG Manager', function() { it('should add an OIDC OP', function() { browser.get('/#/confs/latest'); element(by.id('t-oidcOPMetaDataNodes')).click(); - element(by.css('.glyphicon-plus-sign')).click(); + element.all(by.css('.glyphicon-plus-sign')).first().click(); element(by.id('promptok')).click(); browser.sleep(500); element(by.id('a-oidcOPMetaDataNodes/new__op-example')).click(); @@ -18,7 +18,7 @@ describe('11 Lemonldap::NG Manager', function() { element(by.id('t-oidcOPMetaDataNodes/new__op-example/oidcOPMetaDataJWKS')).click(); element(by.id('filetext')).sendKeys('{"c":"d"}'); element(by.id('t-oidcOPMetaDataNodes/new__op-example/oidcOPMetaDataExportedVars')).click(); - element(by.css('.glyphicon-plus-sign')).click(); + element.all(by.css('.glyphicon-plus-sign')).first().click(); //element(by.id('a-oidcOPMetaDataNodes/new__op-example/oidcOPMetaDataExportedVars')).click(); element(by.id('t-oidcOPMetaDataNodes/new__op-example/oidcOPMetaDataExportedVars/n1')).click(); element(by.id('hashkeyinput')).clear().sendKeys('MyKey'); diff --git a/e2e-tests/manager/12-oidcrp-config.js b/e2e-tests/manager/12-oidcrp-config.js index 7d284e90e..b23ef1afd 100644 --- a/e2e-tests/manager/12-oidcrp-config.js +++ b/e2e-tests/manager/12-oidcrp-config.js @@ -9,12 +9,12 @@ describe('12 Lemonldap::NG Manager', function() { it('should add an OIDC RP', function() { browser.get('/#/confs/latest'); element(by.id('t-oidcRPMetaDataNodes')).click(); - element(by.css('.glyphicon-plus-sign')).click(); + element.all(by.css('.glyphicon-plus-sign')).first().click(); element(by.id('promptok')).click(); browser.sleep(500); element(by.id('a-oidcRPMetaDataNodes/new__rp-example')).click(); element(by.id('t-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataExportedVars')).click(); - element(by.css('.glyphicon-plus-sign')).click(); + element.all(by.css('.glyphicon-plus-sign')).first().click(); //element(by.id('a-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataExportedVars')).click(); element(by.id('t-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataExportedVars/n1')).click(); element(by.id('hashkeyinput')).clear().sendKeys('MyKey'); @@ -24,7 +24,7 @@ describe('12 Lemonldap::NG Manager', function() { element(by.id('t-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataOptionsClientID')).click(); element(by.id('textinput')).clear().sendKeys('MyClientID'); element(by.id('t-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataOptionsExtraClaims')).click(); - element(by.css('.glyphicon-plus-sign')).click(); + element.all(by.css('.glyphicon-plus-sign')).first().click(); //element(by.id('a-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataOptionsExtraClaims')).click(); element(by.id('t-oidcRPMetaDataNodes/new__rp-example/oidcRPMetaDataOptionsExtraClaims/n2')).click(); element(by.id('hashkeyinput')).clear().sendKeys('MyClaim'); diff --git a/e2e-tests/manager/36-diff.js b/e2e-tests/manager/36-diff.js index 800dd1f41..94aeafbf9 100644 --- a/e2e-tests/manager/36-diff.js +++ b/e2e-tests/manager/36-diff.js @@ -7,7 +7,9 @@ describe('36 Lemonldap::NG Manager', function() { describe('Diff interface', function() { it('should find key changed', function() { - browser.get('/diff.html#!/6/7'); + browser.get('/diff.html#!/5/6'); + browser.sleep(5000); + element(by.id('t-generalParameters')).click(); element(by.id('t-advancedParams')).click(); element(by.id('t-security')).click(); diff --git a/e2e-tests/manager/40-sessions.js b/e2e-tests/manager/40-sessions.js index 05aac57e9..98264abbb 100644 --- a/e2e-tests/manager/40-sessions.js +++ b/e2e-tests/manager/40-sessions.js @@ -6,7 +6,7 @@ describe('40 Lemonldap::NG Manager', function() { browser.get('/'); var links = element.all(by.repeater('l in links')); expect(links.count()).toEqual(4); - element(by.xpath("//a[@href='sessions.html']")).click(); + element.all(by.xpath("//a[@href='sessions.html']")).first().click(); }); }); diff --git a/e2e-tests/protractor-conf.js b/e2e-tests/protractor-conf.js index 328e6a2cb..35fec1a71 100644 --- a/e2e-tests/protractor-conf.js +++ b/e2e-tests/protractor-conf.js @@ -1,10 +1,10 @@ exports.config = { - allScriptsTimeout: 11000, + allScriptsTimeout: 300000, // Specific test - specs: process.env.E2E_TESTS, + // specs: process.env.E2E_TESTS, // All tests - //specs: ['handler/*.js', 'portal/*.js', 'manager/*.js' ], + specs: ['portal/*.js', 'handler/*.js', 'manager/*.js' ], capabilities: { 'browserName': 'chrome' @@ -17,6 +17,6 @@ exports.config = { framework: 'jasmine', jasmineNodeOpts: { - defaultTimeoutInterval: 30000 + defaultTimeoutInterval: 60000 } }; \ No newline at end of file From 0a7da5f474980b81f04e2b74e431b4e17b630682 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Tue, 15 Jan 2019 21:38:40 +0100 Subject: [PATCH 02/10] Fix charset encoding (#1614) --- lemonldap-ng-portal/site/templates/bootstrap/header.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/lemonldap-ng-portal/site/templates/bootstrap/header.tpl b/lemonldap-ng-portal/site/templates/bootstrap/header.tpl index 0033dff9a..cb264917d 100644 --- a/lemonldap-ng-portal/site/templates/bootstrap/header.tpl +++ b/lemonldap-ng-portal/site/templates/bootstrap/header.tpl @@ -2,6 +2,7 @@ Authentication portal + From 66de5a8e1b48fa29f7cc7aa16a59965b4ed266d8 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Tue, 15 Jan 2019 22:31:07 +0100 Subject: [PATCH 03/10] Revert (#1614) --- lemonldap-ng-portal/site/templates/bootstrap/header.tpl | 1 - 1 file changed, 1 deletion(-) diff --git a/lemonldap-ng-portal/site/templates/bootstrap/header.tpl b/lemonldap-ng-portal/site/templates/bootstrap/header.tpl index cb264917d..0033dff9a 100644 --- a/lemonldap-ng-portal/site/templates/bootstrap/header.tpl +++ b/lemonldap-ng-portal/site/templates/bootstrap/header.tpl @@ -2,7 +2,6 @@ Authentication portal - From 3c3b8eccb70a876871df1072a596942a33ec3278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Tue, 15 Jan 2019 22:42:42 +0100 Subject: [PATCH 04/10] Remove utf8 decode for menu (#1614) --- lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm index 4258f23f9..6bf0b08ce 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm @@ -3,11 +3,10 @@ package Lemonldap::NG::Portal::Main::Menu; use strict; -use utf8; use Mouse; use Clone 'clone'; -our $VERSION = '2.0.1'; +our $VERSION = '2.0.2'; extends 'Lemonldap::NG::Common::Module'; @@ -188,7 +187,6 @@ sub appslist { sub _buildCategoryHash { my ( $self, $req, $catid, $cathash, $catlevel ) = @_; my $catname = $cathash->{catname} || $catid; - utf8::decode($catname); my $applications; my $categories; @@ -244,8 +242,6 @@ sub _buildApplicationHash { my $appuri = $apphash->{options}->{uri} || ""; my $appdesc = $apphash->{options}->{description}; my $applogo = $apphash->{options}->{logo}; - utf8::decode($appname); - utf8::decode($appdesc) if $appdesc; # Detect sub applications my $subapphash; From 2c25170c9e4c2ab415be17a4ed0c1ecf28a2e180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Tue, 15 Jan 2019 22:42:42 +0100 Subject: [PATCH 05/10] Remove utf8 decode for menu (#1614) --- lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm index 4258f23f9..6bf0b08ce 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm @@ -3,11 +3,10 @@ package Lemonldap::NG::Portal::Main::Menu; use strict; -use utf8; use Mouse; use Clone 'clone'; -our $VERSION = '2.0.1'; +our $VERSION = '2.0.2'; extends 'Lemonldap::NG::Common::Module'; @@ -188,7 +187,6 @@ sub appslist { sub _buildCategoryHash { my ( $self, $req, $catid, $cathash, $catlevel ) = @_; my $catname = $cathash->{catname} || $catid; - utf8::decode($catname); my $applications; my $categories; @@ -244,8 +242,6 @@ sub _buildApplicationHash { my $appuri = $apphash->{options}->{uri} || ""; my $appdesc = $apphash->{options}->{description}; my $applogo = $apphash->{options}->{logo}; - utf8::decode($appname); - utf8::decode($appdesc) if $appdesc; # Detect sub applications my $subapphash; From 9fa203de2d661d4eecff1433d701866b7c740a4c Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Wed, 16 Jan 2019 11:02:58 +0100 Subject: [PATCH 06/10] Fix tsv call (#1574) --- lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm index 4cc2315cd..b8b7479c7 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm @@ -235,7 +235,7 @@ sub tests { # Warn if cookie name has changed cookieNameChanged => sub { - my $cn = $Lemonldap::NG::Handler::PSGI::API::tsv->{cookieName}; + my $cn = Lemonldap::NG::Handler::Main->tsv->{cookieName}; return ( 1, ( $cn From 2f41ad1b4707a215f5f5d1980bda453dd72717b2 Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Wed, 16 Jan 2019 11:05:58 +0100 Subject: [PATCH 07/10] Tidy --- .../lib/Lemonldap/NG/Manager/Conf/Parser.pm | 289 +++++++++--------- 1 file changed, 138 insertions(+), 151 deletions(-) diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm index c3129a34a..d8d4d3cc3 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm @@ -46,8 +46,7 @@ has warnings => ( hdebug( 'warnings contains', $_[0]->{warnings} ); } ); -has changes => - ( is => 'rw', isa => 'ArrayRef', default => sub { return [] } ); +has changes => ( is => 'rw', isa => 'ArrayRef', default => sub { return [] } ); has message => ( is => 'rw', isa => 'Str', @@ -57,7 +56,7 @@ has message => ( } ); has needConfirmation => - ( is => 'rw', isa => 'ArrayRef', default => sub { return [] } ); + ( is => 'rw', isa => 'ArrayRef', default => sub { return [] } ); # Booleans has confChanged => ( @@ -70,7 +69,7 @@ has confChanged => ( ); # Properties required during build -has refConf => ( is => 'ro', isa => 'HashRef', required => 1 ); +has refConf => ( is => 'ro', isa => 'HashRef', required => 1 ); has req => ( is => 'ro', required => 1 ); has newConf => ( is => 'rw', isa => 'HashRef' ); has tree => ( is => 'rw', isa => 'ArrayRef' ); @@ -125,15 +124,14 @@ sub scanTree { # Set cfgNum to ref cfgNum (will be changed when saving), set other # metadata and set a value to the key if empty $self->newConf->{cfgNum} = $self->req->params('cfgNum'); - $self->newConf->{cfgAuthor} - = $self->req->userData - ->{ &Lemonldap::NG::Handler::Main::tsv->{whatToTrace} - || '_whatToTrace' } // "anonymous"; + $self->newConf->{cfgAuthor} = + $self->req->userData->{ &Lemonldap::NG::Handler::Main::tsv->{whatToTrace} + || '_whatToTrace' } // "anonymous"; $self->newConf->{cfgAuthorIP} = $self->req->address; $self->newConf->{cfgDate} = time; $self->newConf->{cfgVersion} = $VERSION; - $self->newConf->{key} - ||= join( '', map { chr( int( rand(94) ) + 33 ) } ( 1 .. 16 ) ); + $self->newConf->{key} ||= + join( '', map { chr( int( rand(94) ) + 33 ) } ( 1 .. 16 ) ); return 1; } @@ -160,7 +158,7 @@ sub _scanNodes { hdebug("Looking to $name"); # subnode - my $subNodes = $leaf->{nodes} // $leaf->{_nodes}; + my $subNodes = $leaf->{nodes} // $leaf->{_nodes}; my $subNodesCond = $leaf->{nodes_cond} // $leaf->{_nodes_cond}; ################################## @@ -193,7 +191,7 @@ sub _scanNodes { $self->confChanged(1); foreach my $deletedHost (@old) { push @{ $self->changes }, - { key => $leaf->{id}, old => $deletedHost }; + { key => $leaf->{id}, old => $deletedHost }; } } next; @@ -210,7 +208,7 @@ sub _scanNodes { hdebug(" $host becomes $newNames{$host}"); $self->confChanged(1); push @{ $self->changes }, - { key => $base, old => $host, new => $newNames{$host} }; + { key => $base, old => $host, new => $newNames{$host} }; } $self->_scanNodes($subNodes); @@ -218,15 +216,15 @@ sub _scanNodes { } # Other sub levels - elsif ( $leaf->{id} - =~ /^($specialNodeKeys)\/([^\/]+)\/([^\/]+)(?:\/(.*))?$/io ) + elsif ( $leaf->{id} =~ + /^($specialNodeKeys)\/([^\/]+)\/([^\/]+)(?:\/(.*))?$/io ) { - my ( $base, $key, $oldName, $target, $h ) - = ( $1, $newNames{$2}, $2, $3, $4 ); + my ( $base, $key, $oldName, $target, $h ) = + ( $1, $newNames{$2}, $2, $3, $4 ); hdebug( "Special node chield subnode detected $leaf->{id}", " base $base, key $key, target $target, h " - . ( $h ? $h : 'undef' ) + . ( $h ? $h : 'undef' ) ); # VirtualHosts @@ -235,18 +233,18 @@ sub _scanNodes { if ( $target =~ /^(?:locationRules|exportedHeaders|post)$/ ) { if ( $leaf->{cnodes} ) { hdebug(' unopened subnode'); - $self->newConf->{$target}->{$key} - = $self->refConf->{$target}->{$oldName} // {}; + $self->newConf->{$target}->{$key} = + $self->refConf->{$target}->{$oldName} // {}; } elsif ($h) { hdebug(' 4 levels'); if ( $target eq 'locationRules' ) { hdebug(' locationRules'); - my $k - = $leaf->{comment} - ? "(?#$leaf->{comment})$leaf->{re}" - : $leaf->{re}; + my $k = + $leaf->{comment} + ? "(?#$leaf->{comment})$leaf->{re}" + : $leaf->{re}; $self->set( $target, $key, $k, $leaf->{data} ); } else { @@ -262,7 +260,7 @@ sub _scanNodes { if ( ref $subNodes ) { hdebug(' has subnodes'); $self->_scanNodes($subNodes) - or return 0; + or return 0; } if ( exists $self->refConf->{$target}->{$key} and %{ $self->refConf->{$target}->{$key} } ) @@ -276,10 +274,10 @@ sub _scanNodes { hdebug(' missing value in old conf'); $self->confChanged(1); push @{ $self->changes }, - { + { key => "$target, $key", old => $k, - }; + }; } } } @@ -289,7 +287,7 @@ sub _scanNodes { hdebug(" '$key' has values"); $self->confChanged(1); push @{ $self->changes }, - { key => "$target", new => $key }; + { key => "$target", new => $key }; } } } @@ -299,7 +297,7 @@ sub _scanNodes { } else { push @{ $self->errors }, - { message => "Unknown vhost key $target" }; + { message => "Unknown vhost key $target" }; return 0; } next; @@ -314,12 +312,11 @@ sub _scanNodes { hdebug(" SAML data is an array, serializing"); $leaf->{data} = join ';', @{ $leaf->{data} }; } - if ( $target =~ /^saml(?:S|ID)PMetaDataExportedAttributes$/ ) - { + if ( $target =~ /^saml(?:S|ID)PMetaDataExportedAttributes$/ ) { if ( $leaf->{cnodes} ) { hdebug(" $target: unopened node"); - $self->newConf->{$target}->{$key} - = $self->refConf->{$target}->{$oldName} // {}; + $self->newConf->{$target}->{$key} = + $self->refConf->{$target}->{$oldName} // {}; } elsif ($h) { hdebug(" $target: opened node"); @@ -334,17 +331,15 @@ sub _scanNodes { } elsif ( $target =~ /^saml(?:S|ID)PMetaDataXML$/ ) { hdebug(" $target"); - $self->set( - $target, [ $oldName, $key ], - $target, $leaf->{data} - ); + $self->set( $target, [ $oldName, $key ], + $target, $leaf->{data} ); } elsif ( $target =~ /^saml(?:ID|S)PMetaDataOptions/ ) { my $optKey = $&; hdebug(" $base sub key: $target"); - if ( $target - =~ /^(?:$samlIDPMetaDataNodeKeys|$samlSPMetaDataNodeKeys)/o - ) + if ( $target =~ + /^(?:$samlIDPMetaDataNodeKeys|$samlSPMetaDataNodeKeys)/o + ) { $self->set( $optKey, [ $oldName, $key ], @@ -353,14 +348,13 @@ sub _scanNodes { } else { push @{ $self->errors }, - { message => - "Unknown SAML metadata option $target" }; + { message => "Unknown SAML metadata option $target" }; return 0; } } else { push @{ $self->errors }, - { message => "Unknown SAML key $target" }; + { message => "Unknown SAML key $target" }; return 0; } next; @@ -372,8 +366,7 @@ sub _scanNodes { if ( $target =~ /^oidc(?:O|R)PMetaDataOptions$/ ) { hdebug(" $target: looking for subnodes"); $self->_scanNodes($subNodes); - $self->set( $target, $key, $leaf->{title}, - $leaf->{data} ); + $self->set( $target, $key, $leaf->{title}, $leaf->{data} ); } elsif ( $target =~ /^oidcOPMetaData(?:JSON|JWKS)$/ ) { hdebug(" $target"); @@ -383,8 +376,8 @@ sub _scanNodes { hdebug(" $target"); if ( $leaf->{cnodes} ) { hdebug(' unopened'); - $self->newConf->{$target}->{$key} - = $self->refConf->{$target}->{$oldName} // {}; + $self->newConf->{$target}->{$key} = + $self->refConf->{$target}->{$oldName} // {}; } elsif ($h) { hdebug(' opened'); @@ -402,8 +395,8 @@ sub _scanNodes { if ( $target eq 'oidcRPMetaDataOptionsExtraClaims' ) { if ( $leaf->{cnodes} ) { hdebug(' unopened'); - $self->newConf->{$target}->{$key} - = $self->refConf->{$target}->{$oldName} // {}; + $self->newConf->{$target}->{$key} = + $self->refConf->{$target}->{$oldName} // {}; } elsif ($h) { hdebug(' opened'); @@ -415,9 +408,9 @@ sub _scanNodes { $self->_scanNodes($subNodes); } } - elsif ( $target - =~ /^(?:$oidcOPMetaDataNodeKeys|$oidcRPMetaDataNodeKeys)/o - ) + elsif ( $target =~ + /^(?:$oidcOPMetaDataNodeKeys|$oidcRPMetaDataNodeKeys)/o + ) { $self->set( $optKey, [ $oldName, $key ], @@ -426,14 +419,13 @@ sub _scanNodes { } else { push @{ $self->errors }, - { message => - "Unknown OIDC metadata option $target" }; + { message => "Unknown OIDC metadata option $target" }; return 0; } } else { push @{ $self->errors }, - { message => "Unknown OIDC key $target" }; + { message => "Unknown OIDC key $target" }; return 0; } next; @@ -446,15 +438,14 @@ sub _scanNodes { if ( $target =~ /^cas(?:App|Srv)MetaDataOptions$/ ) { hdebug(" $target: looking for subnodes"); $self->_scanNodes($subNodes); - $self->set( $target, $key, $leaf->{title}, - $leaf->{data} ); + $self->set( $target, $key, $leaf->{title}, $leaf->{data} ); } elsif ( $target =~ /^cas(?:App|Srv)MetaDataExportedVars$/ ) { hdebug(" $target"); if ( $leaf->{cnodes} ) { hdebug(' unopened'); - $self->newConf->{$target}->{$key} - = $self->refConf->{$target}->{$oldName} // {}; + $self->newConf->{$target}->{$key} = + $self->refConf->{$target}->{$oldName} // {}; } elsif ($h) { hdebug(' opened'); @@ -472,8 +463,8 @@ sub _scanNodes { if ( $target eq 'casSrvMetaDataOptionsProxiedServices' ) { if ( $leaf->{cnodes} ) { hdebug(' unopened'); - $self->newConf->{$target}->{$key} - = $self->refConf->{$target}->{$oldName} // {}; + $self->newConf->{$target}->{$key} = + $self->refConf->{$target}->{$oldName} // {}; } elsif ($h) { hdebug(' opened'); @@ -485,9 +476,9 @@ sub _scanNodes { $self->_scanNodes($subNodes); } } - elsif ( $target - =~ /^(?:$casSrvMetaDataNodeKeys|$casAppMetaDataNodeKeys)/o - ) + elsif ( $target =~ + /^(?:$casSrvMetaDataNodeKeys|$casAppMetaDataNodeKeys)/o + ) { $self->set( $optKey, [ $oldName, $key ], @@ -496,21 +487,20 @@ sub _scanNodes { } else { push @{ $self->errors }, - { message => - "Unknown CAS metadata option $target" }; + { message => "Unknown CAS metadata option $target" }; return 0; } } else { push @{ $self->errors }, - { message => "Unknown CAS option $target" }; + { message => "Unknown CAS option $target" }; return 0; } next; } else { push @{ $self->errors }, - { message => "Fatal: unknown special sub node $base" }; + { message => "Fatal: unknown special sub node $base" }; return 0; } } @@ -524,39 +514,40 @@ sub _scanNodes { hdebug( $leaf->{title} ); if ( $leaf->{cnodes} ) { hdebug(' unopened'); - $self->newConf->{applicationList} - = $self->refConf->{applicationList} // {}; + $self->newConf->{applicationList} = + $self->refConf->{applicationList} // {}; } else { $self->_scanNodes($subNodes) or return 0; # Check for deleted - my @listCatRef - = map { $self->refConf->{applicationList}->{$_}->{catname} } - keys %{ $self->refConf->{applicationList} }; - my @listCatNew - = map { $self->newConf->{applicationList}->{$_}->{catname} } - keys( - %{ ref $self->newConf->{applicationList} + my @listCatRef = + map { $self->refConf->{applicationList}->{$_}->{catname} } + keys %{ $self->refConf->{applicationList} }; + my @listCatNew = + map { $self->newConf->{applicationList}->{$_}->{catname} } + keys( + %{ + ref $self->newConf->{applicationList} ? $self->newConf->{applicationList} : {} } - ); + ); - @listCatRef = sort @listCatRef; - @listCatNew = sort @listCatNew; + @listCatRef = sort @listCatRef; + @listCatNew = sort @listCatNew; hdebug( '# @listCatRef : ' . \@listCatRef ); hdebug( '# @listCatNew : ' . \@listCatNew ); - for ( my $i = 0; $i < @listCatNew; $i++ ) { + for ( my $i = 0 ; $i < @listCatNew ; $i++ ) { if ( not( defined $listCatRef[$i] ) or $listCatRef[$i] ne $listCatNew[$i] ) { push @{ $self->changes }, - { + { key => $leaf->{id}, new => $listCatNew[$i], old => $listCatRef[$i] - }; + }; } } } @@ -581,9 +572,8 @@ sub _scanNodes { hdebug(" looking to cat $cat"); unless ( defined $knownCat->{$cat} ) { push @{ $self->{errors} }, - { message => - "Fatal: sub cat/app before parent ($leaf->{id})" - }; + { message => + "Fatal: sub cat/app before parent ($leaf->{id})" }; return 0; } $cn = $cn->{ $knownCat->{$cat} }; @@ -600,19 +590,20 @@ sub _scanNodes { hdebug(' menu cat'); $knownCat->{__id}++; my $s = $knownCat->{$app} = sprintf '%04d-cat', - $knownCat->{__id}; + $knownCat->{__id}; $cn->{$s} = { catname => $leaf->{title}, type => 'category' }; unless ($cmp->{$app} and $cmp->{$app}->{catname} eq $cn->{$s}->{catname} ) { $self->confChanged(1); push @{ $self->changes }, - { - key => join( ', ', - 'applicationList', @path, $leaf->{title} ), + { + key => join( + ', ', 'applicationList', @path, $leaf->{title} + ), new => $cn->{$s}->{catname}, old => ( $cn->{$s} ? $cn->{$s}->{catname} : undef ) - }; + }; } if ( ref $subNodes ) { $self->_scanNodes($subNodes) or return 0; @@ -624,10 +615,10 @@ sub _scanNodes { unless ( @listCatRef == @listCatNew ) { $self->confChanged(1); push @{ $self->changes }, - { + { key => join( ', ', 'applicationList', @path ), new => 'Changes in cat(s)/app(s)', - }; + }; } } @@ -636,16 +627,16 @@ sub _scanNodes { hdebug(' new app'); $knownCat->{__id}++; my $name = sprintf( '%04d-app', $knownCat->{__id} ); - $cn->{$name} - = { type => 'application', options => $leaf->{data} }; + $cn->{$name} = + { type => 'application', options => $leaf->{data} }; $cn->{$name}->{options}->{name} = $leaf->{title}; unless ( $cmp->{$app} ) { $self->confChanged(1); push @{ $self->changes }, - { + { key => join( ', ', 'applicationList', @path ), new => $leaf->{title}, - }; + }; } else { foreach my $k ( keys %{ $cn->{$name}->{options} } ) { @@ -654,13 +645,13 @@ sub _scanNodes { { $self->confChanged(1); push @{ $self->changes }, - { + { key => join( ', ', 'applicationList', @path, $leaf->{title}, $k ), new => $cn->{$name}->{options}->{$k}, old => $cmp->{$app}->{options}->{$k} - }; + }; } } } @@ -683,31 +674,31 @@ sub _scanNodes { $self->newConf->{grantSessionRules} = {}; foreach my $n (@$subNodes) { hdebug(" looking at $n subnode"); - my $k = $n->{re} - . ( $n->{comment} ? "##$n->{comment}" : '' ); + my $k = + $n->{re} . ( $n->{comment} ? "##$n->{comment}" : '' ); $self->newConf->{grantSessionRules}->{$k} = $n->{data}; $count++; unless ( defined $ref->{$k} ) { $self->confChanged(1); push @{ $self->changes }, - { keys => 'grantSessionRules', new => $k }; + { keys => 'grantSessionRules', new => $k }; } elsif ( $ref->{$k} ne $n->{data} ) { $self->confChanged(1); push @{ $self->changes }, - { + { key => "grantSessionRules, $k", old => $self->refConf->{grantSessionRules}->{$k}, new => $n->{data} - }; + }; } @old = grep { $_ ne $k } @old; } if (@old) { $self->confChanged(1); push @{ $self->changes }, - { key => 'grantSessionRules', old => $_, } - foreach (@old); + { key => 'grantSessionRules', old => $_, } + foreach (@old); } } next; @@ -720,8 +711,7 @@ sub _scanNodes { if ( $leaf->{data} ) { unless ( ref $leaf->{data} eq 'ARRAY' ) { push @{ $self->{errors} }, - { message => 'Malformed openIdIDPList ' - . $leaf->{data} }; + { message => 'Malformed openIdIDPList ' . $leaf->{data} }; return 0; } $self->set( $name, join( ';', @{ $leaf->{data} } ) ); @@ -754,8 +744,7 @@ sub _scanNodes { $self->newConf->{$name} = {}; foreach my $node ( @{ $leaf->{nodes} } ) { my $tmp; - $tmp->{$_} = $node->{data}->{$_} - foreach (qw(type for)); + $tmp->{$_} = $node->{data}->{$_} foreach (qw(type for)); $tmp->{over} = {}; foreach ( @{ $node->{data}->{over} } ) { $tmp->{over}->{ $_->[0] } = $_->[1]; @@ -791,30 +780,29 @@ sub _scanNodes { } $self->newConf->{$name}->{ $n->{title} } = $n->{data}; $count++; - unless ( - defined $self->refConf->{$name}->{ $n->{title} } ) + unless ( defined $self->refConf->{$name}->{ $n->{title} } ) { $self->confChanged(1); push @{ $self->changes }, - { key => $name, new => $n->{title}, }; + { key => $name, new => $n->{title}, }; } - elsif ( $self->refConf->{$name}->{ $n->{title} } ne - $n->{data} ) + elsif ( + $self->refConf->{$name}->{ $n->{title} } ne $n->{data} ) { $self->confChanged(1); push @{ $self->changes }, - { + { key => "$name, $n->{title}", old => $self->refConf->{$name}->{ $n->{title} }, new => $n->{data} - }; + }; } @old = grep { $_ ne $n->{title} } @old; } if (@old) { $self->confChanged(1); push @{ $self->changes }, { key => $name, old => $_, } - foreach (@old); + foreach (@old); } } next; @@ -851,23 +839,23 @@ sub _scanNodes { @oldKeys = keys %{ $self->refConf->{$name}->{$host} }; } foreach my $prm ( @{ $getHost->{h} } ) { - $self->newConf->{$name}->{$host}->{ $prm->{k} } - = $prm->{v}; - if (!$change + $self->newConf->{$name}->{$host}->{ $prm->{k} } = + $prm->{v}; + if ( + !$change and ( not defined( - $self->refConf->{$name}->{$host} - ->{ $prm->{k} } + $self->refConf->{$name}->{$host}->{ $prm->{k} } ) or $self->newConf->{$name}->{$host}->{ $prm->{k} } ne $self->refConf->{$name}->{$host}->{ $prm->{k} } ) - ) + ) { $self->confChanged(1); hdebug(" key $prm->{k} has been changed"); push @{ $self->changes }, - { key => "$name/$host", new => $prm->{k} }; + { key => "$name/$host", new => $prm->{k} }; } elsif ( !$change ) { @oldKeys = grep { $_ ne $prm->{k} } @oldKeys; @@ -877,15 +865,15 @@ sub _scanNodes { $self->confChanged(1); hdebug( " old keys: " . join( ' ', @oldKeys ) ); push @{ $self->changes }, - { key => "$name/$host", old => $_ } - foreach (@oldKeys); + { key => "$name/$host", old => $_ } + foreach (@oldKeys); } } if (@oldHosts) { $self->confChanged(1); hdebug( " old hosts " . join( ' ', @oldHosts ) ); push @{ $self->changes }, { key => "$name", old => $_ } - foreach (@oldHosts); + foreach (@oldHosts); } next; } @@ -973,16 +961,15 @@ sub set { or ( !defined $confs[0]->{$target} and defined $self->defaultValue($target) and $data eq $self->defaultValue($target) ) - ) + ) { $self->confChanged(1); push @{ $self->changes }, - { + { key => join( ', ', @path, $target ), - old => $confs[0]->{$target} - // $self->defaultValue($target), + old => $confs[0]->{$target} // $self->defaultValue($target), new => $confs[1]->{$target} - }; + }; } }; } @@ -1006,7 +993,7 @@ sub defaultValue { die unless ($target); my $res = eval { &Lemonldap::NG::Manager::Attributes::attributes()->{$target} - ->{'default'}; + ->{'default'}; }; return $res; } @@ -1055,8 +1042,7 @@ sub _unitTest { # Check if key exists unless ($attr) { - push @{ $self->errors }, - { message => "__unknownKey__: $key" }; + push @{ $self->errors }, { message => "__unknownKey__: $key" }; $res = 0; next; } @@ -1066,7 +1052,7 @@ sub _unitTest { $conf->{$key} //= {}; unless ( ref $conf->{$key} eq 'HASH' ) { push @{ $self->errors }, - { message => "$key is not a hash ref" }; + { message => "$key is not a hash ref" }; $res = 0; next; } @@ -1079,20 +1065,21 @@ sub _unitTest { or $attr->{type} =~ /Container$/ ) { my $keyMsg = $attr->{keyMsgFail} // $type->{keyMsgFail}; - my $msg = $attr->{msgFail} // $type->{msgFail}; + my $msg = $attr->{msgFail} // $type->{msgFail}; $res = 0 - unless ( + unless ( $self->_execTest( - { keyTest => $attr->{keyTest} // $type->{keyTest}, + { + keyTest => $attr->{keyTest} // $type->{keyTest}, keyMsgFail => $attr->{keyMsgFail} - // $type->{keyMsgFail}, - test => $attr->{test} // $type->{test}, + // $type->{keyMsgFail}, + test => $attr->{test} // $type->{test}, msgFail => $attr->{msgFail} // $type->{msgFail}, }, $conf->{$key}, $key, $attr, undef, $conf ) - ); + ); } elsif ( defined $attr->{keyTest} ) { @@ -1101,12 +1088,12 @@ sub _unitTest { else { my $msg = $attr->{msgFail} // $type->{msgFail}; $res = 0 - unless ( + unless ( $self->_execTest( $attr->{test} // $type->{test}, $conf->{$key}, $key, $attr, $msg, $conf ) - ); + ); } } } @@ -1121,13 +1108,13 @@ sub _execTest { my ( $self, $test, $value, $key, $attr, $msg, $conf ) = @_; my $ref; die - "Malformed test for $key: only regexp ref or sub are accepted (type \"$ref\")" - unless ( $ref = ref($test) and $ref =~ /^(CODE|Regexp|HASH)$/ ); +"Malformed test for $key: only regexp ref or sub are accepted (type \"$ref\")" + unless ( $ref = ref($test) and $ref =~ /^(CODE|Regexp|HASH)$/ ); if ( $ref eq 'CODE' ) { my ( $r, $m ) = ( $test->( $value, $conf, $attr ) ); if ($m) { push @{ $self->{ ( $r ? 'warnings' : 'errors' ) } }, - { message => "$key: $m" }; + { message => "$key: $m" }; } elsif ( !$r ) { push @{ $self->{errors} }, { message => "$key: $msg" }; @@ -1146,7 +1133,7 @@ sub _execTest { return $res unless ( ref($value) eq 'HASH' ); foreach my $k ( keys %$value ) { $res = 0 - unless ( + unless ( $self->_execTest( $test->{keyTest}, $k, "$key/$k", $attr, $test->{keyMsgFail}, $conf @@ -1155,7 +1142,7 @@ sub _execTest { $test->{test}, $value->{$k}, "$key/$k", $attr, $test->{msgFail}, $conf ) - ); + ); } return $res; } @@ -1170,7 +1157,7 @@ sub _globalTest { require Lemonldap::NG::Manager::Conf::Tests; hdebug('# _globalTest()'); my $result = 1; - my $tests = &Lemonldap::NG::Manager::Conf::Tests::tests( $self->newConf ); + my $tests = &Lemonldap::NG::Manager::Conf::Tests::tests( $self->newConf ); foreach my $name ( keys %$tests ) { if ( $self->{skippedGlobalTests} and $self->{skippedGlobalTests} =~ /\b$name\b/ ) From 3cd434eec1863b71f849f2c19b07f6055817e311 Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Wed, 16 Jan 2019 11:07:22 +0100 Subject: [PATCH 08/10] Fix tsv call (#1574) --- lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm index d8d4d3cc3..3a6feeb61 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Parser.pm @@ -125,7 +125,7 @@ sub scanTree { # metadata and set a value to the key if empty $self->newConf->{cfgNum} = $self->req->params('cfgNum'); $self->newConf->{cfgAuthor} = - $self->req->userData->{ &Lemonldap::NG::Handler::Main::tsv->{whatToTrace} + $self->req->userData->{ Lemonldap::NG::Handler::Main->tsv->{whatToTrace} || '_whatToTrace' } // "anonymous"; $self->newConf->{cfgAuthorIP} = $self->req->address; $self->newConf->{cfgDate} = time; From 2b51cf0c8d8ec6b6f5cd532c8cb9ca4dcf21bd7e Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Wed, 16 Jan 2019 11:09:52 +0100 Subject: [PATCH 09/10] Fix tsv call (#1574) --- .../lib/Lemonldap/NG/Manager/Conf/Tests.pm | 217 +++++++++--------- .../lib/Lemonldap/NG/Manager/Sessions.pm | 2 +- 2 files changed, 113 insertions(+), 106 deletions(-) diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm index b8b7479c7..3e534bc05 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm @@ -30,7 +30,8 @@ sub tests { portalIsInDomain => sub { return ( 1, - ( index( $conf->{portal}, $conf->{domain} ) > 0 + ( + index( $conf->{portal}, $conf->{domain} ) > 0 ? '' : "Portal seems not to be in the domain $conf->{domain}" ) @@ -42,7 +43,7 @@ sub tests { # Checking for ending slash $conf->{portal} .= '/' - unless ( $conf->{portal} =~ qr#/$# ); + unless ( $conf->{portal} =~ qr#/$# ); # Deleting trailing ending slash my $regex = qr#/+$#; @@ -60,10 +61,11 @@ sub tests { } return ( 1, - ( @pb + ( + @pb ? 'Virtual hosts ' - . join( ', ', @pb ) - . " are not in $conf->{domain} and cross-domain-authentication is not set" + . join( ', ', @pb ) + . " are not in $conf->{domain} and cross-domain-authentication is not set" : undef ) ); @@ -77,9 +79,9 @@ sub tests { } if (@pb) { return ( 0, - 'Virtual hosts ' - . join( ', ', @pb ) - . " contain a port, this is not allowed" ); + 'Virtual hosts ' + . join( ', ', @pb ) + . " contain a port, this is not allowed" ); } else { return 1; } }, @@ -92,9 +94,9 @@ sub tests { } if (@pb) { return ( 0, - 'Virtual hosts ' - . join( ', ', @pb ) - . " must be in lower case" ); + 'Virtual hosts ' + . join( ', ', @pb ) + . " must be in lower case" ); } else { return 1; } }, @@ -102,12 +104,12 @@ sub tests { # Check if "userDB" and "authentication" are consistent authAndUserDBConsistency => sub { foreach - my $type (qw(Facebook Google OpenID OpenIDConnect SAML WebID)) + my $type (qw(Facebook Google OpenID OpenIDConnect SAML WebID)) { return ( 0, - "\"$type\" can not be used as user database without using \"$type\" for authentication" - ) - if ($conf->{userDB} =~ /$type/ +"\"$type\" can not be used as user database without using \"$type\" for authentication" + ) + if ( $conf->{userDB} =~ /$type/ and $conf->{authentication} !~ /$type/ ); } return 1; @@ -117,29 +119,30 @@ sub tests { checkAttrAndMacros => sub { my @tmp; foreach my $k ( keys %$conf ) { - if ( $k - =~ /^(?:openIdSreg_(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)|whatToTrace)$/ - ) + if ( $k =~ +/^(?:openIdSreg_(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)|whatToTrace)$/ + ) { my $v = $conf->{$k}; $v =~ s/^$//; next if ( $v =~ /^_/ ); push @tmp, - $k - unless ( + $k + unless ( defined( $conf->{exportedVars}->{$v} - or defined( $conf->{macros}->{$v} ) + or defined( $conf->{macros}->{$v} ) ) - ); + ); } } return ( 1, - ( @tmp + ( + @tmp ? 'Values of parameter(s) "' - . join( ', ', @tmp ) - . '" are not defined in exported attributes or macros' + . join( ', ', @tmp ) + . '" are not defined in exported attributes or macros' : '' ) ); @@ -151,18 +154,18 @@ sub tests { if ( $conf->{userDB} =~ /^Google$/ ) { foreach my $k ( keys %{ $conf->{exportedVars} } ) { my $v = $conf->{exportedVars}->{$k}; - if ( $v !~ Lemonldap::NG::Common::Regexp::GOOGLEAXATTR() ) - { + if ( $v !~ Lemonldap::NG::Common::Regexp::GOOGLEAXATTR() ) { push @tmp, $v; } } } return ( 1, - ( @tmp + ( + @tmp ? 'Values of parameter(s) "' - . join( ', ', @tmp ) - . '" are not exported by Google' + . join( ', ', @tmp ) + . '" are not exported by Google' : '' ) ); @@ -174,8 +177,7 @@ sub tests { if ( $conf->{userDB} =~ /^OpenID$/ ) { foreach my $k ( keys %{ $conf->{exportedVars} } ) { my $v = $conf->{exportedVars}->{$k}; - if ( $v - !~ Lemonldap::NG::Common::Regexp::OPENIDSREGATTR() ) + if ( $v !~ Lemonldap::NG::Common::Regexp::OPENIDSREGATTR() ) { push @tmp, $v; } @@ -183,10 +185,11 @@ sub tests { } return ( 1, - ( @tmp + ( + @tmp ? 'Values of parameter(s) "' - . join( ', ', @tmp ) - . '" are not exported by OpenID SREG' + . join( ', ', @tmp ) + . '" are not exported by OpenID SREG' : '' ) ); @@ -195,40 +198,39 @@ sub tests { # Try to use Apache::Session module testApacheSession => sub { my ( $id, %h ); - my $gc = $Lemonldap::NG::Handler::PSGI::Main::tsv - ->{sessionStorageModule}; + my $gc = Lemonldap::NG::Handler::Main->tsv->{sessionStorageModule}; return 1 - if ( ( $gc and $gc eq $conf->{globalStorage} ) - or $conf->{globalStorage} - =~ /^Lemonldap::NG::Common::Apache::Session::/ ); + if ( ( $gc and $gc eq $conf->{globalStorage} ) + or $conf->{globalStorage} =~ + /^Lemonldap::NG::Common::Apache::Session::/ ); eval "use $conf->{globalStorage}"; return ( -1, "Unknown package $conf->{globalStorage}" ) if ($@); eval { tie %h, 'Lemonldap::NG::Common::Apache::Session', undef, - { + { %{ $conf->{globalStorageOptions} }, backend => $conf->{globalStorage} - }; + }; }; return ( -1, "Unable to create a session ($@)" ) - if ( $@ or not tied(%h) ); + if ( $@ or not tied(%h) ); eval { $h{a} = 1; $id = $h{_session_id} or return ( -1, 'No _session_id' ); untie(%h); tie %h, 'Lemonldap::NG::Common::Apache::Session', $id, - { + { %{ $conf->{globalStorageOptions} }, backend => $conf->{globalStorage} - }; + }; }; return ( -1, "Unable to insert data ($@)" ) if ($@); return ( -1, "Unable to recover data stored" ) - unless ( $h{a} == 1 ); + unless ( $h{a} == 1 ); eval { tied(%h)->delete; }; return ( -1, "Unable to delete session ($@)" ) if ($@); return ( -1, - 'All sessions may be lost and you must restart all your Apache servers' +'All sessions may be lost and you must restart all your Apache servers' ) if ( $gc and $conf->{globalStorage} ne $gc ); return 1; }, @@ -238,8 +240,9 @@ sub tests { my $cn = Lemonldap::NG::Handler::Main->tsv->{cookieName}; return ( 1, - ( $cn - and $cn ne $conf->{cookieName} + ( + $cn + and $cn ne $conf->{cookieName} ? 'Cookie name has changed, you must restart all your web servers' : () ) @@ -250,9 +253,10 @@ sub tests { cookieTTL => sub { return 1 unless ( defined $conf->{cookieExpiration} ); return ( 0, "Cookie TTL must be higher than one minute" ) - unless ( $conf->{cookieExpiration} == 0 || $conf->{cookieExpiration} > 60 ); + unless ( $conf->{cookieExpiration} == 0 + || $conf->{cookieExpiration} > 60 ); return ( 1, "Cookie TTL should be higher or equal than one hour" ) - unless ( $conf->{cookieExpiration} >= 3600 + unless ( $conf->{cookieExpiration} >= 3600 || $conf->{cookieExpiration} == 0 ); # Return @@ -263,7 +267,7 @@ sub tests { sessionTimeout => sub { return 1 unless ( defined $conf->{timeout} ); return ( -1, "Session timeout should be higher than ten minutes" ) - unless ( $conf->{timeout} > 600 + unless ( $conf->{timeout} > 600 || $conf->{timeout} == 0 ); # Return @@ -274,9 +278,9 @@ sub tests { sessionTimeoutActivity => sub { return 1 unless ( defined $conf->{timeoutActivity} ); return ( 0, - "Session activity timeout must be higher or equal than one minute" - ) - unless ( $conf->{timeoutActivity} > 59 +"Session activity timeout must be higher or equal than one minute" + ) + unless ( $conf->{timeoutActivity} > 59 || $conf->{timeoutActivity} == 0 ); # Return @@ -287,11 +291,11 @@ sub tests { timeoutActivityInterval => sub { return 1 unless ( defined $conf->{timeoutActivityInterval} ); return ( 0, - "Activity timeout interval must be lower than session activity timeout" - ) - if ($conf->{timeoutActivity} - and $conf->{timeoutActivity} - <= $conf->{timeoutActivityInterval} ); +"Activity timeout interval must be lower than session activity timeout" + ) + if ( $conf->{timeoutActivity} + and $conf->{timeoutActivity} <= + $conf->{timeoutActivityInterval} ); # Return return 1; @@ -301,7 +305,8 @@ sub tests { managerProtection => sub { return ( 1, - ( $conf->{cfgAuthor} eq 'anonymous' + ( + $conf->{cfgAuthor} eq 'anonymous' ? 'Your manager seems to be unprotected' : '' ) @@ -317,21 +322,21 @@ sub tests { # Use SMTP eval "use Net::SMTP"; return ( 1, "Net::SMTP module is required to use SMTP server" ) - if ($@); + if ($@); # Create SMTP object my $smtp = Net::SMTP->new( $conf->{SMTPServer}, Timeout => 5 ); return ( 1, "SMTP connection to " . $conf->{SMTPServer} . " failed" ) - unless ($smtp); + unless ($smtp); # Skip other tests if no authentication return 1 - unless ( $conf->{SMTPAuthUser} and $conf->{SMTPAuthPass} ); + unless ( $conf->{SMTPAuthUser} and $conf->{SMTPAuthPass} ); # Try authentication return ( 1, "SMTP authentication failed" ) - unless $smtp->auth( $conf->{SMTPAuthUser}, + unless $smtp->auth( $conf->{SMTPAuthUser}, $conf->{SMTPAuthPass} ); # Return @@ -341,14 +346,15 @@ sub tests { # SAML entity ID must be uniq samlIDPEntityIdUniqueness => sub { return 1 - unless ( $conf->{samlIDPMetaDataXML} + unless ( $conf->{samlIDPMetaDataXML} and %{ $conf->{samlIDPMetaDataXML} } ); my @msg; my $res = 1; my %entityIds; foreach my $idpId ( keys %{ $conf->{samlIDPMetaDataXML} } ) { - unless ( $conf->{samlIDPMetaDataXML}->{$idpId} - ->{samlIDPMetaDataXML} =~ /entityID=(['"])(.+?)\1/si ) + unless ( + $conf->{samlIDPMetaDataXML}->{$idpId}->{samlIDPMetaDataXML} + =~ /entityID=(['"])(.+?)\1/si ) { push @msg, "$idpId SAML metadata has no EntityID"; $res = 0; @@ -357,7 +363,7 @@ sub tests { my $eid = $2; if ( defined $entityIds{$eid} ) { push @msg, - "$idpId and $entityIds{$eid} have the same SAML EntityID"; + "$idpId and $entityIds{$eid} have the same SAML EntityID"; $res = 0; next; } @@ -367,15 +373,15 @@ sub tests { }, samlSPEntityIdUniqueness => sub { return 1 - unless ( $conf->{samlSPMetaDataXML} + unless ( $conf->{samlSPMetaDataXML} and %{ $conf->{samlSPMetaDataXML} } ); my @msg; my $res = 1; my %entityIds; foreach my $spId ( keys %{ $conf->{samlSPMetaDataXML} } ) { unless ( - $conf->{samlSPMetaDataXML}->{$spId}->{samlSPMetaDataXML} - =~ /entityID=(['"])(.+?)\1/si ) + $conf->{samlSPMetaDataXML}->{$spId}->{samlSPMetaDataXML} =~ + /entityID=(['"])(.+?)\1/si ) { push @msg, "$spId SAML metadata has no EntityID"; $res = 0; @@ -384,7 +390,7 @@ sub tests { my $eid = $2; if ( defined $entityIds{$eid} ) { push @msg, - "$spId and $entityIds{$eid} have the same SAML EntityID"; + "$spId and $entityIds{$eid} have the same SAML EntityID"; $res = 0; next; } @@ -398,7 +404,7 @@ sub tests { return 1 unless ( $conf->{authentication} eq 'Combination' ); require Lemonldap::NG::Common::Combination::Parser; return ( 0, 'No module declared for combination' ) - unless ( $conf->{combModules} and %{ $conf->{combModules} } ); + unless ( $conf->{combModules} and %{ $conf->{combModules} } ); my $moduleList; foreach my $md ( keys %{ $conf->{combModules} } ) { my $entry = $conf->{combModules}->{$md}; @@ -409,8 +415,8 @@ sub tests { ); } eval { - Lemonldap::NG::Common::Combination::Parser->parse( - $moduleList, $conf->{combination} ); + Lemonldap::NG::Common::Combination::Parser->parse( $moduleList, + $conf->{combination} ); }; return ( 0, $@ ) if ($@); @@ -422,9 +428,9 @@ sub tests { combinationParameters => sub { return 1 unless ( $conf->{authentication} eq "Combination" ); return ( 0, "Combination rule must be defined" ) - unless ( $conf->{combination} ); + unless ( $conf->{combination} ); return ( 0, 'userDB must be set to "Same" to enable Combination' ) - unless ( $conf->{userDB} eq "Same" ); + unless ( $conf->{userDB} eq "Same" ); # Return return 1; @@ -447,7 +453,7 @@ sub tests { eval "use Convert::Base32"; return ( 1, "Convert::Base32 module is required to enable TOTP" ) - if ($@); + if ($@); } # Use U2F @@ -456,7 +462,7 @@ sub tests { { eval "use Crypt::U2F::Server::Simple"; return ( 1, - "Crypt::U2F::Server::Simple module is required to enable U2F" +"Crypt::U2F::Server::Simple module is required to enable U2F" ) if ($@); } @@ -464,7 +470,7 @@ sub tests { if ( $conf->{yubikey2fActivation} ) { eval "use Auth::Yubikey_WebClient"; return ( 1, - "Auth::Yubikey_WebClient module is required to enable Yubikey" +"Auth::Yubikey_WebClient module is required to enable Yubikey" ) if ($@); } @@ -478,7 +484,7 @@ sub tests { my $w = ""; foreach ( 'totp', 'u' ) { $w .= uc($_) . "2F is activated twice \n" - if ( $conf->{ $_ . '2fActivation' } eq '1' ); + if ( $conf->{ $_ . '2fActivation' } eq '1' ); } return ( 1, ( $w ? $w : () ) ); }, @@ -489,8 +495,10 @@ sub tests { return 1 unless ( defined $conf->{totp2fDigits} ); return ( 1, - ( ( $conf->{totp2fDigits} == 6 - or $conf->{totp2fDigits} == 8 + ( + ( + $conf->{totp2fDigits} == 6 + or $conf->{totp2fDigits} == 8 ) ? '' : 'TOTP should be 6 or 8 digits long' @@ -502,9 +510,9 @@ sub tests { totp2fParams => sub { return 1 unless ( $conf->{totp2fActivation} ); return ( 0, 'TOTP range must be defined' ) - unless ( $conf->{totp2fRange} ); + unless ( $conf->{totp2fRange} ); return ( 1, "TOTP interval should be higher than 10s" ) - unless ( $conf->{totp2fInterval} > 10 ); + unless ( $conf->{totp2fInterval} > 10 ); # Return return 1; @@ -515,11 +523,12 @@ sub tests { yubikey2fParams => sub { return 1 unless ( $conf->{yubikey2fActivation} ); return ( 0, "Yubikey client ID and secret key must be set" ) - unless ( defined $conf->{yubikey2fSecretKey} + unless ( defined $conf->{yubikey2fSecretKey} && defined $conf->{yubikey2fClientID} ); return ( 1, - ( ( $conf->{yubikey2fPublicIDSize} == 12 ) + ( + ( $conf->{yubikey2fPublicIDSize} == 12 ) ? '' : 'Yubikey public ID size should be 12 digits long' ) @@ -530,7 +539,7 @@ sub tests { rest2fVerifyUrl => sub { return 1 unless ( $conf->{rest2fActivation} ); return ( 0, "REST 2F Verify URL must be set" ) - unless ( defined $conf->{rest2fVerifyUrl} ); + unless ( defined $conf->{rest2fVerifyUrl} ); # Return return 1; @@ -544,16 +553,15 @@ sub tests { my $ok = 0; foreach (qw(u totp yubikey)) { $ok ||= $conf->{ $_ . '2fActivation' } - && $conf->{ $_ . '2fSelfRegistration' }; + && $conf->{ $_ . '2fSelfRegistration' }; last if ($ok); } $ok ||= $conf->{'utotp2fActivation'} - && ( $conf->{'u2fSelfRegistration'} + && ( $conf->{'u2fSelfRegistration'} || $conf->{'totp2fSelfRegistration'} ); - $msg - = "A self registrable module should be enabled to require 2FA" - unless ($ok); + $msg = "A self registrable module should be enabled to require 2FA" + unless ($ok); return ( 1, $msg ); }, @@ -562,7 +570,7 @@ sub tests { ext2fCommands => sub { return 1 unless ( $conf->{ext2fActivation} ); return ( 0, "External 2F Send or Validate command must be set" ) - unless ( defined $conf->{ext2FSendCommand} + unless ( defined $conf->{ext2FSendCommand} && defined $conf->{ext2FValidateCommand} ); # Return @@ -573,9 +581,9 @@ sub tests { formTimeout => sub { return 1 unless ( defined $conf->{formTimeout} ); return ( 0, "XSRF form token TTL must be higher than 30s" ) - unless ( $conf->{formTimeout} > 30 ); + unless ( $conf->{formTimeout} > 30 ); return ( 1, "XSRF form token TTL should not be higher than 2mn" ) - if ( $conf->{formTimeout} > 120 ); + if ( $conf->{formTimeout} > 120 ); # Return return 1; @@ -584,9 +592,8 @@ sub tests { # Warn if number of password reset retries is null passwordResetRetries => sub { return 1 unless ( $conf->{portalDisplayResetPassword} ); - return ( 1, - "Number of reset password retries should not be null" ) - unless ( $conf->{passwordResetAllowedRetries} ); + return ( 1, "Number of reset password retries should not be null" ) + unless ( $conf->{passwordResetAllowedRetries} ); # Return return 1; @@ -596,10 +603,10 @@ sub tests { bruteForceProtection => sub { return 1 unless ( $conf->{bruteForceProtection} ); return ( 1, - '"History" plugin is required to enable "BruteForceProtection" plugin' +'"History" plugin is required to enable "BruteForceProtection" plugin' ) unless ( $conf->{loginHistoryEnabled} ); return ( 1, - 'Number of failed logins must be higher than 2 to enable "BruteForceProtection" plugin' +'Number of failed logins must be higher than 2 to enable "BruteForceProtection" plugin' ) unless ( $conf->{failedLoginNumber} > 2 ); # Return @@ -610,9 +617,9 @@ sub tests { checkMailResetSecurity => sub { return 1 unless ( $conf->{portalDisplayResetPassword} ); return ( -1, - '"passwordMailReset" plugin is enabled without CSRF Token neither Captcha required !!!' - ) - unless ( $conf->{requireToken} +'"passwordMailReset" plugin is enabled without CSRF Token neither Captcha required !!!' + ) + unless ( $conf->{requireToken} or $conf->{captcha_mail_enabled} ); # Return diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Sessions.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Sessions.pm index f08133d7d..06e762f48 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Sessions.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Sessions.pm @@ -103,7 +103,7 @@ sub sessions { # Case 2: list of sessions - my $whatToTrace = Lemonldap::NG::Handler::PSGI::Main->tsv->{whatToTrace}; + my $whatToTrace = Lemonldap::NG::Handler::Main->tsv->{whatToTrace}; # 2.1 Get fields to require my @fields = ( '_httpSessionType', $self->{ipField}, $whatToTrace ); From 54491c667a32f0459e2594f0a369c48c3cd6bc43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Wed, 16 Jan 2019 12:31:42 +0100 Subject: [PATCH 10/10] Use main Handler version in server signature (#1618) --- .../lib/Lemonldap/NG/Handler/Main/Init.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 018ddbe6e..ef492a9f0 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Init.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Init.pm @@ -1,6 +1,6 @@ package Lemonldap::NG::Handler::Main::Init; -our $VERSION = '2.0.0'; +our $VERSION = '2.0.2'; package Lemonldap::NG::Handler::Main; @@ -66,7 +66,9 @@ sub logLevelInit { # adapt server signature sub serverSignatureInit { my $class = shift; - $class->setServerSignature("Lemonldap::NG/$VERSION"); + require Lemonldap::NG::Handler; + my $version = $Lemonldap::NG::Handler::VERSION; + $class->setServerSignature("Lemonldap::NG/$version"); } ## @ifn protected void statusInit() @@ -107,7 +109,7 @@ sub statusInit { exec $perl_exec, '-MLemonldap::NG::Handler::Lib::Status', # Insert @INC in Perl path - map( { "-I$_" } @INC ), + map( {"-I$_"} @INC ), # Command to launch '-e', '&Lemonldap::NG::Handler::Lib::Status::run()',