aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem.moulin@fripost.org>2012-09-04 22:00:19 +0200
committerGuilhem Moulin <guilhem.moulin@fripost.org>2012-09-04 22:00:19 +0200
commite652956aa8dd6160b078f396e3f89157c15294af (patch)
treef5daa06245f0277925d8d5ad7d74c9a097d4dbd8 /lib
parente04e3174c1c38e7587df495c19082a864f2373b2 (diff)
Edition of mailboxes, aliases and lists.
Diffstat (limited to 'lib')
-rw-r--r--lib/FPanel/Interface.pm240
1 files changed, 203 insertions, 37 deletions
diff --git a/lib/FPanel/Interface.pm b/lib/FPanel/Interface.pm
index 79e36b5..aa5b554 100644
--- a/lib/FPanel/Interface.pm
+++ b/lib/FPanel/Interface.pm
@@ -42,7 +42,7 @@ sub ListDomains : StartRunmode {
fripostOwner
fripostPostmaster/ ]
);
- die $domains->error if $domains->code;
+ die '403' if $domains->code;
$ldap->unbind;
@@ -53,10 +53,10 @@ sub ListDomains : StartRunmode {
$template->param( USER_LOCALPART => $l, USER_DOMAINPART => $d);
$template->param( DOMAINS => [
map { { DOMAIN => $_->get_value('fvd')
+ # TODO: do we really want to list the permissions?
, PERMS => &list_perms_long($_, $authzDN)
, DESCRIPTION => join ("\n", $_->get_value('description'))
- , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE' ?
- 1 : 0
+ , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE'
};
}
$domains->sorted('fvd')
@@ -65,7 +65,7 @@ sub ListDomains : StartRunmode {
}
-# This Run Mode lists the known aliases, users and lists in the current
+# This Run Mode lists the known mailboxes, aliases and lists in the current
# domain.
sub ListLocals : Runmode {
my $self = shift;
@@ -91,9 +91,11 @@ sub ListLocals : Runmode {
fripostOwner
fripostPostmaster/ ]
);
- die $domains->error if $domains->code;
- die "Error: Domains not found" unless $domains->count;
- die "Error: Multiple domains found" if $domains->count > 1;
+ die '404' if $domains->code;
+ # The following is not supposed to happen.
+ die "Error: Multible matching entries found." if $domains->count > 1;
+ my $domain = $domains->pop_entry or die '404';
+
# Query the mailboxes under the given domain
my $mailboxes = $ldap->search( base => "fvd=$domainname,$suffix"
@@ -105,6 +107,7 @@ sub ListLocals : Runmode {
fripostOptionalMaildrop
fripostMailboxQuota/ ]
);
+ # We don't return 403 or 404 here, since it's not supposed to crash.
die $mailboxes->error if $mailboxes->code;
# Query the aliases under the given domain
@@ -117,6 +120,7 @@ sub ListLocals : Runmode {
fripostOwner
fripostMaildrop/ ]
);
+ # We don't return 403 or 404 here, since it's not supposed to crash.
die $aliases->error if $aliases->code;
# Query the lists under the given domain
@@ -129,11 +133,14 @@ sub ListLocals : Runmode {
fripostOwner
fripostListManager/ ]
);
+ # We don't return 403 or 404 here, since it's not supposed to crash.
die $lists->error if $lists->code;
$ldap->unbind;
- my $domain = $domains->entry('0');
+ # Get the perms of the autenticated user, so that we know where
+ # should put "add" and "edit" links (the LDAP ACLs back that up
+ # eventually, anyway).
my $perms = &list_perms($domain, $authzDN);
my $template = $self->load_tmpl( 'list-locals.html', cache => 1, utf8 => 1
@@ -146,7 +153,7 @@ sub ListLocals : Runmode {
$template->param( DESCRIPTION =>
join ("\n", $domain->get_value('description')) );
$template->param( ISACTIVE =>
- $domain->get_value('fripostIsStatusActive') eq 'TRUE' ? 1 : 0 );
+ $domain->get_value('fripostIsStatusActive') eq 'TRUE' );
# Can the user edit the domain (change description, toggle
# activation, modify catchalls?)
$template->param( CANEDIT => $perms =~ /[op]/ );
@@ -158,8 +165,7 @@ sub ListLocals : Runmode {
$template->param( MAILBOXES => [
map { { USER => $_->get_value('fvu')
, DESCRIPTION => join ("\n", $_->get_value('description'))
- , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE' ?
- 1 : 0
+ , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE'
, FORWARDS => [ map { {FORWARD => $_} }
$_->get_value('fripostOptionalMaildrop') ]
, QUOTA => $_->get_value('fripostMailboxQuota') // ''
@@ -176,8 +182,8 @@ sub ListLocals : Runmode {
$template->param( ALIASES => [
map { { ALIAS => $_->get_value('fva')
, DESCRIPTION => join ("\n", $_->get_value('description'))
- , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE' ?
- 1 : 0
+ , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE'
+ # TODO: do we really want to list the owners?
, OWNERS => [ map { {OWNER => &dn2email($_)} }
$_->get_value('fripostOwner') ]
, DESTINATIONS => [ map { {DESTINATION => $_} }
@@ -188,6 +194,7 @@ sub ListLocals : Runmode {
]);
$template->param( CATCHALLS => [ map { {CATCHALL => $_} }
$domain->get_value('fripostOptionalMaildrop') ]
+ # TODO: do we really want to list the owners?
, OWNERS => [ ( map { {OWNER => &dn2email($_)} }
$domain->get_value('fripostOwner') )
, ( map { {OWNER => &dn2email($_)} }
@@ -201,8 +208,8 @@ sub ListLocals : Runmode {
$template->param( LISTS => [
map { { LIST => $_->get_value('fvl')
, DESCRIPTION => join ("\n", $_->get_value('description'))
- , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE' ?
- 1 : 0
+ , ISACTIVE => $_->get_value('fripostIsStatusActive') eq 'TRUE'
+ # TODO: do we really want to list the owners?
, OWNERS => [ map { {OWNER => &dn2email($_)} }
$_->get_value('fripostOwner') ]
, TRANSPORT => $_->get_value('fripostListManager')
@@ -214,7 +221,8 @@ sub ListLocals : Runmode {
}
-# This is the page used to edit domains.
+# In this Run Mode authenticated users can edit the domain description
+# and catchall, and toggle activation (if they have the permission).
sub EditDomain : Runmode {
my $self = shift;
my %CFG = $self->cfg;
@@ -226,24 +234,26 @@ sub EditDomain : Runmode {
my $domainname = (split /\//, $ENV{PATH_INFO}, 3)[1];
- if (defined $self->query->param('submit') or
- defined $self->query->param('active')) {
+ my $error; # Tells wether the change submission has fails.
+ if (defined $self->query->param('submit')) {
# Changes have been submitted: process them
my %changes;
- if (defined $self->query->param('active')) {
- $changes{fripostIsStatusActive} = $self->query->param('active');
+ my $q = $self->query;
+ if (defined $q->param('status')) {
+ $changes{fripostIsStatusActive} = $q->param('status') eq 'active' ?
+ 'TRUE' : 'FALSE';
}
- if (defined $self->query->param('description')) {
+ if (defined $q->param('description')) {
my @desc;
- foreach my $d (split /\n/, $self->query->param('description')) {
+ foreach my $d (split /\n/, $q->param('description')) {
push @desc, $d;
}
$changes{description} = [ @desc ];
}
- if (defined $self->query->param('maildrop')) {
+ if (defined $q->param('maildrop')) {
my @maildrop;
- foreach my $d (split /\n/, $self->query->param('maildrop')) {
- $d =~ s/\s//g;
+ foreach my $d (split /\n/, $q->param('maildrop')) {
+ $d =~ s/\s//g; # lowercase and strip out the spaces
push @maildrop, (lc $d) unless $d =~ /^$/;
}
$changes{fripostOptionalMaildrop} = [ @maildrop ];
@@ -251,16 +261,19 @@ sub EditDomain : Runmode {
my $mesg = $ldap->modify( "fvd=$domainname,$suffix",
replace => \%changes );
- die $mesg->error if $mesg->code;
+ $error = $mesg->error if $mesg->code;
}
- my $answer = $ldap->search( base => "fvd=$domainname,$suffix"
- , scope => 'base'
- , filter => 'objectClass=FripostVirtualDomain'
- , deref => 'never'
- );
- die $answer->error if $answer->code;
- $answer = $answer->entry('0');
+ my $domains = $ldap->search( base => "fvd=$domainname,$suffix"
+ , scope => 'base'
+ , filter => 'objectClass=FripostVirtualDomain'
+ , deref => 'never'
+ );
+ die '404' if $domains->code;
+ # The following is not supposed to happen.
+ die "Error: Multible matching entries found." if $domains->count > 1;
+ my $domain = $domains->pop_entry or die '404';
+
$ldap->unbind;
my $template = $self->load_tmpl( 'edit-domain.html', cache => 1, utf8 => 1
@@ -270,12 +283,165 @@ sub EditDomain : Runmode {
$template->param( USER_LOCALPART => $l, USER_DOMAINPART => $d);
$template->param( DOMAIN => $domainname );
$template->param( DESCRIPTION =>
- join ("\n",$answer->get_value('description')) );
+ join ("\n",$domain->get_value('description')) );
$template->param( MAILDROP =>
- join ("\n",$answer->get_value('fripostOptionalMaildrop')) );
- $template->param( ISACTIVE => $answer->get_value('fripostIsStatusActive') eq 'TRUE' ?
- 1 : 0 );
+ join ("\n",$domain->get_value('fripostOptionalMaildrop')) );
+ $template->param( ISACTIVE => $domain->get_value('fripostIsStatusActive') eq 'TRUE' );
+ $template->param( NEWCHANGES => defined $self->query->param('submit') );
+ $template->param( ERROR => $error );
+ return $template->output;
+}
+
+
+# In this Run Mode authenticated users can edit the entry (if they have
+# the permission).
+sub EditLocal : Runmode {
+ my $self = shift;
+ my %CFG = $self->cfg;
+ my $suffix = join ',', @{$CFG{ldap_suffix}};
+
+ my ($l,$d) = split /@/, $self->authen->username, 2;
+ my $authzDN = "fvu=$l,fvd=$d,". $suffix;
+ my $ldap = $self->ldap_from_auth_user($authzDN);
+
+ my ($null,$domainname,$localname,$crap) = (split /\//, $ENV{PATH_INFO}, 4);
+
+ my $error; # Tells wether the change submission has fails.
+ if (defined $self->query->param('submit')) {
+ # Changes have been submitted: process them
+ my (%changes, $t2);
+ my $q = $self->query;
+ my $t = lc $q->param('t') // die "Error: Unknown type";
+
+ if ($t eq 'mailbox') {
+ $t2 = 'fvu';
+ if ($q->param('oldpassword') ne '' or
+ $q->param('newpassword') ne '' or
+ $q->param('newpassword2') ne '') {
+ # If the user tries to change the password, we make her
+ # bind first, to prevent an attacker from setting a
+ # custom password and accessing the emails.
+
+ if ($q->param('newpassword') eq $q->param('newpassword2')) {
+ my $ldap2 = Net::LDAP->new( $CFG{ldap_uri} );
+ my $mesg = $ldap2->bind ( "fvu=$l,fvd=$d,$suffix",
+ password => $q->param('oldpassword') );
+ if ($mesg->code) {
+ $error = "Wrong password (for ".$self->authen->username.").";
+ }
+ else {
+ my $pw = $q->param('newpassword');
+ # TODO: hash it.
+ $mesg = $ldap2->modify( "fvu=$localname,fvd=$domainname,$suffix",
+ replace => { userPassword => $pw } );
+ $error = $mesg->error if $mesg->code;
+ }
+ $ldap2->unbind;
+ }
+ else {
+ $error = "Password don't match.";
+ }
+ }
+
+ if (defined $q->param('maildrop')) {
+ my @maildrop;
+ foreach my $d (split /\n/, $q->param('maildrop')) {
+ $d =~ s/\s//g; # lowercase and strip out the spaces
+ push @maildrop, (lc $d) unless $d =~ /^$/;
+ }
+ $changes{fripostOptionalMaildrop} = [ @maildrop ];
+ }
+ }
+
+ elsif ($t eq 'alias') {
+ $t2 = 'fva';
+ if (defined $q->param('maildrop')) {
+ my @maildrop;
+ foreach my $d (split /\n/, $q->param('maildrop')) {
+ $d =~ s/\s//g; # lowercase and strip out the spaces
+ push @maildrop, (lc $d) unless $d =~ /^$/;
+ }
+ $changes{fripostMaildrop} = [ @maildrop ];
+ }
+ }
+
+ elsif ($t eq 'list') {
+ $t2 = 'fvl';
+ }
+
+ else {
+ die "Error: Unknown type";
+ }
+
+ # Global parameters
+ if (defined $q->param('status')) {
+ $changes{fripostIsStatusActive} = $q->param('status') eq 'active' ?
+ 'TRUE' : 'FALSE';
+ }
+ if (defined $q->param('description')) {
+ my @desc;
+ foreach my $d (split /\n/, $q->param('description')) {
+ push @desc, $d;
+ }
+ $changes{description} = [ @desc ];
+ }
+
+ unless (defined $error) {
+ my $mesg = $ldap->modify( "$t2=$localname,fvd=$domainname,$suffix",
+ replace => \%changes );
+ $error = $mesg->error if $mesg->code;
+ }
+ }
+
+ # Query *the* matching mailbox, alias or list.
+ my $locals = $ldap->search( base => "fvd=$domainname,$suffix"
+ , scope => 'one'
+ , filter => "(|(&(objectClass=FripostVirtualMailbox)
+ (fvu=$localname))
+ (&(objectClass=FripostVirtualAlias)
+ (fva=$localname))
+ (&(objectClass=FripostVirtualList)
+ (fvl=$localname))
+ )"
+ , deref => 'never'
+ , attrs => [ qw/fvu description
+ fripostIsStatusActive
+ fripostOptionalMaildrop
+ fripostMailboxQuota
+ fva fripostMaildrop
+ fvl fripostListManager/ ]
+ );
+ die '404' if $locals->code;
+ # The following is not supposed to happen.
+ die "Error: Multible matching entries found." if $locals->count > 1;
+ my $local = $locals->pop_entry or die '404';
+
+ my $template;
+ if ($local->dn =~ /^fvu=/) {
+ $template = $self->load_tmpl( 'edit-mailbox.html', cache => 1, utf8 => 1 );
+ $template->param( MAILBOX => $local->get_value('fvu') );
+ $template->param( MAILDROP =>
+ join ("\n",$local->get_value('fripostOptionalMaildrop')) );
+ }
+ elsif ($local->dn =~ /^fva=/) {
+ $template = $self->load_tmpl( 'edit-alias.html', cache => 1, utf8 => 1 );
+ $template->param( ALIAS => $local->get_value('fva') );
+ $template->param( MAILDROP =>
+ join ("\n",$local->get_value('fripostMaildrop')) );
+ }
+ elsif ($local->dn =~ /^fvl=/) {
+ $template = $self->load_tmpl( 'edit-list.html', cache => 1, utf8 => 1 );
+ $template->param( LIST => $local->get_value('fvl') );
+ }
+
+ $template->param( URL => $self->query->url );
+ $template->param( DOMAIN => $domainname );
+ $template->param( USER_LOCALPART => $l, USER_DOMAINPART => $d);
+ $template->param( DESCRIPTION =>
+ join ("\n",$local->get_value('description')) );
+ $template->param( ISACTIVE => $local->get_value('fripostIsStatusActive') eq 'TRUE' );
$template->param( NEWCHANGES => defined $self->query->param('submit') );
+ $template->param( ERROR => $error );
return $template->output;
}