-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Expand file tree
/
Copy pathPublicShareController.php
More file actions
152 lines (133 loc) · 3.47 KB
/
PublicShareController.php
File metadata and controls
152 lines (133 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCP\AppFramework;
use OCP\IRequest;
use OCP\ISession;
/**
* Base controller for public shares
*
* It will verify if the user is properly authenticated to the share. If not a 404
* is thrown by the PublicShareMiddleware.
*
* Use this for example for a controller that is not to be called via a webbrowser
* directly. For example a PublicPreviewController. As this is not meant to be
* called by a user directly.
*
* To show an auth page extend the AuthPublicShareController
*
* @since 14.0.0
*/
abstract class PublicShareController extends Controller {
/**
* @since 33.0.0
*/
public const DAV_AUTHENTICATED_FRONTEND = 'public_link_authenticated_frontend';
/** @var string */
private $token;
/**
* @since 14.0.0
*/
public function __construct(
string $appName,
IRequest $request,
protected ISession $session,
) {
parent::__construct($appName, $request);
}
/**
* Middleware set the token for the request
*
* @since 14.0.0
*/
final public function setToken(string $token) {
$this->token = $token;
}
/**
* Get the token for this request
*
* @since 14.0.0
*/
final public function getToken(): string {
return $this->token;
}
/**
* Get a hash of the password for this share
*
* To ensure access is blocked when the password to a share is changed we store
* a hash of the password for this token.
*
* @since 14.0.0
*/
abstract protected function getPasswordHash(): ?string;
/**
* Is the provided token a valid token
*
* This function is already called from the middleware directly after setting the token.
*
* @since 14.0.0
*/
abstract public function isValidToken(): bool;
/**
* Is a share with this token password protected
*
* @since 14.0.0
*/
abstract protected function isPasswordProtected(): bool;
/**
* Check if a share is authenticated or not
*
* @since 14.0.0
*/
public function isAuthenticated(): bool {
// Always authenticated against non password protected shares
if (!$this->isPasswordProtected()) {
return true;
}
// If we are authenticated properly
if ($this->validateTokenSession($this->getToken(), $this->getPasswordHash())) {
return true;
}
// Fail by default if nothing matches
return false;
}
/**
* Function called if the share is not found.
*
* You can use this to do some logging for example
*
* @since 14.0.0
*/
public function shareNotFound() {
}
/**
* Validate the token and password hash stored in session
*
* @since 33.0.0
*/
protected function validateTokenSession(string $token, string $passwordHash): bool {
$allowedTokensJSON = $this->session->get(self::DAV_AUTHENTICATED_FRONTEND) ?? '[]';
$allowedTokens = json_decode($allowedTokensJSON, true);
if (!is_array($allowedTokens)) {
$allowedTokens = [];
}
return ($allowedTokens[$token] ?? '') === $passwordHash;
}
/**
* Store the token and password hash in session
*
* @since 33.0.0
*/
protected function storeTokenSession(string $token, string $passwordHash = ''): void {
$allowedTokensJSON = $this->session->get(self::DAV_AUTHENTICATED_FRONTEND) ?? '[]';
$allowedTokens = json_decode($allowedTokensJSON, true);
if (!is_array($allowedTokens)) {
$allowedTokens = [];
}
$allowedTokens[$token] = $passwordHash;
$this->session->set(self::DAV_AUTHENTICATED_FRONTEND, json_encode($allowedTokens));
}
}