Commit df247f9d by noraiz-anwar Committed by GitHub

Merge pull request #14074 from edx/TNL-6015

Remove access for inactive users
parents da5f840e 5207e2fc
...@@ -147,13 +147,6 @@ def _course_team_user(request, course_key, email): ...@@ -147,13 +147,6 @@ def _course_team_user(request, course_key, email):
if not ((requester_perms & STUDIO_EDIT_ROLES) or (user.id == request.user.id)): if not ((requester_perms & STUDIO_EDIT_ROLES) or (user.id == request.user.id)):
return permissions_error_response return permissions_error_response
# can't modify an inactive user
if not user.is_active:
msg = {
"error": _('User {email} has registered but has not yet activated his/her account.').format(email=email),
}
return JsonResponse(msg, 400)
if request.method == "DELETE": if request.method == "DELETE":
new_role = None new_role = None
else: else:
...@@ -165,6 +158,13 @@ def _course_team_user(request, course_key, email): ...@@ -165,6 +158,13 @@ def _course_team_user(request, course_key, email):
else: else:
return JsonResponse({"error": _("No `role` specified.")}, 400) return JsonResponse({"error": _("No `role` specified.")}, 400)
# can't modify an inactive user but can remove it
if not (user.is_active or new_role is None):
msg = {
"error": _('User {email} has registered but has not yet activated his/her account.').format(email=email),
}
return JsonResponse(msg, 400)
old_roles = set() old_roles = set()
role_added = False role_added = False
for role_type in role_hierarchy: for role_type in role_hierarchy:
...@@ -177,7 +177,7 @@ def _course_team_user(request, course_key, email): ...@@ -177,7 +177,7 @@ def _course_team_user(request, course_key, email):
role_added = True role_added = True
else: else:
return permissions_error_response return permissions_error_response
elif role.has_user(user): elif role.has_user(user, check_user_activation=False):
# Remove the user from this old role: # Remove the user from this old role:
old_roles.add(role) old_roles.add(role)
......
...@@ -130,11 +130,19 @@ class RoleBase(AccessRole): ...@@ -130,11 +130,19 @@ class RoleBase(AccessRole):
self.course_key = course_key self.course_key = course_key
self._role_name = role_name self._role_name = role_name
def has_user(self, user): # pylint: disable=arguments-differ
def has_user(self, user, check_user_activation=True):
""" """
Return whether the supplied django user has access to this role. Check if the supplied django user has access to this role.
Arguments:
user: user to check against access to role
check_user_activation: Indicating whether or not we need to check
user activation while checking user roles
Return:
bool identifying if user has that particular role or not
""" """
if not (user.is_authenticated() and user.is_active): if check_user_activation and not (user.is_authenticated() and user.is_active):
return False return False
# pylint: disable=protected-access # pylint: disable=protected-access
......
...@@ -2001,6 +2001,7 @@ def auto_auth(request): ...@@ -2001,6 +2001,7 @@ def auto_auth(request):
* `redirect`: Set to "true" will redirect to the `redirect_to` value if set, or * `redirect`: Set to "true" will redirect to the `redirect_to` value if set, or
course home page if course_id is defined, otherwise it will redirect to dashboard course home page if course_id is defined, otherwise it will redirect to dashboard
* `redirect_to`: will redirect to to this url * `redirect_to`: will redirect to to this url
* `is_active` : make/update account with status provided as 'is_active'
If username, email, or password are not provided, use If username, email, or password are not provided, use
randomly generated credentials. randomly generated credentials.
""" """
...@@ -2017,10 +2018,13 @@ def auto_auth(request): ...@@ -2017,10 +2018,13 @@ def auto_auth(request):
is_superuser = request.GET.get('superuser', None) is_superuser = request.GET.get('superuser', None)
course_id = request.GET.get('course_id', None) course_id = request.GET.get('course_id', None)
redirect_to = request.GET.get('redirect_to', None) redirect_to = request.GET.get('redirect_to', None)
active_status = request.GET.get('is_active')
# mode has to be one of 'honor'/'professional'/'verified'/'audit'/'no-id-professional'/'credit' # mode has to be one of 'honor'/'professional'/'verified'/'audit'/'no-id-professional'/'credit'
enrollment_mode = request.GET.get('enrollment_mode', 'honor') enrollment_mode = request.GET.get('enrollment_mode', 'honor')
active_status = (not active_status or active_status == 'true')
course_key = None course_key = None
if course_id: if course_id:
course_key = CourseLocator.from_string(course_id) course_key = CourseLocator.from_string(course_id)
...@@ -2048,6 +2052,7 @@ def auto_auth(request): ...@@ -2048,6 +2052,7 @@ def auto_auth(request):
user = User.objects.get(username=username) user = User.objects.get(username=username)
user.email = email user.email = email
user.set_password(password) user.set_password(password)
user.is_active = active_status
user.save() user.save()
profile = UserProfile.objects.get(user=user) profile = UserProfile.objects.get(user=user)
reg = Registration.objects.get(user=user) reg = Registration.objects.get(user=user)
...@@ -2061,9 +2066,9 @@ def auto_auth(request): ...@@ -2061,9 +2066,9 @@ def auto_auth(request):
user.is_superuser = (is_superuser == "true") user.is_superuser = (is_superuser == "true")
user.save() user.save()
# Activate the user if active_status:
reg.activate() reg.activate()
reg.save() reg.save()
# ensure parental consent threshold is met # ensure parental consent threshold is met
year = datetime.date.today().year year = datetime.date.today().year
......
...@@ -12,19 +12,24 @@ class AutoAuthPage(PageObject): ...@@ -12,19 +12,24 @@ class AutoAuthPage(PageObject):
""" """
The automatic authorization page. The automatic authorization page.
When allowed via the django settings file, visiting When allowed via the django settings file, visiting
this url will create a user and log them in. this url will create/update a user and log them in.
""" """
def __init__(self, browser, username=None, email=None, password=None, def __init__(self, browser, username=None, email=None, password=None,
staff=None, course_id=None, roles=None, no_login=None): staff=None, course_id=None, roles=None, no_login=None, is_active=None):
""" """
Auto-auth is an end-point for HTTP GET requests. Auto-auth is an end-point for HTTP GET requests.
By default, it will create accounts with random user credentials, By default, it will create accounts with random user credentials,
but you can also specify credentials using querystring parameters. but you can also specify credentials using querystring parameters.
Can be used to update an account, call to this end-point with already
made account's credentials along with values to update will result into
an account update.
`username`, `email`, and `password` are the user's credentials (strings) `username`, `email`, and `password` are the user's credentials (strings)
`staff` is a boolean indicating whether the user is global staff. `staff` is a boolean indicating whether the user is global staff.
`course_id` is the ID of the course to enroll the student in. `course_id` is the ID of the course to enroll the student in.
`is_active` activation status of user
Currently, this has the form "org/number/run" Currently, this has the form "org/number/run"
Note that "global staff" is NOT the same as course staff. Note that "global staff" is NOT the same as course staff.
...@@ -55,6 +60,9 @@ class AutoAuthPage(PageObject): ...@@ -55,6 +60,9 @@ class AutoAuthPage(PageObject):
if no_login: if no_login:
self._params['no_login'] = True self._params['no_login'] = True
if is_active is not None:
self._params['is_active'] = 'true' if is_active else 'false'
@property @property
def url(self): def url(self):
""" """
......
...@@ -26,6 +26,17 @@ class CourseTeamPageTest(StudioCourseTest): ...@@ -26,6 +26,17 @@ class CourseTeamPageTest(StudioCourseTest):
).visit() ).visit()
return user return user
def _update_user(self, user_info):
"""
Update user with provided `user_info`
Arguments:
`user_info`: dictionary containing values of attributes to be updated
"""
AutoAuthPage(
self.browser, no_login=True, **user_info
).visit()
def setUp(self, is_staff=False): def setUp(self, is_staff=False):
""" """
Install a course with no content using a fixture. Install a course with no content using a fixture.
...@@ -174,6 +185,34 @@ class CourseTeamPageTest(StudioCourseTest): ...@@ -174,6 +185,34 @@ class CourseTeamPageTest(StudioCourseTest):
self.log_in(self.other_user) self.log_in(self.other_user)
self._assert_current_course(visible=False) self._assert_current_course(visible=False)
def test_admins_can_delete_other_inactive_users(self):
"""
Scenario: Admins can delete other inactive users
Given I have opened a new course in Studio
And I am viewing the course team settings.
When I add other user to the course team,
And then delete that other user from the course team.
And other user logs in
Then he/she does not see the course on page
"""
self.page.add_user_to_course(self.other_user.get('email'))
self._assert_user_present(self.other_user, present=True)
# inactivate user
user_info = {
'username': self.other_user.get('username'),
'email': self.other_user.get('email'),
'password': self.other_user.get('password'),
'is_active': False
}
self._update_user(user_info)
# go to course team page to perform delete operation
self._go_to_course_team_page()
self.page.delete_user_from_course(self.other_user.get('email'))
self._assert_user_present(self.other_user, present=False)
def test_admins_cannot_add_users_that_do_not_exist(self): def test_admins_cannot_add_users_that_do_not_exist(self):
""" """
Scenario: Admins cannot add users that do not exist Scenario: Admins cannot add users that do not exist
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment