Browse Source

Merge pull request #1070 from causefx/v2-develop

V2 develop 980 merge
causefx 7 years ago
parent
commit
b33f8e6217

+ 1 - 0
.gitignore

@@ -73,6 +73,7 @@ users.db
 speedtest.db
 chatpack.db
 Docker.txt
+Demo.txt
 config/cacert.pem
 config/config.php
 config/config*.bak.php

+ 1 - 0
api/config/default.php

@@ -37,6 +37,7 @@ return array(
 	'tautulliURL' => '',
 	'ombiURL' => '',
 	'ombiToken' => '',
+	'ombiAlias' => false,
 	'ssoPlex' => false,
 	'ssoOmbi' => false,
 	'ssoTautulli' => false,

+ 10 - 0
api/functions.php

@@ -16,11 +16,21 @@ configLazy();
 if (isset($GLOBALS['dbLocation'])) {
 	$GLOBALS['organizrLog'] = $GLOBALS['dbLocation'] . 'organizrLog.json';
 	$GLOBALS['organizrLoginLog'] = $GLOBALS['dbLocation'] . 'organizrLoginLog.json';
+	$GLOBALS['paths'] = array(
+		'Root Folder' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR,
+		'API Folder' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR,
+		'DB Folder' => $GLOBALS['dbLocation']
+	);
 	if (($GLOBALS['uuid'] == '')) {
 		$uuid = gen_uuid();
 		$GLOBALS['uuid'] = $uuid;
 		updateConfig(array('uuid' => $uuid));
 	}
+	if ($GLOBALS['docker']) {
+		$getBranch = file_get_contents(dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Docker.txt');
+		$getBranch = (empty($getBranch)) ? 'v2-master' : $getBranch;
+		$GLOBALS['branch'] = $getBranch;
+	}
 	//Upgrade Check
 	upgradeCheck();
 }

+ 3 - 3
api/functions/api-functions.php

@@ -20,7 +20,7 @@ function login($array)
 			}
 		}
 	}
-	$username = strtolower($username);
+	$username = (strpos($GLOBALS['authBackend'], 'emby') !== false) ? $username : strtolower($username);
 	$days = (isset($remember)) ? $GLOBALS['rememberMeDays'] : 1;
 	$oAuth = (isset($oAuth)) ? $oAuth : false;
 	try {
@@ -66,7 +66,7 @@ function login($array)
 								'token' => $tokenInfo['user']['authToken']
 							);
 							coookie('set', 'oAuth', 'true', $GLOBALS['rememberMeDays']);
-							$authSuccess = ((!empty($GLOBALS['plexAdmin']) && strtolower($GLOBALS['plexAdmin']) == strtolower($tokenInfo['user']['username'])) || checkPlexUser($tokenInfo['user']['username'])) ? $authSuccess : false;
+							$authSuccess = ((!empty($GLOBALS['plexAdmin']) && strtolower($GLOBALS['plexAdmin']) == strtolower($tokenInfo['user']['username'])) || (!empty($GLOBALS['plexAdmin']) && strtolower($GLOBALS['plexAdmin']) == strtolower($tokenInfo['user']['email'])) || checkPlexUser($tokenInfo['user']['username'])) ? $authSuccess : false;
 						}
 					}
 					break;
