Skip to content

Commit c1ed57f

Browse files
committed
align naming with the specs
1 parent a2ef634 commit c1ed57f

7 files changed

Lines changed: 61 additions & 57 deletions

File tree

solid/TODO.Notifications

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
TODO:
22
- [ ] advertise the notifications channel in well-known
33
- [ ] advertise the notifications channel in HTTP headers
4-
- [ ] implement function to get subscription in SolidWebhook
54

65
Backlog / later:
76
- [ ] add actor to notifications
@@ -17,3 +16,4 @@ Done:
1716
- [v] handle register requests - this must validate that the requestor has read access to the resource;
1817
- [v] handle unregister requests - only the webid that subscribed should be able to unsubscribe
1918
- [v] reinstate the updates-via header in HEAD requests, which was removed from solid-crud
19+
- [v] implement function to get subscription in SolidWebhook

solid/lib/Controller/SolidWebhookController.php

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,15 @@ public function listWebhooks(): DataResponse {
7373
* @NoAdminRequired
7474
* @NoCSRFRequired
7575
*/
76-
public function register(string $targetUrl, string $webhookUrl, string $expiry): DataResponse {
77-
// FIXME: Validate WAC read access to the target URL for $this->webId
78-
if ($this->checkReadAccess($targetUrl)) {
79-
return new DataResponse($this->webhookService->create($this->webId, $targetUrl, $webhookUrl, $expiry));
76+
public function register(string $topic, string $target): DataResponse {
77+
if (!$this->isValidWebhookTarget($target)) {
78+
return new DataResponse("Error: invalid webhook target", 422);
79+
}
80+
81+
if ($this->checkReadAccess($topic)) {
82+
return new DataResponse($this->webhookService->create($this->webId, $topic, $target));
83+
} else {
84+
return new DataResponse("Error: denied access", 401);
8085
}
8186
}
8287

@@ -85,12 +90,18 @@ public function register(string $targetUrl, string $webhookUrl, string $expiry):
8590
* @NoAdminRequired
8691
* @NoCSRFRequired
8792
*/
88-
public function unregister(string $targetUrl): DataResponse {
89-
return $this->handleNotFound(function () use ($targetUrl) {
90-
return $this->webhookService->delete($this->webId, $targetUrl);
93+
public function unregister(string $topic): DataResponse {
94+
return $this->handleNotFound(function () use ($topic) {
95+
return $this->webhookService->delete($this->webId, $topic);
9196
});
9297
}
9398

99+
private function isValidWebhookTarget($target) {
100+
if (!preg_match("|^https://|", $target)) {
101+
return false;
102+
}
103+
return true;
104+
}
94105

95106
private function getFileSystem() {
96107
// Create the Nextcloud Adapter
@@ -135,22 +146,22 @@ private function initializeStorage($userId) {
135146
$this->filesystem = $this->getFileSystem();
136147
}
137148

138-
private function parseTargetUrl($targetUrl) {
139-
// targetUrl = https://nextcloud.server/solid/@alice/storage/foo/bar
149+
private function parseTopic($topic) {
150+
// topic = https://nextcloud.server/solid/@alice/storage/foo/bar
140151
$appBaseUrl = $this->getAppBaseUrl(); // https://nextcloud.server/solid/
141-
$internalUrl = str_replace($appBaseUrl, '', $targetUrl); // @alice/storage/foo/bar
152+
$internalUrl = str_replace($appBaseUrl, '', $topic); // @alice/storage/foo/bar
142153
$pathicles = explode("/", $internalUrl);
143154
$userId = $pathicles[0]; // @alice
144155
$userId = preg_replace("/^@/", "", $userId); // alice
145156
$storageUrl = $this->getStorageUrl($userId); // https://nextcloud.server/solid/@alice/storage/
146-
$storagePath = str_replace($storageUrl, '/', $targetUrl); // /foo/bar
157+
$storagePath = str_replace($storageUrl, '/', $topic); // /foo/bar
147158
return array(
148159
"userId" => $userId,
149160
"path" => $storagePath
150161
);
151162
}
152163

153-
private function createGetRequest($targetUrl) {
164+
private function createGetRequest($topic) {
154165
$serverParams = [];
155166
$fileParams = [];
156167
$method = "GET";
@@ -160,18 +171,18 @@ private function createGetRequest($targetUrl) {
160171
return new \Laminas\Diactoros\ServerRequest(
161172
$serverParams,
162173
$fileParams,
163-
$targetUrl,
174+
$topic,
164175
$method,
165176
$body,
166177
$headers
167178
);
168179
}
169180

170-
private function checkReadAccess($targetUrl) {
171-
// split out $targetUrl into $userId and $path https://nextcloud.server/solid/@alice/storage/foo/bar
181+
private function checkReadAccess($topic) {
182+
// split out $topic into $userId and $path https://nextcloud.server/solid/@alice/storage/foo/bar
172183
// - userId in this case is the pod owner (not the one doing the request). (alice)
173184
// - path is the path within the storage pod (/foo/bar)
174-
$target = $this->parseTargetUrl($targetUrl);
185+
$target = $this->parseTopic($topic);
175186
$userId = $target["userId"];
176187
$path = $target["path"];
177188

@@ -184,7 +195,7 @@ private function checkReadAccess($targetUrl) {
184195
$serverParams = [];
185196
$fileParams = [];
186197

187-
$request = $this->createGetRequest($targetUrl);
198+
$request = $this->createGetRequest($topic);
188199
if (!$this->WAC->isAllowed($request, $this->webId)) { // Deny if we don't have read grants on the URL;
189200
return false;
190201
}

solid/lib/Db/SolidWebhook.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,16 @@
88

99
class SolidWebhook extends Entity implements JsonSerializable {
1010
public $id;
11-
public $path;
11+
public $topic;
1212
public $webId;
13-
public $url;
14-
public $expiry;
13+
public $target;
1514

1615
public function jsonSerialize(): array {
1716
return [
1817
'id' => $this->id,
1918
'webId' => $this->webId,
20-
'path' => $this->path,
21-
'url' => $this->url,
22-
'expiry' => $this->expiry
19+
'topic' => $this->topic,
20+
'target' => $this->target
2321
];
2422
}
2523
}

solid/lib/Db/SolidWebhookMapper.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ public function __construct(IDBConnection $db) {
1515

1616
/**
1717
* @param string $webId
18-
* @param string $path
18+
* @param string $topic
1919
* @return Entity|SolidWebhook
2020
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
2121
* @throws DoesNotExistException
2222
*/
23-
public function find(string $webId, string $path): SolidWebhook {
23+
public function find(string $webId, string $topic): SolidWebhook {
2424
/* @var $qb IQueryBuilder */
2525
$qb = $this->db->getQueryBuilder();
2626
$qb->select('*')
2727
->from('solid_webhooks')
2828
->where($qb->expr()->eq('web_id', $qb->createNamedParameter($webId)))
29-
->andWhere($qb->expr()->eq('path', $qb->createNamedParameter($path)));
29+
->andWhere($qb->expr()->eq('topic', $qb->createNamedParameter($topic)));
3030
return $this->findEntity($qb);
3131
}
3232

@@ -44,15 +44,15 @@ public function findAll(string $webId): array {
4444
}
4545

4646
/**
47-
* @param string $path
47+
* @param string $topic
4848
* @return array
4949
*/
50-
public function findByPath(string $path): array {
50+
public function findByTopic(string $topic): array {
5151
/* @var $qb IQueryBuilder */
5252
$qb = $this->db->getQueryBuilder();
5353
$qb->select('*')
5454
->from('solid_webhooks')
55-
->where($qb->expr()->eq('path', $qb->createNamedParameter($path)));
55+
->where($qb->expr()->eq('topic', $qb->createNamedParameter($topic)));
5656
return $this->findEntities($qb);
5757
}
5858
}

solid/lib/Migration/Version000000Date20220919084800.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
2222

2323
if (!$schema->hasTable('solid_webhooks')) {
2424
$table = $schema->createTable('solid_webhooks');
25-
// id, webid, path, url, expiry
25+
// id, webid, topic, target
2626
$table->addColumn('id', 'integer', [
2727
'autoincrement' => true,
2828
'notnull' => true,
@@ -31,22 +31,18 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
3131
'notnull' => true,
3232
'length' => 2048
3333
]);
34-
$table->addColumn('path', 'string', [
34+
$table->addColumn('topic', 'string', [
3535
'notnull' => true,
3636
'length' => 2048,
3737
]);
38-
$table->addColumn('url', 'string', [
39-
'notnull' => true,
40-
'length' => 2048,
41-
]);
42-
$table->addColumn('expiry', 'string', [
38+
$table->addColumn('target', 'string', [
4339
'notnull' => true,
4440
'length' => 2048,
4541
]);
4642

4743
$table->setPrimaryKey(['id']);
4844
$table->addIndex(['web_id'], 'solid_webhooks_web_id_index');
49-
$table->addIndex(['path'], 'solid_webhooks_path_index');
45+
$table->addIndex(['target'], 'solid_webhooks_target_index');
5046
}
5147
return $schema;
5248
}

solid/lib/Notifications/SolidWebhook.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,23 @@ public function __construct() {
1111
$this->webhookService = $app->getContainer()->get(SolidWebhookService::class);
1212
}
1313

14-
public function send($path, $type) {
15-
$webhooks = $this->getWebhooks($path);
14+
public function send($topic, $type) {
15+
$webhooks = $this->getWebhooks($topic);
1616
foreach ($webhooks as $webhook) {
1717
try {
18-
$this->postUpdate($webhook->{'url'}, $path, $type);
18+
$this->postUpdate($webhook->{'target'}, $topic, $type);
1919
} catch(\Exception $e) {
2020
// FIXME: add retry code here?
2121
}
2222
}
2323
}
24-
private function getWebhooks($path) {
25-
$urls = $this->webhookService->findByPath($path);
24+
private function getWebhooks($topic) {
25+
$urls = $this->webhookService->findByTopic($topic);
2626
return $urls;
2727
}
28-
private function postUpdate($webhookUrl, $path, $type) {
28+
private function postUpdate($webhookUrl, $topic, $type) {
2929
try {
30-
$postData = $this->createUpdatePayload($path, $type);
30+
$postData = $this->createUpdatePayload($topic, $type);
3131
$opts = array(
3232
'http' => array(
3333
'method' => 'POST',
@@ -45,11 +45,11 @@ private function postUpdate($webhookUrl, $path, $type) {
4545
throw new Exception('Could not write to webhook server', 502, $exception);
4646
}
4747
}
48-
private function createUpdatePayload($path, $type) {
48+
private function createUpdatePayload($topic, $type) {
4949
//$updateId = "urn:uuid:<uuid>";
5050
//$actor = "<WebID>";
5151
$object = [
52-
"id" => $path,
52+
"id" => $topic,
5353
"type" => [
5454
"http://www.w3.org/ns/ldp#Resource"
5555
]

solid/lib/Service/SolidWebhookService.php

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public function findAll(string $webId): array {
2222
return $this->mapper->findAll($webId);
2323
}
2424

25-
public function findByPath(string $path): array {
26-
return $this->mapper->findByPath($path);
25+
public function findByTopic(string $topic): array {
26+
return $this->mapper->findByTopic($topic);
2727
}
2828

2929
private function handleException(Exception $e): void {
@@ -37,26 +37,25 @@ private function handleException(Exception $e): void {
3737
}
3838
}
3939

40-
public function find($webId, $path) {
40+
public function find($webId, $topic) {
4141
try {
42-
return $this->mapper->find($webId, $path);
42+
return $this->mapper->find($webId, $topic);
4343
} catch (Exception $e) {
4444
$this->handleException($e);
4545
}
4646
}
4747

48-
public function create($webId, $path, $url, $expiry) {
48+
public function create($webId, $topic, $target) {
4949
$webhook = new SolidWebhook();
5050
$webhook->setWebId($webId);
51-
$webhook->setPath($path);
52-
$webhook->setUrl($url);
53-
$webhook->setExpiry($expiry);
51+
$webhook->setTopic($topic);
52+
$webhook->setTarget($target);
5453
return $this->mapper->insert($webhook);
5554
}
5655

57-
public function delete($webId, $path) {
56+
public function delete($webId, $topic) {
5857
try {
59-
$webhook = $this->mapper->find($webId, $path);
58+
$webhook = $this->mapper->find($webId, $topic);
6059
$this->mapper->delete($webhook);
6160
return $webhook;
6261
} catch (Exception $e) {

0 commit comments

Comments
 (0)