Passed
Push — master ( 65fd87...291b97 )
by Pauli
03:21
created

SettingController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 9
dl 0
loc 18
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php declare(strict_types=1);
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Morris Jobke <[email protected]>
10
 * @author Pauli Järvinen <[email protected]>
11
 * @copyright Morris Jobke 2013, 2014
12
 * @copyright Pauli Järvinen 2017 - 2023
13
 */
14
15
namespace OCA\Music\Controller;
16
17
use OCP\AppFramework\Controller;
18
use OCP\AppFramework\Http;
19
use OCP\AppFramework\Http\JSONResponse;
20
use OCP\IRequest;
21
use OCP\IURLGenerator;
22
use OCP\Security\ISecureRandom;
23
24
use OCA\Music\AppFramework\Core\Logger;
25
use OCA\Music\Db\AmpacheUserMapper;
26
use OCA\Music\Http\ErrorResponse;
27
use OCA\Music\Utility\AppInfo;
28
use OCA\Music\Utility\LibrarySettings;
29
use OCA\Music\Utility\Scanner;
30
use OCA\Music\Utility\Util;
31
32
class SettingController extends Controller {
33
	const DEFAULT_PASSWORD_LENGTH = 10;
34
	/* Character set without look-alike characters. Similar but even more stripped set would be found
35
	 * on Nextcloud as ISecureRandom::CHAR_HUMAN_READABLE but that's not availalbe on ownCloud. */
36
	const API_KEY_CHARSET = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
37
38
	private $ampacheUserMapper;
39
	private $scanner;
40
	private $userId;
41
	private $librarySettings;
42
	private $secureRandom;
43
	private $urlGenerator;
44
	private $logger;
45
46
	public function __construct(string $appName,
47
								IRequest $request,
48
								AmpacheUserMapper $ampacheUserMapper,
49
								Scanner $scanner,
50
								?string $userId,
51
								LibrarySettings $librarySettings,
52
								ISecureRandom $secureRandom,
53
								IURLGenerator $urlGenerator,
54
								Logger $logger) {
55
		parent::__construct($appName, $request);
56
57
		$this->ampacheUserMapper = $ampacheUserMapper;
58
		$this->scanner = $scanner;
59
		$this->userId = $userId ?? ''; // ensure non-null to satisfy Scrutinizer; the null case should happen only when the user has already logged out
60
		$this->librarySettings = $librarySettings;
61
		$this->secureRandom = $secureRandom;
62
		$this->urlGenerator = $urlGenerator;
63
		$this->logger = $logger;
64
	}
65
66
	/**
67
	 * @NoAdminRequired
68
	 * @NoCSRFRequired
69
	 * @UseSession to keep the session reserved while execution in progress
70
	 */
71
	public function userPath(string $value) {
72
		$prevPath = $this->librarySettings->getPath($this->userId);
73
		$success = $this->librarySettings->setPath($this->userId, $value);
74
75
		if ($success) {
76
			$this->scanner->updatePath($prevPath, $value, $this->userId);
77
		}
78
79
		return new JSONResponse(['success' => $success]);
80
	}
81
82
	/**
83
	 * @NoAdminRequired
84
	 * @NoCSRFRequired
85
	 */
86
	public function userExcludedPaths(array $value) {
87
		$success = $this->librarySettings->setExcludedPaths($this->userId, $value);
88
		return new JSONResponse(['success' => $success]);
89
	}
90
91
	/**
92
	 * @NoAdminRequired
93
	 * @NoCSRFRequired
94
	 */
95
	public function enableScanMetadata(bool $value) {
96
		$this->librarySettings->setScanMetadataEnabled($this->userId, $value);
97
		return new JSONResponse(['success' => true]);
98
	}
99
100
	/**
101
	 * @NoAdminRequired
102
	 * @NoCSRFRequired
103
	 */
104
	public function ignoredArticles(array $value) {
105
		$this->librarySettings->setIgnoredArticles($this->userId, $value);
106
		return new JSONResponse(['success' => true]);
107
	}
108
109
	/**
110
	 * @NoAdminRequired
111
	 * @NoCSRFRequired
112
	 */
113
	public function getAll() {
114
		return [
115
			'path' => $this->librarySettings->getPath($this->userId),
116
			'excludedPaths' => $this->librarySettings->getExcludedPaths($this->userId),
117
			'scanMetadata' => $this->librarySettings->getScanMetadataEnabled($this->userId),
118
			'ignoredArticles' => $this->librarySettings->getIgnoredArticles($this->userId),
119
			'ampacheUrl' => $this->getAmpacheUrl(),
120
			'subsonicUrl' => $this->getSubsonicUrl(),
121
			'ampacheKeys' => $this->getUserKeys(),
122
			'appVersion' => AppInfo::getVersion(),
123
			'user' => $this->userId
124
		];
125
	}
126
127
	/**
128
	 * @NoAdminRequired
129
	 * @NoCSRFRequired
130
	 */
131
	public function getUserKeys() {
132
		return $this->ampacheUserMapper->getAll($this->userId);
133
	}
134
135
	private function getAmpacheUrl() {
136
		return \str_replace('/server/xml.server.php', '',
137
				$this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('music.ampache.xmlApi')));
138
	}
139
140
	private function getSubsonicUrl() {
141
		return \str_replace('/rest/dummy', '',
142
				$this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute(
143
						'music.subsonic.handleRequest', ['method' => 'dummy'])));
144
	}
145
146
	private function storeUserKey($description, $password) {
147
		$hash = \hash('sha256', $password);
148
		$description = Util::truncate($description, 64); // some DB setups can't truncate automatically to column max size
149
		return $this->ampacheUserMapper->addUserKey($this->userId, $hash, $description);
150
	}
151
152
	/**
153
	 * @NoAdminRequired
154
	 */
155
	public function createUserKey($length, $description) {
156
		if ($length == null || $length < self::DEFAULT_PASSWORD_LENGTH) {
157
			$length = self::DEFAULT_PASSWORD_LENGTH;
158
		}
159
160
		$password = $this->secureRandom->generate($length, self::API_KEY_CHARSET);
161
162
		$id = $this->storeUserKey($description, $password);
163
164
		if ($id === null) {
165
			return new ErrorResponse(Http::STATUS_INTERNAL_SERVER_ERROR, 'Error while saving the credentials');
166
		}
167
168
		return new JSONResponse(['id' => $id, 'password' => $password, 'description' => $description], Http::STATUS_CREATED);
169
	}
170
171
	/**
172
	 * The CORS-version of the key creation function is targeted for external clients. We need separate function
173
	 * because the CORS middleware blocks the normal internal access on Nextcloud versions older than 25 as well
174
	 * as on ownCloud 10.0, at least (but not on OC 10.4+).
175
	 *
176
	 * @NoAdminRequired
177
	 * @CORS
178
	 */
179
	public function createUserKeyCors($length, $description) {
180
		return $this->createUserKey($length, $description);
181
	}
182
183
	/**
184
	 * @NoAdminRequired
185
	 * @NoCSRFRequired
186
	 */
187
	public function removeUserKey($id) {
188
		$this->ampacheUserMapper->removeUserKey($this->userId, (int)$id);
189
		return new JSONResponse(['success' => true]);
190
	}
191
}
192