Skip to content

Commit

Permalink
Merge pull request #210 from UW-GAC/main
Browse files Browse the repository at this point in the history
Deploying acm v0.13
  • Loading branch information
jmcarson authored Mar 9, 2023
2 parents 8cc6fc7 + b019b8f commit 9fbfb98
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 31 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
pip install -r requirements/local.txt
- name: Run tests
run: coverage run -p ./manage.py test --settings=config.settings.test
run: coverage run -p -m pytest
env:
# We can set this to an empty string, since we'll never make an API call.
ANVIL_API_SERVICE_ACCOUNT_FILE: foo
Expand Down Expand Up @@ -117,7 +117,7 @@ jobs:
pip install -r requirements/local.txt
- name: Run tests
run: coverage run -p ./manage.py test --settings=config.settings.test
run: coverage run -p -m pytest
env:
# We can set this to an empty string, since we'll never make an API call.
ANVIL_API_SERVICE_ACCOUNT_FILE: foo
Expand Down
9 changes: 2 additions & 7 deletions gregor_django/drupal_oauth_provider/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,9 @@ def get_provider_scope_config(self):
provider_settings = app_settings.PROVIDERS.get(self.id, {})
gregor_oauth_scopes = provider_settings.get("SCOPES")

if not gregor_oauth_scopes:
if not gregor_oauth_scopes or not isinstance(gregor_oauth_scopes, list):
raise ImproperlyConfigured(
f"[get_provider_scope_config] missing provider setting SCOPES {provider_settings}"
)

if not isinstance(gregor_oauth_scopes, list):
raise ImproperlyConfigured(
"[get_provider_scope_config] provider setting SCOPES should be a list"
f"[get_provider_scope_config] provider setting SCOPES {provider_settings} must be a list"
)

return gregor_oauth_scopes
Expand Down
45 changes: 45 additions & 0 deletions gregor_django/drupal_oauth_provider/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
from allauth.socialaccount.adapter import get_adapter
from allauth.socialaccount.tests import OAuth2TestsMixin
from allauth.tests import MockedResponse, TestCase
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.test import RequestFactory
from django.test.utils import override_settings

from .provider import CustomProvider
Expand Down Expand Up @@ -125,3 +128,45 @@ def get_login_response_json(self, with_refresh_token=True):
if with_refresh_token:
response_data["refresh_token"] = "testrf"
return json.dumps(response_data)


class TestProviderConfig(TestCase):
def test_custom_provider_scope_config(self):
custom_provider_settings = settings.SOCIALACCOUNT_PROVIDERS
rf = RequestFactory()
request = rf.get("/fake-url/")
custom_provider_settings["drupal_oauth_provider"]["SCOPES"] = None
with override_settings(SOCIALACCOUNT_PROVIDERS=custom_provider_settings):
with self.assertRaises(ImproperlyConfigured):
CustomProvider(request).get_provider_scope_config()

def test_custom_provider_scope_detail_config(self):
custom_provider_settings = settings.SOCIALACCOUNT_PROVIDERS
rf = RequestFactory()
request = rf.get("/fake-url/")
custom_provider_settings["drupal_oauth_provider"]["SCOPES"] = [
{
"z_drupal_machine_name": "X",
"request_scope": True,
"django_group_name": "Z",
}
]
with override_settings(SOCIALACCOUNT_PROVIDERS=custom_provider_settings):
with self.assertRaises(ImproperlyConfigured):
CustomProvider(request).get_provider_managed_scope_status()

def test_custom_provider_has_scope(self):
custom_provider_settings = settings.SOCIALACCOUNT_PROVIDERS
rf = RequestFactory()
request = rf.get("/fake-url/")
custom_provider_settings["drupal_oauth_provider"]["SCOPES"] = [
{
"drupal_machine_name": "X",
"request_scope": True,
"django_group_name": "Z",
}
]
with override_settings(SOCIALACCOUNT_PROVIDERS=custom_provider_settings):
CustomProvider(request).get_provider_managed_scope_status(
scopes_granted=["X"]
)
6 changes: 0 additions & 6 deletions gregor_django/drupal_oauth_provider/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ def _get_public_key_jwk(self, headers):

def get_public_key(self, headers):

