From 4d4da5ed4284cfdf7ccf752ca58d763d766ffbda Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 16:24:35 -0400 Subject: [PATCH 01/20] Create way to run tests --- runtests.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 runtests.py diff --git a/runtests.py b/runtests.py new file mode 100755 index 0000000..6be55f1 --- /dev/null +++ b/runtests.py @@ -0,0 +1,48 @@ +import sys +import django +from django.conf import settings +from django.test.runner import DiscoverRunner + +settings.configure( + DEBUG=True, + DATABASES={ + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + } + }, + ROOT_URLCONF='tests.urls', + INSTALLED_APPS=( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.admin', + 'accounts.apps.AccountsConfig', + ), + AUTH_USER_MODEL='accounts.User', + AUTHENTICATION_BACKENDS=( + 'accounts.backends.LabsUserBackend', + 'django.contrib.auth.backends.ModelBackend', + ), + MIDDLEWARE=[ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + ], + PLATFORM_ACCOUNTS={ + 'CLIENT_ID': 'id', + 'CLIENT_SECRET': 'secret', + 'REDIRECT_URI': 'example', + } +) + + +django.setup() +test_runner = DiscoverRunner(verbosity=1) + +failures = test_runner.run_tests(['tests']) +if failures: + sys.exit(failures) From cae0d5e251b88c6a69b66a486a9cb0fede6a440d Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 16:24:46 -0400 Subject: [PATCH 02/20] Update tests --- tests/test_views.py | 24 ++++++++++++------------ tests/urls.py | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 tests/urls.py diff --git a/tests/test_views.py b/tests/test_views.py index 32dd486..e213faf 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -3,7 +3,7 @@ from django.test import TestCase, Client from django.urls import reverse from django.contrib.auth import get_user_model -from labs_accounts.settings import CLIENT_ID, PLATFORM_URL, REDIRECT_URI, SCOPE +from accounts.settings import accounts_settings class LoginViewTestCase(TestCase): @@ -12,7 +12,7 @@ def setUp(self): self.User = get_user_model() def test_invalid_next(self): - response = self.client.get(reverse('labs_accounts:login')) + response = self.client.get(reverse('accounts:login')) def test_authenticated_user(self): student = self.User.objects.create_user( @@ -22,22 +22,22 @@ def test_authenticated_user(self): ) self.client.login(username='00000000000000000000000000000001', password='secret') redirect = 'https://example.com/' - response = self.client.get(reverse('labs_accounts:login') + '?next=' + redirect) + response = self.client.get(reverse('accounts:login') + '?next=' + redirect) self.assertRedirects(response, redirect, fetch_redirect_response=False) def test_unauthenticated_user(self): redirect = 'https://example.com/' - response = self.client.get(reverse('labs_accounts:login') + '?next=' + redirect) + response = self.client.get(reverse('accounts:login') + '?next=' + redirect) self.assertEqual(response.status_code, 302) - self.assertIn(PLATFORM_URL + '/accounts/authorize', response.url) + self.assertIn(accounts_settings.PLATFORM_URL + '/accounts/authorize', response.url) self.assertIn('response_type=code', response.url) - self.assertIn('client_id=' + CLIENT_ID, response.url) - self.assertIn('redirect_uri=' + urllib.parse.quote_plus(REDIRECT_URI), response.url) - self.assertIn('scope=' + '+'.join(SCOPE), response.url) + self.assertIn('client_id=' + accounts_settings.CLIENT_ID, response.url) + self.assertIn('redirect_uri=' + urllib.parse.quote_plus(accounts_settings.REDIRECT_URI), response.url) + self.assertIn('scope=' + '+'.join(accounts_settings.SCOPE), response.url) -@patch('labs_accounts.views.OAuth2Session.get') -@patch('labs_accounts.views.OAuth2Session.fetch_token') +@patch('accounts.views.OAuth2Session.get') +@patch('accounts.views.OAuth2Session.fetch_token') class CallbackViewTestCase(TestCase): def setUp(self): self.client = Client() @@ -51,7 +51,7 @@ def setUp(self): def test_active_user(self, mock_fetch_token, mock_get): mock_fetch_token.return_value = {'access_token': 'abc'} mock_get.return_value.json.return_value = {'uuid': '00000000000000000000000000000001'} - response = self.client.get(reverse('labs_accounts:callback')) + response = self.client.get(reverse('accounts:callback')) self.assertRedirects(response, self.redirect, fetch_redirect_response=False) def test_inactive_user(self, mock_fetch_token, mock_get): @@ -63,5 +63,5 @@ def test_inactive_user(self, mock_fetch_token, mock_get): ) mock_fetch_token.return_value = {'access_token': 'abc'} mock_get.return_value.json.return_value = {'uuid': '00000000000000000000000000000001'} - response = self.client.get(reverse('labs_accounts:callback')) + response = self.client.get(reverse('accounts:callback')) self.assertEqual(response.status_code, 500) diff --git a/tests/urls.py b/tests/urls.py new file mode 100644 index 0000000..65b6d06 --- /dev/null +++ b/tests/urls.py @@ -0,0 +1,2 @@ +from django.urls import path, include +urlpatterns = [path('accounts/', include('accounts.urls', namespace='accounts'))] From d29474eedd82a7dc71c4ba01a457d55151824eef Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 16:25:08 -0400 Subject: [PATCH 03/20] Change settings loading --- accounts/settings.py | 38 ++++++++++++++++++++++++++++++++------ accounts/views.py | 23 +++++++++++++++-------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/accounts/settings.py b/accounts/settings.py index a44ab6f..209d956 100644 --- a/accounts/settings.py +++ b/accounts/settings.py @@ -1,10 +1,36 @@ import os from django.conf import settings -CLIENT_ID = getattr(settings, "OAUTH2_CLIENT_ID", os.environ.get('OAUTH2_CLIENT_ID')) -CLIENT_SECRET = getattr(settings, "OAUTH2_CLIENT_SECRET", os.environ.get('OAUTH2_CLIENT_ID')) -REDIRECT_URI = getattr(settings, "OAUTH2_REDIRECT_URI", os.environ.get('OAUTH2_REDIRECT_URI')) -SCOPE = getattr(settings, "OAUTH2_SCOPES", ['read', 'introspection']) -PLATFORM_URL = getattr(settings, "OAUTH2_PLATFORM_URL", 'https://platform.pennlabs.org') - USER_SETTINGS = getattr(settings, "PLATFORM_ACCOUNTS", {}) + +DEFAULTS = { + 'CLIENT_ID': os.environ.get('OAUTH2_CLIENT_ID'), + 'CLIENT_SECRET': os.environ.get('OAUTH2_CLIENT_SECRET'), + 'REDIRECT_URI': os.environ.get('OAUTH2_REDIRECT_URI'), + 'SCOPE': ['read', 'introspection'], + 'PLATFORM_URL': 'https://platform.pennlabs.org', +} + + +class AccountsSettings(object): + """ + Based on https://github.com/encode/django-rest-framework/blob/master/rest_framework/settings.py + """ + def __init__(self, settings=None, defaults=None): + self.settings = settings or {} + self.defaults = defaults or {} + + def __getattr__(self, attr): + if attr not in self.defaults.keys(): + raise AttributeError("Invalid Penn Labs accounts setting: %s" % attr) + + try: + val = self.settings[attr] + except KeyError: + val = self.defaults[attr] + + setattr(self, attr, val) + return val + + +accounts_settings = AccountsSettings(USER_SETTINGS, DEFAULTS) diff --git a/accounts/views.py b/accounts/views.py index 250fea7..017bd47 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -3,15 +3,21 @@ from django.http import HttpResponseServerError from django.shortcuts import redirect from django.views import View -from accounts.settings import CLIENT_ID, CLIENT_SECRET, PLATFORM_URL, REDIRECT_URI, SCOPE +from accounts.settings import accounts_settings class LoginView(View): def get(self, request): request.session.__setitem__('next', request.GET.get('next')) if not request.user.is_authenticated: - platform = OAuth2Session(CLIENT_ID, scope=SCOPE, redirect_uri=REDIRECT_URI) - authorization_url, state = platform.authorization_url(PLATFORM_URL + '/accounts/authorize/') + platform = OAuth2Session( + accounts_settings.CLIENT_ID, + scope=accounts_settings.SCOPE, + redirect_uri=accounts_settings.REDIRECT_URI + ) + authorization_url, state = platform.authorization_url( + accounts_settings.PLATFORM_URL + '/accounts/authorize/' + ) response = redirect(authorization_url) request.session.__setitem__('state', state) return response @@ -22,15 +28,16 @@ class CallbackView(View): def get(self, request): code = request.GET.get('code') state = request.session.pop('state') - platform = OAuth2Session(CLIENT_ID, state=state) + platform = OAuth2Session(accounts_settings.CLIENT_ID, state=state) token = platform.fetch_token( - PLATFORM_URL + '/accounts/token/', - client_secret=CLIENT_SECRET, + accounts_settings.PLATFORM_URL + '/accounts/token/', + client_secret=accounts_settings.CLIENT_SECRET, authorization_response=request.get_full_path() ) - platform = OAuth2Session(CLIENT_ID, token=token) + platform = OAuth2Session(accounts_settings.CLIENT_ID, token=token) access_token = token['access_token'] - uuid = platform.get(PLATFORM_URL + '/accounts/introspect/?token=' + access_token).json()['uuid'] + introspect_url = accounts_settings.PLATFORM_URL + '/accounts/introspect/?token=' + access_token + uuid = platform.get(introspect_url).json()['uuid'] user = auth.authenticate(remote_user=uuid) if user: auth.login(request, user) From f891a1d79e3dc58476272234a2a47846d6484609 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 17:37:30 -0400 Subject: [PATCH 04/20] Create test settings file --- runtests.py | 37 ---------------------- tests/settings.py | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 tests/settings.py diff --git a/runtests.py b/runtests.py index 6be55f1..1800ce6 100755 --- a/runtests.py +++ b/runtests.py @@ -3,43 +3,6 @@ from django.conf import settings from django.test.runner import DiscoverRunner -settings.configure( - DEBUG=True, - DATABASES={ - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - } - }, - ROOT_URLCONF='tests.urls', - INSTALLED_APPS=( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.admin', - 'accounts.apps.AccountsConfig', - ), - AUTH_USER_MODEL='accounts.User', - AUTHENTICATION_BACKENDS=( - 'accounts.backends.LabsUserBackend', - 'django.contrib.auth.backends.ModelBackend', - ), - MIDDLEWARE=[ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - ], - PLATFORM_ACCOUNTS={ - 'CLIENT_ID': 'id', - 'CLIENT_SECRET': 'secret', - 'REDIRECT_URI': 'example', - } -) - - django.setup() test_runner = DiscoverRunner(verbosity=1) diff --git a/tests/settings.py b/tests/settings.py new file mode 100644 index 0000000..00af254 --- /dev/null +++ b/tests/settings.py @@ -0,0 +1,79 @@ +SECRET_KEY = 'supersecret' + +ALLOWED_HOSTS = [] + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + 'django.contrib.messages', + 'accounts', + 'tests' +) + +MIDDLEWARE = [ + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +] + +ROOT_URLCONF = 'tests.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'debug': True, + 'context_processors': [ + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'example.sqlite', + } +} + + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +SITE_ID = 1 + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +STATIC_URL = '/static/' + +AUTH_USER_MODEL = 'accounts.User' + +AUTHENTICATION_BACKENDS = ( + 'accounts.backends.LabsUserBackend', + 'django.contrib.auth.backends.ModelBackend', +) + +PLATFORM_ACCOUNTS = { + 'CLIENT_ID': 'id', + 'CLIENT_SECRET': 'secret', + 'REDIRECT_URI': 'example', +} From 48e0e5101125f2e4392ef029d2ce913566fbd2e5 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 17:37:40 -0400 Subject: [PATCH 05/20] Add CircleCI settings --- .circleci/config.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..152e93c --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,43 @@ +version: 2 +jobs: + build: + working_directory: ~/django-labs-accounts + docker: + - image: themattrix/tox + environment: + PIPENV_VENV_IN_PROJECT: true + steps: + - checkout + - run: sudo chown -R circleci:circleci /usr/local/bin + - run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages + - restore_cache: + key: deps9-{{ .Branch }}-{{ checksum "Pipfile.lock" }} + - run: + name: install dockerize + command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz + environment: + DOCKERIZE_VERSION: v0.3.0 + - run: + name: Install dependencies + command: | + pip tox coveralls + - run: + name: Wait for db + command: dockerize -wait tcp://localhost:3306 -timeout 1m + - save_cache: + key: deps9-{{ .Branch }}-{{ checksum "Pipfile.lock" }} + paths: + - ".venv" + - "/usr/local/bin" + - "/usr/local/lib/python3.7/site-packages" + - run: + name: Run tests + command: | + tox + coveralls + +workflows: + version: 2 + build: + jobs: + - build \ No newline at end of file From d15519631f19da553d9e86bd345a2cbd8d3af742 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 17:37:51 -0400 Subject: [PATCH 06/20] Add tox --- tox.ini | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tox.ini diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..7a853be --- /dev/null +++ b/tox.ini @@ -0,0 +1,24 @@ +[tox] +envlist = + py35-django{20,21}, + py36-django{20,21}, + py37-django{20,21}, + lint + +[testenv] +commands = coverage run runtests.py +setenv = + DJANGO_SETTINGS_MODULE = tests.settings +deps = + django20: Django>=2.0,<2.1 + django21: Django>=2.1,<2.2 + coverage + +[testenv:lint] +skip_install = True +commands = flake8 {toxinidir} +deps = flake8 + +[flake8] +max-line-length = 120 +exclude = docs/, accounts/migrations/, .tox/ From 7d32e9248d8acf9f83d6f9a4f837224af08303f3 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 17:40:11 -0400 Subject: [PATCH 07/20] Update CircleCI config --- .circleci/config.yml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 152e93c..14b860a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,32 +4,12 @@ jobs: working_directory: ~/django-labs-accounts docker: - image: themattrix/tox - environment: - PIPENV_VENV_IN_PROJECT: true steps: - checkout - - run: sudo chown -R circleci:circleci /usr/local/bin - - run: sudo chown -R circleci:circleci /usr/local/lib/python3.7/site-packages - - restore_cache: - key: deps9-{{ .Branch }}-{{ checksum "Pipfile.lock" }} - - run: - name: install dockerize - command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz - environment: - DOCKERIZE_VERSION: v0.3.0 - run: name: Install dependencies command: | pip tox coveralls - - run: - name: Wait for db - command: dockerize -wait tcp://localhost:3306 -timeout 1m - - save_cache: - key: deps9-{{ .Branch }}-{{ checksum "Pipfile.lock" }} - paths: - - ".venv" - - "/usr/local/bin" - - "/usr/local/lib/python3.7/site-packages" - run: name: Run tests command: | From ee61b8daa2fa8c39d9a2fd8477b6d9a1c4bb712a Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 17:41:24 -0400 Subject: [PATCH 08/20] Fix pip typo in circleci config --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 14b860a..c439769 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ jobs: - run: name: Install dependencies command: | - pip tox coveralls + pip install tox coveralls - run: name: Run tests command: | From 3ce8a9a8287fa5f2adba5faaf48c8b3db02ebc7f Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 19:28:09 -0400 Subject: [PATCH 09/20] Fix Flake8 errors --- accounts/views.py | 7 +++++-- runtests.py | 1 - tests/test_backends.py | 2 +- tests/test_models.py | 13 ------------- tests/test_views.py | 5 +++-- 5 files changed, 9 insertions(+), 19 deletions(-) delete mode 100644 tests/test_models.py diff --git a/accounts/views.py b/accounts/views.py index 017bd47..7a56f52 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,6 +1,7 @@ from requests_oauthlib import OAuth2Session from django.contrib import auth from django.http import HttpResponseServerError +from django.http.response import HttpResponseBadRequest from django.shortcuts import redirect from django.views import View from accounts.settings import accounts_settings @@ -8,7 +9,10 @@ class LoginView(View): def get(self, request): - request.session.__setitem__('next', request.GET.get('next')) + return_to = request.GET.get('next') + if not return_to: + return HttpResponseBadRequest("Invalid next parameter") + request.session.__setitem__('next', return_to) if not request.user.is_authenticated: platform = OAuth2Session( accounts_settings.CLIENT_ID, @@ -26,7 +30,6 @@ def get(self, request): class CallbackView(View): def get(self, request): - code = request.GET.get('code') state = request.session.pop('state') platform = OAuth2Session(accounts_settings.CLIENT_ID, state=state) token = platform.fetch_token( diff --git a/runtests.py b/runtests.py index 1800ce6..305f9ea 100755 --- a/runtests.py +++ b/runtests.py @@ -1,6 +1,5 @@ import sys import django -from django.conf import settings from django.test.runner import DiscoverRunner django.setup() diff --git a/tests/test_backends.py b/tests/test_backends.py index 0bdb420..d18d524 100644 --- a/tests/test_backends.py +++ b/tests/test_backends.py @@ -12,7 +12,7 @@ def test_invalid_remote_user(self): self.assertIsNone(user) def test_create_user(self): - user = auth.authenticate(remote_user='00000000000000000000000000000001') + auth.authenticate(remote_user='00000000000000000000000000000001') self.assertEqual(len(self.User.objects.all()), 1) self.assertEqual(str(self.User.objects.all()[0].uuid), '00000000-0000-0000-0000-000000000001') self.assertEqual(str(self.User.objects.all()[0]), '00000000000000000000000000000001') diff --git a/tests/test_models.py b/tests/test_models.py deleted file mode 100644 index faf8ef4..0000000 --- a/tests/test_models.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.test import TestCase -from django.contrib.auth.models import User - -# TODO test createsuperuser and create user methods -# class ModelTestCase(TestCase): -# def setUp(self): -# self.user = User.objects.create_user(username='student', password='secret') - -# def test_str(self): -# self.assertEqual(str(self.user.student), self.user.username) - -# def test_uuid(self): -# self.assertEquals(self.user.student.get_uuid(), str(self.user.student.uuid)) diff --git a/tests/test_views.py b/tests/test_views.py index e213faf..880c1f8 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -13,9 +13,10 @@ def setUp(self): def test_invalid_next(self): response = self.client.get(reverse('accounts:login')) + self.assertEqual(response.status_code, 400) def test_authenticated_user(self): - student = self.User.objects.create_user( + self.User.objects.create_user( username='00000000000000000000000000000001', uuid='00000000000000000000000000000001', password='secret' @@ -55,7 +56,7 @@ def test_active_user(self, mock_fetch_token, mock_get): self.assertRedirects(response, self.redirect, fetch_redirect_response=False) def test_inactive_user(self, mock_fetch_token, mock_get): - student = self.User.objects.create_user( + self.User.objects.create_user( username='00000000000000000000000000000001', uuid='00000000000000000000000000000001', password='secret', From 6dd6c090418c9558caff834b87d426f20a57ab8e Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 19:37:20 -0400 Subject: [PATCH 10/20] Fix coverage source --- .coveragerc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index e270c9d..b26106d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -source = labs_accounts \ No newline at end of file +source = accounts \ No newline at end of file From d0735cdb71922e5de1a914b973451beac84b9dc1 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 19:51:24 -0400 Subject: [PATCH 11/20] Add tests --- tests/test_apps.py | 7 +++++++ tests/test_settings.py | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/test_apps.py create mode 100644 tests/test_settings.py diff --git a/tests/test_apps.py b/tests/test_apps.py new file mode 100644 index 0000000..06d639b --- /dev/null +++ b/tests/test_apps.py @@ -0,0 +1,7 @@ +from django.test import TestCase +from accounts.apps import AccountsConfig + + +class AppsTestCase(TestCase): + def test_apps(self): + self.assertEqual(AccountsConfig.name, 'accounts') diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 0000000..fd0e241 --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,15 @@ +from django.test import TestCase +from tests.settings import PLATFORM_ACCOUNTS +from accounts.settings import accounts_settings, DEFAULTS + + +class SettingsTestCase(TestCase): + def test_invalid_setting(self): + with self.assertRaises(AttributeError): + accounts_settings.INVALID_SETTING + + def test_defined_setting(self): + self.assertEqual(accounts_settings.CLIENT_ID, PLATFORM_ACCOUNTS['CLIENT_ID']) + + def test_default_setting(self): + self.assertEqual(accounts_settings.SCOPE, DEFAULTS['SCOPE']) From 4e42a3a4d94afeaec8be54805509362bd1a804d0 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 19:58:47 -0400 Subject: [PATCH 12/20] Add badges to README --- README.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 731c66c..0118247 100644 --- a/README.rst +++ b/README.rst @@ -1,13 +1,19 @@ Django Labs Accounts ==================== - +.. image:: https://img.shields.io/circleci/project/github/pennlabs/django-labs-accounts/master.svg + :target: https://circleci.com/gh/pennlabs/django-labs-accounts +.. image:: https://coveralls.io/repos/github/pennlabs/django-labs-accounts/badge.svg?branch=feature%2Fsettings + :target: https://coveralls.io/github/pennlabs/django-labs-accounts?branch=feature%2Fsettings +.. image:: https://img.shields.io/pypi/v/django-labs-accounts.svg :alt: PyPI + :target: https://pypi.org/project/django-labs-accounts/ + Requirements ------------ Installation ------------ -Install with pip - pip install django-labs-accounts +Install with pipenv + pipenv install django-labs-accounts Add `accounts` to `INSTALLED_APPS` .. code-block:: python From a3ffef0d9b0e8def009e1bc3e4344da280aedf04 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 19:59:56 -0400 Subject: [PATCH 13/20] Fix badges --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 0118247..b3714b3 100644 --- a/README.rst +++ b/README.rst @@ -4,9 +4,9 @@ Django Labs Accounts :target: https://circleci.com/gh/pennlabs/django-labs-accounts .. image:: https://coveralls.io/repos/github/pennlabs/django-labs-accounts/badge.svg?branch=feature%2Fsettings :target: https://coveralls.io/github/pennlabs/django-labs-accounts?branch=feature%2Fsettings -.. image:: https://img.shields.io/pypi/v/django-labs-accounts.svg :alt: PyPI +.. image:: https://img.shields.io/pypi/v/django-labs-accounts.svg :target: https://pypi.org/project/django-labs-accounts/ - + Requirements ------------ From 6d93e55eda95c34f035a891640e4f87a5b87a1ab Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 20:16:32 -0400 Subject: [PATCH 14/20] Add requirements to README --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index b3714b3..6842919 100644 --- a/README.rst +++ b/README.rst @@ -9,6 +9,8 @@ Django Labs Accounts Requirements ------------ +* Python 3.4+ +* Django 2.0+ Installation ------------ From b1e5bf2e7bcfb2ccfd99c32a291230d4aba06a13 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 20:16:49 -0400 Subject: [PATCH 15/20] Fix syntax errors in README --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 6842919..f241c35 100644 --- a/README.rst +++ b/README.rst @@ -18,6 +18,7 @@ Install with pipenv pipenv install django-labs-accounts Add `accounts` to `INSTALLED_APPS` + .. code-block:: python INSTALLED_APPS = ( @@ -26,6 +27,7 @@ Add `accounts` to `INSTALLED_APPS` ) Add the following to `urls.py` + .. code-block:: python urlpatterns = [ From 8a1006049a01a7234caa25893e80f42feafd65ac Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 21:03:50 -0400 Subject: [PATCH 16/20] Update Changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d950ed7..7c4578f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Changelog ========= +0.2.0 (2019-03-24) +------------------ +* New feature: Provide an easier way to access settings through a new `accounts_settings` object + 0.1.0 (2019-03-17) ------------------ * Initial Release \ No newline at end of file From 0361c436e6034efe60992ce6c858a2fb1c9e1a56 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 21:17:07 -0400 Subject: [PATCH 17/20] Modify environment variable prefix --- accounts/settings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/settings.py b/accounts/settings.py index 209d956..138d6ab 100644 --- a/accounts/settings.py +++ b/accounts/settings.py @@ -4,9 +4,9 @@ USER_SETTINGS = getattr(settings, "PLATFORM_ACCOUNTS", {}) DEFAULTS = { - 'CLIENT_ID': os.environ.get('OAUTH2_CLIENT_ID'), - 'CLIENT_SECRET': os.environ.get('OAUTH2_CLIENT_SECRET'), - 'REDIRECT_URI': os.environ.get('OAUTH2_REDIRECT_URI'), + 'CLIENT_ID': os.environ.get('LABS_CLIENT_ID'), + 'CLIENT_SECRET': os.environ.get('LABS_CLIENT_SECRET'), + 'REDIRECT_URI': os.environ.get('LABS_REDIRECT_URI'), 'SCOPE': ['read', 'introspection'], 'PLATFORM_URL': 'https://platform.pennlabs.org', } From a6bbce3fed8702b27ab0d7faff80d575b11e6042 Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 21:17:30 -0400 Subject: [PATCH 18/20] Add documentation to README --- README.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f241c35..cbd6fdc 100644 --- a/README.rst +++ b/README.rst @@ -37,7 +37,29 @@ Add the following to `urls.py` Documentation ------------- -TODO +All settings are handled with a `PLATFORM_ACCOUNTS` dictionary. + +Example: + +.. code-block:: python + + PLATFORM_ACCOUNTS = { + 'CLIENT_ID': 'id', + 'CLIENT_SECRET': 'secret', + 'REDIRECT_URI': 'example', + } + +The available settings are: + +`CLIENT_ID` the client ID to connect to platform with. Defaults to `LABS_CLIENT_ID` environment variable. + +`CLIENT_SECRET` the client secret to connect to platform with. Defaults to `LABS_CLIENT_SECRET` environment variable. + +`REDIRECT_URI` the redirect uri to send to platform. Defaults to `LABS_REDIRECT_URI` environment variable. + +`SCOPE` the scope for this applications tokens. Must include `introspection`. Defaults to `['read', 'introspection']`. + +`PLATFORM_URL` URL of platform server to connect to. Should be `https://platform(-dev).pennlabs.org` (no trailing slash) Changelog --------- From 9870117c538058dc8d68b4c73e4e62326da4664d Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 21:26:09 -0400 Subject: [PATCH 19/20] Fix README formatting --- README.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index cbd6fdc..c5eaa95 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,7 @@ Installation Install with pipenv pipenv install django-labs-accounts -Add `accounts` to `INSTALLED_APPS` +Add ``accounts`` to ``INSTALLED_APPS`` .. code-block:: python @@ -26,7 +26,7 @@ Add `accounts` to `INSTALLED_APPS` 'accounts.apps.AccountsConfig', ) -Add the following to `urls.py` +Add the following to ``urls.py`` .. code-block:: python @@ -37,7 +37,7 @@ Add the following to `urls.py` Documentation ------------- -All settings are handled with a `PLATFORM_ACCOUNTS` dictionary. +All settings are handled with a ``PLATFORM_ACCOUNTS`` dictionary. Example: @@ -51,20 +51,20 @@ Example: The available settings are: -`CLIENT_ID` the client ID to connect to platform with. Defaults to `LABS_CLIENT_ID` environment variable. +``CLIENT_ID`` the client ID to connect to platform with. Defaults to ``LABS_CLIENT_ID`` environment variable. -`CLIENT_SECRET` the client secret to connect to platform with. Defaults to `LABS_CLIENT_SECRET` environment variable. +``CLIENT_SECRET`` the client secret to connect to platform with. Defaults to ``LABS_CLIENT_SECRET`` environment variable. -`REDIRECT_URI` the redirect uri to send to platform. Defaults to `LABS_REDIRECT_URI` environment variable. +``REDIRECT_URI`` the redirect uri to send to platform. Defaults to ``LABS_REDIRECT_URI`` environment variable. -`SCOPE` the scope for this applications tokens. Must include `introspection`. Defaults to `['read', 'introspection']`. +``SCOPE`` the scope for this applications tokens. Must include ``introspection``. Defaults to ``['read', 'introspection']``. -`PLATFORM_URL` URL of platform server to connect to. Should be `https://platform(-dev).pennlabs.org` (no trailing slash) +``PLATFORM_URL`` URL of platform server to connect to. Should be ``https://platform(-dev).pennlabs.org`` (no trailing slash) Changelog --------- -See `CHANGELOG.md `_. +See ``CHANGELOG.md ``_. License ------- -Licensed See `LICENSE.md `_. +Licensed See ``LICENSE.md ``_. From 197bc780dc4fd150be1dd155418c06f918bb540d Mon Sep 17 00:00:00 2001 From: ArmaanT <13340433+ArmaanT@users.noreply.github.com> Date: Sun, 24 Mar 2019 21:27:01 -0400 Subject: [PATCH 20/20] Fix README formatting again --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index c5eaa95..77a6844 100644 --- a/README.rst +++ b/README.rst @@ -63,8 +63,8 @@ The available settings are: Changelog --------- -See ``CHANGELOG.md ``_. +See `CHANGELOG.md `_. License ------- -Licensed See ``LICENSE.md ``_. +Licensed See `LICENSE.md `_.