Completed
Push — master ( d03f6d...56f3d1 )
by Joas
20:52 queued 17s
created
apps/dav/lib/BulkUpload/MultipartRequestParser.php 1 patch
Indentation   +235 added lines, -235 removed lines patch added patch discarded remove patch
@@ -15,239 +15,239 @@
 block discarded – undo
15 15
 
16 16
 class MultipartRequestParser {
17 17
 
18
-	/** @var resource */
19
-	private $stream;
20
-
21
-	/** @var string */
22
-	private $boundary = '';
23
-
24
-	/** @var string */
25
-	private $lastBoundary = '';
26
-
27
-	/**
28
-	 * @throws BadRequest
29
-	 */
30
-	public function __construct(
31
-		RequestInterface $request,
32
-		protected LoggerInterface $logger,
33
-	) {
34
-		$stream = $request->getBody();
35
-		$contentType = $request->getHeader('Content-Type');
36
-
37
-		if (!is_resource($stream)) {
38
-			throw new BadRequest('Body should be of type resource');
39
-		}
40
-
41
-		if ($contentType === null) {
42
-			throw new BadRequest('Content-Type can not be null');
43
-		}
44
-
45
-		$this->stream = $stream;
46
-
47
-		$boundary = $this->parseBoundaryFromHeaders($contentType);
48
-		$this->boundary = '--' . $boundary . "\r\n";
49
-		$this->lastBoundary = '--' . $boundary . "--\r\n";
50
-	}
51
-
52
-	/**
53
-	 * Parse the boundary from the Content-Type header.
54
-	 * Example: Content-Type: "multipart/related; boundary=boundary_bf38b9b4b10a303a28ed075624db3978"
55
-	 *
56
-	 * @throws BadRequest
57
-	 */
58
-	private function parseBoundaryFromHeaders(string $contentType): string {
59
-		try {
60
-			if (!str_contains($contentType, ';')) {
61
-				throw new \InvalidArgumentException('No semicolon in header');
62
-			}
63
-			[$mimeType, $boundary] = explode(';', $contentType);
64
-			if (!str_contains($boundary, '=')) {
65
-				throw new \InvalidArgumentException('No equal in boundary header');
66
-			}
67
-			[$boundaryKey, $boundaryValue] = explode('=', $boundary);
68
-		} catch (\Exception $e) {
69
-			throw new BadRequest('Error while parsing boundary in Content-Type header.', Http::STATUS_BAD_REQUEST, $e);
70
-		}
71
-
72
-		$boundaryValue = trim($boundaryValue);
73
-
74
-		// Remove potential quotes around boundary value.
75
-		if (str_starts_with($boundaryValue, '"') && str_ends_with($boundaryValue, '"')) {
76
-			$boundaryValue = substr($boundaryValue, 1, -1);
77
-		}
78
-
79
-		if (trim($mimeType) !== 'multipart/related') {
80
-			throw new BadRequest('Content-Type must be multipart/related');
81
-		}
82
-
83
-		if (trim($boundaryKey) !== 'boundary') {
84
-			throw new BadRequest('Boundary is invalid');
85
-		}
86
-
87
-		return $boundaryValue;
88
-	}
89
-
90
-	/**
91
-	 * Check whether the stream's cursor is sitting right before the provided string.
92
-	 *
93
-	 * @throws Exception
94
-	 */
95
-	private function isAt(string $expectedContent): bool {
96
-		$expectedContentLength = strlen($expectedContent);
97
-
98
-		$content = fread($this->stream, $expectedContentLength);
99
-		if ($content === false) {
100
-			throw new Exception('An error occurred while checking content');
101
-		}
102
-
103
-		$seekBackResult = fseek($this->stream, -$expectedContentLength, SEEK_CUR);
104
-		if ($seekBackResult === -1) {
105
-			throw new Exception('Unknown error while seeking content', Http::STATUS_INTERNAL_SERVER_ERROR);
106
-		}
107
-
108
-		return $expectedContent === $content;
109
-	}
110
-
111
-
112
-	/**
113
-	 * Check whether the stream's cursor is sitting right before the boundary.
114
-	 */
115
-	private function isAtBoundary(): bool {
116
-		return $this->isAt($this->boundary);
117
-	}
118
-
119
-	/**
120
-	 * Check whether the stream's cursor is sitting right before the last boundary.
121
-	 */
122
-	public function isAtLastBoundary(): bool {
123
-		return $this->isAt($this->lastBoundary);
124
-	}
125
-
126
-	/**
127
-	 * Parse and return the next part of the multipart headers.
128
-	 *
129
-	 * Example:
130
-	 * --boundary_azertyuiop
131
-	 * Header1: value
132
-	 * Header2: value
133
-	 *
134
-	 * Content of
135
-	 * the part
136
-	 *
137
-	 */
138
-	public function parseNextPart(): array {
139
-		$this->readBoundary();
140
-
141
-		$headers = $this->readPartHeaders();
142
-
143
-		$length = (int)$headers['content-length'];
144
-
145
-		$this->validateHash($length, $headers['x-file-md5'] ?? '', $headers['oc-checksum'] ?? '');
146
-		$content = $this->readPartContent($length);
147
-
148
-		return [$headers, $content];
149
-	}
150
-
151
-	/**
152
-	 * Read the boundary and check its content.
153
-	 *
154
-	 * @throws BadRequest
155
-	 */
156
-	private function readBoundary(): string {
157
-		if (!$this->isAtBoundary()) {
158
-			throw new BadRequest('Boundary not found where it should be.');
159
-		}
160
-
161
-		return fread($this->stream, strlen($this->boundary));
162
-	}
163
-
164
-	/**
165
-	 * Return the headers of a part of the multipart body.
166
-	 *
167
-	 * @throws Exception
168
-	 * @throws BadRequest
169
-	 * @throws LengthRequired
170
-	 */
171
-	private function readPartHeaders(): array {
172
-		$headers = [];
173
-
174
-		while (($line = fgets($this->stream)) !== "\r\n") {
175
-			if ($line === false) {
176
-				throw new Exception('An error occurred while reading headers of a part');
177
-			}
178
-
179
-			if (!str_contains($line, ':')) {
180
-				$this->logger->error('Header missing ":" on bulk request: ' . json_encode($line));
181
-				throw new Exception('An error occurred while reading headers of a part', Http::STATUS_BAD_REQUEST);
182
-			}
183
-
184
-			try {
185
-				[$key, $value] = explode(':', $line, 2);
186
-				$headers[strtolower(trim($key))] = trim($value);
187
-			} catch (\Exception $e) {
188
-				throw new BadRequest('An error occurred while parsing headers of a part', Http::STATUS_BAD_REQUEST, $e);
189
-			}
190
-		}
191
-
192
-		if (!isset($headers['content-length'])) {
193
-			throw new LengthRequired('The Content-Length header must not be null.');
194
-		}
195
-
196
-		// TODO: Drop $md5 condition when the latest desktop client that uses it is no longer supported.
197
-		if (!isset($headers['x-file-md5']) && !isset($headers['oc-checksum'])) {
198
-			throw new BadRequest('The hash headers must not be null.');
199
-		}
200
-
201
-		return $headers;
202
-	}
203
-
204
-	/**
205
-	 * Return the content of a part of the multipart body.
206
-	 *
207
-	 * @throws Exception
208
-	 * @throws BadRequest
209
-	 */
210
-	private function readPartContent(int $length): string {
211
-		if ($length === 0) {
212
-			$content = '';
213
-		} else {
214
-			$content = stream_get_line($this->stream, $length);
215
-		}
216
-
217
-		if ($content === false) {
218
-			throw new Exception("Fail to read part's content.");
219
-		}
220
-
221
-		if ($length !== 0 && feof($this->stream)) {
222
-			throw new Exception('Unexpected EOF while reading stream.');
223
-		}
224
-
225
-		// Read '\r\n'.
226
-		stream_get_contents($this->stream, 2);
227
-
228
-		return $content;
229
-	}
230
-
231
-	/**
232
-	 * Compute the MD5 or checksum hash of the next x bytes.
233
-	 * TODO: Drop $md5 argument when the latest desktop client that uses it is no longer supported.
234
-	 */
235
-	private function validateHash(int $length, string $fileMd5Header, string $checksumHeader): void {
236
-		if ($checksumHeader !== '') {
237
-			[$algorithm, $hash] = explode(':', $checksumHeader, 2);
238
-		} elseif ($fileMd5Header !== '') {
239
-			$algorithm = 'md5';
240
-			$hash = $fileMd5Header;
241
-		} else {
242
-			throw new BadRequest('No hash provided.');
243
-		}
244
-
245
-		$context = hash_init($algorithm);
246
-		hash_update_stream($context, $this->stream, $length);
247
-		fseek($this->stream, -$length, SEEK_CUR);
248
-		$computedHash = hash_final($context);
249
-		if ($hash !== $computedHash) {
250
-			throw new BadRequest("Computed $algorithm hash is incorrect ($computedHash).");
251
-		}
252
-	}
18
+    /** @var resource */
19
+    private $stream;
20
+
21
+    /** @var string */
22
+    private $boundary = '';
23
+
24
+    /** @var string */
25
+    private $lastBoundary = '';
26
+
27
+    /**
28
+     * @throws BadRequest
29
+     */
30
+    public function __construct(
31
+        RequestInterface $request,
32
+        protected LoggerInterface $logger,
33
+    ) {
34
+        $stream = $request->getBody();
35
+        $contentType = $request->getHeader('Content-Type');
36
+
37
+        if (!is_resource($stream)) {
38
+            throw new BadRequest('Body should be of type resource');
39
+        }
40
+
41
+        if ($contentType === null) {
42
+            throw new BadRequest('Content-Type can not be null');
43
+        }
44
+
45
+        $this->stream = $stream;
46
+
47
+        $boundary = $this->parseBoundaryFromHeaders($contentType);
48
+        $this->boundary = '--' . $boundary . "\r\n";
49
+        $this->lastBoundary = '--' . $boundary . "--\r\n";
50
+    }
51
+
52
+    /**
53
+     * Parse the boundary from the Content-Type header.
54
+     * Example: Content-Type: "multipart/related; boundary=boundary_bf38b9b4b10a303a28ed075624db3978"
55
+     *
56
+     * @throws BadRequest
57
+     */
58
+    private function parseBoundaryFromHeaders(string $contentType): string {
59
+        try {
60
+            if (!str_contains($contentType, ';')) {
61
+                throw new \InvalidArgumentException('No semicolon in header');
62
+            }
63
+            [$mimeType, $boundary] = explode(';', $contentType);
64
+            if (!str_contains($boundary, '=')) {
65
+                throw new \InvalidArgumentException('No equal in boundary header');
66
+            }
67
+            [$boundaryKey, $boundaryValue] = explode('=', $boundary);
68
+        } catch (\Exception $e) {
69
+            throw new BadRequest('Error while parsing boundary in Content-Type header.', Http::STATUS_BAD_REQUEST, $e);
70
+        }
71
+
72
+        $boundaryValue = trim($boundaryValue);
73
+
74
+        // Remove potential quotes around boundary value.
75
+        if (str_starts_with($boundaryValue, '"') && str_ends_with($boundaryValue, '"')) {
76
+            $boundaryValue = substr($boundaryValue, 1, -1);
77
+        }
78
+
79
+        if (trim($mimeType) !== 'multipart/related') {
80
+            throw new BadRequest('Content-Type must be multipart/related');
81
+        }
82
+
83
+        if (trim($boundaryKey) !== 'boundary') {
84
+            throw new BadRequest('Boundary is invalid');
85
+        }
86
+
87
+        return $boundaryValue;
88
+    }
89
+
90
+    /**
91
+     * Check whether the stream's cursor is sitting right before the provided string.
92
+     *
93
+     * @throws Exception
94
+     */
95
+    private function isAt(string $expectedContent): bool {
96
+        $expectedContentLength = strlen($expectedContent);
97
+
98
+        $content = fread($this->stream, $expectedContentLength);
99
+        if ($content === false) {
100
+            throw new Exception('An error occurred while checking content');
101
+        }
102
+
103
+        $seekBackResult = fseek($this->stream, -$expectedContentLength, SEEK_CUR);
104
+        if ($seekBackResult === -1) {
105
+            throw new Exception('Unknown error while seeking content', Http::STATUS_INTERNAL_SERVER_ERROR);
106
+        }
107
+
108
+        return $expectedContent === $content;
109
+    }
110
+
111
+
112
+    /**
113
+     * Check whether the stream's cursor is sitting right before the boundary.
114
+     */
115
+    private function isAtBoundary(): bool {
116
+        return $this->isAt($this->boundary);
117
+    }
118
+
119
+    /**
120
+     * Check whether the stream's cursor is sitting right before the last boundary.
121
+     */
122
+    public function isAtLastBoundary(): bool {
123
+        return $this->isAt($this->lastBoundary);
124
+    }
125
+
126
+    /**
127
+     * Parse and return the next part of the multipart headers.
128
+     *
129
+     * Example:
130
+     * --boundary_azertyuiop
131
+     * Header1: value
132
+     * Header2: value
133
+     *
134
+     * Content of
135
+     * the part
136
+     *
137
+     */
138
+    public function parseNextPart(): array {
139
+        $this->readBoundary();
140
+
141
+        $headers = $this->readPartHeaders();
142
+
143
+        $length = (int)$headers['content-length'];
144
+
145
+        $this->validateHash($length, $headers['x-file-md5'] ?? '', $headers['oc-checksum'] ?? '');
146
+        $content = $this->readPartContent($length);
147
+
148
+        return [$headers, $content];
149
+    }
150
+
151
+    /**
152
+     * Read the boundary and check its content.
153
+     *
154
+     * @throws BadRequest
155
+     */
156
+    private function readBoundary(): string {
157
+        if (!$this->isAtBoundary()) {
158
+            throw new BadRequest('Boundary not found where it should be.');
159
+        }
160
+
161
+        return fread($this->stream, strlen($this->boundary));
162
+    }
163
+
164
+    /**
165
+     * Return the headers of a part of the multipart body.
166
+     *
167
+     * @throws Exception
168
+     * @throws BadRequest
169
+     * @throws LengthRequired
170
+     */
171
+    private function readPartHeaders(): array {
172
+        $headers = [];
173
+
174
+        while (($line = fgets($this->stream)) !== "\r\n") {
175
+            if ($line === false) {
176
+                throw new Exception('An error occurred while reading headers of a part');
177
+            }
178
+
179
+            if (!str_contains($line, ':')) {
180
+                $this->logger->error('Header missing ":" on bulk request: ' . json_encode($line));
181
+                throw new Exception('An error occurred while reading headers of a part', Http::STATUS_BAD_REQUEST);
182
+            }
183
+
184
+            try {
185
+                [$key, $value] = explode(':', $line, 2);
186
+                $headers[strtolower(trim($key))] = trim($value);
187
+            } catch (\Exception $e) {
188
+                throw new BadRequest('An error occurred while parsing headers of a part', Http::STATUS_BAD_REQUEST, $e);
189
+            }
190
+        }
191
+
192
+        if (!isset($headers['content-length'])) {
193
+            throw new LengthRequired('The Content-Length header must not be null.');
194
+        }
195
+
196
+        // TODO: Drop $md5 condition when the latest desktop client that uses it is no longer supported.
197
+        if (!isset($headers['x-file-md5']) && !isset($headers['oc-checksum'])) {
198
+            throw new BadRequest('The hash headers must not be null.');
199
+        }
200
+
201
+        return $headers;
202
+    }
203
+
204
+    /**
205
+     * Return the content of a part of the multipart body.
206
+     *
207
+     * @throws Exception
208
+     * @throws BadRequest
209
+     */
210
+    private function readPartContent(int $length): string {
211
+        if ($length === 0) {
212
+            $content = '';
213
+        } else {
214
+            $content = stream_get_line($this->stream, $length);
215
+        }
216
+
217
+        if ($content === false) {
218
+            throw new Exception("Fail to read part's content.");
219
+        }
220
+
221
+        if ($length !== 0 && feof($this->stream)) {
222
+            throw new Exception('Unexpected EOF while reading stream.');
223
+        }
224
+
225
+        // Read '\r\n'.
226
+        stream_get_contents($this->stream, 2);
227
+
228
+        return $content;
229
+    }
230
+
231
+    /**
232
+     * Compute the MD5 or checksum hash of the next x bytes.
233
+     * TODO: Drop $md5 argument when the latest desktop client that uses it is no longer supported.
234
+     */
235
+    private function validateHash(int $length, string $fileMd5Header, string $checksumHeader): void {
236
+        if ($checksumHeader !== '') {
237
+            [$algorithm, $hash] = explode(':', $checksumHeader, 2);
238
+        } elseif ($fileMd5Header !== '') {
239
+            $algorithm = 'md5';
240
+            $hash = $fileMd5Header;
241
+        } else {
242
+            throw new BadRequest('No hash provided.');
243
+        }
244
+
245
+        $context = hash_init($algorithm);
246
+        hash_update_stream($context, $this->stream, $length);
247
+        fseek($this->stream, -$length, SEEK_CUR);
248
+        $computedHash = hash_final($context);
249
+        if ($hash !== $computedHash) {
250
+            throw new BadRequest("Computed $algorithm hash is incorrect ($computedHash).");
251
+        }
252
+    }
253 253
 }
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/AuthTest.php 1 patch
Indentation   +575 added lines, -575 removed lines patch added patch discarded remove patch
@@ -30,579 +30,579 @@
 block discarded – undo
