Improve Protractor e2e tests (#1600)
This commit is contained in:
parent
681421263e
commit
840c2f259b
|
@ -0,0 +1,47 @@
|
|||
#End 2 End Testing (Protractor)
|
||||
To run the end-2-end tests against the application you use [Protractor](https://github.com/angular/protractor).
|
||||
|
||||
## Testing with Protractor
|
||||
|
||||
As a one-time setup, download webdriver.
|
||||
```
|
||||
npm run update-webdriver
|
||||
```
|
||||
|
||||
Start the Protractor test runner using the e2e configuration:
|
||||
|
||||
```
|
||||
make e2e_test
|
||||
```
|
||||
|
||||
## Devel tips
|
||||
|
||||
{
|
||||
locator_: {
|
||||
using: 'css selector',
|
||||
value: '[ng-click="getLanguage(lang)"]'
|
||||
},
|
||||
parentElementFinder_: null,
|
||||
opt_actionResult_: {
|
||||
then: [Function: then],
|
||||
cancel: [Function: cancel],
|
||||
isPending: [Function: isPending]
|
||||
},
|
||||
opt_index_: 1,
|
||||
click: [Function],
|
||||
sendKeys: [Function],
|
||||
getTagName: [Function],
|
||||
getCssValue: [Function],
|
||||
getAttribute: [Function],
|
||||
getText: [Function],
|
||||
getSize: [Function],
|
||||
getLocation: [Function],
|
||||
isEnabled: [Function],
|
||||
isSelected: [Function],
|
||||
submit: [Function],
|
||||
clear: [Function],
|
||||
isDisplayed: [Function],
|
||||
getOuterHtml: [Function],
|
||||
getInnerHtml: [Function],
|
||||
toWireValue: [Function]
|
||||
}
|
|
@ -57,6 +57,16 @@
|
|||
},
|
||||
"type": "application"
|
||||
},
|
||||
"0008-app": {
|
||||
"options": {
|
||||
"description": "Explore WebSSO 2FA sessions",
|
||||
"display": "auto",
|
||||
"logo": "database.png",
|
||||
"name": "2FA Sessions explorer",
|
||||
"uri": "http://manager.example.com:__port__/2ndfa.html"
|
||||
},
|
||||
"type": "application"
|
||||
},
|
||||
"type": "category"
|
||||
},
|
||||
"0008-cat": {
|
||||
|
|
|
@ -4,77 +4,11 @@
|
|||
|
||||
describe('00 Lemonldap::NG', function() {
|
||||
describe('Auth mechanism', function() {
|
||||
it('Portal should display 11 lang flags', function() {
|
||||
browser.driver.get('http://auth.example.com:' + process.env.TESTWEBSERVERPORT + '/');
|
||||
browser.driver.findElements(by.className('langicon')).then(function(elems) {
|
||||
expect(elems.length).toEqual(11);
|
||||
});
|
||||
browser.driver.findElement(by.xpath("//img[@title='en']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="9"]')).getText()).toEqual('Authentication required');
|
||||
expect(browser.driver.findElement(by.css('[trspan="createAccount"]')).getText()).toEqual('Create an account');
|
||||
browser.driver.findElement(by.xpath("//img[@title='it']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="9"]')).getText()).toEqual('Autenticazione necessaria');
|
||||
expect(browser.driver.findElement(by.css('[trspan="createAccount"]')).getText()).toEqual('Crea un account');
|
||||
browser.driver.findElement(by.xpath("//img[@title='fr']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trspan="createAccount"]')).getText()).toEqual('Créer un compte');
|
||||
});
|
||||
it('should want to crete an account', function() {
|
||||
browser.driver.findElement(by.css('[trspan="createAccount"]')).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="78"]')).getText()).toEqual('Merci de saisir vos informations');
|
||||
|
||||
// A four inputs form + one captcha
|
||||
browser.driver.findElements(by.className('input-group')).then(function(elems) {
|
||||
expect(elems.length).toEqual(4);
|
||||
});
|
||||
browser.driver.findElements(by.className('img-thumbnail')).then(function(elems) {
|
||||
expect(elems.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
it('should want to authenticate with history', function() {
|
||||
expect(browser.driver.findElement(by.css('[trspan="back2Portal"]')).getText()).toEqual('Retourner au portail');
|
||||
browser.driver.findElement(by.css('[trspan="back2Portal"]')).click();
|
||||
|
||||
// Failed login attempt
|
||||
browser.driver.findElement(by.xpath("//input[@name='user']")).sendKeys('dwho');
|
||||
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('ohwd');
|
||||
browser.driver.findElement(by.xpath("//input[@name='checkLogins']")).click();
|
||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="5"]')).getText()).toEqual('Mot de passe ou identifiant incorrect');
|
||||
browser.driver.findElement(by.css('[trspan="goToPortal"]')).click();
|
||||
|
||||
it('should want to authenticate', function() {
|
||||
browser.driver.get('http://auth.example.com:' + process.env.TESTWEBSERVERPORT + '/');
|
||||
// Login attempt
|
||||
browser.driver.findElement(by.xpath("//input[@name='user']")).sendKeys('dwho');
|
||||
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('dwho');
|
||||
browser.driver.findElement(by.xpath("//input[@name='checkLogins']")).click();
|
||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||
browser.driver.findElement(by.xpath("//img[@title='de']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trspan="info"]')).getText()).toEqual("Information");
|
||||
browser.driver.findElements(by.xpath('//table/tbody/tr')).then(function(elems) {
|
||||
expect(elems.length).toEqual(2);
|
||||
});
|
||||
|
||||
// Expect history with one login and one failed login
|
||||
browser.driver.findElements(by.xpath('//form/div/div/h3')).then(function(elems) {
|
||||
expect(elems.length).toEqual(3);
|
||||
expect(elems[0].getText()).toEqual('Information');
|
||||
expect(elems[1].getText()).toEqual('Letzte Anmeldungen');
|
||||
expect(elems[2].getText()).toEqual('Letzte fehlgeschlagene Anmeldungen');
|
||||
});
|
||||
browser.driver.findElements(by.xpath('//table/thead/tr/th')).then(function(elems) {
|
||||
expect(elems.length).toEqual(5);
|
||||
expect(elems[0].getText()).toEqual('Datum');
|
||||
expect(elems[2].getText()).toEqual('Datum');
|
||||
expect(elems[4].getText()).toEqual('Fehlermeldung');
|
||||
});
|
||||
browser.driver.findElements(by.xpath('//table/tbody/tr/td')).then(function(elems) {
|
||||
expect(elems.length).toEqual(5);
|
||||
expect(elems[1].getText()).toEqual('127.0.0.1');
|
||||
expect(elems[3].getText()).toEqual('127.0.0.1');
|
||||
});
|
||||
expect(browser.driver.findElement(by.css('[trspan="PE5"]')).getText()).toEqual('Benutzername oder Passwort nicht korrekt');
|
||||
expect(browser.driver.findElement(by.id('timer')).getText()).toMatch(/^Du wirst in \d{2} Sekunden umgeleitet$/);
|
||||
browser.driver.findElement(by.xpath("//button[@type='reset']")).click();
|
||||
expect(browser.driver.findElement(by.id('timer')).isDisplayed()).toEqual(false);
|
||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
|
||||
|
||||
describe('01 Lemonldap::NG Manager', function() {
|
||||
describe('Tree display', function() {
|
||||
describe('Tree display -> General Parameters', function() {
|
||||
it('Main => should display 12 main nodes', function() {
|
||||
browser.get('/');
|
||||
expect(element.all(by.repeater('node in data track by node.id')).count()).toEqual(12);
|
||||
|
@ -12,7 +12,7 @@ describe('01 Lemonldap::NG Manager', function() {
|
|||
element(by.id('a-generalParameters')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(10);
|
||||
});
|
||||
// ** General Parameters **
|
||||
|
||||
// Portal
|
||||
it('General Parameters > Portal -> Append 4 sub nodes', function() {
|
||||
element(by.id('a-portalParams')).click();
|
||||
|
@ -30,25 +30,25 @@ describe('01 Lemonldap::NG Manager', function() {
|
|||
element(by.id('a-portalModules')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(21);
|
||||
});
|
||||
it('General Parameters > Portal > Menu > Cat. and Apps. => Append 10 sub nodes', function() {
|
||||
it('General Parameters > Portal > Menu > Cat. and Apps. => Append 11 sub nodes', function() {
|
||||
element(by.id('a-applicationList')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(31);
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(32);
|
||||
});
|
||||
it('General Parameters > Portal > Customization => Append 8 sub nodes', function() {
|
||||
element(by.id('a-portalCustomization')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(39);
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(40);
|
||||
});
|
||||
it('General Parameters > Portal > Customization > Buttons => Append 4 sub nodes', function() {
|
||||
element(by.id('a-portalButtons')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(43);
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(44);
|
||||
});
|
||||
it('General Parameters > Portal > Customization > Password Management => Append 3 sub nodes', function() {
|
||||
element(by.id('a-passwordManagement')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(46);
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(47);
|
||||
});
|
||||
it('General Parameters > Portal > Customization > Other => Append 6 sub nodes', function() {
|
||||
element(by.id('a-portalOther')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(52);
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(53);
|
||||
});
|
||||
// Authentication Parameters
|
||||
it('Main => should display 12 main nodes', function() {
|
||||
|
@ -210,28 +210,5 @@ describe('01 Lemonldap::NG Manager', function() {
|
|||
expect(element.all(by.xpath('//tbody/tr')).count()).toEqual(2);
|
||||
expect(element.all(by.xpath('//tbody/tr/td/input')).count()).toEqual(4);
|
||||
});
|
||||
|
||||
// ** Variables **
|
||||
it('Main => should display 12 main nodes', function() {
|
||||
browser.get('/');
|
||||
expect(element.all(by.repeater('node in data track by node.id')).count()).toEqual(12);
|
||||
});
|
||||
it('Variables should display 3 sub nodes', function() {
|
||||
element(by.id('a-variables')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(3);
|
||||
});
|
||||
|
||||
// ** Virtual Hosts
|
||||
it('should find a rule', function() {
|
||||
browser.get('/#/confs/1');
|
||||
var vhs = element(by.id('a-virtualHosts'));
|
||||
vhs.click();
|
||||
var vh = element(by.id('a-virtualHosts/manager.example.com'));
|
||||
vh.click();
|
||||
var r = element(by.id('a-virtualHosts/manager.example.com/locationRules'));
|
||||
r.click();
|
||||
var def = element.all(by.id("t-virtualHosts/manager.example.com/locationRules/1"));
|
||||
expect(def.count()).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
|
||||
|
||||
describe('01 Lemonldap::NG Manager', function() {
|
||||
describe('Tree display -> Variables', function() {
|
||||
it('Main => should display 12 main nodes', function() {
|
||||
browser.get('/');
|
||||
expect(element.all(by.repeater('node in data track by node.id')).count()).toEqual(12);
|
||||
});
|
||||
it('Variables should display 3 sub nodes', function() {
|
||||
element(by.id('a-variables')).click();
|
||||
expect(element.all(by.repeater('node in node.nodes track by node.id')).count()).toEqual(3);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
|
||||
|
||||
describe('01 Lemonldap::NG Manager', function() {
|
||||
describe('Tree display', function() {
|
||||
it('Main => should display 12 main nodes', function() {
|
||||
browser.get('/');
|
||||
expect(element.all(by.repeater('node in data track by node.id')).count()).toEqual(12);
|
||||
});
|
||||
it('should find a rule', function() {
|
||||
browser.get('/#/confs/1');
|
||||
var vhs = element(by.id('a-virtualHosts'));
|
||||
vhs.click();
|
||||
var vh = element(by.id('a-virtualHosts/manager.example.com'));
|
||||
vh.click();
|
||||
var r = element(by.id('a-virtualHosts/manager.example.com/locationRules'));
|
||||
r.click();
|
||||
var def = element.all(by.id("t-virtualHosts/manager.example.com/locationRules/1"));
|
||||
expect(def.count()).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
'use strict';
|
||||
|
||||
/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
|
||||
|
||||
describe('00 Lemonldap::NG', function() {
|
||||
describe('Auth mechanism', function() {
|
||||
it('Portal should display 11 lang flags', function() {
|
||||
browser.driver.get('http://auth.example.com:' + process.env.TESTWEBSERVERPORT + '/');
|
||||
browser.driver.findElements(by.className('langicon')).then(function(elems) {
|
||||
expect(elems.length).toEqual(11);
|
||||
});
|
||||
browser.driver.findElement(by.xpath("//img[@title='en']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="9"]')).getText()).toEqual('Authentication required');
|
||||
expect(browser.driver.findElement(by.css('[trspan="createAccount"]')).getText()).toEqual('Create an account');
|
||||
browser.driver.findElement(by.xpath("//img[@title='it']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="9"]')).getText()).toEqual('Autenticazione necessaria');
|
||||
expect(browser.driver.findElement(by.css('[trspan="createAccount"]')).getText()).toEqual('Crea un account');
|
||||
browser.driver.findElement(by.xpath("//img[@title='fr']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trspan="createAccount"]')).getText()).toEqual('Créer un compte');
|
||||
});
|
||||
it('should want to crete an account', function() {
|
||||
browser.driver.findElement(by.css('[trspan="createAccount"]')).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="78"]')).getText()).toEqual('Merci de saisir vos informations');
|
||||
|
||||
// A four inputs form + one captcha
|
||||
browser.driver.findElements(by.className('input-group')).then(function(elems) {
|
||||
expect(elems.length).toEqual(4);
|
||||
});
|
||||
browser.driver.findElements(by.className('img-thumbnail')).then(function(elems) {
|
||||
expect(elems.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
it('should want to authenticate with history', function() {
|
||||
expect(browser.driver.findElement(by.css('[trspan="back2Portal"]')).getText()).toEqual('Retourner au portail');
|
||||
browser.driver.findElement(by.css('[trspan="back2Portal"]')).click();
|
||||
|
||||
// Failed login attempt
|
||||
browser.driver.findElement(by.xpath("//input[@name='user']")).sendKeys('dwho');
|
||||
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('ohwd');
|
||||
browser.driver.findElement(by.xpath("//input[@name='checkLogins']")).click();
|
||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trmsg="5"]')).getText()).toEqual('Mot de passe ou identifiant incorrect');
|
||||
browser.driver.findElement(by.css('[trspan="goToPortal"]')).click();
|
||||
|
||||
// Login attempt
|
||||
browser.driver.findElement(by.xpath("//input[@name='user']")).sendKeys('dwho');
|
||||
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('dwho');
|
||||
browser.driver.findElement(by.xpath("//input[@name='checkLogins']")).click();
|
||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||
browser.driver.findElement(by.xpath("//img[@title='de']")).click();
|
||||
expect(browser.driver.findElement(by.css('[trspan="info"]')).getText()).toEqual("Information");
|
||||
browser.driver.findElements(by.xpath('//table/tbody/tr')).then(function(elems) {
|
||||
expect(elems.length).toEqual(5);
|
||||
});
|
||||
|
||||
// Expect history with one login and one failed login
|
||||
browser.driver.findElements(by.xpath('//form/div/div/h3')).then(function(elems) {
|
||||
expect(elems.length).toEqual(3);
|
||||
expect(elems[0].getText()).toEqual('Information');
|
||||
expect(elems[1].getText()).toEqual('Letzte Anmeldungen');
|
||||
expect(elems[2].getText()).toEqual('Letzte fehlgeschlagene Anmeldungen');
|
||||
});
|
||||
browser.driver.findElements(by.xpath('//table/thead/tr/th')).then(function(elems) {
|
||||
expect(elems.length).toEqual(5);
|
||||
expect(elems[0].getText()).toEqual('Datum');
|
||||
expect(elems[2].getText()).toEqual('Datum');
|
||||
expect(elems[4].getText()).toEqual('Fehlermeldung');
|
||||
});
|
||||
browser.driver.findElements(by.xpath('//table/tbody/tr/td')).then(function(elems) {
|
||||
expect(elems.length).toEqual(11);
|
||||
expect(elems[1].getText()).toEqual('127.0.0.1');
|
||||
expect(elems[3].getText()).toEqual('127.0.0.1');
|
||||
});
|
||||
browser.sleep(5000);
|
||||
expect(browser.driver.findElement(by.css('[trspan="PE5"]')).getText()).toEqual('Benutzername oder Passwort nicht korrekt');
|
||||
expect(browser.driver.findElement(by.id('timer')).getText()).toMatch(/^Du wirst in \d{2} Sekunden umgeleitet$/);
|
||||
browser.driver.findElement(by.xpath("//button[@type='reset']")).click();
|
||||
expect(browser.driver.findElement(by.id('timer')).isDisplayed()).toEqual(false);
|
||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
|
||||
|
||||
describe('99 Lemonldap::NG auth mechanism', function() {
|
||||
|
||||
it('should allow logout', function() {
|
||||
browser.driver.get('http://auth.example.com:' + process.env.TESTWEBSERVERPORT + '/?logout=1');
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
#End 2 End Testing (Protractor)
|
||||
To run the end-2-end tests against the application you use [Protractor](https://github.com/angular/protractor).
|
||||
|
||||
## Testing with Protractor
|
||||
|
||||
As a one-time setup, download webdriver.
|
||||
```
|
||||
npm run update-webdriver
|
||||
```
|
||||
|
||||
Start the Protractor test runner using the e2e configuration:
|
||||
|
||||
```
|
||||
make e2e_test
|
||||
```
|
||||
|
||||
## Devel tips
|
||||
|
||||
{
|
||||
locator_: {
|
||||
using: 'css selector',
|
||||
value: '[ng-click="getLanguage(lang)"]'
|
||||
},
|
||||
parentElementFinder_: null,
|
||||
opt_actionResult_: {
|
||||
then: [Function: then],
|
||||
cancel: [Function: cancel],
|
||||
isPending: [Function: isPending]
|
||||
},
|
||||
opt_index_: 1,
|
||||
click: [Function],
|
||||
sendKeys: [Function],
|
||||
getTagName: [Function],
|
||||
getCssValue: [Function],
|
||||
getAttribute: [Function],
|
||||
getText: [Function],
|
||||
getSize: [Function],
|
||||
getLocation: [Function],
|
||||
isEnabled: [Function],
|
||||
isSelected: [Function],
|
||||
submit: [Function],
|
||||
clear: [Function],
|
||||
isDisplayed: [Function],
|
||||
getOuterHtml: [Function],
|
||||
getInnerHtml: [Function],
|
||||
toWireValue: [Function]
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
|
||||
specs: ['manager/*.js', 'handler/*.js'],
|
||||
specs: ['handler/*.js', 'portal/*.js', 'manager/*.js' ],
|
||||
//specs: ['manager/*.js'],
|
||||
|
||||
|
||||
//specs: ['manager/00-auth.js', 'manager/01-tree.js'],
|
||||
capabilities: {
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
|
|
|
@ -6,32 +6,32 @@ use Mouse;
|
|||
use POSIX qw(strftime);
|
||||
use Lemonldap::NG::Common::FormEncode;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_BADCREDENTIALS
|
||||
PE_BADMAILTOKEN
|
||||
PE_CAPTCHAEMPTY
|
||||
PE_CAPTCHAERROR
|
||||
PE_MAILCONFIRMATION_ALREADY_SENT
|
||||
PE_MAILCONFIRMOK
|
||||
PE_MAILERROR
|
||||
PE_MAILFIRSTACCESS
|
||||
PE_MAILFORMEMPTY
|
||||
PE_MAILNOTFOUND
|
||||
PE_MAILOK
|
||||
PE_MALFORMEDUSER
|
||||
PE_NOTOKEN
|
||||
PE_OK
|
||||
PE_PASSWORDFIRSTACCESS
|
||||
PE_PASSWORDFORMEMPTY
|
||||
PE_PASSWORD_MISMATCH
|
||||
PE_PASSWORD_OK
|
||||
PE_TOKENEXPIRED
|
||||
PE_USERNOTFOUND
|
||||
PE_BADCREDENTIALS
|
||||
PE_BADMAILTOKEN
|
||||
PE_CAPTCHAEMPTY
|
||||
PE_CAPTCHAERROR
|
||||
PE_MAILCONFIRMATION_ALREADY_SENT
|
||||
PE_MAILCONFIRMOK
|
||||
PE_MAILERROR
|
||||
PE_MAILFIRSTACCESS
|
||||
PE_MAILFORMEMPTY
|
||||
PE_MAILNOTFOUND
|
||||
PE_MAILOK
|
||||
PE_MALFORMEDUSER
|
||||
PE_NOTOKEN
|
||||
PE_OK
|
||||
PE_PASSWORDFIRSTACCESS
|
||||
PE_PASSWORDFORMEMPTY
|
||||
PE_PASSWORD_MISMATCH
|
||||
PE_PASSWORD_OK
|
||||
PE_TOKENEXPIRED
|
||||
PE_USERNOTFOUND
|
||||
);
|
||||
|
||||
our $VERSION = '2.0.1';
|
||||
|
||||
extends 'Lemonldap::NG::Portal::Main::Plugin',
|
||||
'Lemonldap::NG::Portal::Lib::SMTP';
|
||||
'Lemonldap::NG::Portal::Lib::SMTP';
|
||||
|
||||
# PROPERTIES
|
||||
|
||||
|
@ -41,8 +41,8 @@ has ott => (
|
|||
is => 'rw',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
my $ott =
|
||||
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
|
||||
my $ott = $_[0]->{p}
|
||||
->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
|
||||
$ott->timeout( $_[0]->conf->{formTimeout} );
|
||||
return $ott;
|
||||
}
|
||||
|
@ -87,12 +87,11 @@ sub _reset {
|
|||
my ( $mailToken, $newPwd, $confirmPwd, %tplPrms );
|
||||
|
||||
# PASSWORD CHANGE FORM => changePwd()
|
||||
if (
|
||||
$req->method =~ /^POST$/i
|
||||
if ($req->method =~ /^POST$/i
|
||||
and ( $req->param('newpassword')
|
||||
or $req->param('confirmpassword')
|
||||
or $req->param('reset') )
|
||||
)
|
||||
)
|
||||
{
|
||||
return $self->changePwd($req);
|
||||
}
|
||||
|
@ -109,7 +108,8 @@ sub _reset {
|
|||
|
||||
# OTHER FORMS
|
||||
if ($mailToken) {
|
||||
$self->logger->debug( "Token given for password reset: " . $mailToken );
|
||||
$self->logger->debug(
|
||||
"Token given for password reset: " . $mailToken );
|
||||
|
||||
# Check if token is valid
|
||||
my $mailSession = $self->p->getApacheSession($mailToken);
|
||||
|
@ -119,8 +119,8 @@ sub _reset {
|
|||
}
|
||||
|
||||
$req->{user} = $mailSession->data->{user};
|
||||
$req->data->{mailAddress} =
|
||||
$mailSession->data->{ $self->conf->{mailSessionKey} };
|
||||
$req->data->{mailAddress}
|
||||
= $mailSession->data->{ $self->conf->{mailSessionKey} };
|
||||
$self->logger->debug( 'User associated to: ' . $req->{user} );
|
||||
|
||||
# Restore pdata if any
|
||||
|
@ -136,22 +136,24 @@ sub _reset {
|
|||
$req->{user} = $req->param('mail');
|
||||
|
||||
# Check if token exists
|
||||
my $token;
|
||||
if ( $self->conf->{requireToken} or $self->captcha ) {
|
||||
$token = $req->param('token');
|
||||
unless ($token) {
|
||||
$self->setSecurity($req);
|
||||
$self->userLogger->warn('Reset try without token');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
#my $token;
|
||||
#if ( $self->conf->{requireToken} or $self->captcha ) {
|
||||
my $token = $req->param('token');
|
||||
unless ($token) {
|
||||
$self->setSecurity($req);
|
||||
$self->userLogger->warn('Reset try without token');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
|
||||
# }
|
||||
|
||||
# Captcha for register form
|
||||
if ( $self->captcha ) {
|
||||
my $captcha = $req->param('captcha');
|
||||
|
||||
unless ($captcha) {
|
||||
$self->userLogger->notice('Reset try with captcha not filled');
|
||||
$self->userLogger->notice(
|
||||
'Reset try with captcha not filled');
|
||||
|
||||
# Set captcha or token
|
||||
$self->setSecurity($req);
|
||||
|
@ -168,10 +170,11 @@ sub _reset {
|
|||
}
|
||||
$self->logger->debug("Captcha code verified");
|
||||
}
|
||||
elsif ( $self->conf->{requireToken} ) {
|
||||
else {
|
||||
unless ( $self->ott->getToken($token) ) {
|
||||
$self->setSecurity($req);
|
||||
$self->userLogger->warn('Reset try with expired/bad token');
|
||||
$self->userLogger->warn(
|
||||
'Reset try with expired or bad token');
|
||||
return PE_TOKENEXPIRED;
|
||||
}
|
||||
}
|
||||
|
@ -183,8 +186,7 @@ sub _reset {
|
|||
|
||||
# Search user in database
|
||||
$req->steps(
|
||||
[
|
||||
'getUser', 'setSessionInfo',
|
||||
[ 'getUser', 'setSessionInfo',
|
||||
'setMacros', 'setGroups',
|
||||
'setPersistentSessionInfo', 'setLocalGroups'
|
||||
]
|
||||
|
@ -192,24 +194,22 @@ sub _reset {
|
|||
if ( my $error = $self->p->process( $req, useMail => $searchByMail ) ) {
|
||||
if ( $error == PE_USERNOTFOUND or $error == PE_BADCREDENTIALS ) {
|
||||
$self->userLogger->warn( "Reset asked for an unvalid user ("
|
||||
. $req->param('mail')
|
||||
. ")" );
|
||||
. $req->param('mail')
|
||||
. ")" );
|
||||
|
||||
# To avoid mail enumeration, return OK
|
||||
# unless portalErrorOnMailNotFound is set
|
||||
|
||||
if ( $self->conf->{portalErrorOnMailNotFound} ) {
|
||||
$self->setSecurity($req);
|
||||
return PE_MAILNOTFOUND;
|
||||
}
|
||||
|
||||
my $mailTimeout =
|
||||
$self->conf->{mailTimeout} || $self->conf->{timeout};
|
||||
my $mailTimeout
|
||||
= $self->conf->{mailTimeout} || $self->conf->{timeout};
|
||||
my $expTimestamp = time() + $mailTimeout;
|
||||
$req->data->{expMailDate} =
|
||||
strftime( "%d/%m/%Y", localtime $expTimestamp );
|
||||
$req->data->{expMailTime} =
|
||||
strftime( "%H:%M", localtime $expTimestamp );
|
||||
$req->data->{expMailDate}
|
||||
= strftime( "%d/%m/%Y", localtime $expTimestamp );
|
||||
$req->data->{expMailTime}
|
||||
= strftime( "%H:%M", localtime $expTimestamp );
|
||||
return PE_MAILCONFIRMOK;
|
||||
}
|
||||
return $error;
|
||||
|
@ -238,8 +238,7 @@ sub _reset {
|
|||
$infos->{mailSessionStartTimestamp} = $time;
|
||||
|
||||
# Store mail
|
||||
$infos->{ $self->conf->{mailSessionKey} } =
|
||||
$self->p->getFirstValue(
|
||||
$infos->{ $self->conf->{mailSessionKey} } = $self->p->getFirstValue(
|
||||
$req->{sessionInfo}->{ $self->conf->{mailSessionKey} } );
|
||||
|
||||
# Store user
|
||||
|
@ -270,19 +269,19 @@ sub _reset {
|
|||
|
||||
$self->logger->debug("Mail expiration timestamp: $expTimestamp");
|
||||
|
||||
$req->data->{expMailDate} =
|
||||
strftime( "%d/%m/%Y", localtime $expTimestamp );
|
||||
$req->data->{expMailTime} =
|
||||
strftime( "%H:%M", localtime $expTimestamp );
|
||||
$req->data->{expMailDate}
|
||||
= strftime( "%d/%m/%Y", localtime $expTimestamp );
|
||||
$req->data->{expMailTime}
|
||||
= strftime( "%H:%M", localtime $expTimestamp );
|
||||
|
||||
# Mail session start date
|
||||
my $startTimestamp = $mailSession->data->{mailSessionStartTimestamp};
|
||||
|
||||
$self->logger->debug("Mail start timestamp: $startTimestamp");
|
||||
$req->data->{startMailDate} =
|
||||
strftime( "%d/%m/%Y", localtime $startTimestamp );
|
||||
$req->data->{startMailTime} =
|
||||
strftime( "%H:%M", localtime $startTimestamp );
|
||||
$req->data->{startMailDate}
|
||||
= strftime( "%d/%m/%Y", localtime $startTimestamp );
|
||||
$req->data->{startMailTime}
|
||||
= strftime( "%H:%M", localtime $startTimestamp );
|
||||
|
||||
# Ask if user wants an another confirmation email
|
||||
if ( $req->data->{mailAlreadySent}
|
||||
|
@ -299,21 +298,20 @@ sub _reset {
|
|||
}
|
||||
|
||||
# Get mail address
|
||||
$req->data->{mailAddress} ||=
|
||||
$self->p->getFirstValue(
|
||||
$req->data->{mailAddress} ||= $self->p->getFirstValue(
|
||||
$req->{sessionInfo}->{ $self->conf->{mailSessionKey} } );
|
||||
return PE_MAILERROR unless ( $req->data->{mailAddress} );
|
||||
|
||||
# Build confirmation url
|
||||
my $req_url = $req->data->{_url};
|
||||
my $skin = $self->p->getSkin($req);
|
||||
my $url =
|
||||
$self->conf->{mailUrl} . '?'
|
||||
. build_urlencoded(
|
||||
my $url
|
||||
= $self->conf->{mailUrl} . '?'
|
||||
. build_urlencoded(
|
||||
mail_token => $req->{id},
|
||||
skin => $skin,
|
||||
( $req_url ? ( url => $req_url ) : () ),
|
||||
);
|
||||
);
|
||||
|
||||
# Build mail content
|
||||
$tplPrms{MAIN_LOGO} = $self->conf->{portalMainLogo};
|
||||
|
@ -353,7 +351,7 @@ sub _reset {
|
|||
$req->data->{mailAddress},
|
||||
$subject, $body, $html
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
$self->logger->debug('Unable to send reset mail');
|
||||
|
||||
|
@ -366,8 +364,7 @@ sub _reset {
|
|||
# A token is required
|
||||
$self->ott->setToken(
|
||||
$req,
|
||||
{
|
||||
%{ $req->sessionInfo },
|
||||
{ %{ $req->sessionInfo },
|
||||
pwdAllowed => $self->conf->{passwordResetAllowedRetries}
|
||||
}
|
||||
);
|
||||
|
@ -381,7 +378,7 @@ sub changePwd {
|
|||
$self->logger->debug('Change password form response');
|
||||
|
||||
if ( my $token = $req->param('token') ) {
|
||||
$req->sessionInfo( $self->ott->getToken($token) );
|
||||
$req->sessionInfo( $self->ott->getToken( $token, 1 ) );
|
||||
unless ( $req->sessionInfo ) {
|
||||
$self->userLogger->warn(
|
||||
'User tries to change password with an invalid or expired token'
|
||||
|
@ -393,7 +390,8 @@ sub changePwd {
|
|||
# These 2 cases means that a user tries to change password without
|
||||
# following valid links!!!
|
||||
else {
|
||||
$self->userLogger->error('User tries to change password without token');
|
||||
$self->userLogger->error(
|
||||
'User tries to change password without token');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
|
||||
|
@ -409,8 +407,8 @@ sub changePwd {
|
|||
"Reset password request for " . $req->{sessionInfo}->{_user} );
|
||||
|
||||
# Generate a complex password
|
||||
my $password =
|
||||
$self->gen_password( $self->conf->{randomPasswordRegexp} );
|
||||
my $password
|
||||
= $self->gen_password( $self->conf->{randomPasswordRegexp} );
|
||||
|
||||
$self->logger->debug( "Generated password: " . $password );
|
||||
|
||||
|
@ -430,8 +428,8 @@ sub changePwd {
|
|||
{
|
||||
$self->ott->setToken( $req, $req->sessionInfo );
|
||||
( $req->data->{newpassword} && $req->data->{confirmpassword} )
|
||||
? return PE_PASSWORD_MISMATCH
|
||||
: return PE_PASSWORDFORMEMPTY;
|
||||
? return PE_PASSWORD_MISMATCH
|
||||
: return PE_PASSWORDFORMEMPTY;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -441,8 +439,7 @@ sub changePwd {
|
|||
my $tmp = $self->conf->{portalRequireOldPassword};
|
||||
$self->conf->{portalRequireOldPassword} = 0;
|
||||
$req->user( $req->{sessionInfo}->{_user} );
|
||||
my $result =
|
||||
$self->p->_passwordDB->modifyPassword( $req,
|
||||
my $result = $self->p->_passwordDB->modifyPassword( $req,
|
||||
$req->data->{newpassword}, 1 );
|
||||
$req->{user} = undef;
|
||||
$self->conf->{portalRequireOldPassword} = $tmp;
|
||||
|
@ -451,8 +448,7 @@ sub changePwd {
|
|||
return $result unless ( $result == PE_PASSWORD_OK or $result == PE_OK );
|
||||
|
||||
# Send mail containing the new password
|
||||
$req->data->{mailAddress} ||=
|
||||
$self->p->getFirstValue(
|
||||
$req->data->{mailAddress} ||= $self->p->getFirstValue(
|
||||
$req->{sessionInfo}->{ $self->conf->{mailSessionKey} } );
|
||||
|
||||
# Build mail content
|
||||
|
@ -488,7 +484,7 @@ sub changePwd {
|
|||
|
||||
# Send mail
|
||||
return PE_MAILERROR
|
||||
unless $self->send_mail( $req->data->{mailAddress}, $subject, $body,
|
||||
unless $self->send_mail( $req->data->{mailAddress}, $subject, $body,
|
||||
$html );
|
||||
|
||||
PE_MAILOK;
|
||||
|
@ -499,7 +495,7 @@ sub setSecurity {
|
|||
if ( $self->captcha ) {
|
||||
$self->captcha->setCaptcha($req);
|
||||
}
|
||||
elsif ( $self->conf->{requireToken} ) {
|
||||
else {
|
||||
$self->ott->setToken($req);
|
||||
}
|
||||
}
|
||||
|
@ -533,7 +529,8 @@ sub display {
|
|||
DISPLAY_PASSWORD_FORM => 0,
|
||||
);
|
||||
if ( $req->data->{mailToken}
|
||||
and !$self->p->checkXSSAttack( 'mail_token', $req->data->{mailToken} ) )
|
||||
and
|
||||
!$self->p->checkXSSAttack( 'mail_token', $req->data->{mailToken} ) )
|
||||
{
|
||||
$tplPrm{MAIL_TOKEN} = $req->data->{mailToken};
|
||||
}
|
||||
|
@ -548,16 +545,14 @@ sub display {
|
|||
}
|
||||
|
||||
# Display form the first time
|
||||
if (
|
||||
(
|
||||
$req->error == PE_MAILFORMEMPTY
|
||||
if (( $req->error == PE_MAILFORMEMPTY
|
||||
or $req->error == PE_MAILFIRSTACCESS
|
||||
or $req->error == PE_MAILNOTFOUND
|
||||
or $req->error == PE_CAPTCHAERROR
|
||||
or $req->error == PE_CAPTCHAEMPTY
|
||||
)
|
||||
and !$req->data->{mailToken}
|
||||
)
|
||||
)
|
||||
{
|
||||
$self->logger->debug('Display form');
|
||||
$tplPrm{DISPLAY_FORM} = 1;
|
||||
|
|
Loading…
Reference in New Issue