Teach 1975/ensure in development units are not visible to signed out users #66459
Conversation
…nto TEACH-1975/Ensure-in-development-units-are-not-visible-to-signed-out-users-
…e-not-visible-to-signed-out-users-
| # TEACH-1975 for more details).This solves the issue by explicitly calling authorize! | ||
| # on the @script if it is set. | ||
| private def authorize_script | ||
| authorize! params[:action].to_sym, @script || Unit |
There was a problem hiding this comment.
I think I just ran into a similar issue on my UI test PR, which involves some similar logic in the script levels controller. I don't see how this can work in all cases because cancan doesn't know about the published state of the UnitGroup, which is (should be?) a factor in whether the unit is visible to a user via show.
There was a problem hiding this comment.
can you please make sure you are testing these scenarios or something equivalent?
originalunit group isin_development,modularunit is inbeta, student CAN access/courses/modular/units/1originalunit group is inbeta,modularunit isin_development, student can NOT access/courses/modular/units/1
There was a problem hiding this comment.
hm, yeah, just testing manually the first thing i found which was csd-2025 in preview as the original course and focus-on-coding-2025 which is in development as the "modular" course. I was able to access courses/focus-on-coding-2025/units/1. It looks like we'll need to add an additional check on the unit group.
There was a problem hiding this comment.
thoughts on authorizing the unit group in that same method?
private def authorize_script
authorize! params[:action].to_sym, @course || UnitGroup
authorize! params[:action].to_sym, @script || Unit
endThere was a problem hiding this comment.
nevermind. that only works when the modular course is "stricter" than the original course, for example, the original course is stable, but the modular course is in development.
There was a problem hiding this comment.
I got as far as being not quite sure how to approach this -- I'm not sure cancan is well set up to authorize when multiple objects are needed. Will dig in more this morning.
There was a problem hiding this comment.
We could use other auth methods outside of can can is that's what's needed. Not ideal, however, everything should be as simple as possible but not simpler.
There was a problem hiding this comment.
thoughts on authorizing the unit group in that same method?
private def authorize_script authorize! params[:action].to_sym, @course || UnitGroup authorize! params[:action].to_sym, @script || Unit end
I think you are on the right track here --
- authorize UnitGroup based on published state, etc
- authorize Unit based on login_required but NOT published state (of unit or of original unit group)
thoughts?
davidsbailey
left a comment
There was a problem hiding this comment.
This solution looks great! One readability nitpick inline.
| else | ||
| false | ||
| end | ||
| end |
| test_user_gets_response_for :show, response: :not_found, user: nil, | ||
| params: -> {{course_course_name: original_course.name, unit_position: unit_position, position: lesson_position}}, | ||
| name: 'signed out user cannot view in-development original course' |
There was a problem hiding this comment.
I'm not sure if this is technically against any style rule, but I'm finding this formatting to be a bit hard to read, at least with github wrapping it at around 100 chars. in particular it's hard to quickly see the name or the difference in params. Would this style work for you?
or this (from later in this PR)?
code-dot-org/dashboard/test/controllers/scripts_controller_test.rb
Lines 1619 to 1622 in 1217cef
as an alternative, I could also see extracting original_path and modular_path param objects that could be passed in as params: -> {original_path} to make the lines a bit shorter.
sorry for the nit 😬
There was a problem hiding this comment.
No apologies, I agree! I'll update it to make it more readable. thanks!
…e-not-visible-to-signed-out-users-
Currently, with the new
/courses/.../units/...URL structure, units were not being authorized correctly withauthorize_resource. This PR adds a separate before action to manually authorize the selected unit.Background
I found that the issue came down to CanCan authorizing the Unit model instead of the specific unit object with the new url structure. Based on my understanding, this is because the new urls no longer have the :id parameter to search for the unit by, which CanCan falls back to.
@scriptis set in:set_unit. Theinstance_namepart ofauthorize_resourceis telling it to reference the@scriptinstance when authorizing. Through debugging I confirmed that@scriptwas properly set whenauthorize_resourcewas called, it just wasn't being used to authorize. It wasn't until I added anid_paramthat it actually used@script. From my understanding, id_param tells CanCan what parameter to use to find the unit if@scriptis empty when it tries to authorize. With the new url structure, we don't get a param that could be used by that find method to identify a Unit.Note:
db_query_test.rbhad to be updated because prior to this PR, the unit was rendering a no_access instead of the unit overview page. the changes in this PR have the side-effect of fixing the test, resulting in a larger query count.Links
This solves 2 tickets:
Testing story