4 * This file contains functions that service ajax requests for
5 * ACL(php-gacl) administration within OpenEMR. All returns are
8 * Important - Ensure that display_errors=Off in php.ini settings.
11 * @link https://www.open-emr.org
12 * @author Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2007-2018 Brady Miller <brady.g.miller@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 require_once("../../interface/globals.php");
18 require_once("$srcdir/user.inc");
20 use OpenEMR\Common\Acl\AclExtended
;
21 use OpenEMR\Common\Acl\AclMain
;
22 use OpenEMR\Common\Csrf\CsrfUtils
;
23 use OpenEMR\Common\Logging\EventAuditLogger
;
24 use OpenEMR\Services\UserService
;
27 header("Content-type: text/xml");
28 header("Cache-Control: no-cache");
30 //initiate error array
34 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
35 echo error_xml(xl('Authentication Error'));
36 CsrfUtils
::csrfNotVerified(false);
39 //ensure user has proper access
40 if (!AclMain
::aclCheckCore('admin', 'acl')) {
41 echo error_xml(xl('ACL Administration Not Authorized'));
42 CsrfUtils
::csrfNotVerified(false);
45 //Display red alert if Emergency Login ACL is activated for a user.
46 if ($_POST["action"] == "add") {
47 if (!empty($_POST["selection"]) && 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 log it, then return updated membership data
77 AclExtended
::addUserAros($_POST["name"], $_POST["selection"]);
78 EventAuditLogger
::instance()->newEvent("security-administration-update", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Added " . $_POST["name"] . " to following access group(s): " . implode(', ', $_POST["selection"]));
79 echo user_group_listings_xml($_POST["name"], $error);
82 if ($_POST["action"] == "remove") {
83 if ($_POST["selection"][0] == "null") {
84 //no selection, return soft error, and just return membership data
85 array_push($error, (xl('No group was selected') . "!"));
86 echo user_group_listings_xml($_POST["name"], $error);
90 // check if user is protected. If so, then state message unable to remove from admin group.
91 $userNametoID = (new $userService())->getIdByUsername($_POST["name"]);
92 if (checkUserSetting("gacl_protect", "1", $userNametoID) ||
($_POST["name"] == "admin")) {
95 $gacl_protect = false;
98 if ($gacl_protect && in_array("Administrators", $_POST["selection"])) {
99 //unable to remove admin user from administrators group, process remove,
100 // send soft error, then return data
101 array_push($error, (xl('Not allowed to remove this user from the Administrators group') . "!"));
102 AclExtended
::removeUserAros($_POST["name"], $_POST["selection"]);
103 echo user_group_listings_xml($_POST["name"], $error);
107 //remove the group(s), then log it, then return updated membership data
108 AclExtended
::removeUserAros($_POST["name"], $_POST["selection"]);
109 EventAuditLogger
::instance()->newEvent("security-administration-update", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Removed " . $_POST["name"] . " from following access group(s): " . implode(', ', $_POST["selection"]));
110 echo user_group_listings_xml($_POST["name"], $error);
115 //PROCESS ACL REQUESTS
116 if ($_POST["control"] == "acl") {
117 if ($_POST["action"] == "list") {
118 //return acl titles with return values
119 echo AclExtended
::aclListingsXml($error);
122 if ($_POST["action"] == "add") {
125 if (empty($_POST["title"])) {
127 array_push($error, ("title_" . xl('Need to enter title') . "!"));
128 } elseif (!ctype_alpha(str_replace(' ', '', $_POST["title"]))) {
130 array_push($error, ("title_" . xl('Please only use alphabetic characters') . "!"));
131 } elseif (AclExtended
::aclExist($_POST["title"], false, $_POST["return_value"])) {
133 array_push($error, ("title_" . xl('Already used, choose another title') . "!"));
136 if (empty($_POST["identifier"])) {
138 array_push($error, ("identifier_" . xl('Need to enter identifier') . "!"));
139 } elseif (!ctype_alpha($_POST["identifier"])) {
141 array_push($error, ("identifier_" . xl('Please only use alphabetic characters with no spaces') . "!"));
142 } elseif (AclExtended
::aclExist(false, $_POST["identifier"], $_POST["return_value"])) {
144 array_push($error, ("identifier_" . xl('Already used, choose another identifier') . "!"));
147 if (empty($_POST["return_value"])) {
149 array_push($error, ("return_" . xl('Need to enter a Return Value') . "!"));
152 if (empty($_POST["description"])) {
154 array_push($error, ("description_" . xl('Need to enter a description') . "!"));
155 } elseif (!ctype_alpha(str_replace(' ', '', $_POST["description"]))) {
157 array_push($error, ("description_" . xl('Please only use alphabetic characters') . "!"));
160 //process if data is valid
162 AclExtended
::aclAdd($_POST["title"], $_POST["identifier"], $_POST["return_value"], $_POST["description"]);
163 echo "<?xml version=\"1.0\"?>\n" .
165 "\t<success>SUCCESS</success>\n" .
167 } else { //$form_error = true, so return errors
168 echo error_xml($error);
172 if ($_POST["action"] == "remove") {
175 if (empty($_POST["title"])) {
177 array_push($error, ("aclTitle_" . xl('Need to enter title') . "!"));
180 if ($_POST["title"] == "Administrators") {
182 array_push($error, ("aclTitle_" . xl('Not allowed to delete the Administrators group') . "!"));
185 //process if data is valid
187 AclExtended
::aclRemove($_POST["title"], $_POST["return_value"]);
188 echo "<?xml version=\"1.0\"?>\n" .
190 "\t<success>SUCCESS</success>\n" .
192 } else { //$form_error = true, so return errors
193 echo error_xml($error);
197 if ($_POST["action"] == "returns") {
198 //simply return all the possible acl return_values
199 echo AclExtended
::returnValuesXml($error);
204 //PROCESS ACO REQUESTS
205 if ($_POST["control"] == "aco") {
206 if ($_POST["action"] == "list") {
208 echo AclExtended
::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
211 if ($_POST["action"] == "add") {
212 if ($_POST["selection"][0] == "null") {
213 //no selection, return soft error, and just return data
214 array_push($error, (xl('Nothing was selected') . "!"));
215 echo AclExtended
::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
219 //add the aco, then return updated membership data
220 AclExtended
::aclAddAcos($_POST["name"], $_POST["return_value"], $_POST["selection"]);
221 echo AclExtended
::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
224 if ($_POST["action"] == "remove") {
225 if ($_POST["selection"][0] == "null") {
226 //no selection, return soft error, and just return data
227 array_push($error, (xl('Nothing was selected') . "!"));
228 echo AclExtended
::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
232 if ($_POST["name"] == "Administrators") {
233 //will not allow removal of acos from Administrators ACL
234 array_push($error, (xl('Not allowed to inactivate anything from the Administrators ACL') . "!"));
235 echo AclExtended
::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
239 //remove the acos, then return updated data
240 AclExtended
::aclRemoveAcos($_POST["name"], $_POST["return_value"], $_POST["selection"]);
241 echo AclExtended
::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
247 // Returns username listings via xml message.
248 // It will also include alert if user is not joined
250 // $err = error strings (array)
252 function username_listings_xml($err)
254 $message = "<?xml version=\"1.0\"?>\n" .
256 $res = sqlStatement("select * from users where username != '' and active = 1 order by username");
257 for ($iter = 0; $row = sqlFetchArray($res); $iter++
) {
258 $result4[$iter] = $row;
261 foreach ($result4 as $iter) {
262 $message .= "\t<user>\n" .
263 "\t\t<username>" . $iter["username"] . "</username>\n";
264 $username_acl_groups = AclExtended
::aclGetGroupTitles($iter["username"]);
265 if (!$username_acl_groups) {
266 //not joined to any group, so send alert
267 $message .= "\t\t<alert>no membership</alert>\n";
270 $message .= "\t</user>\n";
274 foreach ($err as $value) {
275 $message .= "\t<error>" . $value . "</error>\n";
279 $message .= "</response>\n";
284 // Returns user group listings(active and inactive lists)
286 // $username = username
287 // $err = error strings (array)
289 function user_group_listings_xml($username, $err)
291 $list_acl_groups = AclExtended
::aclGetGroupTitleList();
292 $username_acl_groups = AclExtended
::aclGetGroupTitles($username);
293 //note aclGetGroupTitles() returns a 0 if user in no groups
295 $message = "<?xml version=\"1.0\"?>\n" .
298 foreach ($list_acl_groups as $value) {
299 if ((!$username_acl_groups) ||
(!(in_array($value, $username_acl_groups)))) {
300 $message .= "\t\t<group>\n";
301 $message .= "\t\t\t<value>" . $value . "</value>\n";
303 // Modified 6-2009 by BM - Translate gacl group name if applicable
304 $message .= "\t\t\t<label>" . xl_gacl_group($value) . "</label>\n";
306 $message .= "\t\t</group>\n";
310 $message .= "\t</inactive>\n" .
312 if ($username_acl_groups) {
313 foreach ($username_acl_groups as $value) {
314 $message .= "\t\t<group>\n";
315 $message .= "\t\t\t<value>" . $value . "</value>\n";
317 // Modified 6-2009 by BM - Translate gacl group name if applicable
318 $message .= "\t\t\t<label>" . xl_gacl_group($value) . "</label>\n";
320 $message .= "\t\t</group>\n";
324 $message .= "\t</active>\n";
326 foreach ($err as $value) {
327 $message .= "\t<error>" . $value . "</error>\n";
331 $message .= "</response>\n";
336 // Returns error string(s) via xml
337 // $err = error (string or array)
339 function error_xml($err)
341 $message = "<?xml version=\"1.0\"?>\n" .
343 if (is_array($err)) {
344 foreach ($err as $value) {
345 $message .= "\t<error>" . $value . "</error>\n";
348 $message .= "\t<error>" . $err . "</error>\n";
351 $message .= "</response>\n";