Configure POST form replay for each vhost in Manager (#174)

This commit is contained in:
Clément Oudot 2010-09-30 12:22:18 +00:00
parent eec03867da
commit 7601bc6415
7 changed files with 274 additions and 12 deletions

View File

@ -102,7 +102,7 @@ sub unserialize {
# Manage hashes
if ( $k =~
/^(?:exportedVars|locationRules|groups|exportedHeaders|macros|globalStorageOptions|remoteGlobalStorageOptions|notificationStorageOptions|samlIDPMetaDataXML|samlIDPMetaDataExportedAttributes|samlIDPMetaDataOptions|samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions|samlStorageOptions|CAS_proxiedServices|logoutServices|authChoiceModules|applicationList)$/
/^(?:exportedVars|locationRules|groups|exportedHeaders|macros|globalStorageOptions|remoteGlobalStorageOptions|notificationStorageOptions|samlIDPMetaDataXML|samlIDPMetaDataExportedAttributes|samlIDPMetaDataOptions|samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions|samlStorageOptions|CAS_proxiedServices|logoutServices|authChoiceModules|applicationList|post)$/
and $v ||= {}
and not ref($v) )
{

View File

@ -152,23 +152,25 @@ function lmdata(id){
function lmparent(id){
return $('#'+id).parent().parent().attr('id');
}
function setlmtext(id,v){
function setlmtext(id,v,prefixvalue){
if(!prefixvalue){prefixvalue="";}
if(v.length==0){
alert("Null value");
}
else {
$('#text_'+id).attr('name',v);
$('#text_'+id).attr('name',prefixvalue+v);
$('#text_'+id).text(v);
}
}
function setlminputtext(id,input){
function setlminputtext(id,input,prefixvalue){
var inputname=$(input).attr('id');
var inputvalue=$(input).attr('value');
if(!prefixvalue){prefixvalue="";}
if(inputvalue.length==0){
alert('No '+inputname);
return false;
}
setlmtext(id,inputvalue);
setlmtext(id,inputvalue,prefixvalue);
}
function setlmdata(id,v){
$('#text_'+id).attr('value',escape(v));
@ -288,6 +290,8 @@ function display(div,title) {
$('#newchoicer,#newchoice,#delchoice').hide();
$('#newcategoryr,#delcategory').hide();
$('#newapplicationr,#delapplication').hide();
$('#newpostr,#delpost').hide();
$('#newpostdatar,#delpostdata').hide();
var height_cur=$('#buttons').height()+$('#edition').height()+$('#help').height();
var height_max=$('#menu').height();
if(height_cur > height_max || $('#help_content').is(':visible')==false){
@ -1084,3 +1088,55 @@ function applicationListApplication(id){
$('#delapplication').show();
}
/* Post */
function postRoot(id){
currentId=id;
display('default','');
$('#newpostr').show();
}
function newPostR(){
var newIdValue=newId(currentId);
var newPostKey = 'none';
simpleTreeCollection[0].addNode(newIdValue,newPostKey,function(d,s){
$('>span',s).attr('onClick','post("'+newIdValue+'")').attr('name',newPostKey).attr('value','').attr('id','text_'+newIdValue);
post(newIdValue);
});
return false;
}
function newPostDataR(){
var newIdValue=newId(currentId);
var newPostKey = 'login';
simpleTreeCollection[0].addNode(newIdValue,newPostKey,function(d,s){
$('>span',s).attr('onClick','postData("'+newIdValue+'")').attr('name','postdata:'+newPostKey).attr('value','$uid').attr('id','text_'+newIdValue);
postData(newIdValue);
});
return false;
}
function post(id){
currentId=id;
$('#postKey').attr('value',lmtext(id));
$('#postUrl').attr('value',lmdata(id));
display('post',lmtext(lmparent(id)));
$('#delpost,#newpostdatar').show();
}
function postData(id){
currentId=id;
var cleankey = lmtext(id).replace('postdata:','');
$('#postDataKey').attr('value',cleankey);
$('#postDataValue').attr('value',lmdata(id));
display('postdata',cleankey);
$('#delpostdata').show();
}
function delPost(){
delKey();
}
function delPostData(){
delKey();
}

View File

@ -165,6 +165,21 @@
<lang en="Delete application" fr="Supprimer l'application" />
</button>
<button id="newpostr" style="display:none;" onclick="newPostR();return false;" class="ui-state-default ui-corner-all">
<lang en="New POST URL" fr="Nouvelle URL POST" />
</button>
<button id="delpost" style="display:none;" onclick="delPost();return false;" class="ui-state-default ui-corner-all">
<lang en="Delete POST URL" fr="Supprimer l'URL POST" />
</button>
<button id="newpostdatar" style="display:none;" onclick="newPostDataR();return false;" class="ui-state-default ui-corner-all">
<lang en="New POST data" fr="Nouvelle donnée POST" />
</button>
<button id="delpostdata" style="display:none;" onclick="delPostData();return false;" class="ui-state-default ui-corner-all">
<lang en="Delete POST data" fr="Supprimer la donnée POST" />
</button>
</div>
@ -518,6 +533,32 @@
</button>
</div>
<!-- Post -->
<div id="content_post" class="hidden">
<table>
<tr>
<td><lang en="POST URL" fr="URL POST"/></td>
<td><input type="text" id="postKey" /></td>
</tr>
<tr>
<td><lang en="Target URL (optional)" fr="URL cible (optionnelle)"/></td>
<td><input type="text" id="postUrl" /></td>
</tr>
</table>
<br />
<button onclick="setlminputtext(currentId,postKey);setlminputdata(currentId,postUrl);return false;" class="ui-state-default ui-corner-all">
<lang en="Apply" fr="Appliquer" />
</button>
</div>
<div id="content_postdata" class="hidden">
<input type="text" id="postDataKey" /> <input type="text" id="postDataValue" />
<br />
<button onclick="setlminputtext(currentId,postDataKey,'postdata:');setlminputdata(currentId,postDataValue);return false;" class="ui-state-default ui-corner-all">
<lang en="Apply" fr="Appliquer" />
</button>
</div>
</div>
</form>

View File

@ -80,7 +80,7 @@ sub node {
}
# subnode points to a configuration node
elsif ( $flag =~ /^(n?hash|applicationlist)$/ ) {
elsif ( $flag =~ /^(n?hash|applicationlist|post)$/ ) {
$res .=
$self->confNode( $node, "$flag:$target", $help, $_j );
}
@ -261,8 +261,6 @@ sub confNode {
if ( %{ $h->{$catid} } ) {
$res .= '<ul>';
# $res .= '<li class="line">&nbsp;</li>';
}
foreach my $appid ( sort keys %{ $h->{$catid} } ) {
@ -301,6 +299,81 @@ sub confNode {
}
}
# POST
elsif ( $target =~ s/^post:// ) {
$self->lmLog( "Load POST data (target $target)", 'debug' );
my $h = $self->keyToH( $target, $self->conf );
# Try to get value from defaultConf
unless ($h) {
unless ( $h = $self->subDefaultConf()->{post} ) {
$self->lmLog( "Try to get default conf for post", 'debug' );
$self->lmLog( "$target hash is not defined in configuration",
'error' );
return;
}
}
# Loop on POST URI
foreach my $posturi ( sort keys %$h ) {
# Build ID
my $id = "$target/$posturi";
$id =~ s/=*$//;
# Display menu item
$self->lmLog( "Display menu item for POST URI $posturi", 'debug' );
# Here, "notranslate" is set to true : hashvalues must not be
# translated
$res .= $self->li($id)
. $self->span(
id => $id,
text => "$posturi",
data => $h->{$posturi}->{postUrl},
js => $js,
help => $help,
noT => 1
);
# Loop on post data (expr)
if ( %{ $h->{$posturi}->{expr} } ) {
$res .= '<ul>';
}
foreach my $postdata ( sort keys %{ $h->{$posturi}->{expr} } ) {
$id = "$target/$posturi/$postdata";
$id =~ s/=*$//;
# Display menu item
$self->lmLog( "Display menu item for POST data $postdata",
'debug' );
$res .= $self->li($id)
. $self->span(
id => $id,
text => "$postdata",
name => "postdata:$postdata",
data => $h->{$posturi}->{expr}->{$postdata},
js => "postData",
help => $help,
noT => 1
) . "</li>";
}
if ( %{ $h->{$posturi}->{expr} } ) {
$res .= '</ul>';
}
$res .= "</li>";
}
}
else {
$target =~ s/^(\w+)://;
my $type = $1 || 'text';
@ -568,7 +641,8 @@ sub span {
$args{js} .= "('$args{id}')" unless ( $args{js} =~ /\(/ );
# Text
my $tmp = $args{text};
$args{name} ||= $args{text};
my $tmp = $args{name};
$tmp =~ s/"/&#39;/g;
$args{text} = join ' ', map { $self->translate($_) } split /\s+/,
$args{text}

View File

@ -36,10 +36,12 @@ sub confUpload {
# - Virtual host name
# - SP and IDP name
# - Menu category ID
# - POST URL name
my $vhostname;
my $idpname;
my $spname;
my $catid;
my $postname;
# 1. ANALYSE DATAS
@ -71,6 +73,10 @@ sub confUpload {
my $catflag = 0;
my $appflag = 0;
# For POST URL keys
my $postflag = 0;
my $postdataflag = 0;
# Unescape value
$value = uri_unescape($value);
@ -118,6 +124,19 @@ sub confUpload {
}
}
# Get POST URL name
if ( $id =~ /post\/([^\/]*)?\/.*$/ ) {
if ( $name =~ s/^postdata:// ) {
$self->lmLog( "POST data $name", 'debug' );
$postdataflag = 1;
}
else {
$self->lmLog( "Entering POST URL $name", 'debug' );
$postflag = 1;
$postname = $name;
}
}
# Manage new keys
if ($NK) {
@ -141,6 +160,9 @@ s/^virtualHosts\/([^\/]*)?\/header.*/exportedHeaders\/$1\/$name/;
$id =~
s/^virtualHosts\/([^\/]*)?\/rule.*/locationRules\/$1\/$name/;
# Virtual Host post
$id =~ s/^virtualHosts\/([^\/]*)?\/post.*/post\/$1\/$name/;
# SAML IDP attribute
$id =~
s/^samlIDPMetaDataExportedAttributes\/([^\/]*)?.*/samlIDPMetaDataExportedAttributes\/$1\/$name/;
@ -166,7 +188,7 @@ s/^generalParameters\/authParams\/choiceParams\/([^\/]*)?.*/authChoiceModules\/$
# Set current Virtual Host name
$id =~
s/^(exportedHeaders|locationRules)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$3/;
s/^(exportedHeaders|locationRules|post)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$3/;
# Set current SAML IDP name
$id =~
@ -176,6 +198,9 @@ s/^(samlIDPMetaDataXML|samlIDPMetaDataExportedAttributes|samlIDPMetaDataOptions)
$id =~
s/^(samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$spname\/$3/;
# Set current POST URL name
$id =~ s/^(post)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$postname/;
$self->lmLog( "id transformed into $id", 'debug' );
if ( $id =~
@ -279,6 +304,29 @@ s/^(samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions)\/(
"application" );
}
# Post URL
elsif ($postflag) {
$self->lmLog( "Register POST URL $name data", 'debug' );
# Set postUrl
$self->setKeyToH(
$newConf, "post/$vhostname",
"$postname", { postUrl => $value }
) if $value;
}
# Post data
elsif ($postdataflag) {
$self->lmLog( "Register POST data $name", 'debug' );
# Set post data in expr
$self->setKeyToH( $newConf, "post/$vhostname", "$postname",
{ expr => { $name => $value } } )
if $value;
}
# Default case
else {
$self->setKeyToH(
$newConf, $confKey,
@ -636,11 +684,42 @@ sub setKeyToH {
);
$tmp->{$key} = {};
}
# Value can be an hashref
if ( ref($value) eq 'HASH' ) {
foreach my $vv ( keys %$value ) {
# vv can be an hashref
if ( ref( $value->{$vv} ) eq 'HASH' ) {
foreach my $vvv ( keys %{ $value->{$vv} } ) {
$self->lmLog(
"setKeyToH: set "
. $value->{$vv}->{$vvv}
. " in key $vvv in key $vv in key $k2 inside key $key",
'debug'
);
$tmp->{$key}->{$k2}->{$vv}->{$vvv} =
$value->{$vv}->{$vvv};
}
}
else {
$self->lmLog(
"setKeyToH: set "
. $value->{$vv}
. " in key $vv in key $k2 inside key $key",
'debug'
);
$tmp->{$key}->{$k2}->{$vv} = $value->{$vv};
}
}
}
else {
$self->lmLog(
"setKeyToH: set $value in key $k2 inside key $key",
'debug' );
$tmp->{$key}->{$k2} = $value;
}
}
else {
$self->lmLog( "setKeyToH: set $value in key $key", 'debug' );
$tmp->{$key} = $value;

View File

@ -29,7 +29,7 @@ sub cstruct {
%$h,
virtualHosts => {
$k2 => {
_nodes => [qw(rules:rules:rules headers)],
_nodes => [qw(rules:rules:rules headers post:post:post)],
rules => {
_nodes => ["hash:/locationRules/$k2:rules:rules"],
_js => 'rulesRoot'
@ -38,6 +38,10 @@ sub cstruct {
_nodes => ["hash:/exportedHeaders/$k2"],
_js => 'hashRoot'
},
post => {
_nodes => ["post:/post/$k2:post:post"],
_js => 'postRoot'
},
}
}
);
@ -759,7 +763,7 @@ sub struct {
#################
virtualHosts => {
_nodes => ['nhash:/locationRules:virtualHosts:vhost'],
_upload => ['/exportedHeaders'],
_upload => [ '/exportedHeaders', '/post' ],
_help => 'virtualHosts',
_js => 'vhostRoot',
},
@ -1305,6 +1309,11 @@ sub testStruct {
test => qr/\w+$/,
msgFail => 'Unvalid session field',
},
post => {
keyTest => Lemonldap::NG::Common::Regexp::HOSTNAME,
keyMsgFail => 'Bad virtual host name',
'*' => { keyTest => $pcre, },
},
protection => {
keyTest => qr/^(?:none|authentificate|manager|)$/,
msgFail => 'must be one of none authentificate manager',
@ -1763,6 +1772,7 @@ sub subDefaultConf {
},
notificationStorageOptions =>
{ dirName => '/var/lib/lemonldap-ng/notifications', },
post => { none => { expr => {}, }, },
remoteGlobalStorageOptions => {
'proxy' => 'https://remote/index.pl/sessions',
'ns' => 'https://remote/Lemonldap/NG/Common/CGI/SOAPService',

View File

@ -215,6 +215,7 @@ sub en {
portalRequireOldPassword => 'Require old password',
portalSkin => 'Skin',
portalUserAttr => 'User attribute',
post => 'Form replay',
proxyParams => 'Proxy parameters',
randomPasswordRegexp => 'Regexp for password generation',
redirection => 'Handler redirections',
@ -573,6 +574,7 @@ sub fr {
portalRequireOldPassword => 'Ancien mot de passe requis',
portalSkin => 'Thème visuel',
portalUserAttr => "Attribut de l'utilisateur",
post => 'Rejeu de formulaires',
proxyParams => 'Paramètres Proxy',
randomPasswordRegexp =>
'Expression regulière pour la génération des mots de passe',