30 30
  * @group DB
31 31
  */
32 32
 class AuthTest extends TestCase {
33
-	private ISession&MockObject $session;
34
-	private Session&MockObject $userSession;
35
-	private IRequest&MockObject $request;
36
-	private Manager&MockObject $twoFactorManager;
37
-	private IThrottler&MockObject $throttler;
38
-	private Auth $auth;
39
-
40
-	protected function setUp(): void {
41
-		parent::setUp();
42
-		$this->session = $this->createMock(ISession::class);
43
-		$this->userSession = $this->createMock(Session::class);
44
-		$this->request = $this->createMock(IRequest::class);
45
-		$this->twoFactorManager = $this->createMock(Manager::class);
46
-		$this->throttler = $this->createMock(IThrottler::class);
47
-		$this->auth = new Auth(
48
-			$this->session,
49
-			$this->userSession,
50
-			$this->request,
51
-			$this->twoFactorManager,
52
-			$this->throttler
53
-		);
54
-	}
55
-
56
-	public function testIsDavAuthenticatedWithoutDavSession(): void {
57
-		$this->session
58
-			->expects($this->once())
59
-			->method('get')
60
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
61
-			->willReturn(null);
62
-
63
-		$this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
64
-	}
65
-
66
-	public function testIsDavAuthenticatedWithWrongDavSession(): void {
67
-		$this->session
68
-			->expects($this->exactly(2))
69
-			->method('get')
70
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
71
-			->willReturn('AnotherUser');
72
-
73
-		$this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
74
-	}
75
-
76
-	public function testIsDavAuthenticatedWithCorrectDavSession(): void {
77
-		$this->session
78
-			->expects($this->exactly(2))
79
-			->method('get')
80
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
81
-			->willReturn('MyTestUser');
82
-
83
-		$this->assertTrue(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
84
-	}
85
-
86
-	public function testValidateUserPassOfAlreadyDAVAuthenticatedUser(): void {
87
-		$user = $this->createMock(IUser::class);
88
-		$user->expects($this->exactly(1))
89
-			->method('getUID')
90
-			->willReturn('MyTestUser');
91
-		$this->userSession
92
-			->expects($this->once())
93
-			->method('isLoggedIn')
94
-			->willReturn(true);
95
-		$this->userSession
96
-			->expects($this->exactly(1))
97
-			->method('getUser')
98
-			->willReturn($user);
99
-		$this->session
100
-			->expects($this->exactly(2))
101
-			->method('get')
102
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
103
-			->willReturn('MyTestUser');
104
-		$this->session
105
-			->expects($this->once())
106
-			->method('close');
107
-
108
-		$this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
109
-	}
110
-
111
-	public function testValidateUserPassOfInvalidDAVAuthenticatedUser(): void {
112
-		$user = $this->createMock(IUser::class);
113
-		$user->expects($this->once())
114
-			->method('getUID')
115
-			->willReturn('MyTestUser');
116
-		$this->userSession
117
-			->expects($this->once())
118
-			->method('isLoggedIn')
119
-			->willReturn(true);
120
-		$this->userSession
121
-			->expects($this->once())
122
-			->method('getUser')
123
-			->willReturn($user);
124
-		$this->session
125
-			->expects($this->exactly(2))
126
-			->method('get')
127
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
128
-			->willReturn('AnotherUser');
129
-		$this->session
130
-			->expects($this->once())
131
-			->method('close');
132
-
133
-		$this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
134
-	}
135
-
136
-	public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword(): void {
137
-		$user = $this->createMock(IUser::class);
138
-		$user->expects($this->exactly(2))
139
-			->method('getUID')
140
-			->willReturn('MyTestUser');
141
-		$this->userSession
142
-			->expects($this->once())
143
-			->method('isLoggedIn')
144
-			->willReturn(true);
145
-		$this->userSession
146
-			->expects($this->exactly(2))
147
-			->method('getUser')
148
-			->willReturn($user);
149
-		$this->session
150
-			->expects($this->exactly(2))
151
-			->method('get')
152
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
153
-			->willReturn('AnotherUser');
154
-		$this->userSession
155
-			->expects($this->once())
156
-			->method('logClientIn')
157
-			->with('MyTestUser', 'MyTestPassword', $this->request)
158
-			->willReturn(true);
159
-		$this->session
160
-			->expects($this->once())
161
-			->method('set')
162
-			->with('AUTHENTICATED_TO_DAV_BACKEND', 'MyTestUser');
163
-		$this->session
164
-			->expects($this->once())
165
-			->method('close');
166
-
167
-		$this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
168
-	}
169
-
170
-	public function testValidateUserPassWithInvalidPassword(): void {
171
-		$this->userSession
172
-			->expects($this->once())
173
-			->method('isLoggedIn')
174
-			->willReturn(false);
175
-		$this->userSession
176
-			->expects($this->once())
177
-			->method('logClientIn')
178
-			->with('MyTestUser', 'MyTestPassword')
179
-			->willReturn(false);
180
-		$this->session
181
-			->expects($this->once())
182
-			->method('close');
183
-
184
-		$this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
185
-	}
186
-
187
-
188
-	public function testValidateUserPassWithPasswordLoginForbidden(): void {
189
-		$this->expectException(PasswordLoginForbidden::class);
190
-
191
-		$this->userSession
192
-			->expects($this->once())
193
-			->method('isLoggedIn')
194
-			->willReturn(false);
195
-		$this->userSession
196
-			->expects($this->once())
197
-			->method('logClientIn')
198
-			->with('MyTestUser', 'MyTestPassword')
199
-			->will($this->throwException(new PasswordLoginForbiddenException()));
200
-		$this->session
201
-			->expects($this->once())
202
-			->method('close');
203
-
204
-		self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']);
205
-	}
206
-
207
-	public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGet(): void {
208
-		$request = $this->createMock(RequestInterface::class);
209
-		$response = $this->createMock(ResponseInterface::class);
210
-		$this->userSession
211
-			->expects($this->any())
212
-			->method('isLoggedIn')
213
-			->willReturn(true);
214
-		$this->request
215
-			->expects($this->any())
216
-			->method('getMethod')
217
-			->willReturn('POST');
218
-		$this->session
219
-			->expects($this->any())
220
-			->method('get')
221
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
222
-			->willReturn(null);
223
-		$user = $this->createMock(IUser::class);
224
-		$user->expects($this->any())
225
-			->method('getUID')
226
-			->willReturn('MyWrongDavUser');
227
-		$this->userSession
228
-			->expects($this->any())
229
-			->method('getUser')
230
-			->willReturn($user);
231
-		$this->request
232
-			->expects($this->once())
233
-			->method('passesCSRFCheck')
234
-			->willReturn(false);
235
-
236
-		$expectedResponse = [
237
-			false,
238
-			"No 'Authorization: Basic' header found. Either the client didn't send one, or the server is misconfigured",
239
-		];
240
-		$response = $this->auth->check($request, $response);
241
-		$this->assertSame($expectedResponse, $response);
242
-	}
243
-
244
-	public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenAndCorrectlyDavAuthenticated(): void {
245
-		$request = $this->createMock(RequestInterface::class);
246
-		$response = $this->createMock(ResponseInterface::class);
247
-		$this->userSession
248
-			->expects($this->any())
249
-			->method('isLoggedIn')
250
-			->willReturn(true);
251
-		$this->request
252
-			->expects($this->any())
253
-			->method('getMethod')
254
-			->willReturn('PROPFIND');
255
-		$this->request
256
-			->expects($this->any())
257
-			->method('isUserAgent')
258
-			->willReturn(false);
259
-		$this->session
260
-			->expects($this->any())
261
-			->method('get')
262
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
263
-			->willReturn('LoggedInUser');
264
-		$user = $this->createMock(IUser::class);
265
-		$user->expects($this->any())
266
-			->method('getUID')
267
-			->willReturn('LoggedInUser');
268
-		$this->userSession
269
-			->expects($this->any())
270
-			->method('getUser')
271
-			->willReturn($user);
272
-		$this->request
273
-			->expects($this->once())
274
-			->method('passesCSRFCheck')
275
-			->willReturn(false);
276
-		$this->auth->check($request, $response);
277
-	}
278
-
279
-
280
-	public function testAuthenticateAlreadyLoggedInWithoutTwoFactorChallengePassed(): void {
281
-		$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
282
-		$this->expectExceptionMessage('2FA challenge not passed.');
283
-
284
-		$request = $this->createMock(RequestInterface::class);
285
-		$response = $this->createMock(ResponseInterface::class);
286
-		$this->userSession
287
-			->expects($this->any())
288
-			->method('isLoggedIn')
289
-			->willReturn(true);
290
-		$this->request
291
-			->expects($this->any())
292
-			->method('getMethod')
293
-			->willReturn('PROPFIND');
294
-		$this->request
295
-			->expects($this->any())
296
-			->method('isUserAgent')
297
-			->willReturn(false);
298
-		$this->session
299
-			->expects($this->any())
300
-			->method('get')
301
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
302
-			->willReturn('LoggedInUser');
303
-		$user = $this->createMock(IUser::class);
304
-		$user->expects($this->any())
305
-			->method('getUID')
306
-			->willReturn('LoggedInUser');
307
-		$this->userSession
308
-			->expects($this->any())
309
-			->method('getUser')
310
-			->willReturn($user);
311
-		$this->request
312
-			->expects($this->once())
313
-			->method('passesCSRFCheck')
314
-			->willReturn(true);
315
-		$this->twoFactorManager->expects($this->once())
316
-			->method('needsSecondFactor')
317
-			->with($user)
318
-			->willReturn(true);
319
-		$this->auth->check($request, $response);
320
-	}
321
-
322
-
323
-	public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenAndIncorrectlyDavAuthenticated(): void {
324
-		$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
325
-		$this->expectExceptionMessage('CSRF check not passed.');
326
-
327
-		$request = $this->createMock(RequestInterface::class);
328
-		$response = $this->createMock(ResponseInterface::class);
329
-		$this->userSession
330
-			->expects($this->any())
331
-			->method('isLoggedIn')
332
-			->willReturn(true);
333
-		$this->request
334
-			->expects($this->any())
335
-			->method('getMethod')
336
-			->willReturn('PROPFIND');
337
-		$this->request
338
-			->expects($this->any())
339
-			->method('isUserAgent')
340
-			->willReturn(false);
341
-		$this->session
342
-			->expects($this->any())
343
-			->method('get')
344
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
345
-			->willReturn('AnotherUser');
346
-		$user = $this->createMock(IUser::class);
347
-		$user->expects($this->any())
348
-			->method('getUID')
349
-			->willReturn('LoggedInUser');
350
-		$this->userSession
351
-			->expects($this->any())
352
-			->method('getUser')
353
-			->willReturn($user);
354
-		$this->request
355
-			->expects($this->once())
356
-			->method('passesCSRFCheck')
357
-			->willReturn(false);
358
-		$this->auth->check($request, $response);
359
-	}
360
-
361
-	public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGetAndDesktopClient(): void {
362
-		$request = $this->createMock(RequestInterface::class);
363
-		$response = $this->createMock(ResponseInterface::class);
364
-		$this->userSession
365
-			->expects($this->any())
366
-			->method('isLoggedIn')
367
-			->willReturn(true);
368
-		$this->request
369
-			->expects($this->any())
370
-			->method('getMethod')
371
-			->willReturn('POST');
372
-		$this->request
373
-			->expects($this->any())
374
-			->method('isUserAgent')
375
-			->willReturn(true);
376
-		$this->session
377
-			->expects($this->any())
378
-			->method('get')
379
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
380
-			->willReturn(null);
381
-		$user = $this->createMock(IUser::class);
382
-		$user->expects($this->any())
383
-			->method('getUID')
384
-			->willReturn('MyWrongDavUser');
385
-		$this->userSession
386
-			->expects($this->any())
387
-			->method('getUser')
388
-			->willReturn($user);
389
-		$this->request
390
-			->expects($this->once())
391
-			->method('passesCSRFCheck')
392
-			->willReturn(false);
393
-
394
-		$this->auth->check($request, $response);
395
-	}
396
-
397
-	public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForGet(): void {
398
-		$request = $this->createMock(RequestInterface::class);
399
-		$response = $this->createMock(ResponseInterface::class);
400
-		$this->userSession
401
-			->expects($this->any())
402
-			->method('isLoggedIn')
403
-			->willReturn(true);
404
-		$this->session
405
-			->expects($this->any())
406
-			->method('get')
407
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
408
-			->willReturn(null);
409
-		$user = $this->createMock(IUser::class);
410
-		$user->expects($this->any())
411
-			->method('getUID')
412
-			->willReturn('MyWrongDavUser');
413
-		$this->userSession
414
-			->expects($this->any())
415
-			->method('getUser')
416
-			->willReturn($user);
417
-		$this->request
418
-			->expects($this->any())
419
-			->method('getMethod')
420
-			->willReturn('GET');
421
-
422
-		$response = $this->auth->check($request, $response);
423
-		$this->assertEquals([true, 'principals/users/MyWrongDavUser'], $response);
424
-	}
425
-
426
-	public function testAuthenticateAlreadyLoggedInWithCsrfTokenForGet(): void {
427
-		$request = $this->createMock(RequestInterface::class);
428
-		$response = $this->createMock(ResponseInterface::class);
429
-		$this->userSession
430
-			->expects($this->any())
431
-			->method('isLoggedIn')
432
-			->willReturn(true);
433
-		$this->session
434
-			->expects($this->any())
435
-			->method('get')
436
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
437
-			->willReturn(null);
438
-		$user = $this->createMock(IUser::class);
439
-		$user->expects($this->any())
440
-			->method('getUID')
441
-			->willReturn('MyWrongDavUser');
442
-		$this->userSession
443
-			->expects($this->any())
444
-			->method('getUser')
445
-			->willReturn($user);
446
-		$this->request
447
-			->expects($this->once())
448
-			->method('passesCSRFCheck')
449
-			->willReturn(true);
450
-
451
-		$response = $this->auth->check($request, $response);
452
-		$this->assertEquals([true, 'principals/users/MyWrongDavUser'], $response);
453
-	}
454
-
455
-	public function testAuthenticateNoBasicAuthenticateHeadersProvided(): void {
456
-		$server = $this->createMock(Server::class);
457
-		$server->httpRequest = $this->createMock(RequestInterface::class);
458
-		$server->httpResponse = $this->createMock(ResponseInterface::class);
459
-		$response = $this->auth->check($server->httpRequest, $server->httpResponse);
460
-		$this->assertEquals([false, 'No \'Authorization: Basic\' header found. Either the client didn\'t send one, or the server is misconfigured'], $response);
461
-	}
462
-
463
-
464
-	public function testAuthenticateNoBasicAuthenticateHeadersProvidedWithAjax(): void {
465
-		$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
466
-		$this->expectExceptionMessage('Cannot authenticate over ajax calls');
467
-
468
-		/** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
469
-		$httpRequest = $this->createMock(RequestInterface::class);
470
-		/** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
471
-		$httpResponse = $this->createMock(ResponseInterface::class);
472
-		$this->userSession
473
-			->expects($this->any())
474
-			->method('isLoggedIn')
475
-			->willReturn(false);
476
-		$httpRequest
477
-			->expects($this->exactly(2))
478
-			->method('getHeader')
479
-			->willReturnMap([
480
-				['X-Requested-With', 'XMLHttpRequest'],
481
-				['Authorization', null],
482
-			]);
483
-
484
-		$this->auth->check($httpRequest, $httpResponse);
485
-	}
486
-
487
-	public function testAuthenticateWithBasicAuthenticateHeadersProvidedWithAjax(): void {
488
-		// No CSRF
489
-		$this->request
490
-			->expects($this->once())
491
-			->method('passesCSRFCheck')
492
-			->willReturn(false);
493
-
494
-		/** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
495
-		$httpRequest = $this->createMock(RequestInterface::class);
496
-		/** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
497
-		$httpResponse = $this->createMock(ResponseInterface::class);
498
-		$httpRequest
499
-			->expects($this->any())
500
-			->method('getHeader')
501
-			->willReturnMap([
502
-				['X-Requested-With', 'XMLHttpRequest'],
503
-				['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
504
-			]);
505
-
506
-		$user = $this->createMock(IUser::class);
507
-		$user->expects($this->any())
508
-			->method('getUID')
509
-			->willReturn('MyDavUser');
510
-		$this->userSession
511
-			->expects($this->any())
512
-			->method('isLoggedIn')
513
-			->willReturn(false);
514
-		$this->userSession
515
-			->expects($this->once())
516
-			->method('logClientIn')
517
-			->with('username', 'password')
518
-			->willReturn(true);
519
-		$this->userSession
520
-			->expects($this->any())
521
-			->method('getUser')
522
-			->willReturn($user);
523
-
524
-		$this->auth->check($httpRequest, $httpResponse);
525
-	}
526
-
527
-	public function testAuthenticateNoBasicAuthenticateHeadersProvidedWithAjaxButUserIsStillLoggedIn(): void {
528
-		/** @var \Sabre\HTTP\RequestInterface $httpRequest */
529
-		$httpRequest = $this->createMock(RequestInterface::class);
530
-		/** @var \Sabre\HTTP\ResponseInterface $httpResponse */
531
-		$httpResponse = $this->createMock(ResponseInterface::class);
532
-		$user = $this->createMock(IUser::class);
533
-		$user->method('getUID')->willReturn('MyTestUser');
534
-		$this->userSession
535
-			->expects($this->any())
536
-			->method('isLoggedIn')
537
-			->willReturn(true);
538
-		$this->userSession
539
-			->expects($this->any())
540
-			->method('getUser')
541
-			->willReturn($user);
542
-		$this->session
543
-			->expects($this->atLeastOnce())
544
-			->method('get')
545
-			->with('AUTHENTICATED_TO_DAV_BACKEND')
546
-			->willReturn('MyTestUser');
547
-		$this->request
548
-			->expects($this->once())
549
-			->method('getMethod')
550
-			->willReturn('GET');
551
-		$httpRequest
552
-			->expects($this->atLeastOnce())
553
-			->method('getHeader')
554
-			->with('Authorization')
555
-			->willReturn(null);
556
-		$this->assertEquals(
557
-			[true, 'principals/users/MyTestUser'],
558
-			$this->auth->check($httpRequest, $httpResponse)
559
-		);
560
-	}
561
-
562
-	public function testAuthenticateValidCredentials(): void {
563
-		$server = $this->createMock(Server::class);
564
-		$server->httpRequest = $this->createMock(RequestInterface::class);
565
-		$server->httpRequest
566
-			->expects($this->once())
567
-			->method('getHeader')
568
-			->with('Authorization')
569
-			->willReturn('basic dXNlcm5hbWU6cGFzc3dvcmQ=');
570
-
571
-		$server->httpResponse = $this->createMock(ResponseInterface::class);
572
-		$this->userSession
573
-			->expects($this->once())
574
-			->method('logClientIn')
575
-			->with('username', 'password')
576
-			->willReturn(true);
577
-		$user = $this->createMock(IUser::class);
578
-		$user->expects($this->exactly(2))
579
-			->method('getUID')
580
-			->willReturn('MyTestUser');
581
-		$this->userSession
582
-			->expects($this->exactly(3))
583
-			->method('getUser')
584
-			->willReturn($user);
585
-		$response = $this->auth->check($server->httpRequest, $server->httpResponse);
586
-		$this->assertEquals([true, 'principals/users/MyTestUser'], $response);
587
-	}
588
-
589
-	public function testAuthenticateInvalidCredentials(): void {
590
-		$server = $this->createMock(Server::class);
591
-		$server->httpRequest = $this->createMock(RequestInterface::class);
592
-		$server->httpRequest
593
-			->expects($this->exactly(2))
594
-			->method('getHeader')
595
-			->willReturnMap([
596
-				['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
597
-				['X-Requested-With', null],
598
-			]);
599
-		$server->httpResponse = $this->createMock(ResponseInterface::class);
600
-		$this->userSession
601
-			->expects($this->once())
602
-			->method('logClientIn')
603
-			->with('username', 'password')
604
-			->willReturn(false);
605
-		$response = $this->auth->check($server->httpRequest, $server->httpResponse);
606
-		$this->assertEquals([false, 'Username or password was incorrect'], $response);
607
-	}
33
+    private ISession&MockObject $session;
34
+    private Session&MockObject $userSession;
35
+    private IRequest&MockObject $request;
36
+    private Manager&MockObject $twoFactorManager;
37
+    private IThrottler&MockObject $throttler;
38
+    private Auth $auth;
39
+
40
+    protected function setUp(): void {
41
+        parent::setUp();
42
+        $this->session = $this->createMock(ISession::class);
43
+        $this->userSession = $this->createMock(Session::class);
44
+        $this->request = $this->createMock(IRequest::class);
45
+        $this->twoFactorManager = $this->createMock(Manager::class);
46
+        $this->throttler = $this->createMock(IThrottler::class);
47
+        $this->auth = new Auth(
48
+            $this->session,
49
+            $this->userSession,
50
+            $this->request,
51
+            $this->twoFactorManager,
52
+            $this->throttler
53
+        );
54
+    }
55
+
56
+    public function testIsDavAuthenticatedWithoutDavSession(): void {
57
+        $this->session
58
+            ->expects($this->once())
59
+            ->method('get')
60
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
61
+            ->willReturn(null);
62
+
63
+        $this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
64
+    }
65
+
66
+    public function testIsDavAuthenticatedWithWrongDavSession(): void {
67
+        $this->session
68
+            ->expects($this->exactly(2))
69
+            ->method('get')
70
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
71
+            ->willReturn('AnotherUser');
72
+
73
+        $this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
74
+    }
75
+
76
+    public function testIsDavAuthenticatedWithCorrectDavSession(): void {
77
+        $this->session
78
+            ->expects($this->exactly(2))
79
+            ->method('get')
80
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
81
+            ->willReturn('MyTestUser');
82
+
83
+        $this->assertTrue(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
84
+    }
85
+
86
+    public function testValidateUserPassOfAlreadyDAVAuthenticatedUser(): void {
87
+        $user = $this->createMock(IUser::class);
88
+        $user->expects($this->exactly(1))
89
+            ->method('getUID')
90
+            ->willReturn('MyTestUser');
91
+        $this->userSession
92
+            ->expects($this->once())
93
+            ->method('isLoggedIn')
94
+            ->willReturn(true);
95
+        $this->userSession
96
+            ->expects($this->exactly(1))
97
+            ->method('getUser')
98
+            ->willReturn($user);
99
+        $this->session
100
+            ->expects($this->exactly(2))
101
+            ->method('get')
102
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
103
+            ->willReturn('MyTestUser');
104
+        $this->session
105
+            ->expects($this->once())
106
+            ->method('close');
107
+
108
+        $this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
109
+    }
110
+
111
+    public function testValidateUserPassOfInvalidDAVAuthenticatedUser(): void {
112
+        $user = $this->createMock(IUser::class);
113
+        $user->expects($this->once())
114
+            ->method('getUID')
115
+            ->willReturn('MyTestUser');
116
+        $this->userSession
117
+            ->expects($this->once())
118
+            ->method('isLoggedIn')
119
+            ->willReturn(true);
120
+        $this->userSession
121
+            ->expects($this->once())
122
+            ->method('getUser')
123
+            ->willReturn($user);
124
+        $this->session
125
+            ->expects($this->exactly(2))
126
+            ->method('get')
127
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
128
+            ->willReturn('AnotherUser');
129
+        $this->session
130
+            ->expects($this->once())
131
+            ->method('close');
132
+
133
+        $this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
134
+    }
135
+
136
+    public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword(): void {
137
+        $user = $this->createMock(IUser::class);
138
+        $user->expects($this->exactly(2))
139
+            ->method('getUID')
140
+            ->willReturn('MyTestUser');
141
+        $this->userSession
142
+            ->expects($this->once())
143
+            ->method('isLoggedIn')
144
+            ->willReturn(true);
145
+        $this->userSession
146
+            ->expects($this->exactly(2))
147
+            ->method('getUser')
148
+            ->willReturn($user);
149
+        $this->session
150
+            ->expects($this->exactly(2))
151
+            ->method('get')
152
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
153
+            ->willReturn('AnotherUser');
154
+        $this->userSession
155
+            ->expects($this->once())
156
+            ->method('logClientIn')
157
+            ->with('MyTestUser', 'MyTestPassword', $this->request)
158
+            ->willReturn(true);
159
+        $this->session
160
+            ->expects($this->once())
161
+            ->method('set')
162
+            ->with('AUTHENTICATED_TO_DAV_BACKEND', 'MyTestUser');
163
+        $this->session
164
+            ->expects($this->once())
165
+            ->method('close');
166
+
167
+        $this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
168
+    }
169
+
170
+    public function testValidateUserPassWithInvalidPassword(): void {
171
+        $this->userSession
172
+            ->expects($this->once())
173
+            ->method('isLoggedIn')
174
+            ->willReturn(false);
175
+        $this->userSession
176
+            ->expects($this->once())
177
+            ->method('logClientIn')
178
+            ->with('MyTestUser', 'MyTestPassword')
179
+            ->willReturn(false);
180
+        $this->session
181
+            ->expects($this->once())
182
+            ->method('close');
183
+
184
+        $this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
185
+    }
186
+
187
+
188
+    public function testValidateUserPassWithPasswordLoginForbidden(): void {
189
+        $this->expectException(PasswordLoginForbidden::class);
190
+
191
+        $this->userSession
192
+            ->expects($this->once())
193
+            ->method('isLoggedIn')
194
+            ->willReturn(false);
195
+        $this->userSession
196
+            ->expects($this->once())
197
+            ->method('logClientIn')
198
+            ->with('MyTestUser', 'MyTestPassword')
199
+            ->will($this->throwException(new PasswordLoginForbiddenException()));
200
+        $this->session
201
+            ->expects($this->once())
202
+            ->method('close');
203
+
204
+        self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']);
205
+    }
206
+
207
+    public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGet(): void {
208
+        $request = $this->createMock(RequestInterface::class);
209
+        $response = $this->createMock(ResponseInterface::class);
210
+        $this->userSession
211
+            ->expects($this->any())
212
+            ->method('isLoggedIn')
213
+            ->willReturn(true);
214
+        $this->request
215
+            ->expects($this->any())
216
+            ->method('getMethod')
217
+            ->willReturn('POST');
218
+        $this->session
219
+            ->expects($this->any())
220
+            ->method('get')
221
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
222
+            ->willReturn(null);
223
+        $user = $this->createMock(IUser::class);
224
+        $user->expects($this->any())
225
+            ->method('getUID')
226
+            ->willReturn('MyWrongDavUser');
227
+        $this->userSession
228
+            ->expects($this->any())
229
+            ->method('getUser')
230
+            ->willReturn($user);
231
+        $this->request
232
+            ->expects($this->once())
233
+            ->method('passesCSRFCheck')
234
+            ->willReturn(false);
235
+
236
+        $expectedResponse = [
237
+            false,
238
+            "No 'Authorization: Basic' header found. Either the client didn't send one, or the server is misconfigured",
239
+        ];
240
+        $response = $this->auth->check($request, $response);
241
+        $this->assertSame($expectedResponse, $response);
242
+    }
243
+
244
+    public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenAndCorrectlyDavAuthenticated(): void {
245
+        $request = $this->createMock(RequestInterface::class);
246
+        $response = $this->createMock(ResponseInterface::class);
247
+        $this->userSession
248
+            ->expects($this->any())
249
+            ->method('isLoggedIn')
250
+            ->willReturn(true);
251
+        $this->request
252
+            ->expects($this->any())
253
+            ->method('getMethod')
254
+            ->willReturn('PROPFIND');
255
+        $this->request
256
+            ->expects($this->any())
257
+            ->method('isUserAgent')
258
+            ->willReturn(false);
259
+        $this->session
260
+            ->expects($this->any())
261
+            ->method('get')
262
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
263
+            ->willReturn('LoggedInUser');
264
+        $user = $this->createMock(IUser::class);
265
+        $user->expects($this->any())
266
+            ->method('getUID')
267
+            ->willReturn('LoggedInUser');
268
+        $this->userSession
269
+            ->expects($this->any())
270
+            ->method('getUser')
271
+            ->willReturn($user);
272
+        $this->request
273
+            ->expects($this->once())
274
+            ->method('passesCSRFCheck')
275
+            ->willReturn(false);
276
+        $this->auth->check($request, $response);
277
+    }
278
+
279
+
280
+    public function testAuthenticateAlreadyLoggedInWithoutTwoFactorChallengePassed(): void {
281
+        $this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
282
+        $this->expectExceptionMessage('2FA challenge not passed.');
283
+
284
+        $request = $this->createMock(RequestInterface::class);
285
+        $response = $this->createMock(ResponseInterface::class);
286
+        $this->userSession
287
+            ->expects($this->any())
288
+            ->method('isLoggedIn')
289
+            ->willReturn(true);
290
+        $this->request
291
+            ->expects($this->any())
292
+            ->method('getMethod')
293
+            ->willReturn('PROPFIND');
294
+        $this->request
295
+            ->expects($this->any())
296
+            ->method('isUserAgent')
297
+            ->willReturn(false);
298
+        $this->session
299
+            ->expects($this->any())
300
+            ->method('get')
301
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
302
+            ->willReturn('LoggedInUser');
303
+        $user = $this->createMock(IUser::class);
304
+        $user->expects($this->any())
305
+            ->method('getUID')
306
+            ->willReturn('LoggedInUser');
307
+        $this->userSession
308
+            ->expects($this->any())
309
+            ->method('getUser')
310
+            ->willReturn($user);
311
+        $this->request
312
+            ->expects($this->once())
313
+            ->method('passesCSRFCheck')
314
+            ->willReturn(true);
315
+        $this->twoFactorManager->expects($this->once())
316
+            ->method('needsSecondFactor')
317
+            ->with($user)
318
+            ->willReturn(true);
319
+        $this->auth->check($request, $response);
320
+    }
321
+
322
+
323
+    public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenAndIncorrectlyDavAuthenticated(): void {
324
+        $this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
325
+        $this->expectExceptionMessage('CSRF check not passed.');
326
+
327
+        $request = $this->createMock(RequestInterface::class);
328
+        $response = $this->createMock(ResponseInterface::class);
329
+        $this->userSession
330
+            ->expects($this->any())
331
+            ->method('isLoggedIn')
332
+            ->willReturn(true);
333
+        $this->request
334
+            ->expects($this->any())
335
+            ->method('getMethod')
336
+            ->willReturn('PROPFIND');
337
+        $this->request
338
+            ->expects($this->any())
339
+            ->method('isUserAgent')
340
+            ->willReturn(false);
341
+        $this->session
342
+            ->expects($this->any())
343
+            ->method('get')
344
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
345
+            ->willReturn('AnotherUser');
346
+        $user = $this->createMock(IUser::class);
347
+        $user->expects($this->any())
348
+            ->method('getUID')
349
+            ->willReturn('LoggedInUser');
350
+        $this->userSession
351
+            ->expects($this->any())
352
+            ->method('getUser')
353
+            ->willReturn($user);
354
+        $this->request
355
+            ->expects($this->once())
356
+            ->method('passesCSRFCheck')
357
+            ->willReturn(false);
358
+        $this->auth->check($request, $response);
359
+    }
360
+
361
+    public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGetAndDesktopClient(): void {
362
+        $request = $this->createMock(RequestInterface::class);
363
+        $response = $this->createMock(ResponseInterface::class);
364
+        $this->userSession
365
+            ->expects($this->any())
366
+            ->method('isLoggedIn')
367
+            ->willReturn(true);
368
+        $this->request
369
+            ->expects($this->any())
370
+            ->method('getMethod')
371
+            ->willReturn('POST');
372
+        $this->request
373
+            ->expects($this->any())
374
+            ->method('isUserAgent')
375
+            ->willReturn(true);
376
+        $this->session
377
+            ->expects($this->any())
378
+            ->method('get')
379
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
380
+            ->willReturn(null);
381
+        $user = $this->createMock(IUser::class);
382
+        $user->expects($this->any())
383
+            ->method('getUID')
384
+            ->willReturn('MyWrongDavUser');
385
+        $this->userSession
386
+            ->expects($this->any())
387
+            ->method('getUser')
388
+            ->willReturn($user);
389
+        $this->request
390
+            ->expects($this->once())
391
+            ->method('passesCSRFCheck')
392
+            ->willReturn(false);
393
+
394
+        $this->auth->check($request, $response);
395
+    }
396
+
397
+    public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForGet(): void {
398
+        $request = $this->createMock(RequestInterface::class);
399
+        $response = $this->createMock(ResponseInterface::class);
400
+        $this->userSession
401
+            ->expects($this->any())
402
+            ->method('isLoggedIn')
403
+            ->willReturn(true);
404
+        $this->session
405
+            ->expects($this->any())
406
+            ->method('get')
407
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
408
+            ->willReturn(null);
409
+        $user = $this->createMock(IUser::class);
410
+        $user->expects($this->any())
411
+            ->method('getUID')
412
+            ->willReturn('MyWrongDavUser');
413
+        $this->userSession
414
+            ->expects($this->any())
415
+            ->method('getUser')
416
+            ->willReturn($user);
417
+        $this->request
418
+            ->expects($this->any())
419
+            ->method('getMethod')
420
+            ->willReturn('GET');
421
+
422
+        $response = $this->auth->check($request, $response);
423
+        $this->assertEquals([true, 'principals/users/MyWrongDavUser'], $response);
424
+    }
425
+
426
+    public function testAuthenticateAlreadyLoggedInWithCsrfTokenForGet(): void {
427
+        $request = $this->createMock(RequestInterface::class);
428
+        $response = $this->createMock(ResponseInterface::class);
429
+        $this->userSession
430
+            ->expects($this->any())
431
+            ->method('isLoggedIn')
432
+            ->willReturn(true);
433
+        $this->session
434
+            ->expects($this->any())
435
+            ->method('get')
436
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
437
+            ->willReturn(null);
438
+        $user = $this->createMock(IUser::class);
439
+        $user->expects($this->any())
440
+            ->method('getUID')
441
+            ->willReturn('MyWrongDavUser');
442
+        $this->userSession
443
+            ->expects($this->any())
444
+            ->method('getUser')
445
+            ->willReturn($user);
446
+        $this->request
447
+            ->expects($this->once())
448
+            ->method('passesCSRFCheck')
449
+            ->willReturn(true);
450
+
451
+        $response = $this->auth->check($request, $response);
452
+        $this->assertEquals([true, 'principals/users/MyWrongDavUser'], $response);
453
+    }
454
+
455
+    public function testAuthenticateNoBasicAuthenticateHeadersProvided(): void {
456
+        $server = $this->createMock(Server::class);
457
+        $server->httpRequest = $this->createMock(RequestInterface::class);
458
+        $server->httpResponse = $this->createMock(ResponseInterface::class);
459
+        $response = $this->auth->check($server->httpRequest, $server->httpResponse);
460
+        $this->assertEquals([false, 'No \'Authorization: Basic\' header found. Either the client didn\'t send one, or the server is misconfigured'], $response);
461
+    }
462
+
463
+
464
+    public function testAuthenticateNoBasicAuthenticateHeadersProvidedWithAjax(): void {
465
+        $this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
466
+        $this->expectExceptionMessage('Cannot authenticate over ajax calls');
467
+
468
+        /** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
469
+        $httpRequest = $this->createMock(RequestInterface::class);
470
+        /** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
471
+        $httpResponse = $this->createMock(ResponseInterface::class);
472
+        $this->userSession
473
+            ->expects($this->any())
474
+            ->method('isLoggedIn')
475
+            ->willReturn(false);
476
+        $httpRequest
477
+            ->expects($this->exactly(2))
478
+            ->method('getHeader')
479
+            ->willReturnMap([
480
+                ['X-Requested-With', 'XMLHttpRequest'],
481
+                ['Authorization', null],
482
+            ]);
483
+
484
+        $this->auth->check($httpRequest, $httpResponse);
485
+    }
486
+
487
+    public function testAuthenticateWithBasicAuthenticateHeadersProvidedWithAjax(): void {
488
+        // No CSRF
489
+        $this->request
490
+            ->expects($this->once())
491
+            ->method('passesCSRFCheck')
492
+            ->willReturn(false);
493
+
494
+        /** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
495
+        $httpRequest = $this->createMock(RequestInterface::class);
496
+        /** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
497
+        $httpResponse = $this->createMock(ResponseInterface::class);
498
+        $httpRequest
499
+            ->expects($this->any())
500
+            ->method('getHeader')
501
+            ->willReturnMap([
502
+                ['X-Requested-With', 'XMLHttpRequest'],
503
+                ['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
504
+            ]);
505
+
506
+        $user = $this->createMock(IUser::class);
507
+        $user->expects($this->any())
508
+            ->method('getUID')
509
+            ->willReturn('MyDavUser');
510
+        $this->userSession
511
+            ->expects($this->any())
512
+            ->method('isLoggedIn')
513
+            ->willReturn(false);
514
+        $this->userSession
515
+            ->expects($this->once())
516
+            ->method('logClientIn')
517
+            ->with('username', 'password')
518
+            ->willReturn(true);
519
+        $this->userSession
520
+            ->expects($this->any())
521
+            ->method('getUser')
522
+            ->willReturn($user);
523
+
524
+        $this->auth->check($httpRequest, $httpResponse);
525
+    }
526
+
527
+    public function testAuthenticateNoBasicAuthenticateHeadersProvidedWithAjaxButUserIsStillLoggedIn(): void {
528
+        /** @var \Sabre\HTTP\RequestInterface $httpRequest */
529
+        $httpRequest = $this->createMock(RequestInterface::class);
530
+        /** @var \Sabre\HTTP\ResponseInterface $httpResponse */
531
+        $httpResponse = $this->createMock(ResponseInterface::class);
532
+        $user = $this->createMock(IUser::class);
533
+        $user->method('getUID')->willReturn('MyTestUser');
534
+        $this->userSession
535
+            ->expects($this->any())
536
+            ->method('isLoggedIn')
537
+            ->willReturn(true);
538
+        $this->userSession
539
+            ->expects($this->any())
540
+            ->method('getUser')
541
+            ->willReturn($user);
542
+        $this->session
543
+            ->expects($this->atLeastOnce())
544
+            ->method('get')
545
+            ->with('AUTHENTICATED_TO_DAV_BACKEND')
546
+            ->willReturn('MyTestUser');
547
+        $this->request
548
+            ->expects($this->once())
549
+            ->method('getMethod')
550
+            ->willReturn('GET');
551
+        $httpRequest
552
+            ->expects($this->atLeastOnce())
553
+            ->method('getHeader')
554
+            ->with('Authorization')
555
+            ->willReturn(null);
556
+        $this->assertEquals(
557
+            [true, 'principals/users/MyTestUser'],
558
+            $this->auth->check($httpRequest, $httpResponse)
559
+        );
560
+    }
561
+
562
+    public function testAuthenticateValidCredentials(): void {
563
+        $server = $this->createMock(Server::class);
564
+        $server->httpRequest = $this->createMock(RequestInterface::class);
565
+        $server->httpRequest
566
+            ->expects($this->once())
567
+            ->method('getHeader')
568
+            ->with('Authorization')
569
+            ->willReturn('basic dXNlcm5hbWU6cGFzc3dvcmQ=');
570
+
571
+        $server->httpResponse = $this->createMock(ResponseInterface::class);
572
+        $this->userSession
573
+            ->expects($this->once())
574
+            ->method('logClientIn')
575
+            ->with('username', 'password')
576
+            ->willReturn(true);
577
+        $user = $this->createMock(IUser::class);
578
+        $user->expects($this->exactly(2))
579
+            ->method('getUID')
580
+            ->willReturn('MyTestUser');
581
+        $this->userSession
582
+            ->expects($this->exactly(3))
583
+            ->method('getUser')
584
+            ->willReturn($user);
585
+        $response = $this->auth->check($server->httpRequest, $server->httpResponse);
586
+        $this->assertEquals([true, 'principals/users/MyTestUser'], $response);
587
+    }
588
+
589
+    public function testAuthenticateInvalidCredentials(): void {
590
+        $server = $this->createMock(Server::class);
591
+        $server->httpRequest = $this->createMock(RequestInterface::class);
592
+        $server->httpRequest
593
+            ->expects($this->exactly(2))
594
+            ->method('getHeader')
595
+            ->willReturnMap([
596
+                ['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
597
+                ['X-Requested-With', null],
598
+            ]);
599
+        $server->httpResponse = $this->createMock(ResponseInterface::class);
600
+        $this->userSession
601
+            ->expects($this->once())
602
+            ->method('logClientIn')
603
+            ->with('username', 'password')
604
+            ->willReturn(false);
605
+        $response = $this->auth->check($server->httpRequest, $server->httpResponse);
606
+        $this->assertEquals([false, 'Username or password was incorrect'], $response);
607
+    }
608 608
 }
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -19,39 +19,39 @@
 block discarded – undo
19 19
  * @package OCA\DAV\Tests\unit\Connector\Sabre\RequestTest
20 20
  */
21 21
 class DownloadTest extends RequestTestCase {
22
-	public function testDownload(): void {
23
-		$user = self::getUniqueID();
24
-		$view = $this->setupUser($user, 'pass');
22
+    public function testDownload(): void {
23
+        $user = self::getUniqueID();
24
+        $view = $this->setupUser($user, 'pass');
25 25
 
26
-		$view->file_put_contents('foo.txt', 'bar');
26
+        $view->file_put_contents('foo.txt', 'bar');
27 27
 
28
-		$response = $this->request($view, $user, 'pass', 'GET', '/foo.txt');
29
-		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
30
-		$this->assertEquals(stream_get_contents($response->getBody()), 'bar');
31
-	}
28
+        $response = $this->request($view, $user, 'pass', 'GET', '/foo.txt');
29
+        $this->assertEquals(Http::STATUS_OK, $response->getStatus());
30
+        $this->assertEquals(stream_get_contents($response->getBody()), 'bar');
31
+    }
32 32
 
33
-	public function testDownloadWriteLocked(): void {
34
-		$user = self::getUniqueID();
35
-		$view = $this->setupUser($user, 'pass');
33
+    public function testDownloadWriteLocked(): void {
34
+        $user = self::getUniqueID();
35
+        $view = $this->setupUser($user, 'pass');
36 36
 
37
-		$view->file_put_contents('foo.txt', 'bar');
37
+        $view->file_put_contents('foo.txt', 'bar');
38 38
 
39
-		$view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE);
39
+        $view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE);
40 40
 
41
-		$result = $this->request($view, $user, 'pass', 'GET', '/foo.txt', 'asd');
42
-		$this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
43
-	}
41
+        $result = $this->request($view, $user, 'pass', 'GET', '/foo.txt', 'asd');
42
+        $this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
43
+    }
44 44
 
45
-	public function testDownloadReadLocked(): void {
46
-		$user = self::getUniqueID();
47
-		$view = $this->setupUser($user, 'pass');
45
+    public function testDownloadReadLocked(): void {
46
+        $user = self::getUniqueID();
47
+        $view = $this->setupUser($user, 'pass');
48 48
 
49
-		$view->file_put_contents('foo.txt', 'bar');
49
+        $view->file_put_contents('foo.txt', 'bar');
50 50
 
51
-		$view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED);
51
+        $view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED);
52 52
 
53
-		$response = $this->request($view, $user, 'pass', 'GET', '/foo.txt', 'asd');
54
-		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
55
-		$this->assertEquals(stream_get_contents($response->getBody()), 'bar');
56
-	}
53
+        $response = $this->request($view, $user, 'pass', 'GET', '/foo.txt', 'asd');
54
+        $this->assertEquals(Http::STATUS_OK, $response->getStatus());
55
+        $this->assertEquals(stream_get_contents($response->getBody()), 'bar');
56
+    }
57 57
 }
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php 1 patch
Indentation   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -18,25 +18,25 @@
 block discarded – undo
