Ejemplo n.º 1
0
def get_template_request_context(request=None):
    """
    Returns the template processing context to use for the current request,
    or returns None if there is not a current request.
    """

    if request is None:
        request = get_current_request()

    if request is None:
        return None

    request_cache_dict = RequestCache('edxmako').data
    cache_key = "request_context"
    if cache_key in request_cache_dict:
        return request_cache_dict[cache_key]

    context = RequestContext(request)

    context['is_secure'] = request.is_secure()
    context['site'] = safe_get_host(request)

    request_cache_dict[cache_key] = context

    return context
Ejemplo n.º 2
0
def add_email_marketing_cookies(sender, response=None, user=None,
                                **kwargs):  # pylint: disable=unused-argument
    """
    Signal function for adding any cookies needed for email marketing

    Args:
        response: http response object
        user: The user object for the user being changed

    Returns:
        response: http response object with cookie added
    """
    email_config = EmailMarketingConfiguration.current()
    if not email_config.enabled:
        return response

    post_parms = {
        'id': user.email,
        'fields': {'keys': 1},
        'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")}
    }

    # get anonymous_interest cookie to capture usage before logon
    request = crum.get_current_request()
    if request:
        sailthru_content = request.COOKIES.get('anonymous_interest')
        if sailthru_content:
            post_parms['cookies'] = {'anonymous_interest': sailthru_content}

    try:
        sailthru_client = SailthruClient(email_config.sailthru_key, email_config.sailthru_secret)
        log.info(
            'Sending to Sailthru the user interest cookie [%s] for user [%s]',
            post_parms.get('cookies', ''),
            user.email
        )
        sailthru_response = \
            sailthru_client.api_post("user", post_parms)
    except SailthruClientError as exc:
        log.error("Exception attempting to obtain cookie from Sailthru: %s", unicode(exc))
        return response

    if sailthru_response.is_ok():
        if 'keys' in sailthru_response.json and 'cookie' in sailthru_response.json['keys']:
            cookie = sailthru_response.json['keys']['cookie']

            response.set_cookie(
                'sailthru_hid',
                cookie,
                max_age=365 * 24 * 60 * 60,  # set for 1 year
                domain=settings.SESSION_COOKIE_DOMAIN,
                path='/',
            )
        else:
            log.error("No cookie returned attempting to obtain cookie from Sailthru for %s", user.email)
    else:
        error = sailthru_response.get_error()
        # generally invalid email address
        log.info("Error attempting to obtain cookie from Sailthru: %s", error.get_message())
    return response
Ejemplo n.º 3
0
def get_request_or_stub():
    """
    Return the current request or a stub request.

    If called outside the context of a request, construct a fake
    request that can be used to build an absolute URI.

    This is useful in cases where we need to pass in a request object
    but don't have an active request (for example, in tests, celery tasks, and XBlocks).
    """
    request = crum.get_current_request()

    if request is None:

        # The settings SITE_NAME may contain a port number, so we need to
        # parse the full URL.
        full_url = "http://{site_name}".format(site_name=settings.SITE_NAME)
        parsed_url = urlparse(full_url)

        # Construct the fake request.  This can be used to construct absolute
        # URIs to other paths.
        return RequestFactory(
            SERVER_NAME=parsed_url.hostname,
            SERVER_PORT=parsed_url.port or 80,
        ).get("/")

    else:
        return request
Ejemplo n.º 4
0
def add_email_marketing_cookies(sender, response=None, user=None,
                                **kwargs):  # pylint: disable=unused-argument
    """
    Signal function for adding any cookies needed for email marketing

    Args:
        response: http response object
        user: The user object for the user being changed

    Returns:
        response: http response object with cookie added
    """
    email_config = EmailMarketingConfiguration.current()
    if not email_config.enabled:
        return response

    post_parms = {
        'id': user.email,
        'fields': {'keys': 1},
        'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")}
    }

    # get anonymous_interest cookie to capture usage before logon
    request = crum.get_current_request()
    if request:
        sailthru_content = request.COOKIES.get('anonymous_interest')
        if sailthru_content:
            post_parms['cookies'] = {'anonymous_interest': sailthru_content}

    time_before_call = datetime.datetime.now()
    sailthru_response = get_email_cookies_via_sailthru.delay(user.email, post_parms)

    try:
        # synchronous call to get result of an asynchronous celery task, with timeout
        sailthru_response.get(timeout=email_config.user_registration_cookie_timeout_delay,
                              propagate=True)
        cookie = sailthru_response.result
        _log_sailthru_api_call_time(time_before_call)

    except TimeoutError as exc:
        log.error("Timeout error while attempting to obtain cookie from Sailthru: %s", unicode(exc))
        return response
    except SailthruClientError as exc:
        log.error("Exception attempting to obtain cookie from Sailthru: %s", unicode(exc))
        return response

    if not cookie:
        log.error("No cookie returned attempting to obtain cookie from Sailthru for %s", user.email)
        return response
    else:
        response.set_cookie(
            'sailthru_hid',
            cookie,
            max_age=365 * 24 * 60 * 60,  # set for 1 year
            domain=settings.SESSION_COOKIE_DOMAIN,
            path='/',
        )
        log.info("sailthru_hid cookie:%s successfully retrieved for user %s", cookie, user.email)

    return response
Ejemplo n.º 5
0
def get_request_or_stub():
    """
    Return the current request or a stub request.

    If called outside the context of a request, construct a fake
    request that can be used to build an absolute URI.

    This is useful in cases where we need to pass in a request object
    but don't have an active request (for example, in test cases).
    """
    request = crum.get_current_request()

    if request is None:
        log.warning(
            "Could not retrieve the current request. "
            "A stub request will be created instead using settings.SITE_NAME. "
            "This should be used *only* in test cases, never in production!"
        )

        # The settings SITE_NAME may contain a port number, so we need to
        # parse the full URL.
        full_url = "http://{site_name}".format(site_name=settings.SITE_NAME)
        parsed_url = urlparse(full_url)

        # Construct the fake request.  This can be used to construct absolute
        # URIs to other paths.
        return RequestFactory(
            SERVER_NAME=parsed_url.hostname,
            SERVER_PORT=parsed_url.port or 80,
        ).get("/")

    else:
        return request
Ejemplo n.º 6
0
def get_template_request_context(request=None):
    """
    Returns the template processing context to use for the current request,
    or returns None if there is not a current request.
    """

    if request is None:
        request = get_current_request()

    if request is None:
        return None

    request_cache_dict = request_cache.get_cache('edxmako')
    cache_key = "request_context"
    if cache_key in request_cache_dict:
        return request_cache_dict[cache_key]

    context = RequestContext(request)

    context['is_secure'] = request.is_secure()
    context['site'] = safe_get_host(request)

    # This used to happen when a RequestContext object was initialized but was
    # moved to a different part of the logic when template engines were introduced.
    # Since we are not using template engines we do this here.
    # https://github.com/django/django/commit/37505b6397058bcc3460f23d48a7de9641cd6ef0
    for processor in get_template_context_processors():
        context.update(processor(request))

    request_cache_dict[cache_key] = context

    return context
Ejemplo n.º 7
0
def get_request():
    """
    Return the current request.

    Deprecated: Please use crum to retrieve current requests.
    """
    return crum.get_current_request()
Ejemplo n.º 8
0
def handle_enroll_status_change(sender, event=None, user=None, mode=None, course_id=None,
                                **kwargs):  # pylint: disable=unused-argument
    """
    Signal receiver for enroll/unenroll/purchase events
    """
    email_config = EmailMarketingConfiguration.current()
    if not email_config.enabled or not event or not user or not mode or not course_id:
        return

    # skip tracking (un)enrolls if simulated cost=0
    if email_config.sailthru_enroll_cost == 0:
        return

    request = crum.get_current_request()
    if not request:
        return

    # get string course_id serializable to send through celery
    course_id_string = unicode(course_id)

    # figure out course url
    course_url = _build_course_url(request, course_id_string, email_config)

    # pass event to email_marketing.tasks
    update_course_enrollment.delay(user.email, course_url, event, mode,
                                   course_id=course_id_string,
                                   message_id=request.COOKIES.get('sailthru_bid'))
Ejemplo n.º 9
0
    def is_flag_active(self, flag_name, check_before_waffle_callback=None, flag_undefined_default=None):
        """
        Returns and caches whether the provided flag is active.

        If the flag value is already cached in the request, it is returned.
        If check_before_waffle_callback is supplied, it is called before
            checking waffle.
        If check_before_waffle_callback returns None, or if it is not supplied,
            then waffle is used to check the flag.

        Important: Caching for the check_before_waffle_callback must be handled
            by the callback itself.

        Arguments:
            flag_name (String): The name of the flag to check.
            check_before_waffle_callback (function): (Optional) A function that
                will be checked before continuing on to waffle. If
                check_before_waffle_callback(namespaced_flag_name) returns True
                or False, it is returned. If it returns None, then waffle is
                used.
            flag_undefined_default (Boolean): A default value to be returned if
                the waffle flag is to be checked, but doesn't exist.
        """
        # Import is placed here to avoid model import at project startup.
        from waffle.models import Flag

        # validate arguments
        namespaced_flag_name = self._namespaced_name(flag_name)
        value = None
        if check_before_waffle_callback:
            value = check_before_waffle_callback(namespaced_flag_name)

        if value is None:
            # Do not get cached value for the callback, because the key might be different.
            # The callback needs to handle its own caching if it wants it.
            value = self._cached_flags.get(namespaced_flag_name)
            if value is None:

                if flag_undefined_default is not None:
                    # determine if the flag is undefined in waffle
                    try:
                        Flag.objects.get(name=namespaced_flag_name)
                    except Flag.DoesNotExist:
                        value = flag_undefined_default

                if value is None:
                    request = crum.get_current_request()
                    if request:
                        value = flag_is_active(request, namespaced_flag_name)
                    else:
                        log.warn(u"%sFlag '%s' accessed without a request", self.log_prefix, namespaced_flag_name)
                        # Return the default value if not in a request context.
                        # Note: this skips the cache as the value might be different
                        # in a normal request context. This case seems to occur when
                        # a page redirects to a 404. In this case, we'll just return
                        # the default value.
                        return bool(flag_undefined_default)

                self._cached_flags[namespaced_flag_name] = value
        return value
