-
Notifications
You must be signed in to change notification settings - Fork 480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add no_redirect query param for course, script, and puzzle show routes #28311
Conversation
@@ -382,10 +382,10 @@ def script_level_params(script_level) | |||
end | |||
|
|||
test "show: redirect to latest stable script version in family for logged out user if one exists" do | |||
courseg_2018 = create :script, name: 'courseg-2018', family_name: 'courseg', version_year: '2018' | |||
Script.stubs(:latest_stable_version).returns(courseg_2018) | |||
courseg_2017 = create :script, name: 'courseg-2017', family_name: 'courseg', version_year: '2017', is_stable: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: this is just clean-up, not changing test behavior
test "show: redirect to latest assigned script version in family for student if one exists" do | ||
sign_in @student | ||
|
||
courseg_2018 = create :script, name: 'courseg-2018', family_name: 'courseg', version_year: '2018' | ||
Script.stubs(:latest_assigned_version).returns(courseg_2018) | ||
courseg_2017 = create :script, name: 'courseg-2017', family_name: 'courseg', version_year: '2017', is_stable: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: this is just clean-up, not changing test behavior
I know Dave suggested an alternative at one point:
On the surface it sounds simpler. As part of this PR, will you document why we chose this solution instead? |
@@ -62,7 +62,8 @@ def show | |||
end | |||
|
|||
# Attempt to redirect user if we think they ended up on the wrong course overview page. | |||
if redirect_course = redirect_course(course) | |||
# Do not redirect users that have added the 'no_redirect' query parameter to the request. | |||
if !params[:no_redirect] && redirect_course = redirect_course(course) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm tempted to push the no_redirect
check down into the redirect_course
helper (or redirect_script
in other cases). I think it's because the rest of the "do we redirect" logic is hidden down in that layer. I don't feel too bad about referencing params
from the helper, since in every case it's still implemented as part of the same controller.
That said, it wouldn't actually remove any duplication and might be considered surprising behavior. Your call.
|
||
get :show, params: {course_name: 'csp-2017', no_redirect: "true"} | ||
|
||
assert_response :ok |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My own ignorance: I had to think carefully and look some things up to understand that this checks for exactly 200 OK
, unlike assert_response :success
which matches any 2XX, and that either would confirm that the response to this request was not a (3XX) redirect. 🤦♂️
@islemaster re: your comment --
part of the request from the international team (Amanda and I talked with Suky about it) was to have a single URL that would let the user bypass our redirect logic, so to achieve this, it seemed simplest to just ignore the redirect logic if the URL has |
I think the idea with using /next is that we wanted to let the user navigate around the course without getting sent back to the latest stable version. For example, if you send a signed-out user to https://studio.code.org/courses/csp-2019?no_redirect=true and then they click on the first unit, they will get sent back to csp-2018 since that is the latest stable version. is that outcome acceptable? |
good question, dave. i think that outcome is acceptable because it gives us the flexibility to send a user to a specific level, where they would "make progress" so that they are no longer redirected to the latest stable version (this, to me, is the same as using /next to get around version redirects), or any user can visit a course/script/level once with the |
Hi Maddie, the behavior I'm seeing is that once you go to http://localhost-studio.code.org:3000/s/csd1-2019?no_redirect=true, there's no way to ' "make progress" so that they are no longer redirected to the latest stable version '. These are the steps I'm taking:
Is there a different way you've found to make progress from http://localhost-studio.code.org:3000/s/csd1-2019?no_redirect=true ? it's ok if this needs to be implemented across multiple PRs, but want to know that this builds in the right direction. |
ah, i'm sorry, i should have been more specific in my original comment. these are the steps i was thinking: a user who wants to disable redirects permanently for a course or script would do the following:
visiting an individual will provide a permanent override for version redirects, or a user can visit something like http://localhost-studio.code.org:3000/s/coursea-2019?no_redirect=true for a one-time override (curriculum folks and other internal users have asked for this as well, especially for courses/scripts that are still in development like the 2019 versions) |
after pulling down your branch, when i follow these steps while signed out, I am not seeing the same result as you. I am getting redirected to coursea-2018. I think perhaps an additional step is needed, of finishing the level, so that progress is created. can you try the steps you listed in a fresh incognito window to determine if we're seeing the same thing? |
🤦♀ you're right, this solution only works for signed in users. unfortunately, we will have the same issue with the code-dot-org/dashboard/app/models/script.rb Lines 566 to 567 in a4c8003
i'll talk to Amanda to figure out if this is a case we want to solve for (a signed out user who wants to permanently override versioning redirects for a course/script). if we do solve for this case, i see this path forward:
the above sounds a little heavy-handed, but i can't think of a better solution... thoughts? |
ahh, that explains it, I had not tried for signed-in users. Signed-out users do have progress, but unfortunately it is stored in localStorage in their browser, which we can't access on the server. Based on that, I think you are on the right track with using a cookie to persist this setting. However, it may be easier to use the rails session instead, since they are like cookies but hide more details away. Here is an example of rails session being used:
If you do go with a cookie instead, here is one thought:
whichever approach you decide:
|
ooo, i like the idea of using the rails session, so i'll try that first. thanks for your help on this! |
@davidsbailey @islemaster I refactored the solution to store course/script version redirect overrides in the Rails session -- PTAL! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool - the Rails session seems like an elegant solution to this problem.
Will you add to the PR description an example case of where/why we'd want to use this queryparam?
@@ -0,0 +1,37 @@ | |||
module VersionRedirectOverrider |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have a file- or module-level comment here giving a prose description of the desired redirect logic, and/or a link out to a spec describing the desired behavior in detail. Even with the good tests you've written, I worry that the desired behavior is complex enough, and the related logic spread out enough, that it'll be challenging to reconstruct a mental model for these redirects in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, good call! i'll add a description and some usage info to the module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice work Maddie! A few comments inline.
script_overrides = script_version_overrides(session) | ||
course_overrides = course_version_overrides(session) | ||
|
||
script_overrides.include?(script.name) || course_overrides.include?(script.course&.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice call making this a module so it can be used many places.
there's a fair bit of complexity we're adding here, between storing lists of scripts + courses, and checking both before deciding whether to redirect a script or not. the simple alternative would be to just store one "no redirect" setting per user. I think the added complexity is worth it though, since we really want to the limit the chances that students will end up with progress in the wrong version of a course.
lastly, IIRC the docs say that things stored in the rails session expire when the browser window is closed, but that could be worth confirming -- it might be bad if one person accessing a no_redirect url on a shared computer made it behave that way forever for signed-out users.
id: courseg_2017_stage_1_script_level.position, | ||
no_redirect: "true" | ||
} | ||
assert_response :ok |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional: it's a bit hard to see that this is an apples-to-apples comparison against the following test which does the same but without no_redirect. my recommendation would be to either extract common setup steps, or to just drop this get / assert at the end of the following test so that you can see the no_redirect param is making the difference.
this PR has dragged on a bit already, so feel free to skip and keep in mind for next time.
end | ||
|
||
test "show: do not redirect to latest stable version if no_redirect query param is supplied" do | ||
get :show, params: {id: @coursez_2017.name, no_redirect: "true"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar to above, it would make this test case more clear to add a get / assert above this line showing the behavior without no_redirect
LP-346
Adds the ability to override our course/script version redirect logic by adding the
no_redirect
query parameter to the request. This "redirect override" will then be stored in the Rails session to be remembered for the life of the session.This is most useful for internal users (especially content translators) who need to visit an old or unstable course/script without being redirected. This is primarily useful for logged out users who want to visit these courses/scripts one or more times (since logged out users and students are the only users who are ever redirected away from courses/scripts).
To use this feature, visit a course, script, or level URL with the
?no_redirect=true
query param:Redirect overrides are stored in the session as follows:
If a script has an override, its course (if present) is implicitly overridden as well, and vice versa.
Note: the value of this query param is ignored -- we just check for the presence of the
no_redirect
key in our params hash.