Skip to content

Commit

Permalink
Refactor endpoints, REST style.
Browse files Browse the repository at this point in the history
Update tests.
  • Loading branch information
redblom committed Jul 17, 2024
1 parent ceb94fb commit 8ddd9aa
Show file tree
Hide file tree
Showing 48 changed files with 2,334 additions and 1,759 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ buildapp-tests:
ln -s ../ $(app_name) && \
tar cvzfh $(appstore_package_name).tar.gz \
--exclude="$(app_name)/build" \
--exclude="$(app_name)/Makefile" \
--exclude="$(app_name)/*.log" \
--exclude="$(app_name)/js/node_modules" \
--exclude="$(app_name)/js/tests" \
Expand Down
80 changes: 16 additions & 64 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,85 +8,37 @@
* without the controller part, the stuff after the hash is the method.
* eg. page#index -> OCA\Invitation\Controller\PageController->index()
*
*
*
* General endpoint syntax follows REST good practices:
* /resource/{resourceProperty}?param=value
*
*
* Query parameter names are written camel case:
* eg. GET /[email protected]@surf.nl
* Query filter, sorting, pagination, navigation parameter names are written snake case:
* eg. _next,
* _sort,
* timestamp_after ('_after' filter parameter name appended to entity parameter name)
*
* eg. _next,
* _sort,
* timestamp_after ('_after' filter parameter name appended to parameter (resource property) name)
*
*/

declare(strict_types=1);

return [
'resources' => [
'note' => ['url' => '/notes'],
'note_api' => ['url' => '/api/0.1/notes']
],
'ocs' => [
['root' => '/invitation', 'name' => 'ocs#find_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'],
],
'routes' => [
// bespoke API - invitation
// ['name' => 'invitation#index', 'url' => '/index', 'verb' => 'GET'],
['name' => 'invitation#find_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'],
['name' => 'invitation#find', 'url' => '/invitations', 'verb' => 'GET'],
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],

// unprotected endpoint /invitation
['name' => 'invitation#invitation', 'url' => '/invite/{token}', 'verb' => 'GET'],
['name' => 'invitation#invitation_form', 'url' => '/invitation-form', 'verb' => 'GET'],
['name' => 'invitation#generate_invite', 'url' => '/generate-invite', 'verb' => 'POST'],
['name' => 'invitation#handle_invite', 'url' => '/handle-invite', 'verb' => 'GET'],
['name' => 'invitation#accept_invite', 'url' => '/accept-invite/{token}', 'verb' => 'PUT'],
['name' => 'invitation#decline_invite', 'url' => '/decline-invite/{token}', 'verb' => 'PUT'],
['name' => 'invitation#update', 'url' => '/update-invitation', 'verb' => 'PUT'],
['name' => 'invitation#get_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'],
['name' => 'invitation#update', 'url' => '/invitations/{token}', 'verb' => 'PUT'],
['name' => 'invitation#find', 'url' => '/invitations', 'verb' => 'GET'],
['name' => 'invitation#generate_invite', 'url' => '/invitations', 'verb' => 'POST'],

// bespoke API - remote user
['name' => 'remote_user#search', 'url' => '/remote-user/search', 'verb' => 'GET'],
['name' => 'remote_user#get_remote_user', 'url' => '/remote-user', 'verb' => 'GET'],

// bespoke API - mesh registry
['name' => 'mesh_registry#forward_invite', 'url' => '/registry/forward-invite', 'verb' => 'GET'],

// route '/registry/invitation-service-provider' concerns remote invitation service providers
// returns the properties of the invitation service provider like endpoint, domain, name
// unprotected
['name' => 'mesh_registry#invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'GET'],
// adds a remote invitation service provider
['name' => 'mesh_registry#add_invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'POST'],
// update the properties of this invitation service provider
['name' => 'mesh_registry#update_invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'PUT'],
['name' => 'mesh_registry#delete_invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'DELETE'],

// route '/registry/invitation-service-providers' returns all providers
['name' => 'mesh_registry#invitation_service_providers', 'url' => '/registry/invitation-service-providers', 'verb' => 'GET'],

// route '/endpoint' of this instance
['name' => 'mesh_registry#get_endpoint', 'url' => '/registry/endpoint', 'verb' => 'GET'],
['name' => 'mesh_registry#set_endpoint', 'url' => '/registry/endpoint', 'verb' => 'PUT'],

// route '/name' of this instance
['name' => 'mesh_registry#get_name', 'url' => '/registry/name', 'verb' => 'GET'],
['name' => 'mesh_registry#set_name', 'url' => '/registry/name', 'verb' => 'PUT'],

// route '/share-with-invited-users-only' of this instance
['name' => 'mesh_registry#get_allow_sharing_with_invited_users_only', 'url' => '/share-with-invited-users-only', 'verb' => 'GET'],
['name' => 'mesh_registry#set_allow_sharing_with_invited_users_only', 'url' => '/share-with-invited-users-only', 'verb' => 'PUT'],
// unprotected
['name' => 'mesh_registry#get_name', 'url' => '/registry/name', 'verb' => 'GET'],

// OCM - Open Cloud Mesh protocol
['name' => 'ocm#invite_accepted', 'url' => '/ocm/invite-accepted', 'verb' => 'POST'],

// miscellaneous endpoints
['name' => 'page#wayf', 'url' => '/page/wayf', 'verb' => 'GET'],
['name' => 'error#invitation', 'url' => 'error/invitation', 'verb' => 'GET'],

[
'name' => 'note_api#preflighted_cors', 'url' => '/api/0.1/{path}',
'verb' => 'OPTIONS', 'requirements' => ['path' => '.+']
]
// unprotected
['name' => 'ocm#invite_accepted', 'url' => '/ocm/invite-accepted', 'verb' => 'POST'],
]
];
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
{
"name": "nextcloud/invitation",
"description": "Enhanced federated sharing between Nextcloud instances.",
"description": "Enhanced federated sharing between EFSS instances.",
"type": "project",
"license": "AGPL-3.0-or-later",
"authors": [
{
"name": "Antoon Prins"
}
],
"require": {
"ramsey/uuid": "4.2.3"
},
"require-dev": {
"phpunit/phpunit": "^9",
"sabre/dav": "^4.1",
Expand Down
8 changes: 8 additions & 0 deletions img/app.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class Application extends App implements IBootstrap

public const CONFIG_ALLOW_SHARING_WITH_INVITED_USERS_ONLY = 'allow_sharing_with_invited_users_only';

public const INVITATION_EMAIL_SUBJECT = 'INVITATION_EMAIL_SUBJECT';

public function __construct()
{
parent::__construct(self::APP_ID);
Expand Down
26 changes: 26 additions & 0 deletions lib/Controller/Errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

// SPDX-FileCopyrightText: Antoon Prins <[email protected]>
// SPDX-License-Identifier: AGPL-3.0-or-later

namespace OCA\Invitation\Controller;

use Closure;
use OCA\Invitation\Service\NoteNotFound;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;

trait Errors
{
protected function handleNotFound(Closure $callback): DataResponse
{
try {
return new DataResponse($callback());
} catch (NoteNotFound $e) {
$message = ['message' => $e->getMessage()];
return new DataResponse($message, Http::STATUS_NOT_FOUND);
}
}
}
Loading

0 comments on commit 8ddd9aa

Please sign in to comment.