Skip to content

Implement public cohort for anonymous and unenrolled users - #19385

Merged
ormsbee merged 1 commit into
openedx:masterfrom
open-craft:pooja/implement-public-cohort
Feb 8, 2019
Merged

Implement public cohort for anonymous and unenrolled users#19385
ormsbee merged 1 commit into
openedx:masterfrom
open-craft:pooja/implement-public-cohort

Conversation

@pkulkark

@pkulkark pkulkark commented Dec 7, 2018

Copy link
Copy Markdown
Contributor

This PR is based on #19284 and is part of the series of work related to the proposal #18134 .

Description:

Allow anonymous and unenrolled users access to public courses with cohorts enabled.
Current behaviour is that if the course had cohorts enabled and any user accessing the course that is not assigned to a cohort gets assigned to a "default" cohort. This PR avoids the assignment of anonymous/unenrolled users to any cohort when course is public. Anonymous or unenrolled users will only see content that does not have a content group assigned.
The "View Course" link to the course outline is shown on the course about page for a course marked public/public outline. It also makes course handouts available for public courses (not for public_outline).
This PR also hides the different warnings and messages asking the user to sign-in and enroll in the course, when the course is marked public. It modifies the default public_view text to include the component display_name when unenrolled access is not available.

Sandbox server:

Contains 2 courses:

  • edX Demo Course has seo.enable_anonymous_courseware_access course waffle flag, and the "Advanced Settings > Course Visibility For Unenrolled Learners" set to public.

  • Test Course also is set to public. It contains 3 units : Unit-1 is accessible to all, Unit-2 has access restricted to "test_cohort" and can only be seen by the verified@example.com user and Unit-3 is a randomized content block that can be viewed only when the user is enrolled.

Testing Instructions:

  • Create a course and enable cohorts.

  • Mark the course as public and try accessing the course content as an anonymous or unenrolled user. The course content not assigned to any content group should be accessible. None of the warnings should be seen.

  • Mark the course as public/public_outline and access the course about page. There should be a "View Course" button visible which links to the course outline.

  • If the course is marked public, the course handouts should be available to anonymous/unenrolled users as well. If course is marked public_outline, handouts should not be available.

@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @pkulkark! I've created OSPR-2885 to keep track of it in JIRA. JIRA is a place for product owners to prioritize feature reviews by the engineering development teams.

Feel free to add as much of the following information to the ticket:

  • supporting documentation
  • edx-code email threads
  • timeline information ("this must be merged by XX date", and why that is)
  • partner information ("this is a course on edx.org")
  • any other information that can help Product understand the context for the PR

All technical communication about the code itself will still be done via the GitHub pull request interface. As a reminder, our process documentation is here.

@openedx-webhooks openedx-webhooks added needs triage open-source-contribution PR author is not from Axim or 2U labels Dec 7, 2018
@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch from 7757a0e to a1d857e Compare December 7, 2018 06:39
@natabene

natabene commented Dec 7, 2018

Copy link
Copy Markdown
Contributor

@pkulkark Thank you for your contribution. Please let me know once it is ready to be looked at.

@openedx-webhooks openedx-webhooks added waiting on author PR author needs to resolve review requests, answer questions, fix tests, etc. and removed needs triage labels Dec 7, 2018
@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch from a1d857e to cf5fbb5 Compare December 11, 2018 10:31
@symbolist

Copy link
Copy Markdown
Contributor

Hi @natabene, do we need to trigger Jenkins manually here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to the top of the method? I do not see why we need to do any of above if it's an anonymous user?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the sake of completeness can you also check that it returns None if the course is not cohorted?

And this docstring needs to be updated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does get_student_module_as_dict() not return {} if the user is Anonymous. I know this saves a query but we are calling out to the StudentModule in the courseware as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The query to database fails when queried with anonymous user object with TypeError("'AnonymousUser' object is not iterable",).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to push this logic down into get_student_module_as_dict, even if it means that we have to add an explicit check there for .is_authenticated there? The CSM state dict for any unauthenticated user for a given block is always going to be empty right?

