Fixed quote escaping problem in view.php.
[openemr.git] / library / acl.inc
blob71468d381a9dbb436bbfe498d6110bbf7ea2df2c
1 <?php
2 // php-GACL access controls are included in OpenEMR. The below
3 // function will automatically create the path where gacl.class.php
4 // can be found. Note that this path can be manually set below
5 // for users who are using an external version of php-GACL.
6 // Also note that php-GACL access controls can be turned off
7 // below.
8  if (isset ($GLOBALS['fileroot'])) {
9   //normal use during OpenEMR
10   $phpgacl_location = $GLOBALS['fileroot'] . "/gacl";
11  }
12  else {  
13   //special case during OpenEMR and php-GACL install/upgrade scripts,
14   //which are run from main OpenEMR directory.
15   $phpgacl_location = "gacl";
16  }
18 // If using an external version of phpGACL, then uncomment the following
19 // line and manually place the path below.  IN THIS CASE YOU MUST ALSO
20 // COMMENT OUT BOTH $phpgacl_location ASSIGNMENTS ABOVE, OR BACKUPS WILL
21 // NOT RESTORE PROPERLY!
23 //$phpgacl_location = "/var/www/gacl";
25 // If you want to turn off php-GACL, then uncomment the following line.
26 // IN THIS CASE YOU MUST ALSO COMMENT OUT ALL $phpgacl_location ASSIGNMENTS
27 // ABOVE, OR BACKUPS WILL NOT RESTORE PROPERLY!
29 //unset($phpgacl_location);
32   // The following Access Control Objects (ACO) are currently supported.
33   // These are the "things to be protected":
34   //
35   // Section "admin" (Administration):
36   //   super       Superuser - can delete patients, encounters, issues
37   //   calendar    Calendar Settings
38   //   database    Database Reporting
39   //   forms       Forms Administration
40   //   practice    Practice Settings
41   //   superbill   Superbill Codes Administration
42   //   users       Users/Groups/Logs Administration
43   //   batchcom    Batch Communication Tool
44   //   language    Language Interface Tool
45   //   drugs       Pharmacy Dispensary
46   //   acl         ACL Administration
47   //
48   // Section "acct" (Accounting):
49   //   bill        Billing (write optional)
50   //   disc        Allowed to discount prices (in Fee Sheet or Checkout form)
51   //   eob         EOB Data Entry
52   //   rep         Financial Reporting - my encounters
53   //   rep_a       Financial Reporting - anything
54   //
55   // Section "patients" (Patient Information):
56   //   appt        Appointments (write optional)
57   //   demo        Demographics (write,addonly optional)
58   //   med         Medical Records and History (write,addonly optional)
59   //   trans       Transactions, e.g. referrals (write optional)
60   //   docs        Documents (write,addonly optional)
61   //   notes       Patient Notes (write,addonly optional)
62   //
63   // Section "encounters" (Encounter Information):
64   //   auth        Authorize - my encounters
65   //   auth_a      Authorize - any encounters
66   //   coding      Coding - my encounters (write,wsome optional)
67   //   coding_a    Coding - any encounters (write,wsome optional)
68   //   notes       Notes - my encounters (write,addonly optional)
69   //   notes_a     Notes - any encounters (write,addonly optional)
70   //   date_a      Fix encounter dates - any encounters
71   //   relaxed     Less-private information (write,addonly optional)
72   //               (e.g. the Sports Fitness encounter form)
73   //
74   // Section "squads" applies to sports team use only:
75   //   acos in this section define the user-specified list of squads
76   //
77   // Section "sensitivities" (Sensitivities):
78   //   normal     Normal
79   //   high       High
81   if (isset ($phpgacl_location)) {
82     include_once("$phpgacl_location/gacl.class.php");
83     $gacl_object = new gacl();
84     //DO NOT CHANGE BELOW VARIABLE
85     $section_aro_value = 'users';
86   }
88   // acl_check should return 0 if access is denied.  Otherwise it may
89   // return anything that evaluates to true.  In addition if any of the
90   // following types of access are applicable, then the corresponding value
91   // must be returned if and only if such access is granted (ony one may
92   // be specified):
93   //
94   // * write   - the user may add or modify the ACO
95   // * wsome   - the user has limited add/modify access to the ACO
96   // * addonly - the user may view and add but not modify entries
97   //
98   function acl_check($section, $value, $user = '') {
99     global $gacl_object, $phpgacl_location, $section_aro_value;
100     if (! $user) $user = $_SESSION['authUser'];
102     if ($phpgacl_location) {
103       return $gacl_object->acl_check($section, $value, $section_aro_value, $user);
104     }
106     // If no phpgacl, then apply the old static rules whereby "authorized"
107     // users (providers) can do anything, and other users can do most things.
108     // If you want custom access control but don't want to mess with phpGACL,
109     // then you could customize the code below instead.
111     if ($user == 'admin') return 'write';
112     if ($section == 'admin' && $value == 'super') return 0;
113     if ($_SESSION['userauthorized']) return 'write';
115     if ($section == 'patients') {
116       if ($value == 'med') return 1;
117       return 'write';
118     }
119     else if ($section == 'encounters') {
120       if (strpos($value, 'coding' ) === 0) return 'write';
121       if (strpos($value, 'notes'  ) === 0) return 'write';
122       if ($value == 'relaxed') return 'write';
123     }
124     else if ($section != 'admin') {
125       return 'write';
126     }
128     return 0;
129   }
131   // Get the ACO name/value pairs for a designated section.  Each value
132   // is an array (section_value, value, order_value, name, hidden).
133   //
134   function acl_get_section_acos($section) {
135     global $phpgacl_location;
136     if ($phpgacl_location) {
137       include_once("$phpgacl_location/gacl_api.class.php");
138       $gacl = new gacl_api();
139       $arr1 = $gacl->get_objects($section, 1, 'ACO');
140       $arr = array();
141       if (!empty($arr1[$section])) {
142         foreach ($arr1[$section] as $value) {
143           $odata = $gacl->get_object_data($gacl->get_object_id($section, $value, 'ACO'), 'ACO');
144           $arr[$value] = $odata[0];
145         }
146       }
147       return $arr;
148     }
149     return 0;
150   }
152   // Return an array keyed on squad ACO names.
153   // This is only applicable for sports team use.
154   //
155   function acl_get_squads() {
156     return acl_get_section_acos('squads');
157   }
159   // Return an array keyed on encounter sensitivity level ACO names.
160   // Sensitivities are useful when some encounter notes are not
161   // medically sensitive (e.g. a physical fitness test), and/or if
162   // some will be "for doctor's eyes only" (e.g. STD treatment).
163   //
164   // When a non-blank sensitivity value exists in the new encounter
165   // form, it names an additional ACO required for access to all forms
166   // in the encounter.  If you want some encounters to be non-sensitive,
167   // then you also need some default nonblank sensitivity for normal
168   // encounters, as well as greater encounter notes permissions for
169   // those allowed to view non-sensitive encounters.
170   //
171   function acl_get_sensitivities() {
172     return acl_get_section_acos('sensitivities');
173   }
175   //
176   // Returns a sorted array of all available Group Titles.
177   //
178   function acl_get_group_title_list() {
179     global $phpgacl_location;
180     if (isset ($phpgacl_location)) {
181       include_once("$phpgacl_location/gacl_api.class.php");
182       $gacl = new gacl_api();
183       $parent_id = $gacl->get_root_group_id();
184       $arr_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
185       $arr_group_titles = array();
186       foreach ($arr_group_ids as $value) {
187         $arr_group_data = $gacl->get_group_data($value, 'ARO');
188         $arr_group_titles[$value] = $arr_group_data[3];
189       }
190       sort($arr_group_titles);
191       return $arr_group_titles;
192     }
193     return 0;
194   }
196   //
197   // Returns a sorted array of group Titles that a user belongs to.
198   // Returns 0 if does not belong to any group yet.
199   //   $user_name = Username, which is login name.
200   //
201   function acl_get_group_titles($user_name) {
202     global $phpgacl_location, $section_aro_value;
203     if (isset ($phpgacl_location)) {
204       include_once("$phpgacl_location/gacl_api.class.php");
205       $gacl = new gacl_api();
206       $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
207       if ($user_aro_id) {
208         $arr_group_id = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
209         if ($arr_group_id) {
210           foreach ($arr_group_id as $key => $value) {
211             $arr_group_data = $gacl->get_group_data($value, 'ARO');
212             $arr_group_titles[$key] =  $arr_group_data[3];
213           }
214         sort($arr_group_titles);
215         return $arr_group_titles;
216         }
217       }
218     }
219     return 0;
220   }
222   //
223   // This will place the user aro object into selected group(s)
224   // It uses the set_user_aro() function
225   //   $username = username (string)
226   //   $group = title of group(s) (string or array)
227   //
228   function add_user_aros($username, $group) {
229    $current_user_groups = acl_get_group_titles($username);
230    if (!$current_user_groups) {
231     $current_user_groups = array();
232    }
233    if (is_array($group)){
234     foreach ($group as $value) {
235        if (!in_array($value, $current_user_groups)) { 
236         array_push($current_user_groups, $value);
237        }
238     }
239    }
240    else {
241     if (!in_array($group, $current_user_groups)) {
242      array_push($current_user_groups, $group);
243     }
244    }
245    $user_data = mysql_fetch_array(sqlStatement("select * from users where username='" .
246     $username . "'"));
247    set_user_aro($current_user_groups, $username, $user_data["fname"],
248     $user_data["mname"], $user_data["lname"]);
249    return;
250   }
252   //
253   // This will remove the user aro object from the selected group(s)
254   // It uses the set_user_aro() function
255   //   $username = username (string)
256   //   $group = title of group(s) (string or array)
257   //
258   function remove_user_aros($username, $group) {
259    $current_user_groups = acl_get_group_titles($username);
260    $new_user_groups = array();
261    if (is_array($group)){
262     foreach ($current_user_groups as $value) {
263      if (!in_array($value, $group)) {
264       array_push($new_user_groups, $value);
265      }
266     }
267    }
268    else {
269     foreach ($current_user_groups as $value) {
270      if ($value != $group) {
271       array_push($new_user_groups, $value);
272      }
273     }
274    }
275    $user_data = mysql_fetch_array(sqlStatement("select * from users where username='" .
276     $username . "'"));
277    set_user_aro($new_user_groups, $username, $user_data["fname"],
278     $user_data["mname"], $user_data["lname"]);
279    return;
280   }
282   //
283   // This will either create or edit a user aro object, and then place it
284   // in the requested groups. It will not allow removal of the 'admin'
285   // user from the 'admin' group.
286   //   $arr_group_titles = titles of the groups that user will be added to.
287   //   $user_name = username, which is login name.
288   //   $first_name = first name
289   //   $middle_name = middle name
290   //   $last_name = last name
291   //
292   function set_user_aro($arr_group_titles, $user_name, $first_name, $middle_name, $last_name) {
293     global $phpgacl_location, $section_aro_value;
295     if (isset ($phpgacl_location)) {
296       include_once("$phpgacl_location/gacl_api.class.php");
297       $gacl = new gacl_api();
299       //get array of all available group ID numbers
300       $parent_id = $gacl->get_root_group_id();
301       $arr_all_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
303       //Cycle through ID array to find and process each selected group
304       //Create a counter since processing of first hit is unique
305       $counter = 0;
306       foreach ($arr_all_group_ids as $value) {
307         $arr_group_data = $gacl->get_group_data($value, 'ARO');
308         if ((empty($arr_group_titles)) ||
309          (in_array($arr_group_data[3], $arr_group_titles))) {
310           //We have a hit, so need to add group and increment counter
311           // because processing of first hit is unique
312           //This will also deal with an empty $arr_group_titles array
313           // removing user from all groups unless 'admin'
314           $counter = $counter + 1;
315           //create user full name field
316           if ($middle_name) {
317             $full_name = $first_name . " " . $middle_name . " " .  $last_name;
318           }
319           else {
320             if ($last_name) {
321               $full_name = $first_name . " " . $last_name;
322             }
323             else {
324               $full_name = $first_name;
325             }
326           }
328           //If this is not the first group to be added, then will skip below
329           // and will be added. If this is the first group, then need to
330           // go thru several steps before adding the group.
331           if ($counter == 1) {
332             //get ID of user ARO object, if it exist
333             $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
334             if ($user_aro_id) {
335               //user ARO object already exist, so will edit it
336               $gacl->edit_object($user_aro_id, $section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
338               //remove all current user ARO object group associations
339               $arr_remove_group_ids = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
340               foreach ($arr_remove_group_ids as $value2) {
341                 $gacl->del_group_object($value2, $section_aro_value, $user_name, 'ARO');
342               }
343             }
344             else {
345               //user ARO object does not exist, so will create it
346               $gacl->add_object($section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
347             }
348           }
350           //place the user ARO object in the selected group (if group(s) is selected)
351           if (!empty($arr_group_titles)) {
352             $gacl->add_group_object($value, $section_aro_value, $user_name, 'ARO');
353           }
355           //
356           //Below will not allow 'admin' user to be removed from 'admin' group
357           //
358           if ($user_name == 'admin') {
359             $boolean_admin=0;
360             $admin_id = $gacl->get_object_id($section_aro_value, 'admin', 'ARO');
361             $arr_admin = $gacl->get_object_groups($admin_id, 'ARO', 'NO_RECURSE');
362             foreach ($arr_admin as $value3) {
363               $arr_admin_data = $gacl->get_group_data($value3, 'ARO');
364               if (strcmp($arr_admin_data[2], 'admin') == 0) {
365                 $boolean_admin=1;
366               }
367             }
368             if (!$boolean_admin) {
369               foreach ($arr_all_group_ids as $value4) {
370                 $arr_temp = $gacl->get_group_data($value4, 'ARO');
371                 if ($arr_temp[2] == 'admin') {
372                   $gacl->add_group_object($value4, $section_aro_value, 'admin', 'ARO');
373                 }
374               }
375             }
376           }
377         }
378         //if array of groups was empty, then we are done, and can break from loop
379         if (empty($arr_group_titles)) break;
380       }
381     }
382    return;
383   }
385   //
386   // Returns true if acl exist
387   // Returns false if acl doesn't exist
388   //  EITHER $title or $name is required(send FALSE in variable
389   //  not being used). If both are sent, then only $title will be
390   //  used.
391   //  $return_value is required
392   //    $title = title of acl (string)
393   //    $name = name of acl (string)
394   //    $return_value = return value of acl (string)
395   //
396   function acl_exist($title, $name, $return_value) {
397    global $phpgacl_location;
398    if (isset ($phpgacl_location)) {
399     include_once("$phpgacl_location/gacl_api.class.php");
400     $gacl = new gacl_api();
401     if (!$name) {
402      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
403     }
404     else if (!$title) {
405      $group_id = $gacl->get_group_id($name, NULL, 'ARO');
406      if ($group_id) {
407       $group_data = $gacl->get_group_data($group_id, 'ARO');
408       $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $group_data[3], FALSE, FALSE, FALSE, $return_value);
409      }
410      else {
411      return false;
412      }
413     }
414     else {
415      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
416     }
417     if (!empty($acl)) {
418      return true;
419     }
420     else {
421      return false;
422     }
423    }
424   }
426   //
427   // This will add a new acl and group(if group doesn't yet exist)
428   // with one aco in it.
429   //   $acl_title = title of acl (string)
430   //   $acl_name = name of acl (string)
431   //   $return_value = return value of acl (string)
432   //   $note = description of acl (array)
433   //
434   function acl_add($acl_title, $acl_name, $return_value, $note) {
435    global $phpgacl_location;
436    if (isset ($phpgacl_location)) {
437     include_once("$phpgacl_location/gacl_api.class.php");
438     $gacl = new gacl_api();
439     $group_id = $gacl->get_group_id($acl_name, $acl_title, 'ARO');
440     if ($group_id) {
441      //group already exist, so just create acl
442      $gacl->add_acl(array("patients"=>array("appt")),
443       NULL, array($group_id), NULL, NULL, 1, 1, $return_value, $note);
444     }
445     else {
446      //create group, then create acl
447      $parent_id = $gacl->get_root_group_id();
448      $aro_id = $gacl->add_group($acl_name, $acl_title, $parent_id, 'ARO');
449      $gacl->add_acl(array("patients"=>array("appt")),
450       NULL, array($aro_id), NULL, NULL, 1, 1, $return_value, $note);
451     }
452     return;
453    }
454    return 0;
455   }
457   //
458   // This will remove acl. It will also remove group(if the group
459   // is no longer associated with any acl's).
460   //   $acl_title = title of acl (string)
461   //   $acl_name = name of acl (string)
462   //   $return_value = return value of acl (string)
463   //   $note = description of acl (array)
464   //
465   function acl_remove($acl_title, $return_value) {
466    global $phpgacl_location;
467    if (isset ($phpgacl_location)) {
468     include_once("$phpgacl_location/gacl_api.class.php");
469     $gacl = new gacl_api();
470     //First, delete the acl
471     $acl_id=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
472     $gacl->del_acl($acl_id[0]);
473     //Then, remove the group(if no more acl's are remaining)
474     $acl_search=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, FALSE);
475     if (empty($acl_search)){
476      $group_id=$gacl-> get_group_id(NULL, $acl_title, 'ARO');
477      $gacl->del_group($group_id, TRUE, 'ARO');
478     }
479     return;
480    }
481    return 0;
482   }
484   //
485   // This will place the aco(s) into the selected acl
486   //   $acl_title = title of acl (string)
487   //   $return_value = return value of acl (string)
488   //   $aco_id = id of aco (array)
489   //
490   function acl_add_acos($acl_title, $return_value, $aco_id) {
491    global $phpgacl_location;
492    if (isset ($phpgacl_location)) {
493     include_once("$phpgacl_location/gacl_api.class.php");
494     $gacl = new gacl_api();
495     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
496     foreach ($aco_id as $value) { 
497      $aco_data = $gacl->get_object_data($value, 'ACO');
498      $aco_section = $aco_data[0][0];
499      $aco_name = $aco_data[0][1];   
500      $gacl->append_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
501     }
502     return;
503    }
504    return 0;
505   }
507   //
508   // This will remove the aco(s) from the selected acl
509   //   $acl_title = title of acl (string)
510   //   $return_value = return value of acl (string)
511   //   $aco_id = id of aco (array)
512   //
513   function acl_remove_acos($acl_title, $return_value, $aco_id) {
514    global $phpgacl_location;
515    if (isset ($phpgacl_location)) {
516     include_once("$phpgacl_location/gacl_api.class.php");
517     $gacl = new gacl_api();
518     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
519     foreach ($aco_id as $value) {
520      $aco_data = $gacl->get_object_data($value, 'ACO');
521      $aco_section = $aco_data[0][0];
522      $aco_name = $aco_data[0][1];
523      $gacl->shift_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
524      }
525     return;
526    }
527    return 0;
528   }
530   //
531   // This will return the number of aco objects
532   //  in a specified acl.
533   //   $acl_title = title of acl (string)
534   //   $return_value = return value of acl (string)
535   //
536   function acl_count_acos($acl_title, $return_value) {
537    global $phpgacl_location;
538    if (isset ($phpgacl_location)) {
539     include_once("$phpgacl_location/gacl_api.class.php");
540     $gacl = new gacl_api();
541     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
542     $acl_data = $gacl->get_acl($acl_id[0]);
543     $aco_count = 0;
544     foreach ($acl_data['aco'] as $key => $value) {
545      $aco_count = $aco_count + count($acl_data['aco'][$key]);
546     }
547     return $aco_count;
548    }
549    return 0;
550   }