diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json new file mode 100644 index 0000000000..2c8bb6ee66 --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json @@ -0,0 +1,14 @@ +{ + "ocs": { + ... + "data": { + ... + "capabilities": { + ... + "notifications": { + "ocs-endpoints": ["list", "get", "delete"] + } + } + } + } +} diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json new file mode 100644 index 0000000000..cf2b51f433 --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json @@ -0,0 +1,15 @@ +{ + "ocs": { + "data": { + "capabilities": { + "notifications": { + "ocs-endpoints": [ + "list", + "get", + "delete" + ] + } + } + } + } +} diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml new file mode 100644 index 0000000000..5f9518483e --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml @@ -0,0 +1,16 @@ + + + + + + + + + list + get + delete + + + + + diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json new file mode 100644 index 0000000000..05317fda46 --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json @@ -0,0 +1,12 @@ +{ + "ocs": { + "meta": { + "status": "ok", + "statuscode": 200, + "message": null, + "totalitems": "", + "itemsperpage": "" + }, + "data": [] + } +} diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json new file mode 100644 index 0000000000..7c2ee8aa9f --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json @@ -0,0 +1,31 @@ +{ + "ocs": { + "meta": { + "status": "ok", + "statuscode": 200, + "message": null + }, + "data": [{ + "notification_id": 61, + "app": "files_sharing", + "user": "admin", + "datetime": "2004-02-12T15:19:21+00:00", + "object_type": "remote_share", + "object_id": "13", + "subject": "You received admin@localhost as a remote share from test", + "message": "", + "link": "http://localhost/index.php/apps/files_sharing/pending", + "actions": [{ + "label": "Accept", + "link": "http:\/\/localhost\/ocs\/v1.php\/apps\/files_sharing\/api\/v1\/remote_shares\/13", + "type": "POST", + "primary": true + }, { + "label": "Decline", + "link": "http:\/\/localhost\/ocs\/v1.php\/apps\/files_sharing\/api\/v1\/remote_shares\/13", + "type": "DELETE", + "primary": false + }] + }] + } +} diff --git a/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh new file mode 100644 index 0000000000..929a97a00e --- /dev/null +++ b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +USERNAME=admin +PASSWORD={oc-examples-password} +API_PATH="ocs/v2.php/cloud/capabilities" +SERVER_URI="{oc-examples-server-url}" + +# Get server capabilities in XML format +curl '$SERVER_URI/$API_PATH/' \ + --user "${USERNAME}:${PASSWORD}" + +# Get server capabilities in JSON format +curl '$SERVER_URI/$API_PATH?format=json' \ + --user "${USERNAME}:${PASSWORD}" | jq diff --git a/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh new file mode 100644 index 0000000000..70c0034609 --- /dev/null +++ b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +USERNAME=admin +PASSWORD={oc-examples-password} +API_PATH="ocs/v2.php/apps/notifications/api/v1/notifications" +SERVER_URI="{oc-examples-server-url}" + +# Get response in XML format +curl '$SERVER_URI/$API_PATH/' \ + --user "${USERNAME}:${PASSWORD}" + +# Get response in JSON format +curl '$SERVER_URI/$API_PATH?format=json' \ + --user "${USERNAME}:${PASSWORD}" | jq + diff --git a/modules/developer_manual/nav.adoc b/modules/developer_manual/nav.adoc index bf8471876f..1ab7f7439a 100644 --- a/modules/developer_manual/nav.adoc +++ b/modules/developer_manual/nav.adoc @@ -22,6 +22,7 @@ *** xref:core/apis/index.adoc[Available APIs] **** xref:core/apis/externalapi.adoc[The External API] **** OCS +***** xref:core/apis/ocs/notifications/ocs-endpoint-v1.adoc[The OCS Notifications API (v1)] ***** xref:core/apis/ocs-capabilities.adoc[The OCS REST API] ***** xref:core/apis/ocs-recipient-api.adoc[The OCS Recipient API] ***** xref:core/apis/ocs-share-api.adoc[The OCS Share API] diff --git a/modules/developer_manual/pages/app/advanced/notifications.adoc b/modules/developer_manual/pages/app/advanced/notifications.adoc index efadc091d5..775243fdaf 100644 --- a/modules/developer_manual/pages/app/advanced/notifications.adoc +++ b/modules/developer_manual/pages/app/advanced/notifications.adoc @@ -1,8 +1,191 @@ = Notifications -In this document, you can learn how to send notifications in apps. +In this document, you can learn how to: -== Sending Notifications +* xref:create-a-new-notification[Create a notification] +* xref:mark-a-notification[Mark a notification] +* xref:prepare-a-notification-for-display[Prepare a notification for display] +* xref:send-notifications[Send notifications] + +== Create a New Notification + +To create a new notification requires the following steps: + +. xref:retrieve-new-notification-object[Retrieve a new notification object from the notification manager] +. xref:set-the-necessary-information-for-the-notification[Set the necessary notification information] +. xref:send-the-notification-back-to-the-manager[Send the notification back to the manager] + +[[retrieve-new-notification-object]] +=== Retrieve a New Notification Object From the Notification Manager + +Grab a new notification object (`\OCP\Notification\INotification`) from the manager (`\OCP\Notification\IManager`). + +[source,php] +---- +getNotificationManager(); +$notification = $manager->createNotification(); +---- + +=== Set the Necessary Information for the Notification + +[source,php] +---- +createAction(); +$acceptAction + ->setLabel('accept') + ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'POST'); + +$declineAction = $notification->createAction(); +$declineAction->setLabel('decline') + ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'DELETE'); + +$notification->setApp('files_sharing') + ->setUser('recipient1') + ->setDateTime(new DateTime()) + ->setObject('remote', '1337') // $type and $id + ->setSubject('remote_share', ['/fancyFolder']) // $subject and $parameters + ->addAction($acceptAction) + ->addAction($declineAction) +; +---- + +TIP: Setting _app_, _user_, _timestamp_, _object_ and _subject_ are mandatory. + +You should not use a translated _subject_, _message_ or _action label_. +Use something like a "_language key_", to avoid length problems with translations in the storage of a notification app. +Translation is done via invocation of your notifier by the manager when the notification is prepared for display. + +=== Send the Notification Back to the Manager + +[source,php] +---- +notify($notification); + +---- +== Mark a Notification + +If the user accepted the share or the share was removed/unshared, we want to remove the notification, because no user action is needed anymore. +To do this, we simply have to call the `markProcessed()` method on the manager with the necessary information on a notification object: + +[source,php] +---- +getNotificationManager(); +$notification + ->setApp('files_sharing') + ->setObject('remote', 1337) + ->setUser('recipient1'); +$manager->markProcessed($notification); +---- + +Only the app name is mandatory, so if you don't set the user, the notification will be marked as processed for all users that have it. + +The following example shows how to mark all notifications for the `files_sharing` app on the object "_remote #1337_" as processed. + +[source,php] +---- +getNotificationManager(); +$notification + ->setApp('files_sharing') + ->setObject('remote', 1337); +$manager->markProcessed($notification); +---- + +Notifications can be marked as _read_, _deleted_, _processed_, or _obsoleted_. +To + + +== Prepare a Notification for Display + +To prepare a notification for display, in `app.php`, register your Notifier (`\OCP\Notification\INotifier`) interface to the manager, using a `\Closure`. + +[source,php] +---- +getNotificationManager(); +$manager->registerNotifier(function() { + return new \OCA\Files_Sharing\Notifier(\OC::$server->getL10NFactory()); +}); +---- + +The manager will execute the closure and then call the `prepare()` method on your notifier. +If the notification is not known by your app, throw an `\InvalidArgumentException`. +However, if it is actually from your app, you must set the parsed _subject_, _message_, and _action_ labels. + +[source,php] +---- +factory = $factory; +} + +/** + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + */ +public function prepare(INotification $notification, $languageCode) { + if ($notification->getApp() !== 'files_sharing') { + // Not my app => throw + throw new \InvalidArgumentException(); + } + + // Read the language from the notification + $l = $this->factory->get('myapp', $languageCode); + + switch ($notification->getSubject()) { + // Deal with known subjects + case 'remote_share': + $notification->setParsedSubject( + (string) $l->t( + 'You received the remote share "%s"', + $notification->getSubjectParameters() + ) + ); + + // Deal with the actions for a known subject + foreach ($notification->getActions() as $action) { + switch ($action->getLabel()) { + case 'accept': + $action->setParsedLabel( + (string) $l->t('Accept') + ); + break; + + case 'decline': + $action->setParsedLabel( + (string) $l->t('Decline') + ); + break; + } + + $notification->addParsedAction($action); + } + return $notification; + break; + + default: + // Unknown subject => Unknown notification => throw + throw new \InvalidArgumentException(); + } +} +---- + +NOTE: Currently, no markup is allowed. + +== Send Notifications To send notifications from your app, requires four steps, these are: diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc new file mode 100644 index 0000000000..ccc6314b88 --- /dev/null +++ b/modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc @@ -0,0 +1,6 @@ += Notifications API + +In this section you will information on ownCloud’s Notifications API, including: + +* xref:core/apis/ocs/notifications/notification-workflow.adoc[The notification workflow] +* xref:core/apis/ocs/notifications/ocs-endpoint-v1.adoc[The OCS API Endpoint (v1)] diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc new file mode 100644 index 0000000000..2baa66fe83 --- /dev/null +++ b/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc @@ -0,0 +1,267 @@ += OCS Notifications API (v1) +:toc: right +:toclevels: 1 +:request-base-path: ocs/v2.php +:2fa-app-url: https://github.com/owncloud/twofactor_totp + +== Prerequisites + +This API requires {2fa-app-url}[the 2-Factor Authentication app] to be installed and enabled. + +== Check Server Capabilities + +In order to find out if notifications is installed and enabled on the server, you can run a request against the capabilities endpoint. + +* Path: `{request-base-path}/cloud/capabilities` +* Method: `GET` + +=== Request Parameters + +[cols="15%,15%,70%",options="header",width=100%] +|=== +|Attribute +|Type +|Description + +|`format` +|string +|The format to return the response in. +It can be either `XML` or `JSON`. +|=== + +=== Returns + +On success, the request returns either an XML (the default) or a JSON response, along with an `HTTP 200 OK` status code, which shows the server’s notifications capabilities. + +=== Example Responses + +[tabs] +==== +JSON:: ++ +-- +[source,json] +---- +include::{examplesdir}core/apis/ocs/notifications/get-server-capabilities-response.json[] +---- +-- + +XML:: ++ +-- +[source,xml] +---- +include::{examplesdir}core/apis/ocs/notifications/get-server-capabilities-response.xml[] +---- +-- +==== + +=== Code Example + +[tabs] +==== +Curl:: ++ +-- +[source,bash] +---- +include::{examplesdir}core/scripts/curl/ocs/notifications/get-server-capabilities.sh[] +---- +-- +==== + +== Get User Notifications + +This endpoint supports retrieving a list of notifications for a user. + +* Path: `{request-base-path}/apps/notifications/api/v1/notifications` +* Method: `GET` + +[TIP] +==== +In order to get a single notification, you can send a `GET` request against the endpoint below. +Note the {id} property at the end of the endpoint. + +[source,console] +---- +{request-base-path}/apps/notifications/api/v1/notifications/{id} +---- +==== + +=== Request Parameters + +[cols="15%,15%,70%",options="header",width=100%] +|=== +|Attribute +|Type +|Description + +|`format` +|string +|The format to return the response in. +It can be either `XML` or `JSON`. +|=== + +=== Returns + +On success, the request returns either an XML (the default) or a JSON response, along with an `HTTP 200 OK` status code, which shows the server’s notifications capabilities. + +=== Example Responses + +==== Response With Notifications + +[tabs] +==== +JSON:: ++ +-- +[source,json] +---- +include::{examplesdir}core/apis/ocs/notifications/get-user-notifications-response.json[] +---- +-- +==== + +==== Response Without Notifications + +[tabs] +==== +JSON:: ++ +-- +[source,json] +---- +include::{examplesdir}core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json[] +---- +-- +==== + +=== Specification + +Optional elements are still set in the array, the value is just empty: + +[options="header"] +|=== +|Type | Empty value +|array | `[]` +|string | `""` +|=== + +==== Notification Element + +[cols="20%,10%,70%",options="header"] +|=== +|Field name +|Type +|Value description + +|`actions` +|array +|(Optional) An array of action elements. + +|`app` +|string +|The name of the app that triggered the notification. + +|`datetime` +|string +|The ISO 8601 date and time of when the notification was published. + +|`link` +|string +|(Optional) A link that should be followed when the subject/message is clicked. + +|`message` +|string +|(Optional) The translated, potentially longer, message that should be presented to the user. + +|`notification_id` +|int +|The unique notification identifier. +It can be used to dismiss a notification. + +|`object_id` +|string +|The ID of the object which the notification is about. +The id can be used in PHP to mark a notification as resolved. + +|`object_type` +|string +|The type of the object which the notification is about. +It can be used in PHP to mark a notification as resolved. + +|`subject` +|string +|The translated short subject that should be presented to the user. + +|`user` +|string +|The user id of the user that receives the notification. +|=== + +==== Action Element + +[cols="20%,10%,70%",options="header"] +|=== +|Field name +|Type +|Value description + +|`label` +|string +|The translated short label of the action/button that should be presented to the user. + +|`link` +|string +|A link that should be followed when the action is performed/clicked. + +|`primary` +|bool +|If the action is the primary action for the notification or not. + +|`type` +|string +|The HTTP method that should be used for the request against the link. +It can be one of `GET`, `POST`, or `DELETE`. +|=== + +=== Code Example + +[tabs] +==== +Curl:: ++ +-- +[source,bash] +---- +include::{examplesdir}core/scripts/curl/ocs/notifications/get-user-notifications.sh[] +---- +-- +==== + +NOTE: If the HTTP status code is `204` (No Content), you can slow down the polling to once per hour. +This status code means that there is no app that can generate notifications. + +== Delete a User Notification + +To delete a notification, send a `DELETE` request against `{request-base-path}/apps/notifications/api/v1/notifications/{id}` + +* Path: `{request-base-path}/apps/notifications/api/v1/notifications/{id}` +* Method: `DELETE` + +=== Request Parameters + +[cols="15%,15%,70%",options="header",width=100%] +|=== +|Attribute +|Type +|Description + +|`id` +|integer +|The id of the notification to delete. +|=== + +=== Returns + +On success, the request returns either an {http-status-codes-base-url}/100[HTTP 100 Continue] status code, and no response body. diff --git a/site.yml b/site.yml index d66ea334b2..4fc40f1054 100644 --- a/site.yml +++ b/site.yml @@ -60,6 +60,7 @@ asciidoc: occ-command-example-prefix: 'sudo -u www-data php occ' occ-command-example-prefix-no-sudo: 'php occ' php-supported-versions-url: https://secure.php.net/supported-versions.php + http-status-codes-base-url: https://developer.mozilla.org/en-US/docs/Web/Status recommended-php-version: 7.3 std-port-http: 8080 std-port-memcache: 11211