Skip to content

Commit 175c421

Browse files
Merge branch 'master' into contributors-readme-action-Qh5ssVdXX7
2 parents c993e27 + f03b648 commit 175c421

29 files changed

+1168
-147
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,9 @@ reqs-install:
1515

1616
reqs-install-dev:
1717
pip install -r requirements/requirements.dev.txt --no-index --find-links ./vendor/
18+
19+
build-local:
20+
cd dev-local ; make build-local ; cd ..
21+
22+
run-local:
23+
cd dev-local ; make run-local ; cd ..

apps/authorization/views.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ class Meta:
3232
fields = ('id', 'name', 'logo_uri', 'tos_uri', 'policy_uri', 'contacts')
3333

3434
def get_contacts(self, obj):
35-
print(obj)
3635
application = Application.objects.get(id=obj.id)
3736
return application.support_email or ""
3837

apps/core/management/commands/create_test_feature_switches.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def handle(self, *args, **options):
3434
for switch in WAFFLE_FEATURE_SWITCHES:
3535
try:
3636
Switch.objects.get(name=switch[0])
37-
self._log("Feature switch already exists: %s" % (str(switch)))
3837
except Switch.DoesNotExist:
3938
Switch.objects.create(name=switch[0], active=switch[1], note=switch[2])
4039
self._log("Feature switch created: %s" % (str(switch)))
@@ -46,7 +45,6 @@ def handle(self, *args, **options):
4645

4746
try:
4847
flag_obj = Flag.objects.get(name=flag[0])
49-
self._log("Feature flag already exists: %s" % (str(flag_obj)))
5048
except Flag.DoesNotExist:
5149
flag_obj = Flag.objects.create(name=flag[0])
5250
self._log("Feature flag created: %s" % (str(flag[0])))
@@ -62,7 +60,6 @@ def handle(self, *args, **options):
6260
flag_obj.save()
6361
self._log("User {} added to feature flag: {}".format(u, flag))
6462
except Exception as e:
65-
print(e)
6663
self._log("Exception when adding user {} to feature flag: {}".format(u, flag))
6764
except User.DoesNotExist:
6865
# assuming test users exist before creating flags associated with them

apps/dot_ext/tests/test_views.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
SCOPES_TO_URL_BASE_PATH,
2525
)
2626

27+
import os
28+
2729
from hhs_oauth_server.settings.base import MOCK_FHIR_ENDPOINT_HOSTNAME
2830

2931

@@ -576,16 +578,15 @@ def test_delete_token_success(self):
576578

577579
# This assertion is incorrectly crafted - it actually requires a local server started
578580
# so that the fhir fetch data is called and hence generate cert file not found error.
579-
# TODO: refactor test to not depend on a server up and running.
580-
581-
# Post Django 2.2: An OSError exception is expected when trying to reach the
582-
# backend FHIR server and proves authentication worked.
583-
with self.assertRaisesRegexp(
584-
OSError, 'Could not find the TLS certificate file'
585-
):
586-
response = self.client.get(
587-
'/v1/fhir/Patient', headers={'authorization': 'Bearer ' + anna_token.token}
588-
)
581+
# 20251120 This test is now gated on a variable; if the variable does not exist, or
582+
# is not set, the test will run. This is the desired behavior.
583+
if os.getenv("RUNNING_IN_LOCAL_STACK", None) != "true":
584+
with self.assertRaisesRegexp(
585+
OSError, 'Could not find the TLS certificate file'
586+
):
587+
response = self.client.get(
588+
'/v1/fhir/Patient', headers={'authorization': 'Bearer ' + anna_token.token}
589+
)
589590

