api-functions.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. <?php /** @noinspection SqlResolve */
  2. /** @noinspection SqlResolve */
  3. /** @noinspection SqlResolve */
  4. /** @noinspection SqlResolve */
  5. /** @noinspection SyntaxError */
  6. function login($array)
  7. {
  8. // Grab username and Password from login form
  9. $username = $password = $oAuth = $oAuthType = '';
  10. foreach ($array['data'] as $items) {
  11. foreach ($items as $key => $value) {
  12. if ($key == 'name') {
  13. $newKey = $value;
  14. }
  15. if ($key == 'value') {
  16. $newValue = $value;
  17. }
  18. if (isset($newKey) && isset($newValue)) {
  19. $$newKey = $newValue;
  20. }
  21. }
  22. }
  23. $username = strtolower($username);
  24. $days = (isset($remember)) ? 7 : 1;
  25. $oAuth = (isset($oAuth)) ? $oAuth : false;
  26. try {
  27. $database = new Dibi\Connection([
  28. 'driver' => 'sqlite3',
  29. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  30. ]);
  31. $authSuccess = false;
  32. $function = 'plugin_auth_' . $GLOBALS['authBackend'];
  33. if (!$oAuth) {
  34. $result = $database->fetch('SELECT * FROM users WHERE username = ? COLLATE NOCASE OR email = ? COLLATE NOCASE', $username, $username);
  35. switch ($GLOBALS['authType']) {
  36. case 'external':
  37. if (function_exists($function)) {
  38. $authSuccess = $function($username, $password);
  39. }
  40. break;
  41. /** @noinspection PhpMissingBreakStatementInspection */
  42. case 'both':
  43. if (function_exists($function)) {
  44. $authSuccess = $function($username, $password);
  45. }
  46. // no break
  47. default: // Internal
  48. if (!$authSuccess) {
  49. // perform the internal authentication step
  50. if (password_verify($password, $result['password'])) {
  51. $authSuccess = true;
  52. }
  53. }
  54. }
  55. } else {
  56. // Has oAuth Token!
  57. switch ($oAuthType) {
  58. case 'plex':
  59. if ($GLOBALS['plexoAuth']) {
  60. $tokenInfo = checkPlexToken($oAuth);
  61. if ($tokenInfo) {
  62. $authSuccess = array(
  63. 'username' => $tokenInfo['user']['username'],
  64. 'email' => $tokenInfo['user']['email'],
  65. 'image' => $tokenInfo['user']['thumb'],
  66. 'token' => $tokenInfo['user']['authToken']
  67. );
  68. $authSuccess = ((!empty($GLOBALS['plexAdmin']) && strtolower($GLOBALS['plexAdmin']) == strtolower($tokenInfo['user']['username'])) || checkPlexUser($tokenInfo['user']['username'])) ? $authSuccess : false;
  69. }
  70. }
  71. break;
  72. default:
  73. return 'error';
  74. break;
  75. }
  76. $result = ($authSuccess) ? $database->fetch('SELECT * FROM users WHERE username = ? COLLATE NOCASE OR email = ? COLLATE NOCASE', $authSuccess['username'], $authSuccess['email']) : '';
  77. }
  78. if ($authSuccess) {
  79. // Make sure user exists in database
  80. $userExists = false;
  81. $passwordMatches = ($oAuth) ? true : false;
  82. $token = (is_array($authSuccess) && isset($authSuccess['token']) ? $authSuccess['token'] : '');
  83. if ($result['username']) {
  84. $userExists = true;
  85. $username = $result['username'];
  86. $passwordMatches = (password_verify($password, $result['password'])) ? true : false;
  87. }
  88. if ($userExists) {
  89. //does org password need to be updated
  90. if (!$passwordMatches) {
  91. $database->query('
  92. UPDATE users SET', [
  93. 'password' => password_hash($password, PASSWORD_BCRYPT)
  94. ], '
  95. WHERE id=?', $result['id']);
  96. writeLog('success', 'Login Function - User Password updated from backend', $username);
  97. }
  98. if ($token !== '') {
  99. if ($token !== $result['plex_token']) {
  100. $database->query('
  101. UPDATE users SET', [
  102. 'plex_token' => $token
  103. ], '
  104. WHERE id=?', $result['id']);
  105. writeLog('success', 'Login Function - User Plex Token updated from backend', $username);
  106. }
  107. }
  108. // 2FA might go here
  109. if ($result['auth_service'] !== 'internal' && strpos($result['auth_service'], '::') !== false) {
  110. $TFA = explode('::', $result['auth_service']);
  111. // Is code with login info?
  112. if ($tfaCode == '') {
  113. return '2FA';
  114. } else {
  115. if (!verify2FA($TFA[1], $tfaCode, $TFA[0])) {
  116. return '2FA-incorrect';
  117. }
  118. }
  119. }
  120. // End 2FA
  121. // authentication passed - 1) mark active and update token
  122. if (createToken($result['username'], $result['email'], $result['image'], $result['group'], $result['group_id'], $GLOBALS['organizrHash'], $days)) {
  123. writeLoginLog($username, 'success');
  124. writeLog('success', 'Login Function - A User has logged in', $username);
  125. ssoCheck($username, $password, $token); //need to work on this
  126. return true;
  127. } else {
  128. return 'error';
  129. }
  130. } else {
  131. // Create User
  132. ssoCheck($username, $password, $token);
  133. return authRegister((is_array($authSuccess) && isset($authSuccess['username']) ? $authSuccess['username'] : $username), $password, defaultUserGroup(), (is_array($authSuccess) && isset($authSuccess['email']) ? $authSuccess['email'] : ''));
  134. }
  135. } else {
  136. // authentication failed
  137. writeLoginLog($username, 'error');
  138. writeLog('error', 'Login Function - Wrong Password', $username);
  139. return 'mismatch';
  140. }
  141. } catch (Dibi\Exception $e) {
  142. return $e;
  143. }
  144. }
  145. function createDB($path, $filename)
  146. {
  147. try {
  148. if (!file_exists($path)) {
  149. mkdir($path, 0777, true);
  150. }
  151. $createDB = new Dibi\Connection([
  152. 'driver' => 'sqlite3',
  153. 'database' => $path . $filename,
  154. ]);
  155. // Create Users
  156. $createDB->query('CREATE TABLE `users` (
  157. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  158. `username` TEXT UNIQUE,
  159. `password` TEXT,
  160. `email` TEXT,
  161. `plex_token` TEXT,
  162. `group` TEXT,
  163. `group_id` INTEGER,
  164. `locked` INTEGER,
  165. `image` TEXT,
  166. `register_date` DATE,
  167. `auth_service` TEXT DEFAULT \'internal\'
  168. );');
  169. // Create Tokens
  170. $createDB->query('CREATE TABLE `chatroom` (
  171. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  172. `username` TEXT,
  173. `gravatar` TEXT,
  174. `uid` TEXT,
  175. `date` DATE,
  176. `ip` TEXT,
  177. `message` TEXT
  178. );');
  179. $createDB->query('CREATE TABLE `tokens` (
  180. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  181. `token` TEXT UNIQUE,
  182. `user_id` INTEGER,
  183. `created` DATE,
  184. `expires` DATE
  185. );');
  186. $createDB->query('CREATE TABLE `groups` (
  187. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  188. `group` TEXT UNIQUE,
  189. `group_id` INTEGER,
  190. `image` TEXT,
  191. `default` INTEGER
  192. );');
  193. $createDB->query('CREATE TABLE `categories` (
  194. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  195. `order` INTEGER,
  196. `category` TEXT UNIQUE,
  197. `category_id` INTEGER,
  198. `image` TEXT,
  199. `default` INTEGER
  200. );');
  201. // Create Tabs
  202. $createDB->query('CREATE TABLE `tabs` (
  203. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  204. `order` INTEGER,
  205. `category_id` INTEGER,
  206. `name` TEXT,
  207. `url` TEXT,
  208. `url_local` TEXT,
  209. `default` INTEGER,
  210. `enabled` INTEGER,
  211. `group_id` INTEGER,
  212. `image` TEXT,
  213. `type` INTEGER,
  214. `splash` INTEGER,
  215. `ping` INTEGER,
  216. `ping_url` TEXT
  217. );');
  218. // Create Options
  219. $createDB->query('CREATE TABLE `options` (
  220. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  221. `name` TEXT UNIQUE,
  222. `value` TEXT
  223. );');
  224. // Create Invites
  225. $createDB->query('CREATE TABLE `invites` (
  226. `id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
  227. `code` TEXT UNIQUE,
  228. `date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  229. `email` TEXT,
  230. `username` TEXT,
  231. `dateused` TIMESTAMP,
  232. `usedby` TEXT,
  233. `ip` TEXT,
  234. `valid` TEXT,
  235. `type` TEXT
  236. );');
  237. return true;
  238. } catch (Dibi\Exception $e) {
  239. return false;
  240. }
  241. }
  242. // Upgrade Database
  243. function updateDB($oldVerNum = false)
  244. {
  245. $tempLock = $GLOBALS['dbLocation'] . 'DBLOCK.txt';
  246. if (!file_exists($tempLock)) {
  247. touch($tempLock);
  248. // Create Temp DB First
  249. $migrationDB = 'tempMigration.db';
  250. $pathDigest = pathinfo($GLOBALS['dbLocation'] . $GLOBALS['dbName']);
  251. if (file_exists($GLOBALS['dbLocation'] . $migrationDB)) {
  252. unlink($GLOBALS['dbLocation'] . $migrationDB);
  253. }
  254. $backupDB = $pathDigest['dirname'] . '/' . $pathDigest['filename'] . '[' . date('Y-m-d_H-i-s') . ']' . ($oldVerNum ? '[' . $oldVerNum . ']' : '') . '.bak.db';
  255. copy($GLOBALS['dbLocation'] . $GLOBALS['dbName'], $backupDB);
  256. $success = createDB($GLOBALS['dbLocation'], $migrationDB);
  257. if ($success) {
  258. try {
  259. $connectOldDB = new Dibi\Connection([
  260. 'driver' => 'sqlite3',
  261. 'database' => $backupDB,
  262. ]);
  263. $connectNewDB = new Dibi\Connection([
  264. 'driver' => 'sqlite3',
  265. 'database' => $GLOBALS['dbLocation'] . $migrationDB,
  266. ]);
  267. $tables = $connectOldDB->fetchAll('SELECT name FROM sqlite_master WHERE type="table"');
  268. foreach ($tables as $table) {
  269. $data = $connectOldDB->fetchAll('SELECT * FROM ' . $table['name']);
  270. foreach ($data as $row) {
  271. $connectNewDB->query('INSERT into ' . $table['name'], $row);
  272. }
  273. }
  274. $connectOldDB->disconnect();
  275. $connectNewDB->disconnect();
  276. // Remove Current Database
  277. if (file_exists($GLOBALS['dbLocation'] . $migrationDB)) {
  278. $oldFileSize = filesize($GLOBALS['dbLocation'] . $GLOBALS['dbName']);
  279. $newFileSize = filesize($GLOBALS['dbLocation'] . $migrationDB);
  280. if ($newFileSize >= $oldFileSize) {
  281. @unlink($GLOBALS['dbLocation'] . $GLOBALS['dbName']);
  282. copy($GLOBALS['dbLocation'] . $migrationDB, $GLOBALS['dbLocation'] . $GLOBALS['dbName']);
  283. @unlink($GLOBALS['dbLocation'] . $migrationDB);
  284. writeLog('success', 'Update Function - Migrated Old Info to new Database', 'Database');
  285. unlink($tempLock);
  286. return true;
  287. }
  288. }
  289. unlink($tempLock);
  290. return false;
  291. } catch (Dibi\Exception $e) {
  292. writeLog('error', 'Update Function - Error [' . $e . ']', 'Database');
  293. unlink($tempLock);
  294. return false;
  295. }
  296. }
  297. unlink($tempLock);
  298. return false;
  299. }
  300. return false;
  301. }
  302. function createFirstAdmin($path, $filename, $username, $password, $email)
  303. {
  304. try {
  305. $createDB = new Dibi\Connection([
  306. 'driver' => 'sqlite3',
  307. 'database' => $path . $filename,
  308. ]);
  309. $userInfo = [
  310. 'username' => $username,
  311. 'password' => password_hash($password, PASSWORD_BCRYPT),
  312. 'email' => $email,
  313. 'group' => 'Admin',
  314. 'group_id' => 0,
  315. 'image' => gravatar($email),
  316. 'register_date' => $GLOBALS['currentTime'],
  317. ];
  318. $groupInfo0 = [
  319. 'group' => 'Admin',
  320. 'group_id' => 0,
  321. 'default' => false,
  322. 'image' => 'plugins/images/groups/admin.png',
  323. ];
  324. $groupInfo1 = [
  325. 'group' => 'Co-Admin',
  326. 'group_id' => 1,
  327. 'default' => false,
  328. 'image' => 'plugins/images/groups/coadmin.png',
  329. ];
  330. $groupInfo2 = [
  331. 'group' => 'Super User',
  332. 'group_id' => 2,
  333. 'default' => false,
  334. 'image' => 'plugins/images/groups/superuser.png',
  335. ];
  336. $groupInfo3 = [
  337. 'group' => 'Power User',
  338. 'group_id' => 3,
  339. 'default' => false,
  340. 'image' => 'plugins/images/groups/poweruser.png',
  341. ];
  342. $groupInfo4 = [
  343. 'group' => 'User',
  344. 'group_id' => 4,
  345. 'default' => true,
  346. 'image' => 'plugins/images/groups/user.png',
  347. ];
  348. $groupInfoGuest = [
  349. 'group' => 'Guest',
  350. 'group_id' => 999,
  351. 'default' => false,
  352. 'image' => 'plugins/images/groups/guest.png',
  353. ];
  354. $settingsInfo = [
  355. 'order' => 1,
  356. 'category_id' => 0,
  357. 'name' => 'Settings',
  358. 'url' => 'api/?v1/settings/page',
  359. 'default' => false,
  360. 'enabled' => true,
  361. 'group_id' => 1,
  362. 'image' => 'fontawesome::cog',
  363. 'type' => 0
  364. ];
  365. $homepageInfo = [
  366. 'order' => 2,
  367. 'category_id' => 0,
  368. 'name' => 'Homepage',
  369. 'url' => 'api/?v1/homepage/page',
  370. 'default' => false,
  371. 'enabled' => false,
  372. 'group_id' => 4,
  373. 'image' => 'fontawesome::home',
  374. 'type' => 0
  375. ];
  376. $unsortedInfo = [
  377. 'order' => 1,
  378. 'category' => 'Unsorted',
  379. 'category_id' => 0,
  380. 'image' => 'plugins/images/categories/unsorted.png',
  381. 'default' => true
  382. ];
  383. $createDB->query('INSERT INTO [users]', $userInfo);
  384. $createDB->query('INSERT INTO [groups]', $groupInfo0);
  385. $createDB->query('INSERT INTO [groups]', $groupInfo1);
  386. $createDB->query('INSERT INTO [groups]', $groupInfo2);
  387. $createDB->query('INSERT INTO [groups]', $groupInfo3);
  388. $createDB->query('INSERT INTO [groups]', $groupInfo4);
  389. $createDB->query('INSERT INTO [groups]', $groupInfoGuest);
  390. $createDB->query('INSERT INTO [tabs]', $settingsInfo);
  391. $createDB->query('INSERT INTO [tabs]', $homepageInfo);
  392. $createDB->query('INSERT INTO [categories]', $unsortedInfo);
  393. return true;
  394. } catch (Dibi\Exception $e) {
  395. writeLog('error', 'Wizard Function - Error [' . $e . ']', 'Wizard');
  396. return false;
  397. }
  398. }
  399. function defaultUserGroup()
  400. {
  401. try {
  402. $connect = new Dibi\Connection([
  403. 'driver' => 'sqlite3',
  404. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  405. ]);
  406. $all = $connect->fetch('SELECT * FROM groups WHERE `default` = 1');
  407. return $all;
  408. } catch (Dibi\Exception $e) {
  409. return false;
  410. }
  411. }
  412. function defaultTabCategory()
  413. {
  414. try {
  415. $connect = new Dibi\Connection([
  416. 'driver' => 'sqlite3',
  417. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  418. ]);
  419. $all = $connect->fetch('SELECT * FROM categories WHERE `default` = 1');
  420. return $all;
  421. } catch (Dibi\Exception $e) {
  422. return false;
  423. }
  424. }
  425. function getGuest()
  426. {
  427. if (isset($GLOBALS['dbLocation'])) {
  428. try {
  429. $connect = new Dibi\Connection([
  430. 'driver' => 'sqlite3',
  431. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  432. ]);
  433. $all = $connect->fetch('SELECT * FROM groups WHERE `group` = "Guest"');
  434. return $all;
  435. } catch (Dibi\Exception $e) {
  436. return false;
  437. }
  438. } else {
  439. return array(
  440. 'group' => 'Guest',
  441. 'group_id' => 999,
  442. 'image' => 'plugins/images/groups/guest.png'
  443. );
  444. }
  445. }
  446. function adminEditGroup($array)
  447. {
  448. switch ($array['data']['action']) {
  449. case 'changeDefaultGroup':
  450. try {
  451. $connect = new Dibi\Connection([
  452. 'driver' => 'sqlite3',
  453. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  454. ]);
  455. $connect->query('UPDATE groups SET `default` = 0');
  456. $connect->query('
  457. UPDATE groups SET', [
  458. 'default' => 1
  459. ], '
  460. WHERE id=?', $array['data']['id']);
  461. writeLog('success', 'Group Management Function - Changed Default Group from [' . $array['data']['oldGroupName'] . '] to [' . $array['data']['newGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  462. return true;
  463. } catch (Dibi\Exception $e) {
  464. return false;
  465. }
  466. break;
  467. case 'deleteUserGroup':
  468. try {
  469. $connect = new Dibi\Connection([
  470. 'driver' => 'sqlite3',
  471. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  472. ]);
  473. $connect->query('DELETE FROM groups WHERE id = ?', $array['data']['id']);
  474. writeLog('success', 'Group Management Function - Deleted Group [' . $array['data']['groupName'] . ']', $GLOBALS['organizrUser']['username']);
  475. return true;
  476. } catch (Dibi\Exception $e) {
  477. return false;
  478. }
  479. break;
  480. case 'addUserGroup':
  481. try {
  482. $connect = new Dibi\Connection([
  483. 'driver' => 'sqlite3',
  484. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  485. ]);
  486. $newGroup = [
  487. 'group' => $array['data']['newGroupName'],
  488. 'group_id' => $array['data']['newGroupID'],
  489. 'default' => false,
  490. 'image' => $array['data']['newGroupImage'],
  491. ];
  492. $connect->query('INSERT INTO [groups]', $newGroup);
  493. writeLog('success', 'Group Management Function - Added Group [' . $array['data']['newGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  494. return true;
  495. } catch (Dibi\Exception $e) {
  496. return false;
  497. }
  498. break;
  499. case 'editUserGroup':
  500. try {
  501. $connect = new Dibi\Connection([
  502. 'driver' => 'sqlite3',
  503. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  504. ]);
  505. $connect->query('
  506. UPDATE groups SET', [
  507. 'group' => $array['data']['groupName'],
  508. 'image' => $array['data']['groupImage'],
  509. ], '
  510. WHERE id=?', $array['data']['id']);
  511. writeLog('success', 'Group Management Function - Edited Group Info for [' . $array['data']['oldGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  512. return true;
  513. } catch (Dibi\Exception $e) {
  514. return false;
  515. }
  516. break;
  517. default:
  518. return false;
  519. break;
  520. }
  521. }
  522. function adminEditUser($array)
  523. {
  524. switch ($array['data']['action']) {
  525. case 'changeGroup':
  526. try {
  527. $connect = new Dibi\Connection([
  528. 'driver' => 'sqlite3',
  529. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  530. ]);
  531. $connect->query('
  532. UPDATE users SET', [
  533. 'group' => $array['data']['newGroupName'],
  534. 'group_id' => $array['data']['newGroupID'],
  535. ], '
  536. WHERE id=?', $array['data']['id']);
  537. writeLog('success', 'User Management Function - User: ' . $array['data']['username'] . '\'s group was changed from [' . $array['data']['oldGroup'] . '] to [' . $array['data']['newGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  538. return true;
  539. } catch (Dibi\Exception $e) {
  540. writeLog('error', 'User Management Function - Error - User: ' . $array['data']['username'] . '\'s group was changed from [' . $array['data']['oldGroup'] . '] to [' . $array['data']['newGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  541. return false;
  542. }
  543. break;
  544. case 'editUser':
  545. try {
  546. $connect = new Dibi\Connection([
  547. 'driver' => 'sqlite3',
  548. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  549. ]);
  550. if (!usernameTakenExcept($array['data']['username'], $array['data']['email'], $array['data']['id'])) {
  551. $connect->query('
  552. UPDATE users SET', [
  553. 'username' => $array['data']['username'],
  554. 'email' => $array['data']['email'],
  555. ], '
  556. WHERE id=?', $array['data']['id']);
  557. if (!empty($array['data']['password'])) {
  558. $connect->query('
  559. UPDATE users SET', [
  560. 'password' => password_hash($array['data']['password'], PASSWORD_BCRYPT)
  561. ], '
  562. WHERE id=?', $array['data']['id']);
  563. }
  564. writeLog('success', 'User Management Function - User: ' . $array['data']['username'] . '\'s info was changed', $GLOBALS['organizrUser']['username']);
  565. return true;
  566. } else {
  567. return false;
  568. }
  569. } catch (Dibi\Exception $e) {
  570. writeLog('error', 'User Management Function - Error - User: ' . $array['data']['username'] . '\'s group was changed from [' . $array['data']['oldGroup'] . '] to [' . $array['data']['newGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  571. return false;
  572. }
  573. break;
  574. case 'addNewUser':
  575. $defaults = defaultUserGroup();
  576. if (createUser($array['data']['username'], $array['data']['password'], $defaults, $array['data']['email'])) {
  577. writeLog('success', 'Create User Function - Account created for [' . $array['data']['username'] . ']', $GLOBALS['organizrUser']['username']);
  578. return true;
  579. } else {
  580. writeLog('error', 'Registration Function - An error occurred', $GLOBALS['organizrUser']['username']);
  581. return 'username taken';
  582. }
  583. break;
  584. case 'deleteUser':
  585. try {
  586. $connect = new Dibi\Connection([
  587. 'driver' => 'sqlite3',
  588. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  589. ]);
  590. $connect->query('DELETE FROM users WHERE id = ?', $array['data']['id']);
  591. writeLog('success', 'User Management Function - Deleted User [' . $array['data']['username'] . ']', $GLOBALS['organizrUser']['username']);
  592. return true;
  593. } catch (Dibi\Exception $e) {
  594. return false;
  595. }
  596. break;
  597. default:
  598. return false;
  599. break;
  600. }
  601. }
  602. function editTabs($array)
  603. {
  604. switch ($array['data']['action']) {
  605. case 'changeGroup':
  606. try {
  607. $connect = new Dibi\Connection([
  608. 'driver' => 'sqlite3',
  609. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  610. ]);
  611. $connect->query('
  612. UPDATE tabs SET', [
  613. 'group_id' => $array['data']['newGroupID'],
  614. ], '
  615. WHERE id=?', $array['data']['id']);
  616. writeLog('success', 'Tab Editor Function - Tab: ' . $array['data']['tab'] . '\'s group was changed to [' . $array['data']['newGroupName'] . ']', $GLOBALS['organizrUser']['username']);
  617. return true;
  618. } catch (Dibi\Exception $e) {
  619. return false;
  620. }
  621. break;
  622. case 'changeCategory':
  623. try {
  624. $connect = new Dibi\Connection([
  625. 'driver' => 'sqlite3',
  626. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  627. ]);
  628. $connect->query('
  629. UPDATE tabs SET', [
  630. 'category_id' => $array['data']['newCategoryID'],
  631. ], '
  632. WHERE id=?', $array['data']['id']);
  633. writeLog('success', 'Tab Editor Function - Tab: ' . $array['data']['tab'] . '\'s category was changed to [' . $array['data']['newCategoryName'] . ']', $GLOBALS['organizrUser']['username']);
  634. return true;
  635. } catch (Dibi\Exception $e) {
  636. return false;
  637. }
  638. break;
  639. case 'changeType':
  640. try {
  641. $connect = new Dibi\Connection([
  642. 'driver' => 'sqlite3',
  643. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  644. ]);
  645. $connect->query('
  646. UPDATE tabs SET', [
  647. 'type' => $array['data']['newTypeID'],
  648. ], '
  649. WHERE id=?', $array['data']['id']);
  650. writeLog('success', 'Tab Editor Function - Tab: ' . $array['data']['tab'] . '\'s type was changed to [' . $array['data']['newTypeName'] . ']', $GLOBALS['organizrUser']['username']);
  651. return true;
  652. } catch (Dibi\Exception $e) {
  653. return false;
  654. }
  655. break;
  656. case 'changeEnabled':
  657. try {
  658. $connect = new Dibi\Connection([
  659. 'driver' => 'sqlite3',
  660. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  661. ]);
  662. $connect->query('
  663. UPDATE tabs SET', [
  664. 'enabled' => $array['data']['tabEnabled'],
  665. ], '
  666. WHERE id=?', $array['data']['id']);
  667. writeLog('success', 'Tab Editor Function - Tab: ' . $array['data']['tab'] . '\'s enable status was changed to [' . $array['data']['tabEnabledWord'] . ']', $GLOBALS['organizrUser']['username']);
  668. return true;
  669. } catch (Dibi\Exception $e) {
  670. return false;
  671. }
  672. break;
  673. case 'changeSplash':
  674. try {
  675. $connect = new Dibi\Connection([
  676. 'driver' => 'sqlite3',
  677. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  678. ]);
  679. $connect->query('
  680. UPDATE tabs SET', [
  681. 'splash' => $array['data']['tabSplash'],
  682. ], '
  683. WHERE id=?', $array['data']['id']);
  684. writeLog('success', 'Tab Editor Function - Tab: ' . $array['data']['tab'] . '\'s splash status was changed to [' . $array['data']['tabSplashWord'] . ']', $GLOBALS['organizrUser']['username']);
  685. return true;
  686. } catch (Dibi\Exception $e) {
  687. return false;
  688. }
  689. break;
  690. case 'changePing':
  691. try {
  692. $connect = new Dibi\Connection([
  693. 'driver' => 'sqlite3',
  694. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  695. ]);
  696. $connect->query('
  697. UPDATE tabs SET', [
  698. 'ping' => $array['data']['tabPing'],
  699. ], '
  700. WHERE id=?', $array['data']['id']);
  701. writeLog('success', 'Tab Editor Function - Tab: ' . $array['data']['tab'] . '\'s ping status was changed to [' . $array['data']['tabPingWord'] . ']', $GLOBALS['organizrUser']['username']);
  702. return true;
  703. } catch (Dibi\Exception $e) {
  704. return false;
  705. }
  706. break;
  707. case 'changeDefault':
  708. try {
  709. $connect = new Dibi\Connection([
  710. 'driver' => 'sqlite3',
  711. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  712. ]);
  713. $connect->query('UPDATE tabs SET `default` = 0');
  714. $connect->query('
  715. UPDATE tabs SET', [
  716. 'default' => 1
  717. ], '
  718. WHERE id=?', $array['data']['id']);
  719. writeLog('success', 'Tab Editor Function - Changed Default Tab to [' . $array['data']['tab'] . ']', $GLOBALS['organizrUser']['username']);
  720. return true;
  721. } catch (Dibi\Exception $e) {
  722. return false;
  723. }
  724. break;
  725. case 'deleteTab':
  726. try {
  727. $connect = new Dibi\Connection([
  728. 'driver' => 'sqlite3',
  729. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  730. ]);
  731. $connect->query('DELETE FROM tabs WHERE id = ?', $array['data']['id']);
  732. writeLog('success', 'Tab Editor Function - Deleted Tab [' . $array['data']['tab'] . ']', $GLOBALS['organizrUser']['username']);
  733. return true;
  734. } catch (Dibi\Exception $e) {
  735. return false;
  736. }
  737. break;
  738. case 'editTab':
  739. try {
  740. $connect = new Dibi\Connection([
  741. 'driver' => 'sqlite3',
  742. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  743. ]);
  744. $connect->query('
  745. UPDATE tabs SET', [
  746. 'name' => $array['data']['tabName'],
  747. 'url' => $array['data']['tabURL'],
  748. 'ping_url' => $array['data']['pingURL'],
  749. 'image' => $array['data']['tabImage'],
  750. ], '
  751. WHERE id=?', $array['data']['id']);
  752. writeLog('success', 'Tab Editor Function - Edited Tab Info for [' . $array['data']['tabName'] . ']', $GLOBALS['organizrUser']['username']);
  753. return true;
  754. } catch (Dibi\Exception $e) {
  755. return false;
  756. }
  757. case 'changeOrder':
  758. try {
  759. $connect = new Dibi\Connection([
  760. 'driver' => 'sqlite3',
  761. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  762. ]);
  763. foreach ($array['data']['tabs']['tab'] as $key => $value) {
  764. if ($value['order'] != $value['originalOrder']) {
  765. $connect->query('
  766. UPDATE tabs SET', [
  767. 'order' => $value['order'],
  768. ], '
  769. WHERE id=?', $value['id']);
  770. writeLog('success', 'Tab Editor Function - ' . $value['name'] . ' Order Changed From ' . $value['order'] . ' to ' . $value['originalOrder'], $GLOBALS['organizrUser']['username']);
  771. }
  772. }
  773. writeLog('success', 'Tab Editor Function - Tab Order Changed', $GLOBALS['organizrUser']['username']);
  774. return true;
  775. } catch (Dibi\Exception $e) {
  776. return false;
  777. }
  778. break;
  779. case 'addNewTab':
  780. try {
  781. $default = defaultTabCategory()['category_id'];
  782. $connect = new Dibi\Connection([
  783. 'driver' => 'sqlite3',
  784. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  785. ]);
  786. $newTab = [
  787. 'order' => $array['data']['tabOrder'],
  788. 'category_id' => $default,
  789. 'name' => $array['data']['tabName'],
  790. 'url' => $array['data']['tabURL'],
  791. 'ping_url' => $array['data']['pingURL'],
  792. 'default' => $array['data']['tabDefault'],
  793. 'enabled' => 1,
  794. 'group_id' => $array['data']['tabGroupID'],
  795. 'image' => $array['data']['tabImage'],
  796. 'type' => $array['data']['tabType']
  797. ];
  798. $connect->query('INSERT INTO [tabs]', $newTab);
  799. writeLog('success', 'Tab Editor Function - Created Tab for: ' . $array['data']['tabName'], $GLOBALS['organizrUser']['username']);
  800. return true;
  801. } catch (Dibi\Exception $e) {
  802. return false;
  803. }
  804. break;
  805. default:
  806. return false;
  807. break;
  808. }
  809. }
  810. function editCategories($array)
  811. {
  812. switch ($array['data']['action']) {
  813. case 'changeDefault':
  814. try {
  815. $connect = new Dibi\Connection([
  816. 'driver' => 'sqlite3',
  817. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  818. ]);
  819. $connect->query('UPDATE categories SET `default` = 0');
  820. $connect->query('
  821. UPDATE categories SET', [
  822. 'default' => 1
  823. ], '
  824. WHERE id=?', $array['data']['id']);
  825. writeLog('success', 'Category Editor Function - Changed Default Category from [' . $array['data']['oldCategoryName'] . '] to [' . $array['data']['newCategoryName'] . ']', $GLOBALS['organizrUser']['username']);
  826. return true;
  827. } catch (Dibi\Exception $e) {
  828. return false;
  829. }
  830. break;
  831. case 'deleteCategory':
  832. try {
  833. $connect = new Dibi\Connection([
  834. 'driver' => 'sqlite3',
  835. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  836. ]);
  837. $connect->query('DELETE FROM categories WHERE id = ?', $array['data']['id']);
  838. writeLog('success', 'Category Editor Function - Deleted Category [' . $array['data']['category'] . ']', $GLOBALS['organizrUser']['username']);
  839. return true;
  840. } catch (Dibi\Exception $e) {
  841. return false;
  842. }
  843. break;
  844. case 'addNewCategory':
  845. try {
  846. $connect = new Dibi\Connection([
  847. 'driver' => 'sqlite3',
  848. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  849. ]);
  850. $newCategory = [
  851. 'category' => $array['data']['categoryName'],
  852. 'order' => $array['data']['categoryOrder'],
  853. 'category_id' => $array['data']['categoryID'],
  854. 'default' => false,
  855. 'image' => $array['data']['categoryImage'],
  856. ];
  857. $connect->query('INSERT INTO [categories]', $newCategory);
  858. writeLog('success', 'Category Editor Function - Added Category [' . $array['data']['categoryName'] . ']', $GLOBALS['organizrUser']['username']);
  859. return true;
  860. } catch (Dibi\Exception $e) {
  861. return $e;
  862. }
  863. break;
  864. case 'editCategory':
  865. try {
  866. $connect = new Dibi\Connection([
  867. 'driver' => 'sqlite3',
  868. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  869. ]);
  870. $connect->query('
  871. UPDATE categories SET', [
  872. 'category' => $array['data']['name'],
  873. 'image' => $array['data']['image'],
  874. ], '
  875. WHERE id=?', $array['data']['id']);
  876. writeLog('success', 'Category Editor Function - Edited Category Info for [' . $array['data']['name'] . ']', $GLOBALS['organizrUser']['username']);
  877. return true;
  878. } catch (Dibi\Exception $e) {
  879. return false;
  880. }
  881. break;
  882. case 'changeOrder':
  883. try {
  884. $connect = new Dibi\Connection([
  885. 'driver' => 'sqlite3',
  886. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  887. ]);
  888. foreach ($array['data']['categories']['category'] as $key => $value) {
  889. if ($value['order'] != $value['originalOrder']) {
  890. $connect->query('
  891. UPDATE categories SET', [
  892. 'order' => $value['order'],
  893. ], '
  894. WHERE id=?', $value['id']);
  895. writeLog('success', 'Category Editor Function - ' . $value['name'] . ' Order Changed From ' . $value['order'] . ' to ' . $value['originalOrder'], $GLOBALS['organizrUser']['username']);
  896. }
  897. }
  898. writeLog('success', 'Category Editor Function - Category Order Changed', $GLOBALS['organizrUser']['username']);
  899. return true;
  900. } catch (Dibi\Exception $e) {
  901. return false;
  902. }
  903. break;
  904. default:
  905. return false;
  906. break;
  907. }
  908. }
  909. function allUsers()
  910. {
  911. try {
  912. $connect = new Dibi\Connection([
  913. 'driver' => 'sqlite3',
  914. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  915. ]);
  916. $users = $connect->fetchAll('SELECT * FROM users');
  917. $groups = $connect->fetchAll('SELECT * FROM groups ORDER BY group_id ASC');
  918. foreach ($users as $k => $v) {
  919. // clear password from array
  920. unset($users[$k]['password']);
  921. }
  922. $all['users'] = $users;
  923. $all['groups'] = $groups;
  924. return $all;
  925. } catch (Dibi\Exception $e) {
  926. return false;
  927. }
  928. }
  929. function usernameTaken($username, $email)
  930. {
  931. try {
  932. $connect = new Dibi\Connection([
  933. 'driver' => 'sqlite3',
  934. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  935. ]);
  936. $all = $connect->fetch('SELECT * FROM users WHERE username = ? COLLATE NOCASE OR email = ? COLLATE NOCASE', $username, $email);
  937. return ($all) ? true : false;
  938. } catch (Dibi\Exception $e) {
  939. return false;
  940. }
  941. }
  942. function usernameTakenExcept($username, $email, $id)
  943. {
  944. try {
  945. $connect = new Dibi\Connection([
  946. 'driver' => 'sqlite3',
  947. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  948. ]);
  949. $all = $connect->fetch('SELECT * FROM users WHERE id IS NOT ? AND username = ? COLLATE NOCASE OR id IS NOT ? AND email = ? COLLATE NOCASE', $id, $username, $id, $email);
  950. return ($all) ? true : false;
  951. } catch (Dibi\Exception $e) {
  952. return false;
  953. }
  954. }
  955. function createUser($username, $password, $defaults, $email = null)
  956. {
  957. $email = ($email) ? $email : random_ascii_string(10) . '@placeholder.eml';
  958. try {
  959. if (!usernameTaken($username, $email)) {
  960. $createDB = new Dibi\Connection([
  961. 'driver' => 'sqlite3',
  962. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  963. ]);
  964. $userInfo = [
  965. 'username' => $username,
  966. 'password' => password_hash($password, PASSWORD_BCRYPT),
  967. 'email' => $email,
  968. 'group' => $defaults['group'],
  969. 'group_id' => $defaults['group_id'],
  970. 'image' => gravatar($email),
  971. 'register_date' => $GLOBALS['currentTime'],
  972. ];
  973. $createDB->query('INSERT INTO [users]', $userInfo);
  974. return true;
  975. } else {
  976. return false;
  977. }
  978. } catch (Dibi\Exception $e) {
  979. return false;
  980. }
  981. }
  982. function importUsers($array)
  983. {
  984. $imported = 0;
  985. $defaults = defaultUserGroup();
  986. foreach ($array as $user) {
  987. $password = random_ascii_string(30);
  988. if ($user['username'] !== '' && $user['email'] !== '' && $password !== '' && $defaults !== '') {
  989. $newUser = createUser($user['username'], $password, $defaults, $user['email']);
  990. if (!$newUser) {
  991. writeLog('error', 'Import Function - Error', $user['username']);
  992. } else {
  993. $imported++;
  994. }
  995. }
  996. }
  997. return $imported;
  998. }
  999. function importUsersType($array)
  1000. {
  1001. $type = $array['data']['type'];
  1002. if ($type !== '') {
  1003. switch ($type) {
  1004. case 'plex':
  1005. return importUsers(allPlexUsers(true));
  1006. break;
  1007. default:
  1008. return false;
  1009. }
  1010. }
  1011. return false;
  1012. }
  1013. function allTabs()
  1014. {
  1015. if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
  1016. try {
  1017. $connect = new Dibi\Connection([
  1018. 'driver' => 'sqlite3',
  1019. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  1020. ]);
  1021. $all['tabs'] = $connect->fetchAll('SELECT * FROM tabs ORDER BY `order` ASC');
  1022. $all['categories'] = $connect->fetchAll('SELECT * FROM categories ORDER BY `order` ASC');
  1023. $all['groups'] = $connect->fetchAll('SELECT * FROM groups ORDER BY `group_id` ASC');
  1024. return $all;
  1025. } catch (Dibi\Exception $e) {
  1026. return false;
  1027. }
  1028. }
  1029. return false;
  1030. }
  1031. function allGroups()
  1032. {
  1033. if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
  1034. try {
  1035. $connect = new Dibi\Connection([
  1036. 'driver' => 'sqlite3',
  1037. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  1038. ]);
  1039. $all = $connect->fetchAll('SELECT * FROM groups ORDER BY `group_id` ASC');
  1040. return $all;
  1041. } catch (Dibi\Exception $e) {
  1042. return false;
  1043. }
  1044. }
  1045. return false;
  1046. }
  1047. function loadTabs()
  1048. {
  1049. if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
  1050. try {
  1051. $connect = new Dibi\Connection([
  1052. 'driver' => 'sqlite3',
  1053. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  1054. ]);
  1055. $sort = ($GLOBALS['unsortedTabs'] == 'top') ? 'DESC' : 'ASC';
  1056. $tabs = $connect->fetchAll('SELECT * FROM tabs WHERE `group_id` >= ? AND `enabled` = 1 ORDER BY `order` ' . $sort, $GLOBALS['organizrUser']['groupID']);
  1057. $categories = $connect->fetchAll('SELECT * FROM categories ORDER BY `order` ASC');
  1058. $all['tabs'] = $tabs;
  1059. foreach ($tabs as $k => $v) {
  1060. $v['access_url'] = isset($v['url_local']) && getenv('SERVER_ADDR') == userIP() ? $v['url_local'] : $v['url'];
  1061. }
  1062. $count = array_map(function ($element) {
  1063. return $element['category_id'];
  1064. }, $tabs);
  1065. $count = (array_count_values($count));
  1066. foreach ($categories as $k => $v) {
  1067. $v['count'] = isset($count[$v['category_id']]) ? $count[$v['category_id']] : 0;
  1068. }
  1069. $all['categories'] = $categories;
  1070. return $all;
  1071. } catch (Dibi\Exception $e) {
  1072. return false;
  1073. }
  1074. }
  1075. return false;
  1076. }
  1077. function getActiveTokens()
  1078. {
  1079. try {
  1080. $connect = new Dibi\Connection([
  1081. 'driver' => 'sqlite3',
  1082. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  1083. ]);
  1084. $all = $connect->fetchAll('SELECT * FROM `tokens` WHERE `user_id` = ? AND `expires` > ?', $GLOBALS['organizrUser']['userID'], $GLOBALS['currentTime']);
  1085. return $all;
  1086. } catch (Dibi\Exception $e) {
  1087. return false;
  1088. }
  1089. }
  1090. function revokeToken($array)
  1091. {
  1092. if ($array['data']['token']) {
  1093. try {
  1094. $connect = new Dibi\Connection([
  1095. 'driver' => 'sqlite3',
  1096. 'database' => $GLOBALS['dbLocation'] . $GLOBALS['dbName'],
  1097. ]);
  1098. $connect->query('DELETE FROM tokens WHERE user_id = ? AND token = ?', $GLOBALS['organizrUser']['userID'], $array['data']['token']);
  1099. return true;
  1100. } catch (Dibi\Exception $e) {
  1101. return false;
  1102. }
  1103. }
  1104. }