diff options
Diffstat (limited to 'lib/Fripost/Panel')
-rw-r--r-- | lib/Fripost/Panel/Interface.pm | 309 |
1 files changed, 117 insertions, 192 deletions
diff --git a/lib/Fripost/Panel/Interface.pm b/lib/Fripost/Panel/Interface.pm index a0c9dd9..7f7d770 100644 --- a/lib/Fripost/Panel/Interface.pm +++ b/lib/Fripost/Panel/Interface.pm @@ -216,8 +216,8 @@ sub ListLocals : Runmode { my @lists = grep { $_->{type} eq 'list' } @locals; # Add a link to the list (external) homepage. - map { $_->{listURL} = $CFG{'listurl_'.$_->{transport}}. - email_to_ascii($_->{name}.'@'.$domainname) } + map { $_->{list_URL} = $CFG{'listurl_'.$_->{transport}}. + email_to_ascii($_->{name}.'@'.$domainname) } @lists; my $template = $self->load_tmpl( 'list-locals.html', cache => 1, @@ -256,258 +256,183 @@ sub ListLocals : Runmode { # Can the user add lists? $template->param( canAddList => $domain->{permissions} =~ /[lop]/ ); $template->param( listCanAddList => [ map { {item => encode_entities($_)} } - @{$domain->{canAddList}} ] ) + @{$domain->{canAddList}} ] ) if $domain->{permissions} =~ /[op]/; # Should we list lists? $template->param( listLists => $#lists >= 0 || $domain->{permissions} =~ /[lop]/ ); $template->param( lists => [ - map { {&fill_HTML_template_from_entry ($_, -loop => ['destination'])} } + map { { &fill_HTML_template_from_entry ($_, -loop => ['destination'] ) + , isPending => $_->{isPending} + } } @lists ]); return $template->output; } -# In this Run Mode authenticated users can edit the entry (if they have -# the permission). -sub EditLocal : Runmode { +# In this Run Mode authenticated users can add users, aliases and lists +# (if they have the permission). +sub AddLocal : Runmode { my $self = shift; my %CFG = $self->cfg; my $q = $self->query; - return $self->redirect('../') if defined $q->param('cancel'); + return $self->redirect('./') if defined $q->param('cancel'); # Cancellation + # Get the domain name from the URL. + my $domainname = ($self->split_path)[1]; + my $t = $q->param('t') // return $self->redirect('./'); + return $self->redirect('./') unless grep { $t eq $_ } qw/user alias list/; my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); - # Search for *the* matching user, alias or list. - my ($d,$l) = ($self->split_path)[1,2]; - $fp->domain->get ($d, -die => 404, -assert_exist => 1); - my %local = $fp->local->get ($l.'@'.$d, -die => 404, - -concat => "\x{0D}\x{0A}" ); - die "Unknown type" unless grep { $local{type} eq $_ } - qw/user alias list/; - die "404\n" if $local{ispending}; - my $error; # Tells whether the change submission has failed. - my $t = $local{type}; - - if (defined $q->param('a') and $q->param('a') eq 'delete') { - # Delete the entry - $error = $fp->$t->delete($l.'@'.$d, -die => 0); - unless ($error) { - $fp->done; - return $self->redirect('../'); - } - } if (defined $q->param('submit')) { # Changes have been submitted: process them - my %entry; - if ($t eq 'user') { - $entry{user} = $l.'@'.$d; - $entry{forwards} = $q->param('forwards') // undef; - - if (($q->param('oldpw') // '') ne '' or - ($q->param('newpw') // '') ne '' or - ($q->param('newpw2') // '') 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('newpw') ne $q->param('newpw2')) { - $error = "Passwords do not match"; - } - elsif (length $q->param('newpw') < $CFG{password_min_length}) { - $error = "Password should be at least " - .$CFG{password_min_length} - ." characters long."; - } - else { - my $fp; - eval { - my $u = email_to_unicode($self->authen->username); - $fp = Fripost::Schema::->auth( - $u, - $q->param('oldpw') // '', - %CFG, - -die => "Wrong password (for ‘".$u."’)." ); - }; - $error = $@ || $fp->user->passwd( - $entry{user}, - Fripost::Password::hash($q->param('newpw') // '') - ); - $fp->done if defined $fp; - } + my $local = &parse_CGI_query($q); + $local->{type} = $q->param('t'); + $local->{name} = $q->param('name').'@'.$domainname; + my %rest; + + if ($q->param('password') || $q->param('password2')) { + if ($q->param('password') ne $q->param('password2')) { + $error = "Passwords do not match"; } + # TODO: ! move that to Password.pm + elsif (length $q->param('password') < $CFG{password_min_length}) { + $error = "Password should be at least " + .$CFG{password_min_length} + ." characters long."; + } + else { + $local->{password} = Fripost::Password::hash($q->param('password')); + } + # TODO: inherit the user quota from the postmaster's? } - elsif ($t eq 'alias') { - $entry{alias} = $l.'@'.$d; - $entry{maildrop} = $q->param('maildrop') // undef; - } - elsif ($t eq 'list') { - $entry{list} = $l.'@'.$d; - $entry{transport} = $q->param('transport') // undef; - } - $entry{isactive} = $q->param('isactive') // 1; - $entry{description} = $q->param('description') // undef; - $error = $fp->$t->replace( \%entry, -concat => "(\n|\x{0D}\x{0A})") - unless $error; - } + $local->{password} = $q->param('password') if $t eq 'list'; - my $template = $self->load_tmpl( "edit-$t.html", cache => 1 ); - $template->param( $self->userInfo ); - $template->param( domain => encode_entities($d) ); + $rest{gpg} = { use_agent => 0 + , keydir => $CFG{gpghome} + , key => $CFG{gpg_private_key_id} + , passphrase => $CFG{gpg_private_key_passphrase} + }; - if ($error and defined $q->param('submit')) { - # Preserve the (incorrect) form, except the passwords - if ($t eq 'user') { - $template->param( user => encode_entities($l) - , forwards => $q->param('forwards') // undef ); - } - elsif ($t eq 'alias') { - $template->param( alias => encode_entities($l) - , maildrop => $q->param('maildrop') // undef ); - } - elsif ($t eq 'list') { - $template->param( list => encode_entities($l) ); - } - $template->param( isactive => $q->param('isactive') // 1 - , description => $q->param('description') // undef ); - } - else { - %local = $fp->local->get ($l.'@'.$d, -die => 404, - -concat => "\x{0D}\x{0A}" ); - if ($t eq 'user') { - $template->param( user => encode_entities($local{user}) - , forwards => encode_entities($local{forwards}) ); - } - elsif ($t eq 'alias') { - $template->param( alias => encode_entities($local{alias}) - , maildrop => encode_entities($local{maildrop}) ); - } - elsif ($t eq 'list') { - $template->param( list => encode_entities($local{list}) ); + unless ($error) { + my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); + $fp->domain->search ($domainname, -filter => 'unlocked', -count => 1) + or die "404\n"; + $fp->local->add( $local, %rest, -error => \$error ); + $fp->done; + return $self->redirect('./') unless $error; } - $template->param( isactive => $local{isactive} - , description => $local{description} ); } - $fp->done; - my $news = (defined $q->param('submit') or - (defined $q->param('a') and $q->param('a') eq 'delete')); - $template->param( newChanges => $news ); + + # Do not send passwords back to the sender. + $q->delete(qw/password password2/); + + my $template = $self->load_tmpl( "add-$t.html", cache => 1 ); + $template->param( $self->userInfo + , domainname => encode_entities($domainname) + , &fill_HTML_template_from_query ($q)); + $template->param( transport => + [ { item => 'mailman', selected => $q->param('transport') eq 'mailman', name => 'GNU Mailman' } + , { item => 'schleuder', selected => $q->param('transport') eq 'schleuder', name => 'Schleuder' } + ]) # TODO ugly + if $t eq 'list' and defined $q->param('transport'); $template->param( error => encode_entities ($error) ) if $error; - $template->param( canDelete => 1 ) if $t eq 'alias'; - $template->param( listURL => $CFG{'listurl_'.$local{transport}}. - email_to_ascii($l.'@'.$d) ) - if $t eq 'list'; - $q->delete('a'); return $template->output; } - -# In this Run Mode authenticated users can add users, aliases and lists -# (if they have the permission). -sub AddLocal : Runmode { +# 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 $q = $self->query; - return $self->redirect('./') if defined $q->param('cancel'); + return $self->redirect('./') if defined $q->param('cancel'); # Cancellation + + # Get the domain name from the URL. + my ($localname,$domainname) = ($self->split_path)[2,1]; + my $name = $localname.'@'.$domainname; + my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); + + # Search for *the* matching user, alias or list. + $fp->domain->search ($domainname, -filter => 'unlocked', -count => 1) + or die "404\n"; + my $local = $fp->local->search ($name, -filter => 'unlocked') + or die "404\n"; - my $d = ($self->split_path)[1]; - my $t = $q->param('t') // die "Undefined type"; my $error; # Tells whether the change submission has failed. + if (defined $q->param('a') and $q->param('a') eq 'delete') { + # Delete the entry + $fp->local->delete($name, -error => \$error ); + unless ($error) { + $fp->done; + return $self->redirect('../'); + } + } + $fp->done; + if (defined $q->param('submit')) { # Changes have been submitted: process them - my %entry; + my $local = &parse_CGI_query($q); + $local->{type} = $q->param('t'); + $local->{name} = $name; my %rest; - if ($t eq 'user') { - $entry{user} = $q->param('user').'@'.$d; - $entry{forwards} = $q->param('forwards'); - if ($q->param('password') ne $q->param('password2')) { - $error = "Passwords do not match"; - } - elsif (length $q->param('password') < $CFG{password_min_length}) { - $error = "Password should be at least " - .$CFG{password_min_length} - ." characters long."; - } - else { - $entry{password} = Fripost::Password::hash($q->param('password')); - } - # TODO: inherit the quota from the postmaster's? - } - elsif ($t eq 'alias') { - $entry{alias} = $q->param('alias').'@'.$d; - $entry{maildrop} = $q->param('maildrop'); - } - elsif ($t eq 'list') { - $entry{list} = $q->param('list').'@'.$d; - $entry{transport} = $q->param('transport'); + + if ($q->param('password') || $q->param('password2')) { if ($q->param('password') ne $q->param('password2')) { $error = "Passwords do not match"; } + # TODO: ! move that to Password.pm + # TODO: change password elsif (length $q->param('password') < $CFG{password_min_length}) { $error = "Password should be at least " .$CFG{password_min_length} ." characters long."; } else { - $rest{gpg} = { use_agent => 0 - , keydir => $CFG{gpghome} - , key => $CFG{gpg_private_key_id} - , passphrase => $CFG{gpg_private_key_passphrase} - }; - $entry{password} = $q->param('password'); + $local->{password} = Fripost::Password::hash($q->param('password')); } } - else { - # Unknown type - return $self->redirect('./'); - } - $entry{isactive} = $q->param('isactive') // 1; - $entry{description} = $q->param('description') // undef; - - unless ($error) { - my $fp = Fripost::Schema::->SASLauth( $self->authen->username, %CFG ); - $fp->domain->get ($d, -die => 404, -assert_exist => 1); - $error = $fp->$t->add( \%entry, -concat => "(\n|\x{0D}\x{0A})", %rest); - $fp->done; - return $self->redirect('./') unless $error; - } } - my $template = $self->load_tmpl( "add-$t.html", cache => 1 ); - $template->param( $self->userInfo ); - $template->param( domain => encode_entities($d) ); + # Do not send passwords back to the sender. + $q->delete(qw/password password2/); + + my $t = $local->{type}; + my $template = $self->load_tmpl( "edit-$t.html", cache => 1 ); + $template->param( $self->userInfo + , localpart => encode_entities($localname) + , domainpart => encode_entities($domainname) ); + if ($error) { # Preserve the (incorrect) form, except the passwords - if ($t eq 'user') { - $template->param( user => $q->param('user') // undef - , forwards => $q->param('forwards') // undef ); - } - elsif ($t eq 'alias') { - $template->param( alias => $q->param('alias') // undef - , maildrop => $q->param('maildrop') // undef ); - } - elsif ($t eq 'list') { - $template->param( list => $q->param('list') // undef - , isenc => $q->param('transport') eq 'schleuder' ); - } - else { - # Unknown type - return $self->redirect('./'); - } - $template->param( isactive => $q->param('isactive') // 1 - , description => $q->param('description') // undef - , error => encode_entities ($error) ); + $template->param( &fill_HTML_template_from_query ($q) ); } else { - $template->param( isactive => 1 ); + $template->param( &fill_HTML_template_from_entry ($local, + -hide => [qw/quota transport/]) ); } + # TODO: submit + my $news = (defined $q->param('submit') or + (defined $q->param('a') and $q->param('a') eq 'delete')); + $template->param( newChanges => $news ); + $template->param( error => encode_entities ($error) ) if $error; + $template->param( canDelete => 1 ) if $t eq 'alias'; + $template->param( list_URL => $CFG{'listurl_'.$local->{transport}}. + email_to_ascii($name) ) + if $t eq 'list'; + + $q->delete('a'); return $template->output; } + + + sub mkURL { my $host = shift; my @path = map { encodeURIComponent($_) } @_; |