From ff9b32034774d794aa0a70e225fd22f1a2bbb639 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Nov 03 2021 08:15:39 +0000 Subject: 🔒 Fix unauthorized manipulations of invitations (#254) --- diff --git a/CHANGELOG b/CHANGELOG index b712577..3aa8f68 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ Revision history for Lufi - 💄 Disable signature when using LDAP (#249) - 🌐 Update translations - 🔒 Fix XSS where using zip feature (#254) + - 🔒 Fix unauthorized manipulations of invitations (#254) 0.05.14 2021-06-16 - 🔧 Set default morbo port to 3000 (as it should have stay) diff --git a/lib/Lufi/Controller/Invitation.pm b/lib/Lufi/Controller/Invitation.pm index 22ee695..887d16e 100644 --- a/lib/Lufi/Controller/Invitation.pm +++ b/lib/Lufi/Controller/Invitation.pm @@ -122,61 +122,79 @@ sub delete_invitations { my $c = shift; my @tokens = @{$c->every_param('tokens[]')}; - my @result = (); - for my $token (@tokens) { - my $i = Lufi::DB::Invitation->new(app => $c->app) - ->from_token($token) - ->deleted(1) - ->write; - push @result, { msg => $c->l('The invitation %1 has been deleted.', $i->token), token => $i->token, deleted => $i->deleted }; - } + if ($c->is_user_authenticated) { + my @result = (); + my @failures = (); + for my $token (@tokens) { + my $i = Lufi::DB::Invitation->new(app => $c->app) + ->from_token($token); + if ($i->ldap_user eq $c->current_user->{username}) { + $i->deleted(1) + ->write; + push @result, { msg => $c->l('The invitation %1 has been deleted.', $i->token), token => $i->token, deleted => $i->deleted }; + } else { + push @failures, $c->l('The invitation %1 can’t be deleted: it wasn’t created by you (%2).', $i->token, $c->current_user->{username}); + } + } - $c->render(json => { - success => true, - tokens => \@result - }); + $c->render(json => { + success => (scalar(@result) > 0) ? true : false, + tokens => \@result, + failures => \@failures + }); + } else { + $c->redirect_to($c->url_for('login')->query(redirect => 'my_invitations')); + } } sub resend_invitations { my $c = shift; my @tokens = @{$c->every_param('tokens[]')}; - my @success; - my @failures; - for my $token (@tokens) { - my $i = Lufi::DB::Invitation->new(app => $c->app) - ->from_token($token); + if ($c->is_user_authenticated) { + my @success = (); + my @failures = (); + for my $token (@tokens) { + my $i = Lufi::DB::Invitation->new(app => $c->app) + ->from_token($token); - if ($i->files_sent_at) { - 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); - } else { - if ($c->config('invitations')->{'extend_invitation_expiration_on_resend'}) { - $i->expire_at(time + $i->expire_at - $i->created_at) - ->write; - } + if ($i->ldap_user eq $c->current_user->{username}) { + if ($i->files_sent_at) { + 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); + } else { + if ($c->config('invitations')->{'extend_invitation_expiration_on_resend'}) { + $i->expire_at(time + $i->expire_at - $i->created_at) + ->write; + } - my $from = ($c->config('invitations')->{'send_invitation_with_ldap_user_mail'}) ? $i->ldap_user_mail : $c->config('mail_sender'); - my $url = $c->url_for('guest', token => $i->token)->to_abs; - my $expire = $c->get_date_lang()->time2str($c->l('%A %d %B %Y at %T'), $i->expire_at); - $c->mail( - from => $from, - to => $i->guest_mail, - template => 'invitations/invite', - format => 'mail', - ldap_user => ucfirst($i->ldap_user), - url => $url, - invitation => $i, - expires => $expire - ); + my $from = ($c->config('invitations')->{'send_invitation_with_ldap_user_mail'}) ? $i->ldap_user_mail : $c->config('mail_sender'); + my $url = $c->url_for('guest', token => $i->token)->to_abs; + my $expire = $c->get_date_lang()->time2str($c->l('%A %d %B %Y at %T'), $i->expire_at); + $c->mail( + from => $from, + to => $i->guest_mail, + template => 'invitations/invite', + format => 'mail', + ldap_user => ucfirst($i->ldap_user), + url => $url, + invitation => $i, + expires => $expire + ); - push @success, { msg => $c->l('Invitation resent to %1.
URL: %2', $i->guest_mail, $url), expires => $expire, token => $i->token }; + push @success, { msg => $c->l('Invitation resent to %1.
URL: %2', $i->guest_mail, $url), expires => $expire, token => $i->token }; + } + } else { + push @failures, $c->l('The invitation %1 can’t be resent: it wasn’t created by you (%2).', $i->token, $c->current_user->{username}); + } } - } - $c->render(json => { - success => \@success, - failures => \@failures - }); + $c->render(json => { + success => \@success, + failures => \@failures + }); + } else { + $c->redirect_to($c->url_for('login')->query(redirect => 'my_invitations')); + } } sub toggle_invitations_visibility { diff --git a/themes/default/lib/Lufi/I18N/en.po b/themes/default/lib/Lufi/I18N/en.po index 13b6725..d1a2e5b 100644 --- a/themes/default/lib/Lufi/I18N/en.po +++ b/themes/default/lib/Lufi/I18N/en.po @@ -41,7 +41,7 @@ msgstr "%1 sent you files" msgid "%1 used your invitation to send you files:" msgstr "%1 used your invitation to send you files:" -#: lib/Lufi/Controller/Invitation.pm:160 lib/Lufi/Controller/Invitation.pm:85 themes/default/templates/invitations/my_invitations.html.ep:51 themes/default/templates/invitations/my_invitations.html.ep:52 themes/default/templates/invitations/my_invitations.html.ep:53 themes/default/templates/invitations/notification_files_sent.mail.ep:12 +#: lib/Lufi/Controller/Invitation.pm:172 lib/Lufi/Controller/Invitation.pm:85 themes/default/templates/invitations/my_invitations.html.ep:51 themes/default/templates/invitations/my_invitations.html.ep:52 themes/default/templates/invitations/my_invitations.html.ep:53 themes/default/templates/invitations/notification_files_sent.mail.ep:12 msgid "%A %d %B %Y at %T" msgstr "%A %d %B %Y at %T" @@ -364,7 +364,7 @@ msgid "Invert selection" msgstr "Invert selection" #. ($i->guest_mail, $url) -#: lib/Lufi/Controller/Invitation.pm:172 +#: lib/Lufi/Controller/Invitation.pm:184 msgid "Invitation resent to %1.
URL: %2" msgstr "Invitation resent to %1.
URL: %2" @@ -505,11 +505,11 @@ msgstr "Send all links by email" msgid "Send the invitation" msgstr "Send the invitation" -#: themes/default/templates/mail.html.ep:46 +#: themes/default/templates/mail.html.ep:47 msgid "Send with this server" msgstr "Send with this server" -#: themes/default/templates/mail.html.ep:47 +#: themes/default/templates/mail.html.ep:49 msgid "Send with your own mail software" msgstr "Send with your own mail software" @@ -518,7 +518,7 @@ msgid "Sending part XX1 of XX2. Please, be patient, the progress bar can take a msgstr "Sending part XX1 of XX2. Please, be patient, the progress bar can take a while to move." #. (url_for('/') -#: themes/default/templates/partial/mail.js.ep:48 +#: themes/default/templates/partial/mail.js.ep:49 msgid "Share your files in total privacy on %1" msgstr "Share your files in total privacy on %1" @@ -534,7 +534,7 @@ msgstr "Show zip content" msgid "Signin" msgstr "Signin" -#: lib/Lufi/Controller/Invitation.pm:284 themes/default/templates/invitations/exception.html.ep:16 +#: lib/Lufi/Controller/Invitation.pm:302 themes/default/templates/invitations/exception.html.ep:16 msgid "Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?" msgstr "Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?" @@ -556,7 +556,7 @@ msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 msgstr "Sorry, your invitation has expired or has been deleted. Please contact %1 to have another invitation." #. ($invitation->ldap_user_mail) -#: lib/Lufi/Controller/Invitation.pm:277 +#: lib/Lufi/Controller/Invitation.pm:295 msgid "The URLs of your files have been sent by email to %1." msgstr "The URLs of your files have been sent by email to %1." @@ -603,13 +603,23 @@ msgstr "The following email addresses are not valid: %1" msgid "The guest email address (%1) is unvalid." msgstr "The guest email address (%1) is unvalid." +#. ($i->token, $c->current_user->{username}) +#: lib/Lufi/Controller/Invitation.pm:136 +msgid "The invitation %1 can’t be deleted: it wasn’t created by you (%2)." +msgstr "The invitation %1 can’t be deleted: it wasn’t created by you (%2)." + #. ($i->token, $i->guest_mail) -#: lib/Lufi/Controller/Invitation.pm:151 +#: lib/Lufi/Controller/Invitation.pm:163 msgid "The invitation %1 can’t be resent: %2 has already sent files.
Please create a new invitation." msgstr "The invitation %1 can’t be resent: %2 has already sent files.
Please create a new invitation." +#. ($i->token, $c->current_user->{username}) +#: lib/Lufi/Controller/Invitation.pm:187 +msgid "The invitation %1 can’t be resent: it wasn’t created by you (%2)." +msgstr "The invitation %1 can’t be resent: it wasn’t created by you (%2)." + #. ($i->token) -#: lib/Lufi/Controller/Invitation.pm:131 +#: lib/Lufi/Controller/Invitation.pm:134 msgid "The invitation %1 has been deleted." msgstr "The invitation %1 has been deleted." diff --git a/themes/default/lib/Lufi/I18N/lufi.pot b/themes/default/lib/Lufi/I18N/lufi.pot index 13f4672..2daa2e3 100644 --- a/themes/default/lib/Lufi/I18N/lufi.pot +++ b/themes/default/lib/Lufi/I18N/lufi.pot @@ -41,7 +41,7 @@ msgstr "" msgid "%1 used your invitation to send you files:" msgstr "" -#: lib/Lufi/Controller/Invitation.pm:160 lib/Lufi/Controller/Invitation.pm:85 themes/default/templates/invitations/my_invitations.html.ep:51 themes/default/templates/invitations/my_invitations.html.ep:52 themes/default/templates/invitations/my_invitations.html.ep:53 themes/default/templates/invitations/notification_files_sent.mail.ep:12 +#: lib/Lufi/Controller/Invitation.pm:172 lib/Lufi/Controller/Invitation.pm:85 themes/default/templates/invitations/my_invitations.html.ep:51 themes/default/templates/invitations/my_invitations.html.ep:52 themes/default/templates/invitations/my_invitations.html.ep:53 themes/default/templates/invitations/notification_files_sent.mail.ep:12 msgid "%A %d %B %Y at %T" msgstr "" @@ -364,7 +364,7 @@ msgid "Invert selection" msgstr "" #. ($i->guest_mail, $url) -#: lib/Lufi/Controller/Invitation.pm:172 +#: lib/Lufi/Controller/Invitation.pm:184 msgid "Invitation resent to %1.
URL: %2" msgstr "" @@ -505,11 +505,11 @@ msgstr "" msgid "Send the invitation" msgstr "" -#: themes/default/templates/mail.html.ep:46 +#: themes/default/templates/mail.html.ep:47 msgid "Send with this server" msgstr "" -#: themes/default/templates/mail.html.ep:47 +#: themes/default/templates/mail.html.ep:49 msgid "Send with your own mail software" msgstr "" @@ -518,7 +518,7 @@ msgid "Sending part XX1 of XX2. Please, be patient, the progress bar can take a msgstr "" #. (url_for('/') -#: themes/default/templates/partial/mail.js.ep:48 +#: themes/default/templates/partial/mail.js.ep:49 msgid "Share your files in total privacy on %1" msgstr "" @@ -534,7 +534,7 @@ msgstr "" msgid "Signin" msgstr "" -#: lib/Lufi/Controller/Invitation.pm:284 themes/default/templates/invitations/exception.html.ep:16 +#: lib/Lufi/Controller/Invitation.pm:302 themes/default/templates/invitations/exception.html.ep:16 msgid "Sorry, the invitation doesn’t exist. Are you sure you are on the right URL?" msgstr "" @@ -556,7 +556,7 @@ msgid "Sorry, your invitation has expired or has been deleted. Please contact %1 msgstr "" #. ($invitation->ldap_user_mail) -#: lib/Lufi/Controller/Invitation.pm:277 +#: lib/Lufi/Controller/Invitation.pm:295 msgid "The URLs of your files have been sent by email to %1." msgstr "" @@ -603,13 +603,23 @@ msgstr "" msgid "The guest email address (%1) is unvalid." msgstr "" +#. ($i->token, $c->current_user->{username}) +#: lib/Lufi/Controller/Invitation.pm:136 +msgid "The invitation %1 can’t be deleted: it wasn’t created by you (%2)." +msgstr "" + #. ($i->token, $i->guest_mail) -#: lib/Lufi/Controller/Invitation.pm:151 +#: lib/Lufi/Controller/Invitation.pm:163 msgid "The invitation %1 can’t be resent: %2 has already sent files.
Please create a new invitation." msgstr "" +#. ($i->token, $c->current_user->{username}) +#: lib/Lufi/Controller/Invitation.pm:187 +msgid "The invitation %1 can’t be resent: it wasn’t created by you (%2)." +msgstr "" + #. ($i->token) -#: lib/Lufi/Controller/Invitation.pm:131 +#: lib/Lufi/Controller/Invitation.pm:134 msgid "The invitation %1 has been deleted." msgstr "" diff --git a/themes/default/public/js/lufi-list-invitations.js b/themes/default/public/js/lufi-list-invitations.js index 5f9f75d..8aab3d8 100644 --- a/themes/default/public/js/lufi-list-invitations.js +++ b/themes/default/public/js/lufi-list-invitations.js @@ -44,9 +44,17 @@ function deleteInvit(e) { Materialize.toast(t.msg, 6000, 'teal accent-3'); $('#row-' + t.token).remove(); }); + data.failures.forEach(function(msg) { + Materialize.toast(msg, 10000, 'red accent-2'); + }); disableButtons(); } else { - Materialize.toast(data.msg, 10000, 'red accent-2'); + data.failures.forEach(function(msg) { + Materialize.toast(msg, 10000, 'red accent-2'); + }); + if (data.msg) { + Materialize.toast(data.msg, 10000, 'red accent-2'); + } } } });