Ejemplo n.º 10
0
def _set_current_user_on_request(sender, **kwargs):
    """
    Signal handler to store current user to request.
    """
    from crum import get_current_request
    request = get_current_request()
    if request:
        request.user = kwargs['user']
Ejemplo n.º 11
0
    def is_permitted(self):
        if self.state == "unpublished":
            return False
        elif self.state == "published":
            site = get_current_site(get_current_request())
            return self.sites.filter(id__exact=site.id).exists()

        return False
Ejemplo n.º 12
0
def get_current_request():
    """
    Return current request instance.

    Returns:
         (HttpRequest): returns current request
    """
    return crum.get_current_request()
Ejemplo n.º 13
0
 def _site_from_org(cls, org):
     configuration = SiteConfiguration.get_configuration_for_org(org, select_related=['site'])
     if configuration is None:
         try:
             return Site.objects.get(id=settings.SITE_ID)
         except Site.DoesNotExist:
             return RequestSite(crum.get_current_request())
     else:
         return configuration.site
Ejemplo n.º 14
0
def _get_current_site():
    """
    Returns the site for the current request if any.
    """
    request = crum.get_current_request()
    if not request:
        return

    return {'id': request.site.id, 'domain': request.site.domain, 'name': request.site.name}
Ejemplo n.º 15
0
def get_current_request_hostname():
    """
    This method will return the hostname that was used in the current Django request
    """
    hostname = None
    request = get_current_request()
    if request:
        hostname = request.META.get("HTTP_HOST")

    return hostname
Ejemplo n.º 16
0
def get_request_user():
    """
    Helper to get the authenticated user from the current HTTP request (if
    applicable).

    If the requester of an unenrollment is not the same person as the student
    being unenrolled, we authenticate to the commerce service as the requester.
    """
    request = get_current_request()
    return getattr(request, 'user', None)
Ejemplo n.º 17
0
def check_course_access(course, user, action, check_if_enrolled=False, check_survey_complete=True):
    """
    Check that the user has the access to perform the specified action
    on the course (CourseDescriptor|CourseOverview).

    check_if_enrolled: If true, additionally verifies that the user is enrolled.
    check_survey_complete: If true, additionally verifies that the user has completed the survey.
    """
    # Allow staff full access to the course even if not enrolled
    if has_access(user, 'staff', course.id):
        return

    request = get_current_request()
    check_content_start_date_for_masquerade_user(course.id, user, request, course.start)

    access_response = has_access(user, action, course, course.id)
    if not access_response:
        # Redirect if StartDateError
        if isinstance(access_response, StartDateError):
            start_date = strftime_localized(course.start, 'SHORT_DATE')
            params = QueryDict(mutable=True)
            params['notlive'] = start_date
            raise CourseAccessRedirect('{dashboard_url}?{params}'.format(
                dashboard_url=reverse('dashboard'),
                params=params.urlencode()
            ), access_response)

        # Redirect if AuditExpiredError
        if isinstance(access_response, AuditExpiredError):
            params = QueryDict(mutable=True)
            params['access_response_error'] = access_response.additional_context_user_message
            raise CourseAccessRedirect('{dashboard_url}?{params}'.format(
                dashboard_url=reverse('dashboard'),
                params=params.urlencode()
            ), access_response)

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, MilestoneAccessError):
            raise CourseAccessRedirect('{dashboard_url}'.format(
                dashboard_url=reverse('dashboard'),
            ), access_response)

        # Deliberately return a non-specific error message to avoid
        # leaking info about access control settings
        raise CoursewareAccessException(access_response)

    if check_if_enrolled:
        # If the user is not enrolled, redirect them to the about page
        if not CourseEnrollment.is_enrolled(user, course.id):
            raise CourseAccessRedirect(reverse('about_course', args=[unicode(course.id)]))

    # Redirect if the user must answer a survey before entering the course.
    if check_survey_complete and action == 'load':
        if is_survey_required_and_unanswered(user, course):
            raise CourseAccessRedirect(reverse('course_survey', args=[unicode(course.id)]))
Ejemplo n.º 18
0
    def access_denied_message(self, block_key, user, user_group, allowed_groups):
        course_key = block_key.course_key
        modes = CourseMode.modes_for_course_dict(course_key)
        verified_mode = modes.get(CourseMode.VERIFIED)
        if (verified_mode is None or not self._is_audit_enrollment(user, course_key) or
                user_group == FULL_ACCESS):
            return None

        request = crum.get_current_request()
        if request and is_request_from_mobile_app(request):
            return _(u"Graded assessments are available to Verified Track learners.")
        else:
            return _(u"Graded assessments are available to Verified Track learners. Upgrade to Unlock.")
Ejemplo n.º 19
0
    def access_denied_fragment(self, block, user, user_group, allowed_groups):
        modes = CourseMode.modes_for_course_dict(block.scope_ids.usage_id.course_key)
        verified_mode = modes.get(CourseMode.VERIFIED)
        if verified_mode is None or not self._is_audit_enrollment(user, block):
            return None
        ecommerce_checkout_link = self._get_checkout_link(user, verified_mode.sku)

        request = crum.get_current_request()
        frag = Fragment(render_to_string('content_type_gating/access_denied_message.html', {
            'mobile_app': is_request_from_mobile_app(request),
            'ecommerce_checkout_link': ecommerce_checkout_link,
            'min_price': str(verified_mode.min_price)
        }))
        return frag
Ejemplo n.º 20
0
 def save(self, *args, **kwargs):
     ### vengono aggiunti l'ip l'utente e la data di modifica/creazione in automatico
     request = get_current_request()
     if request:
         remote_addr = request.META['REMOTE_ADDR']
     
     user = get_current_user()
     if user and not user.pk:
         user = None
     if not self.pk:
         self.created_by = user.get_username() + '[' + remote_addr + ']'
         self.created = datetime.now()
     self.modified_by = user.get_username() + '[' + remote_addr + ']'
     self.modified = datetime.now()        
     super(Base, self).save(*args, **kwargs)        
Ejemplo n.º 21
0
    def get_queryset(self, for_user=None):
        is_staff = getattr(for_user, "is_staff", False)
        queryset = super(PermittedManager, self).get_queryset()

        # Exclude unpublished if user is not staff
        if not is_staff:
            queryset = queryset.exclude(
                state="unpublished"
            )

        # Filter objects for current site. During the first migration the sites
        # table may not exist yet. Since get_current_site needs to access the
        # database that poses a problem and there is also no opportunity to use
        # a migration dependency to avoid the issue.
        try:
            site = get_current_site(get_current_request())
            queryset = queryset.filter(sites__id__exact=site.id)
        except (OperationalError, ProgrammingError, Site.DoesNotExist):
            logger.info("Sites not loaded yet. This message should appear \
                only during the first migration."
            )

        # Layers follow the same pattern as sites. Unlike the sites framework
        # layers are optional, ie. for a specific project layers may not be
        # enabled.
        try:
            layer = get_current_layer(get_current_request())
            if layer:
                queryset = queryset.filter(layers__name=layer)
        except (OperationalError, ProgrammingError, Layer.DoesNotExist):
            logger.info("Layers not loaded yet. This message should appear \
                only during the first migration. Also, remember to run \
                load_layers."
            )

        return queryset
Ejemplo n.º 22
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            data = {"user_id": self.user.id, "course_id": self.course_id, "mode": self.mode}

            with tracker.get_tracker().context(event_name, context):
                server_track(crum.get_current_request(), event_name, data)
        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception(
                    "Unable to emit event %s for user %s and course %s", event_name, self.user.username, self.course_id
                )
Ejemplo n.º 23
0
    def access_denied_fragment(self, block, user, user_group, allowed_groups):
        course_key = self._get_course_key_from_course_block(block)
        modes = CourseMode.modes_for_course_dict(course_key)
        verified_mode = modes.get(CourseMode.VERIFIED)
        if (verified_mode is None or user_group == FULL_ACCESS or
                user_group in allowed_groups):
            return None

        ecommerce_checkout_link = self._get_checkout_link(user, verified_mode.sku)
        request = crum.get_current_request()
        frag = Fragment(render_to_string('content_type_gating/access_denied_message.html', {
            'mobile_app': request and is_request_from_mobile_app(request),
            'ecommerce_checkout_link': ecommerce_checkout_link,
            'min_price': str(verified_mode.min_price)
        }))
        return frag
Ejemplo n.º 24
0
    def __init__(self, apps=None, *args, **kwargs):
        super(AppDirectoriesFinder, self).__init__(apps, *args, **kwargs)

        # Extends apps, add to storages
        layers = list(get_current_layer_stack(get_current_request()))
        layers.reverse()
        processed = []
        for k, v in self.storages.items():
            for layer in layers:
                pth = os.path.join(v.location, layer)
                if os.path.exists(pth) and (pth not in processed):
                    processed.append(pth)
                    # We're not really adding an app, but the superclass
                    # attaches no app specific logic to it so it is safe.
                    self.apps.append(pth)
                    filesystem_storage = FileSystemStorage(location=pth)
                    filesystem_storage.prefix = ""
                    self.storages[pth] = filesystem_storage
Ejemplo n.º 25
0
    def date_html(self, date_format='shortDate'):
        """
        Returns a representation of the date as HTML.

        Note: this returns a span that will be localized on the client.
        """
        locale = to_locale(get_language())
        user_timezone = user_timezone_locale_prefs(crum.get_current_request())['user_timezone']
        return HTML(
            '<span class="date localized-datetime" data-format="{date_format}" data-datetime="{date_time}"'
            ' data-timezone="{user_timezone}" data-language="{user_language}">'
            '</span>'
        ).format(
            date_format=date_format,
            date_time=self.date,
            user_timezone=user_timezone,
            user_language=locale,
        )
Ejemplo n.º 26
0
def _get_variables_from_context(context, tag_name):
    if 'request' in context:
        request = context['request']
    else:
        request = get_current_request()

    if request is None:
        raise template.VariableDoesNotExist(
            'The {0} template tag requires a "request" to be present in the template context. Consider using '
            '"emulate_http_request" if you are rendering the template in a celery task.'.format(tag_name)
        )

    message = context.get('message')
    if message is None:
        raise template.VariableDoesNotExist(
            'The {0} template tag requires a "message" to be present in the template context.'.format(tag_name)
        )

    return request.site, request.user, message
