Skip to content

Commit

Permalink
Switch from using Mojolicious templates to a text .msg file and basic…
Browse files Browse the repository at this point in the history
… interpolation.

Mojolicious templates allow to much, and as such are a security
vulnerability.  Too bad.

This calls the WeBWorK::Utils::processEmailMessage method again.  Then
interpolates some achievement specific variable in after that.  More
variables may be needed, but this is a start.
  • Loading branch information
drgrice1 committed Dec 2, 2023
1 parent 80193ff commit c53b343
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 47 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$FN

Congratulations, you just earned the $ACHIEVEMENT_NAME achievement!

$ACHIEVEMENT_DESCRIPTION

You have $POINTS_TO_NEXT_LEVEL points remaining until your next level-up.

Great job!
--Prof. X
46 changes: 28 additions & 18 deletions lib/Mojolicious/WeBWorK/Tasks/AchievementNotification.pm
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ use Mojo::Base 'Minion::Job', -signatures;

use Email::Stuffer;
use Email::Sender::Transport::SMTP;
use Mojo::File;

use WeBWorK::Debug qw(debug);
use WeBWorK::CourseEnvironment;
use WeBWorK::DB;
use WeBWorK::Localize;
use WeBWorK::Utils qw(createEmailSenderTransportSMTP);
use WeBWorK::Utils qw(processEmailMessage createEmailSenderTransportSMTP);

