ACL Fine Granular Control

From OpenEMR Project Wiki

Introduction

A practice, with staff performing a multitude of tasks, at some point, would wish to delineate the degree of access to the various parts of OpenEMR. Because the Navigation Menu is the nexus of all modules, it is this part of the application that users seek to customize access for staff, commensurate with their duties.

Ideally changing permissions should be as simple as described in the Wiki article, but that is not the case. Because permissions tend to overlap and because each permission may encompass more functions than its stated title, fine granular control is difficult to achieve.

Adding to the complexity is the fact that new snippets need to be added to the relevant .php file. Forum members are all too aware that, even with the help of developers, at least 2 pages of discussion are usually required to accomplish the task. Fine tuning is possible with a healthy dose of patience.

There is an excellent explanation of ACL by the authors of the module. It can be found by navigating from Administration->ACL-> Advanced link in the heading->Manual tab. "Star Wars" aficionados will appreciate the analogy.

Explain.png

Two important concepts are ARO, or Access Control Objects (the people who need the access) and ACO, or Access Control Objects (functions to which access is being granted).

If a practice has many groups of ARO's beyond the default, it may be easier to start with the Front Desk because it has the most limited access. From that set of ACO's the practice can configure additional layers of ACO's.

We will endeavor to provide as many examples as possible to permit the user to do this on his own. There will be many times when it is impossible not to ask for help in the Fora, so feel free .

Building Blocks

In addition to the ACL module, the user must become familiar with the various aspects of the Navigation Menu, the Array and the Disallowed sections of the openemr/interface/main/left_nav.php that governs it and the .php files that generate the frames in question.

Navigation Menu provides an in-depth look at the left side bar.

To find the .php for the frame that is to be hidden, right click on it and choose "This Frame"->"Open In Another Tab". The URL will give the path to the .php file.


Left_Nav.Php

Array Section

The Array section, shown below, describes most of what is listed in the Navigation Menu; but not all of it. Our task is to find the correct primary document (if available) for hiding the part of the Menu that is of interest to us.

Array5.png
Array2.png


Each of the documents has a short descriptor, a more detailed descriptor, information regarding reference point (whether global or about patients) and generally the location of the pertinent .php file. Some of the documents are self-evident, while others are more opaque. All will have comments.

  • "'ros' => array(xl('Roster') , 0, 'reports/players_report.php?embed=1')": Roster of players, probably of little relevence to most practices.
  • "'cal' => array(xl('Calendar') , 0, 'main/main_info.php')": Calendar for scheduling appointments.
  • "'app' => array(xl('Portal Activity') , 0, '../myportal/index.php')": Patient Portal, if enabled.
  • "'msg' => array(xl('Messages') , 0, 'main/messages/messages.php?form_active=1')": Messages Center.
  • "'pwd' => array(xl('Password') , 0, 'usergroup/user_info.php')": Password, under Miscellaneous.
  • "'prf' => array(xl('Preferences') , 0, 'super/edit_globals.php?mode=user')": Preferences, under Miscellaneous.
  • "'adm' => array(xl('Admin') , 0, 'usergroup/admin_frameset.php')": Users, under Administration.
  • "'rep' => array(xl('Reports') , 0, 'reports/index.php')": Reports, for Clients, Clinic, Visits and Financial.
  • "'ono' => array(xl('Ofc Notes') , 0, 'main/onotes/office_comments.php')": Ofc Notes, under Miscellaneous.
  • "'fax' => array(xl('Fax/Scan') , 0, 'fax/faxq.php')": Administration, Globals, Miscellaneous tab.
  • "'adb' => array(xl('Addr Bk') , 0, 'usergroup/addrbook_list.php')": Address Book under Miscellaneous.
  • "'orl' => array(xl('Proc Prov') , 0, 'orders/procedure_provider_list.php')": Providers under Procedures.
  • "'ort' => array(xl('Proc Cat') , 0, 'orders/types.php')": Categories of test in Configuration under Procedures.
  • "'orc' => array(xl('Proc Load') , 0, 'orders/load_compendium.php')": Load Compendium under Procedures.
  • "'orb' => array(xl('Proc Bat') , 0, 'orders/orders_results.php?batch=1')": Batch Results under Procedures.
  • "'ore' => array(xl('E-Reports') , 0, 'orders/list_reports.php')": Electronic Reports under Procedures.
  • "'ppo' => array(xl('CMS Portal'), 0, 'cmsportal/list_requests.php')": CMS Portal.
  • "'cht' => array(xl('Chart Trk') , 0, '../custom/chart_tracker.php')": Chart Tracker under Miscellaneous.
  • "'imp' => array(xl('Import') , 0, '../custom/import.php')": New Documents for import, under Miscellaneous.
  • "'bil' => array(xl('Billing') , 0, 'billing/billing_report.php')": Billing module under Fees.
  • "'sup' => array(xl('Superbill') , 0, 'patient_file/encounter/superbill_custom_full.php')": Superbill under Visits, Reports.
  • "'aun' => array(xl('Authorizations'), 0, 'main/authorizations/authorizations.php')": Authorization under Miscellaneous.
  • "'new' => array(xl('New Pt') , 0, 'new/new.php')": New/Search under Patients/Clients.
  • "'ped' => array(xl('Patient Education'), 0, 'reports/patient_edu_web_lookup.php')": Patient Education under Miscellaneous.
  • "'lab' => array(xl('Check Lab Results') , 0, 'orders/lab_exchange.php')": Lab Exchange in Administration, Globals, Connectors.
  • "'dem' => array(xl('Patient') , 1, "patient_file/summary/demographics.php")": Demographics section of Patient Summary.
  • "'his' => array(xl('History') , 1, 'patient_file/history/history.php')": History tab of Patient Summary.
  • "'ens' => array(xl('Visit History'), 1, 'patient_file/history/encounters.php')": Visit History under Visits, Patients/Clients.
  • "'nen' => array(xl('Create Visit'), 1, 'forms/newpatient/new.php?autoloaded=1&calenc=')": Create Visit under Visits, Patients/Clients.
  • "'pre' => array(xl('Rx') , 1, 'patient_file/summary/rx_frameset.php')": Prescription module.
  • "'iss' => array(xl('Issues') , 1, 'patient_file/summary/stats_full.php?active=all')": Issues tab of Patient Summary.
  • "'imm' => array(xl('Immunize') , 1, 'patient_file/summary/immunizations.php')": Immunizations module of Patient Summary.
  • "'doc' => array(xl('Documents') , 1, '../controller.php?document&list&patient_id={PID}')": Documents tab of Patient Summary.
  • "'orp' => array(xl('Proc Pending Rev'), 1, 'orders/orders_results.php?review=1')": Pending Review under Procedures.
  • "'orr' => array(xl('Proc Res') , 1, 'orders/orders_results.php')": Patient Result under Procedures.
  • "'lda' => array(xl('Lab overview') , 1, 'patient_file/summary/labdata.php')": Lab Overview under Procedures.
  • "'tan' => array(xl('Configure Tracks') , 0, 'forms/track_anything/create.php')": Track Anything module, if enabled.
  • "'prp' => array(xl('Pt Report') , 1, 'patient_file/report/patient_report.php')": Report tab of Patient Summary.
  • "'prq' => array(xl('Pt Rec Request') , 1, 'patient_file/transaction/record_request.php')": Record Request in Transaction tab of Patient Summary.
  • "'pno' => array(xl('Pt Notes') , 1, 'patient_file/summary/pnotes.php')": Notes in Patient Summary.
  • "'tra' => array(xl('Transact') , 1, 'patient_file/transaction/transactions.php')": Transaction tab of Patient Summary.
  • "'sum' => array(xl('Summary') , 1, 'patient_file/summary/summary_bottom.php')": Summary under Patients/Clients.
  • "'enc' => array(xl('Encounter') , 2, 'patient_file/encounter/encounter_top.php')": New Encounter from Encounter History drop down menu.
  • "'erx' => array(xl('e-Rx') , 1, 'eRx.php')": E-Prescribe if enabled.
  • "'err' => array(xl('e-Rx Renewal') , 1, 'eRx.php?page=status')": E-Prescription renewal.
  • "'pay' => array(xl('Payment') , 1, '../patient_file/front_payment.php')": Payment under Fees.
  • "'edi' => array(xl('EDI History') , 0, 'billing/edih_view.php')": EDI History under Fees.
  • "'dld' => array(xl('Display Documents'), 0, 'main/display_documents.php')": Display from Documents tab of Patient Summary.