Ejemplo n.º 27
0
def handle_enroll_status_change(sender, event=None, user=None, mode=None, course_id=None, cost=None, currency=None,
                                **kwargs):  # pylint: disable=unused-argument
    """
    Signal receiver for enroll/unenroll/purchase events
    """
    email_config = EmailMarketingConfiguration.current()
    if not email_config.enabled or not event or not user or not mode or not course_id:
        return

    request = crum.get_current_request()
    if not request:
        return

    # figure out course url
    course_url = _build_course_url(request, course_id.to_deprecated_string())

    # pass event to email_marketing.tasks
    update_course_enrollment.delay(user.email, course_url, event, mode,
                                   unit_cost=cost, course_id=course_id, currency=currency,
                                   message_id=request.COOKIES.get('sailthru_bid'))
Ejemplo n.º 28
0
    def __init__(self, apps=None, *args, **kwargs):
        super(FileSystemFinder, self).__init__(apps, *args, **kwargs)

        # Extend locations
        layers = list(get_current_layer_stack(get_current_request()))
        layers.reverse()
        processed = []
        new_locations = []
        for prefix, location in self.locations:
            for layer in layers:
                pth = os.path.join(location, layer)
                if os.path.exists(pth) and (pth not in processed):
                    processed.append(pth)
                    new_locations.append(('', pth))
        for location in reversed(new_locations):
            self.locations.insert(0, location)

        for prefix, location in new_locations:
            filesystem_storage = FileSystemStorage(location=location)
            filesystem_storage.prefix = prefix
            self.storages[location] = filesystem_storage
Ejemplo n.º 29
0
    def get_template_sources(self, template_name, template_dirs=None):
        """Make the loader layer aware"""

        if not template_dirs:
            template_dirs = self.get_dirs()
        layers = list(get_current_layer_stack(get_current_request()))
        layers.reverse()
        for template_dir in template_dirs:
            for layer in layers:
                l_template_name = os.path.join(layer, template_name)
                try:
                    name = safe_join(template_dir, l_template_name)
                except SuspiciousFileOperation:
                    # The joined path was located outside of this template_dir
                    # (it might be inside another one, so this isn"t fatal).
                    continue

                yield Origin(
                    name=name,
                    template_name=template_name,
                    loader=self,
                )
Ejemplo n.º 30
0
def _fire_score_changed_for_block(course_id, student, block, module_state_key):
    """
    Fires a PROBLEM_SCORE_CHANGED event for the given module. The earned points are
    always zero. We must retrieve the possible points from the XModule, as
    noted below.
    """
    if block and block.has_score:
        cache = FieldDataCache.cache_for_descriptor_descendents(
            course_id=course_id,
            user=student,
            descriptor=block,
            depth=0
        )
        # For implementation reasons, we need to pull the max_score from the XModule,
        # even though the data is not user-specific.  Here we bind the data to the
        # current user.
        request = crum.get_current_request()
        module = get_module_for_descriptor(
            user=student,
            request=request,
            descriptor=block,
            field_data_cache=cache,
            course_key=course_id
        )
        max_score = module.max_score()
        if max_score is None:
            return
        else:
            points_earned, points_possible = weighted_score(0, max_score, getattr(module, 'weight', None))
    else:
        points_earned, points_possible = 0, 0
    PROBLEM_SCORE_CHANGED.send(
        sender=None,
        points_possible=points_possible,
        points_earned=points_earned,
        user_id=student.id,
        course_id=unicode(course_id),
        usage_id=unicode(module_state_key)
    )
Ejemplo n.º 31
0
 def get_last_url(self):
     request = get_current_request()
     if 'url_last' in request.session:
         return request.session['url_last']
     return settings.LOGIN_REDIRECT_URL
Ejemplo n.º 32
0
def get_experiment_user_metadata_context(course, user):
    """
    Return a context dictionary with the keys used by the user_metadata.html.
    """
    enrollment_mode = None
    enrollment_time = None
    enrollment = None
    # TODO: clean up as part of REVO-28 (START)
    has_non_audit_enrollments = None
    # TODO: clean up as part of REVO-28 (END)
    # TODO: clean up as part of REVEM-106 (START)
    program_key = None
    # TODO: clean up as part of REVEM-106 (END)
    try:
        # TODO: clean up as part of REVO-28 (START)
        user_enrollments = CourseEnrollment.objects.select_related(
            'course').filter(user_id=user.id)
        audit_enrollments = user_enrollments.filter(mode='audit')
        has_non_audit_enrollments = (len(audit_enrollments) !=
                                     len(user_enrollments))
        # TODO: clean up as part of REVO-28 (END)
        enrollment = CourseEnrollment.objects.select_related('course').get(
            user_id=user.id, course_id=course.id)
        if enrollment.is_active:
            enrollment_mode = enrollment.mode
            enrollment_time = enrollment.created

            # TODO: clean up as part of REVEM-106 (START)
            # get program data for this course
            request = get_current_request()
            if request:
                enrollment_list = [enrollment]
                meter = ProgramProgressMeter(request.site,
                                             user,
                                             enrollments=enrollment_list)
                if meter.engaged_programs and meter.engaged_programs[0]:
                    org_name = None
                    courses_not_started = 0
                    courses_in_progress = 0
                    courses_completed = 0
                    program_data = meter.engaged_programs[0]
                    program_data = ProgramDataExtender(
                        program_data, user, mobile_only=False).extend()
                    program_orgs = program_data.get(
                        'credit_backing_organizations')
                    if program_orgs and program_orgs[0]:
                        org = program_orgs[0]
                        org_name = org.get('name')
                    if meter.progress() and meter.progress()[0]:
                        progress = meter.progress()[0]
                        courses_not_started = progress.get('not_started')
                        courses_in_progress = progress.get('in_progress')
                        courses_completed = progress.get('completed')
                    program_key = {
                        'uuid': program_data.get('uuid'),
                        'title': program_data.get('title'),
                        'marketing_url': program_data.get('marketing_url'),
                        'org_name': org_name,
                        'courses_not_started': courses_not_started,
                        'courses_in_progress': courses_in_progress,
                        'courses_completed': courses_completed,
                    }
            # TODO: clean up as part of REVEM-106 (END)
    except CourseEnrollment.DoesNotExist:
        pass  # Not enrolled, used the default None values

    # upgrade_link and upgrade_date should be None if user has passed their dynamic pacing deadline.
    upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date(
        user, enrollment, course)
    has_staff_access = has_staff_access_to_preview_mode(user, course.id)
    forum_roles = []
    if user.is_authenticated:
        forum_roles = list(
            Role.objects.filter(
                users=user,
                course_id=course.id).values_list('name').distinct())

    # get user partition data
    if user.is_authenticated():
        partition_groups = get_all_partitions_for_course(course)
        user_partitions = get_user_partition_groups(course.id,
                                                    partition_groups, user,
                                                    'name')
    else:
        user_partitions = {}

    return {
        'upgrade_link': upgrade_link,
        'upgrade_price': unicode(get_cosmetic_verified_display_price(course)),
        'enrollment_mode': enrollment_mode,
        'enrollment_time': enrollment_time,
        'pacing_type':
        'self_paced' if course.self_paced else 'instructor_paced',
        'upgrade_deadline': upgrade_date,
        'course_key': course.id,
        'course_start': course.start,
        'course_end': course.end,
        'has_staff_access': has_staff_access,
        'forum_roles': forum_roles,
        'partition_groups': user_partitions,
        # TODO: clean up as part of REVO-28 (START)
        'has_non_audit_enrollments': has_non_audit_enrollments,
        # TODO: clean up as part of REVO-28 (END)
        # TODO: clean up as part of REVEM-106 (START)
        'program_key_fields': program_key,
        # TODO: clean up as part of REVEM-106 (END)
    }
Ejemplo n.º 33
0
def add_email_marketing_cookies(sender, response=None, user=None, **kwargs):  # pylint: disable=unused-argument
    """
    Signal function for adding any cookies needed for email marketing

    Args:
        response: http response object
        user: The user object for the user being changed

    Returns:
        response: http response object with cookie added
    """
    email_config = EmailMarketingConfiguration.current()
    if not email_config.enabled:
        return response

    post_parms = {
        'id': user.email,
        'fields': {
            'keys': 1
        },
        'vars': {
            'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")
        }
    }

    # get sailthru_content cookie to capture usage before logon
    request = crum.get_current_request()
    if request:
        sailthru_content = request.COOKIES.get('sailthru_content')
        if sailthru_content:
            post_parms['cookies'] = {'sailthru_content': sailthru_content}

    try:
        sailthru_client = SailthruClient(email_config.sailthru_key,
                                         email_config.sailthru_secret)
        sailthru_response = \
            sailthru_client.api_post("user", post_parms)
    except SailthruClientError as exc:
        log.error("Exception attempting to obtain cookie from Sailthru: %s",
                  unicode(exc))
        return response

    if sailthru_response.is_ok():
        if 'keys' in sailthru_response.json and 'cookie' in sailthru_response.json[
                'keys']:
            cookie = sailthru_response.json['keys']['cookie']

            response.set_cookie(
                'sailthru_hid',
                cookie,
                max_age=365 * 24 * 60 * 60,  # set for 1 year
                domain=settings.SESSION_COOKIE_DOMAIN,
                path='/',
            )
        else:
            log.error(
                "No cookie returned attempting to obtain cookie from Sailthru for %s",
                user.email)
    else:
        error = sailthru_response.get_error()
        # generally invalid email address
        log.info("Error attempting to obtain cookie from Sailthru: %s",
                 error.get_message())
    return response
Ejemplo n.º 34
0
 def update_session(self, user):
     request = get_current_request()
     if user == request.user:
         update_session_auth_hash(request, user)
Ejemplo n.º 35
0
def _get_current_user_from_request(sender, **kwargs):
    """
    Signal handler to retrieve current user from request.
    """
    from crum import get_current_request
    return (getattr(get_current_request(), 'user', False), -10)