# send student notification that they have earned an achievement
sub run ($job, $mail_data) {
Expand Down Expand Up @@ -60,25 +61,34 @@ sub send_achievement_notification ($job, $ce, $db, $mail_data) {
my $user_record = $db->getUser($mail_data->{recipient});
die "Record for user $mail_data->{recipient} not found\n" unless ($user_record);
die "User $mail_data->{recipient} does not have an email address -- skipping\n"
unless ($user_record->email_address =~ /\S/);

my $template = "$ce->{courseDirs}{achievement_notifications}/$mail_data->{achievement}{email_template}";
my $renderer = Mojo::Template->new(vars => 1);

# what other data might need to be passed to the template?
my $body = $renderer->render_file(
$template,
{
ce => $ce, # holds achievement URLs
achievement => $mail_data->{achievement}, # full db record
setID => $mail_data->{set_id},
nextLevelPoints => $mail_data->{nextLevelPoints},
pointsEarned => $mail_data->{pointsEarned},
user => $user_record,
user_status => $ce->status_abbrev_to_name($user_record->status)
}
unless $user_record->email_address =~ /\S/;

my $body = processEmailMessage(
Mojo::File->new("$ce->{courseDirs}{achievement_notifications}/$mail_data->{achievement}{email_template}")
->slurp('UTF-8'),
$user_record, $ce->status_abbrev_to_name($user_record->status)
);

{
# Additional macros that can be used in the email message.
# What other data might need to be passed to the template?
my $ACHIEVEMENT_NAME = $mail_data->{achievement}{name};
my $ACHIEVEMENT_DESCRIPTION = $mail_data->{achievement}{description};
my $SET_ID = $mail_data->{set_id};
my $NEXT_LEVEL_POINTS = $mail_data->{nextLevelPoints};
my $POINTS_EARNED = $mail_data->{pointsEarned};
my $POINTS_TO_NEXT_LEVEL = $$NEXT_LEVEL_POINTS > $POINTS_EARNED ? $NEXT_LEVEL_POINTS - $POINTS_EARNED : 0;

$body =~ s/\$ACHIEVEMENT_NAME/$ACHIEVEMENT_NAME/g;
$body =~ s/\$ACHIEVEMENT_DESCRIPTION/$ACHIEVEMENT_DESCRIPTION/g;
$body =~ s/\$SET_ID/$SET_ID/g;
$body =~ s/\$NEXT_LEVEL_POINTS/$NEXT_LEVEL_POINTS/g;
$body =~ s/\$POINTS_EARNED/$POINTS_EARNED/g;
$body =~ s/\$POINTS_TO_NEXT_LEVEL/$POINTS_TO_NEXT_LEVEL/g;

$body =~ s/\r//g;
}

my $email =
Email::Stuffer->to($user_record->email_address)->from($from)->subject($mail_data->{subject})->text_body($body)
->header('X-Remote-Host' => $mail_data->{remote_host});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ sub pre_header_initialize ($c) {
}

$c->{sourceFilePath} =
$c->ce->{courseDirs}{achievement_notifications} . '/'
. ($c->{achievement}->email_template || 'default.html.ep');
$c->ce->{courseDirs}{achievement_notifications} . '/' . ($c->{achievement}->email_template || 'default.msg');

my $actionID = $c->param('action');

Expand Down Expand Up @@ -199,8 +198,8 @@ sub save_as_handler ($c) {
$c->addbadmessage($c->maketext('Achievement notification contents is empty.'))
unless $c->stash->{achievementNotification};

# Rescue the user in case they forgot to end the file name with .html.ep
$new_file_name =~ s/(\.html)?(\.ep)?$/.html.ep/;
# Rescue the user in case they forgot to end the file name with .msg
$new_file_name =~ s/(\.msg)?$/.msg/;

# Construct the output file path.
my $outputFilePath = $c->ce->{courseDirs}{achievement_notifications} . '/' . $new_file_name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
url_for('instructor_achievement_notification', achievementID => $achievement_id),
), begin =%>
<%= $_->email_template
? maketext('Edit Email Template [_1]', $_->email_template =~ s/\.html\.ep//r)
? maketext('Edit Email Template [_1]', $_->email_template =~ s/\.msg//r)
: maketext('Enable Email Notification') =%>
<% end =%>
</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<div class="col-auto">
% my $relativeSourceFilePath = $c->getRelativeSourceFilePath($c->{sourceFilePath});
<%= select_field 'action.existing.target_file' => [
map { [ $_ =~ s/(\.html)?\.ep//r => $_, $_ eq $relativeSourceFilePath ? (selected => undef) : () ] }
@{ path($ce->{courseDirs}{achievement_notifications})->list->grep(qr/\.ep$/)
map { [ $_ =~ s/\.msg$//r => $_, $_ eq $relativeSourceFilePath ? (selected => undef) : () ] }
@{ path($ce->{courseDirs}{achievement_notifications})->list->grep(qr/\.msg$/)
->map(sub { $c->getRelativeSourceFilePath($_) })->to_array }
],
id => 'action.existing.target_file_id', class => 'form-select form-select-sm d-inline w-auto',
Expand Down
25 changes: 15 additions & 10 deletions templates/HelpFiles/InstructorAchievementNotificationEditor.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,21 @@
</dl>
<h2><%= maketext('Template Substitutions') %></h2>
<p>
<%== maketext('The following variables are available for use in the template. These variables can be used inside '
. '[_1] tags. For example, [_2] will insert the description of the achievement into the email body.',
'<code>&lt;%= ... %&gt;</code>', '<code>&lt;%= $achievement->description %&gt;</code>') =%>
<%== maketext('The following variables are available for use in the template.') =%>
</p>
<ul class="mb-0">
<li><code>$ce</code>: This gives access to the entire course environment.</li>
<li><code>$achievement</code>: The database record for the achievement.</li>
<li><code>$setID</code>: The name of the set the student was working when the achievement was earned.</li>
<li><code>$nextLevelPoints</code>: The number of points that the student must attain to reach the next level.</li>
<li><code>$pointsEarned</code>: The number of achievement points earned for this achievement.</li>
<li><code>$user</code>: The database record for the student user.</li>
<li><code>$user_status</code>: The enrollment status of the user.</li>
<li><code>$SID</code>: Student id</li>
<li><code>$FN</code>: Student first name</li>
<li><code>$LN</code>: Student last name</li>
<li><code>$SECTION</code>: Section the student is in</li>
<li><code>$RECITATION</code>: Recitation the student is in</li>
<li><code>$EMAIL</code>: Student email address</li>
<li><code>$LOGIN</code>: Student login name</li>
<li><code>$STATUS</code>: The enrollment status of the student.</li>
<li><code>$ACHIEVEMENT_NAME</code>: Achievement name.</li>
<li><code>$ACHIEVEMENT_DESCRIPTION</code>: Achievement description</li>
<li><code>$SET_ID</code>: The name of the set the student was working when the achievement was earned.</li>
<li><code>$NEXT_LEVEL_POINTS</code>: The number of points that the student must attain to reach the next level.</li>
<li><code>$POINTS_EARNED</code>: The number of achievement points earned for this achievement.</li>
<li><code>$POINTS_TO_NEXT_LEVEL</code>: The number of achievement points the student needs to earn to level up</li>
</ul>

0 comments on commit c53b343

Please sign in to comment.