Browse Source

added testFolder function
added logLocation and dbLocation to updateConfigItems function to cleanDirectory
added logLocation to log settings
added logLocation to logFunctions trait file
added makeDir to normal-functions.php file
added makeDir to setOrganizrLog function
added folder to settingsOption function
added folder to buildFormItem function
added test/folder api endpoint

CauseFX 4 years ago
parent
commit
3459a024bb

+ 28 - 0
api/classes/organizr.class.php

@@ -1891,6 +1891,7 @@ class Organizr
 				$this->settingsOption('code-editor', 'blacklistedMessage', ['mode' => 'html']),
 			],
 			'Logs' => [
+				$this->settingsOption('folder', 'logLocation', ['label' => 'Log Save Path', 'help' => 'Folder path to save Organizr Logs - Please test before saving', 'value' => $this->logLocation()]),
 				$this->settingsOption('select', 'logLevel', ['label' => 'Log Level', 'options' => $this->logLevels()]),
 				$this->settingsOption('switch', 'includeDatabaseQueriesInDebug', ['label' => 'Include Database Queries', 'help' => 'Include Database queries in debug logs']),
 				$this->settingsOption('number', 'maxLogFiles', ['label' => 'Maximum Log Files', 'help' => 'Number of log files to preserve', 'attr' => 'min="1"']),
@@ -2229,6 +2230,16 @@ class Organizr
 					}
 				}
 			}
+			switch ($k) {
+				case 'logLocation':
+				case 'dbLocation':
+					if (!empty($v)) {
+						$v = $this->cleanDirectory($v);
+					}
+					break;
+				default:
+					break;
+			}
 			if (strtolower($k) !== 'formkey') {
 				$newItem[$k] = $v;
 				$this->config[$k] = $v;
@@ -6577,6 +6588,23 @@ class Organizr
 		}
 	}
 
+	public function testFolder($folder = null)
+	{
+		$folder = $folder['folder'] ?? null;
+		if (!$folder) {
+			$this->setResponse(409, 'Folder was not supplied');
+			return false;
+		}
+		$testFolder = $this->makeDir($folder);
+		if ($testFolder) {
+			$this->setResponse(200, 'Folder approved for logs');
+			return true;
+		} else {
+			$this->setResponse(409, 'Folder path is not valid or permissions insufficient');
+			return false;
+		}
+	}
+
 	protected function processQueries(array $request, $migration = false)
 	{
 		$results = array();

+ 29 - 24
api/functions/log-functions.php

@@ -2,71 +2,77 @@
 
 trait LogFunctions
 {
+	public function logLocation()
+	{
+		return isset($this->config['logLocation']) && $this->config['logLocation'] !== '' ? $this->config['logLocation'] : $this->config['dbLocation'] . 'logs' . DIRECTORY_SEPARATOR;
+	}
+
 	public function debug($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->debug($msg, $context);
 		}
 	}
-	
+
 	public function info($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->info($msg, $context);
 		}
 	}
-	
+
 	public function notice($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->notice($msg, $context);
 		}
 	}
-	
+
 	public function warning($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->warning($msg, $context);
 		}
 	}
-	
+
 	public function error($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->error($msg, $context);
 		}
 	}
-	
+
 	public function critical($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->critical($msg, $context);
 		}
 	}
-	
+
 	public function alert($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->alert($msg, $context);
 		}
 	}
-	
+
 	public function emergency($msg, $context = [])
 	{
 		if ($this->logger) {
 			$this->logger->emergency($msg, $context);
 		}
 	}
-	
+
 	public function setOrganizrLog()
 	{
 		if ($this->hasDB()) {
-			$logPath = $this->config['dbLocation'] . 'logs' . DIRECTORY_SEPARATOR;
+			$this->makeDir($this->logLocation());
+			$logPath = $this->logLocation();
 			return $logPath . 'organizr.log';
 		}
 		return false;
 	}
-	
+
 	public function readLog($file, $pageSize = 10, $offset = 0, $filter = 'NONE', $trace_id = null)
 	{
 		$combinedLogs = false;
@@ -126,7 +132,7 @@ trait LogFunctions
 		}
 		return false;
 	}
-	
+
 	public function formatLogResults($lines, $pageSize, $offset)
 	{
 		if (is_array($lines)) {
@@ -150,12 +156,12 @@ trait LogFunctions
 			return json_decode($lines, true);
 		}
 	}
-	
+
 	public function getLatestLogFile()
 	{
 		if ($this->log) {
 			if (isset($this->log)) {
-				$folder = $this->config['dbLocation'] . 'logs' . DIRECTORY_SEPARATOR;
+				$folder = $this->logLocation();
 				$directoryIterator = new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS);
 				$iteratorIterator = new RecursiveIteratorIterator($directoryIterator);
 				$files = [];
@@ -176,12 +182,12 @@ trait LogFunctions
 		}
 		return false;
 	}
-	
+
 	public function getLogFiles()
 	{
 		if ($this->log) {
 			if (isset($this->log)) {
-				$folder = $this->config['dbLocation'] . 'logs' . DIRECTORY_SEPARATOR;
+				$folder = $this->logLocation();
 				$directoryIterator = new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS);
 				$iteratorIterator = new RecursiveIteratorIterator($directoryIterator);
 				$files = [];
@@ -200,7 +206,7 @@ trait LogFunctions
 		}
 		return false;
 	}
-	
+
 	public function setLoggerChannel($channel = 'Organizr', $username = null)
 	{
 		if ($this->hasDB()) {
@@ -225,7 +231,7 @@ trait LogFunctions
 			}
 		}
 	}
-	
+
 	public function setupLogger($channel = 'Organizr', $username = null)
 	{
 		if (!$username) {
@@ -280,9 +286,8 @@ trait LogFunctions
 		exception:
 		$this->logger->critical($exception, $context);
 		*/
-		
 	}
-	
+
 	public function tempLogIfNeeded()
 	{
 		if (!$this->log) {
@@ -291,7 +296,7 @@ trait LogFunctions
 			return $this->log;
 		}
 	}
-	
+
 	public function getLog($pageSize = 10, $offset = 0, $filter = 'NONE', $number = 0, $trace_id = null)
 	{
 		if ($this->log) {
@@ -319,7 +324,7 @@ trait LogFunctions
 			return false;
 		}
 	}
-	
+
 	public function purgeLog($number)
 	{
 		$this->setLoggerChannel('Logger');
@@ -366,7 +371,7 @@ trait LogFunctions
 			return false;
 		}
 	}
-	
+
 	public function logArray($context)
 	{
 		if (!is_array($context)) {
@@ -380,7 +385,7 @@ trait LogFunctions
 			return $context;
 		}
 	}
-	
+
 	function buildLogDropdown()
 	{
 		$logs = $this->getLogFiles();
@@ -400,7 +405,7 @@ trait LogFunctions
 		}
 		return false;
 	}
-	
+
 	function buildFilterDropdown()
 	{
 		$dropdownItems = '<li><a href="javascript:toggleLogFilter(\'DEBUG\')"><span lang="en">Debug</span></a></li>';

+ 5 - 0
api/functions/normal-functions.php

@@ -698,6 +698,11 @@ trait NormalFunctions
 		}
 		return false;
 	}
+
+	public function makeDir($dirPath, $mode = 0777)
+	{
+		return is_dir($dirPath) || @mkdir($dirPath, $mode, true);
+	}
 }
 
 // Leave for deluge class

+ 8 - 0
api/functions/option-functions.php

@@ -100,6 +100,14 @@ trait OptionsFunction
 					'placeholder' => '* * * * *'
 				];
 				break;
+			case 'folder':
+				$settingMerge = [
+					'type' => 'folder',
+					'label' => 'Save Path',
+					'help' => 'Folder path',
+					'placeholder' => '/path/to/folder'
+				];
+				break;
 			case 'cronfile':
 				$path = $this->root . DIRECTORY_SEPARATOR . 'cron.php';
 				$server = $this->serverIP();

+ 22 - 24
api/v2/routes/connectionTester.php

@@ -26,7 +26,6 @@ $app->post('/test/ldap', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/ldap/login', function ($request, $response, $args) {
 	/**
@@ -49,7 +48,6 @@ $app->post('/test/ldap/login', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/iframe', function ($request, $response, $args) {
 	/**
@@ -72,7 +70,6 @@ $app->post('/test/iframe', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/path', function ($request, $response, $args) {
 	/**
@@ -92,7 +89,6 @@ $app->post('/test/path', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/plex', function ($request, $response, $args) {
 	/**
@@ -115,7 +111,6 @@ $app->post('/test/plex', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/emby', function ($request, $response, $args) {
 	/**
@@ -138,7 +133,6 @@ $app->post('/test/emby', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/jellyfin', function ($request, $response, $args) {
 	/**
@@ -161,7 +155,6 @@ $app->post('/test/jellyfin', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/sabnzbd', function ($request, $response, $args) {
 	/**
@@ -184,7 +177,6 @@ $app->post('/test/sabnzbd', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/pihole', function ($request, $response, $args) {
 	/**
@@ -207,7 +199,6 @@ $app->post('/test/pihole', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/rtorrent', function ($request, $response, $args) {
 	/**
@@ -230,7 +221,6 @@ $app->post('/test/rtorrent', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/sonarr', function ($request, $response, $args) {
 	/**
@@ -253,7 +243,6 @@ $app->post('/test/sonarr', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/radarr', function ($request, $response, $args) {
 	/**
@@ -276,7 +265,6 @@ $app->post('/test/radarr', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/lidarr', function ($request, $response, $args) {
 	/**
@@ -299,7 +287,6 @@ $app->post('/test/lidarr', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/sickrage', function ($request, $response, $args) {
 	/**
@@ -322,7 +309,6 @@ $app->post('/test/sickrage', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/ombi', function ($request, $response, $args) {
 	/**
@@ -345,7 +331,6 @@ $app->post('/test/ombi', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/overseerr', function ($request, $response, $args) {
 	/**
@@ -368,7 +353,6 @@ $app->post('/test/overseerr', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/nzbget', function ($request, $response, $args) {
 	/**
@@ -391,7 +375,6 @@ $app->post('/test/nzbget', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/utorrent', function ($request, $response, $args) {
 	/**
@@ -414,7 +397,6 @@ $app->post('/test/utorrent', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/deluge', function ($request, $response, $args) {
 	/**
@@ -437,7 +419,6 @@ $app->post('/test/deluge', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/jdownloader', function ($request, $response, $args) {
 	/**
@@ -460,7 +441,6 @@ $app->post('/test/jdownloader', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/transmission', function ($request, $response, $args) {
 	/**
@@ -483,7 +463,6 @@ $app->post('/test/transmission', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/qbittorrent', function ($request, $response, $args) {
 	/**
@@ -506,7 +485,6 @@ $app->post('/test/qbittorrent', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/unifi', function ($request, $response, $args) {
 	/**
@@ -529,7 +507,6 @@ $app->post('/test/unifi', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/unifi/site', function ($request, $response, $args) {
 	/**
@@ -552,7 +529,6 @@ $app->post('/test/unifi/site', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
-	
 });
 $app->post('/test/tautulli', function ($request, $response, $args) {
 	/**
@@ -624,4 +600,26 @@ $app->get('/test/cron', function ($request, $response, $args) {
 	return $response
 		->withHeader('Content-Type', 'application/json;charset=UTF-8')
 		->withStatus($GLOBALS['responseCode']);
+});
+$app->post('/test/folder', function ($request, $response, $args) {
+	/**
+	 * @OA\Post(
+	 *     security={{ "api_key":{} }},
+	 *     tags={"test connection"},
+	 *     path="/api/v2/test/folder",
+	 *     summary="Test folder path",
+	 *     @OA\Response(response="200",description="Success",@OA\JsonContent(ref="#/components/schemas/success-message")),
+	 *     @OA\Response(response="401",description="Unauthorized",@OA\JsonContent(ref="#/components/schemas/unauthorized-message")),
+	 *     @OA\Response(response="422",description="Error",@OA\JsonContent(ref="#/components/schemas/error-message")),
+	 *     @OA\Response(response="500",description="Error",@OA\JsonContent(ref="#/components/schemas/error-message")),
+	 * )
+	 */
+	$Organizr = ($request->getAttribute('Organizr')) ?? new Organizr();
+	if ($Organizr->qualifyRequest(1, true)) {
+		$Organizr->testFolder($Organizr->apiData($request));
+	}
+	$response->getBody()->write(jsonE($GLOBALS['api']));
+	return $response
+		->withHeader('Content-Type', 'application/json;charset=UTF-8')
+		->withStatus($GLOBALS['responseCode']);
 });

+ 6 - 0
js/custom.js

@@ -1962,4 +1962,10 @@ $(document).on("change", ".choose-organizr-log", function () {
 $(document).on('click', '.test-cron', function() {
 	let cron = $(this).parent().parent().find('input').val();
 	testAPIConnection('cron',cron);
+});
+
+// Test Folder
+$(document).on('click', '.test-folder', function() {
+    let folder = $(this).parent().parent().find('input').val();
+    testAPIConnection('folder',{'folder':folder});
 });

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


+ 2 - 0
js/functions.js

@@ -1159,6 +1159,8 @@ function buildFormItem(item){
 		case 'cron':
 			return `${smallLabel}<div class="input-group"><input data-changed="false" class="form-control ${extraClass}" ${placeholder} ${value} ${id} ${name} ${disabled} ${type} ${label} ${attr} autocomplete="new-password"><span class="input-group-btn"><button class="btn btn-info test-cron" type="button"><i class="fa fa-flask"></i></button></span></div>`;
 			break;
+        case 'folder':
+            return `${smallLabel}<div class="input-group"><input data-changed="false" class="form-control ${extraClass}" ${placeholder} ${value} ${id} ${name} ${disabled} ${type} ${label} ${attr} autocomplete="new-password"><span class="input-group-btn"><button class="btn btn-info test-folder" type="button"><i class="fa fa-flask"></i></button></span></div>`;
 		default:
 			return '<span class="text-danger">BuildFormItem Class not setup...';
 	}

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