Ejemplo n.º 36
0
    def is_satisfied(self, offer, basket):  # pylint: disable=unused-argument
        """
        Determines if a user is eligible for an enterprise customer offer
        based on their association with the enterprise customer.

        It also filter out the offer if the `enterprise_customer_catalog_uuid`
        value set on the offer condition does not match with the basket catalog
        value when explicitly provided by the enterprise learner.

        Note: Currently there is no mechanism to prioritize or apply multiple
        offers that may apply as opposed to disqualifying offers if the
        catalog doesn't explicitly match.

        Arguments:
            basket (Basket): Contains information about order line items, the current site,
                             and the user attempting to make the purchase.
        Returns:
            bool
        """
        if not basket.owner:
            # An anonymous user is never linked to any EnterpriseCustomer.
            return False

        enterprise_in_condition = str(self.enterprise_customer_uuid)
        enterprise_catalog = str(self.enterprise_customer_catalog_uuid) if self.enterprise_customer_catalog_uuid \
            else None
        enterprise_name_in_condition = str(self.enterprise_customer_name)
        username = basket.owner.username
        course_run_ids = []
        for line in basket.all_lines():
            course = line.product.course
            if not course:
                # Basket contains products not related to a course_run.
                # Only log for non-site offers to avoid noise.
                if offer.offer_type != ConditionalOffer.SITE:
                    logger.warning(
                        '[Code Redemption Failure] Unable to apply enterprise offer because '
                        'the Basket contains a product not related to a course_run. '
                        'User: %s, Offer: %s, Product: %s, Enterprise: %s, Catalog: %s',
                        username, offer.id, line.product.id,
                        enterprise_in_condition, enterprise_catalog)
                return False

            course_run_ids.append(course.id)

        courses_in_basket = ','.join(course_run_ids)
        user_enterprise = get_enterprise_id_for_user(basket.site, basket.owner)
        if user_enterprise and enterprise_in_condition != user_enterprise:
            # Learner is not linked to the EnterpriseCustomer associated with this condition.
            if offer.offer_type == ConditionalOffer.VOUCHER:
                logger.warning(
                    '[Code Redemption Failure] Unable to apply enterprise offer because Learner\'s '
                    'enterprise (%s) does not match this conditions\'s enterprise (%s). '
                    'User: %s, Offer: %s, Enterprise: %s, Catalog: %s, Courses: %s',
                    user_enterprise, enterprise_in_condition, username,
                    offer.id, enterprise_in_condition, enterprise_catalog,
                    courses_in_basket)

                logger.info(
                    '[Code Redemption Issue] Linking learner with the enterprise in Condition. '
                    'User [%s], Enterprise [%s]', username,
                    enterprise_in_condition)
                get_or_create_enterprise_customer_user(
                    basket.site, enterprise_in_condition, username, False)
                msg = _(
                    'This coupon has been made available through {new_enterprise}. '
                    'To redeem this coupon, you must first logout. When you log back in, '
                    'please select {new_enterprise} as your enterprise '
                    'and try again.').format(
                        new_enterprise=enterprise_name_in_condition)
                messages.warning(
                    crum.get_current_request(),
                    msg,
                )

            return False

        # Verify that the current conditional offer is related to the provided
        # enterprise catalog, this will also filter out offers which don't
        # have `enterprise_customer_catalog_uuid` value set on the condition.
        catalog = self._get_enterprise_catalog_uuid_from_basket(basket)
        if catalog:
            if offer.condition.enterprise_customer_catalog_uuid != catalog:
                logger.warning(
                    'Unable to apply enterprise offer %s because '
                    'Enterprise catalog id on the basket (%s) '
                    'does not match the catalog for this condition (%s).',
                    offer.id, catalog,
                    offer.condition.enterprise_customer_catalog_uuid)
                return False

        try:
            catalog_contains_course = catalog_contains_course_runs(
                basket.site,
                course_run_ids,
                enterprise_in_condition,
                enterprise_customer_catalog_uuid=enterprise_catalog)
        except (ReqConnectionError, KeyError, SlumberHttpBaseException,
                Timeout) as exc:
            logger.exception(
                '[Code Redemption Failure] Unable to apply enterprise offer because '
                'we failed to check if course_runs exist in the catalog. '
                'User: %s, Offer: %s, Message: %s, Enterprise: %s, Catalog: %s, Courses: %s',
                username, offer.id, exc, enterprise_in_condition,
                enterprise_catalog, courses_in_basket)
            return False

        if not catalog_contains_course:
            # Basket contains course runs that do not exist in the EnterpriseCustomerCatalogs
            # associated with the EnterpriseCustomer.
            logger.warning(
                '[Code Redemption Failure] Unable to apply enterprise offer because '
                'Enterprise catalog does not contain the course(s) in this basket. '
                'User: %s, Offer: %s, Enterprise: %s, Catalog: %s, Courses: %s',
                username, offer.id, enterprise_in_condition,
                enterprise_catalog, courses_in_basket)
            return False

        if not is_offer_max_discount_available(basket, offer):
            logger.warning(
                '[Enterprise Offer Failure] Unable to apply enterprise offer because bookings limit is consumed.'
                'User: %s, Offer: %s, Enterprise: %s, Catalog: %s, Courses: %s, BookingsLimit: %s, TotalDiscount: %s',
                username,
                offer.id,
                enterprise_in_condition,
                enterprise_catalog,
                courses_in_basket,
                offer.max_discount,
                offer.total_discount,
            )
            return False

        if not is_offer_max_user_discount_available(basket, offer):
            logger.warning(
                '[Enterprise Offer Failure] Unable to apply enterprise offer because user bookings limit is consumed.'
                'User: %s, Offer: %s, Enterprise: %s, Catalog: %s, Courses: %s, UserBookingsLimit: %s',
                username, offer.id, enterprise_in_condition,
                enterprise_catalog, courses_in_basket, offer.max_user_discount)
            return False

        return True
Ejemplo n.º 37
0
    def fetch_enterprise_learner_data(self, user):
        """
        Fetch information related to enterprise from the Enterprise Service.

        Example:
            fetch_enterprise_learner_data(user)

        Argument:
            user: (User) django auth user

        Returns:
            dict:
            {
                "count": 1,
                "num_pages": 1,
                "current_page": 1,
                "next": null,
                "start": 0,
                "previous": null
                "results": [
                    {
                        "enterprise_customer": {
                            "uuid": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                            "name": "TestShib",
                            "active": true,
                            "site": {
                                "domain": "example.com",
                                "name": "example.com"
                            },
                            "enable_data_sharing_consent": true,
                            "enforce_data_sharing_consent": "at_login",
                            "branding_configuration": {
                                "enterprise_customer": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                                "logo": "https://open.edx.org/sites/all/themes/edx_open/logo.png"
                            },
                            "enterprise_customer_entitlements": [
                                {
                                    "enterprise_customer": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                                    "entitlement_id": 69
                                }
                            ],
                            "replace_sensitive_sso_username": False,
                        },
                        "user_id": 5,
                        "user": {
                            "username": "******",
                            "first_name": "",
                            "last_name": "",
                            "email": "*****@*****.**",
                            "is_staff": true,
                            "is_active": true,
                            "date_joined": "2016-09-01T19:18:26.026495Z"
                        },
                        "data_sharing_consent_records": [
                            {
                                "username": "******",
                                "enterprise_customer_uuid": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                                "exists": true,
                                "course_id": "course-v1:edX DemoX Demo_Course",
                                "consent_provided": true,
                                "consent_required": false
                            }
                        ]
                    }
                ],
            }

        Raises:
            ConnectionError: requests exception "ConnectionError", raised if if ecommerce is unable to connect
                to enterprise api server.
            SlumberBaseException: base slumber exception "SlumberBaseException", raised if API response contains
                http error status like 4xx, 5xx etc.
            Timeout: requests exception "Timeout", raised if enterprise API is taking too long for returning
                a response. This exception is raised for both connection timeout and read timeout.

        """
        if not user.is_authenticated:
            return None

        api_resource_name = 'enterprise-learner'

        try:
            endpoint = getattr(self.client, api_resource_name)
            querystring = {'username': user.username}
            response = endpoint().get(**querystring)
        except (HttpClientError, HttpServerError):
            LOGGER.exception(
                u'Failed to get enterprise-learner for user [%s] with client user [%s]. Caller: %s, Request PATH: %s',
                user.username,
                self.user.username,
                "".join(traceback.format_stack()),
                get_current_request().META['PATH_INFO'],
            )
            return None

        return response
Ejemplo n.º 38
0
    def make_review(self, attempt, data, backend=None):
        """
        Save the review and review comments
        """
        attempt_code = attempt['attempt_code']
        if not backend:
            backend = get_backend_provider(attempt['proctored_exam'])

        # this method should convert the payload into a normalized format
        backend_review = backend.on_review_callback(attempt, data)

        # do we already have a review for this attempt?!? We may not allow updates
        review = ProctoredExamSoftwareSecureReview.get_review_by_attempt_code(
            attempt_code)

        if review:
            if not constants.ALLOW_REVIEW_UPDATES:
                err_msg = (
                    'We already have a review submitted regarding '
                    'attempt_code {attempt_code}. We do not allow for updates!'
                    .format(attempt_code=attempt_code))
                raise ProctoredExamReviewAlreadyExists(err_msg)

            # we allow updates
            warn_msg = (
                'We already have a review submitted from our proctoring provider regarding '
                'attempt_code {attempt_code}. We have been configured to allow for '
                'updates and will continue...'.format(
                    attempt_code=attempt_code))
            LOG.warning(warn_msg)
        else:
            # this is first time we've received this attempt_code, so
            # make a new record in the review table
            review = ProctoredExamSoftwareSecureReview()

        # first, validate that the backend review status is valid
        ReviewStatus.validate(backend_review['status'])
        # For now, we'll convert the standard review status to the old
        # software secure review status.
        # In the future, the old data should be standardized.
        review.review_status = SoftwareSecureReviewStatus.from_standard_status.get(
            backend_review['status'])

        review.attempt_code = attempt_code
        review.raw_data = json.dumps(data)
        review.student_id = attempt['user']['id']
        review.exam_id = attempt['proctored_exam']['id']

        try:
            review.reviewed_by = get_user_model().objects.get(
                email=data['reviewed_by'])
        except (ObjectDoesNotExist, KeyError):
            review.reviewed_by = None

        # If the reviewing user is a user in the system (user may be None for automated reviews) and does
        # not have permission to submit a review, log a warning.
        course_id = attempt['proctored_exam']['course_id']
        if review.reviewed_by is not None and not is_user_course_or_global_staff(
                review.reviewed_by, course_id):
            LOG.warning(
                'User %(user)s does not have the required permissions to submit '
                'a review for attempt_code %(attempt_code)s.', {
                    'user': review.reviewed_by,
                    'attempt_code': attempt_code
                })

        review.save()

        # go through and populate all of the specific comments
        for comment in backend_review.get('comments', []):
            comment = ProctoredExamSoftwareSecureComment(
                review=review,
                start_time=comment.get('start', 0),
                stop_time=comment.get('stop', 0),
                duration=comment.get('duration', 0),
                comment=comment['comment'],
                status=comment['status'])
            comment.save()

        if review.should_notify:
            instructor_service = get_runtime_service('instructor')
            request = get_current_request()
            if instructor_service and request:
                course_id = attempt['proctored_exam']['course_id']
                exam_id = attempt['proctored_exam']['id']
                review_url = request.build_absolute_uri(
                    u'{}?attempt={}'.format(
                        reverse('edx_proctoring:instructor_dashboard_exam',
                                args=[course_id, exam_id]),
                        attempt['external_id']))
                instructor_service.send_support_notification(
                    course_id=attempt['proctored_exam']['course_id'],
                    exam_name=attempt['proctored_exam']['exam_name'],
                    student_username=attempt['user']['username'],
                    review_status=review.review_status,
                    review_url=review_url,
                )