@@ -130,7 +130,7 @@ function login($array)
 					ssoCheck($username, $password, $token); //need to work on this
 					return true;
 				} else {
-					return 'error';
+					return 'Token Creation Error';
 				}
 			} else {
 				// Create User

+ 44 - 36
api/functions/homepage-connect-functions.php

@@ -1954,53 +1954,61 @@ function getOmbiRequests($type = "both")
 					$movie = json_decode($movie->body, true);
 					//$movie = array_reverse($movie);
 					foreach ($movie as $key => $value) {
-						$requests[] = array(
-							'test' => $value,
-							'id' => $value['theMovieDbId'],
-							'title' => $value['title'],
-							'overview' => $value['overview'],
-							'poster' => (isset($value['posterPath']) && $value['posterPath'] !== '') ? 'https://image.tmdb.org/t/p/w300/' . $value['posterPath'] : '',
-							'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
-							'approved' => $value['approved'],
-							'available' => $value['available'],
-							'denied' => $value['denied'],
-							'deniedReason' => $value['deniedReason'],
-							'user' => $value['requestedUser']['userName'],
-							'request_id' => $value['id'],
-							'request_date' => $value['requestedDate'],
-							'release_date' => $value['releaseDate'],
-							'type' => 'movie',
-							'icon' => 'mdi mdi-filmstrip',
-							'color' => 'palette-Deep-Purple-900 bg white',
-						);
-					}
-				}
-				if (isset($tv) && (is_array($tv) || is_object($tv))) {
-					$tv = json_decode($tv->body, true);
-					foreach ($tv as $key => $value) {
-						if (is_array($value['childRequests'][0])) {
+						$proceed = (($GLOBALS['ombiLimitUser']) && strtolower($GLOBALS['organizrUser']['username']) == strtolower($value['requestedUser']['userName'])) || (!$GLOBALS['ombiLimitUser']) || qualifyRequest(1) ? true : false;
+						if ($proceed) {
 							$requests[] = array(
 								'test' => $value,
-								'id' => $value['tvDbId'],
+								'id' => $value['theMovieDbId'],
 								'title' => $value['title'],
 								'overview' => $value['overview'],
-								'poster' => $value['posterPath'],
+								'poster' => (isset($value['posterPath']) && $value['posterPath'] !== '') ? 'https://image.tmdb.org/t/p/w300/' . $value['posterPath'] : '',
 								'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
-								'approved' => $value['childRequests'][0]['approved'],
-								'available' => $value['childRequests'][0]['available'],
-								'denied' => $value['childRequests'][0]['denied'],
-								'deniedReason' => $value['childRequests'][0]['deniedReason'],
-								'user' => $value['childRequests'][0]['requestedUser']['userName'],
+								'approved' => $value['approved'],
+								'available' => $value['available'],
+								'denied' => $value['denied'],
+								'deniedReason' => $value['deniedReason'],
+								'user' => $value['requestedUser']['userName'],
+								'userAlias' => $value['requestedUser']['userAlias'],
 								'request_id' => $value['id'],
-								'request_date' => $value['childRequests'][0]['requestedDate'],
+								'request_date' => $value['requestedDate'],
 								'release_date' => $value['releaseDate'],
-								'type' => 'tv',
-								'icon' => 'mdi mdi-television',
-								'color' => 'grayish-blue-bg',
+								'type' => 'movie',
+								'icon' => 'mdi mdi-filmstrip',
+								'color' => 'palette-Deep-Purple-900 bg white',
 							);
 						}
 					}
 				}
+				if (isset($tv) && (is_array($tv) || is_object($tv))) {
+					$tv = json_decode($tv->body, true);
+					foreach ($tv as $key => $value) {
+						if (count($value['childRequests']) > 0) {
+							$proceed = (($GLOBALS['ombiLimitUser']) && strtolower($GLOBALS['organizrUser']['username']) == strtolower($value['childRequests'][0]['requestedUser']['userName'])) || (!$GLOBALS['ombiLimitUser']) || qualifyRequest(1) ? true : false;
+							if ($proceed) {
+								$requests[] = array(
+									'test' => $value,
+									'id' => $value['tvDbId'],
+									'title' => $value['title'],
+									'overview' => $value['overview'],
+									'poster' => $value['posterPath'],
+									'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
+									'approved' => $value['childRequests'][0]['approved'],
+									'available' => $value['childRequests'][0]['available'],
+									'denied' => $value['childRequests'][0]['denied'],
+									'deniedReason' => $value['childRequests'][0]['deniedReason'],
+									'user' => $value['childRequests'][0]['requestedUser']['userName'],
+									'userAlias' => $value['childRequests'][0]['requestedUser']['userAlias'],
+									'request_id' => $value['id'],
+									'request_date' => $value['childRequests'][0]['requestedDate'],
+									'release_date' => $value['releaseDate'],
+									'type' => 'tv',
+									'icon' => 'mdi mdi-television',
+									'color' => 'grayish-blue-bg',
+								);
+							}
+						}
+					}
+				}
 				//sort here
 				usort($requests, function ($item1, $item2) {
 					if ($item1['request_date'] == $item2['request_date']) {

+ 7 - 0
api/functions/homepage-functions.php

@@ -2006,6 +2006,13 @@ function getHomepageList()
 						'label' => 'Refresh Seconds',
 						'value' => $GLOBALS['ombiRefresh'],
 						'options' => optionTime()
+					),
+					array(
+						'type' => 'switch',
+						'name' => 'ombiAlias',
+						'label' => 'Use Ombi Alias Names',
+						'value' => $GLOBALS['ombiAlias'],
+						'help' => 'Use Ombi Alias Names instead of Usernames - If Alias is blank, Alias will fallback to Username'
 					)
 				),
 				'Test Connection' => array(

+ 48 - 7
api/functions/organizr-functions.php

@@ -21,6 +21,7 @@ function organizrSpecialSettings()
 				'authRequest' => (qualifyRequest($GLOBALS['homepageOmbiRequestAuth'])) ? true : false,
 				'sso' => ($GLOBALS['ssoOmbi']) ? true : false,
 				'cookie' => (isset($_COOKIE['Auth'])) ? true : false,
+				'alias' => ($GLOBALS['ombiAlias']) ? true : false,
 			),
 			'options' => array(
 				'alternateHomepageHeaders' => $GLOBALS['alternateHomepageHeaders'],
@@ -89,6 +90,7 @@ function organizrSpecialSettings()
 			'authDebug' => $GLOBALS['authDebug'],
 			'minimalLoginScreen' => $GLOBALS['minimalLoginScreen'],
 			'unsortedTabs' => $GLOBALS['unsortedTabs'],
+			'authType' => $GLOBALS['authType'],
 			'authBackend' => $GLOBALS['authBackend'],
 			'newMessageSound' => (isset($GLOBALS['CHAT-newMessageSound-include'])) ? $GLOBALS['CHAT-newMessageSound-include'] : '',
 			'uuid' => $GLOBALS['uuid'],
@@ -419,6 +421,15 @@ function organizrStatus()
 	return $status;
 }
 
+function pathsWritable($paths)
+{
+	$results = array();
+	foreach ($paths as $k => $v) {
+		$results[$k] = is_writable($v);
+	}
+	return $results;
+}
+
 function getSettingsMain()
 {
 	return array(
@@ -428,7 +439,9 @@ function getSettingsMain()
 				'name' => 'branch',
 				'label' => 'Branch',
 				'value' => $GLOBALS['branch'],
-				'options' => getBranches()
+				'options' => getBranches(),
+				'disabled' => $GLOBALS['branch'],
+				'help' => ($GLOBALS['docker']) ? 'Since you are using the Official Docker image, Change the image to change the branch' : 'Choose which branch to download from'
 			),
 			array(
 				'type' => 'button',
@@ -1372,16 +1385,33 @@ function showLogin()
 	}
 }
 
+function checkoAuth()
+{
+	return ($GLOBALS['plexoAuth'] && $GLOBALS['authType'] !== 'internal') ? true : false;
+}
+
 function showoAuth()
 {
 	$buttons = '';
-	if ($GLOBALS['plexoAuth']) {
-		$buttons .= '<a href="javascript:void(0)" onclick="oAuthStart(\'plex\')" class="btn btn-lg btn-block text-uppercase waves-effect waves-light bg-plex text-muted" data-toggle="tooltip" title="" data-original-title="Login with Plex"> <span>Login with Plex Account</span><i aria-hidden="true" class="mdi mdi-plex m-l-5"></i> </a>';
+	if ($GLOBALS['plexoAuth'] && $GLOBALS['authType'] !== 'internal') {
+		$buttons .= '<a href="javascript:void(0)" onclick="oAuthStart(\'plex\')" class="btn btn-lg btn-block text-uppercase waves-effect waves-light bg-plex text-muted" data-toggle="tooltip" title="" data-original-title="Login with Plex"> <span>Login</span><i aria-hidden="true" class="mdi mdi-plex m-l-5"></i> </a>';
 	}
 	return ($buttons) ? '
-		<div class="row">
-            <div class="col-xs-12 col-sm-12 col-md-12 m-t-10 text-center">
-                <div class="social">' . $buttons . '</div>
+		<div class="panel">
+            <div class="panel-heading bg-org" id="plex-login-heading" role="tab">
+            	<a class="panel-title" data-toggle="collapse" href="#plex-login-collapse" data-parent="#login-panels" aria-expanded="false" aria-controls="organizr-login-collapse">
+	                <img class="lazyload loginTitle" data-src="plugins/images/tabs/plex.png"> &nbsp;
+                    <span class="text-uppercase fw300" lang="en">Login with Plex</span>
+            	</a>
+            </div>
+            <div class="panel-collapse collapse in" id="plex-login-collapse" aria-labelledby="plex-login-heading" role="tabpanel">
+                <div class="panel-body">
+               		<div class="row">
+			            <div class="col-xs-12 col-sm-12 col-md-12 text-center">
+			                <div class="social m-b-0">' . $buttons . '</div>
+			            </div>
+			        </div>
+               </div>
             </div>
         </div>
 	' : '';
@@ -1979,5 +2009,16 @@ function importUserButtons()
 function settingsDocker()
 {
 	$type = ($GLOBALS['docker']) ? 'Official Docker' : 'Native';
-	return '<li><div class="bg-info"><i class="mdi mdi-flag mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">Install Type</span> ' . $type . '</li>';
+	return '<li><div class="bg-info"><i class="mdi mdi-flag mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">Install Type</span> ' . $type . '</li>';
+}
+
+function settingsPathChecks()
+{
+	$items = '';
+	$type = (array_search(false, pathsWritable($GLOBALS['paths']))) ? 'Not Writable' : 'Writable';
+	$result = '<li class="mouse" onclick="toggleWritableFolders();"><div class="bg-info"><i class="mdi mdi-folder mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">Organizr Paths</span> ' . $type . '</li>';
+	foreach (pathsWritable($GLOBALS['paths']) as $k => $v) {
+		$items .= '<li class="folders-writable hidden"><div class="bg-info"><i class="mdi mdi-folder mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">' . $k . '</span> ' . (($v) ? 'Writable' : 'Not Writable') . '</li>';
+	}
+	return $result . $items;
 }

+ 1 - 1
api/functions/static-globals.php

@@ -1,7 +1,7 @@
 <?php
 // ===================================
 // Organizr Version
-$GLOBALS['installedVersion'] = '2.0.0-beta.950';
+$GLOBALS['installedVersion'] = '2.0.0-beta.980';
 // ===================================
 // Quick php Version check
 $GLOBALS['minimumPHP'] = '7.0.0';

+ 1 - 1
api/functions/token-functions.php

@@ -94,7 +94,7 @@ function createToken($username, $email, $image, $group, $groupID, $key, $days =
 		$database->query('INSERT INTO [tokens]', $addToken);
 		return $jwttoken;
 	} catch (Dibi\Exception $e) {
-		writeLog('error', $e, 'SYSTEM');
+		writeLog('error', 'Token Error: ' . $e, 'SYSTEM');
 		return false;
 	}
 }

+ 57 - 52
api/functions/update-functions.php

@@ -2,61 +2,66 @@
 // Upgrade the installation
 function upgradeInstall($branch = 'v2-master', $stage)
 {
-	ini_set('max_execution_time', 0);
-	set_time_limit(0);
-	$url = 'https://github.com/causefx/Organizr/archive/' . $branch . '.zip';
-	$file = "upgrade.zip";
-	$source = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'upgrade' . DIRECTORY_SEPARATOR . 'Organizr-' . str_replace('v2', '2', $branch) . DIRECTORY_SEPARATOR;
-	$cleanup = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . "upgrade" . DIRECTORY_SEPARATOR;
-	$destination = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR;
-	switch ($stage) {
-		case '1':
-			writeLog('success', 'Update Function -  Started Upgrade Process', $GLOBALS['organizrUser']['username']);
-			if (downloadFile($url, $file)) {
-				writeLog('success', 'Update Function -  Downloaded Update File for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				return true;
-			} else {
-				writeLog('error', 'Update Function -  Downloaded Update File Failed  for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				return false;
-			}
-			break;
-		case '2':
-			if (unzipFile($file)) {
-				writeLog('success', 'Update Function -  Unzipped Update File for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				return true;
-			} else {
-				writeLog('error', 'Update Function -  Unzip Failed for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				return false;
-			}
-			break;
-		case '3':
-			if (rcopy($source, $destination)) {
-				writeLog('success', 'Update Function -  Overwrited Files using Updated Files from Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				$updateComplete = $GLOBALS['dbLocation'] . 'completed.txt';
-				if (!file_exists($updateComplete)) {
-					touch($updateComplete);
+	$notWritable = array_search(false, pathsWritable($GLOBALS['paths']));
+	if ($notWritable == false) {
+		ini_set('max_execution_time', 0);
+		set_time_limit(0);
+		$url = 'https://github.com/causefx/Organizr/archive/' . $branch . '.zip';
+		$file = "upgrade.zip";
+		$source = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'upgrade' . DIRECTORY_SEPARATOR . 'Organizr-' . str_replace('v2', '2', $branch) . DIRECTORY_SEPARATOR;
+		$cleanup = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . "upgrade" . DIRECTORY_SEPARATOR;
+		$destination = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR;
+		switch ($stage) {
+			case '1':
+				writeLog('success', 'Update Function -  Started Upgrade Process', $GLOBALS['organizrUser']['username']);
+				if (downloadFile($url, $file)) {
+					writeLog('success', 'Update Function -  Downloaded Update File for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					return true;
+				} else {
+					writeLog('error', 'Update Function -  Downloaded Update File Failed  for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					return false;
 				}
-				return true;
-			} else {
-				writeLog('error', 'Update Function -  Overwrite Failed for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				return false;
-			}
-			break;
-		case '4':
-			if (rrmdir($cleanup)) {
-				writeLog('success', 'Update Function -  Deleted Update Files from Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
-				writeLog('success', 'Update Function -  Update Completed', $GLOBALS['organizrUser']['username']);
-				return true;
-			} else {
-				writeLog('error', 'Update Function -  Removal of Update Files Failed for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+				break;
+			case '2':
+				if (unzipFile($file)) {
+					writeLog('success', 'Update Function -  Unzipped Update File for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					return true;
+				} else {
+					writeLog('error', 'Update Function -  Unzip Failed for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					return false;
+				}
+				break;
+			case '3':
+				if (rcopy($source, $destination)) {
+					writeLog('success', 'Update Function -  Overwrited Files using Updated Files from Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					$updateComplete = $GLOBALS['dbLocation'] . 'completed.txt';
+					if (!file_exists($updateComplete)) {
+						touch($updateComplete);
+					}
+					return true;
+				} else {
+					writeLog('error', 'Update Function -  Overwrite Failed for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					return false;
+				}
+				break;
+			case '4':
+				if (rrmdir($cleanup)) {
+					writeLog('success', 'Update Function -  Deleted Update Files from Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					writeLog('success', 'Update Function -  Update Completed', $GLOBALS['organizrUser']['username']);
+					return true;
+				} else {
+					writeLog('error', 'Update Function -  Removal of Update Files Failed for Branch: ' . $branch, $GLOBALS['organizrUser']['username']);
+					return false;
+				}
+				break;
+			default:
 				return false;
-			}
-			break;
-		default:
-			return false;
-			break;
+				break;
+		}
+	} else {
+		return 'permissions';
 	}
-	return false;
+	
 }
 
 function downloadFile($url, $path)

+ 56 - 31
api/pages/login.php

@@ -1,5 +1,8 @@
 <?php
-$pageLogin = '
+if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
+	$hideOrganizrLogin = (checkoAuth()) ? 'collapse' : 'collapse in';
+	$hideOrganizrLoginHeader = (checkoAuth()) ? '' : 'hidden';
+	$pageLogin = '
 <script>
 if(activeInfo.settings.login.rememberMe){
 	$(\'#checkbox-login\').prop(\'checked\',true);
@@ -29,41 +32,62 @@ if(activeInfo.settings.login.rememberMe){
 	                        <div class="input-group-addon hidden-xs"><i class="ti-lock"></i></div>
 	                        <input type="text" class="form-control tfa-input" name="tfaCode" placeholder="Code" autocomplete="off" autocorrect="off" autocapitalize="off" maxlength="6" spellcheck="false" autofocus="">
 	                    </div>
+	                    <button class="btn btn-warning btn-lg btn-block text-uppercase waves-effect waves-light login-button m-t-10" type="submit" lang="en">Login</button>
                     </div>
                 </div>
             </div>
           </div>
         </div>
-        <div class="form-group m-t-40">
-          <div class="col-xs-12">
-            <input id="login-username-Input" class="form-control" name="username" type="text" required="" placeholder="Username" lang="en" autofocus>
-          </div>
-        </div>
-        <div class="form-group">
-          <div class="col-xs-12">
-            <input id="login-password-Input" class="form-control" name="password" type="password" required="" placeholder="Password" lang="en">
-          </div>
-        </div>
-        <div class="form-group">
-          <div class="col-md-12">
-            <div class="checkbox checkbox-primary pull-left p-t-0 remember-me">
-              <input id="checkbox-login" name="remember" type="checkbox">
-              <label for="checkbox-login" lang="en">Remember Me</label>
-            </div>
-        	</div>
-        </div>
-        <div class="form-group text-center m-t-20 m-b-0">
-          <div class="col-xs-12">
-            <button class="btn btn-info btn-lg btn-block text-uppercase waves-effect waves-light login-button" type="submit" lang="en">Login</button>
-          </div>
-        </div>
-		' . showoAuth() . '
-        <div class="form-group m-b-0">
-          <div class="col-sm-12 text-center">
-          	<input id="oAuth-Input" class="form-control" name="oAuth" type="hidden">
-            <input id="oAuthType-Input" class="form-control" name="oAuthType" type="hidden">
-            ' . showLogin() . '
-          </div>
+        <div class="panel-group" id="login-panels" data-type="accordion" aria-multiselectable="true" role="tablist">
+	        <!-- ORGANIZR LOGIN -->
+	        <div class="panel">
+	            <div class="panel-heading bg-org ' . $hideOrganizrLoginHeader . '" id="organizr-login-heading" role="tab">
+	            	<a class="panel-title collapsed" data-toggle="collapse" href="#organizr-login-collapse" data-parent="#login-panels" aria-expanded="false" aria-controls="organizr-login-collapse">
+                        <img class="lazyload loginTitle" data-src="plugins/images/organizr/logo-no-border.png"> &nbsp;
+                        <span class="text-uppercase fw300" lang="en">Login with Organizr</span>
+	            	</a>
+	            	<div class="clearfix"></div>
+	            </div>
+	            <div class="panel-collapse ' . $hideOrganizrLogin . '" id="organizr-login-collapse" aria-labelledby="organizr-login-heading" role="tabpanel">
+	                <div class="panel-body">
+	                
+	                	<div class="form-group">
+				          <div class="col-xs-12">
+				            <input id="login-username-Input" class="form-control" name="username" type="text" required="" placeholder="Username" lang="en" autofocus>
+				          </div>
+				        </div>
+				        <div class="form-group">
+				          <div class="col-xs-12">
+				            <input id="login-password-Input" class="form-control" name="password" type="password" required="" placeholder="Password" lang="en">
+				          </div>
+				        </div>
+				        <div class="form-group">
+				          <div class="col-md-12">
+				            <div class="checkbox checkbox-primary pull-left p-t-0 remember-me">
+				              <input id="checkbox-login" name="remember" type="checkbox">
+				              <label for="checkbox-login" lang="en">Remember Me</label>
+				            </div>
+				            </div>
+				        </div>
+				        <div class="form-group text-center m-t-20 m-b-0">
+				          <div class="col-xs-12">
+				            <button class="btn btn-info btn-lg btn-block text-uppercase waves-effect waves-light login-button" type="submit" lang="en">Login</button>
+				          </div>
+				        </div>
+				        <div class="form-group m-b-0">
+				          <div class="col-sm-12 text-center">
+				            <input id="oAuth-Input" class="form-control" name="oAuth" type="hidden">
+				            <input id="oAuthType-Input" class="form-control" name="oAuthType" type="hidden">
+				            ' . showLogin() . '
+				          </div>
+				        </div>
+	                </div>
+	            </div>
+	        </div>
+	        <!-- END ORGANIZR LOGIN -->
+        	<!-- PLEX OAUTH LOGIN -->
+	        ' . showoAuth() . '
+	        <!-- END PLEX OAUTH LOGIN -->
         </div>
       </form>
       <form class="form-horizontal form-material hidden" id="registerForm" onsubmit="return false;">
@@ -125,3 +149,4 @@ if(activeInfo.settings.login.rememberMe){
   </div>
 </section>
 ';
+}

+ 1 - 0
api/pages/settings-tab-editor-tabs.php

@@ -103,6 +103,7 @@ allIcons().success(function(data) {
 </form>
 <form id="edit-tab-form" class="mfp-hide white-popup-block mfp-with-anim">
     <input type="hidden" name="id" value="x">
+    <span class="hidden" id="originalTabName"></span>
     <h1 lang="en">Edit Tab</h1>
     <fieldset style="border:0;">
     	<div class="alert alert-success alert-dismissable tabEditTestMessage hidden">

+ 22 - 8
api/pages/settings.php

@@ -6,6 +6,7 @@ if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
         updateCheck();
         authDebugCheck();
         sponsorLoad();
+        newsLoad();
         [].slice.call(document.querySelectorAll(\'.sttabs\')).forEach(function(el) {
             new CBPFWTabs(el);
         });
@@ -180,6 +181,19 @@ if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
                                 <div class="clearfix"></div>
                             </div>
                             <div role="tabpanel" class="tab-pane fade active in" id="settings-settings-about">
+                            	<div class="row">
+	                                <div class="col-lg-12">
+							            <div class="panel panel-default">
+											<div class="panel-heading bg-org p-t-10 p-b-10">
+												<span class="pull-left m-t-5"><span lang="en">Organizr News</span></span>
+												<div class="clearfix"></div>
+											</div>
+							                <div class="panel-wrapper p-b-0 collapse in bg-org">
+							        			<div id="organizrNewsPanel"></div>
+							                </div>
+							            </div>
+							        </div>
+    							</div>
     							<div class="row">
     								<div class="col-lg-6 col-sm-12 col-md-6">
     									<div class="panel bg-org">
@@ -211,15 +225,15 @@ if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
                                         <div class="white-box bg-org">
                                             <h3 class="box-title" lang="en">Information</h3>
                                             <ul class="feeds">
-                                                <li><div class="bg-info"><i class="mdi mdi-webpack mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">Organizr Version</span> ' . $GLOBALS['installedVersion'] . '</li>
-                                                <li><div class="bg-info"><i class="mdi mdi-github-box mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">Organizr Branch</span> ' . $GLOBALS['branch'] . '</li>
-                                                <li><div class="bg-info"><i class="mdi mdi-database mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">Database Location</span> ' . $GLOBALS['dbLocation'] . $GLOBALS['dbName'] . '</li>
-                                                ' . settingsDocker() . '
+                                                <li><div class="bg-info"><i class="mdi mdi-webpack mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">Organizr Version</span> ' . $GLOBALS['installedVersion'] . '</li>
+                                                <li><div class="bg-info"><i class="mdi mdi-github-box mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">Organizr Branch</span> ' . $GLOBALS['branch'] . '</li>
+                                                <li><div class="bg-info"><i class="mdi mdi-database mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">Database Location</span> ' . $GLOBALS['dbLocation'] . $GLOBALS['dbName'] . '</li>
+                                                ' . settingsDocker() . settingsPathChecks() . '
                                                 <hr class="m-t-10">
-                                                <li><div class="bg-info"><i class="mdi mdi-language-php mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">PHP Version</span> ' . phpversion() . '</li>
-                                                <li><div class="bg-info"><i class="mdi mdi-package-variant-closed mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">Webserver Version</span> ' . $_SERVER['SERVER_SOFTWARE'] . '</li>
+                                                <li><div class="bg-info"><i class="mdi mdi-language-php mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">PHP Version</span> ' . phpversion() . '</li>
+                                                <li><div class="bg-info"><i class="mdi mdi-package-variant-closed mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">Webserver Version</span> ' . $_SERVER['SERVER_SOFTWARE'] . '</li>
                                                 <hr class="m-t-10">
-                                                <li><div class="bg-info"><i class="mdi mdi-account-card-details mdi-24px text-white"></i></div><span class="text-muted hidden-xs" lang="en">License</span> ' . ucwords($GLOBALS['license']) . '</li>
+                                                <li><div class="bg-info"><i class="mdi mdi-account-card-details mdi-24px text-white"></i></div><span class="text-muted hidden-xs m-t-10" lang="en">License</span> ' . ucwords($GLOBALS['license']) . '</li>
                                             </ul>
                                         </div>
                                     </div>
@@ -297,7 +311,7 @@ if (file_exists('config' . DIRECTORY_SEPARATOR . 'config.php')) {
                                             </div>
                                             <div class="tab-pane" id="donate-patreon">
                                                 <blockquote>Need specialized support or just want to support Organizr?  If so head to Patreon...<br/>Please click the button to continue.</blockquote>
-                                                <button onclick="window.open(\'https://www.patreon.com/bePatron?u=8370887\', \'_blank\')" class="btn btn-primary btn-rounded waves-effect waves-light" type="button"><span class="btn-label"><i class="fa fa-link"></i></span><span lang="en">Continue To Website</span></button>
+                                                <button onclick="window.open(\'https://www.patreon.com/join/organizr?\', \'_blank\')" class="btn btn-primary btn-rounded waves-effect waves-light" type="button"><span class="btn-label"><i class="fa fa-link"></i></span><span lang="en">Continue To Website</span></button>
                                             </div>
                                             <div class="tab-pane" id="donate-ads">
                                                 <blockquote>Money not an option?  No problem.  Show some love to this Google Ad below:</blockquote>

+ 1 - 1
api/plugins/js/chat.js

@@ -8,7 +8,7 @@ function chatLaunch(){
     }else{
         if(activeInfo.plugins["CHAT-enabled"] == true && activeInfo.plugins.includes["CHAT-authKey-include"] !== '' && activeInfo.plugins.includes["CHAT-appID-include"] !== '' && activeInfo.plugins.includes["CHAT-cluster-include"] !== ''){
             if (activeInfo.user.groupID <= activeInfo.plugins.includes["CHAT-Auth-include"]) {
-                var menuList = `<li><a class=""  onclick="tabActions(event,'chat','plugin');chatEntry();"><i class="fa fa-comments-o fa-fw"></i> <span lang="en">Chat</span><small class="chat-counter label label-rouded label-info pull-right hidden">0</small></a></li>`;
+                var menuList = `<li><a class=""  href="javascript:void(0)" onclick="tabActions(event,'chat','plugin');chatEntry();"><i class="fa fa-comments-o fa-fw"></i> <span lang="en">Chat</span><small class="chat-counter label label-rouded label-info pull-right hidden">0</small></a></li>`;
 				var htmlDOM = `
                 <div id="container-plugin-chat" class="plugin-container hidden">
                     <div class="chat-main-box bg-org">

+ 22 - 0
css/organizr.css

@@ -1209,6 +1209,28 @@ span.fc-title {
     margin-top: -45px;
     margin-left: -45px;
 }
+.loginTitle {
+    height: 22px;
+    margin-top: -2px;
+}
+.fw300 {
+    font-weight: 300;
+}
+.fw400 {
+    font-weight: 400;
+}
+.fw500 {
+    font-weight: 500;
+}
+.fw600 {
+    font-weight: 600;
+}
+.dropdown-menu {
+    width: 100%;
+}
+#organizrNewsPanel .panel-body {
+    background: #2d2c2c;
+}
 /*
 body,
 html {

File diff suppressed because it is too large
+ 0 - 0
css/organizr.min.css


+ 15 - 0
index.php

@@ -88,6 +88,21 @@
         <!-- /.navbar-header -->
         <!-- /.navbar-top-links -->
         <!-- /.navbar-static-side -->
+        <div class="dropdown-menu animated bounceInDown bg-danger text-white" id="main-org-error-container">
+            <div class="mega-dropdown-menu row">
+                <div class="col-lg-12 mb-4">
+                    <h3 class="mb-3 pull-left"><i class="fa fa-close text-white"></i>&nbsp; <span lang="en">An Error Occured</span>
+                    </h3>
+                    <h3 class="mb-3 pull-right mouse" onclick="closeOrgError();"><i
+                                class="fa fa-check text-success"></i>&nbsp;
+                        <span lang="en">Close Error</span>
+                    </h3>
+                    <br/>
+                    <br/>
+                    <div class="m-t-20" id="main-org-error"></div>
+                </div>
+            </div>
+        </div>
     </nav>
     <!-- End Top Navigation -->
     <!-- ============================================================== -->

+ 48 - 31
js/custom.js

@@ -337,37 +337,44 @@ function doneTypingMediaSearch () {
 }
 $(document).on("click", ".login-button", function(e) {
     e.preventDefault;
-    $('div.login-box').block({
-        message: '<h5><img width="20" src="plugins/images/busy.gif" /> Just a moment...</h4>',
-        css: {
-            color: '#fff',
-            border: '1px solid #2cabe3',
-            backgroundColor: '#2cabe3'
-        }
-    });
-    var post = $( '#loginform' ).serializeArray();
-    organizrAPI('POST','api/?v1/login',post).success(function(data) {
-        var html = JSON.parse(data);
-        if(html.data == true){
-            location.reload();
-        }else if(html.data == 'mismatch') {
-            $('div.login-box').unblock({});
-            message('Login Error', ' Wrong username/email/password combo', activeInfo.settings.notifications.position, '#FFF', 'warning', '10000');
-            console.error('Organizr Function: Login failed - wrong username/email/password');
-        }else if(html.data == '2FA'){
-            $('div.login-box').unblock({});
-            $('#tfa-div').removeClass('hidden');
-            $('#loginform [name=tfaCode]').focus()
-        }else{
+    var check = (local('g','loggingIn'));
+    if(check == null) {
+        local('s','loggingIn', true);
+        $('div.login-box').block({
+            message: '<h5><img width="20" src="plugins/images/busy.gif" /> Just a moment...</h4>',
+            css: {
+                color: '#fff',
+                border: '1px solid #2cabe3',
+                backgroundColor: '#2cabe3'
+            }
+        });
+        var post = $('#loginform').serializeArray();
+        organizrAPI('POST', 'api/?v1/login', post).success(function (data) {
+            var html = JSON.parse(data);
+            if (html.data == true) {
+                local('set','message','Welcome|Login Successful|success');
+                location.reload();
+            } else if (html.data == 'mismatch') {
+                $('div.login-box').unblock({});
+                message('Login Error', ' Wrong username/email/password combo', activeInfo.settings.notifications.position, '#FFF', 'warning', '10000');
+                console.error('Organizr Function: Login failed - wrong username/email/password');
+            } else if (html.data == '2FA') {
+                $('div.login-box').unblock({});
+                $('#tfa-div').removeClass('hidden');
+                $('#loginform [name=tfaCode]').focus()
+            } else {
+                $('div.login-box').unblock({});
+                message('Login Error', html.data, activeInfo.settings.notifications.position, '#FFF', 'warning', '10000');
+                console.error('Organizr Function: Login failed');
+            }
+            local('r','loggingIn');
+        }).fail(function (xhr) {
             $('div.login-box').unblock({});
-            message('Login Error',html.data,activeInfo.settings.notifications.position,'#FFF','warning','10000');
-            console.error('Organizr Function: Login failed');
-        }
-    }).fail(function(xhr) {
-        $('div.login-box').unblock({});
-        message('Login Error','API Connection Failed',activeInfo.settings.notifications.position,'#FFF','warning','10000');
-        console.error("Organizr Function: API Connection Failed");
-    });
+            message('Login Error', 'API Connection Failed', activeInfo.settings.notifications.position, '#FFF', 'warning', '10000');
+            console.error("Organizr Function: API Connection Failed");
+            local('r','loggingIn');
+        });
+    }
 });
 $(document).on("click", ".unlockButton", function(e) {
     e.preventDefault;
@@ -839,6 +846,7 @@ $(document).on("click", ".deleteTab", function () {
 //EDIT TAB GET ID
 $(document).on("click", ".editTabButton", function () {
     $('#edit-tab-form [name=tabName]').val($(this).parent().parent().attr("data-name"));
+    $('#originalTabName').html($(this).parent().parent().attr("data-name"));
     $('#edit-tab-form [name=tabURL]').val($(this).parent().parent().attr("data-url"));
     $('#edit-tab-form [name=tabLocalURL]').val($(this).parent().parent().attr("data-local-url"));
     $('#edit-tab-form [name=pingURL]').val($(this).parent().parent().attr("data-ping-url"));
@@ -852,6 +860,7 @@ $(document).on("click", ".editTabButton", function () {
 });
 //EDIT TAB
 $(document).on("click", ".editTab", function () {
+    var originalTabName = $('#originalTabName').html();
     //Create POST Array
     var post = {
         action:'editTab',
@@ -878,6 +887,10 @@ $(document).on("click", ".editTab", function () {
     if ((typeof post.tabURL == 'undefined' || post.tabURL == '') && (typeof post.tabLocalURL == 'undefined' || post.tabLocalURL == '')) {
         message('Edit Tab Error',' Please set a Tab URL or Local URL',activeInfo.settings.notifications.position,'#FFF','warning','5000');
     }
+    if(checkIfTabNameExists(post.tabName) && originalTabName !== post.tabName){
+        message('Edit Tab Error',' Tab name already used',activeInfo.settings.notifications.position,'#FFF','warning','5000');
+        return false;
+    }
     if(post.id !== '' && post.tabName !== '' && post.tabImage !== ''){
         var callbacks = $.Callbacks();
         callbacks.add( buildTabEditor );
@@ -903,7 +916,7 @@ $(document).on("click", ".addNewTab", function () {
         tabDefault:0,
         tabType:1,
         messageTitle:'Created Tab '+$('#new-tab-form [name=tabName]').val(),
-        messageBody:'Please <a href="javascript(\'window.location.reload(false);\');">RELOAD</a> page to update',
+        messageBody:'Please <a href="javascript:void(0)" onclick="window.location.reload(false);">RELOAD</a> page to update',
         error:'Organizr Function: Tab API Connection Failed'
     };
     if (typeof post.tabOrder == 'undefined' || post.tabOrder == '') {
@@ -918,6 +931,10 @@ $(document).on("click", ".addNewTab", function () {
     if (typeof post.tabImage == 'undefined' || post.tabImage == '') {
         message('New Tab Error',' Please set a Tab Image',activeInfo.settings.notifications.position,'#FFF','warning','5000');
     }
+    if(checkIfTabNameExists(post.tabName)){
+        message('New Tab Error',' Tab name already used',activeInfo.settings.notifications.position,'#FFF','warning','5000');
+        return false;
+    }
     if(post.tabOrder !== '' && post.tabName !== '' && (post.tabURL !== '' || post.tabLocalURL !== '') && post.tabImage !== '' ){
         var callbacks = $.Callbacks();
         callbacks.add( buildTabEditor );

File diff suppressed because it is too large
+ 0 - 0
js/custom.min.js


File diff suppressed because it is too large
+ 491 - 101
js/functions.js


+ 9 - 0
js/news.json

@@ -0,0 +1,9 @@
+[
+  {
+    "title": "Testing out News Area",
+    "subTitle": null,
+    "date": "2019-02-22 21:40",
+    "body": "There will be news here in the future, thanks for bearing with me in the meantime throughout the v2 beta!",
+    "author": "CauseFX"
+  }
+]

+ 14 - 0
js/version.json

@@ -110,5 +110,19 @@
     "new": "Ombi SSO with Plex Token|Default TV Request options for Ombi|Token Section in user settings|Local URL connection if on LAN|Added preload Tab options|Added downloader count to combined downloader|Added option to disable Strict Plex Friend",
     "fixed": "Fixed Emby Connect|Disable lock function for oAuth users (#973)|Better error handling for the *arrs|make settings open first tab if not active already (#901)|make sure db ends with .db (#971)|Fix deluge hide seeding etc (#867)|fix downloaders showing blank if no permissions (#977)|Plex login button css (#985)|Add tab help (#987)|Fix close buttons (#883)|close buttons on popups fixed (#996)|fix clipboard with value with filename containing space (#994)|Move machine ID check outside of foreach (#1014)|Fixed language error if not langpack is installed for that lang (#1028)|undefined index on sickrage (#1038)|Fix iframe focus not shifting back (#1042)",
     "notes": "Added more debug information|Reworked the way languages are loaded|Updated Language strings|Revamped Splash page"
+  },
+  "2.0.0-beta.960": {
+    "date": "2019-01-27 00:20",
+    "title": "Some fixes before v2.0",
+    "new": "Update page includes links to GH issues|Cleaner Login|Default to Plex Auth if enabled on login screen",
+    "fixed": "Fix Plex oAuth remains enabled when switching back to Organizr DB only (#1046)|Fix Ombi if no TV Requests again|2FA box includes login button now",
+    "notes": "Hoping for a smooth release of 2.0 this coming week"
+  },
+  "2.0.0-beta.980": {
+    "date": "2019-02-22 15:30",
+    "title": "Little things here and there",
+    "new": "Added news section to settings page|Add new pathsWritable function for multiple paths|Added global variable for main path and api path|Added update check for folder permissions|Added login with plex email and plex username for oauth|Added option for Ombi Homepage pulls Ombi Username instead of alias (#1052)|Added error catching on json parse for ajax calls|Add Pi-Hole image (#1060)|Added DB Path to folder check|Disable update and download if using docker container|Added Close Tab to Alt + Click|Disable branch change for docker users",
+    "fixed": "Fix update button on message not working if not on settings page (#1050)|Fix js reload button on new tab creation|Finally fix ombi limit to user|Fix tab edit/create when using same tab name already in use (#1066)|Embi local API requires exact case for username (#1061)|Fix edit tab name if exists",
+    "notes": "Remove constant welcome message - Added welcome message only on login|Clean up org errors a little bit"
   }
 }

BIN
plugins/images/organizr/logo-no-border.png


BIN
plugins/images/tabs/pihole.png


Some files were not shown because too many files changed in this diff