parent
b78022558d
commit
8a3bb7b0f9
|
@ -30,6 +30,7 @@ lib/Lemonldap/NG/Common/Conf/ReConstants.pm
|
|||
lib/Lemonldap/NG/Common/Conf/RESTServer.pm
|
||||
lib/Lemonldap/NG/Common/Conf/SAML/Metadata.pm
|
||||
lib/Lemonldap/NG/Common/Conf/Serializer.pm
|
||||
lib/Lemonldap/NG/Common/Conf/Wrapper.pm
|
||||
lib/Lemonldap/NG/Common/Crypto.pm
|
||||
lib/Lemonldap/NG/Common/FormEncode.pm
|
||||
lib/Lemonldap/NG/Common/Module.pm
|
||||
|
|
|
@ -23,7 +23,7 @@ use constant HANDLERSECTION => "handler";
|
|||
use constant MANAGERSECTION => "manager";
|
||||
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
|
||||
use constant APPLYSECTION => "apply";
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va))r|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|re(?:moteGlobalStorageOption|loadUrl)|cas(?:StorageOption|Attribute)|CAS_proxiedService|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)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:uthChoiceModules|pplicationList)|v(?:hostOptions|irtualHost))$/;
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va))r|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|re(?:moteGlobalStorageOption|loadUrl)|CAS_proxiedService|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(?:StorageOption|Attribute)s|omb(?:Modules|Over))|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:uthChoiceModules|pplicationList)|v(?:hostOptions|irtualHost))$/;
|
||||
|
||||
our @sessionTypes = ( 'remoteGlobal', 'cas', 'global', 'localSession', 'persistent', 'saml', 'oidc' );
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ our $specialNodeHash = {
|
|||
};
|
||||
|
||||
our $doubleHashKeys = 'issuerDBGetParameters';
|
||||
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|re(?:moteGlobalStorageOption|loadUrl)|cas(?:StorageOption|Attribute)|CAS_proxiedService|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember)|a(?:uthChoiceModules|pplicationList))';
|
||||
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|re(?:moteGlobalStorageOption|loadUrl)|CAS_proxiedService|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember)|c(?:as(?:StorageOption|Attribute)s|omb(?:Modules|Over))|a(?:uthChoiceModules|pplicationList))';
|
||||
our $specialNodeKeys = '(?:(?:saml(?:ID|S)|oidc[OR])PMetaDataNode|virtualHost)s';
|
||||
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|S(?:toreIDToken|cope)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
|
||||
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|(?:RedirectUri|ExtraClaim)s|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|UserIDAttr)|ExportedVars)';
|
||||
|
@ -33,11 +33,11 @@ our $authParameters = {
|
|||
apacheParams => [qw(apacheAuthnLevel)],
|
||||
casParams => [qw(CAS_authnLevel CAS_url CAS_CAFile CAS_renew CAS_gateway CAS_pgtFile CAS_proxiedServices)],
|
||||
choiceParams => [qw(authChoiceParam authChoiceModules)],
|
||||
combinationParams => [qw(combination combModules combOver)],
|
||||
dbiParams => [qw(dbiAuthnLevel dbiExportedVars dbiAuthChain dbiAuthUser dbiAuthPassword dbiUserChain dbiUserUser dbiUserPassword dbiAuthTable dbiUserTable dbiAuthLoginCol dbiAuthPasswordCol dbiPasswordMailCol userPivot dbiAuthPasswordHash)],
|
||||
demoParams => [qw(demoExportedVars)],
|
||||
facebookParams => [qw(facebookAuthnLevel facebookExportedVars facebookAppId facebookAppSecret)],
|
||||
ldapParams => [qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapBase managerDn managerPassword ldapTimeout ldapVersion ldapRaw LDAPFilter AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword)],
|
||||
multiParams => [qw(multiAuthStack multiUserDBStack)],
|
||||
nullParams => [qw(nullAuthnLevel)],
|
||||
oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],
|
||||
openidParams => [qw(openIdAuthnLevel openIdExportedVars openIdSecret openIdIDPList)],
|
||||
|
|
58
lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Wrapper.pm
Normal file
58
lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Wrapper.pm
Normal file
|
@ -0,0 +1,58 @@
|
|||
package Lemonldap::NG::Common::Conf::Wrapper;
|
||||
|
||||
use strict;
|
||||
|
||||
our $VERSION = '2.0.0';
|
||||
|
||||
sub TIEHASH {
|
||||
my ( $class, $conf, $overrides ) = @_;
|
||||
return bless {
|
||||
_wrapC => $conf,
|
||||
_wrapO => $overrides,
|
||||
}, $class;
|
||||
}
|
||||
|
||||
sub FETCH {
|
||||
my ( $self, $key ) = @_;
|
||||
return (
|
||||
exists( $self->{_wrapO}->{$key} )
|
||||
? $self->{_wrapO}->{$key}
|
||||
: $self->{_wrapC}->{$key}
|
||||
);
|
||||
}
|
||||
|
||||
sub STORE {
|
||||
my ( $self, $key, $value ) = @_;
|
||||
return $self->{_wrapO}->{$key} = $value;
|
||||
}
|
||||
|
||||
sub DELETE {
|
||||
my ( $self, $key ) = @_;
|
||||
my $res = $self->{_wrapO}->{$key} // $self->{_wrapC}->{$key};
|
||||
$self->{_wrapO}->{$key} = undef;
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub EXISTS {
|
||||
my ( $self, $key ) = @_;
|
||||
return (
|
||||
exists( $self->{_wrapC}->{$key} )
|
||||
or exists( $self->{_wrapO}->{$key} )
|
||||
);
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
my $self = shift;
|
||||
delete $self->{_wrapO};
|
||||
delete $self->{_wrapC};
|
||||
}
|
||||
|
||||
sub FIRSTKEY {
|
||||
return each %{ $_[0]->{_wrapC} };
|
||||
}
|
||||
|
||||
sub NEXTKEY {
|
||||
return each %{ $_[0]->{_wrapC} };
|
||||
}
|
||||
|
||||
1;
|
|
@ -654,6 +654,15 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => 1,
|
||||
'type' => 'bool'
|
||||
},
|
||||
'combination' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'combModules' => {
|
||||
'type' => 'keyTextContainer'
|
||||
},
|
||||
'combOver' => {
|
||||
'type' => 'keyTextContainer'
|
||||
},
|
||||
'confirmFormMethod' => {
|
||||
'default' => 'post',
|
||||
'select' => [
|
||||
|
@ -1359,12 +1368,6 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
|
|||
'test' => qr/^\S*$/,
|
||||
'type' => 'password'
|
||||
},
|
||||
'multiAuthStack' => {
|
||||
'type' => 'authParamsText'
|
||||
},
|
||||
'multiUserDBStack' => {
|
||||
'type' => 'authParamsText'
|
||||
},
|
||||
'multiValuesSeparator' => {
|
||||
'default' => '; ',
|
||||
'type' => 'authParamsText'
|
||||
|
|
|
@ -342,6 +342,11 @@ sub attributes {
|
|||
default => '',
|
||||
documentation => 'Syslog facility',
|
||||
},
|
||||
multiValuesSeparator => {
|
||||
type => 'authParamsText',
|
||||
default => '; ',
|
||||
documentation => 'Separator for multiple values',
|
||||
},
|
||||
|
||||
# Manager
|
||||
protection => {
|
||||
|
@ -1796,11 +1801,11 @@ sub attributes {
|
|||
userDB => {
|
||||
type => 'select',
|
||||
select => [
|
||||
{ k => 'Same', v => 'Same' },
|
||||
{ k => 'AD', v => 'Active Directory' },
|
||||
{ k => 'DBI', v => 'Database (DBI)' },
|
||||
{ k => 'LDAP', v => 'LDAP' },
|
||||
{ k => 'Null', v => 'None' },
|
||||
{ k => 'Same', v => 'Same' },
|
||||
{ k => 'AD', v => 'Active Directory' },
|
||||
{ k => 'DBI', v => 'Database (DBI)' },
|
||||
{ k => 'LDAP', v => 'LDAP' },
|
||||
{ k => 'Null', v => 'None' },
|
||||
],
|
||||
default => 'Same',
|
||||
documentation => 'User module',
|
||||
|
@ -2262,17 +2267,17 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
],
|
||||
},
|
||||
|
||||
# Multi
|
||||
multiAuthStack => {
|
||||
type => 'authParamsText',
|
||||
# Combination
|
||||
combination => {
|
||||
type => 'text',
|
||||
},
|
||||
multiUserDBStack => {
|
||||
type => 'authParamsText',
|
||||
combModules => {
|
||||
type => 'keyTextContainer',
|
||||
},
|
||||
multiValuesSeparator => {
|
||||
type => 'authParamsText',
|
||||
default => '; ',
|
||||
documentation => 'Separator for multiple values',
|
||||
combOver => {
|
||||
|
||||
#TODO: create new type
|
||||
type => 'keyTextContainer',
|
||||
},
|
||||
|
||||
# Yubikey
|
||||
|
|
|
@ -250,10 +250,10 @@ sub tree {
|
|||
]
|
||||
},
|
||||
{
|
||||
title => 'multiParams',
|
||||
help => 'authmulti.html',
|
||||
form => 'authParamsTextContainer',
|
||||
nodes => [ 'multiAuthStack', 'multiUserDBStack' ]
|
||||
title => 'combinationParams',
|
||||
help => 'authcombination.html',
|
||||
nodes =>
|
||||
[ 'combination', 'combModules', 'combOver' ]
|
||||
},
|
||||
{
|
||||
title => 'nullParams',
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,7 @@
|
|||
|
||||
use Test::More;
|
||||
use strict;
|
||||
use Data::Dumper;
|
||||
|
||||
my $formDir = 'site/static/forms';
|
||||
|
||||
|
@ -31,7 +32,7 @@ $count += 4;
|
|||
|
||||
my %types = %{ getTypes( $tree, values(%$ctrees), $attr ) };
|
||||
|
||||
foreach (qw(home menuCat menuApp)) {
|
||||
foreach (qw(home menuCat menuApp authParamsTextContainer)) {
|
||||
ok( $forms{$_}, "Found $_ form" );
|
||||
$count++;
|
||||
delete $forms{$_};
|
||||
|
@ -39,10 +40,13 @@ foreach (qw(home menuCat menuApp)) {
|
|||
|
||||
foreach my $type ( keys %types ) {
|
||||
delete $types{$type};
|
||||
next
|
||||
if ( $type =~
|
||||
if ( $type =~
|
||||
/^(?:authParamsText|url|PerlModule|hostname|pcre|lmAttrOrMacro|subContainer|RSAP(?:ublic|rivate)Key(?:OrCertificate)?)$/
|
||||
);
|
||||
)
|
||||
{
|
||||
delete $forms{$type};
|
||||
next;
|
||||
}
|
||||
ok( $forms{$type}, "Found $type" );
|
||||
delete $forms{$type};
|
||||
$count++;
|
||||
|
@ -53,7 +57,7 @@ foreach my $type ( keys %types ) {
|
|||
$count++;
|
||||
}
|
||||
}
|
||||
ok( !%forms, "No unused forms" );
|
||||
ok( !%forms, "No unused forms" ) or print "Found:\n" . Dumper( \%forms );
|
||||
$count++;
|
||||
|
||||
done_testing($count);
|
||||
|
|
|
@ -372,6 +372,7 @@ t/34-Auth-Proxy-and-REST-Server.t
|
|||
t/34-Auth-Proxy-and-SOAP-Server.t
|
||||
t/35-REST-sessions-with-REST-server.t
|
||||
t/35-SOAP-sessions-with-SOAP-server.t
|
||||
t/36-Combination-with-over.t
|
||||
t/36-Combination.t
|
||||
t/40-Notifications-JSON-DBI.t
|
||||
t/40-Notifications-JSON-File-with-token.t
|
||||
|
|
|
@ -16,31 +16,49 @@ has stackSub => ( is => 'rw' );
|
|||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
|
||||
# Check if expression exists
|
||||
unless ( $self->conf->{combination} ) {
|
||||
$self->error('No combination found');
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Load all declared modules
|
||||
my %mods;
|
||||
foreach my $mod ( @{ $self->conf->{combModules} } ) {
|
||||
my @tmp = ( undef, undef );
|
||||
|
||||
# TODO: override params
|
||||
# Override parameters
|
||||
my $over = $self->conf->{combOver}->{ $mod->{name} };
|
||||
|
||||
# "for" key can have 3 values:
|
||||
# 0: this module will be used for Auth and UserDB
|
||||
# 1: this module will be user for Auth only
|
||||
# 2: this module will be user for UserDB only
|
||||
|
||||
# Load Auth module
|
||||
if ( $mod->{for} < 2 ) {
|
||||
$tmp[0] = $self->p->loadPlugin("::Auth::$mod->{type}");
|
||||
$tmp[0] = $self->loadPlugin( "::Auth::$mod->{type}", $over );
|
||||
unless ( $tmp[0] ) {
|
||||
$self->error("Unable to load Auth::$mod->{type}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Load UserDB module
|
||||
unless ( $mod->{for} == 1 ) {
|
||||
$tmp[1] = $self->p->loadPlugin("::UserDB::$mod->{type}");
|
||||
$tmp[1] = $self->loadPlugin( "::UserDB::$mod->{type}", $over );
|
||||
unless ( $tmp[1] ) {
|
||||
$self->error("Unable to load UserDB::$mod->{type}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Store modules as array
|
||||
$mods{ $mod->{name} } = \@tmp;
|
||||
}
|
||||
|
||||
# Compile expression
|
||||
eval {
|
||||
$self->stackSub(
|
||||
Lemonldap::NG::Common::Combination::Parser->parse(
|
||||
|
@ -55,12 +73,8 @@ sub init {
|
|||
return 1;
|
||||
}
|
||||
|
||||
sub name {
|
||||
my ( $self, $req, $type ) = @_;
|
||||
return $req->sessionInfo->{ ( $type eq 'auth' ? '_auth' : '_userDB' ) }
|
||||
|| 'Combination';
|
||||
}
|
||||
|
||||
# Each first method must call getStack() to get the auth scheme available for
|
||||
# the current user
|
||||
sub extractFormInfo {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
|
@ -69,6 +83,7 @@ sub extractFormInfo {
|
|||
return $self->try( 0, 'extractFormInfo', $req );
|
||||
}
|
||||
|
||||
# Note that UserDB::Combination use the same object.
|
||||
sub getUser {
|
||||
return $_[0]->try( 1, 'getUser', $_[1] );
|
||||
}
|
||||
|
@ -98,7 +113,7 @@ sub getDisplayType {
|
|||
sub getStack {
|
||||
my ( $self, $req, @steps ) = @_;
|
||||
return $req->datas->{multiStack} if ( $req->datas->{multiStack} );
|
||||
my $stack = $req->datas->{multiStack} = $self->stackSub->($req->env);
|
||||
my $stack = $req->datas->{multiStack} = $self->stackSub->( $req->env );
|
||||
unless ($stack) {
|
||||
$self->lmLog( 'No authentication scheme for this user', 'error' );
|
||||
}
|
||||
|
@ -107,6 +122,7 @@ sub getStack {
|
|||
return $stack;
|
||||
}
|
||||
|
||||
# Main running method: launch the next scheme if the current fails
|
||||
sub try {
|
||||
my ( $self, $type, $subname, $req ) = @_;
|
||||
my ( $nb, $stack ) = ( $req->datas->{multiTry}, $req->datas->{multiStack} );
|
||||
|
@ -134,4 +150,34 @@ sub try {
|
|||
return $res;
|
||||
}
|
||||
|
||||
# try() stores real Auth/UserDB module in sessionInfo
|
||||
# This method reads them. It is called by getModule()
|
||||
# (see Main::Run)
|
||||
sub name {
|
||||
my ( $self, $req, $type ) = @_;
|
||||
return $req->sessionInfo->{ ( $type eq 'auth' ? '_auth' : '_userDB' ) }
|
||||
|| 'Combination';
|
||||
}
|
||||
|
||||
# To avoid "tied" destroy, tied configurations are kept here
|
||||
our %overC;
|
||||
|
||||
# Override portal loadPlugin() to use a wrapped configuration
|
||||
sub loadPlugin {
|
||||
my ( $self, $plugin, $over ) = @_;
|
||||
my $obj;
|
||||
my $nc;
|
||||
if($over) {
|
||||
require Lemonldap::NG::Common::Conf::Wrapper;
|
||||
tie %$nc, 'Lemonldap::NG::Common::Conf::Wrapper', $self->conf, $over;
|
||||
$overC{$plugin} = $nc;
|
||||
}
|
||||
else {
|
||||
$nc = $self->conf;
|
||||
}
|
||||
return 0
|
||||
unless ( $obj = $self->p->loadModule( "$plugin", $nc ) );
|
||||
return $self->p->findEP( $plugin, $obj );
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -142,7 +142,7 @@ sub reloadConf {
|
|||
my $csp = '';
|
||||
foreach (qw(default img src style font connect)) {
|
||||
my $prm = $self->conf->{ 'csp' . ucfirst($_) };
|
||||
$csp .= "$_-src $prm;" if($prm);
|
||||
$csp .= "$_-src $prm;" if ($prm);
|
||||
}
|
||||
$self->csp($csp);
|
||||
|
||||
|
@ -183,7 +183,7 @@ sub reloadConf {
|
|||
$self->error("$type is not set");
|
||||
return $self->fail;
|
||||
}
|
||||
$mod = $self->conf->{$type} unless($self->conf->{$type} eq 'Same');
|
||||
$mod = $self->conf->{$type} unless ( $self->conf->{$type} eq 'Same' );
|
||||
my $module = '::' . ucfirst($type) . '::' . $mod;
|
||||
$module =~ s/Authentication/Auth/;
|
||||
|
||||
|
@ -278,6 +278,11 @@ sub loadPlugin {
|
|||
my $obj;
|
||||
return 0
|
||||
unless ( $obj = $self->loadModule("$plugin") );
|
||||
return $self->findEP( $plugin, $obj );
|
||||
}
|
||||
|
||||
sub findEP {
|
||||
my ( $self, $plugin, $obj ) = @_;
|
||||
foreach my $sub (
|
||||
qw(beforeAuth betweenAuthAndDatas afterDatas forAuthUser beforeLogout))
|
||||
{
|
||||
|
@ -295,7 +300,8 @@ sub loadPlugin {
|
|||
}
|
||||
|
||||
sub loadModule {
|
||||
my ( $self, $module ) = @_;
|
||||
my ( $self, $module, $conf ) = @_;
|
||||
$conf //= $self->conf;
|
||||
my $obj;
|
||||
$module = "Lemonldap::NG::Portal$module" if ( $module =~ /^::/ );
|
||||
|
||||
|
@ -305,7 +311,7 @@ sub loadModule {
|
|||
return 0;
|
||||
}
|
||||
eval {
|
||||
$obj = $module->new( { p => $self, conf => $self->conf } );
|
||||
$obj = $module->new( { p => $self, conf => $conf } );
|
||||
$self->lmLog( "Module $module loaded", 'debug' );
|
||||
};
|
||||
if ($@) {
|
||||
|
|
|
@ -136,7 +136,7 @@ sub do {
|
|||
'WWW-Authenticate' => "SSO " . $self->conf->{portal},
|
||||
'Access-Control-Allow-Origin' => '*'
|
||||
],
|
||||
[]
|
||||
[qq'{"result":0,"error":$err"}']
|
||||
];
|
||||
}
|
||||
elsif ( $err > 0 ) {
|
||||
|
|
95
lemonldap-ng-portal/t/36-Combination-with-over.t
Normal file
95
lemonldap-ng-portal/t/36-Combination-with-over.t
Normal file
|
@ -0,0 +1,95 @@
|
|||
use Test::More;
|
||||
use strict;
|
||||
use IO::String;
|
||||
|
||||
require 't/test-lib.pm';
|
||||
|
||||
my $res;
|
||||
my $mainTests = 0;
|
||||
my $client;
|
||||
|
||||
eval { unlink 't/userdb.db' };
|
||||
|
||||
SKIP: {
|
||||
eval { require DBI; require DBD::SQLite; };
|
||||
if ($@) {
|
||||
skip 'DBD::SQLite not found', $mainTests;
|
||||
}
|
||||
my $dbh = DBI->connect("dbi:SQLite:dbname=t/userdb.db");
|
||||
$dbh->do('CREATE TABLE users (user text,password text,name text)');
|
||||
$dbh->do("INSERT INTO users VALUES ('dvador','dvador','Test user 1')");
|
||||
$dbh->do("INSERT INTO users VALUES ('rtyler','rtyler','Test user 1')");
|
||||
|
||||
$client = iniCmb('[Dm] or [DB]');
|
||||
expectCookie( try('dwho') );
|
||||
expectCookie( try('dvador') );
|
||||
}
|
||||
count($mainTests);
|
||||
clean_sessions();
|
||||
eval { unlink 't/userdb.db' };
|
||||
done_testing( count() );
|
||||
|
||||
sub try {
|
||||
my $user = shift;
|
||||
my $s = "user=$user&password=$user";
|
||||
my $res;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/', IO::String->new($s),
|
||||
length => length($s),
|
||||
custom => { HTTP_X => $user }
|
||||
),
|
||||
" Try to connect with login $user"
|
||||
);
|
||||
count(1);
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub iniCmb {
|
||||
my $expr = shift;
|
||||
if (
|
||||
my $res = LLNG::Manager::Test->new(
|
||||
{
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
useSafeJail => 1,
|
||||
authentication => 'Combination',
|
||||
userDB => 'Same',
|
||||
|
||||
combination => $expr,
|
||||
combModules => [
|
||||
{
|
||||
for => 0,
|
||||
name => 'DB',
|
||||
type => 'DBI',
|
||||
},
|
||||
{
|
||||
for => 0,
|
||||
name => 'Dm',
|
||||
type => 'Demo',
|
||||
},
|
||||
],
|
||||
|
||||
combOver => {
|
||||
DB => {
|
||||
dbiAuthChain => 'dbi:SQLite:dbname=t/userdb.db',
|
||||
dbiAuthUser => '',
|
||||
dbiAuthPassword => '',
|
||||
dbiAuthTable => 'users',
|
||||
dbiAuthLoginCol => 'user',
|
||||
dbiAuthPasswordCol => 'password',
|
||||
dbiAuthPasswordHash => '',
|
||||
dbiExportedVars => {},
|
||||
}
|
||||
},
|
||||
demoExportedVars => {},
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
{
|
||||
pass(qq'Expression loaded: "$expr"');
|
||||
count(1);
|
||||
return $res;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user