Skip to content

WeBWorK 2.21 Release Candidate - #2940

Merged
drgrice1 merged 570 commits into
mainfrom
WeBWorK-2.21
Aug 4, 2026
Merged

WeBWorK 2.21 Release Candidate#2940
drgrice1 merged 570 commits into
mainfrom
WeBWorK-2.21

Conversation

@drgrice1

Copy link
Copy Markdown
Member

This is the release candidate for WeBWorK 2.21. Please re-target any pull requests that you want to get into the release for this branch.

drgrice1 and others added 30 commits May 6, 2026 07:50
…structor.

When an instructor uses the "Grade Test for" button and the test is on
its final submission, currently the grading occurs, but the test is
still set as a proctored test.

To fix this the condition that determines if the assignment type should
be changed needs to check the `$can{recordAnswers}` value in the case
that the `$userID` and `$effectiveUserID` are different.  In that case
`$can{recordAnswers}` is the result of the `can_recordAnswers` method
which will be true if either the user has the
`record_answers_when_acting_as_student` permission or the user can grade
an unsubmitted test.

This fixes issue #2962.

The `GatewayQuiz.pm` module is really so convoluted at this point that
it is really becoming impossible to do anything with, and is in
desperate need of a complete overhaul and rewrite. Any time any new
feature is added to the module or change is made to the module it is
almost impossible to go through all of the possibilities and ensure you
haven't broken something.
This was done for the student nav elsewhere but missed here.
Brackets in a string that are intended to be literal brackets need to be
escaped.

To test this earn the "Mysterious Package (with Ribbons)" achievement
reward, make sure the `templates/achievements/surprise_message.txt` file
does NOT exist, and then open a problem set page.  With the WeBWorK-2.21
release candidate branch an exception is thrown.

This particular bug apparently has been there since 2015.
Fix an invalid localization string in a maketext call.
Fix grading proctored tests that require proctor authorization to do so.
…-test

Make sure that a proctored test becomes unproctored when graded by instructor.
Fix the active colors of the selected test or filter in the test nav.
Fix division by zero in {Full,Half}CreditSet Items.
Fix the `change_user_id` script for the case that a user does not have a password.
The colors for this were inline style.  Colors cannot be inline anymore
since the server cannot detect if the user will have the browser in dark
mode or not.  So this switches to using Bootstrap alerts instead.
Fix colors on the proctor login page for dark mode. (Bootstrap alert aproach)
Now that the student nav is on every set and problem page there is a
need to make the retrieval of all users assigned to the set faster.  I
noticed in a large class with more than 25,000 users this is quite slow
now.  It takes about 8 seconds for each page to load.  The problem is
the query is passing all of the user ids of those assigned to the set to
the `getUsersWhere` method.  That means that `SQL::Abstract` has to
process all of those and compile a rather long sql statement.  That is
slow.  So this breaks the list of user ids into chunks of 500.  For the
class with more than 25,000 users this drops the page load time to just
under 2 seconds.  Stil not great, but considerably better.

On my production placement exam server that has just over 32,000 users
it currently takes more than 35 seconds for each page to load.  With
this pull request it drops the time to about 8 seconds.  Again, not
great but considerably better.  Clearly the placement server is not as
fast as my local computer also.

Note that for classes with less than 500 users this won't change
anything.

Also note that this is only an issue for those that have the student nav
shown.
This was suggested by @Alex-Jordan, and does seem to be much better.
This set has nothing of value in it anymore.  The problems are really
not what we want problem authors to use as a model for new problems.

It is time for this set to go.
This was a remnant of my first approach for the Demo set of moving it to
`assets/pg` and using a link in the model course, and then rewriting all
of the problems using modern techniques. This link should not have made
it into #2979.
Remove a symbolic link accidentally added in #2979.
Improve the speed of the database user retrieval for the student nav.
I used the wrong thing in #2975.
Add `$achievementExtensionFactor` setting that is used to configure
the length of extensions. This works as a multiplicative factor, by
multiplying the base time (either 24 or 48 hours) by the factor. The
extension time is always rounded to the nearest hour, and cannot be
less than a single hour (two hours for the super extensions).

This affects all items that have an extension time.

* ExtendDueDate
* ExtendDueDateGW
* ExtendReducedDate
* ReducedCred
* RessurectGW
* RessurectHW
* SuperExtendDueDate
* SuperExtendReducedDate
Store the setID of all completed sets in the globalHash when
evaluating achievements. This allows achievements to use this
data vs just counting the number of completed sets. One use case
is being able to exclude optional sets, such as review sets, from
some achievements without completely excluding them from all
achievements.

In addition saving all the setIDs can avoid a double counting
completed sets, as there is currently no check to ensure a set
is not counted multiple times.
The code and rendering panels are now not only vertically resizable, but
are horizontally resizable when the window with is at or above the large
breakpoint (992 pixels).

Furthermore, resizing does not work with the native browser resize via
the css `resize` property. Instead it is controlled with JavaScript.
The resize grips (which are much more visible now) can be also be
focused with the keyboard and when focused the arrow keys can be used to
resize the code and render panels. Note that if `Ctrl` is pressed with
an arrow key a 1 pixel resize occurs, and if `Alt` is pressed with an
arrow key a 50 pixel resize occurs.  Without a modifier key the arrow
keys perform a 20 pixel resize.

In addition, the dimensions are saved to local storage and persist when
the page reloads. Unfortunately there will be some flickering of content
as the resize occurs after the page loads.