590591
bob_tkn = self._create_test_token(bob, bob_application)
591592
self.assertTrue(
@@ -638,24 +639,26 @@ def test_delete_token_success(self):
638639

639640
# Post Django 2.2: An OSError exception is expected when trying to reach the
640641
# backend FHIR server and proves authentication worked.
641-
with self.assertRaisesRegexp(
642-
OSError, 'Could not find the TLS certificate file'
643-
):
644-
response = self.client.get(
645-
'/v1/fhir/Patient', headers={'authorization': 'Bearer ' + bob_tkn.token}
646-
)
642+
if os.getenv("RUNNING_IN_LOCAL_STACK", None) != "true":
643+
with self.assertRaisesRegexp(
644+
OSError, 'Could not find the TLS certificate file'
645+
):
646+
response = self.client.get(
647+
'/v1/fhir/Patient', headers={'authorization': 'Bearer ' + bob_tkn.token}
648+
)
647649

648650
next_tkn = self._create_test_token(anna, anna_application)
649651

650652
# Post Django 2.2: An OSError exception is expected when trying to reach the
651653
# backend FHIR server and proves authentication worked.
652-
with self.assertRaisesRegexp(
653-
OSError, 'Could not find the TLS certificate file'
654-
):
655-
response = self.client.get(
656-
'/v1/fhir/Patient',
657-
headers={'authorization': 'Bearer ' + next_tkn.token},
658-
)
654+
if os.getenv("RUNNING_IN_LOCAL_STACK", None) != "true":
655+
with self.assertRaisesRegexp(
656+
OSError, 'Could not find the TLS certificate file'
657+
):
658+
response = self.client.get(
659+
'/v1/fhir/Patient',
660+
headers={'authorization': 'Bearer ' + next_tkn.token},
661+
)
659662

660663
# self.assertEqual(next_tkn.token, tkn.token)
661664
self.assertTrue(

apps/fhir/bluebutton/tests/test_wellknown_endpoints.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,10 @@ def test_smart_configuration_missing_fields_in_v3(self):
147147
# is commented above for reference.
148148

149149
@skipIf((not settings.RUN_ONLINE_TESTS), "Can't reach external sites.")
150-
# This overrides the switch and sets it to true, always.
151-
# We should only run the test if we have v3 enabled.
152150
@override_switch('v3_endpoints', active=True)
153151
def test_fhir_metadata_extensions_have_v3(self):
154-
response = self.client.get(f'{BASEURL}/v3/fhir/metadata')
152+
the_url = f'{BASEURL}/v3/fhir/metadata'
153+
response = self.client.get(the_url)
155154
self.assertEqual(response.status_code, 200)
156155
json = response.json()
157156
self.assertIn('v3', json['implementation']['url'])

apps/testclient/management/commands/create_test_user_and_application.py

Lines changed: 93 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@
1212
from datetime import timedelta, datetime
1313
from django.conf import settings
1414
from apps.authorization.models import update_grants
15+
from apps.authorization.models import ArchivedDataAccessGrant, DataAccessGrant
1516

17+
# Imports for quieting things during startup.
18+
from waffle.models import Switch
19+
20+
from uuid import uuid4
1621

17-
def create_group(name="BlueButton"):
1822

23+
def create_group(name="BlueButton"):
1924
g, created = Group.objects.get_or_create(name=name)
2025
if created:
2126
print("%s group created" % (name))
@@ -24,42 +29,29 @@ def create_group(name="BlueButton"):
2429
return g
2530

2631

27-
def create_user(group, usr):
28-
u_name = "fred"
29-
first_name = "Fred"
30-
last_name = "Flinstone"
31-
32-
password = "foobarfoobarfoobar"
32+
def create_user(the_group):
33+
username = "rogersf"
34+
first_name = "Fred"
35+
last_name = "Rogers"
36+
37+
password = uuid4()
3338
user_type = "BEN"
34-
35-
if usr is not None:
36-
u_name = usr
37-
first_name = "{}{}".format(usr, "First")
38-
last_name = "{}{}".format(usr, "Last")
39-
email = "{}.{}@example.com".format(first_name, last_name)
40-
user_type = "DEV"
41-
42-
43-
if User.objects.filter(username=u_name).exists():
44-
User.objects.filter(username=u_name).delete()
45-
46-
u = None
47-
48-
if usr is not None:
49-
u = User.objects.create_user(username=u_name,
50-
first_name=first_name,
51-
last_name=last_name,
52-
email=email)
53-
u.set_unusable_password()
54-
else:
55-
# create a sample user 'fred' for dev local that has a usable password
56-
u = User.objects.create_user(username=u_name,
57-
first_name=first_name,
58-
last_name=last_name,
59-
email=email,
60-
password=password,)
61-
62-
UserProfile.objects.create(user=u,
39+
40+
# We will do this over-and-over.
41+
# If we don't already exist, then create the user.
42+
if User.objects.filter(username=username).exists():
43+
print(f"👟 {username} already exists. Skipping test user creation.")
44+
return User.objects.get(username=username)
45+
46+
# If the user didn't exist, it is our first time through.
47+
# Create the user.
48+
user_obj = User.objects.create(username=username,
49+
first_name=first_name,
50+
last_name=last_name,
51+
email=email,
52+
password=password,)
53+
user_obj.set_unusable_password()
54+
UserProfile.objects.create(user=user_obj,
6355
user_type=user_type,
6456
create_applications=True,
6557
password_reset_question_1='1',
@@ -68,33 +60,35 @@ def create_user(group, usr):
6860
password_reset_answer_2='Frank',
6961
password_reset_question_3='3',
7062
password_reset_answer_3='Bentley')
63+
user_obj.groups.add(the_group)
7164

72-
u.groups.add(group)
65+
# CROSSWALK
66+
# Removing any existing crosswalks for this artificial user.
67+
# Why? Just in case.
68+
user_id_hash = "ee78989d1d9ba0b98f3cfbd52479f10c7631679c17563186f70fbef038cc9536"
69+
Crosswalk.objects.filter(_user_id_hash=user_id_hash).delete()
70+
Crosswalk.objects.get_or_create(user=user_obj,
71+
fhir_id_v2=settings.DEFAULT_SAMPLE_FHIR_ID_V2,
72+
_user_id_hash=user_id_hash)
73+
return user_obj
7374

74-
if usr is None:
75-
c, g_o_c = Crosswalk.objects.get_or_create(user=u,
76-
fhir_id_v2=settings.DEFAULT_SAMPLE_FHIR_ID_V2,
77-
_user_id_hash="ee78989d1d9ba0b98f3cfbd52479f10c7631679c17563186f70fbef038cc9536")
78-
return u
7975

76+
def create_application(user):
77+
app_name = "TestApp"
78+
if Application.objects.filter(name=app_name).exists():
79+
return Application.objects.get(name=app_name)
80+
81+
# If the app doesn't exist, create the test app.
8082

81-
def create_application(user, group, app, redirect):
82-
app_name = "TestApp" if app is None else app
8383
Application.objects.filter(name=app_name).delete()
8484
redirect_uri = "{}{}".format(settings.HOSTNAME_URL, settings.TESTCLIENT_REDIRECT_URI)
8585

86-
if redirect:
87-
redirect_uri = redirect
88-
89-
if not(redirect_uri.startswith("http://") or redirect_uri.startswith("https://")):
90-
redirect_uri = "https://" + redirect_uri
91-
92-
a = Application.objects.create(name=app_name,
93-
redirect_uris=redirect_uri,
94-
user=user,
95-
data_access_type="THIRTEEN_MONTH",
96-
client_type="confidential",
97-
authorization_grant_type="authorization-code")
86+
the_app = Application.objects.create(name=app_name,
87+
redirect_uris=redirect_uri,
88+
user=user,
89+
data_access_type="THIRTEEN_MONTH",
90+
client_type="confidential",
91+
authorization_grant_type="authorization-code",)
9892

9993
titles = ["My Medicare and supplemental coverage information.",
10094
"My Medicare claim information.",
@@ -104,49 +98,64 @@ def create_application(user, group, app, redirect):
10498

10599
for t in titles:
106100
c = ProtectedCapability.objects.get(title=t)
107-
a.scope.add(c)
108-
return a
101+
the_app.scope.add(c)
102+
103+
return the_app
109104

110105

111-
def create_test_token(user, application):
106+
def create_test_token(the_user, the_app):
112107

108+
# Set expiration one day from now.
113109
now = timezone.now()
114110
expires = now + timedelta(days=1)
115111

116-
scopes = application.scope.all()
112+
scopes = the_app.scope.all()
117113
scope = []
118114
for s in scopes:
119115
scope.append(s.slug)
120116

121-
t = AccessToken.objects.create(user=user, application=application,
117+
# We have to have a tokent with token="sample-token-string", because we
118+
# rely on it existing for unit tests. Which are actually integration tests.
119+
if AccessToken.objects.filter(token="sample-token-string").exists():
120+
t = AccessToken.objects.get(token="sample-token-string")
121+
t.expires = expires
122+
t.save()
123+
else:
124+
AccessToken.objects.create(user=the_user,
125+
application=the_app,
126+
# This needs to be "sample-token-string", because
127+
# we have tests that rely on it.
122128
token="sample-token-string",
123129
expires=expires,
124-
scope=' '.join(scope))
125-
return t
130+
scope=' '.join(scope),)
131+
132+
133+
def get_switch(name):
134+
try:
135+
sw = Switch.objects.get(name=name)
136+
return sw.active
137+
except Exception as e:
138+
print(f"Could not get switch {name}: {e}")
139+
140+
141+
def set_switch(name, b):
142+
sw, _ = Switch.objects.get_or_create(name=name)
143+
sw.active = b
144+
sw.save()
126145

127146

128147
class Command(BaseCommand):
129148
help = 'Create a test user and application for the test client'
130149

131-
def add_arguments(self, parser):
132-
parser.add_argument("-u", "--user", help="Name of the user to be created (unique).")
133-
parser.add_argument("-a", "--app", help="Name of the application to be created (unique).")
134-
parser.add_argument("-r", "--redirect", help="Redirect url of the application.")
135-
136150
def handle(self, *args, **options):
137-
usr = options["user"]
138-
app = options["app"]
139-
redirect = options["redirect"]
140-
141-
g = create_group()
142-
u = create_user(g, usr)
143-
a = create_application(u, g, app, redirect)
144-
t = None
145-
if usr is None and app is None:
146-
t = create_test_token(u, a)
147-
update_grants()
148-
print("Name:", a.name)
149-
print("client_id:", a.client_id)
150-
print("client_secret:", a.client_secret)
151-
print("access_token:", t.token if t else "None")
152-
print("redirect_uri:", a.redirect_uris)
151+
152+
set_switch('outreach_email', False)
153+
154+
the_group = create_group()
155+
the_user = create_user(the_group)
156+
the_app = create_application(the_user)
157+
create_test_token(the_user, the_app)
158+
update_grants()
159+
160+
# Restore switch to whatever it was.
161+
set_switch('outreach_email', True)

0 commit comments

Comments
 (0)