diff doc/rest.txt @ 7045:ca90f7270cd4 issue2550923_computed_property

merge from main tip. This should fix test failure in Markdown2TestCase.test_string_markdown_code_block_attribute by merging html diff method used in tests.
author John Rouillard <rouilj@ieee.org>
date Mon, 07 Nov 2022 22:58:38 -0500
parents e7b4ad2c57ac
children 42e68162279b
line wrap: on
line diff
--- a/doc/rest.txt	Thu Apr 21 16:54:17 2022 -0400
+++ b/doc/rest.txt	Mon Nov 07 22:58:38 2022 -0500
@@ -1,5 +1,5 @@
 .. meta::
-    :description language=en:
+    :description:
         Documentation on the RESTful interface to the Roundup Issue
 	Tracker.
 
@@ -72,6 +72,11 @@
 tracker's config.ini should have ``csrf_enforce_header_x-requested-with
 = yes`` or ``required``.
 
+If you want to allow Roundup's api to be accessed by an application
+that is not hosted at the same origin as Roundup, you must permit
+the origin using the ``allowed_api_origins`` setting in
+``config.ini``.
+
 Rate Limiting the API
 =====================
 
@@ -203,6 +208,48 @@
 ``application/x-www-form-urlencoded``. Any other value returns error
 code 415.
 
+CORS preflight requests
+^^^^^^^^^^^^^^^^^^^^^^^
+
+CORS preflight requests are done using the OPTIONS method. They
+require that REST be enabled. These requests do not make any changes
+or get any information from the database. As a result they are
+available to the anonymous user and any authenticated user. The user
+does not need to have `Rest Access` permissions. Also these requests
+bypass CSRF checks except for the Origin header check which is always
+run for preflight requests.
+
+You can permit only allowed ORIGINS by setting ``allowed_api_origins``
+in ``config.ini`` to the list of origins permitted to access your
+api. By default only your tracker's origin is allowed. If a preflight
+request fails, the api request will be stopped by the browser.
+
+The following CORS preflight headers are usually added automatically by
+the browser and must all be present:
+
+* `Access-Control-Request-Headers`
+* `Access-Control-Request-Method`
+* `Origin`
+
+The 204 response will include the headers:
+
+* `Access-Control-Allow-Origin`
+* `Access-Control-Allow-Headers`
+* `Access-Control-Allow-Methods`
+* `Access-Control-Allow-Credentials: true`
+* `Access-Control-Max-Age: 86400`
+
+If the endpoint accepts the PATCH verb the header `Accept-Patch` with
+valid mime types (usually `application/x-www-form-urlencoded,
+multipart/form-data`) will be included.
+
+It will also include rate limit headers since the request is included
+in the rate limit for the URL.  The results from the CORS preflight
+should be cached for a day so preflight requests are not expected to
+cause a problem. If it is an issue, you can see
+`Creating Custom Rate Limits`_
+and craft a rate limiter that ignores anonymous OPTIONS requests.
+
 Response Formats
 ================
 
@@ -212,6 +259,20 @@
 data using the header ``Accept: application/xml`` in your
 request. Both output formats are similar in structure.
 
+``dicttoxml.py`` should be installed in the Python install directory,
+or the file can be added to the Roundup installation directory long
+ide ``rest.py``. It can also be enabled on a per tracker basis by
+adding ``dicttoxml.py`` to the lib directory in your tracker home (you
+may need to create the directory). Then this can be added to
+`interfaces.py`_ to enable xml::
+
+   from roundup import rest
+   from dicttoxml import dicttoxml as dtox # from tracker_root/lib directory
+
+   rest.dicttoxml = dtox
+
+.. _interfaces.py: customizing.html#interfaces-py-hooking-into-the-core-of-roundup 
+
 The rest interface accepts the http accept header and can include
 ``q`` values to specify the preferred mechanism. This is the preferred
 way to specify alternate acceptable response formats.
@@ -423,7 +484,7 @@
   * - ``status=open``
     - Link
     - find any issue where the name of the status is open.
-      Note this is not a string match so using nosy=ope will fail.
+      Note this is not a string match so using status=ope will fail.
   * - ``nosy=1``
     - MultiLink
     - find any issue where the multilink nosy includes the id 1.
@@ -643,12 +704,10 @@
       "data": {
 	  "collection": [
 	      {
-		  "link":
-      "https://.../rest/data/issue/1",
+		  "link": "https://.../rest/data/issue/1",
 		  "id": "1",
 		  "status": {
-		      "link":
-      "https://.../rest/data/status/1",
+		      "link": "https://.../rest/data/status/1",
 		      "id": "1"
 		  }
 	      },
@@ -1102,8 +1161,7 @@
 	      ]
 	  },
 	  "type": "issue",
-	  "link":
-	  "https://example.com/demo/rest/data/issue/23",
+	  "link": "https://example.com/demo/rest/data/issue/23",
 	  "id": "23"
       }
   }
@@ -1266,7 +1324,8 @@
     "id": "11",
     "type": "<class 'str'>",
     "link": "https://.../demo/rest/data/msg/11/content",
-    "data": "of has to who pleasure. or of account give because the reprehenderit\neu to quisquam velit, passage, was or...",
+    "data": "of has to who pleasure. or of account give because the
+              reprehenderit\neu to quisquam velit, passage, was or...",
             "@etag": "\"584f82231079e349031bbb853747df1c\""
     }
   }		
@@ -1407,7 +1466,10 @@
 Note the addition of headers for: x-requested-with and referer. This
 allows the request to pass the CSRF protection mechanism. You may need
 to add an Origin header if this check is enabled in your tracker's