Ejemplo n.º 39
0
    def fetch_enterprise_learner_data(self, user):
        """
        Fetch information related to enterprise from the Enterprise Service.

        Example:
            fetch_enterprise_learner_data(user)

        Argument:
            user: (User) django auth user

        Returns:
            dict:
            {
                "count": 1,
                "num_pages": 1,
                "current_page": 1,
                "next": null,
                "start": 0,
                "previous": null
                "results": [
                    {
                        "enterprise_customer": {
                            "uuid": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                            "name": "TestShib",
                            "active": true,
                            "site": {
                                "domain": "example.com",
                                "name": "example.com"
                            },
                            "enable_data_sharing_consent": true,
                            "enforce_data_sharing_consent": "at_login",
                            "branding_configuration": {
                                "enterprise_customer": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                                "logo": "https://open.edx.org/sites/all/themes/edx_open/logo.png"
                            },
                            "enterprise_customer_entitlements": [
                                {
                                    "enterprise_customer": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                                    "entitlement_id": 69
                                }
                            ],
                            "replace_sensitive_sso_username": False,
                        },
                        "user_id": 5,
                        "user": {
                            "username": "******",
                            "first_name": "",
                            "last_name": "",
                            "email": "*****@*****.**",
                            "is_staff": true,
                            "is_active": true,
                            "date_joined": "2016-09-01T19:18:26.026495Z"
                        },
                        "data_sharing_consent_records": [
                            {
                                "username": "******",
                                "enterprise_customer_uuid": "cf246b88-d5f6-4908-a522-fc307e0b0c59",
                                "exists": true,
                                "course_id": "course-v1:edX DemoX Demo_Course",
                                "consent_provided": true,
                                "consent_required": false
                            }
                        ]
                    }
                ],
            }
        """
        if not user.is_authenticated:
            return None

        api_url = urljoin(f"{self.base_api_url}/", "enterprise-learner/")

        try:
            querystring = {'username': user.username}
            response = self.client.get(api_url, params=querystring)
            response.raise_for_status()
        except HTTPError:
            LOGGER.exception(
                'Failed to get enterprise-learner for user [%s] with client user [%s]. Caller: %s, Request PATH: %s',
                user.username,
                self.user.username,
                "".join(traceback.format_stack()),
                get_current_request().META['PATH_INFO'],
            )
            return None

        return response.json()
Ejemplo n.º 40
0
    def get_bucket(self, course_key=None, track=True):
        """
        Return which bucket number the specified user is in.

        Bucket 0 is assumed to be the control bucket and will be returned if the experiment is not enabled for
        this user and course.
        """
        # Keep some imports in here, because this class is commonly used at a module level, and we want to avoid
        # circular imports for any models.
        from experiments.models import ExperimentKeyValue

        request = get_current_request()
        if not request:
            return 0

        if not hasattr(request, 'user') or not request.user.id:
            # We need username for stable bucketing and id for tracking, so just skip anonymous (not-logged-in) users
            return 0

        # Use course key in experiment name to separate caches and segment calls per-course-run
        experiment_name = self.namespaced_flag_name + ('.{}'.format(course_key)
                                                       if course_key else '')

        # Check if we have a cache for this request already
        request_cache = RequestCache('experiments')
        cache_response = request_cache.get_cached_response(experiment_name)
        if cache_response.is_found:
            return cache_response.value

        # Check if the main flag is even enabled for this user and course.
        if not self.is_experiment_on(
                course_key):  # grabs user from the current request, if any
            return self._cache_bucket(experiment_name, 0)

        # Check if the enrollment should even be considered (if it started before the experiment wants, we ignore)
        if course_key and self.experiment_id is not None:
            values = ExperimentKeyValue.objects.filter(
                experiment_id=self.experiment_id).values('key', 'value')
            values = {pair['key']: pair['value'] for pair in values}

            if not self._is_enrollment_inside_date_bounds(
                    values, request.user, course_key):
                return self._cache_bucket(experiment_name, 0)

        bucket = stable_bucketing_hash_group(experiment_name, self.num_buckets,
                                             request.user.username)

        # Now check if the user is forced into a particular bucket, using our subordinate bucket flags
        for i, bucket_flag in enumerate(self.bucket_flags):
            if bucket_flag.is_enabled(course_key):
                bucket = i
                break

        session_key = 'tracked.{}'.format(experiment_name)
        if track and hasattr(request,
                             'session') and session_key not in request.session:
            segment.track(user_id=request.user.id,
                          event_name='edx.bi.experiment.user.bucketed',
                          properties={
                              'site': request.site.domain,
                              'app_label': self.waffle_namespace.name,
                              'experiment': self.flag_name,
                              'course_id':
                              str(course_key) if course_key else None,
                              'bucket': bucket,
                              'is_staff': request.user.is_staff,
                              'nonInteraction': 1,
                          })

            # Mark that we've recorded this bucketing, so that we don't do it again this session
            request.session[session_key] = True

        return self._cache_bucket(experiment_name, bucket)
Ejemplo n.º 41
0
    def all_current_course_configs(cls):
        """
        Return configuration for all courses
        """
        all_courses = CourseOverview.objects.all()
        all_site_configs = SiteConfiguration.objects.filter(
            site_values__contains='course_org_filter',
            enabled=True).select_related('site')

        try:
            default_site = Site.objects.get(id=settings.SITE_ID)
        except Site.DoesNotExist:
            default_site = RequestSite(crum.get_current_request())

        sites_by_org = defaultdict(lambda: default_site)
        site_cfg_org_filters = ((site_cfg.site,
                                 site_cfg.site_values['course_org_filter'])
                                for site_cfg in all_site_configs)
        sites_by_org.update({
            org: site
            for (site, orgs) in site_cfg_org_filters
            for org in (orgs if isinstance(orgs, list) else [orgs])
        })

        all_overrides = cls.objects.current_set()
        overrides = {(override.site_id, override.org, override.org_course,
                      override.course_id): override
                     for override in all_overrides}

        stackable_fields = [
            cls._meta.get_field(field_name)
            for field_name in cls.STACKABLE_FIELDS
        ]
        field_defaults = {
            field.name: field.get_default()
            for field in stackable_fields
        }

        def provenance(course, field):
            """
            Return provenance for given field
            """
            org_course = cls._org_course_from_course_key(course.id)
            org = cls._org_from_org_course(org_course)

            for (config_key, provenance) in [
                ((None, None, None, course.id), Provenance.run),
                ((None, None, org_course, None), Provenance.org_course),
                ((None, org, None, None), Provenance.org),
                ((sites_by_org[course.id.org].id, None, None, None),
                 Provenance.site),
                ((None, None, None, None), Provenance.global_),
            ]:
                config = overrides.get(config_key)
                if config is None:
                    continue
                value = field.value_from_object(config)
                if value != field_defaults[field.name]:
                    return (value, provenance)

            return (field_defaults[field.name], Provenance.default)

        return {
            course.id: {
                field.name: provenance(course, field)
                for field in stackable_fields
            }
            for course in all_courses
        }
Ejemplo n.º 42
0
    def save(self, *args, **kwargs):
        request = get_current_request()
        self.state_track = request.META[
            'REMOTE_ADDR'] + ',' + request.user_agent.browser.family + ',' + request.user_agent.os.family + ',' + request.user_agent.device.family

        super(State, self).save(*args, **kwargs)
Ejemplo n.º 43
0
def current_decoded_jwt():
    return get_decoded_jwt(crum.get_current_request())
Ejemplo n.º 44
0
def check_course_access(course,
                        user,
                        action,
                        check_if_enrolled=False,
                        check_survey_complete=True):
    """
    Check that the user has the access to perform the specified action
    on the course (CourseDescriptor|CourseOverview).

    check_if_enrolled: If true, additionally verifies that the user is enrolled.
    check_survey_complete: If true, additionally verifies that the user has completed the survey.
    """
    # Allow staff full access to the course even if not enrolled
    if has_access(user, 'staff', course.id):
        return

    request = get_current_request()
    check_content_start_date_for_masquerade_user(course.id, user, request,
                                                 course.start)

    access_response = has_access(user, action, course, course.id)
    if not access_response:
        # Redirect if StartDateError
        if isinstance(access_response, StartDateError):
            start_date = strftime_localized(course.start, 'SHORT_DATE')
            params = QueryDict(mutable=True)
            params['notlive'] = start_date
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode()), access_response)

        # Redirect if AuditExpiredError
        if isinstance(access_response, AuditExpiredError):
            params = QueryDict(mutable=True)
            params[
                'access_response_error'] = access_response.additional_context_user_message
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode()), access_response)

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, MilestoneAccessError):
            raise CourseAccessRedirect(
                '{dashboard_url}'.format(dashboard_url=reverse('dashboard'), ),
                access_response)

        # Deliberately return a non-specific error message to avoid
        # leaking info about access control settings
        raise CoursewareAccessException(access_response)

    if check_if_enrolled:
        # If the user is not enrolled, redirect them to the about page
        if not CourseEnrollment.is_enrolled(user, course.id):
            raise CourseAccessRedirect(
                reverse('about_course', args=[six.text_type(course.id)]))

    # Redirect if the user must answer a survey before entering the course.
    if check_survey_complete and action == 'load':
        if is_survey_required_and_unanswered(user, course):
            raise CourseAccessRedirect(
                reverse('course_survey', args=[six.text_type(course.id)]))
