3 * This file contains functions that service ajax requests for
4 * ACL(php-gacl) administration within OpenEMR. All returns are
7 * Important - Ensure that display_errors=Off in php.ini settings.
10 * @link http://www.open-emr.org
11 * @author Brady Miller <brady.g.miller@gmail.com>
12 * @copyright Copyright (c) 2007-2017 Brady Miller <brady.g.miller@gmail.com>
13 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 require_once("../../interface/globals.php");
17 require_once("$srcdir/acl.inc");
18 require_once("$srcdir/user.inc");
19 require_once("$srcdir/calendar.inc");
21 header("Content-type: text/xml");
22 header("Cache-Control: no-cache");
24 //initiate error array
28 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
29 echo error_xml(xl('Authentication Error'));
33 //ensure user has proper access
34 if (!acl_check('admin', 'acl')) {
35 echo error_xml(xl('ACL Administration Not Authorized'));
39 //ensure php is installed
40 if (!isset($phpgacl_location)) {
41 echo error_xml(xl('PHP-gacl is not installed'));
45 //Display red alert if Emergency Login ACL is activated for a user.
46 if ($_POST["action"] == "add") {
47 if (is_array($_POST["selection"]) && in_array("Emergency Login", $_POST["selection"])) {
48 array_push($error, (xl('Emergency Login ACL is chosen. The user is still in active state, please de-activate the user and activate the same when required during emergency situations. Visit Administration->Users for activation or de-activation.') ));
52 //PROCESS USERNAME REQUESTS
53 if ($_POST["control"] == "username") {
54 if ($_POST["action"] == "list") {
55 //return username list with alert if user is not joined to group
56 echo username_listings_xml($error);
61 //PROCESS MEMBERSHIP REQUESTS
62 if ($_POST["control"] == "membership") {
63 if ($_POST["action"] == "list") {
64 //return membership data
65 echo user_group_listings_xml($_POST["name"], $error);
68 if ($_POST["action"] == "add") {
69 if ($_POST["selection"][0] == "null") {
70 //no selection, return soft error, and just return membership data
71 array_push($error, (xl('No group was selected') . "!"));
72 echo user_group_listings_xml($_POST["name"], $error);
76 //add the group, then return updated membership data
77 add_user_aros($_POST["name"], $_POST["selection"]);
78 echo user_group_listings_xml($_POST["name"], $error);
81 if ($_POST["action"] == "remove") {
82 if ($_POST["selection"][0] == "null") {
83 //no selection, return soft error, and just return membership data
84 array_push($error, (xl('No group was selected') . "!"));
85 echo user_group_listings_xml($_POST["name"], $error);
89 // check if user is protected. If so, then state message unable to remove from admin group.
90 $userNametoID = getIDfromUser($_POST["name"]);
91 if (checkUserSetting("gacl_protect", "1", $userNametoID) ||
($_POST["name"] == "admin")) {
94 $gacl_protect = false;
97 if ($gacl_protect && in_array("Administrators", $_POST["selection"])) {
98 //unable to remove admin user from administrators group, process remove,
99 // send soft error, then return data
100 array_push($error, (xl('Not allowed to remove this user from the Administrators group') . "!"));
101 remove_user_aros($_POST["name"], $_POST["selection"]);
102 echo user_group_listings_xml($_POST["name"], $error);
106 //remove the group(s), then return updated membership data
107 remove_user_aros($_POST["name"], $_POST["selection"]);
108 echo user_group_listings_xml($_POST["name"], $error);
113 //PROCESS ACL REQUESTS
114 if ($_POST["control"] == "acl") {
115 if ($_POST["action"] == "list") {
116 //return acl titles with return values
117 echo acl_listings_xml($error);
120 if ($_POST["action"] == "add") {
123 if (empty($_POST["title"])) {
125 array_push($error, ("title_" . xl('Need to enter title') . "!"));
126 } else if (!ctype_alpha(str_replace(' ', '', $_POST["title"]))) {
128 array_push($error, ("title_" . xl('Please only use alphabetic characters') . "!"));
129 } else if (acl_exist($_POST["title"], false, $_POST["return_value"])) {
131 array_push($error, ("title_" . xl('Already used, choose another title') . "!"));
134 if (empty($_POST["identifier"])) {
136 array_push($error, ("identifier_" . xl('Need to enter identifier') . "!"));
137 } else if (!ctype_alpha($_POST["identifier"])) {
139 array_push($error, ("identifier_" . xl('Please only use alphabetic characters with no spaces') . "!"));
140 } else if (acl_exist(false, $_POST["identifier"], $_POST["return_value"])) {
142 array_push($error, ("identifier_" . xl('Already used, choose another identifier') . "!"));
145 if (empty($_POST["return_value"])) {
147 array_push($error, ("return_" . xl('Need to enter a Return Value') . "!"));
150 if (empty($_POST["description"])) {
152 array_push($error, ("description_" . xl('Need to enter a description') . "!"));
153 } else if (!ctype_alpha(str_replace(' ', '', $_POST["description"]))) {
155 array_push($error, ("description_" . xl('Please only use alphabetic characters') . "!"));
158 //process if data is valid
160 acl_add($_POST["title"], $_POST["identifier"], $_POST["return_value"], $_POST["description"]);
161 echo "<?xml version=\"1.0\"?>\n" .
163 "\t<success>SUCCESS</success>\n" .
165 } else { //$form_error = true, so return errors
166 echo error_xml($error);
170 if ($_POST["action"] == "remove") {
173 if (empty($_POST["title"])) {
175 array_push($error, ("aclTitle_" . xl('Need to enter title') . "!"));
178 if ($_POST["title"] == "Administrators") {
180 array_push($error, ("aclTitle_" . xl('Not allowed to delete the Administrators group') . "!"));
183 //process if data is valid
185 acl_remove($_POST["title"], $_POST["return_value"]);
186 echo "<?xml version=\"1.0\"?>\n" .
188 "\t<success>SUCCESS</success>\n" .
190 } else { //$form_error = true, so return errors
191 echo error_xml($error);
195 if ($_POST["action"] == "returns") {
196 //simply return all the possible acl return_values
197 echo return_values_xml($error);
202 //PROCESS ACO REQUESTS
203 if ($_POST["control"] == "aco") {
204 if ($_POST["action"] == "list") {
206 echo aco_listings_xml($_POST["name"], $_POST["return_value"], $error);
209 if ($_POST["action"] == "add") {
210 if ($_POST["selection"][0] == "null") {
211 //no selection, return soft error, and just return data
212 array_push($error, (xl('Nothing was selected') . "!"));
213 echo aco_listings_xml($_POST["name"], $_POST["return_value"], $error);
217 //add the aco, then return updated membership data
218 acl_add_acos($_POST["name"], $_POST["return_value"], $_POST["selection"]);
219 echo aco_listings_xml($_POST["name"], $_POST["return_value"], $error);
222 if ($_POST["action"] == "remove") {
223 if ($_POST["selection"][0] == "null") {
224 //no selection, return soft error, and just return data
225 array_push($error, (xl('Nothing was selected') . "!"));
226 echo aco_listings_xml($_POST["name"], $_POST["return_value"], $error);
230 if ($_POST["name"] == "Administrators") {
231 //will not allow removal of acos from Administrators ACL
232 array_push($error, (xl('Not allowed to inactivate anything from the Administrators ACL') . "!"));
233 echo aco_listings_xml($_POST["name"], $_POST["return_value"], $error);
237 //remove the acos, then return updated data
238 acl_remove_acos($_POST["name"], $_POST["return_value"], $_POST["selection"]);
239 echo aco_listings_xml($_POST["name"], $_POST["return_value"], $error);
245 // Returns username listings via xml message.
246 // It will also include alert if user is not joined
248 // $err = error strings (array)
250 function username_listings_xml($err)
252 $message = "<?xml version=\"1.0\"?>\n" .
254 $res = sqlStatement("select * from users where username != '' and active = 1 order by username");
255 for ($iter = 0; $row = sqlFetchArray($res); $iter++
) {
256 $result4[$iter] = $row;
259 foreach ($result4 as $iter) {
260 $message .= "\t<user>\n" .
261 "\t\t<username>" . $iter{"username"} . "</username>\n";
262 $username_acl_groups = acl_get_group_titles($iter{"username"});
263 if (!$username_acl_groups) {
264 //not joined to any group, so send alert
265 $message .= "\t\t<alert>no membership</alert>\n";
268 $message .= "\t</user>\n";
272 foreach ($err as $value) {
273 $message .= "\t<error>" . $value . "</error>\n";
277 $message .= "</response>\n";
282 // Returns user group listings(active and inactive lists)
284 // $username = username
285 // $err = error strings (array)
287 function user_group_listings_xml($username, $err)
289 $list_acl_groups = acl_get_group_title_list();
290 $username_acl_groups = acl_get_group_titles($username);
291 //note acl_get_group_titles() returns a 0 if user in no groups
293 $message = "<?xml version=\"1.0\"?>\n" .
296 foreach ($list_acl_groups as $value) {
297 if ((!$username_acl_groups) ||
(!(in_array($value, $username_acl_groups)))) {
298 $message .= "\t\t<group>\n";
299 $message .= "\t\t\t<value>" . $value . "</value>\n";
301 // Modified 6-2009 by BM - Translate gacl group name if applicable
302 $message .= "\t\t\t<label>" . xl_gacl_group($value) . "</label>\n";
304 $message .= "\t\t</group>\n";
308 $message .= "\t</inactive>\n" .
310 if ($username_acl_groups) {
311 foreach ($username_acl_groups as $value) {
312 $message .= "\t\t<group>\n";
313 $message .= "\t\t\t<value>" . $value . "</value>\n";
315 // Modified 6-2009 by BM - Translate gacl group name if applicable
316 $message .= "\t\t\t<label>" . xl_gacl_group($value) . "</label>\n";
318 $message .= "\t\t</group>\n";
322 $message .= "\t</active>\n";
324 foreach ($err as $value) {
325 $message .= "\t<error>" . $value . "</error>\n";
329 $message .= "</response>\n";
334 // Returns acl listings(including return value) via xml message.
335 // $err = error strings (array)
337 function acl_listings_xml($err)
339 global $phpgacl_location;
340 include_once("$phpgacl_location/gacl_api.class.php");
341 $gacl = new gacl_api();
343 $message = "<?xml version=\"1.0\"?>\n" .
345 foreach (acl_get_group_title_list() as $value) {
346 $acl_id = $gacl->search_acl(false, false, false, false, $value, false, false, false, false);
347 foreach ($acl_id as $value2) {
348 $acl = $gacl->get_acl($value2);
349 $ret = $acl["return_value"];
350 $note = $acl["note"];
352 // Modified 6-2009 by BM - Translate gacl group name if applicable
353 // Translate return value
354 // Translate description
355 $message .= "\t<acl>\n" .
356 "\t\t<value>" . $value . "</value>\n" .
357 "\t\t<title>" . xl_gacl_group($value) . "</title>\n" .
358 "\t\t<returnid>" . $ret . "</returnid>\n" .
359 "\t\t<returntitle>" . xl($ret) . "</returntitle>\n" .
360 "\t\t<note>" . xl($note) . "</note>\n" .
366 foreach ($err as $value) {
367 $message .= "\t<error>" . $value . "</error>\n";
371 $message .= "</response>\n";
376 // Return aco listings by sections(active and inactive lists)
378 // $group = group title (string)
379 // $return_value = return value (string)
380 // $err = error strings (array)
382 function aco_listings_xml($group, $return_value, $err)
384 global $phpgacl_location;
385 include_once("$phpgacl_location/gacl_api.class.php");
386 $gacl = new gacl_api();
388 //collect and sort all aco objects
389 $list_aco_objects = $gacl->get_objects(null, 0, 'ACO');
390 foreach ($list_aco_objects as $key => $value) {
391 asort($list_aco_objects[$key]);
394 //collect aco objects within the specified acl(already sorted)
395 $acl_id = $gacl->search_acl(false, false, false, false, $group, false, false, false, $return_value);
396 $acl = $gacl->get_acl($acl_id[0]);
397 $active_aco_objects = $acl["aco"];
399 $message = "<?xml version=\"1.0\"?>\n" .
402 foreach ($list_aco_objects as $key => $value) {
404 foreach ($list_aco_objects[$key] as $value2) {
405 if (!array_key_exists($key, $active_aco_objects) ||
!in_array($value2, $active_aco_objects[$key])) {
407 $counter = $counter +
1;
408 $aco_section_data = $gacl->get_section_data($key, 'ACO');
409 $aco_section_title = $aco_section_data[3];
411 // Modified 6-2009 by BM - Translate gacl aco section name
412 $message .= "\t\t<section>\n" .
413 "\t\t\t<name>" . xl($aco_section_title) . "</name>\n";
416 $aco_id = $gacl->get_object_id($key, $value2, 'ACO');
417 $aco_data = $gacl->get_object_data($aco_id, 'ACO');
418 $aco_title = $aco_data[0][3];
419 $message .= "\t\t\t<aco>\n";
421 // Modified 6-2009 by BM - Translate gacl aco name
422 $message .= "\t\t\t\t<title>" . xl($aco_title) . "</title>\n";
424 $message .= "\t\t\t\t<id>" . $aco_id . "</id>\n";
425 $message .= "\t\t\t</aco>\n";
430 $message .= "\t\t</section>\n";
434 $message .= "\t</inactive>\n" .
436 foreach ($active_aco_objects as $key => $value) {
437 $aco_section_data = $gacl->get_section_data($key, 'ACO');
438 $aco_section_title = $aco_section_data[3];
440 // Modified 6-2009 by BM - Translate gacl aco section name
441 $message .= "\t\t<section>\n" .
442 "\t\t\t<name>" . xl($aco_section_title) . "</name>\n";
444 foreach ($active_aco_objects[$key] as $value2) {
445 $aco_id = $gacl->get_object_id($key, $value2, 'ACO');
446 $aco_data = $gacl->get_object_data($aco_id, 'ACO');
447 $aco_title = $aco_data[0][3];
448 $message .= "\t\t\t<aco>\n";
450 // Modified 6-2009 by BM - Translate gacl aco name
451 $message .= "\t\t\t\t<title>" . xl($aco_title) . "</title>\n";
453 $message .= "\t\t\t\t<id>" . $aco_id . "</id>\n";
454 $message .= "\t\t\t</aco>\n";
457 $message .= "\t\t</section>\n";
460 $message .= "\t</active>\n";
462 foreach ($err as $value) {
463 $message .= "\t<error>" . $value . "</error>\n";
467 $message .= "</response>\n";
472 // Returns listing of all possible return values via xml message.
473 // $err = error strings (array)
475 function return_values_xml($err)
477 global $phpgacl_location;
478 include_once("$phpgacl_location/gacl_api.class.php");
479 $gacl = new gacl_api();
482 $message = "<?xml version=\"1.0\"?>\n" .
484 foreach (acl_get_group_title_list() as $value) {
485 $acl_id = $gacl->search_acl(false, false, false, false, $value, false, false, false, false);
486 foreach ($acl_id as $value2) {
487 $acl = $gacl->get_acl($value2);
488 $ret = $acl["return_value"];
489 if (!in_array($ret, $returns)) {
490 // Modified 6-2009 by BM - Translate return value
491 $message .= "\t<return>\n";
492 $message .= "\t\t<returnid>" . $ret . "</returnid>\n";
493 $message .= "\t\t<returntitle>" . xl($ret) . "</returntitle>\n";
494 $message .= "\t</return>\n";
496 array_push($returns, $ret);
502 foreach ($err as $value) {
503 $message .= "\t<error>" . $value . "</error>\n";
507 $message .= "</response>\n";
512 // Returns error string(s) via xml
513 // $err = error (string or array)
515 function error_xml($err)
517 $message = "<?xml version=\"1.0\"?>\n" .
519 if (is_array($err)) {
520 foreach ($err as $value) {
521 $message .= "\t<error>" . $value . "</error>\n";
524 $message .= "\t<error>" . $err . "</error>\n";
527 $message .= "</response>\n";