From b5f89baf388c03d3e3b6ec1e2245633784a60775 Mon Sep 17 00:00:00 2001 From: Benjamin Brahmer Date: Sat, 8 May 2021 14:34:58 +0200 Subject: start new documentation Signed-off-by: Benjamin Brahmer --- docs/README.md | 13 - docs/explore/README.md | 46 -- docs/externalapi/External-Api.md | 816 ----------------------------------- docs/externalapi/Legacy.md | 782 --------------------------------- docs/faq/README.md | 107 ----- docs/feedcss/README.md | 16 - docs/install.md | 90 ---- docs/maintenance.md | 25 -- docs/plugins/README.md | 206 --------- docs/updateInterval/README.md | 10 - documentation/docs/index.md | 5 + documentation/mkdocs.yml | 3 + old-docs/README.md | 13 + old-docs/explore/README.md | 46 ++ old-docs/externalapi/External-Api.md | 816 +++++++++++++++++++++++++++++++++++ old-docs/externalapi/Legacy.md | 782 +++++++++++++++++++++++++++++++++ old-docs/faq/README.md | 107 +++++ old-docs/feedcss/README.md | 16 + old-docs/install.md | 90 ++++ old-docs/maintenance.md | 25 ++ old-docs/plugins/README.md | 206 +++++++++ old-docs/updateInterval/README.md | 10 + 22 files changed, 2119 insertions(+), 2111 deletions(-) delete mode 100644 docs/README.md delete mode 100644 docs/explore/README.md delete mode 100644 docs/externalapi/External-Api.md delete mode 100644 docs/externalapi/Legacy.md delete mode 100644 docs/faq/README.md delete mode 100644 docs/feedcss/README.md delete mode 100644 docs/install.md delete mode 100644 docs/maintenance.md delete mode 100644 docs/plugins/README.md delete mode 100644 docs/updateInterval/README.md create mode 100644 documentation/docs/index.md create mode 100644 documentation/mkdocs.yml create mode 100644 old-docs/README.md create mode 100644 old-docs/explore/README.md create mode 100644 old-docs/externalapi/External-Api.md create mode 100644 old-docs/externalapi/Legacy.md create mode 100644 old-docs/faq/README.md create mode 100644 old-docs/feedcss/README.md create mode 100644 old-docs/install.md create mode 100644 old-docs/maintenance.md create mode 100644 old-docs/plugins/README.md create mode 100644 old-docs/updateInterval/README.md diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 62c2dac07..000000000 --- a/docs/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Documentation - - -As a developer you can interact with the News app in the following ways: - -* [Use the API for syncing and updating feeds](externalapi/) -* [Write plugins](plugins/) -* [Add custom CSS for feeds](feedcss/) -* [Customize the explore section](explore/) - - -The News app uses [FeedIO](https://github.com/alexdebril/feed-io) for parsing feeds and full text feeds. FeedIO is a fantastic library so if you contribute or fix bugs, please consider **contributing your changes** back to the library to help others :) - diff --git a/docs/explore/README.md b/docs/explore/README.md deleted file mode 100644 index be77a2a85..000000000 --- a/docs/explore/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Explore Feeds Section - -The News app uses a JSON format to display the feeds in the explore feed section. - -The feeds are stored in a JSON file in the [explore](https://github.com/nextcloud/news/tree/master/lib/Explore/feeds) folder and are localized based on their filename, meaning: feeds.en.json will only be shown for English localized Nextcloud installations, feeds.de.json only for German installations. If no other localization exists, the feeds.en.json will be taken. - -You can also provide your own explore service. - -## Format - -The file has the following format: -```js -{ - "Nextcloud": [{ // category - "title": "Nextcloud Planet", - "favicon": "https://nextcloud.com/contribook/main/images/nextcloud/100.png", - "url": "https://nextcloud.com/news/", - "feed": "https://nextcloud.com/feed/", - "description": "Nextcloud Planet is a blog feed aggregator", - "votes": 1000 - }], -} -``` - -To ease the pain of constructing the JSON object, you can use a nextcloud command to automatically create it: - - php ./occ news:generate-explore https://path.com/to/feed.rss - -By passing a second parameter you can set the vote count which determines the sorting on the explore page: - - php ./occ news:generate-explore https://path.com/to/feed.rss 1000 - -You can paste the output directly into the appropriate json file but you may need to add additional categories and commas - -## Using A Webservice Instead of JSON Files - -If you are using the News app in your company/community it might be interesting to offer your users a bunch of easily to discover default feeds. You could also create a website where people can add and up-vote news feeds like bigger cloud feed readers like Feedly do it or even convert their APIs into a service for the News app (if someone wants to provide one for the News app, feel free to contact us by creating an issue in the bug tracker). - -The URL should be a path to a directory which contains a JSON file in the format of **feeds.LANG_CODE.json** where LANG_CODE is a two character language code (e.g. **en** or **de**). - -For example entering the URL **https://domain.com/directory** as explore URL will produce the following request for German users: - - GET https://domain.com/directory/feeds.de.json - - -**Do not forget to implement [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) in your API, otherwise the request will fail!** \ No newline at end of file diff --git a/docs/externalapi/External-Api.md b/docs/externalapi/External-Api.md deleted file mode 100644 index 1848fe5b3..000000000 --- a/docs/externalapi/External-Api.md +++ /dev/null @@ -1,816 +0,0 @@ -# External API v2 (Draft) - -The **News app** offers a RESTful API which can be used to sync folders, feeds and items. The API also supports [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) which means that you can access the API from your browser using JavaScript. - -In addition, an updater API is exposed which enables API users to run feed updates in parallel using a REST API or ownCloud console API. - -## Conventions -This document uses the following conventions: - -* Object aliases as comments -* Error objects are omitted - -### Object Aliases As Comments - -In order to only specify the JSON objects once, comments are used to alias them. - -There are two types of aliases: -* Objects -* Object arrays - -**Objects**: -```js -{ - "folder": { /* folder object */ }, -} -``` - -means that the folder attributes will be listed inside the **folder** object - -**Object arrays**: -```js -{ - "folders": [ /* array of folder objects */ ], -} -``` - -means that folder objects will be listed inside the **folders** array. - -### Error Objects Are Omitted - -This means that the error object will not be explicitly shown in the examples. All HTTP 400 response status codes contain an error object: - -```json -{ - "error": { - "code": 1, - "message": "error message" - } -} -``` - -## API Stability Contract - -The API level will **change** if the following occurs: - -* a required HTTP request header is added -* a required request parameter is added -* a field of a response object is removed -* a field of a response object is changed to a different datatype -* an HTTP response header is removed -* an HTTP response header is changed to a different datatype -* the meaning of an API call changes (e.g. /sync will not sync any more but show a sync timestamp) - -The API level will **not change** if: - -* a new HTTP response header is added -* an optional new HTTP request header is added -* a new response parameter is added (e.g. each item gets a new field "something": 1) -* The order of the JSON attributes is changed on any level (e.g. "id":3 is not the first field anymore, but the last) - -You have to design your app with these things in mind!: - -* **Don't depend on the order** of object attributes. In JSON it does not matter where the object attribute is since you access the value by name, not by index -* **Don't limit your app to the currently available attributes**. New ones might be added. If you don't handle them, ignore them -* **Use a library to compare versions**, ideally one that uses semantic versioning - -## Request Format -The base URL for all calls is: - - https://yourowncloud.com/index.php/apps/news/api/v2 - -Unless an absolute Url is specified, the relative Urls in the Specification are appended to this url. To access the route **/sync** for instance you'd use the following url: - - https://yourowncloud.com/index.php/apps/news/api/v2/sync - -The required request headers are: -* **Accept**: application/json - -Any request method except GET: -* **Content-Type**: application/json; charset=utf-8 - -Any route that allows caching: -* **If-None-Match**: an Etag, e.g. 6d82cbb050ddc7fa9cbb659014546e59. If no previous Etag is known, this header should be omitted - -The request body is either passed in the URL in case of a **GET** request (e.g.: **?foo=bar&index=0**) or as JSON, e.g.: - -```json -{ - "foo": "bar", - "index": 0 -} -``` - -**Note**: The current Etag implementation contains a unix timestamp in milliseconds. This is an implementation detail and you should not rely on it. - -### API Level Detection -Check the [API level route](#api-level) - -### Authentication -Because REST is stateless you have to re-send user and password each time you access the API. Therefore running ownCloud **with SSL is highly recommended** otherwise **everyone in your network can log your credentials**. - -Credentials are passed as an HTTP header using [HTTP basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side): - - Authorization: Basic $CREDENTIALS - -where $CREDENTIALS is: - - base64(USER:PASSWORD) - -This authentication/authorization method will be the recommended default until core provides an easy way to do OAuth - -**Note**: Even if login cookies are sent back to your client, they will not be considered for authentication. - -## Response Format -The status codes are not always provided by the News app itself, but might also be returned because of ownCloud internal errors. - -The following status codes can always be returned by ownCloud: -* **401**: The provided credentials to log into ownCloud are invalid. -* **403**: The user is not allowed to access the route. This can happen if for instance of only users in the admin group can access the route and the user is not in it. -* **404**: The route can not be found or the resource does not exist. Can also happen if for instance you are trying to delete a folder which does not exist. -* **5xx**: An internal server error occurred. This can happen if the server is in maintenance mode or because of other reasons. - -The following status codes are returned by News: -* **200**: Everything went fine -* **304**: In case the resource was not modified, contains no response body. This means that you can ignore the request since everything is up to date. -* **400**: There was an app related error, check the **error** object if specified -* **409**: Conflict error which means that the resource exists already. Can be returned when updating (**PATCH**) or creating (**POST**) a resource, e.g. a folder - -The response headers are: -* **Content-Type**: application/json; charset=utf-8 -* **Etag**: A string containing a cache header of maximum length 64, e.g. 6d82cbb050ddc7fa9cbb659014546e59. The etag value will be assembled using the number of feeds, folders and the highest last modified timestamp in milliseconds, e.g. 2-3-123131923912392391239. However consider that a detail and dont rely on it. - -The response body is a JSON structure that looks like this, which contains the actual data on the first level. The key is the resource in singular if it's a single resource or plural if its a collection. In case of HTTP 400, an error object is also present to help distinguishing between different error types: - -```json -{ - "error": { - "code": 1, - "message": "error message" - } -} -``` - -* **error**: Only present when an HTTP 400 is returned to help distinguishing between error causes - * **code**: A unique error code - * **message**: A translated error message. The user's configured locale is used. - -In case of an **4xx** or **5xx** error the request was not successful and has to be retried. For instance marking items as read locally and syncing should send the same request again the next time the user syncs in case an error occurred. - -## Security Guidelines -Read the following notes carefully to prevent being subject to security exploits: -* You should always enforce SSL certificate verification and never offer a way to turn it off. Certificate verification is important to prevent MITM attacks which is especially important in the mobile world where users are almost always connected to untrusted networks. In case a user runs a self-signed certificate on his server ask him to either install his certificate on his device or direct him to one of the many ways to sign his certificate for free (most notably letsencrypt.com) -* All string fields in a JSON response **expect an item's body** are **not sanitized**. This means that if you do not escape it properly before rendering you will be vulnerable to [XSS](https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29) attacks -* Basic Auth headers can easily be decrypted by anyone since base64 is an encoding, not an encryption. Therefore only send them if you are accessing an HTTPS website or display an easy to understand warning if the user chooses HTTP -* When creating a feed you can choose to add basic auth authentication credentials. These must be stored in clear text so anyone with access to your database (however they might have achieved it, think of Sql injection) can read them and use them to access the website. You should warn the user about this. -* If you are building a client in JavaScript or are using a link with **target="blank"**, remember to set the **window.opener** property to **null** and/or add a **rel="noreferrer"** to your link to prevent your app from being [target by an XSS attack](https://medium.com/@jitbit/target-blank-the-most-underestimated-vulnerability-ever-96e328301f4c#.wf2ddytbh) - -## Syncing -All routes are given relative to the base API url, e.g.: **/sync** becomes **https://yourowncloud.com/index.php/apps/news/api/v2/sync** - -There are two usecases for syncing: -* **Initial sync**: the user does not have any data at all -* **Syncing local and remote changes**: the user has synced at least once and wants to submit and receive changes - -### Initial Sync -The intial sync happens when a user adds an ownCloud account in your app. In that case you want to download all folders, feeds and unread/starred items. To do this, make the following request: - -* **Method**: GET -* **Route**: /sync -* **Authentication**: [required](#authentication) -* **HTTP headers**: - * **Accept: "application/json"** - -This will return the following status codes: -* **200**: Success - -and the following HTTP headers: -* **Content-Type**: application/json; charset=utf-8 -* **Etag**: A string containing a cache header, maximum size 64 ASCII characters, e.g. 6d82cbb050ddc7fa9cbb659014546e59 - -and the following request body: -```js -{ - "folders": [ /* array of folder objects */ ], - "feeds": [ /* array of feed objects */ ], - "items": [ /* array of item objects */ ] -} -``` - -**Note**: Each object is explained in more detail in a separate section: -* [Folders](#folders) -* [Feeds](#feeds) -* [Items](#items) - - -### Sync Local And Remote Changes -After the initial sync the app has all folders, feeds and items. Now you want to push changes and retrieve updates from the server. To do this, make the following request: - -* **Method**: POST -* **Route**: /sync -* **Authentication**: [required](#authentication) -* **HTTP headers**: - * **Content-Type: "application/json; charset=utf-8"** - * **Accept: "application/json"** - * **If-None-Match: "6d82cbb050ddc7fa9cbb659014546e59"** (Etag from the previous request to the /sync route) - -with the following request body: - -```js -{ - "items": [{ - // read and starred - "id": 5, - "isStarred": false, - "isUnread": true, - "contentHash": "08ffbcf94bd95a1faa6e9e799cc29054" - }, { - // only read - "id": 6, - "isUnread": true, - "contentHash": "09ffbcf94bd95a1faa6e9e799cc29054" - }, { - // only starred - "id": 7, - "isStarred": false, - "contentHash": "18ffbcf94bd95a1faa6e9e799cc29054" - }, /* etc */] -} -``` - -If no items have been read or starred, simply leave the **items** array empty, e.g.: - -```js -{ - "items": [] -} -``` - -The response matches the **GET** call, except there can be two different types of item objects: -* **[Full](#full)**: Contains all attributes -* **[Reduced](#reduced)**: Contains only **id**, **isUnread** and **isStarred** - -The deciding factor whether a full or reduced item object is being returned depends on the contentHash in the request: If the contentHash matches the record in the database a reduced item object is being returned, otherwise a full object is used. Both can occur in the same items array at the same time. - -The idea behind this special handling is that if the contentHash matches the record in the database, the actual item content did not change. Therefore it is enough to know the item status. This greatly reduces the amount sent over the Net which is especially important for mobile apps. - -This also applies to folders and feeds, however the reduced folder and feed objects will only include the **id** element. The deciding factor whether only an id or the full object will be returned is the last modified modified timestamp which is included in the sent etag. - -If you push a list of items to be marked read/starred, there can also be less items in the response than the ones which were initially sent. This means that the item was deleted by the cleanup job and should be removed from the client device. - -For instance let's take a look at the following example. You are **POST**ing the following JSON: -```json -{ - "items": [{ - "id": 5, - "isStarred": false, - "isUnread": true, - "contentHash": "08ffbcf94bd95a1faa6e9e799cc29054" - }, { - "id": 6, - "isUnread": true, - "contentHash": "09ffbcf94bd95a1faa6e9e799cc29054" - }, { - "id": 7, - "isStarred": false, - "contentHash": "18ffbcf94bd95a1faa6e9e799cc29054" - }] -} -``` - -and receive the following output in return: - -```json -{ - "items": [{ - "id": 5, - "isStarred": false, - "isUnread": true - }, { - "id": 6, - "isUnread": true, - "isStarred": false - }] -} -``` - -The item with the **id** **7** is missing from the response. This means that it was deleted on the server. - -For folders and feeds all ids will be returned so you can compare the existing ids with your locally available feeds and folders and remove the difference. - -## Folders -Folders are represented using the following data structure: -```json -{ - "id": 3, - "name": "funny stuff" -} -``` - -The attributes mean the following: -* **id**: 64bit Integer, id -* **name**: Abitrary long text, folder's name - -### Deleting A Folder -To delete a folder, use the following request: -* **Method**: DELETE -* **Route**: /folders/{id} -* **Route Parameters**: - * **{id}**: folder's id -* **Authentication**: [required](#authentication) - -The following response is being returned: - -Status codes: -* **200**: Folder was deleted successfully -* **404**: Folder does not exist - -In case of an HTTP 200, the deleted folder is returned in full in the response, e.g.: - -```js -{ - "folder": { /* folder object */ } -} -``` - -**Note**: Deleted folders will not appear during the next sync so you also need to delete the folder locally afterwards. Folders should only be deleted locally if an HTTP **200** or **404** was returned. - -**Note**: If you delete a folder locally, you should also delete all feeds whose **folderId** attribute matches the folder's **id** attribute and also delete all items whose **feedId** attribute matches the feeds' **id** attribute. This is done automatically on the server and will also be missing on the next request. - -### Creating A Folder -To create a folder, use the following request: -* **Method**: POST -* **Route**: /folders -* **Authentication**: [required](#authentication) - -with the following request body: -```json -{ - "name": "Folder name" -} -``` - -The following response is being returned: - -Status codes: -* **200**: Folder was created successfully -* **400**: Folder creation error, check the error object: - * **code**: 1: folder name is empty - -In case of an HTTP 200, the created or already existing folder is returned in full in the response, e.g.: - -```js -{ - "folder": { /* folder object */ } -} -``` - -### Changing A Folder -The following attributes can be changed on the folder: -* **name** - -To change any number of attributes on a folder, use the following request and provide as much attributes that can be changed as you want: -* **Method**: PATCH -* **Route**: /folders/{id} -* **Route Parameters**: - * **{id}**: folder's id -* **Authentication**: [required](#authentication) - -with the following request body: -```json -{ - "name": "New folder name" -} -``` - -* **name**: Abitrary long text, the folder's name - -The following response is being returned: - -Status codes: -* **200**: Folder was updated successfully -* **400**: Folder update error, check the error object: - * **code**: 1: folder name is empty -* Other ownCloud errors, see [Response Format](#response-format) - -In case of an HTTP 200, the changed or already existing folder is returned in full in the response, e.g.: - -```js -{ - "folder": { /* folder object */ } -} -``` - - -## Feeds -Feeds are represented using the following data structure: - -```json -{ - "id": 4, - "name": "The Oatmeal - Comics, Quizzes, & Stories", - "faviconLink": "http://theoatmeal.com/favicon.ico", - "folderId": 3, - "ordering": 0, - "fullTextEnabled": false, - "updateMode": 0, - "isPinned": true, - "error": { - "code": 1, - "message": "" - } -} -``` - -The attributes mean the following: -* **id**: 64bit Integer, id -* **name**: Abitrary long text, feed's name -* **faviconLink**: Abitrary long text, feed's favicon location, **null** if not found -* **folderId**: 64bit Integer, the feed's folder or **0** in case no folder is specified -* **ordering**: 64bit Integer, overrides the feed's default ordering: - * **0**: Default - * **1**: Oldest on top - * **2**: Newest on top -* **updateMode**: 64bit Integer, describing how item updates are handled: - * **0**: No special behavior - * **1**: If an item is updated, mark it unread -* **isPinned**: Boolean, Used to list certain feeds before others. Feeds are first ordered by their **isPinned** value (true before false) and then by their name in alphabetical order -* **error**: error object, only present if an error occurred: - * **code**: The error code: - * **1**: Error occured during feed update - * **message**: Translated error message depending on the user's configured server locale - - -### Deleting A Feed -To delete a feed, use the following request: -* **Method**: DELETE -* **Route**: /feeds/{id} -* **Route Parameters**: - * **{id}**: feed's id -* **Authentication**: [required](#authentication) - - -The following response is being returned: - -Status codes: -* **200**: Feed was deleted successfully -* **404**: Feed with given id was not found, no error object -* Other ownCloud errors, see [Response Format](#response-format) - - -In case of an HTTP 200, the deleted feed is returned in full in the response, e.g.: - -```js -{ - "feed": { /* feed object */ } -} -``` - -**Note**: Deleted feeds will not appear during the next sync so you also need to delete the feed locally afterwards. Feeds should only be deleted locally if an HTTP **200** or **404** was returned. - -**Note**: If you delete a feed locally, you should also delete all items whose **feedId** attribute matches the feeds' **id** attribute. This is done automatically on the server and will also be missing on the next request. - -### Creating A feed -To create a feed, use the following request: -* **Method**: POST -* **Route**: /feeds -* **Authentication**: [required](#authentication) - - -with the following request body: -```json -{ - "url": "https://feed.url.com", - "name": "Feed name", - "ordering": 0, - "folderId": 3, - "isPinned": true, - "fullTextEnabled": false, - "basicAuthUser": "user", - "basicAuthPassword": "password" -} -``` -* **url**: Abitrary long text, the url needs to have the full schema e.g. https://the-url.com. In case the user omits the schema, prepending **https** is recommended -* **folderId**: 64bit Integer, the feed's folder or **0** in case no folder is specified -* **name (optional)**: Abitrary long text, the feeds name or if not given taken from the RSS/Atom feed -* **basicAuthUser (optional)**: Abitrary long text, if given basic auth headers are sent for the feed -* **basicAuthPassword (optional)**: Abitrary long text, if given basic auth headers are sent for the feed -* **ordering (optional)**: See [Feeds](#feeds) -* **isPinned (optional)**: See [Feeds](#feeds) -* **fullTextEnabled (optional)**: See [Feeds](#feeds) - - -The following response is being returned: - -Status codes: -* **200**: Feed was created successfully -* **400**: Feed creation error, check the **error** object: - * **code**: 1: url is empty - * **code**: 2: malformed xml - * **code**: 3: no feed found for url (e.g. website does not have an RSS or Atom feed or direct link to feed is no feed) - * **code**: 4: feed format not supported (e.g. too old RSS version) - * **code**: 5: ssl issues (e.g. SSL certificate is invalid or php has issues accessing certificates on your server) - * **code**: 6: url can not be found or accessed - * **code**: 7: maximum redirects reached - * **code**: 8: maximum size reached - * **code**: 9: request timed out - * **code**: 10: invalid or missing http basic auth headers - * **code**: 11: not allowed to access the feed (difference here is that the user can be authenticated but not allowed to access the feed) - -In case of an HTTP 200, the created feed is returned in full in the response, e.g.: - -```js -{ - "feed": { /* feed object */ } -} -``` - -**Note**: Because the next sync would also pull in the added feed and items again, the added items will be omitted for saving bandwidth. This also means that after successfully creating a feed you will need to query the [sync route](#sync-local-and-remote-changes) again. - -### Changing A Feed -To change a feed, use the following request: -* **Method**: PATCH -* **Route**: /feeds/{id} -* **Route Parameters**: - * **{id}**: feed's id -* **Authentication**: [required](#authentication) - - -with the following request body: -```json -{ - "url": "https://feed.url.com", - "name": "Feed name", - "ordering": 0, - "folderId": 3, - "isPinned": true, - "fullTextEnabled": false, - "basicAuthUser": "user", - "basicAuthPassword": "password" -} -``` - -All parameters are optional - -* **url (optional)**: Abitrary long text, the url which was entered by the user with the full schema -* **name (optional)**: Abitrary long text, the feeds name or if not given taken from the RSS/Atom feed -* **basicAuthUser (optional)**: Abitrary long text, if given basic auth headers are sent for the feed -* **basicAuthPassword (optional)**: Abitrary long text, if given basic auth headers are sent for the feed -* **ordering (optional)**: See [feeds](#Feeds) -* **isPinned (optional)**: See [feeds](#Feeds) -* **fullTextEnabled (optional)**: See [feeds](#Feeds) -* **folderId (optional)**: 64bit Integer, the feed's folder or **0** in case no folder is specified - -The following response is being returned: - -Status codes: -* **200**: Feed was changed successfully -* **400**: Feed creation error, check the error object: - * **code**: 1: url is empty - * **code**: 2: malformed xml - * **code**: 3: no feed found for url (e.g. website does not have an RSS or Atom feed or direct link to feed is no feed) - * **code**: 4: feed format not supported (e.g. too old RSS version) - * **code**: 5: ssl issues (e.g. SSL certificate is invalid or php has issues accessing certificates on your server) - * **code**: 6: url can not be found or accessed - * **code**: 7: maximum redirects reached - * **code**: 8: maximum size reached - * **code**: 9: request timed out - * **code**: 10: invalid or missing http basic auth headers - * **code**: 11: not allowed to access the feed (difference here is that the user can be authenticated but not allowed to access the feed) -* Other ownCloud errors, see [Response Format](#response-format) - -In case of an HTTP 200, the changed feed is returned in full in the response, e.g.: - -```js -{ - "feed": { /* feed object */ } -} -``` - -**Note**: Because the next sync would also pull in the changed feed and items again, the added or updated items will be omitted for saving bandwidth. This also means that after successfully updating a feed you will need to query the [sync route](#sync-local-and-remote-changes) again. - -## Items - -Items can occur in two different formats: - -* Full -* Reduced - -The attributes mean the following: -* **id**: 64bit Integer, id -* **url**: Abitrary long text, location of the online resource -* **title**: Abitrary long text, item's title -* **author**: Abitrary long text, name of the author/authors -* **publishedAt**: String representing an ISO 8601 DateTime object, when the item was published -* **lastModifiedAt**: String representing an ISO 8601 DateTime object, when the item was last modified -* **enclosure**: An enclosure object or null if none is present - * **mimeType**: Abitrary long text, the enclosures mime type - * **url**: Abitrary long text, location of the enclosure -* **body**: Abitrary long text, **sanitized (meaning: does not have to be escape)**, contains the item's content -* **feedId**: 64bit Integer, the item's feed it belongs to -* **isUnread**: Boolean, true if unread, false if read -* **isStarred**: Boolean, true if starred, false if not starred -* **fingerprint**: 64 ASCII characters, hash that is used to determine if an item is the same as an other one. The following behavior should be implemented: - * Items in a stream (e.g. All items, folders, feeds) should be filtered so that no item with the same fingerprint is present. - * When marking an item read, all items with the same fingerprint should also be marked as read. -* **contentHash**: 64 ASCII characters, used to determine if the item on the client is up to or out of date. The difference between the contentHash and the fingerprint attribute is that contentHash is always calculated from a stable set of attributes (title, author, url, enclosure, body) whereas the fingerprint is calculated from a set of attributes depending on the feed. The reason for this is that some feeds use different URLs for the same article so you would not want to include the URL as uniqueness criteria in that case. If the fingerprint was used for syncing however, an URL update would never reach the client. - -### Full -A full item contains the full content: -```json -{ - "id": 5, - "url": "http://grulja.wordpress.com/2013/04/29/plasma-nm-after-the-solid-sprint/", - "title": "Plasma-nm after the solid sprint", - "author": "Jan Grulich (grulja)", - "publishedAt": "2005-08-15T15:52:01+0000", - "lastModifiedAt": "2005-08-15T15:52:01+0000", - "enclosure": { - "mimeType": "video/webm", - "url": "http://video.webmfiles.org/elephants-dream.webm" - }, - "body": "

At first I have to say...

", - "feedId": 4, - "isUnread": true, - "isStarred": true, - "fingerprint": "08ffbcf94bd95a1faa6e9e799cc29054", - "contentHash": "18ffbcf94bd95a1faa6e9e799cc29054" -} -``` - -### Reduced -A reduced item only contains the item status: -```json -{ - "id": 5, - "isUnread": true, - "isStarred": true -} -``` - -## Updater -Instead of using the built in, slow cron updater you can use the parallel update API to update feeds. The API can be accessed through REST or ownCloud console API. - -The API should be used in the following way: - -* Clean up before the update -* Get all feeds and user ids -* For each feed and user id, run the update -* Clean up after the update - -The reference [implementation in Python](https://github.com/owncloud/news-updater) should give you a good idea how to design your own updater. - -If the REST API is used, Authorization is required via Basic Auth and the user needs to be in the admin group. -If the ownCloud console API is used, no authorization is required. - -### Clean Up Before Update -This is used to clean up the database. It deletes folders and feeds that are marked for deletion. - -**Console API**: - - php -f /path/to/owncloud/occ news:updater:before-update - -**REST API**: - -* **Method**: GET -* **Route**: /updater/before-update -* **Authentication**: [admin](#authentication) - -### Get All Feeds And User Ids -This call returns pairs of feed ids and user ids. - -**Console API**: - - php -f /path/to/owncloud/occ news:updater:all-feeds - -**REST API**: - -* **Method**: GET -* **Route**: /updater/all-feeds -* **Authentication**: [admin](#authentication) - - -Both APIs will return the following response body or terminal output: - -```js -{ - "updater": [{ - "feedId": 3, - "userId": "john" - }, /* etc */] -} -``` - -### Update A User's Feed -After all feed ids and user ids are known, feeds can be updated in parallel. - -**Console API**: -* **Positional Parameters**: - * **{feedId}**: the feed's id - * **{userId}**: the user's id - - - php -f /path/to/owncloud/occ news:updater:update-feed {feedId} {userId} - -**REST API**: - -* **Method**: GET -* **Route**: /updater/update-feed?feedId={feedId}&userId={userId} -* **Route Parameters**: - * **{feedId}**: the feed's id - * **{userId}**: the user's id -* **Authentication**: [admin](#authentication) - - -### Clean Up After Update -This is used to clean up the database. It removes old read articles which are not starred. - -**Console API**: - - php -f /path/to/owncloud/occ news:updater:after-update - -**REST API**: - -* **Method**: GET -* **Route**: /updater/after-update -* **Authentication**: [admin](#authentication) - -## Meta Data -The retrieve meta data about the app, use the following request: - -* **Method**: GET -* **Route**: / -* **Authentication**: [required](#authentication) - - -The following response is being returned: - -Status codes: -* **200**: Meta data accessed successfully - -In case of an HTTP 200, the the following response is returned: - -```json -{ - "version": "9.0.0", - "issues": { - "improperlyConfiguredCron": false - }, - "user": { - "userId": "john", - "displayName": "John Doe", - "avatar": { - "data": "asdiufadfasdfjlkjlkjljdfdf", - "mime": "image/jpeg" - } - } -} -``` - -The attributes mean the following: -* **version**: Abitrary long text, News app version -* **issues**: An object containing a dictionary of issues which need to be displayed to the user: - * **improperlyConfiguredCron**: Boolean, if true this means that no feed updates are run on the server because the updater is misconfigured -* **user**: user information: - * **userId**: Abitrary long text, the login name - * **displayName**: Abitrary long text, the full name like it's displayed in the web interface - * **avatar**: an avatar object, null if none is set - * **data**: Abitrary long text, the user's image encoded as base64 - * **mime**: Abitrary long text, avatar mimetype - - -## API Level -To find out which API levels are supported, make a request to the following route: - -* **Method**: GET -* **Route**: https://yourowncloud.com/index.php/apps/news/api -* **Authentication**: none - -The following response is being returned: - -Status codes: -* **200**: The supported API levels can be parsed from the response -* **404**: The user is either running a version prior to **8.8.0** or the News app is disabled or not installed. - -In case of an HTTP 200, the supported API levels are returned as JSON, e.g.: -```json -{ - "apiLevels": ["v1-2", "v2"] -} -``` - -**apiLevels**: An array of arbitrary long strings, strings represent the the supported api levels which directly correspond to the first fragment after the **/api/** Url fragment. - -To find out if a user is running an older News version than **8.8.0**, make a request to the following route: - -* **Method**: GET -* **Route**: https://yourowncloud.com/index.php/apps/news/api/v1-2/version -* **Authentication**: [required](#authentication) - -Status codes: -* **200**: Only the v1-2 API level is supported -* **404**: The News app is disabled or not installed. - -Since these calls can be expensive you could first try to make a call to the [sync route](#syncing) and if it fails with an HTTP **404** run the API level detection. Of course the choice which APIs you are going to support is entirely yours and you could also hard require v2. - -**Note**: Future News app versions **may remove** the v1-2 API level depending on how widespread the adoption has become. You should therefore always make sure which API levels are actually supported. diff --git a/docs/externalapi/Legacy.md b/docs/externalapi/Legacy.md deleted file mode 100644 index 8afb6f9c7..000000000 --- a/docs/externalapi/Legacy.md +++ /dev/null @@ -1,782 +0,0 @@ -# External API v1-2 (Legacy) - -The **News app 1.2** offers a RESTful API - -## API stability contract - -The API level will **change** if the following occurs: - -* A field of an object is removed -* A field of an object has a different datatype -* The meaning of an API call changes - -The API level will **not change** if: - -* The app version is changed (e.g. 4.0.1.2 instead of 4.0 or 4.001) -* A new attribute is added (e.g. each item gets a new field "something": 1) -* The order of the JSON attributes is changed on any level (e.g. "id":3 is not the first field anymore, but the last) - -You have to design your app with these things in mind!: - -* **Don't depend on the order of object attributes. In JSON it does not matter where the object attribute is since you access the value by name, not by index** -* **Don't limit your app to the currently available attributes. New ones might be added. If you don't handle them, ignore them** -* **Use a library to compare versions, ideally one that uses semantic versioning** - -## Authentication & Basics -Because REST is stateless you have to send user and password each time you access the API. Therefore running Nextcloud **with SSL is highly recommended** otherwise **everyone in your network can log your credentials**. - -The base URL for all calls is: - - https://yournextcloud.com/index.php/apps/news/api/v1-2/ - -All defined routes in the Specification are appended to this url. To access all feeds for instance use this url: - - https://yournextcloud.com/index.php/apps/news/api/v1-2/feeds - -Credentials need to be passed as an HTTP header using [HTTP basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side): - - Authorization: Basic $CREDENTIALS - -where $CREDENTIALS is: - - base64(USER:PASSWORD) - -## How To Sync -This is a small overview over how you should sync your articles with the Nextcloud News app. For more fine-grained details about the API see further down. - -All routes are given relative to the base API url (e.g.: https://yournextcloud.com/index.php/apps/news/api/v1-2) - -### Initial Sync -The intial sync happens, when a user adds a Nextcloud account in your app. In that case you should fetch all feeds, folders and unread or starred articles from the News app. Do not fetch all articles, not only because it syncs faster, but also because the user is primarily interested in unread articles. To fetch all unread and starred articles, you must call 4 routes: - -* **unread articles**: GET /items?type=3&getRead=false&batchSize=-1 -* **starred articles**: GET /items?type=2&getRead=true&batchSize=-1 -* **folders**: GET /folders -* **feeds**: GET /feeds - -The JSON response structures can be viewed further down. - -### Syncing -When syncing, you want to push read/unread and starred/unstarred items to the server and receive new and updated items, feeds and folders. To do that, call the following routes: - -* **Notify the News app of unread articles**: PUT /items/unread/multiple {"items": [1, 3, 5] } -* **Notify the News app of read articles**: PUT /items/read/multiple {"items": [1, 3, 5]} -* **Notify the News app of starred articles**: PUT /items/starred/multiple {"items": [{"feedId": 3, "guidHash": "adadafasdasd1231"}, ...]} -* **Notify the News app of unstarred articles**: PUT /items/unstarred/multiple {"items": [{"feedId": 3, "guidHash": "adadafasdasd1231"}, ...]} -* **Get new folders**: GET /folders -* **Get new feeds**: GET /feeds -* **Get new items and modified items**: GET /items/updated?lastModified=12123123123&type=3 - - -## Accessing API from a web application - -**News 1.401** implements CORS which allows web applications to access the API. **To access the API in a webapp you need to send the correct authorization header instead of simply putting auth data into the URL!**. An example request in jQuery would look like this: - -```js -$.ajax({ - type: 'GET', - url: 'https://yournextcloud.com/index.php/apps/news/api/v1-2/version', - contentType: 'application/json', - success: function (response) { - // handle success - }, - error: function () { - // handle errors - }, - beforeSend: function (xhr) { - var username = 'john'; - var password = 'doe'; - var auth = btoa(username + ':' + password); - xhr.setRequestHeader('Authorization', 'Basic ' + auth); - } -}); -``` -An example with AngularJS would look like this: -```js -angular.module('YourApp', []) - .config(['$httpProvider', '$provide', function ($httpProvider, $provide) { - $provide.factory('AuthInterceptor', ['Credentials', '$q', function (Credentials, $q) { - return { - request: function (config) { - // only set auth headers if url matches the api url - if(config.url.indexOf(Credentials.url) === 0) { - auth = btoa(Credentials.userName + ':' + Credentials.password); - config.headers['Authorization'] = 'Basic ' + auth; - } - return config || $q.when(config); - } - }; - }]); - $httpProvider.interceptors.push('AuthInterceptor'); - }]) - .factory('Credentials', function () { - return { - userName: 'user', - password: 'password', - url: 'https://yournextcloud.com/index.php/apps/news/api' - }; - }) - .run(['$http', function($http) { - $http({ - method: 'GET', - url: 'https://yournextcloud.com/index.php/apps/news/api/v1-2/version' - }).success(function (data, status, header, config) { - // handle success - }).error(function (data, status, header, config) { - // handle error - }); - }]); -``` - -## Input -In general the input parameters can be in the URL or request body, the App Framework doesnt differentiate between them. - -So JSON in the request body like: -```jsonc -{ - "id": 3 -} -``` -will be treated the same as - - /?id=3 - -It is recommended though that you use the following convention: - -* **GET**: parameters in the URL -* **POST**: parameters as JSON in the request body -* **PUT**: parameters as JSON in the request body -* **DELETE**: parameters as JSON in the request body - -## Output -The output is JSON. - -# Folders -## Get all folders - -* **Status**: Implemented -* **Method**: GET -* **Route**: /folders -* **Parameters**: none -* **Returns**: -```jsonc -{ - "folders": [ - { - "id": 4, - "name": "Media" - }, // etc - ] -} -``` - -## Create a folder -Creates a new folder and returns a new folder object - -* **Status**: Implemented -* **Method**: POST -* **Route**: /folders -* **Parameters**: -```jsonc -{ - "name": "folder name" -} -``` -* **Return codes**: - * **HTTP 409**: If the folder exists already - * **HTTP 422**: If the folder name is invalid (for instance empty) -* **Returns**: -```jsonc -{ - "folders": [ - { - "id": 4, - "name": "Media" - } - ] -} -``` - -## Delete a folder -Deletes a folder with the id folderId and all the feeds it contains - -* **Status**: Implemented -* **Method**: DELETE -* **Route**: /folders/{folderId} -* **Parameters**: none -* **Return codes**: - * **HTTP 404**: If the folder does not exist -* **Returns**: nothing - -## Rename a folder -Only the name can be updated - -* **Status**: Implemented -* **Method**: PUT -* **Route**: /folders/{folderId} -* **Parameters**: -```jsonc -{ - "name": "folder name" -} -``` -* **Return codes**: - * **HTTP 409**: If the folder name does already exist - * **HTTP 404**: If the folder does not exist - * **HTTP 422**: If the folder name is invalid (for instance empty) -* **Returns**: nothing - -## Mark items of a folder as read - -* **Status**: Implemented -* **Method**: PUT -* **Route**: /folders/{folderId}/read -* **Parameters**: -```jsonc -{ - // mark all items read lower than equal that id - // this is mean to prevent marking items as read which the client/user does not yet know of - "newestItemId": 10 -} -``` -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: nothing - -# Feeds - -## Sanitation - -The following attributes are **not sanitized** meaning: including them in your web application can lead to XSS: - -* **title** -* **link** - -## Get all feeds - -* **Status**: Implemented -* **Method**: GET -* **Route**: /feeds -* **Parameters**: none -* **Returns**: -```jsonc -{ - "feeds": [ - { - "id": 39, - "url": "http://feeds.feedburner.com/oatmealfeed", - "title": "The Oatmeal - Comics, Quizzes, & Stories", - "faviconLink": "http://theoatmeal.com/favicon.ico", - "added": 1367063790, - "folderId": 4, - "unreadCount": 9, - "ordering": 0, // 0 means no special ordering, 1 means oldest first, 2 newest first, new in 5.1.0 - "link": "http://theoatmeal.com/", - "pinned": true // if a feed should be sorted before other feeds, added in 6.0.3, - "updateErrorCount": 0, // added in 8.6.0, 0 if no errors occured during the last update, - // otherwise is incremented for each failed update. - // Once it reaches a threshold, a message should be displayed to the user - // indicating that the feed has failed to update that many times. - // The webapp displays the message after 50 failed updates - "lastUpdateError": "error message here" // added in 8.6.0, empty string or null if no update - // error happened, otherwise contains the last update error message - }, // etc - ], - "starredCount": 2, - "newestItemId": 3443 // only sent if there are items -} -``` - -## Create a feed -Creates a new feed and returns the feed - -* **Status**: Implemented -* **Method**: POST -* **Route**: /feeds -* **Parameters**: -```jsonc -{ - "url": "http:\/\/www.cyanogenmod.org\/wp-content\/themes\/cyanogenmod\/images\/favicon.ico", - "folderId": 81 // id of the parent folder, null for root -} -``` -* **Return codes**: - * **HTTP 409**: If the feed exists already - * **HTTP 422**: If the feed cant be read (most likely contains errors) -* **Returns**: -```jsonc -{ - "feeds": [ - { - "id": 39, - "url": "http://feeds.feedburner.com/oatmealfeed", - "title": "The Oatmeal - Comics, Quizzes, & Stories", - "faviconLink": "http://theoatmeal.com/favicon.ico", - "added": 1367063790, - "folderId": 4, - "unreadCount": 9, - "ordering": 0, // 0 means no special ordering, 1 means oldest first, 2 newest first, new in 5.1.0 - "link": "http://theoatmeal.com/", - "pinned": true // if a feed should be sorted before other feeds, added in 6.0.3 - } - ], - "newestItemId": 23 // only sent if there are items -} -``` - -## Delete a feed -Deletes a feed with the id feedId and all of its items - -* **Status**: Implemented -* **Method**: DELETE -* **Route**: /feeds/{feedId} -* **Parameters**: none -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: nothing - -## Move a feed to a different folder - -* **Status**: Implemented -* **Method**: PUT -* **Route**: /feeds/{feedId}/move -* **Parameters**: -```jsonc -{ - "folderId": null // id of the parent folder, null for root -} -``` -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: nothing - -## Rename a feed - -* **Status**: Implemented in 1.807 -* **Method**: PUT -* **Route**: /feeds/{feedId}/rename -* **Parameters**: -```jsonc -{ - "feedTitle": "New Title" -} -``` -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: nothing - -## Mark items of a feed as read - -* **Status**: Implemented -* **Method**: PUT -* **Route**: /feeds/{feedId}/read -* **Parameters**: -```jsonc -{ - // mark all items read lower than equal that id - // this is mean to prevent marking items as read which the client/user does not yet know of - "newestItemId": 10 -} -``` -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: nothing - - -# Items - -## Sanitation - -The following attributes are **not sanitized** meaning: including them in your web application can lead to XSS: - -* **title** -* **author** -* **url** -* **enclosureMime** -* **enclosureLink** -* **mediaThumbnail** -* **mediaDescription** - -## Get items -* **Status**: Implemented -* **Method**: GET -* **Route**: /items -* **Parameters**: -```jsonc -{ - "batchSize": 10, // the number of items that should be returned, defaults to -1, new in 5.2.3: -1 returns all items - "offset": 30, // only return older (lower than equal that id) items than the one with id 30 - "type": 1, // the type of the query (Feed: 0, Folder: 1, Starred: 2, All: 3) - "id": 12, // the id of the folder or feed, Use 0 for Starred and All - "getRead": true, // if true it returns all items, false returns only unread items - "oldestFirst": false // implemented in 3.002, if true it reverse the sort order -} -``` -* **Returns**: -```jsonc -{ - "items": [ - { - "id": 3443, - "guid": "http://grulja.wordpress.com/?p=76", - "guidHash": "3059047a572cd9cd5d0bf645faffd077", - "url": "http://grulja.wordpress.com/2013/04/29/plasma-nm-after-the-solid-sprint/", - "title": "Plasma-nm after the solid sprint", - "author": "Jan Grulich (grulja)", - "pubDate": 1367270544, - "body": "

At first I have to say...

", - "enclosureMime": null, - "enclosureLink": null, - "mediaThumbnail": null, // new in 14.1.4-rc1 - "mediaDescription": null, // new in 14.1.4-rc1 - "feedId": 67, - "unread": true, - "starred": false, - "rtl": false, // new in 6.0.2 - "lastModified": 1367273003, - "fingerprint": "aeaae2123" // new in 8.4.0 hash over title, enclosures, body and url. Same fingerprint means same item and it's advised to locally mark the other one read as well and filter out duplicates in folder and all articles view - }, // etc - ] -} -``` - -### Example -Autopaging would work like this: - -* Get the **first 20** items from a feed with **id 12** - -**GET /items**: -```jsonc -{ - "batchSize": 20, - "offset": 0, - "type": 1, - "id": 12, - "getRead": false -} -``` - -The item with the lowest item id is 43. - -* Get the next **20** items: **GET /items**: - -```jsonc -{ - "batchSize": 20, - "offset": 43, - "type": 1, - "id": 12, - "getRead": false -} -``` - - -## Get updated items -This is used to stay up to date. - -* **Status**: Implemented -* **Method**: GET -* **Route**: /items/updated -* **Parameters**: -```jsonc -{ - "lastModified": 123231, // returns only items with a lastModified timestamp >= than this one - // this may also return already existing items whose read or starred status - // has been changed - "type": 1, // the type of the query (Feed: 0, Folder: 1, Starred: 2, All: 3) - "id": 12 // the id of the folder or feed, Use 0 for Starred and All -} -``` -* **Returns**: -```jsonc -{ - "items": [ - { - "id": 3443, - "guid": "http://grulja.wordpress.com/?p=76", - "guidHash": "3059047a572cd9cd5d0bf645faffd077", - "url": "http://grulja.wordpress.com/2013/04/29/plasma-nm-after-the-solid-sprint/", - "title": "Plasma-nm after the solid sprint", - "author": "Jan Grulich (grulja)", - "pubDate": 1367270544, - "body": "

At first I have to say...

", - "enclosureMime": null, - "enclosureLink": null, - "feedId": 67, - "unread": true, - "starred": false, - "lastModified": 1367273003, - "fingerprint": "aeaae2123" // new in 8.4.0 hash over title, enclosures, body and url. Same fingerprint means same item and it's advised to locally mark the other one read as well and filter out duplicates in folder and all articles view - }, // etc - ] -} -``` - -## Mark an item as read -* **Status**: Implemented -* **Method**: PUT -* **Route**: /items/{itemId}/read -* **Parameters**: none -* **Return codes**: - * **HTTP 404**: If the item does not exist -* **Returns**: nothing - -## Mark multiple items as read -* **Status**: Implemented in 1.2 -* **Method**: PUT -* **Route**: /items/read/multiple -* **Parameters**: -```jsonc -{ - "items": [2, 3] // ids of the items -} -``` -* **Returns**: nothing - -## Mark an item as unread -* **Status**: Implemented -* **Method**: PUT -* **Route**: /items/{itemId}/unread -* **Parameters**: none -* **Return codes**: - * **HTTP 404**: If the item does not exist -* **Returns**: nothing - -## Mark multiple items as unread -* **Status**: Implemented in 1.2 -* **Method**: PUT -* **Route**: /items/unread/multiple -* **Parameters**: -```jsonc -{ - "items": [2, 3] // ids of the items -} -``` -* **Returns**: nothing - -## Mark an item as starred -* **Status**: Implemented -* **Method**: PUT -* **Route**: /items/{feedId}/{guidHash}/star -* **Parameters**: none -* **Return codes**: - * **HTTP 404**: If the item does not exist -* **Returns**: nothing - -## Mark multiple items as starred -* **Status**: Implemented in 1.2 -* **Method**: PUT -* **Route**: /items/star/multiple -* **Parameters**: -```jsonc -{ - "items": [ - { - "feedId": 3, - "guidHash": "sdf" - }, // etc - ] -} -``` -* **Returns**: nothing - -## Mark an item as unstarred -* **Status**: Implemented -* **Method**: PUT -* **Route**: /items/{feedId}/{guidHash}/unstar -* **Parameters**: none -* **Return codes**: - * **HTTP 404**: If the item does not exist -* **Returns**: nothing - -## Mark multiple items as unstarred -* **Status**: Implemented in 1.2 -* **Method**: PUT -* **Route**: /items/unstar/multiple -* **Parameters**: -```jsonc -{ - "items": [ - { - "feedId": 3, - "guidHash": "sdf" - }, // etc - ] -} -``` -* **Returns**: nothing - -## Mark all items as read - -* **Status**: Implemented -* **Method**: PUT -* **Route**: /items/read -* **Parameters**: -```jsonc -{ - // mark all items read lower than equal that id - // this is mean to prevent marking items as read which the client/user does not yet know of - "newestItemId": 10 -} -``` -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: nothing - - -# Updater - -To enable people to write their own update scripts instead of relying on the sequential built in web and system cron, API routes and console commands have been created. - -Updating should be done in the following fashion: -* Run the cleanup before the update -* Get all feeds and user ids -* For each feed and user id, run the update command -* Run the cleanup after the update. - -This [implementation in Python](https://github.com/nextcloud/news-updater) should give you a good idea how to design and run it. - -## Trigger cleanup before update -This is used to clean up the database. It deletes folders and feeds that are marked for deletion - -* **Status**: Implemented in 1.601 -* **Authentication**: Requires admin user -* **Method**: GET -* **Route**: /cleanup/before-update -* **Returns**: Nothing - -**New in 8.1.0**: The console command for achieving the same result is: - - php -f nextcloud/occ news:updater:before-update - -## Get feed ids and usernames for all feeds - -* **Status**: Implemented in 1.203 -* **Authentication**: Requires admin user -* **Method**: GET -* **Route**: /feeds/all -* **Parameters**: none -* **Returns**: -```jsonc -{ - "feeds": [ - { - "id": 39, - "userId": "john", - }, // etc - ] -} -``` - -**New in 8.1.0**: The console command for achieving the same result is: - - php -f nextcloud/occ news:updater:all-feeds - - -## Trigger a feed update - -* **Status**: Implemented in 1.601 -* **Authentication**: Requires admin user -* **Method**: GET -* **Route**: /feeds/update -* **Parameters**: -```jsonc -{ - "userId": "john", - "feedId": 3 -} -``` -* **Return codes**: - * **HTTP 404**: If the feed does not exist -* **Returns**: Nothing - -**New in 8.1.0**: The console command for achieving the same result is: - - php -f nextcloud/occ news:updater:update-feed 3 john - -## Trigger cleanup after update -This is used to clean up the database. It removes old read articles which are not starred - -* **Status**: Implemented in 1.601 -* **Authentication**: Requires admin user -* **Method**: GET -* **Route**: /cleanup/after-update -* **Returns**: Nothing - -**New in 8.1.0**: The console command for achieving the same result is: - - php -f nextcloud/occ news:updater:after-update - -# Version - -## Get the version - -* **Status**: Implemented -* **Method**: GET -* **Route**: /version -* **Parameters**: none -* **Returns**: -```jsonc -{ - "version": "5.2.3" -} -``` - -# Status - -This API can be used to display warnings and errors in your client if the web app is improperly configured or not working. It is a good idea to call this route on like every 10th update and after the server connection parameters have been changed since it's likely that the user set up a new instance and configured the app improperly. - -## Get the status - -* **Status**: Implemented in 5.2.4 -* **Method**: GET -* **Route**: /status -* **Parameters**: none -* **Returns**: -```jsonc -{ - "version": "5.2.4", - "warnings": { - "improperlyConfiguredCron": false, // if true the webapp will fail to update the feeds correctly - "incorrectDbCharset": false - } -} -``` - -If **improperlyConfiguredCron** is true you should display a warning that the app will not receive updates properly. - -This is due to the fact that the installation runs the cron in ajax mode to update the feeds. This is the default if you don't change anything and means that the app will only receive feed updates if the webinterface is accessed which will lead to lost updates. - -You should show the following warning and the link should be clickable: - - The News App updater is improperly configured and you will lose updates. - See http://hisdomain.com/index.php/apps/news for instructions on how to fix it. - -If **incorrectDbCharset** is true you should display a warning that database charset is set up incorrectly and updates with unicode characters might fail - -# User - -This API can be used to retrieve metadata about the current user. - -DEPRECATED: This API is deprecated, use the Nextcloud APIs instead. -- https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html#user-metadata for user data -- `https://nc.url/avatar/{userid}/{size}?v={1|2}` for the avatar - -## Get the status - -* **Status**: Implemented in 6.0.5 -* **Method**: GET -* **Route**: /user -* **Parameters**: none -* **Returns**: -```jsonc -{ - "userId": "john", - "displayName": "John Doe", - "lastLoginTimestamp": 1241231233, // unix timestamp - "avatar": { // if no avatar exists, this is null - "data": "asdiufadfasdfjlkjlkjljdfdf", // base64 encoded image - "mime": "image/jpeg" - } -} -``` diff --git a/docs/faq/README.md b/docs/faq/README.md deleted file mode 100644 index ca366910e..000000000 --- a/docs/faq/README.md +++ /dev/null @@ -1,107 +0,0 @@ -## FAQ - -### My browser shows a mixed content warning (Connection is Not Secure) -If you are serving your Nextcloud over HTTPS your browser will very likely warn you with a yellow warnings sign about your connection not being secure. - -Chrome will show no green HTTPS lock sign, Firefox will show you the following image -![Mixed Passive Content](https://ffp4g1ylyit3jdyti1hqcvtb-wpengine.netdna-ssl.com/security/files/2015/10/mixed-passive-click1-600x221.png) - -Note that this warning **is not red and won't block the page like the following images** which signal **a serious issue**: - -![Untrusted Cert](http://www.inmotionhosting.com/support/images/stories/website/errors/ssl/chrome-self-signed-ssl-warning.png) -![Mixed Active Content](http://www.howtogeek.com/wp-content/uploads/2014/02/650x367xchrome-mixed-content-https-problem.png.pagespeed.gp+jp+jw+pj+js+rj+rp+rw+ri+cp+md.ic.r_lQiZiq38.png) - -#### What is the cause of the (yellow) error message - -This warning is caused by [mixed passive content](https://developer.mozilla.org/en/docs/Security/MixedContent) and means that your page loads passive resources from non HTTPS resources, such as: -* Images -* Video/Audio - -This allows a possible attacker to perform a MITM (man-in-the-middle) attack by serving you different images or audio/video. - -#### Why doesn't the News app fix it - -The News app fully prevents mixed **active** content by only allowing HTTPS iframes from known locations; other possible mixed active content elements such as \