PK!mitxpro_core/__init__.pyPK! umitxpro_core/apps.py"""mitxpro_extensions app config""" from __future__ import unicode_literals from django.apps import AppConfig class MITxProCoreConfig(AppConfig): """App configuration""" name = "mitxpro_core" verbose_name = "MIT xPro Openedx Extensions" plugin_app = { "settings_config": { "lms.djangoapp": { "test": {"relative_path": "settings.test"}, "common": {"relative_path": "settings.common"}, # aws deprecated in favor of production, see https://openedx.atlassian.net/browse/DEPR-14 "aws": {"relative_path": "settings.production"}, "production": {"relative_path": "settings.production"}, } } } PK!;dPPmitxpro_core/middleware.py"""MIT xPro Open edX middlware""" import re from django.conf import settings from django.shortcuts import redirect from django.utils.deprecation import MiddlewareMixin def redirect_to_login(): """Returns a response redirecting to the login url""" return redirect(settings.MITXPRO_CORE_REDIRECT_LOGIN_URL) class RedirectAnonymousUsersToLoginMiddleware(MiddlewareMixin): """Middleware to redirect anonymous users to login via xpro""" def process_request(self, request): """Process an incoming request""" if settings.MITXPRO_CORE_REDIRECT_ENABLED and ( not getattr(request, "user", None) or request.user.is_anonymous ): # if allowed regexes are set, redirect if the path doesn't match any allowed_regexes = settings.MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST if allowed_regexes and not any( [re.match(pattern, request.path) for pattern in allowed_regexes] ): return redirect_to_login() # if denied regexes are set, redirect if the path matches any denied_regexes = settings.MITXPRO_CORE_REDIRECT_DENY_RE_LIST if denied_regexes and any( [re.match(pattern, request.path) for pattern in denied_regexes] ): return redirect_to_login() return None PK!``mitxpro_core/middleware_test.py"""Middleware tests""" import pytest @pytest.mark.parametrize("is_enabled", [True, False]) @pytest.mark.parametrize("is_anonymous", [True, False]) @pytest.mark.parametrize( "path, allowed_regexes, denied_regexes, should_redirect", [ ("/allowed", [], [], False), ("/allowed", [r"^/allowed"], [], False), ("/allowed/nested", [r"^/allowed"], [], False), ("/denied", [r"^/allowed"], [], True), ("/allowed", [], [r"^/allowed"], True), ("/allowed/nested", [], [r"^/allowed"], True), ("/denied", [], [r"^/allowed"], False), ("/allowed", [r"^/allowed"], [r"^/allowed/nested"], False), ("/allowed/nested", [r"^/allowed"], [r"^/allowed/nested"], True), ], ) def test_redirect_middleware( settings, rf, mocker, is_enabled, is_anonymous, path, allowed_regexes, denied_regexes, should_redirect, ): # pylint: disable=too-many-arguments """Test that the middleware redirects correctly""" settings.MITXPRO_CORE_REDIRECT_LOGIN_URL = "/login" settings.MITXPRO_CORE_REDIRECT_ENABLED = is_enabled settings.MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST = allowed_regexes settings.MITXPRO_CORE_REDIRECT_DENY_RE_LIST = denied_regexes from mitxpro_core.middleware import RedirectAnonymousUsersToLoginMiddleware should_redirect = should_redirect and is_enabled and is_anonymous mock_get_response = mocker.Mock() middleware = RedirectAnonymousUsersToLoginMiddleware(mock_get_response) request = rf.get(path) request.user = mocker.Mock(is_anonymous=is_anonymous) response = middleware(request) if should_redirect: mock_get_response.assert_not_called() assert response.status_code == 302 assert response.url == settings.MITXPRO_CORE_REDIRECT_LOGIN_URL else: mock_get_response.assert_called_once_with(request) PK!!mitxpro_core/settings/__init__.pyPK!-mitxpro_core/settings/common.py""" Settings for mitxpro-core """ from __future__ import unicode_literals SECRET_KEY = "unsafe-secret-key" INSTALLED_APPS = ( "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", ) def plugin_settings(settings): """Apply default settings for this plugin""" settings.MITXPRO_CORE_REDIRECT_ENABLED = True settings.MITXPRO_CORE_REDIRECT_LOGIN_URL = ( "/auth/login/mitxpro-oauth2/?auth_entry=login" ) settings.MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST = [ r"^/(admin|auth|login|logout|register|api|oauth2|user_api)" ] settings.MITXPRO_CORE_REDIRECT_DENY_RE_LIST = [] settings.MIDDLEWARE_CLASSES.extend( ["mitxpro_core.middleware.RedirectAnonymousUsersToLoginMiddleware"] ) PK! n#mitxpro_core/settings/production.py""" Production settings for mitxpro-core """ from __future__ import unicode_literals def plugin_settings(settings): """Apply production settings for this plugin""" settings.MITXPRO_CORE_REDIRECT_ENABLED = getattr(settings, "ENV_TOKENS", {}).get( "MITXPRO_CORE_REDIRECT_ENABLED", settings.MITXPRO_CORE_REDIRECT_ENABLED ) settings.MITXPRO_CORE_REDIRECT_LOGIN_URL = getattr(settings, "ENV_TOKENS", {}).get( "MITXPRO_CORE_REDIRECT_LOGIN_URL", settings.MITXPRO_CORE_REDIRECT_LOGIN_URL ) settings.MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST = getattr( settings, "ENV_TOKENS", {} ).get( "MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST", settings.MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST, ) settings.MITXPRO_CORE_REDIRECT_DENY_RE_LIST = getattr( settings, "ENV_TOKENS", {} ).get( "MITXPRO_CORE_REDIRECT_DENY_RE_LIST", settings.MITXPRO_CORE_REDIRECT_DENY_RE_LIST, ) PK!YNmitxpro_core/settings/test.py""" Settings for mitxpro_core-core """ from __future__ import absolute_import, unicode_literals from .common import * # pylint: disable=wildcard-import, unused-wildcard-import class SettingsClass(object): # pylint: disable=useless-object-inheritance """ dummy settings class """ def plugin_settings(settings): # pylint: disable=function-redefined """ Configure the plugin for tests """ settings.MITXPRO_CORE_REDIRECT_ENABLED = True settings.MITXPRO_CORE_REDIRECT_LOGIN_URL = ( "/auth/login/mitxpro-oauth2/?auth_entry=login" ) settings.MITXPRO_CORE_REDIRECT_ALLOW_RE_LIST = [ r"^/(admin|auth|login|logout|register|api|oauth2|user_api)" ] settings.MITXPRO_CORE_REDIRECT_DENY_RE_LIST = [] settings.MIDDLEWARE_CLASSES = [ "mitxpro_core.middleware.RedirectAnonymousUsersToLoginMiddleware" ] SETTINGS = SettingsClass() plugin_settings(SETTINGS) vars().update(SETTINGS.__dict__) INSTALLED_APPS += ("mitxpro_core",) ROOT_URLCONF = "mitxpro_core.urls" ALLOWED_HOSTS = ["*"] # This key needs to be defined so that the check_apps_ready passes and the # AppRegistry is loaded DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": "db.sqlite3"}} PK!5.33mitxpro_core/urls.py"""Minimal urls for django app""" urlpatterns = [] PK!HE 7B;mitxpro_openedx_extensions-0.1.0.dist-info/entry_points.txt-KJKO,(,((ʏO/JE|=C*yi\\PK!2mitxpro_openedx_extensions-0.1.0.dist-info/LICENSEBSD 3-Clause License Copyright (c) 2017, MIT Office of Digital Learning All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PK!H|n-WY0mitxpro_openedx_extensions-0.1.0.dist-info/WHEEL A н#Z;/" bFF]xzwK;<*mTֻ0*Ri.4Vm0[H, JPK!H7:b3mitxpro_openedx_extensions-0.1.0.dist-info/METADATAOO0 f'6QC! wCqKP$E۷] n=??=ǾE<|D)$,20%&4juX̢`Q+*{Xέ Œspe/!fOY0pV7c[YSLZL[-ǘ,ۘOSS EG--p"rL6d"6hEF6bo# 8/s2H2kKr]4 )\ꢔG-+Q5lZ "P?8}YaRMöuڨ+;F]yvйc | H'1K1Ed^Ӓdܨ峽[:=Z7^PK!H-`N1mitxpro_openedx_extensions-0.1.0.dist-info/RECORDKo@} Xdq\DeC(ra@76Ilgͥ&JGQ^8fh"s<T,5э[W t ]*`m*sv{eOPoի#ԽHn>5㙞lksKe5]YkᕜK ͪ4--nRₜk> t Jrzbє)D&h00xK='Hc#cL A/˯n1ϧ&MU5 Ė裇|fgaTK0ySDHpO}}/t٣[WPm0E'ZiD0DLfn'ޘgl >$^˰!͍ UU5]~`] LK+T]ۆ*_$.)=OAú{ ݑԌQ40קָ"5fxϢӦ}bvWci ;R] F'5)kI\rl첰Y_Z<2)^B;g枠ˏTɲ ;b똆CO7礤m-ZV%F ĭG"3^ncN';&4 >=noR;YVPK!mitxpro_core/__init__.pyPK! u6mitxpro_core/apps.pyPK!;dPPBmitxpro_core/middleware.pyPK!``mitxpro_core/middleware_test.pyPK!!gmitxpro_core/settings/__init__.pyPK!-mitxpro_core/settings/common.pyPK! n#mitxpro_core/settings/production.pyPK!YNmitxpro_core/settings/test.pyPK!5.33mitxpro_core/urls.pyPK!HE 7B;Mmitxpro_openedx_extensions-0.1.0.dist-info/entry_points.txtPK!2mitxpro_openedx_extensions-0.1.0.dist-info/LICENSEPK!H|n-WY0'$mitxpro_openedx_extensions-0.1.0.dist-info/WHEELPK!H7:b3$mitxpro_openedx_extensions-0.1.0.dist-info/METADATAPK!H-`N1&mitxpro_openedx_extensions-0.1.0.dist-info/RECORDPK~V)