Luc Didry 8b68d7
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
Luc Didry 8b68d7
package Lufi::Controller::Invitation;
Luc Didry 8b68d7
use Mojo::Base 'Mojolicious::Controller';
Luc Didry 8b68d7
use Mojo::Collection 'c';
Luc Didry 8b68d7
use Mojo::File;
Luc Didry 8b68d7
use Mojo::JSON qw(true false decode_json encode_json);
Luc Didry 8b68d7
use Mojo::URL;
Luc Didry 8b68d7
use Email::Valid;
Luc Didry 8b68d7
use Lufi::DB::File;
Luc Didry 8b68d7
use Lufi::DB::Invitation;
Luc Didry 8b68d7
use Date::Format;
Luc Didry 8b68d7
Luc Didry 8b68d7
sub new_invite {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
Luc Didry 8b68d7
    # The `if (defined($c->config('ldap')))` is at the router level in lib/Lufi.pm
Luc Didry 8b68d7
    if ($c->is_user_authenticated) {
Luc Didry 8b68d7
        my $mail_attr            = $c->config('invitations')->{'mail_attr'} // 'mail';
Luc Didry 8b68d7
        my $max_expire_at        = $c->config('invitations')->{'max_invitation_expiration_delay'} // 30;
Luc Didry 8b68d7
        my $send_with_user_email = defined $c->config('invitations')->{'send_invitation_with_ldap_user_mail'};
Luc Didry 8b68d7
        $c->render(
Luc Didry 8b68d7
            template             => 'invitations/invite',
Luc Didry 8b68d7
            max_expire_at        => $max_expire_at,
Luc Didry 8b68d7
            send_with_user_email => $send_with_user_email,
Luc Didry 8b68d7
            user_mail            => ($send_with_user_email) ? $c->current_user->{$mail_attr} : '',
Luc Didry 8b68d7
            fails                => [],
Luc Didry 8b68d7
            success              => []
Luc Didry 8b68d7
        );
Luc Didry 8b68d7
    } else {
Luc Didry 8b68d7
        $c->redirect_to($c->url_for('login')->query(redirect => 'invite'));
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub send_invite {
Luc Didry 8b68d7
    my $c          = shift;
Luc Didry 8b68d7
    my $guest_mail = $c->param('guest_mail');
Luc Didry 8b68d7
    my $expire_at  = $c->param('expire_at');
Luc Didry 8b68d7
Luc Didry 8b68d7
    my $mail_attr            = $c->config('invitations')->{'mail_attr'} // 'mail';
Luc Didry 8b68d7
    my $max_expire_at        = $c->config('invitations')->{'max_invitation_expiration_delay'} // 30;
Luc Didry 8b68d7
    my $send_with_user_email = defined $c->config('invitations')->{'send_invitation_with_ldap_user_mail'};
Luc Didry 8b68d7
Luc Didry 8b68d7
    # The `if (defined($c->config('ldap')))` is at the router level in lib/Lufi.pm
Luc Didry 8b68d7
    if ($c->is_user_authenticated) {
Luc Didry 8b68d7
        my @fails   = ();
Luc Didry 8b68d7
        my @success = ();
Luc Didry 8b68d7
        unless (Email::Valid->address($guest_mail)) {
Luc Didry 8b68d7
            push @fails, $c->l('The guest email address (%1) is unvalid.', $guest_mail);
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
        unless ($expire_at >= 1 && $expire_at <= $max_expire_at) {
Luc Didry 8b68d7
            push @fails, $c->l('The expiration delay (%1) is not between 1 and %2 days.', $expire_at, $max_expire_at);
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
Luc Didry 8b68d7
        unless (scalar(@fails)) {
Luc Didry 8b68d7
            my $invitation       = Lufi::DB::Invitation->new(app => $c->app);
Luc Didry 8b68d7
            my $mail_attr        = $c->config('invitations')->{'mail_attr'} // 'mail';
Luc Didry e9fabb
            my $expend_expire_at = $c->config('invitations')->{'max_additional_period'} // 10;
Luc Didry 8b68d7
Luc Didry 8b68d7
            my $token;
Luc Didry 8b68d7
            do {
Luc Didry 8b68d7
                $token = $c->create_invitation_token;
Luc Didry 8b68d7
            } while ($invitation->is_token_used($token));
Luc Didry 8b68d7
Luc Didry 8b68d7
            $invitation = $invitation->from_token($token);
Luc Didry 8b68d7
            $invitation->ldap_user($c->current_user->{username});
Luc Didry 8b68d7
            $invitation->ldap_user_mail($c->current_user->{$mail_attr});
Luc Didry 8b68d7
            $invitation->created_at(time);
Luc Didry 8b68d7
            $invitation->guest_mail($guest_mail);
Luc Didry 8b68d7
            $invitation->expire_at($invitation->created_at + 86400 * $expire_at);
Luc Didry 8b68d7
            $invitation->expend_expire_at($expend_expire_at);
Luc Didry 8b68d7
            $invitation->show_in_list(1);
Luc Didry 8b68d7
            $invitation = $invitation->write;
Luc Didry 8b68d7
Luc Didry 8b68d7
            my $from = ($c->config('invitations')->{'send_invitation_with_ldap_user_mail'}) ? $invitation->ldap_user_mail : $c->config('mail_sender');
Luc Didry 8b68d7
            my $url  = $c->url_for('guest', token => $invitation->token)->to_abs;
Luc Didry 8b68d7
            $c->mail(
Luc Didry 8b68d7
                from       => $from,
Luc Didry 8b68d7
                to         => $invitation->guest_mail,
Luc Didry 8b68d7
                template   => 'invitations/invite',
Luc Didry 8b68d7
                format     => 'mail',
Luc Didry 8b68d7
                ldap_user  => ucfirst($invitation->ldap_user),
Luc Didry 8b68d7
                url        => $url,
Luc Didry 8b68d7
                invitation => $invitation,
Luc Didry be0b3c
                expires    => $c->get_date_lang()->time2str($c->l('%A %d %B %Y at %T'), $invitation->expire_at)
Luc Didry 8b68d7
            );
Luc Didry 8b68d7
Luc Didry 8b68d7
            push @success, $c->l('Invitation sent to %1.
URL: %2', $invitation->guest_mail, $url);
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
Luc Didry 8b68d7
        $c->render(
Luc Didry 8b68d7
            template             => 'invitations/invite',
Luc Didry 8b68d7
            max_expire_at        => $max_expire_at,
Luc Didry 8b68d7
            send_with_user_email => $send_with_user_email,
Luc Didry 8b68d7
            user_mail            => ($send_with_user_email) ? $c->current_user->{$mail_attr} : '',
Luc Didry 8b68d7
            fails                => \@fails,
Luc Didry 8b68d7
            success              => \@success
Luc Didry 8b68d7
        );
Luc Didry 8b68d7
    } else {
Luc Didry 8b68d7
        $c->redirect_to('login');
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub my_invitations {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
Luc Didry 8b68d7
    # The `if (defined($c->config('ldap')))` is at the router level in lib/Lufi.pm
Luc Didry 8b68d7
    if ($c->is_user_authenticated) {
Luc Didry 8b68d7
        my $invitations = Lufi::DB::Invitation->new(app => $c->app)
Luc Didry 8b68d7
                                              ->from_user($c->current_user->{username});
Luc Didry 8b68d7
        $invitations = c() unless $invitations;
Luc Didry 8b68d7
        $c->render(
Luc Didry 8b68d7
            template    => 'invitations/my_invitations',
Luc Didry 8b68d7
            invitations => $invitations
Luc Didry 8b68d7
        );
Luc Didry 8b68d7
    } else {
Luc Didry 8b68d7
        $c->redirect_to($c->url_for('login')->query(redirect => 'my_invitations'));
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub delete_invitations {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
    my @tokens = @{$c->every_param('tokens[]')};
Luc Didry 8b68d7
Luc Didry 8b68d7
    my @result = ();
Luc Didry 8b68d7
    for my $token (@tokens) {
Luc Didry 8b68d7
        my $i = Lufi::DB::Invitation->new(app => $c->app)
Luc Didry 8b68d7
                                    ->from_token($token)
Luc Didry 8b68d7
                                    ->deleted(1)
Luc Didry 8b68d7
                                    ->write;
Luc Didry 8b68d7
        push @result, { msg => $c->l('The invitation %1 has been deleted.', $i->token), token => $i->token, deleted => $i->deleted };
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
Luc Didry 8b68d7
    $c->render(json => {
Luc Didry 8b68d7
        success => true,
Luc Didry 8b68d7
        tokens  => \@result
Luc Didry 8b68d7
    });
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub resend_invitations {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
    my @tokens = @{$c->every_param('tokens[]')};
Luc Didry 8b68d7
Luc Didry 8b68d7
    my @success;
Luc Didry 8b68d7
    my @failures;
Luc Didry 8b68d7
    for my $token (@tokens) {
Luc Didry 8b68d7
        my $i = Lufi::DB::Invitation->new(app => $c->app)
Luc Didry 8b68d7
                                    ->from_token($token);
Luc Didry 8b68d7
Luc Didry 8b68d7
        if ($i->files_sent_at) {
Luc Didry c8533d
            push @failures, $c->l('The invitation %1 can’t be resent: %2 has already sent files.
Please create a new invitation.', $i->token, $i->guest_mail);
Luc Didry 8b68d7
        } else {
Luc Didry 8b68d7
            if ($c->config('invitations')->{'extend_invitation_expiration_on_resend'}) {
Luc Didry 8b68d7
                $i->expire_at(time + $i->expire_at - $i->created_at)
Luc Didry 8b68d7
                  ->write;
Luc Didry 8b68d7
            }
Luc Didry 8b68d7
Luc Didry 8b68d7
            my $from   = ($c->config('invitations')->{'send_invitation_with_ldap_user_mail'}) ? $i->ldap_user_mail : $c->config('mail_sender');
Luc Didry 8b68d7
            my $url    = $c->url_for('guest', token => $i->token)->to_abs;
Luc Didry be0b3c
            my $expire = $c->get_date_lang()->time2str($c->l('%A %d %B %Y at %T'), $i->expire_at);
Luc Didry 8b68d7
            $c->mail(
Luc Didry 8b68d7
                from       => $from,
Luc Didry 8b68d7
                to         => $i->guest_mail,
Luc Didry 8b68d7
                template   => 'invitations/invite',
Luc Didry 8b68d7
                format     => 'mail',
Luc Didry 8b68d7
                ldap_user  => ucfirst($i->ldap_user),
Luc Didry 8b68d7
                url        => $url,
Luc Didry 8b68d7
                invitation => $i,
Luc Didry 8b68d7
                expires    => $expire
Luc Didry 8b68d7
            );
Luc Didry 8b68d7
Luc Didry 8b68d7
            push @success, { msg => $c->l('Invitation resent to %1.
URL: %2', $i->guest_mail, $url), expires => $expire, token => $i->token };
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
Luc Didry 8b68d7
    $c->render(json => {
Luc Didry 8b68d7
        success  => \@success,
Luc Didry 8b68d7
        failures => \@failures
Luc Didry 8b68d7
    });
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub toggle_invitations_visibility {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
    my @tokens = @{$c->every_param('tokens[]')};
Luc Didry 8b68d7
Luc Didry 8b68d7
    my @result = ();
Luc Didry 8b68d7
    for my $token (@tokens) {
Luc Didry 8b68d7
        my $i = Lufi::DB::Invitation->new(app => $c->app)
Luc Didry 8b68d7
                                    ->from_token($token)
Luc Didry 8b68d7
                                    ->toggle_visibility;
Luc Didry 8b68d7
        push @result, { token => $i->token, show => ($i->show_in_list) ? true : false }
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
Luc Didry 8b68d7
    $c->render(json => {
Luc Didry 8b68d7
        success => true,
Luc Didry 8b68d7
        tokens  => \@result
Luc Didry 8b68d7
    });
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub guest {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
    my $token = $c->param('token');
Luc Didry 8b68d7
Luc Didry 8b68d7
    my $invitation = Lufi::DB::Invitation->new(app => $c->app)->from_token($token);
Luc Didry 8b68d7
    if ($invitation) {
Luc Didry 8b68d7
        if ($invitation->is_valid) {
Luc Didry 8b68d7
            $c->session->{guest_token} = $token;
Luc Didry 8b68d7
            $c->session(expires => $invitation->expire_at);
Luc Didry 8b68d7
            return $c->render(
Luc Didry 8b68d7
                template   => 'index',
Luc Didry 8b68d7
                invitation => $invitation
Luc Didry 8b68d7
            );
Luc Didry 8b68d7
        } else {
Luc Didry 8b68d7
            $c->stash('expired_or_deleted_invitation' => 1);
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
    } else {
Luc Didry 8b68d7
        $c->stash('invitation_not_found' => 1);
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
    return $c->render(template => 'invitations/exception');
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
sub send_mail_to_ldap_user {
Luc Didry 8b68d7
    my $c = shift;
Luc Didry 8b68d7
    my $token = $c->param('token');
Luc Didry 8b68d7
    my $urls  = c(@{$c->every_param('urls[]')});
Luc Didry 8b68d7
Luc Didry 8b68d7
    my $invitation = Lufi::DB::Invitation->new(app => $c->app)->from_token($token);
Luc Didry 8b68d7
    if ($invitation) {
Luc Didry 8b68d7
        my @files = ();
Luc Didry 8b68d7
        if ($c->config('invitations')->{'save_files_url_in_db'} && $urls->size) {
Luc Didry 8b68d7
            my $guest_files = $invitation->files;
Luc Didry 2f8758
            my %list_token;
Luc Didry 8b68d7
            if ($guest_files) {
Luc Didry 8b68d7
                $guest_files = decode_json($guest_files);
Luc Didry 2f8758
                for my $file (@{$guest_files}) {
Luc Didry 2f8758
                    $list_token{$file->{token}} = 1;
Luc Didry 2f8758
                }
Luc Didry 8b68d7
            } else {
Luc Didry 8b68d7
                $guest_files = [];
Luc Didry 8b68d7
            }
Luc Didry 8b68d7
            push @files, @{$guest_files};
Luc Didry 8b68d7
            $urls->each(sub {
Luc Didry 8b68d7
                my ($e, $num) = @_;
Luc Didry 8b68d7
                $e = decode_json($e);
Luc Didry 2f8758
                if (!defined($list_token{$e->{token}})) {
Luc Didry 2f8758
                    push @{$guest_files}, $e;
Luc Didry 2f8758
                    push @files, $e;
Luc Didry 2f8758
                }
Luc Didry 8b68d7
            });
Luc Didry 8b68d7
            $invitation->files(encode_json($guest_files));
Luc Didry 8b68d7
            $invitation->write;
Luc Didry 8b68d7
        } else {
Luc Didry 8b68d7
            $urls->each(sub {
Luc Didry 8b68d7
                push @files, decode_json(shift);
Luc Didry 8b68d7
            });
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
        my $already_notified = 1;
Luc Didry 8b68d7
        unless ($invitation->files_sent_at) {
Luc Didry 8b68d7
            $invitation->files_sent_at(time);
Luc Didry 8b68d7
            $invitation->write;
Luc Didry 8b68d7
            $already_notified = 0;
Luc Didry 8b68d7
        }
Luc Didry 8b68d7
        $c->session(expires => $invitation->files_sent_at + 60 * $invitation->expend_expire_at);
Luc Didry 8b68d7
        $c->mail(
Luc Didry 8b68d7
            from             => $c->config('mail_sender'),
Luc Didry 8b68d7
            to               => $invitation->ldap_user_mail,
Luc Didry 8b68d7
            template         => 'invitations/notification_files_sent',
Luc Didry 8b68d7
            format           => 'mail',
Luc Didry 8b68d7
            files            => c(@files),
Luc Didry 8b68d7
            invitation       => $invitation,
Luc Didry 8b68d7
            already_notified => $already_notified
Luc Didry 8b68d7
        );
Luc Didry 8b68d7
Luc Didry 8b68d7
        return $c->render(
Luc Didry 8b68d7
            json => {
Luc Didry 8b68d7
                success => true,
Luc Didry 8b68d7
                msg     => $c->l('The URLs of your files have been sent by email to %1.', $invitation->ldap_user_mail)
Luc Didry 8b68d7
            }
Luc Didry 8b68d7
        );
Luc Didry 8b68d7
    } else {
Luc Didry 8b68d7
        return $c->render(
Luc Didry 8b68d7
            json => {
Luc Didry 8b68d7
                success => false,
Luc Didry 8b68d7
                msg     => $c->l('Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?')
Luc Didry 8b68d7
            }
Luc Didry 8b68d7
        );
Luc Didry 8b68d7
    }
Luc Didry 8b68d7
}
Luc Didry 8b68d7
Luc Didry 8b68d7
1;