Disallowed Section

If we can work from the Disallowed section, it would be great because it is less difficult to insert snippets here.

Disallowed.png


Hiding The Calendar

There exist practices that don't want the Front Office to view the Calendar. It is a rare occurrence because the Front Office is predominately responsible for booking appointments. We will use this example because the exercise is fairly straightforward.

  • Move the ACO, Patient, Appointments; to the right.
No calendar1.png


  • Note that the Array section has a "cal" document,"'cal' => array(xl('Calendar'), etc."; so we have a fortuitous start.
  • Because the Calendar can be disabled from Globals, a statement must address this fact. The second statement asks if the ARO has permission to view the Calendar. Insert this snippet into Line 189 in the Disallowed section:


$disallowed['cal'] = !(GLOBALS['disable_calendar');] || acl_check('patients','appointments','', 'write'));
No calendar2.png


  • The openemr/interface/main/calendar/index.php handles the Calendar.
  • Insert the 2 snippets:
require_once("$srcdir/acl.inc");
if (!acl_check('patients','appointment','','write')) die("Not authorized!");
No calendar3.png

Hiding Contributed Forms

Despite the fact that the Front Office should not have access to forms like Review of Systems Checks and SOAP, it does.

  • We are fortunate once again that the document, 'enc', exists in the Array section; permitting us to insert the following:
disallowed['enc'] = !(acl_check('encounters','notes','','write'));
No form.png


  • Into each of script for the forms, insert these 2 snippets:
require_once("$srcdir/acl.inc");
if (!acl_check('encounters','notes_a','','write')) die("Not authorized!");
No form ros checks.png


No form soap.png


Hiding Fee Sheet from Physicians

In large clinics where Physicians have no responsibilities for entering charges, the Administrator may wish to hide the Fee Sheet from this ARO.

  • Move the ACO to the left.
No fee1.png


  • There is no public document to be of use to us; but a useful snippet was found, to which was added:
&& acl_check("encounters','coding_a'))
No fee2.png


  • In the Fee Sheet script, insert the following:
if (!acl_check('encounters',"coding_a'))) die("Not authorized!");
No fee3.png