provider_settings = app_settings.PROVIDERS.get(self.provider_id, {})

config_public_key = provider_settings.get("PUBLIC_KEY")
if False and config_public_key:
return config_public_key

public_key_jwk = self._get_public_key_jwk(headers)
try:
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(
Expand Down
18 changes: 18 additions & 0 deletions gregor_django/gregor_anvil/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from django.test import RequestFactory, TestCase
from django.urls import reverse

from gregor_django.users.tests.factories import UserFactory

from .. import models, tables, views
from . import factories

Expand Down Expand Up @@ -282,6 +284,22 @@ def test_view_status_code_with_invalid_pk(self):
with self.assertRaises(Http404):
self.get_view()(request, pk=obj.pk + 1)

def test_site_user_table(self):
"""Contains a table of site users with the correct users."""
obj = self.model_factory.create()
site_user = UserFactory.create()
site_user.research_centers.set([obj])
non_site_user = UserFactory.create()

self.client.force_login(self.user)
response = self.client.get(self.get_url(obj.pk))
self.assertIn("site_user_table", response.context_data)
table = response.context_data["site_user_table"]
self.assertEqual(len(table.rows), 1)

self.assertIn(site_user, table.data)
self.assertNotIn(non_site_user, table.data)


class ResearchCenterListTest(TestCase):
"""Tests for the ResearchCenterList view."""
Expand Down
15 changes: 13 additions & 2 deletions gregor_django/gregor_anvil/views.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from anvil_consortium_manager.auth import AnVILConsortiumManagerViewRequired
from anvil_consortium_manager.models import Account, Workspace
from dal import autocomplete
from django.contrib.auth import get_user_model
from django.db.models import Count, Q
from django.views.generic import DetailView, TemplateView
from django_tables2 import SingleTableView
from django_tables2 import SingleTableMixin, SingleTableView

from gregor_django.users.tables import UserTable

from . import models, tables

User = get_user_model()


class ConsentGroupDetail(AnVILConsortiumManagerViewRequired, DetailView):
"""View to show details about a `ConsentGroups`."""
Expand All @@ -21,10 +26,16 @@ class ConsentGroupList(AnVILConsortiumManagerViewRequired, SingleTableView):
table_class = tables.ConsentGroupTable


class ResearchCenterDetail(AnVILConsortiumManagerViewRequired, DetailView):
class ResearchCenterDetail(
AnVILConsortiumManagerViewRequired, SingleTableMixin, DetailView
):
"""View to show details about a `ResearchCenter`."""

model = models.ResearchCenter
context_table_name = "site_user_table"

def get_table(self):
return UserTable(User.objects.filter(research_centers=self.object))


class ResearchCenterList(AnVILConsortiumManagerViewRequired, SingleTableView):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends "anvil_consortium_manager/__object_detail.html" %}
{% load render_table from django_tables2 %}

{% block title %}Research Center: {{ object.short_name }}{% endblock %}

Expand All @@ -8,3 +9,9 @@
<li>Short name: {{ object.short_name }}</li>
</ul>
{% endblock panel %}

{% block after_panel %}
<h3>Research Center Users</h3>
{% render_table site_user_table %}
<p class='alert alert-warning'>Research center user list only contains those site users who have created an account on this website.</p>
{% endblock after_panel %}
5 changes: 1 addition & 4 deletions gregor_django/users/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,4 @@ class UsersConfig(AppConfig):
verbose_name = _("Users")

def ready(self):
try:
import gregor_django.users.signals # noqa F401
except ImportError:
pass
import gregor_django.users.signals # noqa F401
15 changes: 15 additions & 0 deletions gregor_django/users/tables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import django_tables2 as tables
from django.contrib.auth import get_user_model

User = get_user_model()


class UserTable(tables.Table):
"""A table for `User`s."""

username = tables.columns.Column(linkify=True)
research_centers = tables.columns.ManyToManyColumn(linkify_item=True)

class Meta:
model = User
fields = ("username", "name", "email", "research_centers")
24 changes: 24 additions & 0 deletions gregor_django/users/tests/test_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ def test_update_research_centers_malformed(self):
user, dict(research_center_or_site="FOO")
)

