Account and permission manager and security log viewer. https://netsyms.biz/apps/managepanel
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

action.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /**
  6. * Make things happen when buttons are pressed and forms submitted.
  7. */
  8. require_once __DIR__ . "/required.php";
  9. if ($VARS['action'] !== "signout") {
  10. dieifnotloggedin();
  11. }
  12. /**
  13. * Redirects back to the page ID in $_POST/$_GET['source'] with the given message ID.
  14. * The message will be displayed by the app.
  15. * @param string $msg message ID (see lang/messages.php)
  16. * @param string $arg If set, replaces "{arg}" in the message string when displayed to the user.
  17. * @param [key=>val] $additional Put the given key-value array in the URL
  18. */
  19. function returnToSender($msg, $arg = "", $additional = []) {
  20. global $VARS;
  21. $add = "";
  22. if ($additional != []) {
  23. foreach ($additional as $key => $val) {
  24. $add .= "&" . urlencode($key) . "=" . urlencode($val);
  25. }
  26. }
  27. if ($arg == "") {
  28. header("Location: app.php?page=" . urlencode($VARS['source']) . $add . "&msg=" . $msg);
  29. } else {
  30. header("Location: app.php?page=" . urlencode($VARS['source']) . $add . "&msg=$msg&arg=$arg");
  31. }
  32. die();
  33. }
  34. switch ($VARS['action']) {
  35. case "edituser":
  36. if (empty($VARS['id'])) {
  37. $insert = true;
  38. } else {
  39. if ($database->has('accounts', ['uid' => $VARS['id']])) {
  40. $insert = false;
  41. } else {
  42. returnToSender("invalid_userid");
  43. }
  44. }
  45. if (empty($VARS['name']) || empty($VARS['username']) || empty($VARS['status'])) {
  46. returnToSender('invalid_parameters');
  47. }
  48. if (!$database->has('acctstatus', ['statusid' => $VARS['status']])) {
  49. returnToSender("invalid_parameters");
  50. }
  51. $data = [
  52. 'realname' => $VARS['name'],
  53. 'username' => $VARS['username'],
  54. 'email' => $VARS['email'],
  55. 'acctstatus' => $VARS['status'],
  56. 'deleted' => 0
  57. ];
  58. if (!empty($VARS['pass'])) {
  59. $data['password'] = password_hash($VARS['pass'], PASSWORD_BCRYPT);
  60. }
  61. if ($insert) {
  62. $data['phone1'] = "";
  63. $data['phone2'] = "";
  64. $data['accttype'] = 1;
  65. $database->insert('accounts', $data);
  66. Log::insert(LogType::USER_ADDED, $_SESSION['uid'], $data['username'] . ", " . $data['realname'] . ", " . $data['email'] . ", " . $data['acctstatus']);
  67. } else {
  68. $olddata = $database->select('accounts', '*', ['uid' => $VARS['id']])[0];
  69. $database->update('accounts', $data, ['uid' => $VARS['id']]);
  70. Log::insert(LogType::USER_EDITED, $_SESSION['uid'], "OLD: " . $olddata['username'] . ", " . $olddata['realname'] . ", " . $olddata['email'] . ", " . $olddata['acctstatus'] . "; NEW: " . $data['username'] . ", " . $data['realname'] . ", " . $data['email'] . ", " . $data['acctstatus']);
  71. }
  72. returnToSender("user_saved");
  73. case "deleteuser":
  74. if ($database->has('accounts', ['uid' => $VARS['id']]) !== TRUE) {
  75. returnToSender("invalid_userid");
  76. }
  77. $olddata = $database->select('accounts', '*', ['uid' => $VARS['id']])[0];
  78. $database->delete('accounts', ['uid' => $VARS['id']]);
  79. if (!is_null($database->error()[1])) {
  80. // If we can't delete the account (because it's referenced elsewhere),
  81. // we will flag it as deleted and set the status to LOCKED_OR_DISABLED.
  82. $database->update('accounts', ['acctstatus' => 2, 'deleted' => 1], ['uid' => $VARS['id']]);
  83. }
  84. Log::insert(LogType::USER_REMOVED, $_SESSION['uid'], $olddata['username'] . ", " . $olddata['realname'] . ", " . $olddata['email'] . ", " . $olddata['acctstatus']);
  85. returnToSender("user_deleted");
  86. case "rmtotp":
  87. if ($database->has('accounts', ['uid' => $VARS['id']]) !== TRUE) {
  88. returnToSender("invalid_userid");
  89. }
  90. $u = $database->get('accounts', 'username', ['uid' => $VARS['id']]);
  91. $database->update('accounts', ["authsecret" => null], ['uid' => $VARS['id']]);
  92. Log::insert(LogType::REMOVED_2FA, $_SESSION['uid'], $u);
  93. returnToSender("2fa_removed");
  94. case "clearlog":
  95. $rows = $database->count('authlog');
  96. $database->delete('authlog', []);
  97. Log::insert(LogType::LOG_CLEARED, $_SESSION['uid'], $Strings->build("removed n entries", ['n' => $rows], false));
  98. returnToSender("log_cleared");
  99. case "editmanager":
  100. if (!$database->has('accounts', ['username' => $VARS['manager']])) {
  101. returnToSender("invalid_manager");
  102. }
  103. $manager = User::byUsername($VARS['manager'])->getUID();
  104. $already_assigned = $database->select('managers', 'employeeid', ['managerid' => $manager]);
  105. foreach ($VARS['employees'] as $u) {
  106. $emp = User::byUsername($u);
  107. if (!$emp->exists()) {
  108. returnToSender("user_not_exists", htmlentities($emp->getUsername()));
  109. }
  110. $database->insert('managers', ['employeeid' => $emp->getUID(), 'managerid' => $manager]);
  111. $already_assigned = array_diff($already_assigned, [$emp->getUID()]); // Remove user from old list
  112. }
  113. foreach ($already_assigned as $uid) {
  114. $database->delete('managers', ["AND" => ['employeeid' => $uid, 'managerid' => $manager]]);
  115. }
  116. returnToSender("manager_assigned", "", ["man" => $VARS['manager']]);
  117. break;
  118. case "addmanager":
  119. if (!$database->has('accounts', ['username' => $VARS['manager']])) {
  120. returnToSender("invalid_userid");
  121. }
  122. if (!$database->has('accounts', ['username' => $VARS['employee']])) {
  123. returnToSender("invalid_userid");
  124. }
  125. $manageruid = $database->select('accounts', 'uid', ['username' => $VARS['manager']])[0];
  126. $employeeuid = $database->select('accounts', 'uid', ['username' => $VARS['employee']])[0];
  127. $database->insert('managers', ['managerid' => $manageruid, 'employeeid' => $employeeuid]);
  128. returnToSender("relationship_added");
  129. case "delmanager":
  130. if (!$database->has('managers', ['managerid' => $VARS['mid']])) {
  131. returnToSender("invalid_userid");
  132. }
  133. if (!$database->has('managers', ['employeeid' => $VARS['eid']])) {
  134. returnToSender("invalid_userid");
  135. }
  136. $database->delete('managers', ['AND' => ['managerid' => $VARS['mid'], 'employeeid' => $VARS['eid']]]);
  137. returnToSender("relationship_deleted");
  138. case "editperms":
  139. if (!$database->has('accounts', ['username' => $VARS['user']])) {
  140. returnToSender("invalid_userid");
  141. }
  142. $uid = $database->select('accounts', 'uid', ['username' => $VARS['user']])[0];
  143. $already_assigned = $database->select('assigned_permissions', 'permid', ['uid' => $uid]);
  144. $permids = [];
  145. foreach ($VARS['permissions'] as $perm) {
  146. if (!$database->has('permissions', ['permcode' => $perm])) {
  147. returnToSender("permission_not_exists", htmlentities($perm));
  148. }
  149. $permid = $database->get('permissions', 'permid', ['permcode' => $perm]);
  150. $permids[] = $permid;
  151. $already_assigned = array_diff($already_assigned, [$permid]); // Remove permission from old list
  152. }
  153. foreach ($already_assigned as $permid) {
  154. $database->delete('assigned_permissions', ["AND" => ['uid' => $uid, 'permid' => $permid]]);
  155. }
  156. foreach ($permids as $permid) {
  157. $database->insert('assigned_permissions', ['uid' => $uid, 'permid' => $permid]);
  158. }
  159. returnToSender("permissions_assigned", "", ["user" => $VARS['user']]);
  160. case "addpermission":
  161. if (!$database->has('accounts', ['username' => $VARS['user']])) {
  162. returnToSender("invalid_userid");
  163. }
  164. if (!$database->has('permissions', ['permcode' => $VARS['perm']])) {
  165. returnToSender("permission_not_exists", htmlentities($VARS['perm']));
  166. }
  167. $uid = $database->select('accounts', 'uid', ['username' => $VARS['user']])[0];
  168. $pid = $database->select('permissions', 'permid', ['permcode' => $VARS['perm']])[0];
  169. $database->insert('assigned_permissions', ['uid' => $uid, 'permid' => $pid]);
  170. returnToSender("permission_added");
  171. case "delpermission":
  172. if (!$database->has('accounts', ['uid' => $VARS['uid']])) {
  173. returnToSender("invalid_userid");
  174. }
  175. if (!$database->has('permissions', ['permid' => $VARS['pid']])) {
  176. returnToSender("permission_not_exists", htmlentities($VARS['pid']));
  177. }
  178. $database->delete('assigned_permissions', ['AND' => ['uid' => $VARS['uid'], 'permid' => $VARS['pid']]]);
  179. returnToSender("permission_deleted");
  180. case "autocomplete_user":
  181. header("Content-Type: application/json");
  182. if (empty($VARS['q']) || strlen($VARS['q']) < 3) {
  183. exit(json_encode([]));
  184. }
  185. $data = $database->select('accounts', ['uid', 'username', 'realname (name)'], ["OR" => ['username[~]' => $VARS['q'], 'realname[~]' => $VARS['q']], "LIMIT" => 10]);
  186. exit(json_encode($data));
  187. case "autocomplete_permission":
  188. header("Content-Type: application/json");
  189. if (empty($VARS['q'])) {
  190. exit(json_encode([]));
  191. }
  192. $data = $database->select('permissions', ['permcode (name)', 'perminfo (info)'], ["OR" => ['permcode[~]' => $VARS['q'], 'perminfo[~]' => $VARS['q']], "LIMIT" => 10]);
  193. exit(json_encode($data));
  194. case "assigngroup":
  195. if (!$database->has('groups', ['groupid' => $VARS['gid']])) {
  196. returnToSender("invalid_group");
  197. }
  198. $gid = $VARS['gid'];
  199. $already_assigned = $database->select('assigned_groups', 'uid', ['groupid' => $gid]);
  200. foreach ($VARS['users'] as $u) {
  201. $user = User::byUsername($u);
  202. if (!$user->exists()) {
  203. returnToSender("user_not_exists", htmlentities($user->getUsername()));
  204. }
  205. $database->insert('assigned_groups', ['groupid' => $gid, 'uid' => $user->getUID()]);
  206. $already_assigned = array_diff($already_assigned, [$user->getUID()]); // Remove user from old list
  207. }
  208. foreach ($already_assigned as $uid) {
  209. $database->delete('assigned_groups', ["AND" => ['uid' => $uid, 'groupid' => $gid]]);
  210. }
  211. returnToSender("group_assigned", "", ["gid" => $gid]);
  212. break;
  213. case "addgroup":
  214. $group = htmlspecialchars(strip_tags($VARS['group']), ENT_HTML5);
  215. if ($database->has('groups', ['groupname' => $group])) {
  216. returnToSender("group_exists");
  217. }
  218. $database->insert('groups', ['groupname' => $group]);
  219. returnToSender("group_added");
  220. case "rmgroup":
  221. if (!$database->has('groups', ['groupid' => $VARS['gid']])) {
  222. returnToSender("invalid_group");
  223. }
  224. $database->delete('assigned_groups', ['groupid' => $VARS['gid']]);
  225. $database->delete('groups', ['groupid' => $VARS['gid']]);
  226. returnToSender("group_deleted");
  227. case "export":
  228. require_once __DIR__ . "/lib/reports.php";
  229. generateReport($VARS['type'], $VARS['format']);
  230. break;
  231. case "revokeapikey":
  232. if (empty($VARS['key'])) {
  233. returnToSender("invalid_parameters");
  234. }
  235. if ($VARS['key'] == $SETTINGS['accounthub']['key']) {
  236. returnToSender("cannot_revoke_key_in_use");
  237. }
  238. $database->delete("apikeys", ['key' => $VARS['key'], "LIMIT" => 1]);
  239. returnToSender("api_key_revoked");
  240. break;
  241. case "addapikey":
  242. if (empty($VARS['key']) || empty($VARS['type'])) {
  243. returnToSender("invalid_parameters");
  244. }
  245. $keytypes = ["NONE", "AUTH", "READ", "FULL"];
  246. if (!in_array($VARS['type'], $keytypes)) {
  247. returnToSender("invalid_parameters");
  248. }
  249. if ($database->has("apikeys", ["key" => $VARS['key']])) {
  250. returnToSender("key_already_exists");
  251. }
  252. $database->insert("apikeys", ["key" => $VARS['key'], "notes" => $VARS['notes'], "type" => $VARS['type']]);
  253. returnToSender("api_key_added");
  254. break;
  255. case "signout":
  256. session_destroy();
  257. header('Location: index.php?logout=1');
  258. die("Logged out.");
  259. default:
  260. die("Invalid action");
  261. }