Ejemplo n.º 45
0
def add_email_marketing_cookies(sender, response=None, user=None,
                                **kwargs):  # pylint: disable=unused-argument
    """
    Signal function for adding any cookies needed for email marketing

    Args:
        response: http response object
        user: The user object for the user being changed

    Returns:
        response: http response object with cookie added
    """
    email_config = EmailMarketingConfiguration.current()
    if not email_config.enabled:
        return response

    post_parms = {
        'id': user.email,
        'fields': {'keys': 1},
        'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")}
    }

    # get anonymous_interest cookie to capture usage before logon
    request = crum.get_current_request()
    if request:
        sailthru_content = request.COOKIES.get('anonymous_interest')
        if sailthru_content:
            post_parms['cookies'] = {'anonymous_interest': sailthru_content}

    time_before_call = datetime.datetime.now()
    sailthru_response = get_email_cookies_via_sailthru.delay(user.email, post_parms)

    try:
        # synchronous call to get result of an asynchronous celery task, with timeout
        sailthru_response.get(timeout=email_config.user_registration_cookie_timeout_delay,
                              propagate=True)
        cookie = sailthru_response.result
        _log_sailthru_api_call_time(time_before_call)

    except TimeoutError as exc:
        log.error("Timeout error while attempting to obtain cookie from Sailthru: %s", text_type(exc))
        return response
    except SailthruClientError as exc:
        log.error("Exception attempting to obtain cookie from Sailthru: %s", text_type(exc))
        return response
    except Exception:
        log.error("Exception Connecting to celery task for %s", user.email)
        return response

    if not cookie:
        log.error("No cookie returned attempting to obtain cookie from Sailthru for %s", user.email)
        return response
    else:
        response.set_cookie(
            'sailthru_hid',
            cookie,
            max_age=365 * 24 * 60 * 60,  # set for 1 year
            domain=settings.SESSION_COOKIE_DOMAIN,
            path='/',
            secure=request.is_secure()
        )
        log.info("sailthru_hid cookie:%s successfully retrieved for user %s", cookie, user.email)

    return response
Ejemplo n.º 46
0
Archivo: views.py Proyecto: saadow123/1
 def wrapper(request, *args, **kwargs):
     if not crum.get_current_request():
         crum.set_current_request(request=request)
     return func(request, *args, **kwargs)
Ejemplo n.º 47
0
    def student_view(self, context=None):
        """
        The primary view of the StaffGradedXBlock, shown to students
        when viewing courses.
        """
        frag = Fragment()
        frag.add_css(self.resource_string("static/css/staff_graded.css"))
        loader = ResourceLoader(__name__)
        _ = self.runtime.service(self, "i18n").ugettext

        # Add i18n js
        statici18n_js_url = self._get_statici18n_js_url()
        if statici18n_js_url:
            frag.add_javascript_url(
                self.runtime.local_resource_url(self, statici18n_js_url))

        frag.add_javascript(
            self.resource_string("static/js/src/staff_graded.js"))
        frag.initialize_js('StaffGradedXBlock')

        context['id'] = self.location.html_id()
        context['instructions'] = markdown.markdown(self.instructions)
        context['display_name'] = self.display_name
        context['is_staff'] = self.runtime.user_is_staff

        course_id = self.location.course_key
        context['available_cohorts'] = [
            cohort.name for cohort in get_course_cohorts(course_id=course_id)
        ]
        context['available_tracks'] = [
            (mode.slug, mode.name)
            for mode in modes_for_course(course_id, only_selectable=False)
        ]

        if context['is_staff']:
            from crum import get_current_request
            from django.middleware.csrf import get_token
            context['import_url'] = self.runtime.handler_url(
                self, "csv_import_handler")
            context['export_url'] = self.runtime.handler_url(
                self, "csv_export_handler")
            context['poll_url'] = self.runtime.handler_url(
                self, "get_results_handler")
            context['csrf_token'] = get_token(get_current_request())
            frag.add_javascript(
                loader.load_unicode('static/js/src/staff_graded.js'))
            frag.initialize_js('StaffGradedProblem',
                               json_args={
                                   k: context[k]
                                   for k in ('csrf_token', 'import_url',
                                             'export_url', 'poll_url', 'id')
                               })

        try:
            score = get_score(self.location, self.runtime.user_id) or {}
            context['grades_available'] = True
        except NoSuchServiceError:
            context['grades_available'] = False
        else:
            if score:
                grade = score['score']
                context['score_string'] = _('{score} / {total} points').format(
                    score=grade, total=self.weight)
            else:
                context['score_string'] = _('{total} points possible').format(
                    total=self.weight)
        frag.add_content(
            loader.render_django_template('static/html/staff_graded.html',
                                          context))
        return frag
Ejemplo n.º 48
0
    def _add_honor_code_field(self, form_desc, required=True):
        """Add an honor code field to a form description.
        Arguments:
            form_desc: A form description
        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True
        """

        separate_honor_and_tos = self._is_field_visible("terms_of_service")
        # Separate terms of service and honor code checkboxes
        if separate_honor_and_tos:
            terms_label = _(u"Honor Code")
            terms_link = marketing_link("HONOR")

        # Combine terms of service and honor code checkboxes
        else:
            # Translators: This is a legal document users must agree to
            # in order to register a new account.
            terms_label = _(u"Terms of Service and Honor Code")
            terms_link = marketing_link("HONOR")

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        label = Text(
            _(u"I agree to the {platform_name} {terms_of_service_link_start}{terms_of_service}{terms_of_service_link_end}"
              )).format(
                  platform_name=configuration_helpers.get_value(
                      "PLATFORM_NAME", settings.PLATFORM_NAME),
                  terms_of_service=terms_label,
                  terms_of_service_link_start=HTML(
                      "<a href='{terms_link}' target='_blank'>").format(
                          terms_link=terms_link),
                  terms_of_service_link_end=HTML("</a>"),
              )

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        error_msg = _(
            u"You must agree to the {platform_name} {terms_of_service}"
        ).format(platform_name=configuration_helpers.get_value(
            "PLATFORM_NAME", settings.PLATFORM_NAME),
                 terms_of_service=terms_label)
        field_type = 'checkbox'

        if not separate_honor_and_tos:
            current_request = crum.get_current_request()

            field_type = 'plaintext'

            pp_link = marketing_link("PRIVACY")
            label = Text(
                _(u"By creating an account with {platform_name}, you agree \
                  to abide by our {platform_name} \
                  {terms_of_service_link_start}{terms_of_service}{terms_of_service_link_end} \
                  and agree to our {privacy_policy_link_start}Privacy Policy{privacy_policy_link_end}."
                  )).format(
                      platform_name=configuration_helpers.get_value(
                          "PLATFORM_NAME", settings.PLATFORM_NAME),
                      terms_of_service=terms_label,
                      terms_of_service_link_start=HTML(
                          "<a href='{terms_url}' target='_blank'>").format(
                              terms_url=terms_link),
                      terms_of_service_link_end=HTML("</a>"),
                      privacy_policy_link_start=HTML(
                          "<a href='{pp_url}' target='_blank'>").format(
                              pp_url=pp_link),
                      privacy_policy_link_end=HTML("</a>"),
                  )

        form_desc.add_field(
            "honor_code",
            label=label,
            field_type=field_type,
            default=False,
            required=required,
            error_messages={"required": error_msg},
        )
Ejemplo n.º 49
0
Archivo: flags.py Proyecto: saadow123/1
    def get_bucket(self, course_key=None, track=True):
        """
        Return which bucket number the specified user is in.

        Bucket 0 is assumed to be the control bucket and will be returned if the experiment is not enabled for
        this user and course.
        """
        # Keep some imports in here, because this class is commonly used at a module level, and we want to avoid
        # circular imports for any models.
        from experiments.models import ExperimentKeyValue
        from student.models import CourseEnrollment

        request = get_current_request()
        if not request:
            return 0

        # Use course key in experiment name to separate caches and segment calls per-course-run
        experiment_name = self.namespaced_flag_name + ('.{}'.format(course_key)
                                                       if course_key else '')

        # Check if we have a cache for this request already
        request_cache = RequestCache('experiments')
        cache_response = request_cache.get_cached_response(experiment_name)
        if cache_response.is_found:
            return cache_response.value

        # Check if the main flag is even enabled for this user and course.
        if not self._is_enabled(
                course_key):  # grabs user from the current request, if any
            return self._cache_bucket(experiment_name, 0)

        # Check if the enrollment should even be considered (if it started before the experiment wants, we ignore)
        if course_key and self.experiment_id is not None:
            start_val = ExperimentKeyValue.objects.filter(
                experiment_id=self.experiment_id, key='enrollment_start')
            if start_val:
                try:
                    start_date = dateutil.parser.parse(
                        start_val.first().value).replace(tzinfo=pytz.UTC)
                except ValueError:
                    log.exception(
                        'Could not parse enrollment start date for experiment %d',
                        self.experiment_id)
                    return self._cache_bucket(experiment_name, 0)
                enrollment = CourseEnrollment.get_enrollment(
                    request.user, course_key)
                # Only bail if they have an enrollment and it's old -- if they don't have an enrollment, we want to do
                # normal bucketing -- consider the case where the experiment has bits that show before you enroll. We
                # want to keep your bucketing stable before and after you do enroll.
                if enrollment and enrollment.created < start_date:
                    return self._cache_bucket(experiment_name, 0)

        bucket = stable_bucketing_hash_group(experiment_name, self.num_buckets,
                                             request.user.username)

        # Now check if the user is forced into a particular bucket, using our subordinate bucket flags
        for i, bucket_flag in enumerate(self.bucket_flags):
            if bucket_flag.is_enabled(course_key):
                bucket = i
                break

        session_key = 'tracked.{}'.format(experiment_name)
        if track and hasattr(request,
                             'session') and session_key not in request.session:
            segment.track(user_id=request.user.id,
                          event_name='edx.bi.experiment.user.bucketed',
                          properties={
                              'site': request.site.domain,
                              'app_label': self.waffle_namespace.name,
                              'experiment': self.flag_name,
                              'course_id':
                              str(course_key) if course_key else None,
                              'bucket': bucket,
                              'is_staff': request.user.is_staff,
                              'nonInteraction': 1,
                          })

            # Mark that we've recorded this bucketing, so that we don't do it again this session
            request.session[session_key] = True

        return self._cache_bucket(experiment_name, bucket)
