Package: edc-auth
edc-authAuthentication and permissions for the EdcDefault GroupsThe default groups are required for the normal operation of an EDC deployment. The default groups are:ACCOUNT_MANAGER: members may add/change and delete user accountsADMINISTRATION: members may view the Administration pageAUDITOR: members may view all forms but have no add/change permissions.CLINIC: members may add/edit/delete all CRFs, Requisitions, Actions and other required clinic trial data entry forms. They may also view the Requisition page of the Lab section;EVERYONE: members may access the EDC;LAB: members may perform all functions in the Lab section (Edit requisitions, receive, process, pack, manage manifests, etc);PHARMACY:PII: members may view all personally identifiable data and edit forms that manage such data (Screening, Consents, Patient registration);PII_VIEW: members may view personally identifiable data but have no add/edit permissions for any of the forms that store such data.PermissionsPermissions use Django’s permission framework,  therefore, all permissions are linked to some model.Permissions don’t always naturally link to a model. In such cases, a dummy model is created.
For example, with Navigation bars fromedc_navbar. Permissions to follow an item on a
navigation bar are associated with modeledc_navbar.Navbar. A similar approach is used forlistboardpermissions usingedc_dashboard.Dashboard.Extending permissions withsite_authsglobalA module can add new or update existing groups and roles and even add custom codenames.Thesite_authsglobalautodiscoversconfigurations fromauths.pyin the root of your module.
Thesite_authsglobal gathers but does not validate or change any data in django’sgroup/permissionmodels or the Edc’srolemodel.Thesite_authsglobal gathers data:
* to ADD new groups,
* to update codenames for an existing group,
* to add a new role
* to update the group list for an existing role
* to add to the list of PII models
* to specifiy custom functions to run before and after groups and roles have been updatedFor example,# auths.pyfromedc_auth.constantsimportCLINICIAN_ROLE,STATISTICIAN_ROLEfromedc_auth.site_authsimportsite_authsfromedc_protocol_violation.auth_objectsimport(PROTOCOL_VIOLATION,PROTOCOL_VIOLATION_VIEW,protocol_violation_codenames,protocol_violation_view_codenames,)# add a new group specific to models in this modulesite_auths.add_group(*protocol_violation_codenames,name=PROTOCOL_VIOLATION)# add a new group specific to models in this modulesite_auths.add_group(*protocol_violation_view_codenames,name=PROTOCOL_VIOLATION_VIEW)# update the existing role CLINICIAN_ROLE to add the group PROTOCOL_VIOLATIONsite_auths.update_role(PROTOCOL_VIOLATION,name=CLINICIAN_ROLE)# update the existing role STATISTICIAN_ROLE to add the group PROTOCOL_VIOLATION_VIEWsite_auths.update_role(PROTOCOL_VIOLATION_VIEW,name=STATISTICIAN_ROLE)As a convention, we define group names, lists of codenames and custom functionsauth_objects.py.In the above example, theauth_objects.pylooks like this:# auth_objects.py# declare group namesPROTOCOL_VIOLATION="PROTOCOL_VIOLATION"PROTOCOL_VIOLATION_VIEW="PROTOCOL_VIOLATION_VIEW"# add/change/delete/view codenamesprotocol_violation_codenames=("edc_protocol_violation.add_protocoldeviationviolation","edc_protocol_violation.change_protocoldeviationviolation","edc_protocol_violation.delete_protocoldeviationviolation","edc_protocol_violation.view_protocoldeviationviolation",)# view only codenameprotocol_violation_view_codenames=("edc_protocol_violation.view_protocoldeviationviolation",)AuthUpdaterTheAuthUpdaterclass runs in a post_migrate signal declared inapps.py.
TheAuthUpdaterreads and validates the data gathered bysite_auths. Once all
validation checks pass, theAuthUpdaterupdates Django’sgroupandpermissionmodels as well as the Edc’sRolemodel.Validation checks include confirming models refered to in codenames exist. This means that
the app where models are declared must be in yourINSTALLED_APPS.During tests having all codenames load may not be ideal. See below on some strategies for testing.Testing SiteAuths, AuthUpdaterAn app sets up its own groups and roles using thesite_authsglobal inauths.py. To test just your apps
configuration, you can preventsite_authsfrom autodiscovering other modules by setting:EDC_AUTH_SKIP_SITE_AUTHS=TrueYou can prevent theAuthUpdaterfrom updating groups and permissions by setting:EDC_AUTH_SKIP_AUTH_UPDATER=TrueYou can then override these attributes in your tests@override_settings(EDC_AUTH_SKIP_SITE_AUTHS=True,EDC_AUTH_SKIP_AUTH_UPDATER=False)classTestMyTests(TestCase):...Above thesite_authsglobalautodiscoveris still disabled but theAuthUpdateris not.
In your test setup you can updatesite_authsmanually so that your tests focus on the
add/update or groups/roles/codenames/tuples relevant to your app.You can emulateautodiscoverbehaviour by explicitly importingauthsmodules needed for your tests.For example:fromimportlibimportimport_modulefromdjango.testimportTestCase,override_settingsfromedc_auth.auth_updaterimportAuthUpdaterclassTestAuths(TestCase):@override_settings(EDC_AUTH_SKIP_SITE_AUTHS=True,EDC_AUTH_SKIP_AUTH_UPDATER=True,)deftest_load(self):import_module(f"edc_dashboard.auths")import_module(f"edc_navbar.auths")AuthUpdater(verbose=True)You canclearthesite_authsregistry and add back specific items need for your tests.For example:# taken from edc-dashboard@override_settings(EDC_AUTH_SKIP_SITE_AUTHS=True,EDC_AUTH_SKIP_AUTH_UPDATER=False)classTestMyTests(TestCase):defsetUpTestData(cls):site_auths.clear()site_auths.add_group("edc_dashboard.view_my_listboard",name=CLINIC)site_auths.add_custom_permissions_tuples(model="edc_dashboard.edcpermissions",codename_tuples=(("edc_dashboard.view_my_listboard","View my listboard"),),)AuthUpdater(verbose=False,warn_only=True)returnsuper().setUpTestData()deftest_me(self):...Importing usersYou create user accounts by importing a specially formatted CSV file. Once an account is created a “Welcome” email may be sent.Import users from a CSV file with columns:usernameis_staffis_activefirst_namelast_namejob_titleemailmobilealternate_emailsite_names:acomma-separatedlistofsitesrole_names:acomma-separatedlistofrolesThen import the users from your application commandlinepythonmanage.pyimport_users--csvfile=/Users/erikvw/meta_users.csv--notify-to-test-email=ew2789@gmail--resource-name=meta.clinicedc.org--resend-as-newLegacy notesImportant:If you are upgrading from edc_base.auth:Theuserprofiletable is now inedc_auth.edc_authhas one migration for this table.
Copy the same table fromedc_baseand fake theedc_authmigration.CREATETABLEedc_auth_userprofileLIKEedc_base_userprofile;INSERTedc_auth_userprofileSELECT*FROMedc_base_userprofile;pythonmanage.pymigrateedc_auth--fakeYou can now run theedc_basemigration safely.