The reason I ask is that unauthenticated access is a new dimension of complexity, and I'd like to see that complexity contained to as few places as possible. The more places people have to sprinkle their code with is_authenticated(), the more likely they're going to forget and we're going to get mysterious breakages related to this functionality.

@symbolist symbolist Jan 29, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think that some higher level code (including XBlocks) will want to differentiate between cases where there is a valid user and where there is not. For example, even in the case of the library xblock, maybe it would be better that for anonymous users, it returns the first n children xblocks always instead of a random subset on each page refresh as it is doing right now? (Library xblocks aren't really important for open courses, so we didn't spend too much time on figuring out the right product strategy here but this can be changed if required)

But maybe a lot of places do not need to differentiate. In that case do we want the lower layer to properly support being passed anonymous user objects? My thinking is "higher layer should only call out to the KVS/SM if there is a valid user" because the state is scoped to users and "please get or save (in the case below) this data unless this user is None in which case do nothing." seems a bit unergonomic? Is there a nice way of doing it while pushing the logic down?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine that XBlocks differentiate when they find it useful to do so. But I think it's also reasonable to make get_student_module_as_dict check for anonymous users and do the right thing for them (as opposed to just blowing up).

In any case, it's not something I feel strongly enough to block merging over. Just a long term concern I have. If it's really just this XModule doing it, then it's not worth worrying over. If it becomes a recurring pattern in other classes, then I would get more concerned.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the is_authenticated check to get_student_module_as_dict method.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ormsbee Ah, okay.

@pkulkark Thanks for updating it!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thing with this approach is that it is going to cause make_selection to return a different set of XBlocks on every view. To keep it stable may make more sense to add a mode first which returns the first max_count items from library_children.

And we can move the check to the first line: if not isinstance(usage_info.user, AnonymousUser) and any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I don't think I quite understood. We don't want it to return a different set of Xblocks on every view? I was under the impression that since we select Randomized Content Block while creating the course, the expected behaviour is that it should return random block(s) from the library. Is that not the case?

@symbolist symbolist Dec 12, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that the first time a learner accesses the XBlock a random set of children is calculated and stored in state[selected]. And they continue to see those same children in subsequence views (unless the children or the max_count values change where the list of children is updated).

Having said so I just realize that we do not have a public_view for the library xblock (the learner will be seeing the "Please enroll to view" message) and since we do not need to support it either for now lets just move the check to the outer if and let make_selection return a random set every time as it is the case right now.