Ejemplo n.º 50
0
 def url(cls, course_key):
     """
     Returns the URL for this tool for the specified course key.
     """
     request = get_current_request()
     return verified_upgrade_deadline_link(request.user, course_id=course_key)
Ejemplo n.º 51
0
    def __call__(self, request: WSGIRequest):
        from avishan.utils import discard_monitor, find_token, decode_token, add_token_to_response, find_and_check_user
        from avishan.exceptions import AvishanException
        from avishan.exceptions import save_traceback
        from avishan.configure import get_avishan_config

        request.avishan = AvishanRequestStorage(request)
        request.avishan.project = self.project
        """Checks for avoid-touch requests"""
        if discard_monitor(request.get_full_path()):
            print(f"NOT_MONITORED: {request.get_full_path()}")
            response = self.get_response(request)
            if 'token' in request.COOKIES.keys():
                response.set_cookie('token', request.COOKIES['token'])
            del request.avishan
            return response
        """Find token and parse it"""
        """
        Bara inke yadam nare. tooye sathe middleware vaghti error midim, chon nemidoonim api e ya template, error ro 
        zakhire mikonim mirim decorator, baad oonja k set shod in meghdar, check mikonim chon error hast, barmigarde 
        inja 
        """
        try:
            if find_token():
                decode_token()
                find_and_check_user()
        except AvishanException:
            pass
        except Exception as e:
            save_traceback()
            AvishanException(e)

        get_avishan_config().on_request(request)

        # todo 0.2.2 check for 'avishan_' in request bodies
        """Send request object to the next layer and wait for response"""
        try:
            response = self.get_response(request)
            if not request.avishan.can_touch_response:
                del request.avishan
                return response
        except AvishanException:
            pass
        except Exception as e:
            save_traceback()
            AvishanException(e)

        remove_from_crum = False
        if get_current_request() is None:
            remove_from_crum = True
            set_current_request(request)
        """messages"""
        if request.avishan.have_message():
            # todo 0.2.3: check for debug=True

            if request.avishan.is_api:
                request.avishan.response['messages'] = request.avishan.messages
            else:
                # noinspection PyTypeChecker
                self.fill_messages_framework(request)
                if request.avishan.on_error_view_class and response.status_code == 500:
                    response = request.avishan.on_error_view_class.render()
                # todo fix problem on template: not showing thrown exception message

        add_token_to_response(response)
        status_code = request.avishan.status_code
        is_api = request.avishan.is_api
        json_safe = not request.avishan.json_unsafe
        if is_api:
            response = request.avishan.response.copy()

        if request.avishan.is_tracked or request.avishan.exception is not None:
            self.save_request_track(request)

        del request.avishan
        if remove_from_crum:
            set_current_request(None)

        if is_api:
            return JsonResponse(response, status=status_code, safe=json_safe)
        """Do not change redirection status codes"""
        if response.status_code // 100 != 3:
            response.status_code = status_code
        return response
Ejemplo n.º 52
0
    def get_bucket(self, course_key=None, track=True):
        """
        Return which bucket number the specified user is in.

        The user may be force-bucketed if matching subordinate flags of the form
        "main_flag.BUCKET_NUM" exist. Otherwise, they will be hashed into a default
        bucket based on their username, the experiment name, and the course-run key.

        If `self.use_course_aware_bucketing` is False, the course-run key will
        be omitted from the hashing formula, thus making it so a given user
        has the same default bucket across all course runs; however, subordinate
        flags that match the course-run key will still apply.

        If `course_key` argument is omitted altogether, then subordinate flags
        will be evaluated outside of the course-run context, and the default bucket
        will be calculated as if `self.use_course_aware_bucketing` is False.

        Finally, Bucket 0 is assumed to be the control bucket and will be returned if the
        experiment is not enabled for this user and course.

        Arguments:
            course_key (Optional[CourseKey])
                This argument should always be passed in a course-aware context even if
                course aware bucketing is False.
            track (bool):
                Whether an analytics event should be generated if the user is
                bucketed for the first time.

        Returns: int
        """
        # Keep some imports in here, because this class is commonly used at a module level, and we want to avoid
        # circular imports for any models.
        from lms.djangoapps.experiments.models import ExperimentKeyValue
        from lms.djangoapps.courseware.masquerade import get_specific_masquerading_user

        request = get_current_request()
        if not request:
            return 0

        if hasattr(request, 'user'):
            user = get_specific_masquerading_user(request.user, course_key)

            if user is None:
                user = request.user
                masquerading_as_specific_student = False
            else:
                masquerading_as_specific_student = True

        # If a course key is passed in, include it in the experiment name
        # in order to separate caches and analytics calls per course-run.
        # If we are using course-aware bucketing, then also append that course key
        # to `bucketing_group_name`, such that users can be hashed into different
        # buckets for different course-runs.
        experiment_name = bucketing_group_name = self.name
        if course_key:
            experiment_name += f".{course_key}"
        if course_key and self.use_course_aware_bucketing:
            bucketing_group_name += f".{course_key}"

        # Check if we have a cache for this request already
        request_cache = RequestCache('experiments')
        cache_response = request_cache.get_cached_response(experiment_name)
        if cache_response.is_found:
            return cache_response.value

        # Check if the main flag is even enabled for this user and course.
        if not self.is_experiment_on(course_key):  # grabs user from the current request, if any
            return self._cache_bucket(experiment_name, 0)

        # Check if the enrollment should even be considered (if it started before the experiment wants, we ignore)
        if course_key and self.experiment_id is not None:
            values = ExperimentKeyValue.objects.filter(experiment_id=self.experiment_id).values('key', 'value')
            values = {pair['key']: pair['value'] for pair in values}

            if not self._is_enrollment_inside_date_bounds(values, user, course_key):
                return self._cache_bucket(experiment_name, 0)

        # Determine the user's bucket.
        # First check if forced into a particular bucket, using our subordinate bucket flags.
        # If not, calculate their default bucket using a consistent hash function.
        for i, bucket_flag in enumerate(self.bucket_flags):
            if bucket_flag.is_enabled(course_key):
                bucket = i
                break
        else:
            bucket = stable_bucketing_hash_group(
                bucketing_group_name, self.num_buckets, user
            )

        session_key = f'tracked.{experiment_name}'
        anonymous = not hasattr(request, 'user') or not request.user.id
        if (
                track and hasattr(request, 'session') and
                session_key not in request.session and
                not masquerading_as_specific_student and not anonymous
        ):
            segment.track(
                user_id=user.id,
                event_name='edx.bi.experiment.user.bucketed',
                properties={
                    'site': request.site.domain,
                    'app_label': self._app_label,
                    'experiment': self._experiment_name,
                    'course_id': str(course_key) if course_key else None,
                    'bucket': bucket,
                    'is_staff': user.is_staff,
                    'nonInteraction': 1,
                }
            )

            # Mark that we've recorded this bucketing, so that we don't do it again this session
            request.session[session_key] = True

            # Temporary event for AA-759 experiment
            if course_key and self._experiment_name == 'discount_experiment_AA759':
                modes_dict = CourseMode.modes_for_course_dict(course_id=course_key, include_expired=False)
                verified_mode = modes_dict.get('verified', None)
                if verified_mode:
                    segment.track(
                        user_id=user.id,
                        event_name='edx.bi.experiment.AA759.bucketed',
                        properties={
                            'course_id': str(course_key),
                            'bucket': bucket,
                            'sku': verified_mode.sku,
                        }
                    )

        return self._cache_bucket(experiment_name, bucket)
Ejemplo n.º 53
0
    def is_flag_active(self,
                       flag_name,
                       check_before_waffle_callback=None,
                       flag_undefined_default=None):
        """
        Returns and caches whether the provided flag is active.

        If the flag value is already cached in the request, it is returned.
        If check_before_waffle_callback is supplied, it is called before
            checking waffle.
        If check_before_waffle_callback returns None, or if it is not supplied,
            then waffle is used to check the flag.

        Important: Caching for the check_before_waffle_callback must be handled
            by the callback itself.

        Arguments:
            flag_name (String): The name of the flag to check.
            check_before_waffle_callback (function): (Optional) A function that
                will be checked before continuing on to waffle. If
                check_before_waffle_callback(namespaced_flag_name) returns True
                or False, it is returned. If it returns None, then waffle is
                used.
            DEPRECATED flag_undefined_default (Boolean): A default value to be
                returned if the waffle flag is to be checked, but doesn't exist.
                See module docstring for alternative.
        """
        # Import is placed here to avoid model import at project startup.
        from waffle.models import Flag

        if flag_undefined_default:
            warnings.warn(
                # NOTE: This will be removed once ARCHBOM-132, currently in-progress, is complete.
                'flag_undefined_default has been deprecated. For existing uses this is already actively being fixed.',
                DeprecationWarning)

        # validate arguments
        namespaced_flag_name = self._namespaced_name(flag_name)
        value = None
        if check_before_waffle_callback:
            value = check_before_waffle_callback(namespaced_flag_name)

        if value is None:
            # Do not get cached value for the callback, because the key might be different.
            # The callback needs to handle its own caching if it wants it.
            value = self._cached_flags.get(namespaced_flag_name)
            if value is None:

                if flag_undefined_default is not None:
                    # determine if the flag is undefined in waffle
                    try:
                        Flag.objects.get(name=namespaced_flag_name)
                    except Flag.DoesNotExist:
                        if flag_undefined_default:
                            # This metric will go away once this has been fully retired with ARCHBOM-132.
                            # Also, even though the value will only track the last flag, that should be enough.
                            set_custom_metric('temp_flag_default_used',
                                              namespaced_flag_name)
                        value = flag_undefined_default

                if value is None:
                    request = crum.get_current_request()
                    if request:
                        value = flag_is_active(request, namespaced_flag_name)
                    else:
                        log.warning(u"%sFlag '%s' accessed without a request",
                                    self.log_prefix, namespaced_flag_name)
                        set_custom_metric('warn_flag_no_request', True)
                        # Return the default value if not in a request context.
                        # Note: this skips the cache as the value might be different
                        # in a normal request context. This case seems to occur when
                        # a page redirects to a 404. In this case, we'll just return
                        # the default value.
                        value = bool(flag_undefined_default)
                        self._set_waffle_flag_metric(namespaced_flag_name,
                                                     value)
                        return value

                self._cached_flags[namespaced_flag_name] = value

        self._set_waffle_flag_metric(namespaced_flag_name, value)
        return value
Ejemplo n.º 54
0
 def get_current_request(cls):
     """
     This method is deprecated. Please use :func:`request_cache.get_request`.
     """
     return crum.get_current_request()
Ejemplo n.º 55
0
def generate_course_expired_message(user, course):
    """
    Generate the message for the user course expiration date if it exists.
    """
    expiration_data = get_access_expiration_data(user, course)
    if not expiration_data:
        return

    expiration_date = expiration_data['expiration_date']
    masquerading_expired_course = expiration_data[
        'masquerading_expired_course']
    upgrade_deadline = expiration_data['upgrade_deadline']
    upgrade_url = expiration_data['upgrade_url']

    user_timezone_locale = user_timezone_locale_prefs(
        crum.get_current_request())
    user_timezone = user_timezone_locale['user_timezone']

    if masquerading_expired_course:
        upgrade_message = _(
            'This learner does not have access to this course. '
            'Their access expired on {expiration_date}.')
        return HTML(upgrade_message).format(expiration_date=strftime_localized(
            expiration_date, EXPIRATION_DATE_FORMAT_STR))
    else:
        expiration_message = _(
            '{strong_open}Audit Access Expires {expiration_date}{strong_close}'
            '{line_break}You lose all access to this course, including your progress, on '
            '{expiration_date}.')
        upgrade_deadline_message = _(
            '{line_break}Upgrade by {upgrade_deadline} to get unlimited access to the course '
            'as long as it exists on the site. {a_open}Upgrade now{sronly_span_open} to '
            'retain access past {expiration_date}{span_close}{a_close}')
        full_message = expiration_message
        if upgrade_deadline and upgrade_url:
            full_message += upgrade_deadline_message
            using_upgrade_messaging = True
        else:
            using_upgrade_messaging = False

        language = get_language()
        date_string = get_date_string()
        formatted_expiration_date = date_string.format(
            language=language,
            user_timezone=user_timezone,
            formatted_date=expiration_date.isoformat(),
            formatted_date_localized=strftime_localized(
                expiration_date, EXPIRATION_DATE_FORMAT_STR))
        if using_upgrade_messaging:
            formatted_upgrade_deadline = date_string.format(
                language=language,
                user_timezone=user_timezone,
                formatted_date=upgrade_deadline.isoformat(),
                formatted_date_localized=strftime_localized(
                    upgrade_deadline, EXPIRATION_DATE_FORMAT_STR))

            return HTML(full_message).format(
                a_open=HTML('<a id="FBE_banner" href="{upgrade_link}">'
                            ).format(upgrade_link=upgrade_url),
                sronly_span_open=HTML('<span class="sr-only">'),
                span_close=HTML('</span>'),
                a_close=HTML('</a>'),
                expiration_date=HTML(formatted_expiration_date),
                strong_open=HTML('<strong>'),
                strong_close=HTML('</strong>'),
                line_break=HTML('<br>'),
                upgrade_deadline=HTML(formatted_upgrade_deadline))

        else:
            return HTML(full_message).format(
                span_close=HTML('</span>'),
                expiration_date=HTML(formatted_expiration_date),
                strong_open=HTML('<strong>'),
                strong_close=HTML('</strong>'),
                line_break=HTML('<br>'),
            )
Ejemplo n.º 56
0
def _get_current_user_from_drf_request(sender, **kwargs):
    request = get_current_request()
    drf_request = getattr(request, 'drf_request', None)
    return (getattr(drf_request, 'user', False), 0)
Ejemplo n.º 57
0
def check_course_access_with_redirect(course, user, action, check_if_enrolled=False, check_survey_complete=True, check_if_authenticated=False):  # lint-amnesty, pylint: disable=line-too-long
    """
    Check that the user has the access to perform the specified action
    on the course (CourseBlock|CourseOverview).

    check_if_enrolled: If true, additionally verifies that the user is enrolled.
    check_survey_complete: If true, additionally verifies that the user has completed the survey.
    """
    request = get_current_request()
    check_content_start_date_for_masquerade_user(course.id, user, request,
                                                 course.start)

    access_response = check_course_access(course, user, action, check_if_enrolled, check_survey_complete, check_if_authenticated)  # lint-amnesty, pylint: disable=line-too-long

    if not access_response:
        # Redirect if StartDateError
        if isinstance(access_response, StartDateError):
            start_date = strftime_localized(course.start, 'SHORT_DATE')
            params = QueryDict(mutable=True)
            params['notlive'] = start_date
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode()), access_response)

        # Redirect if AuditExpiredError
        if isinstance(access_response, AuditExpiredError):
            params = QueryDict(mutable=True)
            params[
                'access_response_error'] = access_response.additional_context_user_message
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode()), access_response)

        # Redirect if trying to access an Old Mongo course
        if isinstance(access_response, OldMongoAccessError):
            params = QueryDict(mutable=True)
            params['access_response_error'] = access_response.user_message
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode(),
                ), access_response)

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, MilestoneAccessError):
            raise CourseAccessRedirect(
                '{dashboard_url}'.format(dashboard_url=reverse('dashboard'), ),
                access_response)

        # Redirect if the user is not enrolled and must be to see content
        if isinstance(access_response, EnrollmentRequiredAccessError):
            raise CourseAccessRedirect(
                reverse('about_course', args=[str(course.id)]))

        # Redirect if user must be authenticated to view the content
        if isinstance(access_response, AuthenticationRequiredAccessError):
            raise CourseAccessRedirect(
                reverse('about_course', args=[str(course.id)]))

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, SurveyRequiredAccessError):
            raise CourseAccessRedirect(
                reverse('course_survey', args=[str(course.id)]))

        # Deliberately return a non-specific error message to avoid
        # leaking info about access control settings
        raise CoursewareAccessException(access_response)
Ejemplo n.º 58
0
def email_marketing_user_field_changed(sender, user=None, table=None, setting=None,
                                       old_value=None, new_value=None,
                                       **kwargs):  # pylint: disable=unused-argument
    """
    Update a single user/profile field

    Args:
        sender: Not used
        user: The user object for the user being changed
        table: The name of the table being updated
        setting: The name of the setting being updated
        old_value: Prior value
        new_value: New value
        kwargs: Not used
    """

    # ignore anonymous users
    if user.is_anonymous:
        return

    # ignore anything but User, Profile or UserPreference tables
    if table not in {'auth_user', 'auth_userprofile', 'user_api_userpreference'}:
        return

    # ignore anything not in list of fields to handle
    if setting in CHANGED_FIELDNAMES:
        # skip if not enabled
        #  the check has to be here rather than at the start of the method to avoid
        #  accessing the config during migration 0001_date__add_ecommerce_service_user
        email_config = EmailMarketingConfiguration.current()
        if not email_config.enabled:
            return

        # Is the status of the user account changing to active?
        is_activation = (setting == 'is_active') and new_value is True

        # Is this change in the context of an SSO-initiated registration?
        third_party_provider = None
        if third_party_auth.is_enabled():
            running_pipeline = third_party_auth.pipeline.get(crum.get_current_request())
            if running_pipeline:
                third_party_provider = third_party_auth.provider.Registry.get_from_pipeline(running_pipeline)

        # Send a welcome email if the user account is being activated
        # and we are not in a SSO registration flow whose associated
        # identity provider is configured to allow for the sending
        # of a welcome email.
        send_welcome_email = is_activation and (
            third_party_provider is None or third_party_provider.send_welcome_email
        )

        # set the activation flag when the user is marked as activated
        update_user.delay(_create_sailthru_user_vars(user, user.profile), user.email, site=_get_current_site(),
                          new_user=False, activation=send_welcome_email)

    elif setting == 'email':
        # email update is special case
        email_config = EmailMarketingConfiguration.current()
        if not email_config.enabled:
            return
        update_user_email.delay(user.email, old_value)
Ejemplo n.º 59
0
 def get_group_id_session(self):
     try:
         request = get_current_request()
         return int(request.session['group'].id)
     except:
         return 0
Ejemplo n.º 60
0
    def is_flag_active(self,
                       flag_name,
                       check_before_waffle_callback=None,
                       flag_undefined_default=None):
        """
        Returns and caches whether the provided flag is active.

        If the flag value is already cached in the request, it is returned.
        If check_before_waffle_callback is supplied, it is called before
            checking waffle.
        If check_before_waffle_callback returns None, or if it is not supplied,
            then waffle is used to check the flag.

        Important: Caching for the check_before_waffle_callback must be handled
            by the callback itself.

        Arguments:
            flag_name (String): The name of the flag to check.
            check_before_waffle_callback (function): (Optional) A function that
                will be checked before continuing on to waffle. If
                check_before_waffle_callback(namespaced_flag_name) returns True
                or False, it is returned. If it returns None, then waffle is
                used.
            DEPRECATED flag_undefined_default (Boolean): A default value to be
                returned if the waffle flag is to be checked, but doesn't exist.
                See docs for alternatives.
        """
        # Import is placed here to avoid model import at project startup.
        from waffle.models import Flag

        # validate arguments
        namespaced_flag_name = self._namespaced_name(flag_name)
        value = None
        if check_before_waffle_callback:
            value = check_before_waffle_callback(namespaced_flag_name)

        if value is None:
            # Do not get cached value for the callback, because the key might be different.
            # The callback needs to handle its own caching if it wants it.
            value = self._cached_flags.get(namespaced_flag_name)
            if value is None:

                if flag_undefined_default is not None:
                    # determine if the flag is undefined in waffle
                    try:
                        Flag.objects.get(name=namespaced_flag_name)
                    except Flag.DoesNotExist:
                        value = flag_undefined_default

                if value is None:
                    request = crum.get_current_request()
                    if request:
                        value = flag_is_active(request, namespaced_flag_name)
                    else:
                        log.warn(u"%sFlag '%s' accessed without a request",
                                 self.log_prefix, namespaced_flag_name)
                        # Return the default value if not in a request context.
                        # Note: this skips the cache as the value might be different
                        # in a normal request context. This case seems to occur when
                        # a page redirects to a 404. In this case, we'll just return
                        # the default value.
                        return bool(flag_undefined_default)

                self._cached_flags[namespaced_flag_name] = value
        return value