Refactor previous name into dedicated service (#7571)
[openemr.git] / library / ajax / adminacl_ajax.php
blobd9b9d03b0e1c11442fd58ed548133c0fabd832eb
1 <?php
3 /**
4 * This file contains functions that service ajax requests for
5 * ACL(php-gacl) administration within OpenEMR. All returns are
6 * done via xml.
8 * Important - Ensure that display_errors=Off in php.ini settings.
10 * @package OpenEMR
11 * @link https://www.open-emr.org
12 * @author Brady Miller <brady.g.miller@gmail.com>
13 * @author Rod Roark <rod@sunsetsystems.com>
14 * @copyright Copyright (c) 2007-2018 Brady Miller <brady.g.miller@gmail.com>
15 * @copyright Copyright (c) 2021 Rod Roark <rod@sunsetsystems.com>
16 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
19 require_once("../../interface/globals.php");
20 require_once("$srcdir/user.inc.php");
22 use OpenEMR\Common\Acl\AclExtended;
23 use OpenEMR\Common\Acl\AclMain;
24 use OpenEMR\Common\Csrf\CsrfUtils;
25 use OpenEMR\Common\Logging\EventAuditLogger;
26 use OpenEMR\Services\UserService;
29 header("Content-type: text/xml");
30 header("Cache-Control: no-cache");
32 //initiate error array
33 $error = array();
35 //verify csrf
36 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
37 echo error_xml(xl('Authentication Error'));
38 CsrfUtils::csrfNotVerified(false);
41 //ensure user has proper access
42 if (!AclMain::aclCheckCore('admin', 'acl')) {
43 echo error_xml(xl('ACL Administration Not Authorized'));
44 CsrfUtils::csrfNotVerified(false);
47 //Display red alert if Emergency Login ACL is activated for a user.
48 if ($_POST["action"] == "add") {
49 if (!empty($_POST["selection"]) && is_array($_POST["selection"]) && in_array("Emergency Login", $_POST["selection"])) {
50 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.') ));
54 //PROCESS USERNAME REQUESTS
55 if ($_POST["control"] == "username") {
56 if ($_POST["action"] == "list") {
57 //return username list with alert if user is not joined to group
58 echo username_listings_xml($error);
63 //PROCESS MEMBERSHIP REQUESTS
64 if ($_POST["control"] == "membership") {
65 if ($_POST["action"] == "list") {
66 //return membership data
67 echo user_group_listings_xml($_POST["name"], $error);
70 if ($_POST["action"] == "add") {
71 if ($_POST["selection"][0] == "null") {
72 //no selection, return soft error, and just return membership data
73 array_push($error, (xl('No group was selected') . "!"));
74 echo user_group_listings_xml($_POST["name"], $error);
75 exit;
78 //add the group, then log it, then return updated membership data
79 AclExtended::addUserAros($_POST["name"], $_POST["selection"]);
80 EventAuditLogger::instance()->newEvent("security-administration-update", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Added " . $_POST["name"] . " to following access group(s): " . implode(', ', $_POST["selection"]));
81 echo user_group_listings_xml($_POST["name"], $error);
84 if ($_POST["action"] == "remove") {
85 if ($_POST["selection"][0] == "null") {
86 //no selection, return soft error, and just return membership data
87 array_push($error, (xl('No group was selected') . "!"));
88 echo user_group_listings_xml($_POST["name"], $error);
89 exit;
92 // check if user is protected. If so, then state message unable to remove from admin group.
93 $userNametoID = (new UserService())->getIdByUsername($_POST["name"]);
94 if (checkUserSetting("gacl_protect", "1", $userNametoID) || ($_POST["name"] == "admin")) {
95 $gacl_protect = true;
96 } else {
97 $gacl_protect = false;
100 if ($gacl_protect && in_array("Administrators", $_POST["selection"])) {
101 //unable to remove admin user from administrators group, process remove,
102 // send soft error, then return data
103 array_push($error, (xl('Not allowed to remove this user from the Administrators group') . "!"));
104 AclExtended::removeUserAros($_POST["name"], $_POST["selection"]);
105 echo user_group_listings_xml($_POST["name"], $error);
106 exit;
109 //remove the group(s), then log it, then return updated membership data
110 AclExtended::removeUserAros($_POST["name"], $_POST["selection"]);
111 EventAuditLogger::instance()->newEvent("security-administration-update", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Removed " . $_POST["name"] . " from following access group(s): " . implode(', ', $_POST["selection"]));
112 echo user_group_listings_xml($_POST["name"], $error);
117 //PROCESS ACL REQUESTS
118 if ($_POST["control"] == "acl") {
119 if ($_POST["action"] == "list") {
120 //return acl titles with return values
121 echo AclExtended::aclListingsXml($error);
124 if ($_POST["action"] == "add") {
125 //validate form data
126 $form_error = false;
127 if (empty($_POST["title"])) {
128 $form_error = true;
129 array_push($error, ("title_" . xl('Need to enter title') . "!"));
130 } elseif (!ctype_alpha(str_replace(' ', '', $_POST["title"]))) {
131 $form_error = true;
132 array_push($error, ("title_" . xl('Please only use alphabetic characters') . "!"));
133 } elseif (AclExtended::aclExist($_POST["title"], false, $_POST["return_value"])) {
134 $form_error = true;
135 array_push($error, ("title_" . xl('Already used, choose another title') . "!"));
138 if (empty($_POST["identifier"])) {
139 $form_error = true;
140 array_push($error, ("identifier_" . xl('Need to enter identifier') . "!"));
141 } elseif (!ctype_alpha($_POST["identifier"])) {
142 $form_error = true;
143 array_push($error, ("identifier_" . xl('Please only use alphabetic characters with no spaces') . "!"));
144 } elseif (AclExtended::aclExist(false, $_POST["identifier"], $_POST["return_value"])) {
145 $form_error = true;
146 array_push($error, ("identifier_" . xl('Already used, choose another identifier') . "!"));
149 if (empty($_POST["return_value"])) {
150 $form_error = true;
151 array_push($error, ("return_" . xl('Need to enter a Return Value') . "!"));
154 if (empty($_POST["description"])) {
155 $form_error = true;
156 array_push($error, ("description_" . xl('Need to enter a description') . "!"));
157 } elseif (!ctype_alpha(str_replace(' ', '', $_POST["description"]))) {
158 $form_error = true;
159 array_push($error, ("description_" . xl('Please only use alphabetic characters') . "!"));
162 //process if data is valid
163 if (!$form_error) {
164 AclExtended::aclAdd($_POST["title"], $_POST["identifier"], $_POST["return_value"], $_POST["description"]);
165 echo "<?xml version=\"1.0\"?>\n" .
166 "<response>\n" .
167 "\t<success>SUCCESS</success>\n" .
168 "</response>\n";
169 } else { //$form_error = true, so return errors
170 echo error_xml($error);
174 if ($_POST["action"] == "remove") {
175 //validate form data
176 $form_error = false;
177 if (empty($_POST["title"])) {
178 $form_error = true;
179 array_push($error, ("aclTitle_" . xl('Need to enter title') . "!"));
182 if ($_POST["title"] == "Administrators") {
183 $form_error = true;
184 array_push($error, ("aclTitle_" . xl('Not allowed to delete the Administrators group') . "!"));
187 //process if data is valid
188 if (!$form_error) {
189 AclExtended::aclRemove($_POST["title"], $_POST["return_value"]);
190 echo "<?xml version=\"1.0\"?>\n" .
191 "<response>\n" .
192 "\t<success>SUCCESS</success>\n" .
193 "</response>\n";
194 } else { //$form_error = true, so return errors
195 echo error_xml($error);
199 if ($_POST["action"] == "returns") {
200 //simply return all the possible acl return_values
201 echo AclExtended::returnValuesXml($error);
206 //PROCESS ACO REQUESTS
207 if ($_POST["control"] == "aco") {
208 if ($_POST["action"] == "list") {
209 //send acl data
210 echo AclExtended::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
213 if ($_POST["action"] == "add") {
214 if ($_POST["selection"][0] == "null") {
215 //no selection, return soft error, and just return data
216 array_push($error, (xl('Nothing was selected') . "!"));
217 echo AclExtended::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
218 exit;
221 //add the aco, then return updated membership data
222 AclExtended::aclAddAcos($_POST["name"], $_POST["return_value"], $_POST["selection"]);
223 echo AclExtended::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
226 if ($_POST["action"] == "remove") {
227 if ($_POST["selection"][0] == "null") {
228 //no selection, return soft error, and just return data
229 array_push($error, (xl('Nothing was selected') . "!"));
230 echo AclExtended::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
231 exit;
234 if ($_POST["name"] == "Administrators") {
235 //will not allow removal of acos from Administrators ACL
236 array_push($error, (xl('Not allowed to inactivate anything from the Administrators ACL') . "!"));
237 echo AclExtended::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
238 exit;
241 //remove the acos, then return updated data
242 AclExtended::aclRemoveAcos($_POST["name"], $_POST["return_value"], $_POST["selection"]);
243 echo AclExtended::acoListingsXml($_POST["name"], $_POST["return_value"], $error);
249 // Returns username listings via xml message.
250 // It will also include alert if user is not joined
251 // to a group yet
252 // $err = error strings (array)
254 function username_listings_xml($err)
256 $message = "<?xml version=\"1.0\"?>\n" .
257 "<response>\n";
258 $res = sqlStatement("select * from users where username != '' and active = 1 order by username");
259 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
260 $result4[$iter] = $row;
263 foreach ($result4 as $iter) {
264 // Skip this user if logged-in user does not have all of its permissions.
265 // Note that a superuser now has all permissions.
266 if (!AclExtended::iHavePermissionsOf($iter['username'])) {
267 continue;
270 $message .= "\t<user>\n" .
271 "\t\t<username>" . $iter["username"] . "</username>\n";
272 $username_acl_groups = AclExtended::aclGetGroupTitles($iter["username"]);
273 if (!$username_acl_groups) {
274 //not joined to any group, so send alert
275 $message .= "\t\t<alert>no membership</alert>\n";
278 $message .= "\t</user>\n";
281 if (isset($err)) {
282 foreach ($err as $value) {
283 $message .= "\t<error>" . $value . "</error>\n";
287 $message .= "</response>\n";
288 return $message;
292 // Returns user group listings(active and inactive lists)
293 // via xml message.
294 // $username = username
295 // $err = error strings (array)
297 function user_group_listings_xml($username, $err)
299 $list_acl_groups = AclExtended::aclGetGroupTitleList();
300 $username_acl_groups = AclExtended::aclGetGroupTitles($username);
301 //note aclGetGroupTitles() returns a 0 if user in no groups
303 $message = "<?xml version=\"1.0\"?>\n" .
304 "<response>\n" .
305 "\t<inactive>\n";
306 foreach ($list_acl_groups as $value) {
307 if ((!$username_acl_groups) || (!(in_array($value, $username_acl_groups)))) {
308 $message .= "\t\t<group>\n";
309 $message .= "\t\t\t<value>" . $value . "</value>\n";
311 // Modified 6-2009 by BM - Translate gacl group name if applicable
312 $message .= "\t\t\t<label>" . xl_gacl_group($value) . "</label>\n";
314 $message .= "\t\t</group>\n";
318 $message .= "\t</inactive>\n" .
319 "\t<active>\n";
320 if ($username_acl_groups) {
321 foreach ($username_acl_groups as $value) {
322 $message .= "\t\t<group>\n";
323 $message .= "\t\t\t<value>" . $value . "</value>\n";
325 // Modified 6-2009 by BM - Translate gacl group name if applicable
326 $message .= "\t\t\t<label>" . xl_gacl_group($value) . "</label>\n";
328 $message .= "\t\t</group>\n";
332 $message .= "\t</active>\n";
333 if (isset($err)) {
334 foreach ($err as $value) {
335 $message .= "\t<error>" . $value . "</error>\n";
339 $message .= "</response>\n";
340 return $message;
344 // Returns error string(s) via xml
345 // $err = error (string or array)
347 function error_xml($err)
349 $message = "<?xml version=\"1.0\"?>\n" .
350 "<response>\n";
351 if (is_array($err)) {
352 foreach ($err as $value) {
353 $message .= "\t<error>" . $value . "</error>\n";
355 } else {
356 $message .= "\t<error>" . $err . "</error>\n";
359 $message .= "</response>\n";
360 return $message;