-config.ini (look for csrf_enforce_header_origin).
+config.ini (look for csrf_enforce_header_origin). (Note the Origin
+header check may have to be disabled if an application is making a
+CORS request to the Roundup server. If you have this issue, please
+contact the Roundup team using the mailing lists as this is a bug.)
 
 A similar curl based retire example is to use::
 
@@ -1546,7 +1608,7 @@
 Adding new rest endpoints
 =========================
 
-Add or edit the file interfaces.py at the root of the tracker
+Add or edit the file `interfaces.py`_ at the root of the tracker
 directory.
 
 In that file add::
@@ -1801,7 +1863,7 @@
    jwt module you will see the error ``Support for jwt disabled.``
 2. create a new role that allows Create access to timelog and edit/view
    access to an issues' ``times`` property.
-3. add support for issuing (and validating) jwts to the rest interface.
+3. add support for issuing (and validating) JWTs to the rest interface.
    This uses the `Adding new rest endpoints`_ mechanism.
 4. configure roundup's config.ini [web] jwt_secret with at least 32
    random characters of data. (You will get a message
@@ -1975,19 +2037,19 @@
             return 200, result
 
 **Note this is sample code. Use at your own risk.** It breaks a few
-rules about jwts (e.g. it allows you to make unlimited lifetime
-jwts). If you subscribe to the concept of jwt refresh tokens, this code
-will have to be changed as it will only generate jwts with
+rules about JWTs (e.g. it allows you to make unlimited lifetime
+JWTs). If you subscribe to the concept of JWT refresh tokens, this code
+will have to be changed as it will only generate JWTs with
 username/password authentication.
 
-Currently use of jwts an experiment. If this appeals to you consider
+Currently use of JWTs an experiment. If this appeals to you consider
 providing patches to existing code to:
 
-1. record all jwts created by a user
-2. using the record to allow jwts to be revoked and ignored by the
+1. record all JWTs created by a user
+2. using the record to allow JWTs to be revoked and ignored by the
    roundup core
-3. provide a UI page for managing/revoking jwts
-4. provide a rest api for revoking jwts
+3. provide a UI page for managing/revoking JWTs
+4. provide a rest api for revoking JWTs
 
 These end points can be used like::
 
@@ -1995,23 +2057,23 @@
       -H "X-requested-with: rest" \
       -H "Content-Type: application/json" \
       --data '{"lifetime": "3600", "roles": [ "user:timelog" ] }' \
-   https://.../demo/rest/jwt/issue
+   https://.../demo/rest/JWT/issue
 
 (note roles is a json array/list of strings not a string) to get::
 
   {
     "data": {
-            "jwt":  "eyJ0eXAiOiJK......XxMDb-Q3oCnMpyhxPXMAk"
+            "JWT":  "eyJ0eXAiOiJK......XxMDb-Q3oCnMpyhxPXMAk"
         }
   }
 
-The jwt is shortened in the example since it's large. You can validate
-a jwt to see if it's still valid using::
+The JWT is shortened in the example since it's large. You can validate
+a JWT to see if it's still valid using::
 
 
   curl -s -H "Referer: https://.../demo/" \
   -H "X-requested-with: rest" \
-      https://.../demo/rest/jwt/validate?jwt=eyJ0eXAiOiJK...XxMDb-Q3oCnMpyhxPXMAk
+      https://.../demo/rest/JWT/validate?JWT=eyJ0eXAiOiJK...XxMDb-Q3oCnMpyhxPXMAk
 
 (note no login is required) which returns::
   
@@ -2028,12 +2090,18 @@
      }
   }				
 
+
+There is an issue for `thoughts on JWT credentials`_ that you can view
+for ideas or add your own.
+
+.. _thoughts on JWT credentials: https://issues.roundup-tracker.org/issue2551064
+
 Final steps
 ^^^^^^^^^^^
 
 See the `upgrading directions`_ on how to use the ``updateconfig``
 command to generate an updated copy of config.ini using
-roundup-admin. Then set the ``jwt_secret`` to at least 32 characters
+roundup-admin. Then set the ``JWT_secret`` to at least 32 characters
 (more is better up to 512 bits).
 
 Writing an auditor that uses "db.user.get_roles" to see if the user
@@ -2045,7 +2113,7 @@
 
 Lastly you can create a JWT using the end point above and make a rest
 call to create a new timelog entry and another call to update the
-issues times property.  If you have other ideas on how jwts can be
+issues times property.  If you have other ideas on how JWTs can be
 used, please share on the roundup mailing lists. See:
 https://sourceforge.net/p/roundup/mailman/ for directions on
 subscribing and for archives of the lists.
@@ -2056,7 +2124,8 @@
 
 You can replace the default rate limiter that is configured using
 the tracker's ``config.ini``. You can return different rate
-limits based on the user, time of day, phase of moon etc.
+limits based on the user, time of day, phase of moon, request
+method (via self.client.request.command) etc.
 
 Assume you add two integer valued properties to the user
 object. Let's call them ``rate_limit_interval`` and
@@ -2099,5 +2168,8 @@
 
 Rate limit tests::
 
-   seq 1 300 | xargs -P 20 -n 1 curl --head -si \
-        https://.../rest/data/status/new \# | grep Remaining
+   seq 1 300 | xargs -P 20 -n 1 curl --head -u user:password -si \
+        https://.../rest/data/status/new | grep Remaining
+
+will show you the number of remaining requests to the REST interface
+for the user identified by password.

Roundup Issue Tracker: http://roundup-tracker.org/