diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 67e700b9e..4948e88b9 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -23,6 +23,7 @@ - fixed #11549: Shortcut Asset cannot override Page Layout - added #11502: Gallery: Allow specification of location when uploading ZIP archives - added #11517: Gallery: Sorting of files uploaded in zip archives + - fixed #11559: Unsubscribe Link in Emails 7.9.4 - We're shipping underscore.js now for its suite of extremely handy utility diff --git a/docs/upgrades/packages-7.9.5/root_import_collaboration.wgpkg b/docs/upgrades/packages-7.9.5/root_import_collaboration.wgpkg new file mode 100644 index 000000000..f83442066 Binary files /dev/null and b/docs/upgrades/packages-7.9.5/root_import_collaboration.wgpkg differ diff --git a/docs/upgrades/upgrade_7.9.4-7.9.5.pl b/docs/upgrades/upgrade_7.9.4-7.9.5.pl index bc84dffd0..3d5487d0f 100644 --- a/docs/upgrades/upgrade_7.9.4-7.9.5.pl +++ b/docs/upgrades/upgrade_7.9.4-7.9.5.pl @@ -36,6 +36,7 @@ modifySortItems( $session ); fixRequestForApprovalScratch($session); addRejectNoticeSetting($session); updateGroupGroupingsTable($session); +installNewCSUnsubscribeTemplate($session); finish($session); # this line required @@ -57,6 +58,15 @@ sub addRejectNoticeSetting { print "DONE!\n" unless $quiet; } +#---------------------------------------------------------------------------- +sub installNewCSUnsubscribeTemplate { + my $session = shift; + print "\tAdding new unsubscribe template to the CS... " unless $quiet; + $session->db->write(q|ALTER TABLE Collaboration ADD COLUMN unsubscribeTemplateId CHAR(22) NOT NULL|); + $session->db->write(q|UPDATE Collaboration set unsubscribeTemplateId='default_CS_unsubscribe'|); + print "DONE!\n" unless $quiet; +} + #---------------------------------------------------------------------------- # Add keys and indicies to groupGroupings to help speed up group queries sub updateGroupGroupingsTable { diff --git a/lib/WebGUI/Asset/Post/Thread.pm b/lib/WebGUI/Asset/Post/Thread.pm index d87d2bc3d..056832ed0 100644 --- a/lib/WebGUI/Asset/Post/Thread.pm +++ b/lib/WebGUI/Asset/Post/Thread.pm @@ -1021,18 +1021,22 @@ sub unstick { #------------------------------------------------------------------- -=head2 unsubscribe ( ) +=head2 unsubscribe ( [$user] ) -Negates the subscribe method. +Unsubscribes a user from this thread. + +=head3 $user + +An optional user object to unsubscribe. If the object isn't passed, then it uses the session user. =cut sub unsubscribe { - my $self = shift; + my $self = shift; + my $user = shift || $self->session->user; my $group = WebGUI::Group->new($self->session,$self->get("subscriptionGroupId")); - return - if !$group; - $group->deleteUsers([$self->session->user->userId]); + return unless $group; + $group->deleteUsers([$user->userId]); } @@ -1381,16 +1385,60 @@ sub www_unstick { #------------------------------------------------------------------- -=head2 www_unsubscribe ( ) +=head2 www_unsubscribe ( [$message] ) The web method to unsubscribe from a thread. +=head3 $message + +An error message to display to the user. + =cut sub www_unsubscribe { - my $self = shift; - $self->unsubscribe if $self->canSubscribe; - return $self->www_view; + my $self = shift; + my $message = shift; + if($self->canSubscribe){ + $self->unsubscribe; + return $self->www_view; + } + else { + my $session = $self->session; + my $i18n = WebGUI::International->new($session, 'Asset_Collaboration'); + my $var = $self->get(); + $var->{title} = $self->getTitle; + $var->{url} = $self->getUrl; + $var->{formHeader} = WebGUI::Form::formHeader($session) + . WebGUI::Form::hidden($session, { name => 'func', value => 'unsubscribeConfirm', }, ), + $var->{formFooter} = WebGUI::Form::formFooter($session), + $var->{formSubmit} = WebGUI::Form::submit($session, { value => $i18n->get('unsubscribe'), }), + $var->{formEmail} = WebGUI::Form::email($session, { name => 'userEmail', value => $session->form->process('userEmail'), }), + $var->{formMessage} = $message; + return $self->getParent->processStyle($self->processTemplate($var, $self->getParent->get("unsubscribeTemplateId"))); + } +} + +#------------------------------------------------------------------- + +=head2 www_unsubscribeConfirm ( ) + +Process the unsubscribe form. + +=cut + +sub www_unsubscribeConfirm { + my $self = shift; + my $session = $self->session; + return $self->www_view unless $session->form->validToken; + my $email = $session->form->process('userEmail', 'email'); + return $self->www_view unless $email; + my $user = WebGUI::User->newByEmail($session, $email); + my $i18n = WebGUI::International->new($session, 'Asset_Collaboration'); + if (! $user) { + return $self->www_unsubscribe($i18n->get('no user email error message')); + } + $self->unsubscribe($user); + return $self->www_unsubscribe($i18n->get('You have been unsubscribed')); } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Asset/Wobject/Collaboration.pm b/lib/WebGUI/Asset/Wobject/Collaboration.pm index deff387e6..af0798408 100644 --- a/lib/WebGUI/Asset/Wobject/Collaboration.pm +++ b/lib/WebGUI/Asset/Wobject/Collaboration.pm @@ -895,6 +895,14 @@ sub definition { hoverHelp=>$i18n->get('post received template hoverHelp'), defaultValue=>'default_post_received1', }, + unsubscribeTemplateId =>{ + fieldType=>'template', + namespace=>'Collaboration/Unsubscribe', + tab=>'display', + label=>$i18n->get('unsubscribe template'), + hoverHelp=>$i18n->get('unsubscribe template hoverHelp'), + defaultValue=>'default_CS_unsubscribe', + }, ); push(@{$definition}, { @@ -1542,18 +1550,22 @@ sub subscribe { #------------------------------------------------------------------- -=head2 unsubscribe ( ) +=head2 unsubscribe ( [$user] ) Unsubscribes a user from this collaboration system +=head3 $user + +An optional user object to unsubscribe. If the object isn't passed, then it uses the session user. + =cut sub unsubscribe { - my $self = shift; - my $group = WebGUI::Group->new($self->session,$self->get("subscriptionGroupId")); - return - unless $group; - $group->deleteUsers([$self->session->user->userId],[$self->get("subscriptionGroupId")]); + my $self = shift; + my $user = shift || $self->session->user; + my $group = WebGUI::Group->new($self->session,$self->get("subscriptionGroupId")); + return unless $group; + $group->deleteUsers([$user->userId]); } @@ -1690,24 +1702,64 @@ sub www_unarchiveAll { #------------------------------------------------------------------- -=head2 www_unsubscribe ( ) +=head2 www_unsubscribe ( [$message] ) The web method to unsubscribe from a collaboration. +=head3 $message + +An error message to display to the user. + =cut sub www_unsubscribe { - my $self = shift; + my $self = shift; + my $message = shift; if($self->canSubscribe){ $self->unsubscribe; return $self->www_view; - }else{ - return $self->session->privilege->noAccess; + } + else { + my $session = $self->session; + my $i18n = WebGUI::International->new($session, 'Asset_Collaboration'); + my $var = $self->get(); + $var->{title} = $self->getTitle; + $var->{url} = $self->getUrl; + $var->{formHeader} = WebGUI::Form::formHeader($session) + . WebGUI::Form::hidden($session, { name => 'func', value => 'unsubscribeConfirm', }, ), + $var->{formFooter} = WebGUI::Form::formFooter($session), + $var->{formSubmit} = WebGUI::Form::submit($session, { value => $i18n->get('unsubscribe'), }), + $var->{formEmail} = WebGUI::Form::email($session, { name => 'userEmail', value => $session->form->process('userEmail'), }), + $var->{formMessage} = $message; + return $self->processStyle($self->processTemplate($var, $self->get("unsubscribeTemplateId"))); } } #------------------------------------------------------------------- +=head2 www_unsubscribeConfirm ( ) + +Process the unsubscribe form. + +=cut + +sub www_unsubscribeConfirm { + my $self = shift; + my $session = $self->session; + return $self->www_view unless $session->form->validToken; + my $email = $session->form->process('userEmail', 'email'); + return $self->www_view unless $email; + my $user = WebGUI::User->newByEmail($session, $email); + my $i18n = WebGUI::International->new($session, 'Asset_Collaboration'); + if (! $user) { + return $self->www_unsubscribe($i18n->get('no user email error message')); + } + $self->unsubscribe($user); + return $self->www_unsubscribe($i18n->get('You have been unsubscribed')); +} + +#------------------------------------------------------------------- + =head2 www_view Extend the base method to handle the visitor cache timeout. diff --git a/lib/WebGUI/Help/Asset_Collaboration.pm b/lib/WebGUI/Help/Asset_Collaboration.pm index ef134eb75..2ceb1e4ee 100644 --- a/lib/WebGUI/Help/Asset_Collaboration.pm +++ b/lib/WebGUI/Help/Asset_Collaboration.pm @@ -199,6 +199,26 @@ our $HELP = { related => [ ], }, + 'collaboration unsubscribe template' => { + title => 'collaboration unsubscribe template title', + body => '', + fields => [], + isa => [], + variables => [ + { name => 'formHeader', + description => 'unsubscribe formHeader', }, + { name => 'formSubmit', + description => 'unsubscribe formSubmit', }, + { name => 'formEmail', + description => 'unsubscribe formEmail', }, + { name => 'formFooter', + description => 'unsubscribe formFooter', }, + { name => 'formMessage', + description => 'unsubscribe formMessage', }, + ], + related => [ ], + }, + }; 1; diff --git a/lib/WebGUI/Session/Form.pm b/lib/WebGUI/Session/Form.pm index 47ae64471..e5dff2315 100644 --- a/lib/WebGUI/Session/Form.pm +++ b/lib/WebGUI/Session/Form.pm @@ -186,9 +186,10 @@ the one in this user's current session. sub validToken { my ($self) = @_; my $session = $self->session; - $session->log->debug('HTTP method: '. $session->request->method); - $session->log->debug('CSRF token: '. $session->scratch->get('webguiCsrfToken')); + $session->log->warn('HTTP method: '. $session->request->method); + $session->log->warn('CSRF token: '. $session->scratch->get('webguiCsrfToken')); return 0 unless $session->request->method eq 'POST'; + $session->log->warn('Web token: '. $self->param('webguiCsrfToken')); return 0 unless $self->param('webguiCsrfToken') eq $session->scratch->get('webguiCsrfToken'); return 1; } diff --git a/lib/WebGUI/i18n/English/Asset_Collaboration.pm b/lib/WebGUI/i18n/English/Asset_Collaboration.pm index c795f7249..33ab098db 100644 --- a/lib/WebGUI/i18n/English/Asset_Collaboration.pm +++ b/lib/WebGUI/i18n/English/Asset_Collaboration.pm @@ -597,6 +597,12 @@ our $I18N = { lastUpdated => 1109696029, }, + 'Unsubscribe from %s' => { + message => q|Unsubscribe from %s|, + lastUpdated => 1274216526, + context => q|Label for the unsubscribe form. %s will be filled in with the title of the CS.|, + }, + 'url' => { message => q|URL|, lastUpdated => 1109696029, @@ -1580,17 +1586,37 @@ the Collaboration Asset, the user will be notified.|, message => q|The assetId of this Collaboration System. Unlike the variable assetId, this one will not be overridden by the assetIds inside of Threads or Posts.|, lastUpdated => 1170543345, }, - + 'subscription group label' => { message => q|Subscription Group|, lastUpdated => 1170543345, }, - + 'subscription group hoverHelp' => { message => q|Manage the users in the subscription group for this Collaboration System|, lastUpdated => 1170543345, }, + 'unsubscribe template' => { + message => q|Unsubscribe Template|, + lastUpdated => 1274208100, + }, + + 'unsubscribe template hoverHelp' => { + message => q|Choose a template to help a user, who is not logged in, unsubscribe from either the CS or from a Thread within it.|, + lastUpdated => 1274208493, + }, + + 'unsubscribe instructions' => { + message => q|Please enter in the email address of the user who wants to unsubscribe|, + lastUpdated => 1274208493, + }, + + 'no user email error message' => { + message => q|No user with that email can be found.|, + lastUpdated => 1274208493, + }, + 'group to edit label' => { message => q|Group to Edit Posts|, lastUpdated => 1206733328, @@ -1599,7 +1625,7 @@ the Collaboration Asset, the user will be notified.|, message => q|A group that is allowed to edit posts after they have been submitted.|, lastUpdated => 1269283819, }, - + 'use captcha label' => { message => q|Use Post Captcha|, lastUpdated => 1170543345, @@ -1609,7 +1635,7 @@ the Collaboration Asset, the user will be notified.|, message => q|Choose whether or not to make users verify their humnanity before being able to post to this collaboration system|, lastUpdated => 1170543345, }, - + 'captcha label' => { message => q|Verify your humanity|, lastUpdated => 1170543345, @@ -1631,7 +1657,7 @@ the Collaboration Asset, the user will be notified.|, message => q|Keywords|, lastUpdated => 1170543345, }, - + 'asset not committed' => { message => q{
You need to commit this collaboration system before you can create a new thread
}, lastUpdated => 1166848379, @@ -1683,6 +1709,42 @@ the Collaboration Asset, the user will be notified.|, lastUpdated => 0, }, + 'unsubscribe formHeader' => { + message => q{HTML code to start the unsubscribe form.}, + context => q{Template variable help}, + lastUpdated => 0, + }, + + 'unsubscribe formFooter' => { + message => q{HTML code to end the unsubscribe form.}, + context => q{Template variable help}, + lastUpdated => 0, + }, + + 'unsubscribe formSubmit' => { + message => q{A button to submit the form.}, + context => q{Template variable help}, + lastUpdated => 0, + }, + + 'unsubscribe formEmail' => { + message => q{A text form with email completion.}, + context => q{Template variable help}, + lastUpdated => 0, + }, + + 'unsubscribe formMessage' => { + message => q{Internationalized messages to tell the user about errors and successes.}, + context => q{Template variable help}, + lastUpdated => 0, + }, + + 'You have been unsubscribed' => { + message => q{You have been unsubscribed.}, + context => q{status message}, + lastUpdated => 0, + }, + }; 1;