def test_update_user_research_centers_uknown(self):
adapter = SocialAccountAdapter()
user = UserFactory()
adapter.update_user_research_centers(
user, dict(research_center_or_site=["UNKNOWN"])
)
assert user.research_centers.all().count() == 0

def test_update_user_groups_add(self):
adapter = SocialAccountAdapter()
rc1 = GroupFactory(name="g1")
Expand All @@ -126,6 +134,22 @@ def test_update_user_groups_add(self):
assert user.groups.filter(pk=rc1.pk).exists()
assert user.groups.all().count() == 1

def test_update_user_groups_create(self):
adapter = SocialAccountAdapter()

User = get_user_model()
user = User()
setattr(user, account_settings.USER_MODEL_USERNAME_FIELD, "test")
setattr(user, account_settings.USER_MODEL_EMAIL_FIELD, "[email protected]")

user.save()

adapter.update_user_groups(
user, extra_data=dict(managed_scope_status={"CREATE_GROUP": True})
)
assert user.groups.filter(name="CREATE_GROUP").exists()
assert user.groups.all().count() == 1

def test_update_user_groups_remove(self):
adapter = SocialAccountAdapter()
rc1 = GroupFactory(name="g1")
Expand Down
25 changes: 17 additions & 8 deletions gregor_django/users/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sessions.middleware import SessionMiddleware
Expand All @@ -9,11 +10,11 @@
from django.urls import reverse

from gregor_django.users.forms import UserChangeForm
from gregor_django.users.models import User
from gregor_django.users.tests.factories import UserFactory
from gregor_django.users.views import UserRedirectView, UserUpdateView, user_detail_view

pytestmark = pytest.mark.django_db
pytestmark = pytest.mark.django_db(transaction=True)

User = get_user_model()


class TestUserUpdateView:
Expand All @@ -25,7 +26,7 @@ class TestUserUpdateView:
https://github.com/pytest-dev/pytest-django/pull/258
"""

def dummy_get_response(self, request: HttpRequest):
def dummy_get_response(self, request: HttpRequest): # pragma: no cover
return None

def test_get_success_url(self, user: User, rf: RequestFactory):
Expand All @@ -46,6 +47,14 @@ def test_get_object(self, user: User, rf: RequestFactory):

assert view.get_object() == user

def test_user_update_view(self, client, user: User, rf: RequestFactory):

client.force_login(user)
user_detail_url = reverse("users:update")
response = client.get(user_detail_url)

assert response.status_code == 200

def test_form_valid(self, user: User, rf: RequestFactory):
view = UserUpdateView()
request = rf.get("/fake-url/")
Expand Down Expand Up @@ -78,11 +87,11 @@ def test_get_redirect_url(self, user: User, rf: RequestFactory):


class TestUserDetailView:
def test_authenticated(self, user: User, rf: RequestFactory):
request = rf.get("/fake-url/")
request.user = UserFactory()
def test_authenticated(self, client, user: User, rf: RequestFactory):

response = user_detail_view(request, username=user.username)
client.force_login(user)
user_detail_url = reverse("users:detail", kwargs=dict(username=user.username))
response = client.get(user_detail_url)

assert response.status_code == 200

Expand Down
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ django-dbbackup==4.0.1 # https://github.com/jazzband/django-dbbackup
django-extensions==3.2.1 # https://github.com/django-extensions/django-extensions

# anvil_consortium_manager
git+https://github.com/UW-GAC/django-anvil-consortium-manager.git@v0.12.1
git+https://github.com/UW-GAC/django-anvil-consortium-manager.git@v0.13

# Simple history - model history tracking
django-simple-history==3.1.1 # For tracking history
Expand Down
2 changes: 1 addition & 1 deletion requirements/local.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mypy==0.942 # https://github.com/python/mypy
django-stubs==1.10.1 # https://github.com/typeddjango/django-stubs
types-requests==2.27.25
pytest==7.2.0 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.4 # https://github.com/Frozenball/pytest-sugar
pytest-sugar==0.9.6 # https://github.com/Frozenball/pytest-sugar
responses==0.21.0 # https://github.com/getsentry/responses - for mocking HTTP responses

# Documentation
Expand Down

0 comments on commit 9fbfb98

Please sign in to comment.