Skip to content
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

Make impersonate_user local to a course #670

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

isuruf
Copy link
Contributor

@isuruf isuruf commented Sep 2, 2019

If a user is a super-user, they'll be able to impersonate anyone.
If not, a user (ta) can impersonate a user who they have access
to (student) in that particular course.

Note that when impersonating, a ta will only be able to access the
courses of that student that he/she has permission for. Access to
other courses will be denied. (Any urls starting with /course/)

One possible issue with this approach is that a ta will be able to
see the home page of the student, which means they'll be able to see
the titles of some private courses that the student has access to.

If a user is a super-user, they'll be able to impersonate anyone.
If not, a user (ta) be able to impersonate a user who they have access
to (student) in that particular course.

Note that when impersonating, a ta will only be able to access the
courses of that student that he/she has permission for. Access to
other courses will be denied. (Any urls starting with /course/<id>)

One possible issue with this approach is that a ta will be able to
see the home page of the student, which means they'll be able to see
the titles of some private courses that the student has access to.
course/auth.py Outdated
@@ -234,6 +258,7 @@ def impersonate(request):
impersonee = form.cleaned_data["user"]

request.session['impersonate_id'] = impersonee.id
request.session['impersonate_course'] = course_identifier
Copy link
Owner

Choose a reason for hiding this comment

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

It might be useful to store the primary key and not the identifier. That's cheaper to use (no database roundtrip).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How do you filter by the primary key?

Participation.objects.filter(
        user=impersonator,
        status=participation_status.active,
        course_id=course_id)

?

Copy link
Owner

Choose a reason for hiding this comment

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

Yep.

Copy link
Contributor Author

@isuruf isuruf Sep 4, 2019

Choose a reason for hiding this comment

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

We need to check that the impersonate_course_id is equal to the current course which requires a database call. I'll change the filter to following which saves a database call.

Participation.objects.filter(
        user=impersonator,
        status=participation_status.active,
        course__identifier=course_identifier)

course/auth.py Outdated

my_participations = Participation.objects.filter(
user=impersonator,
status=participation_status.active)
status=participation_status.active,
course=course)
Copy link
Owner

Choose a reason for hiding this comment

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

This should only consider the participation in the course to which the impersonation is scoped.

course/auth.py Outdated
class ImpersonateMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
if 'impersonate_id' in request.session:
imp_id = request.session['impersonate_id']
imp_course = request.session['impersonate_course']
Copy link
Owner

Choose a reason for hiding this comment

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

Could you change this variable to be end in _id (assuming you take the other suggestion on what goes in the session)?

course/auth.py Outdated
course_identifier=cur_course)
else:
qset = get_impersonable_user_qset(cast(User, request.user),
course_identifier=imp_course)
Copy link
Owner

Choose a reason for hiding this comment

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

If the impersonation is course-scoped, no impersonation should happen if cur_course is None.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll have to selectively allow /stop_impersonating (or change stop_impersonating url to also be course based) and signout page, right?

Copy link
Owner

Choose a reason for hiding this comment

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

No, I don't think that's necessary. /stop_impersonating will look directly at the values in the session and will work OK even if the request.user is not the impersonee.

Copy link
Owner

Choose a reason for hiding this comment

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

Same for sign-out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll have to stop the error message though, otherwise clicking that button would give me,

image

Copy link
Owner

Choose a reason for hiding this comment

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

Sure. But if they're already impersonating someone, it's fine to assume that they were (at some point) permitted to do that.

@@ -209,12 +228,17 @@ def __init__(self, *args, **kwargs):
self.helper.add_input(Submit("submit", _("Impersonate")))


def impersonate(request):
def impersonate(request, course_identifier):
Copy link
Owner

Choose a reason for hiding this comment

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

I wonder if we should have a non-course entry point (URL) for the (global) impersonation. (Not for me, but I'm thinking of other folks serving as admins of Relate instances.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would they be superusers? Or users with a relate permission level?

Copy link
Owner

Choose a reason for hiding this comment

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

Would they be superusers?

Yep.

@inducer
Copy link
Owner

inducer commented Sep 3, 2019

Thanks for your work on this!

Repository owner deleted a comment from codecov bot Sep 5, 2019
Repository owner deleted a comment from codecov bot Sep 5, 2019
@inducer
Copy link
Owner

inducer commented Sep 19, 2019

Could you merge in master to get the latest CI? Also, could you remind me what the status is here?

@codecov
Copy link

codecov bot commented Sep 19, 2019

Codecov Report

Merging #670 into master will decrease coverage by 32.76%.
The diff coverage is 12.5%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master     #670       +/-   ##
===========================================
- Coverage   96.59%   63.83%   -32.77%     
===========================================
  Files          45       45               
  Lines       11105    11126       +21     
  Branches     2065     2072        +7     
===========================================
- Hits        10727     7102     -3625     
- Misses        302     3414     +3112     
- Partials       76      610      +534
Impacted Files Coverage Δ
relate/urls.py 90.9% <ø> (-9.1%) ⬇️
course/auth.py 24.8% <12.5%> (-59.69%) ⬇️
course/calendar.py 20.17% <0%> (-79.83%) ⬇️
course/exam.py 23.94% <0%> (-76.06%) ⬇️
course/enrollment.py 25.94% <0%> (-72.88%) ⬇️
accounts/utils.py 37.6% <0%> (-60.69%) ⬇️
course/views.py 41.82% <0%> (-58.18%) ⬇️
relate/checks.py 42.28% <0%> (-57.72%) ⬇️
course/validation.py 50.65% <0%> (-49.17%) ⬇️
... and 21 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1be42ea...97cdba0. Read the comment docs.

@isuruf
Copy link
Contributor Author

isuruf commented Sep 19, 2019

Also, could you remind me what the status is here?

Need to write tests.

Base automatically changed from master to main March 8, 2021 02:15
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.

2 participants