Note that the css `resize` property is actually not supported in all
browsers, so this actually makes resizing work for those browsers as
well.  The browsers that do not support the css `resize` property
include Firefox for Android, and Safari on IOS. Yeah, those are for
mobile devices, and who edits problems on a mobile device?  In any case,
this makes the resize grips more evident.  The native resize grip is
rather small in the lower right corner of the CodeMirror editor panel,
and many probably don't even know it is there.

Note that the code panel has a minmimum width of 400 pixels, and the
rendering panel a minimum width of 300 pixels.  This works out so that
when the window size is 992 pixels the two panels can't really be
resized much or at all (when the site navigation menu width of 250
pixels is taken into account) depending on the browser. But at larger
window widths resizing can be done.

I thought about making it so that the resizing could go all the way to
the right and the rendering panel be resized to a width of 0, but
decided against it.  If that were done, then the rendering would still
be occuring even though you can't see it, and that doesn't seem good.  I
think that this should at least alleviate the request(s) to hide the
rendering panel (which I don't think is really a good idea).
Better keep track of which sets are complete in achievements.
Rework resizing of the problem editor.
This replaces the Grades page for students with a new layout
designed for students. The old grades table is still available
to instructors under "Student Progress". Being a grade page
for students, instructors see the same info a student would
(no hidden sets or grades are shown for instructors acting as
a student). The only difference for an instructor is the student
navigation menu is shown to switch which student to act as.

The assignments are split into categories. Open assignments,
reduced scoring assignments (if reduced scoring is enabled),
and closed assignments. Assignments are ordered using the
same `byUrgency` logic as the ProblemSets page.

The total grade, if configured to be shown, is shown at the
top of the page for all sets that are past the open date.

Each assignment is a list item which shows the total score.
For tests the best test version score is shown if the student
can see the score. Then a table which includes the total score
and status for each problem in the set. For just in time,
only top level problems are shown. For tests, only the best
test version is shown.

The old Grades page code is moved into StudentProgress.pm
where it is still used.
Suggested by @Alex-Jordan, add the weights to the grade page and
then add buttons to hide/show the weights. The buttons use local
storage to save the state. The default state is to have the
weights and attempts hidden. Since the toggle happens at page load
the change is noticed when the page loads if not using the defaults.

Also put the version and score on a single row to save height
and a little bit of refactoring of adding the problems for each
set to save duplication of code.
somiaj and others added 26 commits July 28, 2026 13:54
Guidance for an instructor who has not set the LMS context ID
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
make a few anchors with 'role="button"' respond to space
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
I don't think that anyone uses this anymore, and no one should use it.
It is not secure, and there are better ways to interact with webwork,
such as LTI authentication.
See mathjax/MathJax#3589 where @dpvc provided
the workaround added here into mathjax-config.js.

For the future, MathJax 4.2 will fix the issue by adding a dir="ltr"
attribute to the mjx-container element. That is in
mathjax/MathJax-src#1526
so this change can be removed WeBWorK transitions to MathJax 4.2.
Workaround for issue with MathJax 4 in RTL contexts
put aria-sort attributes on tables in Instructor Tools
Remove the plural on the PGML convert error as was done on the PG side
as there is only ever one error.

Remove the `<pre><code>` wrapper.  That is not right for this type of
message.
…lnerabilities.

Actually only `postcss` needed to be updated, but I updated all of the
development dependencies to their latest versions (only `sass` and
`yargs` were not at their newest versions).  The development
dependencies are easy to test.  If the `generate-assets.js` script still
works as it should then all is good.  Note that you can test by
executing `npm ci` since that runs the script.

I left production dependencies as they are.  I didn't actually even
check if there are any upgrades, but those can take more time to
properly test since we actually use those.
Update the npm development dependencies once again to fix security vulnerabilities.
…ourse directory.

Currently when extracting zip or tar archives in the file manager, any
symbolic link in the archive is extracted assuming the link itself is in
the course directory.  That is a security vulnerability as a link could
point to something like `/etc` and give unsecure access to system files.

So this refuses to extract symbolic links in archives that point outside
the course directory. The way that this works is it actually does create
the links, but then it prunes any links that point outside the course
directory.  This is so that `realpath` can be used, and is the only way
to properly validate the links.  Naively attempting to collapse `..`
instances in the path does not work reliably (see the note for the
`canonpath` method at https://metacpan.org/pod/File::Spec::Unix), and I
was able to subvert that to achieve a functional link to outside of the
course directory.  Note that broken symbolic links must also be
rejected. This is because `realpath` does not work for these, and so
there is no way to validate them as being links that point inside the
course directory.  In fact, it is possible to devise a broken symbolic
link that combined with a valid symbolic link in another archive file,
becomes a link to a location outside of the course directory (and I did
so in testing).

Note this means that the only symbolic links allowed in a course are the
required symbolic links (`Library`, `Contrib`, and `Student_Orientation`
at this point), and those that are created by a system administrator.
Also note that symbolic links in a course archive are still restored as
before when unarchiving a course.  It is considered the responsibility
of the system administrator to validate links in a course archive.

This fixes the last of the security vulnerabilities that @Alex-Jordan
found.  Note that this was initially coded by Claude, but I largely
rewrote what Claude created.
Co-authored-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Updates to the PG problem editor PGML conversion for corresponding changes to PG.
show links to sets even when you are not assigned to those sets
Co-authored-by: Claude <noreply@anthropic.com>
Refuse to extract symbolic links in archives that point outside the course directory.
buttons for reordering problems in a set details page
Allow users (with high enough permission) to set their answer date to…
button to announce remaining time on test
@drgrice1
drgrice1 merged commit 319646a into main Aug 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants