def get_journals(site): """Retrieve journals from the discovery service. Keyword Arguments: site (Site): Site object for the request will be returned Returns: list of dict, representing journals """ if not journals_enabled(): return [] api_resource = 'journals' orgs = configuration_helpers.get_current_site_orgs() cache_key = get_cache_key( site_domain=site.domain, resource=api_resource, orgs=orgs ) # look up in cache journals = cache.get(cache_key) if not journals: api_client = DiscoveryApiClient() if not api_client: return [] journals = api_client.get_journals(orgs) cache.set(cache_key, journals, JOURNALS_CACHE_TIMEOUT) return journals
def get_journals(site): """Retrieve journals from the discovery service. Keyword Arguments: site (Site): Site object for the request will be returned Returns: list of dict, representing journals """ if not journals_enabled(): return [] api_resource = 'journals' orgs = configuration_helpers.get_current_site_orgs() cache_key = get_cache_key(site_domain=site.domain, resource=api_resource, orgs=orgs) # look up in cache journals = cache.get(cache_key) if not journals: api_client = DiscoveryApiClient() if not api_client: return [] journals = api_client.get_journals(orgs) cache.set(cache_key, journals, JOURNALS_CACHE_TIMEOUT) return journals
def get_visible_courses(org=None, filter_=None): """ Yield the CourseOverviews that should be visible in this branded instance. Arguments: org (string): Optional parameter that allows case-insensitive filtering by organization. filter_ (dict): Optional parameter that allows custom filtering by fields on the course. """ # Import is placed here to avoid model import at project startup. from openedx.core.djangoapps.content.course_overviews.models import CourseOverview current_site_orgs = configuration_helpers.get_current_site_orgs() courses = CourseOverview.objects.none() if org: # Check the current site's orgs to make sure the org's courses should be displayed if not current_site_orgs or org in current_site_orgs: courses = CourseOverview.get_all_courses(orgs=[org], filter_=filter_) elif current_site_orgs: # Only display courses that should be displayed on this site courses = CourseOverview.get_all_courses(orgs=current_site_orgs, filter_=filter_) else: courses = CourseOverview.get_all_courses(filter_=filter_) courses = courses.order_by('id') # Filtering can stop here. if current_site_orgs: return courses # See if we have filtered course listings in this domain filtered_visible_ids = None # this is legacy format, which also handle dev case, which should not filter subdomain = configuration_helpers.get_value('subdomain', 'default') if hasattr( settings, 'COURSE_LISTINGS' ) and subdomain in settings.COURSE_LISTINGS and not settings.DEBUG: filtered_visible_ids = frozenset([ CourseKey.from_string(c) for c in settings.COURSE_LISTINGS[subdomain] ]) if filtered_visible_ids: return courses.filter(id__in=filtered_visible_ids) else: # Filter out any courses based on current org, to avoid leaking these. orgs = configuration_helpers.get_all_orgs() return courses.exclude(org__in=orgs)
def get_visible_courses(org=None, filter_=None): """ Return the set of CourseOverviews that should be visible in this branded instance. Arguments: org (string): Optional parameter that allows case-insensitive filtering by organization. filter_ (dict): Optional parameter that allows custom filtering by fields on the course. """ courses = [] current_site_orgs = configuration_helpers.get_current_site_orgs() if org: # Check the current site's orgs to make sure the org's courses should be displayed if not current_site_orgs or org in current_site_orgs: courses = CourseOverview.get_all_courses(orgs=[org], filter_=filter_) elif current_site_orgs: # Only display courses that should be displayed on this site courses = CourseOverview.get_all_courses(orgs=current_site_orgs, filter_=filter_) else: courses = CourseOverview.get_all_courses(filter_=filter_) courses = sorted(courses, key=lambda course: course.number) # Filtering can stop here. if current_site_orgs: return courses # See if we have filtered course listings in this domain filtered_visible_ids = None # this is legacy format, which also handle dev case, which should not filter subdomain = configuration_helpers.get_value('subdomain', 'default') if hasattr( settings, 'COURSE_LISTINGS' ) and subdomain in settings.COURSE_LISTINGS and not settings.DEBUG: filtered_visible_ids = frozenset([ CourseKey.from_string(c) for c in settings.COURSE_LISTINGS[subdomain] ]) if filtered_visible_ids: return [ course for course in courses if course.id in filtered_visible_ids ] else: # Filter out any courses based on current org, to avoid leaking these. orgs = configuration_helpers.get_all_orgs() return [ course for course in courses if course.location.org not in orgs ]
def exclude_dictionary(self, **kwargs): """ Exclude any courses defined outside the current org. """ exclude_dictionary = super(LmsSearchFilterGenerator, self).exclude_dictionary(**kwargs) course_org_filter = configuration_helpers.get_current_site_orgs() # If we have a course filter we are ensuring that we only get those courses above if not course_org_filter: org_filter_out_set = configuration_helpers.get_all_orgs() if org_filter_out_set: exclude_dictionary['org'] = list(org_filter_out_set) return exclude_dictionary
def exclude_dictionary(self, **kwargs): """ Exclude any courses defined outside the current org. """ exclude_dictionary = super(LmsSearchFilterGenerator, self).exclude_dictionary(**kwargs) course_org_filter = configuration_helpers.get_current_site_orgs() # If we have a course filter we are ensuring that we only get those courses above if not course_org_filter: org_filter_out_set = configuration_helpers.get_all_orgs() if org_filter_out_set: exclude_dictionary['org'] = list(org_filter_out_set) return exclude_dictionary
def filter_authorized_organizations_from_list(organizations, is_super_user): """ Filter organizations list on the basis of configured site organizations. """ if not is_super_user: site_orgs = configuration_helpers.get_current_site_orgs() org_names_list = [] for org in organizations: if (org["name"] in site_orgs) or (org["short_name"] in site_orgs): org_names_list.append(org["short_name"]) else: org_names_list = [org["short_name"] for org in organizations] return org_names_list
def get_visible_courses(org=None, filter_=None): """ Yield the CourseOverviews that should be visible in this branded instance. Arguments: org (string): Optional parameter that allows case-insensitive filtering by organization. filter_ (dict): Optional parameter that allows custom filtering by fields on the course. """ # Import is placed here to avoid model import at project startup. from openedx.core.djangoapps.content.course_overviews.models import CourseOverview current_site_orgs = configuration_helpers.get_current_site_orgs() courses = CourseOverview.objects.none() if org: # Check the current site's orgs to make sure the org's courses should be displayed if not current_site_orgs or org in current_site_orgs: courses = CourseOverview.get_all_courses(orgs=[org], filter_=filter_) elif current_site_orgs: # Only display courses that should be displayed on this site courses = CourseOverview.get_all_courses(orgs=current_site_orgs, filter_=filter_) else: courses = CourseOverview.get_all_courses(filter_=filter_) courses = courses.order_by('id') # Filtering can stop here. if current_site_orgs: return courses # See if we have filtered course listings in this domain filtered_visible_ids = None # this is legacy format, which also handle dev case, which should not filter subdomain = configuration_helpers.get_value('subdomain', 'default') if hasattr(settings, 'COURSE_LISTINGS') and subdomain in settings.COURSE_LISTINGS and not settings.DEBUG: filtered_visible_ids = frozenset( [CourseKey.from_string(c) for c in settings.COURSE_LISTINGS[subdomain]] ) if filtered_visible_ids: return courses.filter(id__in=filtered_visible_ids) else: # Filter out any courses based on current org, to avoid leaking these. orgs = configuration_helpers.get_all_orgs() return courses.exclude(org__in=orgs)
def field_dictionary(self, **kwargs): """ add course if provided otherwise add courses in which the user is enrolled in """ field_dictionary = super(LmsSearchFilterGenerator, self).field_dictionary(**kwargs) if kwargs.get('user'): if not kwargs.get('course_id'): user_enrollments = self._enrollments_for_user(kwargs['user']) field_dictionary['course'] = [unicode(enrollment.course_id) for enrollment in user_enrollments] # if we have an org filter, only include results for this org filter course_org_filter = configuration_helpers.get_current_site_orgs() if course_org_filter: field_dictionary['org'] = course_org_filter return field_dictionary
def field_dictionary(self, **kwargs): """ add course if provided otherwise add courses in which the user is enrolled in """ field_dictionary = super(LmsSearchFilterGenerator, self).field_dictionary(**kwargs) if not kwargs.get('user'): field_dictionary['course'] = [] elif not kwargs.get('course_id'): user_enrollments = self._enrollments_for_user(kwargs['user']) field_dictionary['course'] = [six.text_type(enrollment.course_id) for enrollment in user_enrollments] # if we have an org filter, only include results for this org filter course_org_filter = configuration_helpers.get_current_site_orgs() if course_org_filter: field_dictionary['org'] = course_org_filter return field_dictionary
def get_visible_courses(org=None, filter_=None): """ Return the set of CourseOverviews that should be visible in this branded instance. Arguments: org (string): Optional parameter that allows case-insensitive filtering by organization. filter_ (dict): Optional parameter that allows custom filtering by fields on the course. """ courses = [] current_site_orgs = configuration_helpers.get_current_site_orgs() if org: # Check the current site's orgs to make sure the org's courses should be displayed if not current_site_orgs or org in current_site_orgs: courses = CourseOverview.get_all_courses(orgs=[org], filter_=filter_) elif current_site_orgs: # Only display courses that should be displayed on this site courses = CourseOverview.get_all_courses(orgs=current_site_orgs, filter_=filter_) else: courses = CourseOverview.get_all_courses(filter_=filter_) courses = sorted(courses, key=lambda course: course.number) # Filtering can stop here. if current_site_orgs: return courses # See if we have filtered course listings in this domain filtered_visible_ids = None # this is legacy format, which also handle dev case, which should not filter subdomain = configuration_helpers.get_value('subdomain', 'default') if hasattr(settings, 'COURSE_LISTINGS') and subdomain in settings.COURSE_LISTINGS and not settings.DEBUG: filtered_visible_ids = frozenset( [SlashSeparatedCourseKey.from_deprecated_string(c) for c in settings.COURSE_LISTINGS[subdomain]] ) if filtered_visible_ids: return [course for course in courses if course.id in filtered_visible_ids] else: # Filter out any courses based on current org, to avoid leaking these. orgs = configuration_helpers.get_all_orgs() return [course for course in courses if course.location.org not in orgs]
def exclude_dictionary(self, **kwargs): """ Exclude any courses defined outside the current org. """ exclude_dictionary = super().exclude_dictionary(**kwargs) course_org_filter = configuration_helpers.get_current_site_orgs() # If we have a course filter we are ensuring that we only get those courses above if not course_org_filter: org_filter_out_set = configuration_helpers.get_all_orgs() if org_filter_out_set: exclude_dictionary['org'] = list(org_filter_out_set) if not getattr(settings, "SEARCH_SKIP_INVITATION_ONLY_FILTERING", True): exclude_dictionary['invitation_only'] = True if not getattr(settings, "SEARCH_SKIP_SHOW_IN_CATALOG_FILTERING", True): exclude_dictionary['catalog_visibility'] = 'none' return exclude_dictionary
def validate_org(course_id): """ Validate the course organization against all possible orgs for the site To determine if the Org is valid we must look at 3 things 1 Orgs in the current site 2 Orgs in other sites 3 flag EOX_CORE_USER_ENABLE_MULTI_TENANCY """ if not settings.EOX_CORE_USER_ENABLE_MULTI_TENANCY: return True course_key = get_valid_course_key(course_id) current_site_orgs = get_current_site_orgs() or [] if not current_site_orgs: if course_key.org in get_all_orgs(): return False return True else: return course_key.org in current_site_orgs
def get_org_black_and_whitelist_for_site(): """ Returns the org blacklist and whitelist for the current site. Returns: (org_whitelist, org_blacklist): A tuple of lists of orgs that serve as either a blacklist or a whitelist of orgs for the current site. The whitelist takes precedence, and the blacklist is used if the whitelist is None. """ # Default blacklist is empty. org_blacklist = None # Whitelist the orgs configured for the current site. Each site outside # of edx.org has a list of orgs associated with its configuration. org_whitelist = configuration_helpers.get_current_site_orgs() if not org_whitelist: # If there is no whitelist, the blacklist will include all orgs that # have been configured for any other sites. This applies to edx.org, # where it is easier to blacklist all other orgs. org_blacklist = configuration_helpers.get_all_orgs() return org_whitelist, org_blacklist
def get_org_black_and_whitelist_for_site(): """ Returns the org blacklist and whitelist for the current site. Returns: (org_whitelist, org_blacklist): A tuple of lists of orgs that serve as either a blacklist or a whitelist of orgs for the current site. The whitelist takes precedence, and the blacklist is used if the whitelist is None. """ # Default blacklist is empty. org_blacklist = None # Whitelist the orgs configured for the current site. Each site outside # of edx.org has a list of orgs associated with its configuration. org_whitelist = configuration_helpers.get_current_site_orgs() if not org_whitelist: # If there is no whitelist, the blacklist will include all orgs that # have been configured for any other sites. This applies to edx.org, # where it is easier to blacklist all other orgs. org_blacklist = configuration_helpers.get_all_orgs() return org_whitelist, org_blacklist
def inner(request, *args, **kwargs): if not request.user.is_authenticated and not configuration_helpers.get_value( 'SHOW_COURSES_TO_ANONYMOUS_USERS', settings.SHOW_COURSES_TO_ANONYMOUS_USERS ): raise Http404 course_key = kwargs.get('course_key_string') or kwargs.get('course_id') if course_key is not None: try: CourseKey.from_string(course_key) courselike_key = CourseKey.from_string(course_key) library = isinstance(courselike_key, LibraryLocator) if not library: site_orgs = configuration_helpers.get_current_site_orgs() linked_courses = OrganizationCourse.objects.filter(course_id=course_key, organization__name__in=site_orgs, active=True) if not linked_courses: raise Http404 except InvalidKeyError: raise Http404 response = view_func(request, *args, **kwargs) return response
def get_queryset(self): site_organizations = configuration_helpers.get_current_site_orgs() return User.objects.select_related('profile').filter( Q(edly_profile__edly_sub_organizations__slug__in=site_organizations ))
def test_get_current_site_orgs(self): test_orgs = test_config_multi_org['course_org_filter'] six.assertCountEqual( self, list(configuration_helpers.get_current_site_orgs()), test_orgs)
def _record_feedback_in_zendesk(realname, email, subject, details, tags, additional_info, group_name=None, require_update=False, support_email=None, custom_fields=None): """ Create a new user-requested Zendesk ticket. Once created, the ticket will be updated with a private comment containing additional information from the browser and server, such as HTTP headers and user state. Returns a boolean value indicating whether ticket creation was successful, regardless of whether the private comment update succeeded. If `group_name` is provided, attaches the ticket to the matching Zendesk group. If `require_update` is provided, returns False when the update does not succeed. This allows using the private comment to add necessary information which the user will not see in followup emails from support. If `custom_fields` is provided, submits data to those fields in Zendesk. """ zendesk_api = _ZendeskApi() additional_info_string = (u"Additional information:\n\n" + u"\n".join( u"%s: %s" % (key, value) for (key, value) in additional_info.items() if value is not None)) # Tag all issues with LMS to distinguish channel in Zendesk; requested by student support team zendesk_tags = list(tags.values()) + ["LMS"] # Per edX support, we would like to be able to route feedback items by site via tagging current_site_orgs = configuration_helpers.get_current_site_orgs() if current_site_orgs: for org in current_site_orgs: zendesk_tags.append("whitelabel_{org}".format(org=org)) new_ticket = { "ticket": { "requester": { "name": realname, "email": email }, "subject": subject, "comment": { "body": details }, "tags": zendesk_tags } } if custom_fields: new_ticket["ticket"]["custom_fields"] = custom_fields group = None if group_name is not None: group = zendesk_api.get_group(group_name) if group is not None: new_ticket['ticket']['group_id'] = group['id'] if support_email is not None: # If we do not include the `recipient` key here, Zendesk will default to using its default reply # email address when support agents respond to tickets. By setting the `recipient` key here, # we can ensure that WL site users are responded to via the correct Zendesk support email address. new_ticket['ticket']['recipient'] = support_email try: ticket_id = zendesk_api.create_ticket(new_ticket) if group_name is not None and group is None: # Support uses Zendesk groups to track tickets. In case we # haven't been able to correctly group this ticket, log its ID # so it can be found later. log.warning( 'Unable to find group named %s for Zendesk ticket with ID %s.', group_name, ticket_id) except zendesk.ZendeskError: log.exception("Error creating Zendesk ticket") return False # Additional information is provided as a private update so the information # is not visible to the user. ticket_update = { "ticket": { "comment": { "public": False, "body": additional_info_string } } } try: zendesk_api.update_ticket(ticket_id, ticket_update) except zendesk.ZendeskError: log.exception("Error updating Zendesk ticket with ID %s.", ticket_id) # The update is not strictly necessary, so do not indicate # failure to the user unless it has been requested with # `require_update`. if require_update: return False return True
def _record_feedback_in_zendesk( realname, email, subject, details, tags, additional_info, group_name=None, require_update=False, support_email=None, custom_fields=None ): """ Create a new user-requested Zendesk ticket. Once created, the ticket will be updated with a private comment containing additional information from the browser and server, such as HTTP headers and user state. Returns a boolean value indicating whether ticket creation was successful, regardless of whether the private comment update succeeded. If `group_name` is provided, attaches the ticket to the matching Zendesk group. If `require_update` is provided, returns False when the update does not succeed. This allows using the private comment to add necessary information which the user will not see in followup emails from support. If `custom_fields` is provided, submits data to those fields in Zendesk. """ zendesk_api = _ZendeskApi() additional_info_string = ( u"Additional information:\n\n" + u"\n".join(u"%s: %s" % (key, value) for (key, value) in additional_info.items() if value is not None) ) # Tag all issues with LMS to distinguish channel in Zendesk; requested by student support team zendesk_tags = list(tags.values()) + ["LMS"] # Per edX support, we would like to be able to route feedback items by site via tagging current_site_orgs = configuration_helpers.get_current_site_orgs() if current_site_orgs: for org in current_site_orgs: zendesk_tags.append("whitelabel_{org}".format(org=org)) new_ticket = { "ticket": { "requester": {"name": realname, "email": email}, "subject": subject, "comment": {"body": details}, "tags": zendesk_tags } } if custom_fields: new_ticket["ticket"]["custom_fields"] = custom_fields group = None if group_name is not None: group = zendesk_api.get_group(group_name) if group is not None: new_ticket['ticket']['group_id'] = group['id'] if support_email is not None: # If we do not include the `recipient` key here, Zendesk will default to using its default reply # email address when support agents respond to tickets. By setting the `recipient` key here, # we can ensure that WL site users are responded to via the correct Zendesk support email address. new_ticket['ticket']['recipient'] = support_email try: ticket_id = zendesk_api.create_ticket(new_ticket) if group_name is not None and group is None: # Support uses Zendesk groups to track tickets. In case we # haven't been able to correctly group this ticket, log its ID # so it can be found later. log.warning('Unable to find group named %s for Zendesk ticket with ID %s.', group_name, ticket_id) except zendesk.ZendeskError: log.exception("Error creating Zendesk ticket") return False # Additional information is provided as a private update so the information # is not visible to the user. ticket_update = {"ticket": {"comment": {"public": False, "body": additional_info_string}}} try: zendesk_api.update_ticket(ticket_id, ticket_update) except zendesk.ZendeskError: log.exception("Error updating Zendesk ticket with ID %s.", ticket_id) # The update is not strictly necessary, so do not indicate # failure to the user unless it has been requested with # `require_update`. if require_update: return False return True
def test_get_current_site_orgs(self): test_orgs = test_config_multi_org['course_org_filter'] self.assertItemsEqual( list(configuration_helpers.get_current_site_orgs()), test_orgs )