18 18
  * @package OCA\DAV\Tests\unit\Connector\Sabre\RequestTest
19 19
  */
20 20
 class DeleteTest extends RequestTestCase {
21
-	public function testBasicUpload(): void {
22
-		$user = self::getUniqueID();
23
-		$view = $this->setupUser($user, 'pass');
21
+    public function testBasicUpload(): void {
22
+        $user = self::getUniqueID();
23
+        $view = $this->setupUser($user, 'pass');
24 24
 
25
-		$view->file_put_contents('foo.txt', 'asd');
26
-		$mount = $view->getMount('foo.txt');
27
-		$internalPath = $view->getAbsolutePath();
25
+        $view->file_put_contents('foo.txt', 'asd');
26
+        $mount = $view->getMount('foo.txt');
27
+        $internalPath = $view->getAbsolutePath();
28 28
 
29
-		// create a ghost file
30
-		$mount->getStorage()->unlink($mount->getInternalPath($internalPath));
29
+        // create a ghost file
30
+        $mount->getStorage()->unlink($mount->getInternalPath($internalPath));
31 31
 
32
-		// cache entry still exists
33
-		$this->assertInstanceOf(\OCP\Files\FileInfo::class, $view->getFileInfo('foo.txt'));
32
+        // cache entry still exists
33
+        $this->assertInstanceOf(\OCP\Files\FileInfo::class, $view->getFileInfo('foo.txt'));
34 34
 
35
-		$response = $this->request($view, $user, 'pass', 'DELETE', '/foo.txt');
35
+        $response = $this->request($view, $user, 'pass', 'DELETE', '/foo.txt');
36 36
 
37
-		$this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus());
37
+        $this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus());
38 38
 
39
-		// no longer in the cache
40
-		$this->assertFalse($view->getFileInfo('foo.txt'));
41
-	}
39
+        // no longer in the cache
40
+        $this->assertFalse($view->getFileInfo('foo.txt'));
41
+    }
42 42
 }
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php 2 patches
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -22,16 +22,16 @@
 block discarded – undo
