Skip to content

Commit 4d4d362

Browse files
committed
replace @ with ~ in urls
1 parent 99244d5 commit 4d4d362

14 files changed

+2323
-129
lines changed

solid/appinfo/routes.php

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
* it's instantiated in there
1616
*/
1717

18-
1918
$routes = [
2019
['name' => 'page#approval', 'url' => '/sharing/{clientId}', 'verb' => 'GET'],
2120
['name' => 'page#handleRevoke', 'url' => '/revoke/{clientId}', 'verb' => 'DELETE'],
@@ -44,47 +43,47 @@
4443
];
4544

4645
$userIdRoutes = [
47-
['name' => 'page#profile', 'url' => '/@{userId}/', 'verb' => 'GET'],
48-
49-
['name' => 'profile#handleGet', 'url' => '/@{userId}/profile{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
50-
['name' => 'profile#handlePut', 'url' => '/@{userId}/profile{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
51-
['name' => 'profile#handlePatch', 'url' => '/@{userId}/profile{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
52-
['name' => 'profile#handleHead', 'url' => '/@{userId}/profile{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
53-
54-
['name' => 'storage#handleGet', 'url' => '/@{userId}/storage{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
55-
['name' => 'storage#handlePost', 'url' => '/@{userId}/storage{path}', 'verb' => 'POST', 'requirements' => ['path' => '.+'], ],
56-
['name' => 'storage#handlePut', 'url' => '/@{userId}/storage{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
57-
['name' => 'storage#handleDelete', 'url' => '/@{userId}/storage{path}', 'verb' => 'DELETE', 'requirements' => ['path' => '.+'], ],
58-
['name' => 'storage#handlePatch', 'url' => '/@{userId}/storage{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
59-
['name' => 'storage#handleHead', 'url' => '/@{userId}/storage{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
60-
61-
['name' => 'calendar#handleGet', 'url' => '/@{userId}/calendar{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
62-
['name' => 'calendar#handlePost', 'url' => '/@{userId}/calendar{path}', 'verb' => 'POST', 'requirements' => ['path' => '.+'], ],
63-
['name' => 'calendar#handlePut', 'url' => '/@{userId}/calendar{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
64-
['name' => 'calendar#handleDelete', 'url' => '/@{userId}/calendar{path}', 'verb' => 'DELETE', 'requirements' => ['path' => '.+'], ],
65-
['name' => 'calendar#handlePatch', 'url' => '/@{userId}/calendar{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
66-
['name' => 'calendar#handleHead', 'url' => '/@{userId}/calendar{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
67-
68-
['name' => 'contacts#handleGet', 'url' => '/@{userId}/contacts{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
69-
['name' => 'contacts#handlePost', 'url' => '/@{userId}/contacts{path}', 'verb' => 'POST', 'requirements' => ['path' => '.+'], ],
70-
['name' => 'contacts#handlePut', 'url' => '/@{userId}/contacts{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
71-
['name' => 'contacts#handleDelete', 'url' => '/@{userId}/contacts{path}', 'verb' => 'DELETE', 'requirements' => ['path' => '.+'], ],
72-
['name' => 'contacts#handlePatch', 'url' => '/@{userId}/contacts{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
73-
['name' => 'contacts#handleHead', 'url' => '/@{userId}/contacts{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
46+
['name' => 'page#profile', 'url' => '/~{userId}/', 'verb' => 'GET'],
47+
48+
['name' => 'profile#handleGet', 'url' => '/~{userId}/profile{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
49+
['name' => 'profile#handlePut', 'url' => '/~{userId}/profile{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
50+
['name' => 'profile#handlePatch', 'url' => '/~{userId}/profile{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
51+
['name' => 'profile#handleHead', 'url' => '/~{userId}/profile{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
52+
53+
['name' => 'storage#handleGet', 'url' => '/~{userId}/storage{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
54+
['name' => 'storage#handlePost', 'url' => '/~{userId}/storage{path}', 'verb' => 'POST', 'requirements' => ['path' => '.+'], ],
55+
['name' => 'storage#handlePut', 'url' => '/~{userId}/storage{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
56+
['name' => 'storage#handleDelete', 'url' => '/~{userId}/storage{path}', 'verb' => 'DELETE', 'requirements' => ['path' => '.+'], ],
57+
['name' => 'storage#handlePatch', 'url' => '/~{userId}/storage{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
58+
['name' => 'storage#handleHead', 'url' => '/~{userId}/storage{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
59+
60+
['name' => 'calendar#handleGet', 'url' => '/~{userId}/calendar{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
61+
['name' => 'calendar#handlePost', 'url' => '/~{userId}/calendar{path}', 'verb' => 'POST', 'requirements' => ['path' => '.+'], ],
62+
['name' => 'calendar#handlePut', 'url' => '/~{userId}/calendar{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
63+
['name' => 'calendar#handleDelete', 'url' => '/~{userId}/calendar{path}', 'verb' => 'DELETE', 'requirements' => ['path' => '.+'], ],
64+
['name' => 'calendar#handlePatch', 'url' => '/~{userId}/calendar{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
65+
['name' => 'calendar#handleHead', 'url' => '/~{userId}/calendar{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
66+
67+
['name' => 'contacts#handleGet', 'url' => '/~{userId}/contacts{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], ],
68+
['name' => 'contacts#handlePost', 'url' => '/~{userId}/contacts{path}', 'verb' => 'POST', 'requirements' => ['path' => '.+'], ],
69+
['name' => 'contacts#handlePut', 'url' => '/~{userId}/contacts{path}', 'verb' => 'PUT', 'requirements' => ['path' => '.+'], ],
70+
['name' => 'contacts#handleDelete', 'url' => '/~{userId}/contacts{path}', 'verb' => 'DELETE', 'requirements' => ['path' => '.+'], ],
71+
['name' => 'contacts#handlePatch', 'url' => '/~{userId}/contacts{path}', 'verb' => 'PATCH', 'requirements' => ['path' => '.+'], ],
72+
['name' => 'contacts#handleHead', 'url' => '/~{userId}/contacts{path}', 'verb' => 'HEAD', 'requirements' => ['path' => '.+'], ],
7473
];
7574

7675
// @TODO: All routes NOT generated by the UrlGenerator ANYWHERE in the code need to be checked!
7776

7877
if (Application::$userSubDomainsEnabled) {
7978
$userIdRoutes = array_map(function ($route) {
8079
if ($route['name'] === 'page#profile') {
81-
// The profile route should be `/me` instead of `/@{userId}/`
80+
// The profile route should be `/me` instead of `/~{userId}/`
8281
$route['url'] = '/me';
8382
} else {
8483
// When UserSubDomains are enabled, all routes that start with
85-
// `/@{userId}/` should just be `/`, as the userId is present
84+
// `/~{userId}/` should just be `/`, as the userId is present
8685
// in the subdomain.
87-
$route['url'] = preg_replace('#^/@{userId}/#', '/', $route['url']);
86+
$route['url'] = preg_replace('#^/~{userId}/#', '/', $route['url']);
8887
}
8988

9089
// The required userId is set to the userId from the subdomain
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
namespace OCA\Solid\Controller;
3+
4+
use OCA\Solid\ServerConfig;
5+
6+
use OCP\AppFramework\Controller;
7+
use OCP\AppFramework\Http;
8+
use OCP\AppFramework\Http\ContentSecurityPolicy;
9+
use OCP\AppFramework\Http\JSONResponse;
10+
use OCP\AppFramework\Http\TemplateResponse;
11+
use OCP\Contacts\IManager;
12+
use OCP\IConfig;
13+
use OCP\IRequest;
14+
use OCP\IURLGenerator;
15+
use OCP\IUserManager;
16+
17+
class AppController extends Controller {
18+
use GetStorageUrlTrait;
19+
20+
protected ServerConfig $config;
21+
protected IURLGenerator $urlGenerator;
22+
23+
private $userId;
24+
private $userManager;
25+
26+
public function __construct($AppName, IRequest $request, IConfig $config, IUserManager $userManager, IManager $contactsManager, IURLGenerator $urlGenerator, $userId
27+
){
28+
parent::__construct($AppName, $request);
29+
$this->userId = $userId;
30+
$this->userManager = $userManager;
31+
$this->contactsManager = $contactsManager;
32+
$this->request = $request;
33+
$this->urlGenerator = $urlGenerator;
34+
$this->config = new ServerConfig($config, $urlGenerator, $userManager);
35+
}
36+
37+
private function getUserApps($userId) {
38+
$userApps = [];
39+
if ($this->userManager->userExists($userId)) {
40+
$allowedClients = $this->config->getAllowedClients($userId);
41+
foreach ($allowedClients as $clientId) {
42+
$registration = $this->config->getClientRegistration($clientId);
43+
$userApps[] = $registration['client_name'];
44+
}
45+
}
46+
return $userApps;
47+
}
48+
49+
private function getAppsList() {
50+
$path = __DIR__ . "/../solid-app-list.json";
51+
$appsListJson = file_get_contents($path);
52+
$appsList = json_decode($appsListJson, true);
53+
54+
$userApps = $this->getUserApps($this->userId);
55+
56+
foreach ($appsList as $key => $app) {
57+
$parsedOrigin = parse_url($app['launchUrl']);
58+
$origin = $parsedOrigin['host'];
59+
if (in_array($origin, $userApps, true)) {
60+
$appsList[$key]['registered'] = 1;
61+
} else {
62+
$appsList[$key]['registered'] = 0;
63+
}
64+
}
65+
return $appsList;
66+
}
67+
68+
private function getProfilePage() {
69+
return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute("solid.profile.handleGet", array("userId" => $this->userId, "path" => "/card"))) . "#me";
70+
}
71+
72+
/**
73+
* @NoAdminRequired
74+
* @NoCSRFRequired
75+
*/
76+
public function appLauncher() {
77+
$appsList = $this->getAppsList();
78+
if (!$appsList) {
79+
return new JSONResponse(array(), Http::STATUS_NOT_FOUND);
80+
}
81+
$appLauncherData = array(
82+
"appsListJson" => json_encode($appsList),
83+
"webId" => json_encode($this->getProfilePage()),
84+
"storageUrl" => json_encode($this->getStorageUrl($this->userId)),
85+
'solidNavigation' => array(
86+
"profile" => $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute("solid.page.profile", array("userId" => $this->userId))),
87+
"launcher" => $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute("solid.app.appLauncher", array())),
88+
)
89+
);
90+
$templateResponse = new TemplateResponse('solid', 'applauncher', $appLauncherData);
91+
$policy = new ContentSecurityPolicy();
92+
$policy->addAllowedStyleDomain("data:");
93+
$policy->addAllowedScriptDomain("'self'");
94+
$policy->addAllowedScriptDomain("'unsafe-inline'");
95+
$policy->addAllowedScriptDomain("'unsafe-eval'");
96+
$templateResponse->setContentSecurityPolicy($policy);
97+
return $templateResponse;
98+
}
99+
}

solid/lib/Controller/CalendarController.php

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -185,31 +185,31 @@ public function handlePost($userId, $path) {
185185
* @NoAdminRequired
186186
* @NoCSRFRequired
187187
*/
188-
public function handlePut() { // $userId, $path) {
189-
// FIXME: Adding the correct variables in the function name will make nextcloud
190-
// throw an error about accessing put twice, so we will find out the userId and path from $_SERVER instead;
188+
public function handlePut() { // $userId, $path) {
189+
// FIXME: Adding the correct variables in the function name will make nextcloud
190+
// throw an error about accessing put twice, so we will find out the userId and path from $_SERVER instead;
191191

192-
// because we got here, the request uri should look like:
193-
// - if we have user subdomains enabled:
194-
// /index.php/apps/solid/calendar{path}
195-
// and otherwise:
196-
// index.php/apps/solid/~{userId}/calendar{path}
192+
// because we got here, the request uri should look like:
193+
// - if we have user subdomains enabled:
194+
// /index.php/apps/solid/calendar{path}
195+
// and otherwise:
196+
// index.php/apps/solid/~{userId}/calendar{path}
197197

198198
// In the first case, we'll get the username from the SERVER_NAME. In the latter, it will come from the URL;
199-
if ($this->config->getUserSubDomainsEnabled()) {
200-
$pathInfo = explode("calendar/", $_SERVER['REQUEST_URI']);
201-
$path = $pathInfo[1];
202-
$userId = explode(".", $_SERVER['SERVER_NAME'])[0];
203-
} else {
204-
$pathInfo = explode("~", $_SERVER['REQUEST_URI']);
205-
$pathInfo = explode("/", $pathInfo[1], 2);
206-
$userId = $pathInfo[0];
207-
$path = $pathInfo[1];
208-
$path = preg_replace("/^calendar/", "", $path);
209-
}
210-
211-
return $this->handleRequest($userId, $path);
212-
}
199+
if ($this->config->getUserSubDomainsEnabled()) {
200+
$pathInfo = explode("calendar/", $_SERVER['REQUEST_URI']);
201+
$path = $pathInfo[1];
202+
$userId = explode(".", $_SERVER['SERVER_NAME'])[0];
203+
} else {
204+
$pathInfo = explode("~", $_SERVER['REQUEST_URI']);
205+
$pathInfo = explode("/", $pathInfo[1], 2);
206+
$userId = $pathInfo[0];
207+
$path = $pathInfo[1];
208+
$path = preg_replace("/^calendar/", "", $path);
209+
}
210+
211+
return $this->handleRequest($userId, $path);
212+
}
213213
/**
214214
* @PublicPage
215215
* @NoAdminRequired

0 commit comments

Comments
 (0)