Skip to content
Snippets Groups Projects
Commit e53cfccb authored by renater.salaun's avatar renater.salaun
Browse files

First version of the web interface

git-svn-id: https://svn.geant.net/GEANT/edugain_testidp_account_manager/trunk@8 047e039d-479c-447e-8a29-aa6bf4a09bab
parent aa574f40
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/perl
## 15/09/2014, Olivier Salaün
## Web interface for the eduGAIN Test IdP Account Manager
## TODO : rename %erreurs e
use strict;
use utf8;
use lib "/opt/testidp/IdPAccountManager/lib";
use CGI;
use CGI::Cookie;
use CGI::Util;
use Template;
use Template::Constants qw( :debug );
use POSIX;
use IdPAccountManager::TestAccount;
## Defining parameters format
my $urn_or_url_regex = '(http(s?):\/\/|urn:)[^\\\$\*\"\'\`\^\|\<\>\n\s]+'; ## Format de type URL HTTP ou URN
my $url_regex = 'http(s?):\/\/[^\\\$\*\"\'\`\^\|\<\>\n\s]+';
my $email_regex = '([\w\-\_\.\/\+\=\'\&]+|\".*\")\@[\w\-]+(\.[\w\-]+)+';
my $domains_regex = '[\w\.\-]+(,[\w\.\-]+)*';
my %format = (
## URL
#'attributeauthority' => $url_regex,
);
my %actions = ('select_sp' => {'title_en' => 'Select your Service Provider' }
);
## Gives writes for the group
umask 0002;
chdir $IdPAccountManager::Conf::global{'root_manager_dir'};
my $request = new WebRequest;
if (defined $request) {
$request->execute();
}
$request->respond();
package WebRequest;
## New web request
sub new {
my $pkg = shift;
my $request = {};
my $http_query = new CGI;
## Input parameters
my %in_vars = $http_query->Vars;
$request->{'param_in'} = \%in_vars;
## Check if admin acts as another user
$request->{'cookies'} = CGI::Cookie->fetch;
#if (defined $request->{'cookies'}{'as_user'} && $request->{'is_admin'}) {
# $request->{'utilisateur'} = $request->{'as_user'} = $request->{'cookies'}{'as_user'}->value;
# $request->{'is_admin'} = 0;
#}
## Usefull data for output (web pages or mail notices)
$request->{'param_out'}{'url_cgi'} = $ENV{'SCRIPT_NAME'};
$request->{'param_out'}{'env'} = \%ENV;
$request->{'param_out'}{'actions'} = \%actions;
$request->{'param_out'}{'conf'} = \%IdPAccountManager::Conf::global;
## Dumping input data
#open TMP, ">/tmp/account_manager.in"; &IdPAccountManager::Tools::dump_var($request->{'param_in'}, 0, \*TMP); close TMP;
## Clean input vars
foreach my $key (keys %{$request->{'param_in'}}) {
#&IdPAccountManager::Tools::do_log('trace', "PARAM_ENTREE: %s=%s", $key, $request->{'param_in'}{$key});
## Removing all ^M (0D)
$request->{'param_in'}{$key} =~ s/\r//g;
$request->{'param_in'}{$key} =~ s/\s+$//; ## Remove trailing spaces
$request->{'param_in'}{$key} =~ s/^\s+//; ## Remove leading spaces
#if ($request->{'param_in'}{$key} =~ /\0/) {
# my @valeurs = split /\0/, $request->{'param_in'}{$key};
# $request->{'param_in'}{$key} = $valeurs[0]; ## Only keep first value of multi-valued parameters
#}
## If action_xx param is set, then action=xx
## Usefull to have sementicless values in submit forms
if ($key =~ /^action_(\w+)$/) {
#&IdPAccountManager::Tools::do_log('trace', "ACTION $key");
$request->{'param_in'}{'action'} = $1;
}
}
## Check the requested action
if ($request->{'param_in'}{'action'} ) {
$request->{'action'} = $request->{'param_in'}{'action'};
}else {
## Default action
&IdPAccountManager::Tools::do_log('info', "Default action");
$request->{'action'} = 'help';
}
bless $request, $pkg;
return $request;
}
## Execute a web request
sub execute {
my $self = shift;
&IdPAccountManager::Tools::do_log('debug', "");
my $status;
## Check input parameters format
foreach my $key (keys %{$request->{'param_in'}}) {
if ($self->{'param_in'}{$key} !~ /^\s*$/ &&
defined $format{$key} &&
! ref($format{$key})) {
unless ($self->{'param_in'}{$key} =~ /^$format{$key}$/) {
push @{$self->{'param_out'}{'erreurs'}}, "format_$key";
&IdPAccountManager::Tools::do_log('error', "Incorrect parameter format : $key");
return undef;
}
}
}
do {
## Actions can be chained
$self->{'action'} = $self->{'next_action'} if ($self->{'next_action'});
delete $self->{'next_action'}; ## Prevent loops
if (defined $actions{$self->{'action'}}) {
## Execute the target subroutine named req_actionName
my $sub = 'req_'.$self->{'action'};
$status = &{$sub}($self);
}else {
## Inknown action
push @{$self->{'param_out'}{'erreurs'}}, "unknown_action";
&IdPAccountManager::Tools::do_log('error', "Unknown action '%s'", $self->{'action'});
}
} while ($self->{'next_action'});
#return undef if (!defined $status);
return 1;
}
## Return HTML content
sub respond {
my $self = shift;
&IdPAccountManager::Tools::do_log('debug', "");
## Dump output data
#open TMP, ">/tmp/account_registry.out"; &IdPAccountManager::Tools::dump_var($self->{'param_out'}, 0, \*TMP); close TMP;
## Automatic pass object entries to the output hash
foreach my $key (keys %{$self}) {
#&IdPAccountManager::Tools::do_log('trace', "Passing $key");
$self->{'param_out'}{$key} ||= $self->{$key} unless ($key eq 'param_out');
}
## An action may redirect to an external URL
if ($self->{'url_redirection'}) {
#&IdPAccountManager::Tools::do_log('trace', "URL Redirect : $self->{'url_redirection'}");
printf "Location: %s\n\n", $self->{'url_redirection'};
}else {
#$self->{'param_out'}{'cookie'} = CGI::Cookie->new(-name=>'as_user',-value=>$self->{'as_user'},-expires=>'-1M');
## Parse template
my $tt2 = Template->new({
ENCODING => 'iso-8859-1', ## le défaut apparemment
FILTERS => {'encode_utf8', => [\&IdPAccountManager::Tools::encode_utf8, 0],
'escape_quotes' => [\&IdPAccountManager::Tools::escape_quotes, 0]},
#DEBUG => 'all',
#DEBUG => 'caller',
#DEBUG => 'parser'
});
my $template = 'templates/web/index.tt2.html';
unless ($tt2->process($template, $self->{'param_out'}, \*STDOUT)) {
printf "Content-type: text/plain\n\n Error: %s", $tt2->error();
&IdPAccountManager::Tools::do_log('error', "Web parser error : %s", $tt2->error());
}
}
## Ignore some type of errors
my @erreurs_admin;
foreach my $id_erreur (@{$self->{'param_out'}{'erreurs'}}) {
unless ($id_erreur =~ /^(error_x)$/) {
push @erreurs_admin, $id_erreur;
}
}
## Mail notification of admins about the error
if (@erreurs_admin) {
&IdPAccountManager::Tools::mail_notice('template' => 'templates/mail/notification_generic_error.tt2.eml',
'data' => $self->{'param_out'});
}
}
\ No newline at end of file
......@@ -135,6 +135,70 @@ sub do_log {
return 1;
}
## Send a mail notice
## Default is to send email to the manager admins, unless other recipients are specified
## mail_notice(IN)
## IN is a HASH with expected entries :
## template : mail template file
## data : data used by the TT2 parser
sub mail_notice {
my %in = @_;
my $tt2_file = $in{'template'};
my $mail_data = $in{'data'};
$mail_data->{'conf'} ||= \%IdPAccountManager::Conf::global;
my $notice_email = $in{'to'} || $IdPAccountManager::Conf::global{'admin_email'};
$mail_data->{'to'} = $notice_email;
## Protection to prevent notifications during test dev phases
## Notify only adresses @renater.fr
if ($IdPAccountManager::Conf::global{'no_mail_outside'}) {
foreach my $email (split /,/, $notice_email) {
unless ($email =~ /\@(cru|renater)\.fr$/) {
&do_log('error',"Notification to an external address skipped");
return undef;
}
}
}
&do_log('trace', '(template=%s, to=%s)', $in{'template'}, $mail_data->{'to'});
open SENDMAIL, "|/usr/sbin/sendmail -f ".$IdPAccountManager::Conf::global{'notice_from'}." $notice_email";
my $tt2 = Template->new(FILTERS => {qencode => [\&qencode, 0]});
unless ($tt2->process($tt2_file, $mail_data, \*SENDMAIL)) {
&do_log('error', "Erreur TT2 : %s", $tt2->error());
}
close SENDMAIL;
}
sub qencode {
my $string = shift;
# We are not able to determine the name of header field, so assume
# longest (maybe) one.
return MIME::EncWords::encode_mimewords(Encode::decode('utf8', $string),
Encoding=>'A',
Charset=> 'utf8',
Field=>"subject");
}
## usefull to pass parameters to TT2
sub encode_utf8 ($) {
my $string = shift||'';
return Encode::encode('utf8', $string);
}
## usefull to pass parameters to TT2
sub escape_quotes {
my $string = shift;
$string =~ s/\'/\\\'/g;
return $string;
}
1; # Magic true value required at end of module
__END__
......
resources/geant_logo_rgb_300dpi.jpg

