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

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