55
66import apps .logging .request_logger as logging
77
8- from datetime import datetime , timedelta
8+ from datetime import datetime , timedelta , timezone
99from os import listdir
1010from random import randint , randrange , choice , sample
1111from django .contrib .auth .models import Group
1515from django .conf import settings
1616from django .utils import timezone
1717from oauth2_provider .models import AccessToken , RefreshToken
18+ from tqdm import tqdm
1819
1920from apps .accounts .models import UserProfile
2021from apps .fhir .bluebutton .models import Crosswalk
3435 'capability-a' , 'capability-b' ]
3536APPLICATION_SCOPES_NON_DEMOGRAPHIC = ['patient/ExplanationOfBenefit.read' ,
3637 'patient/Coverage.read' , 'capability-a' , 'capability-b' ]
37- DEFAULT_BENE_COUNT = 100
38+
39+ # Keep up with prod count
40+ DEFAULT_BENE_COUNT = 675000
3841DEFAULT_DEV_COUNT = 150
3942DEFAULT_MAX_APPS_PER_DEV = 5
4043
@@ -60,92 +63,114 @@ def get_first_available_number(firstname):
6063 return int (begin ) + 1
6164
6265def create_dev_users_apps_and_bene_crosswalks (
63- group ,
6466 bene_count ,
6567 dev_count ,
6668 app_max ,
6769 refresh_count ,
6870 archived_tokens ,
69- archived_grants
71+ archived_grants ,
72+ auto_generate
7073):
71- #
72- # generate dev users dev0001, dev0002, dev0003 etc, with password, email, security questions, etc.
73- # Counts are based on the inputs, but if undefined,will default to the defaults defined above
74- # each dev user can have 1 to many applications: dev0001-app01, dev0001-app02
75- # generate crosswalk bene users with FHIR-ID. HICN-HASH, MBI-HASH etc
76- #
77-
78- # effectively turn off logging
74+ """Creates bene and dev users, associated apps, and crosswalks for testing
75+
76+ Args:
77+ bene_count (_type_): _description_
78+ dev_count (_type_): _description_
79+ app_max (_type_): _description_
80+ refresh_count (_type_): _description_
81+ archived_tokens (_type_): _description_
82+ archived_grants (_type_): _description_
83+ auto_generate (_type_): _description_
84+ """
7985 mymedicare_cb_logger .setLevel (logging .CRITICAL )
8086 outreach_logger .setLevel (logging .CRITICAL )
8187
88+ group = create_group ()
8289 bene_pk_list = []
83- files = [ f for f in listdir ( './synthetic-data' ) if re . match ( r'synthetic-beneficiary-.*\.rif' , f )]
90+
8491 count = 0
8592 file_cnt = 0
8693 synthetic_bene_cnt = 0
8794 begin_number = get_first_available_number ('bene' )
88-
89- for f in files :
90- print ('file={}' .format (f ))
91- bene_rif = open ('./synthetic-data/{}' .format (f ), 'r' )
92- while True :
93- if count == bene_count :
94- break
95- line = bene_rif .readline ()
96- if not line :
95+ if auto_generate :
96+ for i in tqdm (range (bene_count )):
97+ id = str (i ).zfill (10 )
98+ fn = f'FN{ id } '
99+ ln = f'LN{ id } '
100+ fhir_id = f'-{ id } '
101+ args = {
102+ 'username' : str (uuid .uuid4 ()),
103+ 'user_hicn_hash' : hash_hicn (id ),
104+ 'user_mbi' : f'MBI{ id } ' ,
105+ 'user_id_type' : 'H' ,
106+ 'fhir_id_v2' : fhir_id ,
107+ 'first_name' : fn ,
108+ 'last_name' : ln ,
109+ 'email' : f'{ fn } .{ ln } @xyz.com'
110+ }
111+ slsx_client = OAuth2ConfigSLSx (args )
112+ user = create_beneficiary_record (slsx_client , fhir_id )
113+ bene_pk_list .append (user .pk )
114+ else :
115+ files = [f for f in listdir ('./synthetic-data' ) if re .match (r'synthetic-beneficiary-.*\.rif' , f )]
116+ for f in files :
117+ print ('file={}' .format (f ))
118+ bene_rif = open ('./synthetic-data/{}' .format (f ), 'r' )
119+ while True :
120+ if count == bene_count :
121+ break
122+ line = bene_rif .readline ()
123+ if not line :
124+ break
125+ if line .startswith ('DML_IND|BENE_ID' ):
126+ continue
127+ else :
128+ flds = line .split ('|' )
129+ fhir_id = flds [1 ]
130+ mbi = flds [14 ]
131+ hicn = flds [18 ]
132+ fn = f'bene{ count + begin_number } '
133+ ln = f'user{ count + begin_number } '
134+
135+ # skip fred
136+ if fhir_id != '-20140000008325' :
137+ args = {
138+ 'username' : str (uuid .uuid1 ()),
139+ 'user_hicn_hash' : hash_hicn (hicn ),
140+ 'user_mbi' : mbi ,
141+ 'user_id_type' : 'H' ,
142+ 'fhir_id_v2' : fhir_id ,
143+ 'first_name' : fn ,
144+ 'last_name' : ln ,
145+ 'email' : fn + '.' + ln + '@xyz.net' ,
146+ }
147+ slsx_client = OAuth2ConfigSLSx (args )
148+ try :
149+ u = create_beneficiary_record (slsx_client , fhir_id )
150+ date_picked = datetime .now (timezone .utc ) - timedelta (days = randrange (700 ))
151+ u .date_joined = date_picked .replace (tzinfo = pytz .utc )
152+ u .save ()
153+ c = Crosswalk .objects .get (user = u )
154+ c .created = u .date_joined
155+ c .save ()
156+ bene_pk_list .append (u .pk )
157+ synthetic_bene_cnt += 1
158+ count += 1
159+ except ValidationError :
160+ # If there is something wrong during 'create_beneficiary_record'
161+ # i.e. 'user already exists', just try the next .rif record
162+ continue
163+ bene_rif .close ()
164+ file_cnt += 1
165+ print ('RIF file processed = {}, synthetic bene generated = {}' .format (file_cnt , synthetic_bene_cnt ))
166+ if file_cnt >= 1 :
97167 break
98- if line .startswith ('DML_IND|BENE_ID' ):
99- continue
100- else :
101- flds = line .split ('|' )
102- fhir_id = flds [1 ]
103- mbi = flds [14 ]
104- hicn = flds [18 ]
105- fn = 'bene{}' .format (count + begin_number )
106- ln = 'user{}' .format (count + begin_number )
107-
108- # skip fred
109- if fhir_id != '-20140000008325' :
110- args = {
111- 'username' : str (uuid .uuid1 ()),
112- 'user_hicn_hash' : hash_hicn (hicn ),
113- 'user_mbi' : mbi ,
114- 'user_id_type' : 'H' ,
115- 'fhir_id_v2' : fhir_id ,
116- 'first_name' : fn ,
117- 'last_name' : ln ,
118- 'email' : fn + '.' + ln + '@xyz.net' ,
119- }
120- slsx_client = OAuth2ConfigSLSx (args )
121- try :
122- u = create_beneficiary_record (slsx_client , fhir_id )
123- date_picked = datetime .utcnow () - timedelta (days = randrange (700 ))
124- u .date_joined = date_picked .replace (tzinfo = pytz .utc )
125- u .save ()
126- c = Crosswalk .objects .get (user = u )
127- c .created = u .date_joined
128- c .save ()
129- bene_pk_list .append (u .pk )
130- synthetic_bene_cnt += 1
131- count += 1
132- print ('.' , end = '' , flush = True )
133- time .sleep (.05 )
134- except ValidationError :
135- # If there is something wrong during 'create_beneficiary_record'
136- # i.e. 'user already exists', just try the next .rif record
137- continue
138- bene_rif .close ()
139- file_cnt += 1
140- print ('RIF file processed = {}, synthetic bene generated = {}' .format (file_cnt , synthetic_bene_cnt ))
141- if file_cnt >= 1 :
142- break
143168
144169 # create dev users according dev-count parameter, default to 100
145170 # generate access tokens + refresh tokens + archived tokens for random picked benes for each app
146171 app_index = 0
147172 begin_number = get_first_available_number ('DevUserFN' )
148- for i in range (dev_count ):
173+ for i in tqdm ( range (dev_count ) ):
149174 dev_u_fn = 'DevUserFN{}' .format (i + begin_number )
150175 dev_u_ln = 'DevUserLN{}' .format (i + begin_number )
151176 u = User .objects .create_user (username = '{}.{}' .format (dev_u_fn , dev_u_ln ),
@@ -166,7 +191,6 @@ def create_dev_users_apps_and_bene_crosswalks(
166191 u .groups .add (group )
167192 # apps per DEV user
168193 app_cnt = randint (1 , app_max ) if app_max > 0 else 0
169- print ('>>>>generating apps for user={}' .format (u .username ))
170194 for i in range (app_cnt ):
171195 app_index += 1
172196 app_name = 'app{}_{}' .format (i , u )
@@ -205,7 +229,6 @@ def create_dev_users_apps_and_bene_crosswalks(
205229 for t in titles :
206230 c = ProtectedCapability .objects .get (title = t )
207231 a .scope .add (c )
208- print ('<<<<<generated apps for user={}' .format (u .username ))
209232
210233 # go through benes: each bene sign up to 1, 2, 3 apps
211234 # most 70% 1 app, 25% 2 apps, 5% 3 apps
@@ -274,14 +297,12 @@ def create_test_access_refresh_archived_objects(
274297 scope = scope )
275298 at .created = date_created .replace (tzinfo = pytz .utc )
276299 at .save ()
277- print ('<<< access token created for ' + user .username + '/' + application .name )
278300
279301 for i in range (refresh_count ):
280302 rt = RefreshToken .objects .create (user = user , application = application ,
281303 token = uuid .uuid4 ().hex )
282304 rt .created = at .created
283305 rt .save ()
284- print ('<<< ' + user .username + ' refresh token ' + str (i ) + ' generated' )
285306
286307 # archived token: created, updated, archived_at datetime fields
287308 for i in range (archived_token_count ):
@@ -297,7 +318,6 @@ def create_test_access_refresh_archived_objects(
297318 date_archived = ot .created + timedelta (days = 10 )
298319 ot .archived_at = date_archived .replace (tzinfo = pytz .utc )
299320 ot .save ()
300- print ('<<< ' + user .username + ' archived token ' + str (i ) + ' generated' )
301321
302322 past_date = timezone .now () - timedelta (days = 2 )
303323 for i in range (archived_grant_count ):
@@ -308,8 +328,11 @@ def create_test_access_refresh_archived_objects(
308328 archived_at = past_date )
309329 past_date = past_date - timedelta (days = 2 )
310330 adag .save ()
311- print ('<<< ' + user .username + 'archived grant ' + str (i ) + ' generated' )
312331
332+ def delete_users_apps_crosswalks ():
333+ User .objects .all ().delete ()
334+ Application .objects .all ().delete ()
335+ Crosswalk .objects .all ().delete ()
313336
314337class Command (BaseCommand ):
315338 help = ('Create dev users and create'
@@ -333,6 +356,8 @@ def add_arguments(self, parser):
333356 parser .add_argument ('-g' , '--archived-access-grants' , default = 0 ,
334357 help = 'Archived access grants per user/app combination. '
335358 'If none, defaults to 0.' )
359+ parser .add_argument ('--auto-generate' , default = False , help = 'Do not prompt for user input.' )
360+ parser .add_argument ('--delete' , default = False , help = 'Delete all test users and applications.' )
336361
337362 def handle (self , * args , ** options ):
338363 bene_count = int (options ['bene_count' ])
@@ -341,14 +366,18 @@ def handle(self, *args, **options):
341366 refresh_tokens = int (options ['refresh_tokens' ])
342367 archived_tokens = int (options ['archived_tokens' ])
343368 archived_grants = int (options ['archived_access_grants' ])
344- g = create_group ()
369+ auto_generate = bool (options ['auto_generate' ])
370+ delete = bool (options ['delete' ])
371+
372+ if delete :
373+ delete_users_apps_crosswalks ()
345374 create_dev_users_apps_and_bene_crosswalks (
346- g ,
347375 bene_count ,
348376 dev_count ,
349377 app_max ,
350378 refresh_tokens ,
351379 archived_tokens ,
352- archived_grants )
380+ archived_grants ,
381+ auto_generate )
353382 # update grants
354383 update_grants ()
0 commit comments