70.6 KiB

From: [% conf.app_name %] <[% conf.notice_from %]>
To: [% to %]
Subject: [% subject %]
Content-type: text/plain; charset=UTF-8; format=flowed
You receive this notification as administrator of the eduGAIN Test Account Manager
An error occured during test account processing.
[% IF error_type == 'skipping_provider_metadata_issue' %]
Le fichier de méta-données pour le provider [% entityid %] a un format incorrect ou n'a pas pu être téléchargé.
L'URL des méta-données : [% provider.get('metadataurl') %]
Check logs for more details
[% ELSE %]
Error: [% error_type %]
Check logs for more details
[% END %]
[% IF action == 'select_sp' %]
[% TRY %]
[% PROCESS 'templates/select_sp.tt2.html' %]
[% CATCH %]
An error occured
[% END %]
[% ELSE %]
Error: unknown action
[% END %]
Content-Type: text/html
[% IF cookie %]Set-Cookie: [% cookie %][% END %]
<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x
html1/DTD/xhtml1-transitional.dtd">
<html xml:lang="[% iso639 = locale.match('^(.)(.)'); iso639.0; iso639.1 %]" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link type="text/css" href="/jquery/jquery-ui-1.8.16/css/smoothness/jquery-ui-1.8.16.custom.css" rel="Stylesheet" />
<link rel="stylesheet" media="screen" type="text/css" href="/css/renater.css" />
<link rel="icon" type="image/png" href="/images/favicon.png" />
<script type="text/javascript" src="/jquery/jquery-1.7.min.js"></script>
<script type="text/javascript" src="/jquery/jquery-ui-1.8.16.custom.min.js"></script>
<SCRIPT TYPE="text/javascript">
<!--
// To confirm on a link (A HREF)
function request_confirm_link(my_url, my_message) {
question = confirm(my_message);
if (question !="0") {
top.location = my_url;
}
}
function showhide(div){
var oDiv = document.getElementById(div);
if(oDiv.style.display == "none"){
oDiv.style.display = "block";
}else{
oDiv.style.display = "none";
}
}
function hide(div) {
var oDiv = document.getElementById(div);
oDiv.style.display = "none";
}
//-->
</SCRIPT>
<STYLE type="text/css"><!--
.login {float: left}
.menu {float: right}
.footer {text-align: center}
.prod {background-color: #028A34}
h1 {text-align: center}
li,dd {margin-left:10px;}
li.parametre {margin-bottom: 15px;}
dd.parametre {margin-bottom: 15px;}
div.important{border-style:solid;border-color:black;border-width:1px;background-color:#F5DEB3;padding:5px;}
.mandatory{color:#e00853;font-style:italic;font-weight:bold;margin:0 3px}
.notice{border:2px solid #05a;padding:5px 5px 5px 5px;margin:20px;}
--></STYLE>
<title> [% PROCESS 'templates/web/title.tt2.html' %] </title>
</head>
<body>
<div id="wrapper">
<div id="header">
<div id="bandeau">
<div class="logo">
<img alt="GEANT logo" width="150" src="/resources/geant_logo_rgb_300dpi.jpg"/>
</div>
<div class="connection">
</div>
<div class="title">
[% PROCESS 'templates/web/title.tt2.html' %]
</div>
</div>
<div id="content">
[% IF erreurs %]
<div class="ui-widget">
[% FOREACH err IN erreurs %]
<p class="ui-state-error ui-corner-all" style="margin-top: 20px; padding: 0 .7em;"><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>
[% IF lang == 'en' %]Error: [% ELSE %]Erreur : [% END %]
[% IF err == 'unknown_action' %]
[% IF lang == 'en' %]Unknown action[% ELSE %]action non supportée.[% END %]
[% ELSIF err == 'internal' %]
[% IF lang == 'en' %]internal error; administrators of the federation registry have been notified.[% ELSE %]erreur interne ; les administrateurs du guichet de la fédération ont été notifiés.[% END %]
[% ELSIF (matches = err.match('missing_(\w+)')) %]
[% IF lang == 'en' %]missing parameter '[% matches.0 %]'[% ELSE %]paramètre '[% matches.0 %]' manquant.[% END %]
[% ELSE %]
[% err %]
[% END %] <!-- autorisation -->
</p>
<br/>
[% END %] <!-- FOREACH -->
</div>
[% ELSE %]
[% IF notifications %]
<div class="ui-widget">
[% FOREACH notif IN notifications %]
<p class="ui-state-highlight ui-corner-all" style="border: 2px solid #10427a; background: #DFF1EE;padding: 0.7em;"><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>
[% IF lang == 'en' %]Notice: [% ELSE %]Notification : [% END %]
[% IF notif == 'done' %]
[% IF lang == 'en' %]Operation has been performed[% ELSE %]L'opération a été effectuée;[%END%]
[% ELSE %]
[% notif %]<br/>
[% END %]
[% END %] <!-- FOREACH -->
</b></div>
[% END %] <!-- notifications -->
[% PROCESS 'templates/web/content.tt2.html' %]
[% END %] <!-- IF erreurs -->
<p>
[% IF dump %]
DUMP :<br>
[% USE Dumper %]
[% Dumper.dump_html(dump) %]
</p>
[% END %]
<div>
<hr>
<div align="middle">Test Account Manager [% conf.version %]</div>
</div>
</div>
</div>
</body>
</html>
[% conf.app_name %] -
[% IF actions.$action %]
[% FILTER encode_utf8 %][% actions.$action.title %][% END %]
[% ELSE %]
[% END %]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment