From f4974aebd52c08167f74f12769ef8f18e289627b Mon Sep 17 00:00:00 2001 From: Matt Hughes Date: Mon, 18 Oct 2021 11:12:21 -0400 Subject: [PATCH] fix(program-portals): prevent resume course links from 404ing (#27046) * fix(program-portals): prevent resume course links from 404ing From time to time course teams will delete a problem in an active course. When this happens and that particular problem is the last completed subsection for a learner, some naive attempts to provide a "continue course" that takes the learner back to where they left off may result in 404s. This checks whether a learner would be able to access the block returned from completion data before we try to create a link to that part of the course structure to hand to that learner. It's used on the Master's program learner portal pages. JIRA:EDUCATOR-5313 Co-authored-by: Zach Hancock --- common/djangoapps/student/helpers.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/common/djangoapps/student/helpers.py b/common/djangoapps/student/helpers.py index 54777694f4..76251bdea9 100644 --- a/common/djangoapps/student/helpers.py +++ b/common/djangoapps/student/helpers.py @@ -15,9 +15,9 @@ from completion.utilities import get_key_to_last_completed_block from django.conf import settings from django.contrib.auth import load_backend from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user -from django.core.exceptions import PermissionDenied, ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.validators import ValidationError -from django.db import IntegrityError, transaction, ProgrammingError +from django.db import IntegrityError, ProgrammingError, transaction from django.urls import NoReverseMatch, reverse from django.utils.translation import ugettext as _ from pytz import UTC @@ -44,11 +44,13 @@ from lms.djangoapps.certificates.api import ( auto_certificate_generation_enabled, ) from lms.djangoapps.certificates.data import CertificateStatuses +from lms.djangoapps.course_blocks.api import get_course_blocks from lms.djangoapps.grades.api import CourseGradeFactory from lms.djangoapps.instructor import access from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService from lms.djangoapps.verify_student.utils import is_verification_expiring_soon, verification_for_datetime +from openedx.core.djangoapps.content.block_structure.exceptions import UsageKeyNotInBlockStructure from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.theming.helpers import get_themes from openedx.core.djangoapps.user_authn.utils import is_safe_login_or_logout_redirect @@ -766,10 +768,18 @@ def get_resume_urls_for_enrollments(user, enrollments): for enrollment in enrollments: try: block_key = get_key_to_last_completed_block(user, enrollment.course_id) - url_to_block = reverse( - 'jump_to', - kwargs={'course_id': enrollment.course_id, 'location': block_key} - ) + try: + block_data = get_course_blocks(user, block_key) + except UsageKeyNotInBlockStructure: + url_to_block = '' + else: + if block_key in block_data: + url_to_block = reverse( + 'jump_to', + kwargs={'course_id': enrollment.course_id, 'location': block_key} + ) + else: + url_to_block = '' except UnavailableCompletionData: url_to_block = '' resume_course_urls[enrollment.course_id] = url_to_block