Commit 820691df authored by Xavier Guimard's avatar Xavier Guimard

Start handler reorganization (#1160)

parent 554cd5e7
...@@ -209,7 +209,7 @@ sub virtualHosts { ...@@ -209,7 +209,7 @@ sub virtualHosts {
} }
return $self->sendJSONresponse( $req, $resp ); return $self->sendJSONresponse( $req, $resp );
} }
elsif ( $query =~ /^vhost(?:(?:Aliase|Http)s|Maintenance|Port)$/ ) { elsif ( $query =~ /^vhost(?:(?:Aliase|Http)s|Maintenance|Port|Type)$/ ) {
$self->lmLog( "Query for $vh/$query key", 'debug' ); $self->lmLog( "Query for $vh/$query key", 'debug' );
# TODO: verify how this is done actually # TODO: verify how this is done actually
......
...@@ -26,7 +26,7 @@ our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID) ...@@ -26,7 +26,7 @@ our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|(?:RedirectUri|ExtraClaim)s|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|UserIDAttr)|ExportedVars)'; our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|(?:RedirectUri|ExtraClaim)s|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|UserIDAttr)|ExportedVars)';
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding)|Force(?:Authn|UTF8)|NameIDFormat)|ExportedAttributes|XML)'; our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding)|Force(?:Authn|UTF8)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|ExportedAttributes|XML)'; our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|ExportedAttributes|XML)';
our $virtualHostKeys = '(?:vhost(?:(?:Aliase|Http)s|Maintenance|Port)|(?:exportedHeader|locationRule)s|post)'; our $virtualHostKeys = '(?:vhost(?:(?:Maintenanc|Typ)e|(?:Aliase|Http)s|Port)|(?:exportedHeader|locationRule)s|post)';
our $authParameters = { our $authParameters = {
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)], adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],
......
...@@ -5,8 +5,9 @@ example/scripts/purgeLocalCache ...@@ -5,8 +5,9 @@ example/scripts/purgeLocalCache
example/scripts/purgeLocalCache.cron.d example/scripts/purgeLocalCache.cron.d
lib/Lemonldap/NG/Handler.pm lib/Lemonldap/NG/Handler.pm
lib/Lemonldap/NG/Handler/ApacheMP2.pm lib/Lemonldap/NG/Handler/ApacheMP2.pm
lib/Lemonldap/NG/Handler/ApacheMP2/AuthBasic.pm
lib/Lemonldap/NG/Handler/ApacheMP2/Main.pm
lib/Lemonldap/NG/Handler/API/ExperimentalNginx.pm lib/Lemonldap/NG/Handler/API/ExperimentalNginx.pm
lib/Lemonldap/NG/Handler/AuthBasic.pm
lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm
lib/Lemonldap/NG/Handler/Main.pm lib/Lemonldap/NG/Handler/Main.pm
lib/Lemonldap/NG/Handler/Main/Init.pm lib/Lemonldap/NG/Handler/Main/Init.pm
...@@ -37,7 +38,6 @@ t/12-Lemonldap-NG-Handler-Jail.t ...@@ -37,7 +38,6 @@ t/12-Lemonldap-NG-Handler-Jail.t
t/13-Lemonldap-NG-Handler-Fake-Safe.t t/13-Lemonldap-NG-Handler-Fake-Safe.t
t/50-Lemonldap-NG-Handler-SecureToken.t t/50-Lemonldap-NG-Handler-SecureToken.t
t/51-Lemonldap-NG-Handler-Zimbra.t t/51-Lemonldap-NG-Handler-Zimbra.t
t/52-Lemonldap-NG-Handler-AuthBasic.t
t/60-Lemonldap-NG-Handler-PSGI.t t/60-Lemonldap-NG-Handler-PSGI.t
t/61-Lemonldap-NG-Handler-PSGI-Server.t t/61-Lemonldap-NG-Handler-PSGI-Server.t
t/62-Lemonldap-NG-Handler-Nginx.t t/62-Lemonldap-NG-Handler-Nginx.t
......
# Auth-basic authentication with Lemonldap::NG rights management
# This specific handler is intended to be called directly by Apache
package Lemonldap::NG::Handler::ApacheMP2::AuthBasic;
use strict;
use base 'Lemonldap::NG::Handler::Lib::AuthBasic',
'Lemonldap::NG::Handler::ApacheMP2::Main';
our $VERSION = '2.0.0';
1;
# Auth-basic authentication with Lemonldap::NG rights management
# This specific handler is intended to be called directly by Apache
package Lemonldap::NG::Handler::AuthBasic;
use strict;
use Lemonldap::NG::Handler::ApacheMP2;
use Lemonldap::NG::Handler::Lib::AuthBasic;
BEGIN {
our @ISA = ('Lemonldap::NG::Handler::Main');
}
our $VERSION = '2.0.0';
# PUBLIC METHODS
sub handler {
my $class;
$class = $#_ ? shift : __PACKAGE__;
my ($res) = $class->run(@_);
return $res;
}
# For an obscur reason, inheritance isn't possible with ApacheMP2.pm.
*FORBIDDEN = *Lemonldap::NG::Handler::ApacheMP2::FORBIDDEN;
*HTTP_UNAUTHORIZED = *Lemonldap::NG::Handler::ApacheMP2::HTTP_UNAUTHORIZED;
*REDIRECT = *Lemonldap::NG::Handler::ApacheMP2::REDIRECT;
*OK = *Lemonldap::NG::Handler::ApacheMP2::OK;
*DECLINED = *Lemonldap::NG::Handler::ApacheMP2::DECLINED;
*DONE = *Lemonldap::NG::Handler::ApacheMP2::DONE;
*SERVER_ERROR = *Lemonldap::NG::Handler::ApacheMP2::SERVER_ERROR;
*AUTH_REQUIRED = *Lemonldap::NG::Handler::ApacheMP2::AUTH_REQUIRED;
*MAINTENANCE = *Lemonldap::NG::Handler::ApacheMP2::MAINTENANCE;
*_lmLog = *Lemonldap::NG::Handler::ApacheMP2::_lmLog;
*addToHtmlHead = *Lemonldap::NG::Handler::ApacheMP2::addToHtmlHead;
*args = *Lemonldap::NG::Handler::ApacheMP2::args;
*flatten_bb = *Lemonldap::NG::Handler::ApacheMP2::flatten_bb;
*get_server_port = *Lemonldap::NG::Handler::ApacheMP2::get_server_port;
*header_in = *Lemonldap::NG::Handler::ApacheMP2::header_in;
*hostname = *Lemonldap::NG::Handler::ApacheMP2::hostname;
*is_initial_req = *Lemonldap::NG::Handler::ApacheMP2::is_initial_req;
*method = *Lemonldap::NG::Handler::ApacheMP2::method;
*newRequest = *Lemonldap::NG::Handler::ApacheMP2::newRequest;
*print = *Lemonldap::NG::Handler::ApacheMP2::print;
*redirectFilter = *Lemonldap::NG::Handler::ApacheMP2::redirectFilter;
*remote_ip = *Lemonldap::NG::Handler::ApacheMP2::remote_ip;
*set_header_in = *Lemonldap::NG::Handler::ApacheMP2::set_header_in;
*set_header_out = *Lemonldap::NG::Handler::ApacheMP2::set_header_out;
*set_user = *Lemonldap::NG::Handler::ApacheMP2::set_user;
*setPostParams = *Lemonldap::NG::Handler::ApacheMP2::setPostParams;
*setServerSignature = *Lemonldap::NG::Handler::ApacheMP2::setServerSignature;
*thread_share = *Lemonldap::NG::Handler::ApacheMP2::thread_share;
*unparsed_uri = *Lemonldap::NG::Handler::ApacheMP2::unparsed_uri;
*unset_header_in = *Lemonldap::NG::Handler::ApacheMP2::unset_header_in;
*uri = *Lemonldap::NG::Handler::ApacheMP2::uri;
*uri_with_args = *Lemonldap::NG::Handler::ApacheMP2::uri_with_args;
*unparsed_uri = *Lemonldap::NG::Handler::ApacheMP2::unparsed_uri;
__PACKAGE__->init();
1;
...@@ -42,11 +42,11 @@ sub retrieveSession { ...@@ -42,11 +42,11 @@ sub retrieveSession {
# First check if session already exists # First check if session already exists
return 1 return 1
if ( $class->Lemonldap::NG::Handler::Main::Run::retrieveSession($id) ); if ( $class->Lemonldap::NG::Handler::Main::retrieveSession($id) );
# Then ask portal to create it # Then ask portal to create it
if ( $class->createSession($id) ) { if ( $class->createSession($id) ) {
return $class->Lemonldap::NG::Handler::Main::Run::retrieveSession($id); return $class->Lemonldap::NG::Handler::Main::retrieveSession($id);
} }
else { else {
return 0; return 0;
...@@ -65,15 +65,16 @@ sub createSession { ...@@ -65,15 +65,16 @@ sub createSession {
$xheader .= $class->remote_ip; $xheader .= $class->remote_ip;
my $soapHeaders = HTTP::Headers->new( "X-Forwarded-For" => $xheader ); my $soapHeaders = HTTP::Headers->new( "X-Forwarded-For" => $xheader );
my $soapClient = SOAP::Lite->proxy( $class->tsv->{portal}->(), # TODO: use adminSession or sessions
default_headers => $soapHeaders ) my $soapClient = SOAP::Lite->proxy(
->uri('urn:Lemonldap/NG/Common/PSGI/SOAPService'); $class->tsv->{portal}->() . '/sessions',
default_headers => $soapHeaders
)->uri('urn:Lemonldap/NG/Common/PSGI/SOAPService');
my $creds = $class->header_in('Authorization'); my $creds = $class->header_in('Authorization');
$creds =~ s/^Basic\s+//; $creds =~ s/^Basic\s+//;
my ( $user, $pwd ) = ( decode_base64($creds) =~ /^(.*?):(.*)$/ ); my ( $user, $pwd ) = ( decode_base64($creds) =~ /^(.*?):(.*)$/ );
$class->lmLog( "AuthBasic authentication for user: $user", 'debug' ); $class->lmLog( "AuthBasic authentication for user: $user", 'debug' );
die 'Replace this by REST call';
my $soapRequest = $soapClient->getCookies( $user, $pwd, $id ); my $soapRequest = $soapClient->getCookies( $user, $pwd, $id );
# Catch SOAP errors # Catch SOAP errors
...@@ -116,8 +117,7 @@ sub hideCookie { ...@@ -116,8 +117,7 @@ sub hideCookie {
sub goToPortal { sub goToPortal {
my ( $class, $url, $arg ) = @_; my ( $class, $url, $arg ) = @_;
if ($arg) { if ($arg) {
return $class->Lemonldap::NG::Handler::Main::Run::goToPortal( $url, return $class->Lemonldap::NG::Handler::Main::goToPortal( $url, $arg );
$arg );
} }
else { else {
$class->set_header_out( $class->set_header_out(
......
...@@ -6,13 +6,6 @@ use Lemonldap::NG::Handler::Main::Reload; ...@@ -6,13 +6,6 @@ use Lemonldap::NG::Handler::Main::Reload;
use Lemonldap::NG::Handler::Main::Run; use Lemonldap::NG::Handler::Main::Run;
use Lemonldap::NG::Handler::Main::SharedVariables; use Lemonldap::NG::Handler::Main::SharedVariables;
our @ISA = qw(
Lemonldap::NG::Handler::Main::Init
Lemonldap::NG::Handler::Main::SharedVariables
Lemonldap::NG::Handler::Main::Reload
Lemonldap::NG::Handler::Main::Run
);
our $VERSION = '2.0.0'; our $VERSION = '2.0.0';
1; 1;
package Lemonldap::NG::Handler::Main::Init; package Lemonldap::NG::Handler::Main::Init;
our $VERSION = '2.0.0';
package Lemonldap::NG::Handler::Main;
use strict; use strict;
use Lemonldap::NG::Common::Conf; use Lemonldap::NG::Common::Conf;
our $VERSION = '2.0.0';
## @imethod void init(hashRef args) ## @imethod void init(hashRef args)
# Read parameters and build the Lemonldap::NG::Common::Conf object. # Read parameters and build the Lemonldap::NG::Common::Conf object.
# @param $args hash containing parameters # @param $args hash containing parameters
......
package Lemonldap::NG::Handler::Main::Reload; package Lemonldap::NG::Handler::Main::Reload;
our $VERSION = '2.0.0';
package Lemonldap::NG::Handler::Main;
use strict; use strict;
use Lemonldap::NG::Common::Conf::Constants; #inherits use Lemonldap::NG::Common::Conf::Constants; #inherits
use Lemonldap::NG::Common::Crypto; use Lemonldap::NG::Common::Crypto;
...@@ -10,8 +14,6 @@ use Scalar::Util qw(weaken); ...@@ -10,8 +14,6 @@ use Scalar::Util qw(weaken);
use constant UNPROTECT => 1; use constant UNPROTECT => 1;
use constant SKIP => 2; use constant SKIP => 2;
our $VERSION = '2.0.0';
our @_onReload; our @_onReload;
sub onReload { sub onReload {
...@@ -215,6 +217,12 @@ sub defaultValuesInit { ...@@ -215,6 +217,12 @@ sub defaultValuesInit {
} }
} }
} }
if ( $conf->{vhostOptions} ) {
foreach my $vhost ( keys %{ $conf->{vhostOptions} } ) {
$class->tsv->{type}->{$vhost} =
$conf->{vhostOptions}->{$vhost}->{vhostType};
}
}
return 1; return 1;
} }
......
package Lemonldap::NG::Handler::Main::Run; package Lemonldap::NG::Handler::Main::Run;
our $VERSION = '2.0.0';
package Lemonldap::NG::Handler::Main;
use strict; use strict;
#use AutoLoader 'AUTOLOAD'; #use AutoLoader 'AUTOLOAD';
use MIME::Base64; use MIME::Base64;
use URI::Escape; use URI::Escape;
use Lemonldap::NG::Common::Session; use Lemonldap::NG::Common::Session;
our $VERSION = '2.0.0';
# PUBLIC METHODS # PUBLIC METHODS
...@@ -45,6 +48,21 @@ sub status { ...@@ -45,6 +48,21 @@ sub status {
return $class->OK; return $class->OK;
} }
sub checkType {
my ( $class, $req ) = @_;
$class->newRequest($req);
if ( time() - $class->lastCheck > $class->checkTime ) {
die("$class: No configuration found")
unless ( $class->checkConf );
}
my $vhost = $class->resolveAlias;
return
( defined $class->tsv->{type}->{$vhost} )
? $class->tsv->{type}->{$vhost}
: 'Main';
}
## @rmethod int run ## @rmethod int run
# Check configuration and launch Lemonldap::NG::Handler::Main::run(). # Check configuration and launch Lemonldap::NG::Handler::Main::run().
# Each $checkTime, the Apache child verify if its configuration is the same # Each $checkTime, the Apache child verify if its configuration is the same
...@@ -56,11 +74,6 @@ sub run { ...@@ -56,11 +74,6 @@ sub run {
my ( $class, $req, $rule, $protection ) = @_; my ( $class, $req, $rule, $protection ) = @_;
my ( $id, $session ); my ( $id, $session );
$class->newRequest($req);
if ( time() - $class->lastCheck > $class->checkTime ) {
die("$class: No configuration found")
unless ( $class->checkConf );
}
return $class->DECLINED unless ( $class->is_initial_req ); return $class->DECLINED unless ( $class->is_initial_req );
# Direct return if maintenance mode is active # Direct return if maintenance mode is active
......
package Lemonldap::NG::Handler::Main::SharedVariables; package Lemonldap::NG::Handler::Main::SharedVariables;
our $VERSION = '2.0.0';
# Since handler has no instances but only static classes, this module provides # Since handler has no instances but only static classes, this module provides
# classes properties with accessors # classes properties with accessors
use strict; package Lemonldap::NG::Handler::Main;
our $VERSION = '2.0.0'; use strict;
# Thread shared properties (if threads are available: needs to be loaded elsewhere) # Thread shared properties (if threads are available: needs to be loaded elsewhere)
our $_tshv = { our $_tshv = {
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
package Lemonldap::NG::Handler::Menu; package Lemonldap::NG::Handler::Menu;
use strict; use strict;
use Lemonldap::NG::Handler::ApacheMP2 qw(:all); use Lemonldap::NG::Handler::ApacheMP2::Main qw(:all);
use base qw(Lemonldap::NG::Handler::ApacheMP2); use base qw(Lemonldap::NG::Handler::ApacheMP2::Main);
use Apache2::Filter (); use Apache2::Filter ();
use constant BUFF_LEN => 8192; use constant BUFF_LEN => 8192;
......
...@@ -114,6 +114,9 @@ sub reload { ...@@ -114,6 +114,9 @@ sub reload {
# response is 200. # response is 200.
sub _authAndTrace { sub _authAndTrace {
my ( $self, $req, $noCall ) = @_; my ( $self, $req, $noCall ) = @_;
# TODO: handle types
my $type = $self->api->checkType($req);
my ( $res, $session ) = $self->api->run( $req, $self->{rule} ); my ( $res, $session ) = $self->api->run( $req, $self->{rule} );
$self->portal( $self->api->tsv->{portal}->() ); $self->portal( $self->api->tsv->{portal}->() );
$req->userData($session) if ($session); $req->userData($session) if ($session);
......
...@@ -12,7 +12,7 @@ package Lemonldap::NG::Handler::Specific::ZimbraPreAuth; ...@@ -12,7 +12,7 @@ package Lemonldap::NG::Handler::Specific::ZimbraPreAuth;
use strict; use strict;
use Lemonldap::NG::Handler::ApacheMP2 qw(:all); use Lemonldap::NG::Handler::ApacheMP2 qw(:all);
use base qw(Lemonldap::NG::Handler::ApacheMP2); use base qw(Lemonldap::NG::Handler::ApacheMP2::Main);
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex); use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
our $VERSION = '2.0.0'; our $VERSION = '2.0.0';
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# change 'tests => 1' to 'tests => last_test_to_print'; # change 'tests => 1' to 'tests => last_test_to_print';
use Test::More tests => 5; use Test::More tests => 6;
use Cwd 'abs_path'; use Cwd 'abs_path';
use File::Basename; use File::Basename;
use File::Temp; use File::Temp;
...@@ -55,6 +55,8 @@ my $h = 'Lemonldap::NG::Handler::Test'; ...@@ -55,6 +55,8 @@ my $h = 'Lemonldap::NG::Handler::Test';
ok( $h->init(), 'Initialize handler' ); ok( $h->init(), 'Initialize handler' );
ok( $h->checkType($apacheRequest) eq 'Main', 'Get Main type');
ok( $ret = $h->run($apacheRequest), ok( $ret = $h->run($apacheRequest),
'run Handler with basic configuration and no cookie' ); 'run Handler with basic configuration and no cookie' );
......
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl Lemonldap-NG-Handler-Proxy.t'
#########################
# change 'tests => 1' to 'tests => last_test_to_print';
use Test::More tests => 1;
use Cwd 'abs_path';
use File::Basename;
use File::Temp;
my $ini = File::Temp->new();
my $dir = dirname( abs_path($0) );
print $ini "[all]
[configuration]
type=File
dirName=$dir
";
$ini->flush();
use Env qw(LLNG_DEFAULTCONFFILE);
$LLNG_DEFAULTCONFFILE = $ini->filename;
open STDERR, '>/dev/null';
#########################
# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.
use_ok('Lemonldap::NG::Handler::AuthBasic');
$LLNG_DEFAULTCONFFILE = undef;
...@@ -2983,6 +2983,28 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a- ...@@ -2983,6 +2983,28 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => -1, 'default' => -1,
'type' => 'int' 'type' => 'int'
}, },
'vhostType' => {
'default' => 'Main',
'select' => [
{
'k' => 'Main',
'v' => 'Main'
},
{
'k' => 'Zimbra',
'v' => 'ZimbraPreAuth'
},
{
'k' => 'AuthBasic',
'v' => 'AuthBasic'
},
{
'k' => 'SecureToken',
'v' => 'SecureToken'
}
],
'type' => 'select'
},
'virtualHosts' => { 'virtualHosts' => {
'type' => 'virtualHostContainer' 'type' => 'virtualHostContainer'
}, },
......
...@@ -1131,6 +1131,17 @@ sub attributes { ...@@ -1131,6 +1131,17 @@ sub attributes {
vhostAliases => { vhostAliases => {
type => 'text', type => 'text',
}, },
vhostType => {
type => 'select',
select => [
{ k => 'Main', v => 'Main' },
{ k => 'Zimbra', v => 'ZimbraPreAuth' },
{ k => 'AuthBasic', v => 'AuthBasic' },
{ k => 'SecureToken', v => 'SecureToken' },
],
default => 'Main',
documentation => 'Handler type',
},
# CAS IDP # CAS IDP
casAttr => { type => 'text', }, casAttr => { type => 'text', },
...@@ -2277,19 +2288,19 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?: ...@@ -2277,19 +2288,19 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
keyTest => qr/^\w+$/, keyTest => qr/^\w+$/,
test => sub { 1 }, test => sub { 1 },
documentation => 'Combination module description', documentation => 'Combination module description',
select => [ select => [
{ k => 'Apache', v => 'Apache' }, { k => 'Apache', v => 'Apache' },
{ k => 'AD', v => 'Active Directory' }, { k => 'AD', v => 'Active Directory' },
{ k => 'DBI', v => 'Database (DBI)' }, { k => 'DBI', v => 'Database (DBI)' },
{ k => 'Facebook', v => 'Facebook' }, { k => 'Facebook', v => 'Facebook' },
{ k => 'Google', v => 'Google' }, { k => 'Google', v => 'Google' },
{ k => 'LDAP', v => 'LDAP' }, { k => 'LDAP', v => 'LDAP' },
{ k => 'Radius', v => 'Radius' }, { k => 'Radius', v => 'Radius' },
{ k => 'SSL', v => 'SSL' }, { k => 'SSL', v => 'SSL' },
{ k => 'Twitter', v => 'Twitter' }, { k => 'Twitter', v => 'Twitter' },
{ k => 'WebID', v => 'WebID' }, { k => 'WebID', v => 'WebID' },
{ k => 'Yubikey', v => 'Yubikey' }, { k => 'Yubikey', v => 'Yubikey' },
{ k => 'Demo', v => 'Demonstration' }, { k => 'Demo', v => 'Demonstration' },
{ k => 'CAS', v => 'Central Authentication Service (CAS)' }, { k => 'CAS', v => 'Central Authentication Service (CAS)' },
{ k => 'OpenID', v => 'OpenID' }, { k => 'OpenID', v => 'OpenID' },
{ k => 'OpenIDConnect', v => 'OpenID Connect' }, { k => 'OpenIDConnect', v => 'OpenID Connect' },
......
...@@ -25,7 +25,7 @@ sub cTrees { ...@@ -25,7 +25,7 @@ sub cTrees {
help => 'configvhost.html#options', help => 'configvhost.html#options',
nodes => [ nodes => [
'vhostPort', 'vhostHttps', 'vhostPort', 'vhostHttps',
'vhostMaintenance', 'vhostAliases' 'vhostMaintenance', 'vhostAliases', 'vhostType',
], ],
}, },
], ],
......
...@@ -915,6 +915,31 @@ function templates(tpl,key) { ...@@ -915,6 +915,31 @@ function templates(tpl,key) {
"get" : tpl+"s/"+key+"/"+"vhostAliases", "get" : tpl+"s/"+key+"/"+"vhostAliases",
"id" : tpl+"s/"+key+"/"+"vhostAliases", "id" : tpl+"s/"+key+"/"+"vhostAliases",
"title" : "vhostAliases" "title" : "vhostAliases"
},
{
"default" : "Main",
"get" : tpl+"s/"+key+"/"+"vhostType",
"id" : tpl+"s/"+key+"/"+"vhostType",
"select" : [
{
"k" : "Main",
"v" : "Main"
},
{
"k" : "Zimbra",
"v" : "ZimbraPreAuth"
},
{
"k" : "AuthBasic",
"v" : "AuthBasic"
},
{
"k" : "SecureToken",
"v" : "SecureToken"
}
],
"title" : "vhostType",
"type" : "select"
} }
], ],
"help" : "configvhost.html#options", "help" : "configvhost.html#options",
......
...@@ -671,6 +671,7 @@ ...@@ -671,6 +671,7 @@
"vhostMaintenance": "Maintenance mode", "vhostMaintenance": "Maintenance mode",
"vhostOptions": "Options", "vhostOptions": "Options",
"vhostPort": "Port", "vhostPort": "Port",
"vhostType": "Type",
"view": "View", "view": "View",
"virtualHost": "Virtual Host", "virtualHost": "Virtual Host",
"virtualHostName": "Virtual host hostname", "virtualHostName": "Virtual host hostname",
......
...@@ -671,6 +671,7 @@ ...@@ -671,6 +671,7 @@
"vhostMaintenance": "Mode maintenance", "vhostMaintenance": "Mode maintenance",
"vhostOptions": "Options", "vhostOptions": "Options",
"vhostPort": "Port", "vhostPort": "Port",
"vhostType": "Type",
"view": "Aperçu", "view": "Aperçu",
"virtualHost": "Hôte virtuel", "virtualHost": "Hôte virtuel",
"virtualHostName": "Nom de l'hôte virtuel", "virtualHostName": "Nom de l'hôte virtuel",
......
...@@ -307,6 +307,8 @@ site/templates/dark/password.tpl ...@@ -307,6 +307,8 @@ site/templates/dark/password.tpl
site/templates/dark/redirect.tpl site/templates/dark/redirect.tpl
site/templates/dark/register.tpl site/templates/dark/register.tpl
site/templates/dark/standardform.tpl site/templates/dark/standardform.tpl
site/templates/dark/u2fcheck.tpl
site/templates/dark/u2fregister.tpl
site/templates/dark/yubikeyform.tpl site/templates/dark/yubikeyform.tpl
site/templates/impact/authmessage.tpl