22 22
  * @package OCA\DAV\Tests\Unit\Connector\Sabre\RequestTest
23 23
  */
24 24
 class EncryptionUploadTest extends UploadTest {
25
-	use EncryptionTrait;
25
+    use EncryptionTrait;
26 26
 
27
-	protected function setupUser($name, $password): View {
28
-		$this->createUser($name, $password);
29
-		$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
30
-		$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
31
-		// we use per-user keys
32
-		Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '0');
33
-		$this->setupForUser($name, $password);
34
-		$this->loginWithEncryption($name);
35
-		return new View('/' . $name . '/files');
36
-	}
27
+    protected function setupUser($name, $password): View {
28
+        $this->createUser($name, $password);
29
+        $tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
30
+        $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
31
+        // we use per-user keys
32
+        Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '0');
33
+        $this->setupForUser($name, $password);
34
+        $this->loginWithEncryption($name);
35
+        return new View('/' . $name . '/files');
36
+    }
37 37
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -27,11 +27,11 @@
 block discarded – undo
27 27
 	protected function setupUser($name, $password): View {
28 28
 		$this->createUser($name, $password);
29 29
 		$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
30
-		$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
30
+		$this->registerMount($name, '\OC\Files\Storage\Local', '/'.$name, ['datadir' => $tmpFolder]);
31 31
 		// we use per-user keys
32 32
 		Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '0');
33 33
 		$this->setupForUser($name, $password);
34 34
 		$this->loginWithEncryption($name);
35
-		return new View('/' . $name . '/files');
35
+		return new View('/'.$name.'/files');
36 36
 	}
37 37
 }
Please login to merge, or discard this patch.
tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php 2 patches
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -22,16 +22,16 @@
 block discarded – undo
22 22
  * @package OCA\DAV\Tests\Unit\Connector\Sabre\RequestTest
23 23
  */
24 24
 class EncryptionMasterKeyUploadTest extends UploadTest {
25
-	use EncryptionTrait;
25
+    use EncryptionTrait;
26 26
 
27
-	protected function setupUser($name, $password): View {
28
-		$this->createUser($name, $password);
29
-		$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
30
-		$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
31
-		// we use the master key
32
-		Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '1');
33
-		$this->setupForUser($name, $password);
34
-		$this->loginWithEncryption($name);
35
-		return new View('/' . $name . '/files');
36
-	}
27
+    protected function setupUser($name, $password): View {
28
+        $this->createUser($name, $password);
29
+        $tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
30
+        $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
31
+        // we use the master key
32
+        Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '1');
33
+        $this->setupForUser($name, $password);
34
+        $this->loginWithEncryption($name);
35
+        return new View('/' . $name . '/files');
36
+    }
37 37
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -27,11 +27,11 @@
 block discarded – undo
27 27
 	protected function setupUser($name, $password): View {
28 28
 		$this->createUser($name, $password);
29 29
 		$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
30
-		$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
30
+		$this->registerMount($name, '\OC\Files\Storage\Local', '/'.$name, ['datadir' => $tmpFolder]);
31 31
 		// we use the master key
32 32
 		Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '1');
33 33
 		$this->setupForUser($name, $password);
34 34
 		$this->loginWithEncryption($name);
35
-		return new View('/' . $name . '/files');
35
+		return new View('/'.$name.'/files');
36 36
 	}
37 37
 }
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php 2 patches
Indentation   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -29,115 +29,115 @@
 block discarded – undo
29 29
 use Test\Traits\UserTrait;
30 30
 
31 31
 abstract class RequestTestCase extends TestCase {
32
-	use UserTrait;
33
-	use MountProviderTrait;
34
-	protected ServerFactory $serverFactory;
35
-
36
-	protected function getStream($string) {
37
-		$stream = fopen('php://temp', 'r+');
38
-		fwrite($stream, $string);
39
-		fseek($stream, 0);
40
-		return $stream;
41
-	}
42
-
43
-	protected function setUp(): void {
44
-		parent::setUp();
45
-
46
-		$this->serverFactory = new ServerFactory(
47
-			\OCP\Server::get(IConfig::class),
48
-			\OCP\Server::get(LoggerInterface::class),
49
-			\OCP\Server::get(IDBConnection::class),
50
-			\OCP\Server::get(IUserSession::class),
51
-			\OCP\Server::get(IMountManager::class),
52
-			\OCP\Server::get(ITagManager::class),
53
-			$this->createMock(IRequest::class),
54
-			\OCP\Server::get(IPreview::class),
55
-			\OCP\Server::get(IEventDispatcher::class),
56
-			\OCP\Server::get(IFactory::class)->get('dav'),
57
-		);
58
-	}
59
-
60
-	protected function setupUser($name, $password): View {
61
-		$this->createUser($name, $password);
62
-		$tmpFolder = \OCP\Server::get(ITempManager::class)->getTemporaryFolder();
63
-		$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
64
-		self::loginAsUser($name);
65
-		return new View('/' . $name . '/files');
66
-	}
67
-
68
-	/**
69
-	 * @param View $view the view to run the webdav server against
70
-	 * @param string $user
71
-	 * @param string $password
72
-	 * @param string $method
73
-	 * @param string $url
74
-	 * @param resource|string|null $body
75
-	 * @param array|null $headers
76
-	 * @return \Sabre\HTTP\Response
77
-	 * @throws \Exception
78
-	 */
79
-	protected function request($view, $user, $password, $method, $url, $body = null, $headers = []) {
80
-		if (is_string($body)) {
81
-			$body = $this->getStream($body);
82
-		}
83
-		$this->logout();
84
-		$exceptionPlugin = new ExceptionPlugin('webdav', \OCP\Server::get(LoggerInterface::class));
85
-		$server = $this->getSabreServer($view, $user, $password, $exceptionPlugin);
86
-		$request = new Request($method, $url, $headers, $body);
87
-
88
-		// since sabre catches all exceptions we need to save them and throw them from outside the sabre server
89
-
90
-		$serverParams = [];
91
-		if (is_array($headers)) {
92
-			foreach ($headers as $header => $value) {
93
-				$serverParams['HTTP_' . strtoupper(str_replace('-', '_', $header))] = $value;
94
-			}
95
-		}
96
-		$ncRequest = new \OC\AppFramework\Http\Request([
97
-			'server' => $serverParams
98
-		], $this->createMock(IRequestId::class), $this->createMock(IConfig::class), null);
99
-
100
-		$this->overwriteService(IRequest::class, $ncRequest);
101
-
102
-		$result = $this->makeRequest($server, $request);
103
-
104
-		$this->restoreService(IRequest::class);
105
-
106
-		foreach ($exceptionPlugin->getExceptions() as $exception) {
107
-			throw $exception;
108
-		}
109
-		return $result;
110
-	}
111
-
112
-	/**
113
-	 * @param Server $server
114
-	 * @param Request $request
115
-	 * @return \Sabre\HTTP\Response
116
-	 */
117
-	protected function makeRequest(Server $server, Request $request) {
118
-		$sapi = new Sapi($request);
119
-		$server->sapi = $sapi;
120
-		$server->httpRequest = $request;
121
-		$server->exec();
122
-		return $sapi->getResponse();
123
-	}
124
-
125
-	/**
126
-	 * @param View $view
127
-	 * @param string $user
128
-	 * @param string $password
129
-	 * @param ExceptionPlugin $exceptionPlugin
130
-	 * @return Server
131
-	 */
132
-	protected function getSabreServer(View $view, $user, $password, ExceptionPlugin $exceptionPlugin) {
133
-		$authBackend = new Auth($user, $password);
134
-		$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
135
-
136
-		$server = $this->serverFactory->createServer(false, '/', 'dummy', $authPlugin, function () use ($view) {
137
-			return $view;
138
-		});
139
-		$server->addPlugin($exceptionPlugin);
140
-
141
-		return $server;
142
-	}
32
+    use UserTrait;
33
+    use MountProviderTrait;
34
+    protected ServerFactory $serverFactory;
35
+
36
+    protected function getStream($string) {
37
+        $stream = fopen('php://temp', 'r+');
38
+        fwrite($stream, $string);
39
+        fseek($stream, 0);
40
+        return $stream;
41
+    }
42
+
43
+    protected function setUp(): void {
44
+        parent::setUp();
45
+
46
+        $this->serverFactory = new ServerFactory(
47
+            \OCP\Server::get(IConfig::class),
48
+            \OCP\Server::get(LoggerInterface::class),
49
+            \OCP\Server::get(IDBConnection::class),
50
+            \OCP\Server::get(IUserSession::class),
51
+            \OCP\Server::get(IMountManager::class),
52
+            \OCP\Server::get(ITagManager::class),
53
+            $this->createMock(IRequest::class),
54
+            \OCP\Server::get(IPreview::class),
55
+            \OCP\Server::get(IEventDispatcher::class),
56
+            \OCP\Server::get(IFactory::class)->get('dav'),
57
+        );
58
+    }
59
+
60
+    protected function setupUser($name, $password): View {
61
+        $this->createUser($name, $password);
62
+        $tmpFolder = \OCP\Server::get(ITempManager::class)->getTemporaryFolder();
63
+        $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
64
+        self::loginAsUser($name);
65
+        return new View('/' . $name . '/files');
66
+    }
67
+
68
+    /**
69
+     * @param View $view the view to run the webdav server against
70
+     * @param string $user
71
+     * @param string $password
72
+     * @param string $method
73
+     * @param string $url
74
+     * @param resource|string|null $body
75
+     * @param array|null $headers
76
+     * @return \Sabre\HTTP\Response
77
+     * @throws \Exception
78
+     */
79
+    protected function request($view, $user, $password, $method, $url, $body = null, $headers = []) {
80
+        if (is_string($body)) {
81
+            $body = $this->getStream($body);
82
+        }
83
+        $this->logout();
84
+        $exceptionPlugin = new ExceptionPlugin('webdav', \OCP\Server::get(LoggerInterface::class));
85
+        $server = $this->getSabreServer($view, $user, $password, $exceptionPlugin);
86
+        $request = new Request($method, $url, $headers, $body);
87
+
88
+        // since sabre catches all exceptions we need to save them and throw them from outside the sabre server
89
+
90
+        $serverParams = [];
91
+        if (is_array($headers)) {
92
+            foreach ($headers as $header => $value) {
93
+                $serverParams['HTTP_' . strtoupper(str_replace('-', '_', $header))] = $value;
94
+            }
95
+        }
96
+        $ncRequest = new \OC\AppFramework\Http\Request([
97
+            'server' => $serverParams
98
+        ], $this->createMock(IRequestId::class), $this->createMock(IConfig::class), null);
99
+
100
+        $this->overwriteService(IRequest::class, $ncRequest);
101
+
102
+        $result = $this->makeRequest($server, $request);
103
+
104
+        $this->restoreService(IRequest::class);
105
+
106
+        foreach ($exceptionPlugin->getExceptions() as $exception) {
107
+            throw $exception;
108
+        }
109
+        return $result;
110
+    }
111
+
112
+    /**
113
+     * @param Server $server
114
+     * @param Request $request
115
+     * @return \Sabre\HTTP\Response
116
+     */
117
+    protected function makeRequest(Server $server, Request $request) {
118
+        $sapi = new Sapi($request);
119
+        $server->sapi = $sapi;
120
+        $server->httpRequest = $request;
121
+        $server->exec();
122
+        return $sapi->getResponse();
123
+    }
124
+
125
+    /**
126
+     * @param View $view
127
+     * @param string $user
128
+     * @param string $password
129
+     * @param ExceptionPlugin $exceptionPlugin
130
+     * @return Server
131
+     */
132
+    protected function getSabreServer(View $view, $user, $password, ExceptionPlugin $exceptionPlugin) {
133
+        $authBackend = new Auth($user, $password);
134
+        $authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
135
+
136
+        $server = $this->serverFactory->createServer(false, '/', 'dummy', $authPlugin, function () use ($view) {
137
+            return $view;
138
+        });
139
+        $server->addPlugin($exceptionPlugin);
140
+
141
+        return $server;
142
+    }
143 143
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -60,9 +60,9 @@  discard block
 block discarded – undo
60 60
 	protected function setupUser($name, $password): View {
61 61
 		$this->createUser($name, $password);
62 62
 		$tmpFolder = \OCP\Server::get(ITempManager::class)->getTemporaryFolder();
63
-		$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
63
+		$this->registerMount($name, '\OC\Files\Storage\Local', '/'.$name, ['datadir' => $tmpFolder]);
64 64
 		self::loginAsUser($name);
65
-		return new View('/' . $name . '/files');
65
+		return new View('/'.$name.'/files');
66 66
 	}
67 67
 
68 68
 	/**
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
 		$serverParams = [];
91 91
 		if (is_array($headers)) {
92 92
 			foreach ($headers as $header => $value) {
93
-				$serverParams['HTTP_' . strtoupper(str_replace('-', '_', $header))] = $value;
93
+				$serverParams['HTTP_'.strtoupper(str_replace('-', '_', $header))] = $value;
94 94
 			}
95 95
 		}
96 96
 		$ncRequest = new \OC\AppFramework\Http\Request([
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
 		$authBackend = new Auth($user, $password);
134 134
 		$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
135 135
 
136
-		$server = $this->serverFactory->createServer(false, '/', 'dummy', $authPlugin, function () use ($view) {
136
+		$server = $this->serverFactory->createServer(false, '/', 'dummy', $authPlugin, function() use ($view) {
137 137
 			return $view;
138 138
 		});
139 139
 		$server->addPlugin($exceptionPlugin);
Please login to merge, or discard this patch.
dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php 2 patches
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -19,24 +19,24 @@
 block discarded – undo
19 19
  * @package OCA\DAV\Tests\unit\Connector\Sabre\RequestTest
20 20
  */
21 21
 class PartFileInRootUploadTest extends UploadTest {
22
-	protected function setUp(): void {
23
-		$config = Server::get(IConfig::class);
24
-		$mockConfig = $this->createMock(IConfig::class);
25
-		$mockConfig->expects($this->any())
26
-			->method('getSystemValue')
27
-			->willReturnCallback(function ($key, $default) use ($config) {
28
-				if ($key === 'part_file_in_storage') {
29
-					return false;
30
-				} else {
31
-					return $config->getSystemValue($key, $default);
32
-				}
33
-			});
34
-		$this->overwriteService(AllConfig::class, $mockConfig);
35
-		parent::setUp();
36
-	}
22
+    protected function setUp(): void {
23
+        $config = Server::get(IConfig::class);
24
+        $mockConfig = $this->createMock(IConfig::class);
25
+        $mockConfig->expects($this->any())
26
+            ->method('getSystemValue')
27
+            ->willReturnCallback(function ($key, $default) use ($config) {
28
+                if ($key === 'part_file_in_storage') {
29
+                    return false;
30
+                } else {
31
+                    return $config->getSystemValue($key, $default);
32
+                }
33
+            });
34
+        $this->overwriteService(AllConfig::class, $mockConfig);
35
+        parent::setUp();
36
+    }
37 37
 
38
-	protected function tearDown(): void {
39
-		$this->restoreService('AllConfig');
40
-		parent::tearDown();
41
-	}
38
+    protected function tearDown(): void {
39
+        $this->restoreService('AllConfig');
40
+        parent::tearDown();
41
+    }
42 42
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@
 block discarded – undo
24 24
 		$mockConfig = $this->createMock(IConfig::class);
25 25
 		$mockConfig->expects($this->any())
26 26
 			->method('getSystemValue')
27
-			->willReturnCallback(function ($key, $default) use ($config) {
27
+			->willReturnCallback(function($key, $default) use ($config) {
28 28
 				if ($key === 'part_file_in_storage') {
29 29
 					return false;
30 30
 				} else {
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php 1 patch
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -19,60 +19,60 @@
 block discarded – undo
19 19
  * @package OCA\DAV\Tests\unit\Connector\Sabre\RequestTest
20 20
  */
21 21
 class UploadTest extends RequestTestCase {
22
-	public function testBasicUpload(): void {
23
-		$user = self::getUniqueID();
24
-		$view = $this->setupUser($user, 'pass');
22
+    public function testBasicUpload(): void {
23
+        $user = self::getUniqueID();
24
+        $view = $this->setupUser($user, 'pass');
25 25
 
26
-		$this->assertFalse($view->file_exists('foo.txt'));
27
-		$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
26
+        $this->assertFalse($view->file_exists('foo.txt'));
27
+        $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
28 28
 
29
-		$this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
30
-		$this->assertTrue($view->file_exists('foo.txt'));
31
-		$this->assertEquals('asd', $view->file_get_contents('foo.txt'));
29
+        $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
30
+        $this->assertTrue($view->file_exists('foo.txt'));
31
+        $this->assertEquals('asd', $view->file_get_contents('foo.txt'));
32 32
 
33
-		$info = $view->getFileInfo('foo.txt');
34
-		$this->assertInstanceOf('\OC\Files\FileInfo', $info);
35
-		$this->assertEquals(3, $info->getSize());
36
-	}
33
+        $info = $view->getFileInfo('foo.txt');
34
+        $this->assertInstanceOf('\OC\Files\FileInfo', $info);
35
+        $this->assertEquals(3, $info->getSize());
36
+    }
37 37
 
38
-	public function testUploadOverWrite(): void {
39
-		$user = self::getUniqueID();
40
-		$view = $this->setupUser($user, 'pass');
38
+    public function testUploadOverWrite(): void {
39
+        $user = self::getUniqueID();
40
+        $view = $this->setupUser($user, 'pass');
41 41
 
42
-		$view->file_put_contents('foo.txt', 'foobar');
42
+        $view->file_put_contents('foo.txt', 'foobar');
43 43
 
44
-		$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
44
+        $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
45 45
 
46
-		$this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus());
47
-		$this->assertEquals('asd', $view->file_get_contents('foo.txt'));
46
+        $this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus());
47
+        $this->assertEquals('asd', $view->file_get_contents('foo.txt'));
48 48
 
49
-		$info = $view->getFileInfo('foo.txt');
50
-		$this->assertInstanceOf('\OC\Files\FileInfo', $info);
51
-		$this->assertEquals(3, $info->getSize());
52
-	}
49
+        $info = $view->getFileInfo('foo.txt');
50
+        $this->assertInstanceOf('\OC\Files\FileInfo', $info);
51
+        $this->assertEquals(3, $info->getSize());
52
+    }
53 53
 
54
-	public function testUploadOverWriteReadLocked(): void {
55
-		$user = self::getUniqueID();
56
-		$view = $this->setupUser($user, 'pass');
54
+    public function testUploadOverWriteReadLocked(): void {
55
+        $user = self::getUniqueID();
56
+        $view = $this->setupUser($user, 'pass');
57 57
 
58
-		$view->file_put_contents('foo.txt', 'bar');
58
+        $view->file_put_contents('foo.txt', 'bar');
59 59
 
60
-		$view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED);
60
+        $view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED);
61 61
 
62
-		$result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
63
-		$this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
64
-	}
62
+        $result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
63
+        $this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
64
+    }
65 65
 
66
-	public function testUploadOverWriteWriteLocked(): void {
67
-		$user = self::getUniqueID();
68
-		$view = $this->setupUser($user, 'pass');
69
-		$this->loginAsUser($user);
66
+    public function testUploadOverWriteWriteLocked(): void {
67
+        $user = self::getUniqueID();
68
+        $view = $this->setupUser($user, 'pass');
69
+        $this->loginAsUser($user);
70 70
 
71
-		$view->file_put_contents('foo.txt', 'bar');
71
+        $view->file_put_contents('foo.txt', 'bar');
72 72
 
73
-		$view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE);
73
+        $view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE);
74 74
 
75
-		$result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
76
-		$this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
77
-	}
75
+        $result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
76
+        $this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
77
+    }
78 78
 }
Please login to merge, or discard this patch.