Nit: the convention is to use [is_authenticated](https://docs.djangoproject.com/en/2.1/ref/contrib/auth/#django.contrib.auth.models.User.is_authenticated) instead of the type of user objects.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification. I've moved the check to the outer if.

@mduboseedx

Copy link
Copy Markdown
Contributor

jenkins ok to test

@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch 3 times, most recently from 12f1c97 to 1cab41f Compare December 17, 2018 06:08

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For edX reviewers: Library module is not supported right now. This change is just to prevent errors in case the course has one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The indent here is a bit awkward. I think the recommendation is to use parens around the whole statement and pull the any to the second line.

More importantly: This might be another place where it makes sense to push the logic down the stack. Say a new classmethod on StudentModule that essentially does update_or_create() like the call below, but has a check for is_authenticated() -- assuming of course that it's always wrong to update state for unauthenticated users (which I think is correct?).

This is a question/suggestion, and not a requirement for merging.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the indent. As for moving the logic down the stack, I don't really know much about which level to contain the unauthenticated user check makes sense, but wouldn't moving it down increase the function call overhead when the user is not authenticated? Since we'll now be calling the StudentModule classmethod which then calls the is_authenticated, in place of just is_authenticated?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I just assumed that is_authenticated was really cheap. Is it not?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_authenticated is probably cheap since it's used in a lot of places. I was more concerned with the call to the StudentModule classmethod. But on second thought, it's probably not something to worry about either. I've created a new classmethod and moved the logic to there. Please let me know if that's fine.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to check the course_visibility setting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this here twice?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected it.

@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch 3 times, most recently from b256f7f to 2612a14 Compare December 18, 2018 05:57
@symbolist

Copy link
Copy Markdown
Contributor

@mduboseedx Apparently the xsscommitlint run is failing with quite a few errors in one file which was slightly edited in this PR. Will it require fixing all of them?

@mduboseedx

Copy link
Copy Markdown
Contributor

jenkins run quality

@mduboseedx

Copy link
Copy Markdown
Contributor

@symbolist I think those errors will need to be addressed in order to merge this change. @edx/testeng do all xsscommitlint errors need to be fixed?

@jmbowman

Copy link
Copy Markdown
Contributor

Fixing the XSS warnings is strongly encouraged, but not strictly required. We have a backlog of these "might be a serious problem" code spots identified by the linter, and are trying to fix them as other work is being done in the same files (when the context of that part of the code is already fresh in mind). Documentation on how to avoid and fix these problems can be found here, and this is information that we'd like anybody working on HTML templates or code-generated HTML in Open edX to understand. But if there's a good case for not tackling the issues surfaced by xsscommitlint right now, we can merge the PR despite the linter failure.

@symbolist

Copy link
Copy Markdown
Contributor

@jmbowman @mduboseedx Thanks for the details! Yes, we do follow the guidelines for preventing xss issues. However there are 28 xsslint warnings showing up in this file (none of which are being introduced in this PR) and fixing all those will likely require refactoring it quite a bit. I think it would be better if that is handled separately with any other cleanup the edX team would like.

@pkulkark pkulkark changed the title WIP: Implement public cohort for anonymous and unenrolled users Implement public cohort for anonymous and unenrolled users Dec 21, 2018
@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch from 2612a14 to e7d3b32 Compare January 3, 2019 08:59
@natabene

natabene commented Jan 3, 2019

Copy link
Copy Markdown
Contributor

@pkulkark @symbolist Do you think it should be reviewed now?

@pkulkark

pkulkark commented Jan 4, 2019

Copy link
Copy Markdown
Contributor Author

@natabene The quality check failures are not related to the the changes made in this PR, as mentioned in earlier comments. So this can be reviewed.

@openedx-webhooks openedx-webhooks removed the waiting on author PR author needs to resolve review requests, answer questions, fix tests, etc. label Jan 4, 2019
@pomegranited

Copy link
Copy Markdown
Contributor

@nedbat This is a big change, but it's been done in careful consultation with @ormsbee and @marcotuts (cf https://github.com/edx/edx-platform/pull/18134). It also rounds out the Anonymous Courseware feature really nicely, so would be great if we could get it into Ironwood.

Re documentation -- I know this is no substitute for real docs, but we're working on a blog post for the edX website that also explains (with screenshots) how to enable and use Anonymous Courseware, so there will be something for people to reference.

@ormsbee

ormsbee commented Feb 6, 2019

Copy link
Copy Markdown
Contributor

@pkulkark: Is this ready for another review round?

@pkulkark

pkulkark commented Feb 6, 2019

Copy link
Copy Markdown
Contributor Author

@ormsbee Yes it is

@openedx-webhooks openedx-webhooks removed the waiting on author PR author needs to resolve review requests, answer questions, fix tests, etc. label Feb 6, 2019
@ormsbee

ormsbee commented Feb 6, 2019

Copy link
Copy Markdown
Contributor

@pkulkark: Got it. FWIW, I'm trying to use JIRA more diligently now that I'm tracking more community PRs at once. If you see that a PR has a "Waiting on Author" label when it's really ready for another review round, please let me know that it's ready in a PR comment. Otherwise, it might be a while before I notice. :(

Thank you!

@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch from 6a77a35 to a267537 Compare February 7, 2019 07:06
@pkulkark

pkulkark commented Feb 7, 2019

Copy link
Copy Markdown
Contributor Author

jenkins run bokchoy

2 similar comments
@pomegranited

Copy link
Copy Markdown
Contributor

jenkins run bokchoy

@pomegranited

Copy link
Copy Markdown
Contributor

jenkins run bokchoy

This PR is based on openedx#19284 and is part of the
series of work related to the proposal openedx#18134.

This PR avoids the assignment of
anonymous/unenrolled users to any cohort when
course is public. Anonymous or unenrolled users
will only see content that does not have a
content group assigned.
The "View Course" link to the course outline
is shown on the course about page for a course
marked public/public outline.
It also makes course handouts available for
public courses (not for public_outline).
This PR also hides the different warnings and
messages asking the user to sign-in and enroll
in the course, when the course is marked public.
It modifies the default public_view text to
include the component display_name when
unenrolled access is not available.
@pkulkark
pkulkark force-pushed the pooja/implement-public-cohort branch from a267537 to 9ddb1cc Compare February 7, 2019 16:12
@pomegranited

pomegranited commented Feb 8, 2019

Copy link
Copy Markdown
Contributor

@ormsbee This is ready for another round of review, thank you!

@edx/ospr @natabene -- @pkulkark is unable to trigger jenkins runs with PR comments like jenkins run bokchoy -- is this something you can fix?

@edx-status-bot

Copy link
Copy Markdown

Your PR has finished running tests. The following contexts failed:

  • jenkins/quality

@ormsbee

ormsbee commented Feb 8, 2019

Copy link
Copy Markdown
Contributor

Note for anyone watching: I am merging this in spite of quality check failures because it's XSS linting issues that were not introduced by this PR.

@ormsbee
ormsbee merged commit 4aa6446 into openedx:master Feb 8, 2019
@openedx-webhooks

Copy link
Copy Markdown

@pkulkark 🎉 Your pull request was merged!

Please take a moment to answer a two question survey so we can improve your experience in the future.

@edx-pipeline-bot

Copy link
Copy Markdown
Contributor

EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production on Monday, February 11, 2019.

@edx-pipeline-bot

Copy link
Copy Markdown
Contributor

EdX Release Notice: This PR may have caused e2e tests to fail on Stage. E2E tests have failed. https://gocd.tools.edx.org/go/tab/pipeline/history/STAGE_edxapp_M-D

@pomegranited
pomegranited deleted the pooja/implement-public-cohort branch February 10, 2019 22:58
@pomegranited

Copy link
Copy Markdown
Contributor

Thank you @ormsbee and @pkulkark !
@nedbat Given our discussions, do you think this is appropriate to pull into Ironwood?

@ormsbee

ormsbee commented Feb 11, 2019

Copy link
Copy Markdown
Contributor

Even if we do bring it in, I'd definitely want to wait a little bit just to make sure there are no surprise regressions when we go to prod with this over the next few days.

@pomegranited

Copy link
Copy Markdown
Contributor

@ormsbee Understood.

Our client has noted an issue with the "Enroll" links that are shown on public and public_outline Course pages -- if the course enrollments are "invite only", then the user is looped back to the dashboard, but not enrolled in the course (and no explanatory message shown). They'd like the "Enroll" links to be displayed only if self-enrollment is possible.

@edx-pipeline-bot

Copy link
Copy Markdown
Contributor

EdX Release Notice: This PR has been deployed to the production environment.

@nedbat

nedbat commented Feb 25, 2019

Copy link
Copy Markdown
Contributor

@ormsbee Could we get an Ironwood pull request today?

@nedbat

nedbat commented Feb 25, 2019

Copy link
Copy Markdown
Contributor

Added to Ironwood via #19877

@pomegranited

Copy link
Copy Markdown
Contributor

Thank you so much @nedbat and @ormsbee for getting this into Ironwood!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged open-source-contribution PR author is not from Axim or 2U

Projects

None yet

Development

Successfully merging this pull request may close these issues.