annotate roundup/rest.py @ 8549:e920db4d00d3

build(deps): bump codecov/codecov-action from 5.5.3 to 6.0.0 #87
author John Rouillard <rouilj@ieee.org>
date Mon, 30 Mar 2026 10:55:53 -0400
parents 1ffa1f42e1da
children 9c3ec0a5c7fc
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
1 """
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
2 Restful API for Roundup
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
3
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
4 This module is free software, you may redistribute it
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
5 and/or modify under the same terms as Python.
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
6 """
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
7
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
8 from __future__ import print_function
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
9
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
10 import hmac
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
11 import json
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
12 import logging
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
13 import os
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
14 import re
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
15 import sys
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
16 import time
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
17 import traceback
8207
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
18 from datetime import timedelta
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
19 from hashlib import md5
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
20
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
21 try:
8220
818751637b77 fix: make rest.py still load on python2, do not test bad json
John Rouillard <rouilj@ieee.org>
parents: 8218
diff changeset
22 from json import JSONDecodeError
818751637b77 fix: make rest.py still load on python2, do not test bad json
John Rouillard <rouilj@ieee.org>
parents: 8218
diff changeset
23 except ImportError:
818751637b77 fix: make rest.py still load on python2, do not test bad json
John Rouillard <rouilj@ieee.org>
parents: 8218
diff changeset
24 JSONDecodeError = ValueError
818751637b77 fix: make rest.py still load on python2, do not test bad json
John Rouillard <rouilj@ieee.org>
parents: 8218
diff changeset
25
818751637b77 fix: make rest.py still load on python2, do not test bad json
John Rouillard <rouilj@ieee.org>
parents: 8218
diff changeset
26 try:
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
27 from urllib.parse import urlparse
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
28 except ImportError:
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
29 from urlparse import urlparse
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
30
8207
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
31 from roundup import actions, date, hyperdb
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
32 from roundup.anypy.strings import b2s, bs2b, is_us, u2s
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
33 from roundup.cgi.exceptions import NotFound, PreconditionFailed, Unauthorised
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
34 from roundup.exceptions import Reject, UsageError
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
35 from roundup.i18n import _
8207
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
36 from roundup.rate_limit import Gcra, RateLimit
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
37
6824
9811073b289e replace accidently removed logger setup.
John Rouillard <rouilj@ieee.org>
parents: 6823
diff changeset
38 logger = logging.getLogger('roundup.rest')
9811073b289e replace accidently removed logger setup.
John Rouillard <rouilj@ieee.org>
parents: 6823
diff changeset
39
5631
a5c890d308c3 Add simple support for xml output if the third party dict2xml.py module
John Rouillard <rouilj@ieee.org>
parents: 5630
diff changeset
40 try:
8319
5e6ff4e9cacb build: issue2551397: remove support for python 3.6
John Rouillard <rouilj@ieee.org>
parents: 8275
diff changeset
41 # if dicttoxml2
7684
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
42 # is installed in roundup directory, use it
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
43 from roundup.dicttoxml2 import dicttoxml
5631
a5c890d308c3 Add simple support for xml output if the third party dict2xml.py module
John Rouillard <rouilj@ieee.org>
parents: 5630
diff changeset
44 except ImportError:
5653
ba67e397f063 Fix string/bytes issues under python 3.
John Rouillard <rouilj@ieee.org>
parents: 5646
diff changeset
45 try:
ba67e397f063 Fix string/bytes issues under python 3.
John Rouillard <rouilj@ieee.org>
parents: 5646
diff changeset
46 # else look in sys.path
7684
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
47 from dicttoxml2 import dicttoxml
5653
ba67e397f063 Fix string/bytes issues under python 3.
John Rouillard <rouilj@ieee.org>
parents: 5646
diff changeset
48 except ImportError:
7684
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
49 try:
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
50 from roundup.dicttoxml import dicttoxml
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
51 except ImportError:
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
52 try:
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
53 # else look in sys.path
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
54 from dicttoxml import dicttoxml
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
55 except ImportError:
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
56 # else not supported
3eca3462ba0c fix: add support for dicttoxml2.py
John Rouillard <rouilj@ieee.org>
parents: 7683
diff changeset
57 dicttoxml = None
5631
a5c890d308c3 Add simple support for xml output if the third party dict2xml.py module
John Rouillard <rouilj@ieee.org>
parents: 5630
diff changeset
58
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
59 # Py3 compatible basestring
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
60 try:
8191
30818cc18058 chore(ruff): suppress py2/py3 compatibility code thought useless
John Rouillard <rouilj@ieee.org>
parents: 8190
diff changeset
61 basestring # noqa: B018
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
62 except NameError:
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
63 basestring = str
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
64 unicode = str
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
65
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
66
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
67 def _data_decorator(func):
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
68 """Wrap the returned data into an object."""
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
69 def format_object(self, *args, **kwargs):
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
70 # get the data / error from function
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
71 try:
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
72 code, data = func(self, *args, **kwargs)
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
73 except NotFound as msg:
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
74 code = 404
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
75 data = msg
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
76 except IndexError as msg:
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
77 code = 404
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
78 data = msg
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
79 except Unauthorised as msg:
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
80 code = 403
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
81 data = msg
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
82 except (UsageError, KeyError) as msg:
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
83 code = 400
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
84 data = msg
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
85 except (AttributeError, Reject) as msg:
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
86 code = 405
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
87 data = msg
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
88 except ValueError as msg:
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
89 code = 409
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
90 data = msg
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
91 except PreconditionFailed as msg:
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
92 code = 412
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
93 data = msg
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
94 except NotImplementedError:
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
95 code = 402 # nothing to pay, just a mark for debugging purpose
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
96 data = 'Method under development'
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
97 except: # noqa: E722
8226
54afcb9149eb chore(lint): mark unused variables in assignment with leading _
John Rouillard <rouilj@ieee.org>
parents: 8220
diff changeset
98 _exc, val, _tb = sys.exc_info()
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
99 code = 400
5593
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
100 ts = time.ctime()
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
101 if getattr(self.client.request, 'DEBUG_MODE', None):
5593
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
102 data = val
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
103 else:
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
104 data = '%s: An error occurred. Please check the server log' \
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
105 ' for more information.' % ts
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
106 # out to the logfile
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
107 print('EXCEPTION AT', ts)
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
108 traceback.print_exc()
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
109
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
110 # decorate it
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
111 self.client.response_code = code
8229
c24b02266077 chore(ruff): handle magic number warnings.
John Rouillard <rouilj@ieee.org>
parents: 8227
diff changeset
112 ERROR_CODE_LOWER_BOUND = 400
c24b02266077 chore(ruff): handle magic number warnings.
John Rouillard <rouilj@ieee.org>
parents: 8227
diff changeset
113 if code >= ERROR_CODE_LOWER_BOUND: # any error require error format
7726
6f66d74d37f3 Add configurable logging for REST
Ralf Schlatterbeck <rsc@runtux.com>
parents: 7684
diff changeset
114 logmethod = getattr(logger, self.db.config.WEB_REST_LOGGING, None)
6f66d74d37f3 Add configurable logging for REST
Ralf Schlatterbeck <rsc@runtux.com>
parents: 7684
diff changeset
115 if logmethod:
6f66d74d37f3 Add configurable logging for REST
Ralf Schlatterbeck <rsc@runtux.com>
parents: 7684
diff changeset
116 logmethod("statuscode: %s" % code)
6f66d74d37f3 Add configurable logging for REST
Ralf Schlatterbeck <rsc@runtux.com>
parents: 7684
diff changeset
117 logmethod('message: "%s"' % data)
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
118 result = {
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
119 'error': {
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
120 'status': code,
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
121 'msg': data
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
122 }
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
123 }
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
124 else:
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
125 if hasattr(self.db, 'stats') and self.report_stats:
8190
569aff540a21 chore(ruff): whatespace fixes/silence linting
John Rouillard <rouilj@ieee.org>
parents: 8188
diff changeset
126 self.db.stats['elapsed'] = time.time() - self.start
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
127 data['@stats'] = self.db.stats
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
128 result = {
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
129 'data': data
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
130 }
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
131 return result
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
132
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
133 format_object.wrapped_func = func
5588
6b3a9655a7d9 Move decorator to outside of the class
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5587
diff changeset
134 return format_object
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
135
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
136
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
137 def openapi_doc(d):
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
138 """Annotate rest routes with openapi data. Takes a dict
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
139 for the openapi spec. It can be used standalone
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
140 as the openapi spec paths.<path>.<method> =
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
141
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
142 {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
143 "summary": "this path gets a value",
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
144 "description": "a longer description",
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
145 "responses": {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
146 "200": {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
147 "description": "normal response",
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
148 "content": {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
149 "application/json": {},
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
150 "application/xml": {}
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
151 }
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
152 },
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
153 "406": {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
154 "description": "Unable to provide requested content type",
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
155 "content": {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
156 "application/json": {}
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
157 }
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
158 }
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
159 },
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
160 "parameters": [
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
161 {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
162 "$ref": "#components/parameters/generic_.stats"
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
163 },
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
164 {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
165 "$ref": "#components/parameters/generic_.apiver"
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
166 },
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
167 {
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
168 "$ref": "#components/parameters/generic_.verbose"
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
169 }
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
170 ]
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
171 }
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
172 """
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
173
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
174 def wrapper(f):
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
175 f.openapi_doc = d
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
176 return f
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
177 return wrapper
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
178
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
179
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
180 def calculate_etag(node, key, classname="Missing", node_id="0",
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
181 repr_format="json"):
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
182 '''given a hyperdb node generate a hashed representation of it to be
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
183 used as an etag.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
184
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
185 This code needs a __repr__ function in the Password class. This
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
186 replaces the repr(items) which would be:
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
187
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
188 <roundup.password.Password instance at 0x7f3442406170>
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
189
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
190 with the string representation:
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
191
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
192 {PBKDF2}10000$k4d74EDgxlbH...A
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
193
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
194 This makes the representation repeatable as the location of the
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
195 password instance is not static and we need a constant value to
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
196 calculate the etag.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
197
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
198 Note that repr() is chosen for the node rather than str() since
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
199 repr is meant to be an unambiguous representation.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
200
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
201 classname and node_id are used for logging only.
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
202 '''
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
203
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
204 items = node.items(protected=True) # include every item
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
205 etag = hmac.new(bs2b(key), bs2b(repr_format +
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
206 repr(sorted(items))), md5).hexdigest()
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
207 logger.debug("object=%s%s; tag=%s; repr=%s", classname, node_id,
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
208 etag, repr(node.items(protected=True)))
5674
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
209 # Quotes are part of ETag spec, normal headers don't have quotes
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
210 return '"%s"' % etag
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
211
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
212
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
213 def check_etag(node, key, etags, classname="Missing", node_id="0",
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
214 repr_format="json"):
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
215 '''Take a list of etags and compare to the etag for the given node.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
216
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
217 Iterate over all supplied etags,
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
218 If a tag fails to match, return False.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
219 If at least one etag matches, return True.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
220 If all etags are None, return False.
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
221
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
222 '''
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
223 have_etag_match = False
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
224
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
225 node_etag = calculate_etag(node, key, classname, node_id,
5729
9ea2ce9d10cf A few internet references report that etags for the same underlying
John Rouillard <rouilj@ieee.org>
parents: 5727
diff changeset
226 repr_format=repr_format)
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
227
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
228 for etag in etags:
6539
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
229 # etag includes doublequotes around tag:
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
230 # '"a46a5572190e4fad63958c135f3746fa"'
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
231 # but can include content-encoding suffix like:
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
232 # '"a46a5572190e4fad63958c135f3746fa-gzip"'
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
233 # turn the latter into the former as we don't care what
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
234 # encoding was used to send the body with the etag.
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
235 try:
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
236 suffix_start = etag.rindex('-')
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
237 clean_etag = etag[:suffix_start] + '"'
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
238 except (ValueError, AttributeError):
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
239 # - not in etag or etag is None
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
240 clean_etag = etag
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
241 if clean_etag is not None:
f8df7fed18f6 issue2551175 - Make ETag content-encoding aware.
John Rouillard <rouilj@ieee.org>
parents: 6525
diff changeset
242 if clean_etag != node_etag:
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
243 return False
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
244 have_etag_match = True
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
245
8192
b4d7f9358ba6 chore(ruff): return/suppress boolen directly
John Rouillard <rouilj@ieee.org>
parents: 8191
diff changeset
246 if have_etag_match: # noqa: SIM103 leave for coverage reports
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
247 return True
8203
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
248 return False
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
249
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
250
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
251 def obtain_etags(headers, input_payload):
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
252 '''Get ETags value from headers or payload data
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
253 Only supports one etag value not list.
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
254 '''
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
255 etags = []
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
256 if '@etag' in input_payload:
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
257 etags.append(input_payload['@etag'].value)
5674
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
258 etags.append(headers.get("If-Match", None))
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
259 return etags
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
260
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
261
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
262 def parse_accept_header(accept):
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
263 """
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
264 Parse the Accept header *accept*, returning a list with 3-tuples of
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
265 [(str(media_type), dict(params), float(q_value)),] ordered by q values.
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
266
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
267 If the accept header includes vendor-specific types like::
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
268 application/vnd.yourcompany.yourproduct-v1.1+json
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
269
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
270 It will actually convert the vendor and version into parameters and
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
271 convert the content type into `application/json` so appropriate content
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
272 negotiation decisions can be made.
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
273
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
274 Default `q` for values that are not specified is 1.0
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
275
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
276 If q value > 1.0, it is parsed as a very small value.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
277
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
278 # Based on https://gist.github.com/samuraisam/2714195
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
279 # Also, based on a snipped found in this project:
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
280 # https://github.com/martinblech/mimerender
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
281 """
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
282 result = []
5731
058ef18af5fd Prevent crash when clients do not set accept header. Use
John Rouillard <rouilj@ieee.org>
parents: 5730
diff changeset
283 if not accept:
058ef18af5fd Prevent crash when clients do not set accept header. Use
John Rouillard <rouilj@ieee.org>
parents: 5730
diff changeset
284 return result
058ef18af5fd Prevent crash when clients do not set accept header. Use
John Rouillard <rouilj@ieee.org>
parents: 5730
diff changeset
285
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
286 for media_range in accept.split(","):
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
287 parts = media_range.split(";")
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
288 media_type = parts.pop(0).strip()
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
289 media_params = []
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
290 # convert vendor-specific content types into something useful (see
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
291 # docstring)
6311
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
292 try:
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
293 typ, subtyp = media_type.split('/')
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
294 except ValueError:
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
295 raise UsageError("Invalid media type: %s" % media_type)
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
296 # check for a + in the sub-type
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
297 if '+' in subtyp:
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
298 # if it exists, determine if the subtype is a vendor-specific type
8226
54afcb9149eb chore(lint): mark unused variables in assignment with leading _
John Rouillard <rouilj@ieee.org>
parents: 8220
diff changeset
299 vnd, _sep, extra = subtyp.partition('+')
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
300 if vnd.startswith('vnd'):
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
301 # and then... if it ends in something like "-v1.1" parse the
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
302 # version out
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
303 if '-v' in vnd:
8226
54afcb9149eb chore(lint): mark unused variables in assignment with leading _
John Rouillard <rouilj@ieee.org>
parents: 8220
diff changeset
304 vnd, _sep, rest = vnd.rpartition('-v')
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
305 if len(rest):
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
306 # add the version as a media param
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
307 try:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
308 media_params.append(('version', rest))
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
309 except ValueError:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
310 pass # return no version value; use rest default
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
311 # add the vendor code as a media param
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
312 media_params.append(('vendor', vnd))
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
313 # and re-write media_type to something like application/json so
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
314 # it can be used usefully when looking up emitters
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
315 media_type = '{}/{}'.format(typ, extra)
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
316 q = 1.0
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
317 for part in parts:
6311
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
318 try:
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
319 (key, value) = part.lstrip().split("=", 1)
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
320 except ValueError:
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
321 raise UsageError("Invalid param: %s" % part.lstrip())
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
322 key = key.strip()
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
323 value = value.strip()
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
324 if key == "q":
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
325 q = float(value)
5744
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
326 if q > 1.0:
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
327 # Not sure what to do here. Can't find spec
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
328 # about how to handle q > 1.0. Since invalid
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
329 # I choose to make it lowest in priority.
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
330 q = 0.0001
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
331 else:
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
332 media_params.append((key, value))
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
333 result.append((media_type, dict(media_params), q))
5653
ba67e397f063 Fix string/bytes issues under python 3.
John Rouillard <rouilj@ieee.org>
parents: 5646
diff changeset
334 result.sort(key=lambda x: x[2], reverse=True)
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
335 return result
5567
1af57f9d5bf7 Added exception Handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5566
diff changeset
336
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
337
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
338 class Routing(object):
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
339 __route_map = {}
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
340 __var_to_regex = re.compile(r"<:(\w+)>")
5715
d9a3f6957731 issue2551042 - add extra \ to \w in raw string url_to_regex. Not sure
John Rouillard <rouilj@ieee.org>
parents: 5711
diff changeset
341 url_to_regex = r"([\\w.\-~!$&'()*+,;=:\%%]+)"
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
342
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
343 @classmethod
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
344 def route(cls, rule, methods='GET'):
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
345 """A decorator that is used to register a view function for a
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
346 given URL rule:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
347 @self.route('/')
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
348 def index():
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
349 return 'Hello World'
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
350
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
351 rest/ will be added to the beginning of the url string
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
352
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
353 Args:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
354 rule (string): the URL rule
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
355 methods (string or tuple or list): the http method
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
356 """
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
357 # strip the '/' character from rule string
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
358 rule = rule.strip('/')
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
359
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
360 # add 'rest/' to the rule string
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
361 if not rule.startswith('rest/'):
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
362 rule = '^rest/' + rule + '$'
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
363
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
364 if isinstance(methods, basestring): # convert string to tuple
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
365 methods = (methods,)
8193
d06a140eab4d chore(ruff): replace set(generator) with {set comprehension}
John Rouillard <rouilj@ieee.org>
parents: 8192
diff changeset
366 methods = {item.upper() for item in methods}
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
367
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
368 # convert a rule to a compiled regex object
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
369 # so /data/<:class>/<:id> will become
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
370 # /data/([charset]+)/([charset]+)
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
371 # and extract the variable names to a list [(class), (id)]
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
372 func_vars = cls.__var_to_regex.findall(rule)
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
373 rule = re.compile(cls.__var_to_regex.sub(cls.url_to_regex, rule))
5851
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
374 # Save pattern to represent regex in route_map dictionary
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
375 # The entries consist of a 2-tuple of the (rule, dictionary)
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
376 # where rule is the compiled regex and dictionary contains the
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
377 # func_obj dict indexed by method.
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
378 pattern = rule.pattern
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
379
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
380 # then we decorate it:
5851
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
381 # route_map[pattern] = (rule, func_dict)
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
382 # where func_dict is a dictionary of func_obj (see below)
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
383 # indexed by method name
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
384 def decorator(func):
5851
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
385 rule_route = cls.__route_map.get(pattern, (rule, {}))
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
386 rule_dict = rule_route[1]
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
387 func_obj = {
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
388 'func': func,
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
389 'vars': func_vars
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
390 }
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
391 for method in methods:
5851
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
392 rule_dict[method] = func_obj
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
393 cls.__route_map[pattern] = rule_route
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
394 return func
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
395 return decorator
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
396
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
397 @classmethod
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
398 def execute(cls, instance, path, method, input_payload):
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
399 # format the input_payload, note that we may not lowercase the path
5679
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
400 # here, URL parameters are case-sensitive
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
401 path = path.strip('/')
5622
2a7d23a098ca Make @Routing.route('/') decoration work. This decoration matches
John Rouillard <rouilj@ieee.org>
parents: 5621
diff changeset
402 if path == 'rest':
2a7d23a098ca Make @Routing.route('/') decoration work. This decoration matches
John Rouillard <rouilj@ieee.org>
parents: 5621
diff changeset
403 # allow handler to be called for /rest/
2a7d23a098ca Make @Routing.route('/') decoration work. This decoration matches
John Rouillard <rouilj@ieee.org>
parents: 5621
diff changeset
404 path = 'rest/'
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
405 method = method.upper()
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
406
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
407 # find the rule match the path
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
408 # then get handler match the method
5851
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
409 for path_regex, funcs in cls.__route_map.values():
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
410 # use compiled regex to find rule
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
411 match_obj = path_regex.match(path)
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
412 if match_obj:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
413 try:
5851
167ef847fcdf issue2551053: Fix routing dict in rest.py
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5842
diff changeset
414 func_obj = funcs[method]
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
415 except KeyError:
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
416 valid_methods = ', '.join(sorted(funcs.keys()))
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
417 raise Reject(_('Method %(m)s not allowed. '
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
418 'Allowed: %(a)s') % {
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
419 'm': method,
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
420 'a': valid_methods
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
421 },
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
422 valid_methods)
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
423
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
424 # retrieve the vars list and the function caller
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
425 list_vars = func_obj['vars']
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
426 func = func_obj['func']
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
427
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
428 # zip the varlist into a dictionary, and pass it to the caller
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
429 # FIXME: 3.10 is min version- add strict=True to zip
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
430 # also wrap with try/except ValueError if different number of
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
431 # items (which should never happen).
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
432 args = dict(zip(list_vars, match_obj.groups()))
8196
94999f850fd6 fix: missed on input -> input_payload on e5362f8e1808
John Rouillard <rouilj@ieee.org>
parents: 8195
diff changeset
433 args['input_payload'] = input_payload
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
434 return func(instance, **args)
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
435 raise NotFound('Nothing matches the given URI')
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
436
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
437
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
438 class RestfulInstance(object):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
439 """The RestfulInstance performs REST request from the client"""
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
440
5593
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
441 __default_patch_op = "replace" # default operator for PATCH method
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
442 __accepted_content_type = {
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
443 "application/json": "json",
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
444 "application/*": "json" # json is preferred over application/xml
5594
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
445 }
864cf6cb5790 Added ability to parse HTTP accept header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5593
diff changeset
446 __default_accept_type = "json"
5593
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
447
5685
4b4885f0c6ad Set up basic framework for handling versioning of interface.
John Rouillard <rouilj@ieee.org>
parents: 5682
diff changeset
448 __default_api_version = 1
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
449 __supported_api_versions = [1]
5687
83037aaf3b9d Move definition/initialization of api_version into the class and out
John Rouillard <rouilj@ieee.org>
parents: 5686
diff changeset
450
83037aaf3b9d Move definition/initialization of api_version into the class and out
John Rouillard <rouilj@ieee.org>
parents: 5686
diff changeset
451 api_version = None
83037aaf3b9d Move definition/initialization of api_version into the class and out
John Rouillard <rouilj@ieee.org>
parents: 5686
diff changeset
452
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
453 # to allow override from interfaces.py.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
454 # Used for msg class. Could
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
455 # be useful to set to text/markdown.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
456 default_text_file_mimetype = "text/plain"
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
457
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
458 # allow 10M row response - can change using interfaces.py
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
459 # limit is 1 less than this size.
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
460 max_response_row_size = 10000001
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
461
5568
edab9daa8015 Make objects returned by REST follow the standard
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5567
diff changeset
462 def __init__(self, client, db):
5590
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
463 self.client = client
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
464 self.db = db
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
465 self.translator = client.translator
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
466 # record start time for statistics reporting
7683
b04e222501b8 fix: rest - set self.start from client.start
John Rouillard <rouilj@ieee.org>
parents: 7605
diff changeset
467 self.start = client.start
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
468 # disable stat reporting by default enable with @stats=True
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
469 # query param
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
470 self.report_stats = False
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
471 # This used to be initialized from client.instance.actions which
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
472 # would include too many actions that do not make sense in the
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
473 # REST-API context, so for now we only permit the retire and
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
474 # restore actions.
8201
d5ad7fcb9bf6 chore(ruff): replace dict(...) with equivalent {...}
John Rouillard <rouilj@ieee.org>
parents: 8199
diff changeset
475 self.actions = {"retire": actions.Retire, "restore": actions.Restore}
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
476
5616
aa4c271514ae Original code generated url's using a harcoded protocol and took the
John Rouillard <rouilj@ieee.org>
parents: 5604
diff changeset
477 # note TRACKER_WEB ends in a /
aa4c271514ae Original code generated url's using a harcoded protocol and took the
John Rouillard <rouilj@ieee.org>
parents: 5604
diff changeset
478 self.base_path = '%srest' % (self.db.config.TRACKER_WEB)
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
479 self.data_path = self.base_path + '/data'
5569
2718aeb55ffa Add base_path to generate uri
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5568
diff changeset
480
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
481 if dicttoxml: # add xml if supported
5744
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
482 self.__accepted_content_type["application/xml"] = "xml"
d4de45cde106 Accept header parsing fixes. Now return first acceptable match rather
John Rouillard <rouilj@ieee.org>
parents: 5740
diff changeset
483
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
484 def props_from_args(self, cl, args, itemid=None, skip_protected=True):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
485 """Construct a list of properties from the given arguments,
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
486 and return them after validation.
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
487
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
488 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
489 cl (string): class object of the resource
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
490 args (list): the submitted form of the user
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
491 itemid (string, optional): itemid of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
492
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
493 Returns:
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
494 dict: dictionary of validated properties excluding
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
495 protected properties if strip_protected=True.
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
496
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
497 Raises: UsageError if property does not exist and is not
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
498 prefixed with @ indicating it's a meta variable.
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
499
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
500
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
501 """
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
502 unprotected_class_props = cl.properties.keys()
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
503 protected_class_props = [p for p in
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
504 list(cl.getprops(protected=True))
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
505 if p not in unprotected_class_props]
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
506 props = {}
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
507 # props = dict.fromkeys(class_props, None)
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
508
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
509 if not args:
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
510 raise UsageError("No properties found.")
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
511
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
512 for arg in args:
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
513 key = arg.name
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
514 value = arg.value
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
515 if key.startswith('@'):
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
516 # meta setting, not db property setting/reference
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
517 continue
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
518 if key in protected_class_props:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
519 # Skip protected props as a convenience.
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
520 # Allows user to get object with all props,
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
521 # change one prop, submit entire object
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
522 # without having to remove any protected props
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
523 # FIXME: Enhancement: raise error if value of prop
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
524 # doesn't match db entry. In this case assume user
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
525 # is really trying to set value. Another possibility is
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
526 # they have an old copy of the data and it has been
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
527 # updated. In the update case, we want etag validation
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
528 # to generate the exception to reduce confusion. I think
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
529 # etag validation occurs before this function is called but
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
530 # I am not positive.
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
531 if skip_protected:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
532 continue
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
533 elif key not in unprotected_class_props:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
534 # report bad props as this is an error.
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
535 raise UsageError("Property %s not found in class %s" % (key,
8206
8656bd1cf1f1 chore(ruff): clean whitespace and remove unrecognized noqa directive.
John Rouillard <rouilj@ieee.org>
parents: 8205
diff changeset
536 cl.classname))
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
537 props[key] = self.prop_from_arg(cl, key, value, itemid)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
538
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
539 return props
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
540
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
541 def prop_from_arg(self, cl, key, value, itemid=None):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
542 """Construct a property from the given argument,
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
543 and return them after validation.
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
544
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
545 Args:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
546 cl (string): class object of the resource
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
547 key (string): attribute key
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
548 value (string): attribute value
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
549 itemid (string, optional): itemid of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
550
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
551 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
552 value: value of validated properties
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
553
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
554 """
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
555 prop = None
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
556 if isinstance(key, unicode):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
557 try:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
558 key.encode('ascii') # Check to see if it can be encoded
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
559 except UnicodeEncodeError:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
560 raise UsageError(
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
561 'argument %r is not a valid ascii keyword' % key
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
562 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
563 if value:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
564 try:
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
565 prop = hyperdb.rawToHyperdb(self.db, cl, itemid, key, value)
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
566 except hyperdb.HyperdbValueError as msg:
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
567 raise UsageError(msg)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
568
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
569 return prop
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
570
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
571 def transitive_props(self, class_name, props):
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
572 """Construct a list of transitive properties from the given
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
573 argument, and return it after permission check. Raises
6111
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
574 Unauthorised if no permission. Permission is checked by
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
575 checking View permission on each component. We do not allow to
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
576 traverse multilinks -- the last item of an expansion *may* be a
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
577 multilink but in the middle of a transitive prop.
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
578 """
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
579 checked_props = []
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
580 uid = self.db.getuid()
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
581 for p in props:
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
582 pn = p
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
583 cn = class_name
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
584 if '.' in p:
6111
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
585 prop = None
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
586 for pn in p.split('.'):
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
587 # Tried to dereference a non-Link property
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
588 if cn is None:
8190
569aff540a21 chore(ruff): whatespace fixes/silence linting
John Rouillard <rouilj@ieee.org>
parents: 8188
diff changeset
589 raise UsageError("Property %(base)s can not be dereferenced in %(p)s." % {"base": p[:-(len(pn) + 1)], "p": p})
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
590 cls = self.db.getclass(cn)
6111
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
591 # This raises a KeyError for unknown prop:
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
592 try:
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
593 prop = cls.getprops(protected=True)[pn]
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
594 except KeyError:
6554
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
595 raise KeyError("Unknown property: %s" % p)
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
596 if isinstance(prop, hyperdb.Multilink):
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
597 raise UsageError(
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
598 'Multilink Traversal not allowed: %s' % p)
6111
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
599 # Now we have the classname in cn and the prop name in pn.
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
600 if not self.db.security.hasPermission('View', uid, cn, pn):
7569
940f06dac1b4 flake8: add space between raise and (
John Rouillard <rouilj@ieee.org>
parents: 7552
diff changeset
601 raise (Unauthorised
6111
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
602 ('User does not have permission on "%s.%s"'
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
603 % (cn, pn)))
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
604 try:
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
605 cn = prop.classname
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
606 except AttributeError:
2a513a057691 Fix transitive property check in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6091
diff changeset
607 cn = None
6554
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
608 else:
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
609 cls = self.db.getclass(cn)
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
610 # This raises a KeyError for unknown prop:
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
611 try:
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
612 prop = cls.getprops(protected=True)[pn]
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
613 except KeyError:
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
614 raise KeyError("Unknown property: %s" % pn)
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
615 checked_props.append(p)
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
616 return checked_props
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
617
5590
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
618 def error_obj(self, status, msg, source=None):
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
619 """Return an error object"""
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
620 self.client.response_code = status
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
621 result = {
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
622 'error': {
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
623 'status': status,
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
624 'msg': msg
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
625 }
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
626 }
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
627 if source is not None:
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
628 result['error']['source'] = source
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
629
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
630 return result
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
631
5595
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
632 def patch_data(self, op, old_val, new_val):
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
633 """Perform patch operation based on old_val and new_val
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
634
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
635 Args:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
636 op (string): PATCH operation: add, replace, remove
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
637 old_val: old value of the property
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
638 new_val: new value of the property
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
639
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
640 Returns:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
641 result (string): value after performed the operation
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
642 """
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
643 # add operation: If neither of the value is None, use the other one
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
644 # Otherwise, concat those 2 value
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
645 if op == 'add':
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
646 if old_val is None:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
647 result = new_val
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
648 elif new_val is None:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
649 result = old_val
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
650 else:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
651 result = old_val + new_val
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
652 # Replace operation: new value is returned
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
653 elif op == 'replace':
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
654 result = new_val
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
655 # Remove operation:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
656 # if old_val is not a list/dict, change it to None
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
657 # if old_val is a list/dict, but the parameter is empty,
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
658 # change it to none
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
659 # if old_val is a list/dict, and parameter is not empty
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
660 # proceed to remove the values from parameter from the list/dict
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
661 elif op == 'remove':
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
662 if isinstance(old_val, list):
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
663 if new_val is None:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
664 result = []
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
665 elif isinstance(new_val, list):
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
666 result = [x for x in old_val if x not in new_val]
8198
de6b02c23ee9 chore(ruff): replace 'else: if bool_exp:' with 'elif bool_exp:'
John Rouillard <rouilj@ieee.org>
parents: 8197
diff changeset
667 elif new_val in old_val:
de6b02c23ee9 chore(ruff): replace 'else: if bool_exp:' with 'elif bool_exp:'
John Rouillard <rouilj@ieee.org>
parents: 8197
diff changeset
668 old_val.remove(new_val)
5595
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
669 elif isinstance(old_val, dict):
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
670 if new_val is None:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
671 result = {}
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
672 elif isinstance(new_val, dict):
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
673 for x in new_val:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
674 old_val.pop(x, None)
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
675 else:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
676 old_val.pop(new_val, None)
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
677 else:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
678 result = None
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
679 else:
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
680 raise UsageError('PATCH Operation %s is not allowed' % op)
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
681
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
682 return result
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
683
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
684 def raise_if_no_etag(self, class_name, item_id, input_payload,
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
685 repr_format="json"):
5674
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
686 class_obj = self.db.getclass(class_name)
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
687 if not check_etag(class_obj.getnode(item_id),
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
688 self.db.config.WEB_SECRET_KEY,
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
689 obtain_etags(self.client.request.headers,
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
690 input_payload), class_name, item_id,
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
691 repr_format=repr_format):
5674
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
692 raise PreconditionFailed(
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
693 "If-Match is missing or does not match."
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
694 " Retrieve asset and retry modification if valid.")
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
695
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
696 def format_item(self, node, item_id, props=None, verbose=1):
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
697 ''' display class obj as requested by verbose and
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
698 props.
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
699 '''
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
700 uid = self.db.getuid()
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
701 class_name = node.cl.classname
5685
4b4885f0c6ad Set up basic framework for handling versioning of interface.
John Rouillard <rouilj@ieee.org>
parents: 5682
diff changeset
702
5740
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
703 # version never gets used since we only
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
704 # support version 1 at this time. Set it as
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
705 # placeholder for later use.
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
706 if self.api_version is None:
8230
eb45feb1d01e chore(ruff): remove unused noqa comments.
John Rouillard <rouilj@ieee.org>
parents: 8229
diff changeset
707 version = self.__default_api_version
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
708 else:
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
709 version = self.api_version # noqa: F841
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
710
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
711 result = {}
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
712 try:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
713 # pn = propname
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
714 for pn in sorted(props):
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
715 ok = False
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
716 working_id = item_id
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
717 nd = node
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
718 cn = class_name
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
719 for p in pn.split('.'):
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
720 if not self.db.security.hasPermission(
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
721 'View', uid, cn, p, working_id
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
722 ):
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
723 break
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
724 cl = self.db.getclass(cn)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
725 nd = cl.getnode(working_id)
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
726 working_id = v = getattr(nd, p)
6254
5b66c480f71f Handle empty Link for transitive property
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6185
diff changeset
727 # Handle transitive properties where something on
5b66c480f71f Handle empty Link for transitive property
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6185
diff changeset
728 # the road is None (empty Link property)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
729 if working_id is None:
6254
5b66c480f71f Handle empty Link for transitive property
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6185
diff changeset
730 prop = None
5b66c480f71f Handle empty Link for transitive property
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6185
diff changeset
731 ok = True
5b66c480f71f Handle empty Link for transitive property
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6185
diff changeset
732 break
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
733 prop = cl.getprops(protected=True)[p]
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
734 cn = getattr(prop, 'classname', None)
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
735 else:
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
736 ok = True
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
737 if not ok:
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
738 continue
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
739 if isinstance(prop, (hyperdb.Link, hyperdb.Multilink)):
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
740 linkcls = self.db.getclass(prop.classname)
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
741 cp = '%s/%s/' % (self.data_path, prop.classname)
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
742 if verbose and v:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
743 if isinstance(v, type([])):
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
744 r = []
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
745 for working_id in v:
8201
d5ad7fcb9bf6 chore(ruff): replace dict(...) with equivalent {...}
John Rouillard <rouilj@ieee.org>
parents: 8199
diff changeset
746 d = {"id": working_id,
d5ad7fcb9bf6 chore(ruff): replace dict(...) with equivalent {...}
John Rouillard <rouilj@ieee.org>
parents: 8199
diff changeset
747 "link": cp + working_id}
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
748 if verbose > 1:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
749 label = linkcls.labelprop()
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
750 d[label] = linkcls.get(working_id, label)
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
751 r.append(d)
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
752 result[pn] = r
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
753 else:
8201
d5ad7fcb9bf6 chore(ruff): replace dict(...) with equivalent {...}
John Rouillard <rouilj@ieee.org>
parents: 8199
diff changeset
754 result[pn] = {"id": v, "link": cp + v}
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
755 if verbose > 1:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
756 label = linkcls.labelprop()
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
757 result[pn][label] = linkcls.get(v, label)
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
758 else:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
759 result[pn] = v
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
760 elif isinstance(prop, hyperdb.String) and pn == 'content':
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
761 # Do not show the (possibly HUGE) content prop
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
762 # unless very verbose, we display the standard
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
763 # download link instead
8229
c24b02266077 chore(ruff): handle magic number warnings.
John Rouillard <rouilj@ieee.org>
parents: 8227
diff changeset
764 MIN_VERBOSE_LEVEL_SHOW_CONTENT = 3
c24b02266077 chore(ruff): handle magic number warnings.
John Rouillard <rouilj@ieee.org>
parents: 8227
diff changeset
765 if verbose < MIN_VERBOSE_LEVEL_SHOW_CONTENT:
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
766 u = self.db.config.TRACKER_WEB
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
767 p = u + '%s%s/' % (class_name, node.id)
8201
d5ad7fcb9bf6 chore(ruff): replace dict(...) with equivalent {...}
John Rouillard <rouilj@ieee.org>
parents: 8199
diff changeset
768 result[pn] = {"link": p}
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
769 else:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
770 result[pn] = v
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
771 elif isinstance(prop, hyperdb.Password):
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
772 if v is not None: # locked users like anonymous have None
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
773 result[pn] = "[password hidden scheme %s]" % v.scheme
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
774 else:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
775 # Don't divulge it's a locked account. Choose most
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
776 # secure as default.
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
777 result[pn] = "[password hidden scheme PBKDF2]"
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
778 else:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
779 result[pn] = v
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
780 except KeyError as msg:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
781 raise UsageError("%s field not valid" % msg)
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
782
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
783 return result
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
784
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
785 @Routing.route("/data/<:class_name>", 'GET')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
786 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
787 def get_collection(self, class_name, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
788 """GET resource from class URI.
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
789
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
790 This function returns only items have View permission
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
791 class_name should be valid already
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
792
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
793 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
794 class_name (string): class name of the resource (Ex: issue, msg)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
795 input_payload (list): the submitted form of the user
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
796
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
797 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
798 int: http status code 200 (OK)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
799 list: list of reference item in the class
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
800 id: id of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
801 link: path to the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
802 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
803 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
804 raise NotFound('Class %s not found' % class_name)
5677
1fa59181ce58 Add support for @verbose=2 to a GET on a collection object. Using this
John Rouillard <rouilj@ieee.org>
parents: 5674
diff changeset
805
1fa59181ce58 Add support for @verbose=2 to a GET on a collection object. Using this
John Rouillard <rouilj@ieee.org>
parents: 5674
diff changeset
806 uid = self.db.getuid()
1fa59181ce58 Add support for @verbose=2 to a GET on a collection object. Using this
John Rouillard <rouilj@ieee.org>
parents: 5674
diff changeset
807
5864
5e8e160fe2a0 Fix security checks for individual properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5851
diff changeset
808 if not self.db.security.hasPermission('View', uid, class_name):
5562
70df783c4c0b Cleanup, fixed a bug with delete action
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5561
diff changeset
809 raise Unauthorised('Permission to view %s denied' % class_name)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
810
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
811 class_obj = self.db.getclass(class_name)
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
812 class_path = '%s/%s/' % (self.data_path, class_name)
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
813
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
814 # Handle filtering and pagination
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
815 filter_props = {}
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
816 exact_props = {}
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
817 page = {
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
818 'size': None,
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
819 'index': 1, # setting just size starts at page 1
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
820 }
5677
1fa59181ce58 Add support for @verbose=2 to a GET on a collection object. Using this
John Rouillard <rouilj@ieee.org>
parents: 5674
diff changeset
821 verbose = 1
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
822 display_props = set()
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
823 sort = []
7854
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
824 group = []
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
825 for form_field in input_payload.value:
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
826 key = form_field.name
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
827 value = form_field.value
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
828 if key.startswith("@page_"): # serve the paging purpose
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
829 key = key[6:]
8213
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
830 try:
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
831 value = int(value)
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
832 except ValueError as e:
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
833 raise UsageError("When using @page_%s: %s" %
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
834 (key, e.args[0]))
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
835 page[key] = value
5677
1fa59181ce58 Add support for @verbose=2 to a GET on a collection object. Using this
John Rouillard <rouilj@ieee.org>
parents: 5674
diff changeset
836 elif key == "@verbose":
8213
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
837 try:
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
838 verbose = int(value)
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
839 except ValueError as e:
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
840 raise UsageError("When using @verbose: %s" %
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
841 (e.args[0]))
8197
5b8d1cb290cb chore(ruff): replace 'x == y or x == z' with 'x in [y,z]'
John Rouillard <rouilj@ieee.org>
parents: 8196
diff changeset
842 elif key in ["@fields", "@attrs"]:
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
843 f = value.split(",")
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
844 if len(f) == 1:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
845 f = value.split(":")
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
846 display_props.update(self.transitive_props(class_name, f))
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
847 elif key == "@sort":
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
848 f = value.split(",")
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
849 for p in f:
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
850 if not p:
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
851 raise UsageError("Empty property "
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
852 "for class %s." % (class_name))
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
853 if p[0] in ('-', '+'):
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
854 pn = p[1:]
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
855 ss = p[0]
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
856 else:
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
857 ss = '+'
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
858 pn = p
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
859 # Only include properties where we have search permission
5872
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
860 # Note that hasSearchPermission already returns 0 for
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
861 # non-existing properties.
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
862 if self.db.security.hasSearchPermission(
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
863 uid, class_name, pn
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
864 ):
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
865 sort.append((ss, pn))
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
866 else:
6088
00a24243887c Remove redundant permission check
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6086
diff changeset
867 raise (Unauthorised(
6086
c172bd18fa94 REST API: 403 on non-searchable properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6009
diff changeset
868 'User does not have search permission on "%s.%s"'
c172bd18fa94 REST API: 403 on non-searchable properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6009
diff changeset
869 % (class_name, pn)))
7854
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
870 elif key == "@group":
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
871 f = value.split(",")
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
872 for p in f:
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
873 if not p:
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
874 raise UsageError("Empty property "
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
875 "for class %s." % (class_name))
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
876 if p[0] in ('-', '+'):
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
877 pn = p[1:]
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
878 ss = p[0]
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
879 else:
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
880 ss = '+'
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
881 pn = p
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
882 # Only include properties where we have search permission
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
883 # Note that hasSearchPermission already returns 0 for
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
884 # non-existing properties.
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
885 if self.db.security.hasSearchPermission(
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
886 uid, class_name, pn
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
887 ):
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
888 group.append((ss, pn))
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
889 else:
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
890 raise (Unauthorised(
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
891 'User does not have search permission on "%s.%s"'
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
892 % (class_name, pn)))
5691
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
893 elif key.startswith("@"):
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
894 # ignore any unsupported/previously handled control key
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
895 # like @apiver
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
896 pass
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
897 else: # serve the filter purpose
5874
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
898 exact = False
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
899 if key.endswith(':'):
5874
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
900 exact = True
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
901 key = key[:-1]
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
902 elif key.endswith('~'):
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
903 key = key[:-1]
5872
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
904 p = key.split('.', 1)[0]
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
905 try:
5872
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
906 prop = class_obj.getprops()[p]
5691
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
907 except KeyError:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
908 raise UsageError("Field %s is not valid for %s class." %
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
909 (p, class_name))
6554
576d630fc908 Fix error status for invalid props
John Rouillard <rouilj@ieee.org>
parents: 6544
diff changeset
910 # Call this for the side effect of validating the key
6559
178705fbeaa8 Change _ = to _discard = as _ is the translation service global
John Rouillard <rouilj@ieee.org>
parents: 6554
diff changeset
911 # use _discard as _ is apparently a global for the translation
178705fbeaa8 Change _ = to _discard = as _ is the translation service global
John Rouillard <rouilj@ieee.org>
parents: 6554
diff changeset
912 # service.
8230
eb45feb1d01e chore(ruff): remove unused noqa comments.
John Rouillard <rouilj@ieee.org>
parents: 8229
diff changeset
913 _discard = self.transitive_props(class_name, [key])
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
914
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
915 # We drop properties without search permission silently
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
916 # This reflects the current behavior of other roundup
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
917 # interfaces
5872
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
918 # Note that hasSearchPermission already returns 0 for
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
919 # non-existing properties.
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
920 if not self.db.security.hasSearchPermission(
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
921 uid, class_name, key
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
922 ):
6088
00a24243887c Remove redundant permission check
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6086
diff changeset
923 raise (Unauthorised(
6086
c172bd18fa94 REST API: 403 on non-searchable properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6009
diff changeset
924 'User does not have search permission on "%s.%s"'
c172bd18fa94 REST API: 403 on non-searchable properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6009
diff changeset
925 % (class_name, key)))
5872
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
926
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
927 linkcls = class_obj
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
928 for p in key.split('.'):
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
929 prop = linkcls.getprops(protected=True)[p]
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
930 linkcls = getattr(prop, 'classname', None)
5872
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
931 if linkcls:
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
932 linkcls = self.db.getclass(linkcls)
1b91e3df3fd0 Implement transitive props for sort and filter
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5870
diff changeset
933
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
934 if isinstance(prop, (hyperdb.Link, hyperdb.Multilink)):
5842
9c6617857032 Support use of duplicate rest filters keys. So URL's like:
John Rouillard <rouilj@ieee.org>
parents: 5824
diff changeset
935 if key in filter_props:
9c6617857032 Support use of duplicate rest filters keys. So URL's like:
John Rouillard <rouilj@ieee.org>
parents: 5824
diff changeset
936 vals = filter_props[key]
9c6617857032 Support use of duplicate rest filters keys. So URL's like:
John Rouillard <rouilj@ieee.org>
parents: 5824
diff changeset
937 else:
9c6617857032 Support use of duplicate rest filters keys. So URL's like:
John Rouillard <rouilj@ieee.org>
parents: 5824
diff changeset
938 vals = []
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
939 for p in value.split(","):
8195
beab1ba70d34 chore(ruff): parenthesize "a and b or ..." to enforce/clarify precedence
John Rouillard <rouilj@ieee.org>
parents: 8194
diff changeset
940 dig = (p and p.isdigit()) or \
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
941 (p[0] in ('-', '+') and p[1:].isdigit())
5904
2b78e21d7047 Fix lookup of negative ids
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5874
diff changeset
942 if prop.try_id_parsing and dig:
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
943 vals.append(p)
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
944 else:
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
945 vals.append(linkcls.lookup(p))
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
946 filter_props[key] = vals
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
947 else:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
948 if not isinstance(prop, hyperdb.String):
5874
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
949 exact = False
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
950 props = filter_props
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
951 if exact:
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
952 props = exact_props
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
953 if key in props:
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
954 if isinstance(props[key], list):
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
955 props[key].append(value)
5842
9c6617857032 Support use of duplicate rest filters keys. So URL's like:
John Rouillard <rouilj@ieee.org>
parents: 5824
diff changeset
956 else:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
957 props[key] = [props[key], value]
5842
9c6617857032 Support use of duplicate rest filters keys. So URL's like:
John Rouillard <rouilj@ieee.org>
parents: 5824
diff changeset
958 else:
5874
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
959 props[key] = value
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
960 l = [filter_props] # noqa: E741
5870
5ae426616576 Implement pagination in REST API via limit/offset
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5865
diff changeset
961 kw = {}
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
962 if sort:
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
963 l.append(sort)
7854
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
964 if group:
171ff2e487df Add @group for grouping in rest interface.
John Rouillard <rouilj@ieee.org>
parents: 7853
diff changeset
965 l.append(group)
5874
6630baff5f68 Implement exact string search in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5873
diff changeset
966 if exact_props:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
967 kw['exact_match_spec'] = exact_props
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
968 if page['size'] is None:
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
969 kw['limit'] = self.max_response_row_size
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
970 elif page['size'] > 0:
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
971 if page['size'] >= self.max_response_row_size:
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
972 raise UsageError(_(
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
973 "Page size %(page_size)s must be less than admin "
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
974 "limit on query result size: %(max_size)s.") % {
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
975 "page_size": page['size'],
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
976 "max_size": self.max_response_row_size,
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
977 })
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
978 kw['limit'] = self.max_response_row_size
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
979 if page['index'] is not None and page['index'] > 1:
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
980 kw['offset'] = (page['index'] - 1) * page['size']
8126
f7bd22bdef9d Move permission check code to hyperdb
Ralf Schlatterbeck <rsc@runtux.com>
parents: 8094
diff changeset
981 obj_list = class_obj.filter_with_permissions(None, *l, **kw)
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
982
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
983 # Have we hit the max number of returned rows?
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
984 # If so there may be more data that the client
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
985 # has to explicitly page through using offset/@page_index.
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
986 overflow = len(obj_list) == self.max_response_row_size
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
987
5865
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
988 # Note: We don't sort explicitly in python. The filter implementation
04deafac71ab Implement sorting of collections in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5864
diff changeset
989 # of the DB already sorts by ID if no sort option was given.
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
990
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
991 # add verbose elements. 2 and above get identifying label.
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
992 if verbose > 1:
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
993 lp = class_obj.labelprop()
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
994 display_props.add(lp)
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
995
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
996 # extract result from data
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
997 result = {}
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
998 result['collection'] = []
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
999 for item_id in obj_list:
5864
5e8e160fe2a0 Fix security checks for individual properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5851
diff changeset
1000 r = {}
8126
f7bd22bdef9d Move permission check code to hyperdb
Ralf Schlatterbeck <rsc@runtux.com>
parents: 8094
diff changeset
1001 # No need to check permission on id here, as we have only
f7bd22bdef9d Move permission check code to hyperdb
Ralf Schlatterbeck <rsc@runtux.com>
parents: 8094
diff changeset
1002 # security-checked results
f7bd22bdef9d Move permission check code to hyperdb
Ralf Schlatterbeck <rsc@runtux.com>
parents: 8094
diff changeset
1003 r = {'id': item_id, 'link': class_path + item_id}
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1004 if display_props:
6088
00a24243887c Remove redundant permission check
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6086
diff changeset
1005 # format_item does the permission checks
00a24243887c Remove redundant permission check
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6086
diff changeset
1006 r.update(self.format_item(class_obj.getnode(item_id),
00a24243887c Remove redundant permission check
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6086
diff changeset
1007 item_id, props=display_props, verbose=verbose))
5864
5e8e160fe2a0 Fix security checks for individual properties
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5851
diff changeset
1008 if r:
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1009 result['collection'].append(r)
5677
1fa59181ce58 Add support for @verbose=2 to a GET on a collection object. Using this
John Rouillard <rouilj@ieee.org>
parents: 5674
diff changeset
1010
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1011 result_len = len(result['collection'])
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
1012
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1013 if not overflow: # noqa: SIM108 - no nested ternary
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1014 # add back the number of items in the offset.
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1015 total_len = kw['offset'] + result_len if 'offset' in kw \
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1016 else result_len
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1017 else:
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1018 # we have hit the max number of rows configured to be
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1019 # returned. We hae no idea how many rows can match. We
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1020 # could use 0 as the sentinel, but a filter could match 0
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1021 # rows. So return -1 indicating we exceeded the result
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1022 # max size on this query.
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1023 total_len = -1
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1024
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1025 # truncate result['collection'] to page size
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1026 if page['size'] is not None and page['size'] > 0:
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1027 result['collection'] = result['collection'][:page['size']]
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1028
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1029 # pagination - page_index from 1...N
5870
5ae426616576 Implement pagination in REST API via limit/offset
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5865
diff changeset
1030 if page['size'] is not None and page['size'] > 0:
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1031 result['@links'] = {}
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1032 for rel in ('next', 'prev', 'self'):
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1033 if rel == 'next':
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1034 # if current index includes all data, continue
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1035 if page['size'] >= result_len: continue # noqa: E701
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1036 index = page['index'] + 1
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1037 if rel == 'prev':
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1038 if page['index'] <= 1: continue # noqa: E701
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1039 index = page['index'] - 1
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1040 if rel == 'self': index = page['index'] # noqa: E701
5591
a25d79e874cb Added filtering and pagination
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5590
diff changeset
1041
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1042 result['@links'][rel] = []
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1043 result['@links'][rel].append({
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1044 'rel': rel,
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1045 'uri': "%s/%s?@page_index=%s&" % (self.data_path,
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1046 class_name, index) +
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1047 '&'.join(["%s=%s" % (field.name, field.value)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1048 for field in input_payload.value
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1049 if field.name != "@page_index"])})
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
1050
7853
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1051 result['@total_size'] = total_len
03c1b7ae3a68 issue2551328/issue2551264 unneeded next link and total_count incorrect
John Rouillard <rouilj@ieee.org>
parents: 7750
diff changeset
1052 self.client.setHeader("X-Count-Total", str(total_len))
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1053 self.client.setHeader("Allow", "OPTIONS, GET, POST")
5572
c4c88466da69 Added successful response status code
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5571
diff changeset
1054 return 200, result
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1055
7971
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1056 @Routing.route("/data/user/roles", 'GET')
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1057 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1058 def get_roles(self, input_payload):
7971
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1059 """Return all defined roles for users with Admin role.
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1060 The User class property roles is a string but simulate
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1061 it as a MultiLink to an actual Roles class.
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1062 """
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1063 if not self.client.db.user.has_role(self.client.db.getuid(), "Admin"):
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1064 raise Unauthorised(
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1065 'User does not have permission on "user.roles"')
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1066
7983
dd229bbdd32d issue 2551353 - add roundup-classhelper
John Rouillard <rouilj@ieee.org>
parents: 7971
diff changeset
1067 self.client.setHeader(
dd229bbdd32d issue 2551353 - add roundup-classhelper
John Rouillard <rouilj@ieee.org>
parents: 7971
diff changeset
1068 "Allow",
dd229bbdd32d issue 2551353 - add roundup-classhelper
John Rouillard <rouilj@ieee.org>
parents: 7971
diff changeset
1069 "GET"
dd229bbdd32d issue 2551353 - add roundup-classhelper
John Rouillard <rouilj@ieee.org>
parents: 7971
diff changeset
1070 )
dd229bbdd32d issue 2551353 - add roundup-classhelper
John Rouillard <rouilj@ieee.org>
parents: 7971
diff changeset
1071
7971
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1072 return 200, {"collection":
8190
569aff540a21 chore(ruff): whatespace fixes/silence linting
John Rouillard <rouilj@ieee.org>
parents: 8188
diff changeset
1073 [{"id": rolename, "name": rolename}
7971
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1074 for rolename in list(self.db.security.role.keys())]}
fe0348bbe45b issue2551353 - Add roundup-classhelper for 2.4.0 release
John Rouillard <rouilj@ieee.org>
parents: 7854
diff changeset
1075
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1076 @Routing.route("/data/<:class_name>/<:item_id>", 'GET')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1077 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1078 def get_element(self, class_name, item_id, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1079 """GET resource from object URI.
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1080
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1081 This function returns only properties have View permission
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1082 class_name and item_id should be valid already
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1083
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1084 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1085 class_name (string): class name of the resource (Ex: issue, msg)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1086 item_id (string): id of the resource (Ex: 12, 15)
5678
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1087 or (if the class has a key property) this can also be
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1088 the key name, e.g. class_name = status, item_id = 'open'
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1089 input_payload (list): the submitted form of the user
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1090
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1091 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1092 int: http status code 200 (OK)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1093 dict: a dictionary represents the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1094 id: id of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1095 type: class name of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1096 link: link to the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1097 attributes: a dictionary represent the attributes of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1098 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1099 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1100 raise NotFound('Class %s not found' % class_name)
5678
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1101 class_obj = self.db.getclass(class_name)
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1102 uid = self.db.getuid()
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1103 # If it's not numeric it is a key
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1104 if item_id.isdigit():
5679
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
1105 itemid = item_id
5678
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1106 else:
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1107 keyprop = class_obj.getkey()
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1108 try:
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1109 k, v = item_id.split('=', 1)
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1110 if k != keyprop:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1111 raise UsageError("Field %s is not key property" % k)
5678
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1112 except ValueError:
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1113 v = item_id
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1114 if not self.db.security.hasPermission(
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1115 'View', uid, class_name, itemid=item_id, property=keyprop
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1116 ):
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1117 raise Unauthorised(
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1118 'Permission to view %s%s.%s denied'
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1119 % (class_name, item_id, keyprop)
b8e8b1b3ec77 REST: Add key lookup
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5677
diff changeset
1120 )
7372
886a5c767d7e Invalid REST item spec returns 404 rather than 400.
John Rouillard <rouilj@ieee.org>
parents: 7173
diff changeset
1121 try:
886a5c767d7e Invalid REST item spec returns 404 rather than 400.
John Rouillard <rouilj@ieee.org>
parents: 7173
diff changeset
1122 itemid = class_obj.lookup(v)
886a5c767d7e Invalid REST item spec returns 404 rather than 400.
John Rouillard <rouilj@ieee.org>
parents: 7173
diff changeset
1123 except TypeError:
886a5c767d7e Invalid REST item spec returns 404 rather than 400.
John Rouillard <rouilj@ieee.org>
parents: 7173
diff changeset
1124 raise NotFound("Item '%s' not found" % v)
886a5c767d7e Invalid REST item spec returns 404 rather than 400.
John Rouillard <rouilj@ieee.org>
parents: 7173
diff changeset
1125
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1126 if not self.db.security.hasPermission(
5679
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
1127 'View', uid, class_name, itemid=itemid
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1128 ):
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1129 raise Unauthorised(
5679
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
1130 'Permission to view %s%s denied' % (class_name, itemid)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1131 )
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1132
5679
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
1133 node = class_obj.getnode(itemid)
5726
e199d0ae4a25 issue2551033: prevent reverse engineering hidden data by using etags
John Rouillard <rouilj@ieee.org>
parents: 5715
diff changeset
1134 etag = calculate_etag(node, self.db.config.WEB_SECRET_KEY,
5729
9ea2ce9d10cf A few internet references report that etags for the same underlying
John Rouillard <rouilj@ieee.org>
parents: 5727
diff changeset
1135 class_name, itemid, repr_format="json")
5598
be81e8cca38c Added the ability to limit returned fields by GET
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5597
diff changeset
1136 props = None
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1137 protected = False
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1138 verbose = 1
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1139 for form_field in input_payload.value:
5598
be81e8cca38c Added the ability to limit returned fields by GET
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5597
diff changeset
1140 key = form_field.name
be81e8cca38c Added the ability to limit returned fields by GET
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5597
diff changeset
1141 value = form_field.value
8197
5b8d1cb290cb chore(ruff): replace 'x == y or x == z' with 'x in [y,z]'
John Rouillard <rouilj@ieee.org>
parents: 8196
diff changeset
1142 if key in ["@fields", "@attrs"]:
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1143 if props is None:
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
1144 props = set()
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1145 # support , or : separated elements
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1146 f = value.split(",")
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1147 if len(f) == 1:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1148 f = value.split(":")
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
1149 props.update(self.transitive_props(class_name, f))
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1150 elif key == "@protected":
5638
7e3cceec3f4f Allow client to access read only/protected properties like creator,
John Rouillard <rouilj@ieee.org>
parents: 5636
diff changeset
1151 # allow client to request read only
7e3cceec3f4f Allow client to access read only/protected properties like creator,
John Rouillard <rouilj@ieee.org>
parents: 5636
diff changeset
1152 # properties like creator, activity etc.
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1153 # used only if no @fields/@attrs
5638
7e3cceec3f4f Allow client to access read only/protected properties like creator,
John Rouillard <rouilj@ieee.org>
parents: 5636
diff changeset
1154 protected = value.lower() == "true"
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1155 elif key == "@verbose":
8213
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
1156 try:
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
1157 verbose = int(value)
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
1158 except ValueError as e:
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
1159 raise UsageError("When using @verbose: %s" %
14e92a595828 fix(web) issue2551382 - 409 not 400 errors returned
John Rouillard <rouilj@ieee.org>
parents: 8208
diff changeset
1160 (e.args[0]))
5598
be81e8cca38c Added the ability to limit returned fields by GET
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5597
diff changeset
1161
5661
b08a308c273b Better display for Link/Multilink and content
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5660
diff changeset
1162 result = {}
5598
be81e8cca38c Added the ability to limit returned fields by GET
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5597
diff changeset
1163 if props is None:
6090
e097ff5064b8 Allow transitive properties in @fields in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 6088
diff changeset
1164 props = set(class_obj.getprops(protected=protected))
8198
de6b02c23ee9 chore(ruff): replace 'else: if bool_exp:' with 'elif bool_exp:'
John Rouillard <rouilj@ieee.org>
parents: 8197
diff changeset
1165 elif verbose > 1:
8199
622e7bc2db69 chore(ruff): fix indentation level on de6b02c23ee9
John Rouillard <rouilj@ieee.org>
parents: 8198
diff changeset
1166 lp = class_obj.labelprop()
622e7bc2db69 chore(ruff): fix indentation level on de6b02c23ee9
John Rouillard <rouilj@ieee.org>
parents: 8198
diff changeset
1167 props.add(lp)
5598
be81e8cca38c Added the ability to limit returned fields by GET
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5597
diff changeset
1168
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1169 result = {
5679
df9eb574b717 REST: Bug-fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5678
diff changeset
1170 'id': itemid,
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1171 'type': class_name,
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1172 'link': '%s/%s/%s' % (self.data_path, class_name, item_id),
5680
f77209ddd579 Refactored REST code that formats an item for display. A GET on
John Rouillard <rouilj@ieee.org>
parents: 5679
diff changeset
1173 'attributes': self.format_item(node, itemid, props=props,
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1174 verbose=verbose),
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1175 '@etag': etag
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1176 }
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1177
5674
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
1178 self.client.setHeader("ETag", etag)
5572
c4c88466da69 Added successful response status code
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5571
diff changeset
1179 return 200, result
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
1180
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1181 @Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'GET')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1182 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1183 def get_attribute(self, class_name, item_id, attr_name, input_payload):
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1184 """GET resource from attribute URI.
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1185
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1186 This function returns only attribute has View permission
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1187 class_name should be valid already
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1188
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1189 Args:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1190 class_name (string): class name of the resource (Ex: issue, msg)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1191 item_id (string): id of the resource (Ex: 12, 15)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1192 attr_name (string): attribute of the resource (Ex: title, nosy)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1193 input_payload (list): the submitted form of the user
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1194
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1195 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1196 int: http status code 200 (OK)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1197 list: a dictionary represents the attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1198 id: id of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1199 type: class name of the attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1200 link: link to the attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1201 data: data of the requested attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1202 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1203 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1204 raise NotFound('Class %s not found' % class_name)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1205 if not self.db.security.hasPermission(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1206 'View', self.db.getuid(), class_name, attr_name, item_id
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1207 ):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1208 raise Unauthorised(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1209 'Permission to view %s%s %s denied' %
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1210 (class_name, item_id, attr_name)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1211 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1212
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1213 class_obj = self.db.getclass(class_name)
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1214 node = class_obj.getnode(item_id)
5726
e199d0ae4a25 issue2551033: prevent reverse engineering hidden data by using etags
John Rouillard <rouilj@ieee.org>
parents: 5715
diff changeset
1215 etag = calculate_etag(node, self.db.config.WEB_SECRET_KEY,
8190
569aff540a21 chore(ruff): whatespace fixes/silence linting
John Rouillard <rouilj@ieee.org>
parents: 8188
diff changeset
1216 class_name, item_id, repr_format="json")
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1217 try:
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1218 data = node.__getattr__(attr_name)
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1219 except AttributeError:
7750
216662fbaaee fix(i18n): fix incorrect lookup of some translations
John Rouillard <rouilj@ieee.org>
parents: 7726
diff changeset
1220 raise UsageError(_("Invalid attribute %s") % attr_name)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1221 result = {
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1222 'id': item_id,
5631
a5c890d308c3 Add simple support for xml output if the third party dict2xml.py module
John Rouillard <rouilj@ieee.org>
parents: 5630
diff changeset
1223 'type': str(type(data)),
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1224 'link': "%s/%s/%s/%s" %
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1225 (self.data_path, class_name, item_id, attr_name),
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1226 'data': data,
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1227 '@etag': etag
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1228 }
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1229
5674
6dc4dba1c225 REST: Use If-Match header for incoming requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5669
diff changeset
1230 self.client.setHeader("ETag", etag)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1231 return 200, result
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1232
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1233 @Routing.route("/data/<:class_name>", 'POST')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1234 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1235 def post_collection(self, class_name, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1236 """POST a new object to a class
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1237
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1238 If the item is successfully created, the "Location" header will also
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1239 contain the link to the created object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1240
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1241 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1242 class_name (string): class name of the resource (Ex: issue, msg)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1243 input_payload (list): the submitted form of the user
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1244
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1245 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1246 int: http status code 201 (Created)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1247 dict: a reference item to the created object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1248 id: id of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1249 link: path to the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1250 """
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1251 return self.post_collection_inner(class_name, input_payload)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1252
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1253 @Routing.route("/data/<:class_name>/@poe", 'POST')
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1254 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1255 def get_post_once_exactly(self, class_name, input_payload):
6349
c1a672b1ad85 Document post once functions.
John Rouillard <rouilj@ieee.org>
parents: 6311
diff changeset
1256 """Get the Post Once Exactly token to create a new instance of class
c1a672b1ad85 Document post once functions.
John Rouillard <rouilj@ieee.org>
parents: 6311
diff changeset
1257 See https://tools.ietf.org/html/draft-nottingham-http-poe-00"""
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1258 otks = self.db.Otk
6823
fe0091279f50 Refactor session db logging and key generation for sessions/otks
John Rouillard <rouilj@ieee.org>
parents: 6814
diff changeset
1259 poe_key = otks.getUniqueKey()
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1260
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1261 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1262 lifetime = int(input_payload['lifetime'].value)
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1263 except KeyError:
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1264 lifetime = 30 * 60 # 30 minutes
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1265 except ValueError:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1266 raise UsageError("Value 'lifetime' must be an integer specify lifetime in seconds. Got %s." % input_payload['lifetime'].value)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1267
8229
c24b02266077 chore(ruff): handle magic number warnings.
John Rouillard <rouilj@ieee.org>
parents: 8227
diff changeset
1268 if lifetime > 3600 or lifetime < 1: # noqa: PLR2004
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1269 raise UsageError("Value 'lifetime' must be between 1 second and 1 hour (3600 seconds). Got %s." % input_payload['lifetime'].value)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1270
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1271 try:
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1272 # if generic tag exists, we don't care about the value
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1273 is_generic = input_payload['generic']
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1274 # we generate a generic POE token
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1275 is_generic = True
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1276 except KeyError:
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1277 is_generic = False
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1278
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1279 # a POE must be used within lifetime (30 minutes default).
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1280 # Default OTK lifetime is 1 week. So to make different
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1281 # lifetime, take current time, subtract 1 week and add
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1282 # lifetime.
6814
3f60a71b0812 Summary: Support selecion session/otk data store. Add redis as data store.
John Rouillard <rouilj@ieee.org>
parents: 6693
diff changeset
1283 ts = otks.lifetime(lifetime)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1284 if is_generic:
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1285 otks.set(u2s(poe_key), uid=self.db.getuid(),
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1286 __timestamp=ts)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1287 else:
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1288 otks.set(u2s(poe_key), uid=self.db.getuid(),
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1289 class_name=class_name,
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1290 __timestamp=ts)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1291 otks.commit()
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1292
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1293 return 200, {'link': '%s/%s/@poe/%s' %
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1294 (self.data_path, class_name, poe_key),
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1295 'expires': ts + (60 * 60 * 24 * 7)}
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1296
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1297 @Routing.route("/data/<:class_name>/@poe/<:post_token>", 'POST')
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1298 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1299 def post_once_exactly_collection(self, class_name, post_token, input_payload):
6349
c1a672b1ad85 Document post once functions.
John Rouillard <rouilj@ieee.org>
parents: 6311
diff changeset
1300 """Post exactly one to the resource named by class_name"""
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1301 otks = self.db.Otk
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1302
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1303 # remove expired keys so we don't use an expired key
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1304 otks.clean()
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1305
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1306 if not otks.exists(u2s(post_token)):
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1307 # Don't log this failure. Would allow attackers to fill
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1308 # logs.
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1309 raise UsageError("POE token '%s' not valid." % post_token)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1310
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1311 # find out what user owns the key
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1312 user = otks.get(u2s(post_token), 'uid', default=None)
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1313 # find out what class it was meant for
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1314 cn = otks.get(u2s(post_token), 'class_name', default=None)
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1315
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1316 # Invalidate the key as it has been used.
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1317 otks.destroy(u2s(post_token))
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1318 otks.commit()
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1319
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1320 # verify the same user that requested the key is the user
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1321 # using the key.
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1322 if user != self.db.getuid():
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1323 # Tell the roundup admin that there is an issue
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1324 # as the key got compromised.
5799
7ba0ee980fc7 logger.warn is deprecated. Replace with logger.warning.
John Rouillard <rouilj@ieee.org>
parents: 5745
diff changeset
1325 logger.warning(
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1326 'Post Once key owned by user%s was denied. Used by user%s', user, self.db.getuid()
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1327 )
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1328 # Should we indicate to user that the token is invalid
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1329 # because they are not the user who owns the key? It could
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1330 # be a logic bug in the application. But I assume that
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1331 # the key has been stolen and we don't want to tip our hand.
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1332 raise UsageError("POE token '%s' not valid." % post_token)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1333
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1334 if cn != class_name and cn is not None:
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1335 raise UsageError("POE token '%s' not valid for %s, was generated for class %s" % (post_token, class_name, cn))
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1336
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1337 # handle this as though they POSTed to /rest/data/class
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1338 return self.post_collection_inner(class_name, input_payload)
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
1339
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1340 def post_collection_inner(self, class_name, input_payload):
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1341 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1342 raise NotFound('Class %s not found' % class_name)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1343 if not self.db.security.hasPermission(
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1344 'Create', self.db.getuid(), class_name
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1345 ):
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1346 raise Unauthorised('Permission to create %s denied' % class_name)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1347
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1348 class_obj = self.db.getclass(class_name)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1349
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1350 # convert types
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1351 props = self.props_from_args(class_obj, input_payload.value)
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1352
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1353 # check for the key property
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1354 key = class_obj.getkey()
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1355 if key and key not in props:
5576
77d11a24f718 Exceptions
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5575
diff changeset
1356 raise UsageError("Must provide the '%s' property." % key)
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1357
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1358 for key in props:
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1359 if not self.db.security.hasPermission(
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1360 'Create', self.db.getuid(), class_name, property=key
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1361 ):
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1362 raise Unauthorised(
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1363 'Permission to create %s.%s denied' % (class_name, key)
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1364 )
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1365
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1366 # do the actual create
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1367 try:
5562
70df783c4c0b Cleanup, fixed a bug with delete action
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5561
diff changeset
1368 item_id = class_obj.create(**props)
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1369 self.db.commit()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1370 except (TypeError, IndexError, ValueError) as message:
5576
77d11a24f718 Exceptions
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5575
diff changeset
1371 raise ValueError(message)
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1372 except KeyError as msg:
5576
77d11a24f718 Exceptions
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5575
diff changeset
1373 raise UsageError("Must provide the %s property." % msg)
5562
70df783c4c0b Cleanup, fixed a bug with delete action
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5561
diff changeset
1374
5573
89ae4ef34efe Handle response header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5572
diff changeset
1375 # set the header Location
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1376 link = '%s/%s/%s' % (self.data_path, class_name, item_id)
5573
89ae4ef34efe Handle response header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5572
diff changeset
1377 self.client.setHeader("Location", link)
89ae4ef34efe Handle response header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5572
diff changeset
1378
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1379 self.client.setHeader(
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1380 "Allow",
6544
9aa8df0b4426 issue2551178 - fix Traceback in Apache WSGI
John Rouillard <rouilj@ieee.org>
parents: 6543
diff changeset
1381 None
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1382 )
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1383 self.client.setHeader(
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1384 "Access-Control-Allow-Methods",
6544
9aa8df0b4426 issue2551178 - fix Traceback in Apache WSGI
John Rouillard <rouilj@ieee.org>
parents: 6543
diff changeset
1385 None
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1386 )
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1387
5573
89ae4ef34efe Handle response header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5572
diff changeset
1388 # set the response body
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1389 result = {
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1390 'id': item_id,
5573
89ae4ef34efe Handle response header
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5572
diff changeset
1391 'link': link
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1392 }
5572
c4c88466da69 Added successful response status code
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5571
diff changeset
1393 return 201, result
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1394
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1395 @Routing.route("/data/<:class_name>/<:item_id>", 'PUT')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1396 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1397 def put_element(self, class_name, item_id, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1398 """PUT a new content to an object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1399
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1400 Replace the content of the existing object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1401
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1402 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1403 class_name (string): class name of the resource (Ex: issue, msg)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1404 item_id (string): id of the resource (Ex: 12, 15)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1405 input_payload (list): the submitted form of the user
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1406
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1407 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1408 int: http status code 200 (OK)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1409 dict: a dictionary represents the modified object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1410 id: id of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1411 type: class name of the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1412 link: link to the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1413 attributes: a dictionary represent only changed attributes of
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1414 the object
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1415 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1416 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1417 raise NotFound('Class %s not found' % class_name)
5564
da6b5724314f Added Partial PUT
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5563
diff changeset
1418 class_obj = self.db.getclass(class_name)
da6b5724314f Added Partial PUT
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5563
diff changeset
1419
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1420 props = self.props_from_args(class_obj, input_payload.value, item_id)
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1421 for p in props:
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1422 if not self.db.security.hasPermission(
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1423 'Edit', self.db.getuid(), class_name, p, item_id
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1424 ):
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1425 raise Unauthorised(
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1426 'Permission to edit %s of %s%s denied' %
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1427 (p, class_name, item_id)
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1428 )
5564
da6b5724314f Added Partial PUT
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5563
diff changeset
1429 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1430 self.raise_if_no_etag(class_name, item_id, input_payload)
5564
da6b5724314f Added Partial PUT
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5563
diff changeset
1431 result = class_obj.set(item_id, **props)
da6b5724314f Added Partial PUT
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5563
diff changeset
1432 self.db.commit()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1433 except (TypeError, IndexError, ValueError) as message:
5576
77d11a24f718 Exceptions
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5575
diff changeset
1434 raise ValueError(message)
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1435 except KeyError as message:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1436 # key error returned for changing protected keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1437 # and changing invalid keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1438 raise UsageError(message)
5564
da6b5724314f Added Partial PUT
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5563
diff changeset
1439
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1440 result = {
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1441 'id': item_id,
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1442 'type': class_name,
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1443 'link': '%s/%s/%s' % (self.data_path, class_name, item_id),
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1444 'attribute': result
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1445 }
5572
c4c88466da69 Added successful response status code
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5571
diff changeset
1446 return 200, result
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
1447
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1448 @Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'PUT')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1449 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1450 def put_attribute(self, class_name, item_id, attr_name, input_payload):
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1451 """PUT an attribute to an object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1452
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1453 Args:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1454 class_name (string): class name of the resource (Ex: issue, msg)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1455 item_id (string): id of the resource (Ex: 12, 15)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1456 attr_name (string): attribute of the resource (Ex: title, nosy)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1457 input_payload (list): the submitted form of the user
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1458
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1459 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1460 int: http status code 200 (OK)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1461 dict:a dictionary represents the modified object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1462 id: id of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1463 type: class name of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1464 link: link to the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1465 attributes: a dictionary represent only changed attributes of
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1466 the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1467 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1468 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1469 raise NotFound('Class %s not found' % class_name)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1470 if not self.db.security.hasPermission(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1471 'Edit', self.db.getuid(), class_name, attr_name, item_id
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1472 ):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1473 raise Unauthorised(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1474 'Permission to edit %s%s %s denied' %
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1475 (class_name, item_id, attr_name)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1476 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1477 class_obj = self.db.getclass(class_name)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1478 props = {
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1479 attr_name: self.prop_from_arg(
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1480 class_obj, attr_name, input_payload['data'].value, item_id
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1481 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1482 }
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1483
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1484 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1485 self.raise_if_no_etag(class_name, item_id, input_payload)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1486 result = class_obj.set(item_id, **props)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1487 self.db.commit()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1488 except (TypeError, IndexError, ValueError) as message:
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1489 raise ValueError(message)
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1490 except KeyError as message:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1491 # key error returned for changing protected keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1492 # and changing invalid keys
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
1493 raise AttributeError(message)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1494
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1495 result = {
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1496 'id': item_id,
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1497 'type': class_name,
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1498 'link': '%s/%s/%s' % (self.data_path, class_name, item_id),
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1499 'attribute': result
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1500 }
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1501
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1502 return 200, result
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1503
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1504 @Routing.route("/data/<:class_name>", 'DELETE')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1505 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1506 def delete_collection(self, class_name, input_payload):
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1507 """DELETE (retire) all objects in a class
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1508 There is currently no use-case, so this is disabled and
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1509 always returns Unauthorised.
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1510
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1511 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1512 class_name (string): class name of the resource (Ex: issue, msg)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1513 input_payload (list): the submitted form of the user
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1514
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1515 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1516 int: http status code 200 (OK)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1517 dict:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1518 status (string): 'ok'
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1519 count (int): number of deleted objects
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1520 """
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1521 raise Unauthorised('Deletion of a whole class disabled')
5740
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
1522 ''' Hide original code to silence pylint.
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
1523 Leave it here in case we need to re-enable.
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
1524 FIXME: Delete in December 2020 if not used.
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1525 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1526 raise NotFound('Class %s not found' % class_name)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1527 if not self.db.security.hasPermission(
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1528 'Retire', self.db.getuid(), class_name
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1529 ):
5563
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1530 raise Unauthorised('Permission to delete %s denied' % class_name)
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1531
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1532 class_obj = self.db.getclass(class_name)
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1533 for item_id in class_obj.list():
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1534 if not self.db.security.hasPermission(
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1535 'Retire', self.db.getuid(), class_name, itemid=item_id
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1536 ):
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1537 raise Unauthorised(
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1538 'Permission to retire %s %s denied' % (class_name, item_id)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1539 )
5563
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1540
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1541 count = len(class_obj.list())
5563
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1542 for item_id in class_obj.list():
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1543 class_obj.retire (item_id)
5563
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1544
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1545 self.db.commit()
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1546 result = {
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1547 'status': 'ok',
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1548 'count': count
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1549 }
5563
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1550
5572
c4c88466da69 Added successful response status code
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5571
diff changeset
1551 return 200, result
5740
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
1552 '''
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
1553
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1554 @Routing.route("/data/<:class_name>/<:item_id>", 'DELETE')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1555 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1556 def delete_element(self, class_name, item_id, input_payload):
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1557 """DELETE (retire) an object in a class
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1558
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1559 Args:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1560 class_name (string): class name of the resource (Ex: issue, msg)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1561 item_id (string): id of the resource (Ex: 12, 15)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1562 input_payload (list): the submitted form of the user
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1563
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1564 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1565 int: http status code 200 (OK)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1566 dict:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1567 status (string): 'ok'
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1568 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1569 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1570 raise NotFound('Class %s not found' % class_name)
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1571 class_obj = self.db.classes[class_name]
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1572 if not self.db.security.hasPermission(
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1573 'Retire', self.db.getuid(), class_name, itemid=item_id
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1574 ):
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1575 raise Unauthorised(
5604
ed02a1e0aa5d Fix actions
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5602
diff changeset
1576 'Permission to retire %s %s denied' % (class_name, item_id)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1577 )
5563
9a1614ff752d Implement delete collection
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5562
diff changeset
1578
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1579 self.raise_if_no_etag(class_name, item_id, input_payload)
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1580 class_obj.retire(item_id)
5562
70df783c4c0b Cleanup, fixed a bug with delete action
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5561
diff changeset
1581 self.db.commit()
5570
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1582 result = {
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1583 'status': 'ok'
8431a872b008 Response is now following the design format
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5569
diff changeset
1584 }
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1585
5572
c4c88466da69 Added successful response status code
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5571
diff changeset
1586 return 200, result
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
1587
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1588 @Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'DELETE')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1589 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1590 def delete_attribute(self, class_name, item_id, attr_name, input_payload):
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1591 """DELETE an attribute in a object by setting it to None or empty
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1592
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1593 Args:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1594 class_name (string): class name of the resource (Ex: issue, msg)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1595 item_id (string): id of the resource (Ex: 12, 15)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1596 attr_name (string): attribute of the resource (Ex: title, nosy)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1597 input_payload (list): the submitted form of the user
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1598
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1599 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1600 int: http status code 200 (OK)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1601 dict:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1602 status (string): 'ok'
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1603 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1604 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1605 raise NotFound('Class %s not found' % class_name)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1606 if not self.db.security.hasPermission(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1607 'Edit', self.db.getuid(), class_name, attr_name, item_id
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1608 ):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1609 raise Unauthorised(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1610 'Permission to delete %s%s %s denied' %
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1611 (class_name, item_id, attr_name)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1612 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1613
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1614 class_obj = self.db.getclass(class_name)
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1615 if attr_name not in class_obj.getprops(protected=False):
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1616 if attr_name in class_obj.getprops(protected=True):
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1617 raise AttributeError("Attribute '%s' can not be deleted "
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1618 "for class %s." % (attr_name, class_name))
8203
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
1619 raise UsageError("Attribute '%s' not valid for class %s." % (
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
1620 attr_name, class_name))
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1621 if attr_name in class_obj.get_required_props():
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1622 raise UsageError("Attribute '%s' is required by class %s and can not be deleted." % (
5740
abbea26a11df Clean up pylint reports of unused modules, duplicate imports, indent
John Rouillard <rouilj@ieee.org>
parents: 5732
diff changeset
1623 attr_name, class_name))
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1624 props = {}
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1625 prop_obj = class_obj.get(item_id, attr_name)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1626 if isinstance(prop_obj, list):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1627 props[attr_name] = []
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1628 else:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1629 props[attr_name] = None
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1630
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1631 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1632 self.raise_if_no_etag(class_name, item_id, input_payload)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1633 class_obj.set(item_id, **props)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1634 self.db.commit()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1635 except (TypeError, IndexError, ValueError) as message:
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1636 raise ValueError(message)
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1637 except KeyError as message:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1638 # key error returned for changing protected keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1639 # and changing invalid keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1640 raise UsageError(message)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1641
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1642 result = {
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1643 'status': 'ok'
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1644 }
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1645
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1646 return 200, result
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1647
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1648 @Routing.route("/data/<:class_name>/<:item_id>", 'PATCH')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1649 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1650 def patch_element(self, class_name, item_id, input_payload):
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1651 """PATCH an object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1652
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1653 Patch an element using 3 operators
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1654 ADD : Append new value to the object's attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1655 REPLACE: Replace object's attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1656 REMOVE: Clear object's attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1657
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1658 Args:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1659 class_name (string): class name of the resource (Ex: issue, msg)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1660 item_id (string): id of the resource (Ex: 12, 15)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1661 input_payload (list): the submitted form of the user
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1662
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1663 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1664 int: http status code 200 (OK)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1665 dict: a dictionary represents the modified object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1666 id: id of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1667 type: class name of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1668 link: link to the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1669 attributes: a dictionary represent only changed attributes of
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1670 the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1671 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1672 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1673 raise NotFound('Class %s not found' % class_name)
5580
d5a54b1851aa Add default op action for Patch
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5579
diff changeset
1674 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1675 op = input_payload['@op'].value.lower()
5580
d5a54b1851aa Add default op action for Patch
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5579
diff changeset
1676 except KeyError:
5593
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
1677 op = self.__default_patch_op
5578
c2214d0c9df8 Added PATCH an element
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5577
diff changeset
1678 class_obj = self.db.getclass(class_name)
c2214d0c9df8 Added PATCH an element
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5577
diff changeset
1679
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1680 self.raise_if_no_etag(class_name, item_id, input_payload)
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1681
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1682 # if patch operation is action, call the action handler
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1683 action_args = [class_name + item_id]
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1684 if op == 'action':
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1685 # extract action_name and action_args from form fields
5926
3ca3bfe6de16 Code-robustness, error-message improved
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5904
diff changeset
1686 name = None
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1687 for form_field in input_payload.value:
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1688 key = form_field.name
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1689 value = form_field.value
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
1690 if key == "@action_name":
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1691 name = value
5659
1e51a709431c Make Searching work in REST API
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5658
diff changeset
1692 elif key.startswith('@action_args'):
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1693 action_args.append(value)
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1694
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1695 if name in self.actions:
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1696 action_type = self.actions[name]
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1697 else:
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1698 raise UsageError(
5926
3ca3bfe6de16 Code-robustness, error-message improved
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5904
diff changeset
1699 'action "%s" is not supported, allowed: %s' %
3ca3bfe6de16 Code-robustness, error-message improved
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5904
diff changeset
1700 (name, ', '.join(self.actions.keys()))
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1701 )
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1702 action = action_type(self.db, self.translator)
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1703 result = action.execute(*action_args)
5578
c2214d0c9df8 Added PATCH an element
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5577
diff changeset
1704
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1705 result = {
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1706 'id': item_id,
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1707 'type': class_name,
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1708 'link': '%s/%s/%s' % (self.data_path, class_name, item_id),
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1709 'result': result
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1710 }
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1711 else:
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1712 # else patch operation is processing data
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1713 props = self.props_from_args(class_obj, input_payload.value, item_id,
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1714 skip_protected=False)
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1715
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1716 required_props = class_obj.get_required_props()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1717 for prop in props:
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1718 if not self.db.security.hasPermission(
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1719 'Edit', self.db.getuid(), class_name, prop, item_id
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1720 ):
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1721 raise Unauthorised(
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1722 'Permission to edit %s of %s%s denied' %
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1723 (prop, class_name, item_id)
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1724 )
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1725 if op == 'remove' and prop in required_props:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1726 raise UsageError(
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1727 "Attribute '%s' is required by class %s "
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1728 "and can not be removed." % (prop, class_name)
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1729 )
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1730
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1731 props[prop] = self.patch_data(
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1732 op, class_obj.get(item_id, prop), props[prop]
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1733 )
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1734
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1735 try:
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1736 result = class_obj.set(item_id, **props)
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1737 self.db.commit()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1738 except (TypeError, IndexError, ValueError) as message:
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1739 raise ValueError(message)
5578
c2214d0c9df8 Added PATCH an element
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5577
diff changeset
1740
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1741 result = {
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1742 'id': item_id,
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1743 'type': class_name,
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1744 'link': '%s/%s/%s' % (self.data_path, class_name, item_id),
5599
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1745 'attribute': result
a76d88673375 Added Patch operator 'action'
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5598
diff changeset
1746 }
5578
c2214d0c9df8 Added PATCH an element
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5577
diff changeset
1747 return 200, result
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
1748
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1749 @Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'PATCH')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1750 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1751 def patch_attribute(self, class_name, item_id, attr_name, input_payload):
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1752 """PATCH an attribute of an object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1753
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1754 Patch an element using 3 operators
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1755 ADD : Append new value to the attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1756 REPLACE: Replace attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1757 REMOVE: Clear attribute
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1758
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1759 Args:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1760 class_name (string): class name of the resource (Ex: issue, msg)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1761 item_id (string): id of the resource (Ex: 12, 15)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1762 attr_name (string): attribute of the resource (Ex: title, nosy)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1763 input_payload (list): the submitted form of the user
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1764
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1765 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1766 int: http status code 200 (OK)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1767 dict: a dictionary represents the modified object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1768 id: id of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1769 type: class name of the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1770 link: link to the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1771 attributes: a dictionary represent only changed attributes of
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1772 the object
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1773 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1774 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1775 raise NotFound('Class %s not found' % class_name)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1776 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1777 op = input_payload['@op'].value.lower()
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1778 except KeyError:
5593
344b6a87dac6 Added support to print error
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5591
diff changeset
1779 op = self.__default_patch_op
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1780
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1781 if not self.db.security.hasPermission(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1782 'Edit', self.db.getuid(), class_name, attr_name, item_id
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1783 ):
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1784 raise Unauthorised(
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1785 'Permission to edit %s%s %s denied' %
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1786 (class_name, item_id, attr_name)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1787 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1788
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1789 prop = attr_name
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1790 class_obj = self.db.getclass(class_name)
8203
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
1791 if (attr_name not in class_obj.getprops(protected=False) and
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
1792 attr_name in class_obj.getprops(protected=True)):
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1793 raise AttributeError("Attribute '%s' can not be updated "
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1794 "for class %s." % (attr_name, class_name))
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1795
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1796 self.raise_if_no_etag(class_name, item_id, input_payload)
5630
07abc8d36940 Add etag support to rest interface to prevent multiple users from
John Rouillard <rouilj@ieee.org>
parents: 5622
diff changeset
1797
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1798 props = {
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1799 prop: self.prop_from_arg(
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1800 class_obj, prop, input_payload['data'].value, item_id
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1801 )
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1802 }
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1803
5595
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
1804 props[prop] = self.patch_data(
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
1805 op, class_obj.get(item_id, prop), props[prop]
65caddd54da2 Handle operation for patch separately
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5594
diff changeset
1806 )
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1807
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1808 try:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1809 result = class_obj.set(item_id, **props)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1810 self.db.commit()
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
1811 except (TypeError, IndexError, ValueError) as message:
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1812 raise ValueError(message)
5705
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1813 except KeyError as message:
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1814 # key error returned for changing protected keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1815 # and changing invalid keys
457fc482e6b1 Method PUT: ignore specification of protected properties which can not
John Rouillard <rouilj@ieee.org>
parents: 5702
diff changeset
1816 raise UsageError(message)
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1817
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1818 result = {
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1819 'id': item_id,
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1820 'type': class_name,
5600
e2c74d8121f3 Update resource links
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5599
diff changeset
1821 'link': '%s/%s/%s' % (self.data_path, class_name, item_id),
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1822 'attribute': result
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1823 }
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1824 return 200, result
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1825
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1826 @Routing.route("/data/<:class_name>", 'OPTIONS')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1827 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1828 def options_collection(self, class_name, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1829 """OPTION return the HTTP Header for the class uri
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1830
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1831 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1832 int: http status code 204 (No content)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1833 body (string): an empty string
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1834 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1835 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1836 raise NotFound('Class %s not found' % class_name)
5702
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1837 self.client.setHeader(
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1838 "Allow",
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1839 "OPTIONS, GET, POST"
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1840 )
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1841
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1842 self.client.setHeader(
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1843 "Access-Control-Allow-Methods",
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1844 "OPTIONS, GET, POST"
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1845 )
5575
7a7927643357 Added OPTIONS method
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5574
diff changeset
1846 return 204, ""
7a7927643357 Added OPTIONS method
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5574
diff changeset
1847
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1848 @Routing.route("/data/<:class_name>/<:item_id>", 'OPTIONS')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1849 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1850 def options_element(self, class_name, item_id, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1851 """OPTION return the HTTP Header for the object uri
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1852
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1853 Returns:
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1854 int: http status code 204 (No content)
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1855 body (string): an empty string
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
1856 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1857 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1858 raise NotFound('Class %s not found' % class_name)
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1859 self.client.setHeader(
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
1860 "Accept-Patch",
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1861 "application/x-www-form-urlencoded, multipart/form-data"
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1862 )
5702
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1863 self.client.setHeader(
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1864 "Allow",
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1865 "OPTIONS, GET, PUT, DELETE, PATCH"
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1866 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1867 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1868 "Access-Control-Allow-Methods",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1869 "OPTIONS, GET, PUT, DELETE, PATCH"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1870 )
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1871 return 204, ""
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1872
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1873 @Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'OPTIONS')
5587
cb2b320fde16 Added decorator to handle formatting output data
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5584
diff changeset
1874 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1875 def option_attribute(self, class_name, item_id, attr_name, input_payload):
5584
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1876 """OPTION return the HTTP Header for the attribute uri
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1877
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1878 Returns:
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1879 int: http status code 204 (No content)
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1880 body (string): an empty string
53098db851f2 Added attribute URI handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5583
diff changeset
1881 """
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1882 if class_name not in self.db.classes:
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
1883 raise NotFound('Class %s not found' % class_name)
5702
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1884 class_obj = self.db.getclass(class_name)
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1885 if attr_name in class_obj.getprops(protected=False):
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1886 self.client.setHeader(
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1887 "Accept-Patch",
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1888 "application/x-www-form-urlencoded, multipart/form-data"
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1889 )
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1890 self.client.setHeader(
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1891 "Allow",
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1892 "OPTIONS, GET, PUT, DELETE, PATCH"
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1893 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1894 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1895 "Access-Control-Allow-Methods",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1896 "OPTIONS, GET, PUT, DELETE, PATCH"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1897 )
5702
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1898 elif attr_name in class_obj.getprops(protected=True):
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1899 # It must match a protected prop. These can't be written.
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1900 self.client.setHeader(
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1901 "Allow",
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1902 "OPTIONS, GET"
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1903 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1904 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1905 "Access-Control-Allow-Methods",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1906 "OPTIONS, GET"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
1907 )
5702
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
1908 else:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1909 raise NotFound('Attribute %s not valid for Class %s' % (
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
1910 attr_name, class_name))
5575
7a7927643357 Added OPTIONS method
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5574
diff changeset
1911 return 204, ""
7a7927643357 Added OPTIONS method
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5574
diff changeset
1912
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1913 @openapi_doc({
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1914 "summary": "Describe Roundup rest endpoint.",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1915 "description": (
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1916 "Report all supported api versions "
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1917 "and default api version. "
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1918 "Also report next level of link "
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1919 "endpoints below /rest endpoint"),
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1920 "responses": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1921 "200": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1922 "description": "Successful response.",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1923 "content": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1924 "application/json": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1925 "examples": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1926 "success": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1927 "summary": "Normal json data.",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1928 "value": """
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1929 {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1930 "data": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1931 "default_version": 1,
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1932 "supported_versions": [ 1 ],
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1933 "links": [
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1934 {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1935 "uri": "https://tracker.example.com/demo/rest",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1936 "rel": "self"
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1937 },
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1938 {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1939 "uri": "https://tracker.example.com/demo/rest/data",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1940 "rel": "data"
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1941 },
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1942 {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1943 "uri": "https://tracker.example.com/demo/rest/summary",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1944 "rel": "summary"
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1945 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1946 ]
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1947 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1948 }"""
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1949 }
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1950 }
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1951 },
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1952 "application/xml": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1953 "examples": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1954 "success": {
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1955 "summary": "Normal xml data",
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1956 "value": """
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1957 <dataf type="dict">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1958 <default_version type="int">1</default_version>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1959 <supported_versions type="list">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1960 <item type="int">1</item>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1961 </supported_versions>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1962 <links type="list">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1963 <item type="dict">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1964 <uri type="str">https://rouilj.dynamic-dns.net/sysadmin/rest</uri>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1965 <rel type="str">self</rel>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1966 </item>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1967 <item type="dict">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1968 <uri type="str">https://rouilj.dynamic-dns.net/sysadmin/rest/data</uri>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1969 <rel type="str">data</rel>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1970 </item>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1971 <item type="dict">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1972 <uri type="str">https://rouilj.dynamic-dns.net/sysadmin/rest/summary</uri>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1973 <rel type="str">summary</rel>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1974 </item>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1975 <item type="dict">
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1976 <uri type="str">https://rouilj.dynamic-dns.net/sysadmin/rest/summary2</uri>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1977 <rel type="str">summary2</rel>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1978 </item>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1979 </links>
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1980 </dataf>"""
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1981 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1982 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1983 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1984 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1985 }
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
1986 }
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1987 }
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1988 )
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
1989 @Routing.route("/")
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
1990 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
1991 def describe(self, input_payload):
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1992 """Describe the rest endpoint. Return direct children in
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1993 links list.
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1994 """
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1995
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1996 # paths looks like ['^rest/$', '^rest/summary$',
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1997 # '^rest/data/<:class>$', ...]
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1998 paths = Routing._Routing__route_map.keys()
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
1999
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2000 links = []
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2001 # p[1:-1] removes ^ and $ from regexp
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2002 # if p has only 1 /, it's a child of rest/ root.
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2003 child_paths = sorted([p[1:-1] for p in paths if
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2004 p.count('/') == 1])
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2005 for p in child_paths:
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2006 # p.split('/')[1] is the residual path after
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2007 # removing rest/. child_paths look like:
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2008 # ['rest/', 'rest/summary'] etc.
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2009 rel = p.split('/')[1]
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2010 if rel:
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2011 rel_path = "/" + rel
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2012 else:
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2013 rel_path = rel
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2014 rel = "self"
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2015 links.append({"uri": self.base_path + rel_path,
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2016 "rel": rel})
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2017
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2018 result = {
5685
4b4885f0c6ad Set up basic framework for handling versioning of interface.
John Rouillard <rouilj@ieee.org>
parents: 5682
diff changeset
2019 "default_version": self.__default_api_version,
4b4885f0c6ad Set up basic framework for handling versioning of interface.
John Rouillard <rouilj@ieee.org>
parents: 5682
diff changeset
2020 "supported_versions": self.__supported_api_versions,
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2021 "links": links
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2022 }
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2023
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2024 return 200, result
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2025
6384
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2026 @Routing.route("/", 'OPTIONS')
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2027 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2028 def options_describe(self, input_payload):
6384
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2029 """OPTION return the HTTP Header for the root
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2030
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2031 Returns:
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2032 int: http status code 204 (No content)
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2033 body (string): an empty string
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2034 """
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2035 self.client.setHeader(
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2036 "Allow",
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2037 "OPTIONS, GET"
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2038 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2039 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2040 "Access-Control-Allow-Methods",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2041 "OPTIONS, GET"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2042 )
6384
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2043 return 204, ""
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2044
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2045 @Routing.route("/data")
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2046 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2047 def data(self, input_payload):
5658
3401daf8613b Fix hardcoded /data
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5655
diff changeset
2048 """Describe the subelements of data
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2049
5658
3401daf8613b Fix hardcoded /data
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5655
diff changeset
2050 One entry for each class the user may view
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2051 """
5658
3401daf8613b Fix hardcoded /data
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5655
diff changeset
2052 result = {}
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2053 uid = self.db.getuid()
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2054 for cls in sorted(self.db.classes):
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2055 if self.db.security.hasPermission('View', uid, cls):
8201
d5ad7fcb9bf6 chore(ruff): replace dict(...) with equivalent {...}
John Rouillard <rouilj@ieee.org>
parents: 8199
diff changeset
2056 result[cls] = {"link": self.base_path + '/data/' + cls}
5632
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2057 return 200, result
a29a8dae2095 Initial implementation of function to return data for / and /data
John Rouillard <rouilj@ieee.org>
parents: 5631
diff changeset
2058
6384
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2059 @Routing.route("/data", 'OPTIONS')
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2060 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2061 def options_data(self, input_payload):
6384
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2062 """OPTION return the HTTP Header for the /data element
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2063
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2064 Returns:
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2065 int: http status code 204 (No content)
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2066 body (string): an empty string
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2067 """
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2068 self.client.setHeader(
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2069 "Allow",
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2070 "OPTIONS, GET"
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2071 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2072 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2073 "Access-Control-Allow-Methods",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2074 "OPTIONS, GET"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2075 )
6384
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2076 return 204, ""
66a061e52435 Test options in rest interface against live server; rest doc update
John Rouillard <rouilj@ieee.org>
parents: 6349
diff changeset
2077
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
2078 @Routing.route("/summary")
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2079 @_data_decorator
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2080 def summary(self, input_payload):
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2081 """Get a summary of resource from class URI.
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2082
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2083 This function returns only items have View permission
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2084 class_name should be valid already
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2085
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2086 Args:
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2087 class_name (string): class name of the resource (Ex: issue, msg)
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2088 input_payload (list): the submitted form of the user
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2089
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2090 Returns:
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2091 int: http status code 200 (OK)
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2092 list:
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2093 """
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2094 if not self.db.security.hasPermission(
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2095 'View', self.db.getuid(), 'issue'
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2096 ) and not self.db.security.hasPermission(
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2097 'View', self.db.getuid(), 'status'
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2098 ) and not self.db.security.hasPermission(
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2099 'View', self.db.getuid(), 'issue'
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2100 ):
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2101 raise Unauthorised('Permission to view summary denied')
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2102
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2103 old = date.Date('-1w')
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2104
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2105 created = []
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2106 summary = {}
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2107 messages = []
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2108
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2109 # loop through all the recently-active issues
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2110 for issue_id in self.db.issue.filter(None, {'activity': '-1w;'}):
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2111 num = 0
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2112 status_name = self.db.status.get(
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2113 self.db.issue.get(issue_id, 'status'),
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2114 'name'
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2115 )
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2116 issue_object = {
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2117 'id': issue_id,
5621
39dbe83643c0 Fix path of links in /rest/summary.
John Rouillard <rouilj@ieee.org>
parents: 5620
diff changeset
2118 'link': self.base_path + '/data/issue/' + issue_id,
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2119 'title': self.db.issue.get(issue_id, 'title')
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2120 }
6009
d56e290ecab7 flake8 cleanups. Rename unused for loop vars argument unpacking.
John Rouillard <rouilj@ieee.org>
parents: 5998
diff changeset
2121 for _x, ts, _uid, action, data in self.db.issue.history(issue_id):
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2122 if ts < old:
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2123 continue
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2124 if action == 'create':
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2125 created.append(issue_object)
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2126 elif action == 'set' and 'messages' in data:
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2127 num += 1
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2128 summary.setdefault(status_name, []).append(issue_object)
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2129 messages.append((num, issue_object))
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2130
5668
a4bb88a1a643 A fix for https://issues.roundup-tracker.org/issue2551034
John Rouillard <rouilj@ieee.org>
parents: 5662
diff changeset
2131 sorted(messages, key=lambda tup: tup[0], reverse=True)
5596
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2132
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2133 result = {
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2134 'created': created,
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2135 'summary': summary,
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2136 'most_discussed': messages[:10]
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2137 }
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2138
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2139 return 200, result
55fa81de6a57 Added summary page
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5595
diff changeset
2140
5732
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2141 def getRateLimit(self):
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2142 ''' By default set one rate limit for all users. Values
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2143 for period (in seconds) and count set in config.
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2144 However there is no reason these settings couldn't
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2145 be pulled from the user's entry in the database. So define
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2146 this method to allow a user to change it in the interfaces.py
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2147 to use a field in the user object.
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2148 '''
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2149 # FIXME verify can override from interfaces.py.
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2150 calls = self.db.config.WEB_API_CALLS_PER_INTERVAL
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2151 interval = self.db.config.WEB_API_INTERVAL_IN_SEC
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2152 if calls and interval:
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2153 return RateLimit(calls, timedelta(seconds=interval))
8203
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
2154
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
2155 # disable rate limiting if either parameter is 0
ef1333b153e3 chore(ruff): changes to else/elif and nested ifs to reduce nesting
John Rouillard <rouilj@ieee.org>
parents: 8201
diff changeset
2156 return None
5732
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2157
7605
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2158 def handle_apiRateLimitExceeded(self, apiRateLimit):
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2159 """Determine if the rate limit is exceeded.
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2160
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2161 If not exceeded, return False and the rate limit header values.
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2162 If exceeded, return error message and None
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2163 """
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2164 gcra = Gcra()
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2165 # unique key is an "ApiLimit-" prefix and the uid)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2166 apiLimitKey = "ApiLimit-%s" % self.db.getuid()
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2167 otk = self.db.Otk
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2168 try:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2169 val = otk.getall(apiLimitKey)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2170 gcra.set_tat_as_string(apiLimitKey, val['tat'])
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2171 except KeyError:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2172 # ignore if tat not set, it's 1970-1-1 by default.
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2173 pass
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2174 # see if rate limit exceeded and we need to reject the attempt
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2175 reject = gcra.update(apiLimitKey, apiRateLimit)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2176
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2177 # Calculate a timestamp that will make OTK expire the
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2178 # unused entry 1 hour in the future
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2179 ts = otk.lifetime(3600)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2180 otk.set(apiLimitKey,
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2181 tat=gcra.get_tat_as_string(apiLimitKey),
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2182 __timestamp=ts)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2183 otk.commit()
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2184
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2185 limitStatus = gcra.status(apiLimitKey, apiRateLimit)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2186 if not reject:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2187 return (False, limitStatus)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2188
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2189 for header, value in limitStatus.items():
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2190 self.client.setHeader(header, value)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2191
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2192 # User exceeded limits: tell humans how long to wait
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2193 # Headers above will do the right thing for api
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2194 # aware clients.
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2195 try:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2196 retry_after = limitStatus['Retry-After']
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2197 except KeyError:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2198 # handle race condition. If the time between
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2199 # the call to grca.update and grca.status
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2200 # is sufficient to reload the bucket by 1
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2201 # item, Retry-After will be missing from
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2202 # limitStatus. So report a 1 second delay back
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2203 # to the client. We treat update as sole
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2204 # source of truth for exceeded rate limits.
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2205 retry_after = '1'
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2206 self.client.setHeader('Retry-After', retry_after)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2207
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2208 msg = _("Api rate limits exceeded. Please wait: %s seconds.") % retry_after
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2209 output = self.error_obj(429, msg, source="ApiRateLimiter")
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2210
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2211 # expose these headers to rest clients. Otherwise they can't
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2212 # respond to:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2213 # rate limiting (*RateLimit*, Retry-After)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2214 # obsolete API endpoint (Sunset)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2215 # options request to discover supported methods (Allow)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2216 self.client.setHeader(
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2217 "Access-Control-Expose-Headers",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2218 ", ".join([
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2219 "X-RateLimit-Limit",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2220 "X-RateLimit-Remaining",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2221 "X-RateLimit-Reset",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2222 "X-RateLimit-Limit-Period",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2223 "Retry-After",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2224 "Sunset",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2225 "Allow",
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2226 ])
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2227 )
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2228
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2229 return (self.format_dispatch_output(
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2230 self.__default_accept_type,
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2231 output,
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2232 True # pretty print for this error case as a
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2233 # human may read it
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2234 ), None)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2235
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2236 def create_valid_content_types(self, mime_type):
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2237 """Return a list of mime types matching the submitted mime_type.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2238
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2239 For a MIME type of type/subtype return a list that matches:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2240
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2241 type/subtype
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2242 type/*
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2243 application/octet-stream
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2244 */*
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2245
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2246 If mime_type for the file is empty return:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2247
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2248 ["text/plain", "text/*", "application/octet-stream", */*]
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2249
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2250 Issue messages (msg) often are missing a mime type. So we
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2251 treat them text/plain. text/plain is the value of
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2252 RestfulInterface.default_text_file_mimetype. This can be
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2253 changed.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2254
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2255 The first mime type in the list is usually used as the
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2256 Content-Type in the http response.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2257
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2258 """
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2259 valid_binary_content_types = []
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2260
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2261 if mime_type:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2262 # strip off MIME parameters. We may do param matching
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2263 # in the future but not now.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2264 mime_type, *_more = mime_type.split(';')
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2265 # remove spaces in case they snuck in.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2266 mime_type = mime_type.strip()
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2267 # Put the mime_type first. If the user is requesting a
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2268 # specific type/subtype we will match on first item.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2269 # Also first item is returned as Content-type/accept_type.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2270 valid_binary_content_types.append(mime_type)
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2271
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2272 # For mime type main_type/subtype add main_type/*
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2273 try:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2274 (main_type, _subtype) = mime_type.split('/', 2)
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2275 except ValueError:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2276 # malformed mime type, 0, 2+ '/' chars
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2277 # don't add anything
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2278 pass
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2279 else:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2280 valid_binary_content_types.append(main_type + "/*")
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2281
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2282 if not mime_type:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2283 # allow text/* as msg items can have empty type field
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2284 # also match text/* for text/plain, text/x-rst,
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2285 # text/markdown, text/html etc.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2286 #
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2287 # Ideally we would know the subtype.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2288 #
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2289 # text/plain works for most messages, but
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2290 # text/markdown could be valid for a modified tracker.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2291 #
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2292 # Value can be overridden by interfaces.py, but consider
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2293 # adding config setting for the default file mime type.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2294 valid_binary_content_types.append(self.default_text_file_mimetype)
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2295 valid_binary_content_types.append("text/*")
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2296
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2297 # Octet-stream should be allowed for any content.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2298 # If mime_type unparsable, the file will get the
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2299 # Content-Type of application/octet-stream as this will
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2300 # be the first element of the returned list.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2301 valid_binary_content_types.append("application/octet-stream")
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2302
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2303 # */* should be allowed for any content.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2304 valid_binary_content_types.append("*/*")
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2305
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2306 return valid_binary_content_types
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2307
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2308 def determine_output_format(self, uri):
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2309 """Returns tuple of:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2310
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2311 (format for returned output,
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2312 possibly modified uri,
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2313 output error object (if error else None))
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2314
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2315 Verify that client is requesting an output we can produce
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2316 with a version we support.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2317
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2318 Only application/json and application/xml (optional)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2319 are currently supported. .vcard might be useful
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2320 in the future for user objects.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2321
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2322 Find format for returned output:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2323
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2324 1) Get format from url extension (.json, .xml) and return
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2325 if invalid return (None, uri, 406 error)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2326 if not found continue
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2327 2) Parse Accept header obeying q values
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2328 if header unparsible return 400 error object.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2329 3) if empty or missing Accept header
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2330 return self.__default_accept_type
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2331 4) match and return best Accept header/version
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2332 this includes matching mime types for file downloads
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2333 using the binary_content property
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2334 if version error found in matching type return 406 error
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2335 5) if no requested format is supported return 406
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2336 error
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2337
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2338 """
8208
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2339 MAX_MIME_EXTENSION_LENGTH = 11 # application in /etc/mime.types
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2340
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2341 # get the request format for response
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2342 # priority : extension from uri (/rest/data/issue.json)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2343 # only json or xml valid at this time.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2344 # header (Accept: application/json, application/xml)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2345 # default (application/json)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2346 ext_type = os.path.splitext(urlparse(uri).path)[1][1:]
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2347
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2348 # Check to see if the extension matches a value in
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2349 # self.__accepted_content_type. In the future other output
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2350 # such as .vcard for downloading user info can be
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2351 # supported. This method also allow detection of mistyped
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2352 # types like jon for json. Limit extension length to less than
8208
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2353 # MAX_MIME_EXTENSION_LENGTH characters to allow passing JWT
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2354 # via URL path. Could be useful for magic link login method or
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2355 # account recovery workflow, using a JWT with a short
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2356 # expiration time and limited rights (e.g. only password
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2357 # change permission))
d87350f56100 chore(ruff): use variable not magic number.
John Rouillard <rouilj@ieee.org>
parents: 8207
diff changeset
2358 if ext_type and (len(ext_type) < MAX_MIME_EXTENSION_LENGTH):
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2359 if ext_type not in list(self.__accepted_content_type.values()):
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2360 self.client.response_code = 406
8272
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2361 return (
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2362 None, uri,
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2363 self.error_obj(
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2364 406,
8275
e3099f18a395 fix: missing space in translated message.
John Rouillard <rouilj@ieee.org>
parents: 8272
diff changeset
2365 _("Content type '%(requested)s' requested in URL is "
8272
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2366 "not available.\nAcceptable types: "
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2367 "%(acceptable)s\n") %
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2368 {"requested": ext_type,
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2369 "acceptable": ", ".join(sorted(
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2370 set(self.__accepted_content_type.values())))}))
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2371
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2372 # strip extension so uri makes sense.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2373 # E.G. .../issue.json -> .../issue
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2374 uri = uri[:-(len(ext_type) + 1)]
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2375 return (ext_type, uri, None)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2376
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2377 # parse Accept header and get the content type
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2378 # Acceptable types ordered with preferred one (by q value)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2379 # first in list.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2380 try:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2381 accept_header = parse_accept_header(
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2382 self.client.request.headers.get('Accept')
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2383 )
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2384 except UsageError as e:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2385 self.client.response_code = 406
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2386 return (None, uri, self.error_obj(
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2387 400, _("Unable to parse Accept Header. %(error)s. "
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2388 "Acceptable types: */*, %(acceptable_types)s") % {
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2389 'error': e.args[0],
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2390 'acceptable_types': ", ".join(sorted(
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2391 self.__accepted_content_type.keys()))}))
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2392
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2393 if not accept_header:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2394 # we are using the default
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2395 return (self.__default_accept_type, uri, None)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2396
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2397 accept_type = ""
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2398 valid_binary_content_types = None
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2399 if uri.endswith("/binary_content"):
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2400 request_path = uri
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2401 request_class, request_id = request_path.split('/')[-3:-1]
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2402 try:
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2403 declared_type = self.db.getclass(
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2404 request_class).get(request_id, "type")
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2405 except (KeyError, IndexError):
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2406 # class (KeyError) or
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2407 # id (IndexError) does not exist
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2408 # Return unknown mime type and no error.
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2409 # The 400/404 error will be thrown by other code.
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2410 return (None, uri, None)
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2411
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2412 valid_binary_content_types = self.create_valid_content_types(
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2413 declared_type)
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2414
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2415 for part in accept_header:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2416 if accept_type:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2417 # we accepted the best match, stop searching for
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2418 # lower quality matches. A break happens in every clause
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2419 # that sets accept_type. This is just a safety.
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2420 break
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2421
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2422 # check for structured rest return types (json xml)
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2423 if part[0] in self.__accepted_content_type:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2424 accept_type = self.__accepted_content_type[part[0]]
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2425 # Version order:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2426 # 1) accept header version=X specifier
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2427 # application/vnd.x.y; version=1
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2428 # 2) from type in accept-header type/subtype-vX
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2429 # application/vnd.x.y-v1
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2430 # 3) from @apiver in query string to make browser
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2431 # use easy
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2432 # This code handles 1 and 2. Set api_version to none
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2433 # to trigger @apiver parsing below
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2434 # Places that need the api_version info should
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2435 # use default if version = None
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2436 try:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2437 self.api_version = int(part[1]['version'])
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2438 if self.api_version not in self.__supported_api_versions:
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2439 raise ValueError
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2440 except KeyError:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2441 self.api_version = None
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2442 except (ValueError, TypeError):
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2443 self.client.response_code = 406
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2444 # TypeError if int(None)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2445 msg = _("Unrecognized api version: %s. "
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2446 "See /rest without specifying api version "
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2447 "for supported versions.") % (
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2448 part[1]['version'])
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2449 return (None, uri,
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2450 self.error_obj(406, msg))
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2451 break
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2452
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2453 # client.py sets 'X-Content-Type-Options: nosniff'
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2454 # for file downloads (sendfile) via the html interface,
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2455 # so we should be able to set it in this code as well.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2456 if not valid_binary_content_types:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2457 if part[0] == "*/*":
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2458 accept_type = "json"
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2459 break
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2460
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2461 # check type of binary_content
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2462 elif part[0] in valid_binary_content_types:
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2463 self.client.setHeader("X-Content-Type-Options", "nosniff")
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2464 # try to return most exact MIME type if request
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2465 # includes wildcard.
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2466 accept_type = part[0] if part[0].find('*') == -1 \
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2467 else valid_binary_content_types[0]
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2468 break
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2469
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2470 # accept_type will be empty only if there is an Accept header
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2471 # with invalid values.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2472 if accept_type:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2473 return (accept_type, uri, None)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2474
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2475 if valid_binary_content_types:
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2476 report_acceptable_types = valid_binary_content_types
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2477 else:
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2478 report_acceptable_types = list(self.__accepted_content_type.keys())
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2479 report_acceptable_types.append("*/*")
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2480
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2481 return (None, uri,
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2482 self.error_obj(
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2483 406,
8272
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2484 _("Requested content type(s) '%(requested)s' not "
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2485 "available.\nAcceptable mime types are: "
8272
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2486 "%(acceptable)s") %
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2487 {"requested":
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2488 self.client.request.headers.get('Accept'),
fde5893b6c25 fix: correct strings with multiple %s that can't be translated
John Rouillard <rouilj@ieee.org>
parents: 8230
diff changeset
2489 "acceptable": ", ".join(sorted(
8543
1ffa1f42e1da refactor: rework mime type comparison and clean code
John Rouillard <rouilj@ieee.org>
parents: 8542
diff changeset
2490 report_acceptable_types))}))
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2491
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2492 def dispatch(self, method, uri, input_payload):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
2493 """format and process the request"""
5732
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2494 output = None
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2495
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2496 # Before we do anything has the user hit the rate limit.
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2497
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2498 # Get the limit here and not in the init() routine to allow
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2499 # for a different rate limit per user.
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2500 apiRateLimit = self.getRateLimit()
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2501
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2502 if apiRateLimit: # if None, disable rate limiting
7605
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2503 LimitExceeded, limitStatus = self.handle_apiRateLimitExceeded(
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2504 apiRateLimit)
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2505 if LimitExceeded:
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2506 return LimitExceeded # error message
7595
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2507
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2508 for header, value in limitStatus.items():
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2509 # Retry-After will be 0 because
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2510 # user still has quota available.
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2511 # Don't put out the header.
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2512 if header in ('Retry-After',):
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2513 continue
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2514 self.client.setHeader(header, value)
5732
0e6ed3d72f92 Rest rate limiting code first commit. It is a bit rough and turned off
John Rouillard <rouilj@ieee.org>
parents: 5731
diff changeset
2515
5574
55f97de157e7 Headers
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5573
diff changeset
2516 # if X-HTTP-Method-Override is set, follow the override method
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
2517 headers = self.client.request.headers
5620
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2518 # Never allow GET to be an unsafe operation (i.e. data changing).
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2519 # User must use POST to "tunnel" DELETE, PUT, OPTIONS etc.
5650
e8ca7072c629 Fix Python 3 issues in REST code.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5646
diff changeset
2520 override = headers.get('X-HTTP-Method-Override')
5620
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2521 if override:
5730
4aa26a9f3b47 Tighten up use of X-HTTP-Method-Override to only work with POST.
John Rouillard <rouilj@ieee.org>
parents: 5729
diff changeset
2522 if method.upper() == 'POST':
5620
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2523 logger.debug(
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2524 'Method overridden from %s to %s', method, override)
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2525 method = override
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2526 else:
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2527 output = self.error_obj(400,
5730
4aa26a9f3b47 Tighten up use of X-HTTP-Method-Override to only work with POST.
John Rouillard <rouilj@ieee.org>
parents: 5729
diff changeset
2528 "X-HTTP-Method-Override: %s must be used with "
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2529 "POST method not %s." % (override, method.upper()))
5620
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2530 logger.info(
5730
4aa26a9f3b47 Tighten up use of X-HTTP-Method-Override to only work with POST.
John Rouillard <rouilj@ieee.org>
parents: 5729
diff changeset
2531 'Ignoring X-HTTP-Method-Override using %s request on %s',
4aa26a9f3b47 Tighten up use of X-HTTP-Method-Override to only work with POST.
John Rouillard <rouilj@ieee.org>
parents: 5729
diff changeset
2532 method.upper(), uri)
4aa26a9f3b47 Tighten up use of X-HTTP-Method-Override to only work with POST.
John Rouillard <rouilj@ieee.org>
parents: 5729
diff changeset
2533
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2534 # FIXME: when this method is refactored, change
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2535 # determine_output_format to raise an exception. Catch it here
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2536 # and return early. Also set self.client.response_code from
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2537 # error object['error']['status'] and remove from
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2538 # determine_output_format.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2539 (output_format, uri, error) = self.determine_output_format(uri)
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2540 if error:
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2541 output = error
7596
e5fa31aad344 fix: replace bad reverted code change; allow js rate headers
John Rouillard <rouilj@ieee.org>
parents: 7595
diff changeset
2542
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2543 if method.upper() == 'OPTIONS':
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2544 # add access-control-allow-* access-control-max-age to support
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2545 # CORS preflight
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2546 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2547 "Access-Control-Allow-Headers",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2548 "Content-Type, Authorization, X-Requested-With, X-HTTP-Method-Override"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2549 )
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2550 # can be overridden by options handlers to provide supported
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2551 # methods for endpoint
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2552 self.client.setHeader(
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2553 "Access-Control-Allow-Methods",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2554 "HEAD, OPTIONS, GET, POST, PUT, DELETE, PATCH"
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2555 )
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2556 # cache the Access headings for a week. Allows one CORS pre-flight
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2557 # request to be reused again and again.
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2558 self.client.setHeader("Access-Control-Max-Age", "86400")
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2559
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2560 # response may change based on Origin value.
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2561 self.client.setVary("Origin")
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2562
7156
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2563 # expose these headers to rest clients. Otherwise they can't
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2564 # respond to:
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2565 # rate limiting (*RateLimit*, Retry-After)
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2566 # obsolete API endpoint (Sunset)
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2567 # options request to discover supported methods (Allow)
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2568 self.client.setHeader(
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2569 "Access-Control-Expose-Headers",
7173
5159d8ea585a chore: flake8 formatting fixes
John Rouillard <rouilj@ieee.org>
parents: 7158
diff changeset
2570 ", ".join([
7156
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2571 "X-RateLimit-Limit",
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2572 "X-RateLimit-Remaining",
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2573 "X-RateLimit-Reset",
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2574 "X-RateLimit-Limit-Period",
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2575 "Retry-After",
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2576 "Sunset",
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2577 "Allow",
7173
5159d8ea585a chore: flake8 formatting fixes
John Rouillard <rouilj@ieee.org>
parents: 7158
diff changeset
2578 ])
7156
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2579 )
6f09103a6522 [issue2551263] expose headers to rest clients
John Rouillard <rouilj@ieee.org>
parents: 7155
diff changeset
2580
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2581 # Allow-Origin must match origin supplied by client. '*' doesn't
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2582 # work for authenticated requests.
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
2583 self.client.setHeader(
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2584 "Access-Control-Allow-Origin",
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2585 self.client.request.headers.get("Origin")
5581
30793a435185 Code convention improved
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5580
diff changeset
2586 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2587
7155
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2588 # Allow credentials if origin is acceptable.
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2589 #
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2590 # If Access-Control-Allow-Credentials header not returned,
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2591 # but the client request is made with credentials
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2592 # data will be sent but not made available to the
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2593 # calling javascript in browser.
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2594 # Prevents exposure of data to an invalid origin when
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2595 # credentials are sent by client.
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2596 #
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2597 # If admin puts * first in allowed_api_origins
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2598 # we do not allow credentials but do reflect the origin.
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2599 # This allows anonymous access.
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2600 if self.client.is_origin_header_ok(api=True, credentials=True):
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2601 self.client.setHeader(
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2602 "Access-Control-Allow-Credentials",
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2603 "true"
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2604 )
89a59e46b3af improve REST interface security
John Rouillard <rouilj@ieee.org>
parents: 6926
diff changeset
2605
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2606 # set allow header in case of error. 405 handlers below should
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2607 # replace it with a custom version as will OPTIONS handler
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2608 # doing CORS.
5590
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
2609 self.client.setHeader(
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
2610 "Allow",
5702
61874fd78ced Fix OPTIONS responses:
John Rouillard <rouilj@ieee.org>
parents: 5701
diff changeset
2611 "OPTIONS, GET, POST, PUT, DELETE, PATCH"
5590
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
2612 )
6693
9a1f5e496e6c issue2551203 - Add support for CORS preflight request
John Rouillard <rouilj@ieee.org>
parents: 6561
diff changeset
2613
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2614 # Is there an input_payload.value with format json data?
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2615 # If so turn it into an object that emulates enough
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2616 # of the FieldStorge methods/props to allow a response.
5650
e8ca7072c629 Fix Python 3 issues in REST code.
Joseph Myers <jsm@polyomino.org.uk>
parents: 5646
diff changeset
2617 content_type_header = headers.get('Content-Type', None)
5655
207e0f5d551c Merge in non-conflicting changes from ba67e397f063
John Rouillard <rouilj@ieee.org>
parents: 5650 5653
diff changeset
2618 # python2 is str type, python3 is bytes
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2619 if type(input_payload.value) in (str, bytes) and content_type_header:
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2620 # the structure of a content-type header
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2621 # is complex: mime-type; options(charset ...)
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2622 # for now we just accept application/json.
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2623 # FIXME there should be a function:
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2624 # parse_content_type_header(content_type_header)
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2625 # that returns a tuple like the Accept header parser.
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2626 # Then the test below could use:
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2627 # parsed_content_type_header[0].lower() == 'json'
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2628 # That way we could handle stuff like:
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2629 # application/vnd.roundup-foo+json; charset=UTF8
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2630 # for example.
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2631 if content_type_header.lower() == "application/json":
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2632 try:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2633 input_payload = SimulateFieldStorageFromJson(b2s(input_payload.value))
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2634 except ValueError as msg:
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2635 output = self.error_obj(400, msg)
6311
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
2636 else:
8094
8e310a7b5e09 issue2551131 - Return accept-patch if patch body not accepted (415 code)
John Rouillard <rouilj@ieee.org>
parents: 7983
diff changeset
2637 if method.upper() == "PATCH":
8e310a7b5e09 issue2551131 - Return accept-patch if patch body not accepted (415 code)
John Rouillard <rouilj@ieee.org>
parents: 7983
diff changeset
2638 self.client.setHeader("Accept-Patch",
8e310a7b5e09 issue2551131 - Return accept-patch if patch body not accepted (415 code)
John Rouillard <rouilj@ieee.org>
parents: 7983
diff changeset
2639 "application/json, "
8e310a7b5e09 issue2551131 - Return accept-patch if patch body not accepted (415 code)
John Rouillard <rouilj@ieee.org>
parents: 7983
diff changeset
2640 "application/x-www-form-urlencoded")
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2641 output = self.error_obj(415,
6311
be8d5a8e090a Fix uncaught error when parsing rest headers, document
John Rouillard <rouilj@ieee.org>
parents: 6254
diff changeset
2642 "Unable to process input of type %s" %
6926
626ef84579a3 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 6824
diff changeset
2643 content_type_header)
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2644
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2645 # check for pretty print
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2646 try:
8194
2ecd1a871993 chore(ruff): replace not a == b with a != b
John Rouillard <rouilj@ieee.org>
parents: 8193
diff changeset
2647 pretty_output = input_payload['@pretty'].value.lower() != "false"
5823
edd9e2c67785 Make REST-API updates work with WSGI
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5808
diff changeset
2648 # Can also return a TypeError ("not indexable")
edd9e2c67785 Make REST-API updates work with WSGI
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5808
diff changeset
2649 # In case the FieldStorage could not parse the result
edd9e2c67785 Make REST-API updates work with WSGI
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5808
diff changeset
2650 except (KeyError, TypeError):
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2651 pretty_output = True
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2652
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
2653 # check for runtime statistics
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
2654 try:
6561
01a5dd90286e Remove unused report_stats
John Rouillard <rouilj@ieee.org>
parents: 6559
diff changeset
2655 # self.report_stats initialized to False
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2656 self.report_stats = input_payload['@stats'].value.lower() == "true"
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
2657 # Can also return a TypeError ("not indexable")
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
2658 # In case the FieldStorage could not parse the result
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
2659 except (KeyError, TypeError):
6561
01a5dd90286e Remove unused report_stats
John Rouillard <rouilj@ieee.org>
parents: 6559
diff changeset
2660 pass
6185
1cb2375015f0 Enable timing stats reporting in REST interface.
John Rouillard <rouilj@ieee.org>
parents: 6111
diff changeset
2661
5686
eb51c0d9c9bf Move @apiver version extraction code after the input is parsed for
John Rouillard <rouilj@ieee.org>
parents: 5685
diff changeset
2662 # check for @apiver in query string
6510
d5a3fe9ac12d Make error message for bad apiver a little better.
John Rouillard <rouilj@ieee.org>
parents: 6509
diff changeset
2663 msg = _("Unrecognized api version: %s. "
d5a3fe9ac12d Make error message for bad apiver a little better.
John Rouillard <rouilj@ieee.org>
parents: 6509
diff changeset
2664 "See /rest without specifying api version "
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2665 "for supported versions.")
5686
eb51c0d9c9bf Move @apiver version extraction code after the input is parsed for
John Rouillard <rouilj@ieee.org>
parents: 5685
diff changeset
2666 try:
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2667 # FIXME: the version priority here is different
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2668 # from accept header. accept mime type in url
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2669 # takes priority over Accept header. Opposite here.
5686
eb51c0d9c9bf Move @apiver version extraction code after the input is parsed for
John Rouillard <rouilj@ieee.org>
parents: 5685
diff changeset
2670 if not self.api_version:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2671 self.api_version = int(input_payload['@apiver'].value)
5823
edd9e2c67785 Make REST-API updates work with WSGI
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5808
diff changeset
2672 # Can also return a TypeError ("not indexable")
edd9e2c67785 Make REST-API updates work with WSGI
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5808
diff changeset
2673 # In case the FieldStorage could not parse the result
edd9e2c67785 Make REST-API updates work with WSGI
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5808
diff changeset
2674 except (KeyError, TypeError):
5686
eb51c0d9c9bf Move @apiver version extraction code after the input is parsed for
John Rouillard <rouilj@ieee.org>
parents: 5685
diff changeset
2675 self.api_version = None
eb51c0d9c9bf Move @apiver version extraction code after the input is parsed for
John Rouillard <rouilj@ieee.org>
parents: 5685
diff changeset
2676 except ValueError:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2677 output = self.error_obj(406, msg % input_payload['@apiver'].value)
5711
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2678
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2679 # by this time the API version is set. Error if we don't
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2680 # support it?
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2681 if self.api_version is None:
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2682 # FIXME: do we need to raise an error if client did not specify
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2683 # version? This may be a good thing to require. Note that:
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2684 # Accept: application/json; version=1 may not be legal but....
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2685 # Use default if not specified for now.
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2686 self.api_version = self.__default_api_version
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2687 elif self.api_version not in self.__supported_api_versions:
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2688 output = self.error_obj(406, msg % self.api_version)
5711
aea2cc142c1b Added some more rest testing and make sure api version is valid.
John Rouillard <rouilj@ieee.org>
parents: 5710
diff changeset
2689
5691
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
2690 # sadly del doesn't work on FieldStorage which can be the type of
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2691 # input_payload. So we have to ignore keys starting with @ at other
5691
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
2692 # places in the code.
dbf422a8cff7 Add error handling. @apiver was being processed as a search
John Rouillard <rouilj@ieee.org>
parents: 5690
diff changeset
2693 # else:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2694 # del(input_payload['@apiver'])
5686
eb51c0d9c9bf Move @apiver version extraction code after the input is parsed for
John Rouillard <rouilj@ieee.org>
parents: 5685
diff changeset
2695
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
2696 # Call the appropriate method
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
2697 try:
5620
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2698 # If output was defined by a prior error
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2699 # condition skip call
5f8e6034427c Do not honor the X-HTTP-Method-Override if the original method used
John Rouillard <rouilj@ieee.org>
parents: 5619
diff changeset
2700 if not output:
8188
e5362f8e1808 chore(ruff): rename input and id parms/vars - don't shadow builtin
John Rouillard <rouilj@ieee.org>
parents: 8180
diff changeset
2701 output = Routing.execute(self, uri, method, input_payload)
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
2702 except NotFound as msg:
5597
de9933cfcfc4 Added routing decorator
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5596
diff changeset
2703 output = self.error_obj(404, msg)
5602
c40d04915e23 Python3 fixes
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5600
diff changeset
2704 except Reject as msg:
6525
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2705 output = self.error_obj(405, msg.args[0])
c505c774a94d Mutiple changes to REST code.
John Rouillard <rouilj@ieee.org>
parents: 6517
diff changeset
2706 self.client.setHeader("Allow", msg.args[1])
5567
1af57f9d5bf7 Added exception Handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5566
diff changeset
2707
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2708 return self.format_dispatch_output(output_format,
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2709 output,
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2710 pretty_output)
7595
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2711
7605
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2712 def format_dispatch_output(self, accept_mime_type, output,
5b3ecdfd77f7 refactor(api): extract api rate limit handling; add default val
John Rouillard <rouilj@ieee.org>
parents: 7597
diff changeset
2713 pretty_print=True):
5590
4d8746c73fdb Change the way core function is called
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5589
diff changeset
2714 # Format the content type
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2715 # if accept_mime_type is None, the client specified invalid
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2716 # mime types so we default to json output.
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2717 if accept_mime_type == "json" or accept_mime_type is None:
5589
5a2de4c19109 Fix an indentation bug
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5588
diff changeset
2718 self.client.setHeader("Content-Type", "application/json")
7595
26ef5054e510 refactor(api): early return if REST rate limit is exceeded
John Rouillard <rouilj@ieee.org>
parents: 7569
diff changeset
2719 if pretty_print:
5589
5a2de4c19109 Fix an indentation bug
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5588
diff changeset
2720 indent = 4
5574
55f97de157e7 Headers
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5573
diff changeset
2721 else:
5589
5a2de4c19109 Fix an indentation bug
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5588
diff changeset
2722 indent = None
5a2de4c19109 Fix an indentation bug
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5588
diff changeset
2723 output = RoundupJSONEncoder(indent=indent).encode(output)
8177
2967f37e73e4 refactor: issue2551289. invalid REST Accept header stops request
John Rouillard <rouilj@ieee.org>
parents: 8126
diff changeset
2724 elif accept_mime_type == "xml" and dicttoxml:
5631
a5c890d308c3 Add simple support for xml output if the third party dict2xml.py module
John Rouillard <rouilj@ieee.org>
parents: 5630
diff changeset
2725 self.client.setHeader("Content-Type", "application/xml")
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2726 if 'error' in output:
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2727 # capture values in error with types unsupported
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2728 # by dicttoxml e.g. an exception, into something it
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2729 # can handle
8207
894eabf95385 chore(ruff): sort imports.
John Rouillard <rouilj@ieee.org>
parents: 8206
diff changeset
2730 import collections
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2731 import numbers
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2732 for key, val in output['error'].items():
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2733 if isinstance(val, numbers.Number) or type(val) in \
8205
4993e122235e chore(ruff): suppress combine branches with one or expression
John Rouillard <rouilj@ieee.org>
parents: 8204
diff changeset
2734 (str, unicode): # noqa: SIM114
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2735 pass
8205
4993e122235e chore(ruff): suppress combine branches with one or expression
John Rouillard <rouilj@ieee.org>
parents: 8204
diff changeset
2736 elif hasattr(val, 'isoformat'): # datetime # noqa: SIM114
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2737 pass
8205
4993e122235e chore(ruff): suppress combine branches with one or expression
John Rouillard <rouilj@ieee.org>
parents: 8204
diff changeset
2738 elif type(val) is bool: # noqa: SIM114
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2739 pass
8205
4993e122235e chore(ruff): suppress combine branches with one or expression
John Rouillard <rouilj@ieee.org>
parents: 8204
diff changeset
2740 elif isinstance(val, dict): # noqa: SIM114
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2741 pass
8205
4993e122235e chore(ruff): suppress combine branches with one or expression
John Rouillard <rouilj@ieee.org>
parents: 8204
diff changeset
2742 elif isinstance(val, collections.Iterable): # noqa: SIM114
5707
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2743 pass
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2744 elif val is None:
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2745 pass
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2746 else:
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2747 output['error'][key] = str(val)
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2748
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2749 output = '<?xml version="1.0" encoding="UTF-8" ?>\n' + \
f9a762678af6 Change some 400 errors to 405 (method not allowed) errors where user is
John Rouillard <rouilj@ieee.org>
parents: 5705
diff changeset
2750 b2s(dicttoxml(output, root=False))
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2751 elif accept_mime_type:
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2752 self.client.setHeader("Content-Type", accept_mime_type)
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2753 # do not send etag when getting binary_content. The ETag
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2754 # is for the item not the content of the item. So the ETag
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2755 # can change even though the content is the same. Since
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2756 # content is immutable by default, the client shouldn't
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2757 # need the etag for writing.
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2758 self.client.setHeader("ETag", None)
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2759 return output['data']['data']
5589
5a2de4c19109 Fix an indentation bug
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5588
diff changeset
2760 else:
8180
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2761 self.client.response_code = 500
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2762 output = _("Internal error while formatting response.\n"
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2763 "accept_mime_type is not defined. This should\n"
d02ce1d14acd feat: issue2551068 - Provide way to retrieve file/msg data via rest endpoint.
John Rouillard <rouilj@ieee.org>
parents: 8177
diff changeset
2764 "never happen\n")
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
2765
5639
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
2766 # Make output json end in a newline to
f576957cbb1f Add support for prev/next/self links when returning paginated results.
John Rouillard <rouilj@ieee.org>
parents: 5638
diff changeset
2767 # separate from following text in logs etc..
5653
ba67e397f063 Fix string/bytes issues under python 3.
John Rouillard <rouilj@ieee.org>
parents: 5646
diff changeset
2768 return bs2b(output + "\n")
5566
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2769
5567
1af57f9d5bf7 Added exception Handling
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5566
diff changeset
2770
5566
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2771 class RoundupJSONEncoder(json.JSONEncoder):
5582
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
2772 """RoundupJSONEncoder overrides the default JSONEncoder to handle all
519b7fd8c8c3 Added docstring
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5581
diff changeset
2773 types of the object without returning any error"""
5566
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2774 def default(self, obj):
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2775 try:
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2776 result = json.JSONEncoder.default(self, obj)
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2777 except TypeError:
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2778 result = str(obj)
2830793d1510 Added RoundupJSONEncoder
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5565
diff changeset
2779 return result
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2780
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2781
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2782 class SimulateFieldStorageFromJson():
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2783 '''
5689
2c516d113620 Fix encoding for incoming json requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5687
diff changeset
2784 The internals of the rest interface assume the data was sent as
2c516d113620 Fix encoding for incoming json requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5687
diff changeset
2785 application/x-www-form-urlencoded. So we should have a
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2786 FieldStorage and MiniFieldStorage structure.
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2787
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2788 However if we want to handle json data, we need to:
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2789 1) create the Fieldstorage/MiniFieldStorage structure
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2790 or
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2791 2) simultate the interface parts of FieldStorage structure
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2792
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2793 To do 2, create a object that emulates the:
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2794
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2795 object['prop'].value
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2796
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2797 references used when accessing a FieldStorage structure.
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2798
5690
4aae822e2cb4 Added a few comments and a test that fails with the pre-patched code
John Rouillard <rouilj@ieee.org>
parents: 5689
diff changeset
2799 That's what this class does with all names and values as native
4aae822e2cb4 Added a few comments and a test that fails with the pre-patched code
John Rouillard <rouilj@ieee.org>
parents: 5689
diff changeset
2800 strings. Note that json is UTF-8, so we convert any unicode to
4aae822e2cb4 Added a few comments and a test that fails with the pre-patched code
John Rouillard <rouilj@ieee.org>
parents: 5689
diff changeset
2801 string.
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2802
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2803 '''
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
2804
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
2805 __slots__ = ("json_dict", "value")
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
2806
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2807 def __init__(self, json_string):
8218
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2808 '''Parse the json string into an internal dict.
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2809
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2810 Because spec for rest post once exactly (POE) shows
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2811 posting empty content. An empty string results in an empty
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2812 dict, not a json parse error.
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2813 '''
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2814 def raise_error_on_constant(x):
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2815 raise ValueError("Unacceptable number: %s" % x)
8218
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2816 if json_string == "":
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2817 self.json_dict = {}
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2818 self.value = None
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2819 return
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2820
8542
a4f017ae1477 perf: dereference methods before using in loop
John Rouillard <rouilj@ieee.org>
parents: 8536
diff changeset
2821 fsvalue = self.FsValue
5710
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
2822 try:
0b79bfcb3312 Add support for making an idempotent POST. This allows retrying a POST
John Rouillard <rouilj@ieee.org>
parents: 5707
diff changeset
2823 self.json_dict = json.loads(json_string,
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2824 parse_constant=raise_error_on_constant)
8542
a4f017ae1477 perf: dereference methods before using in loop
John Rouillard <rouilj@ieee.org>
parents: 8536
diff changeset
2825 json_dict = self.json_dict
a4f017ae1477 perf: dereference methods before using in loop
John Rouillard <rouilj@ieee.org>
parents: 8536
diff changeset
2826 self.value = [fsvalue(index, json_dict[index])
a4f017ae1477 perf: dereference methods before using in loop
John Rouillard <rouilj@ieee.org>
parents: 8536
diff changeset
2827 for index in json_dict if
a4f017ae1477 perf: dereference methods before using in loop
John Rouillard <rouilj@ieee.org>
parents: 8536
diff changeset
2828 json_dict[index] is not None]
8220
818751637b77 fix: make rest.py still load on python2, do not test bad json
John Rouillard <rouilj@ieee.org>
parents: 8218
diff changeset
2829 except (JSONDecodeError, ValueError) as e:
8218
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2830 raise ValueError(e.args[0] + ". JSON is: " + json_string)
32aaf5dc562b fix(REST): issue2551383; improve errors for bad json, fix PUT docs
John Rouillard <rouilj@ieee.org>
parents: 8213
diff changeset
2831
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2832 class FsValue:
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
2833
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
2834 __slots__ = ("name", "value")
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 8319
diff changeset
2835
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2836 '''Class that does nothing but response to a .value property '''
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2837 def __init__(self, name, val):
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2838 self.name = u2s(name)
5689
2c516d113620 Fix encoding for incoming json requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5687
diff changeset
2839 if is_us(val):
5690
4aae822e2cb4 Added a few comments and a test that fails with the pre-patched code
John Rouillard <rouilj@ieee.org>
parents: 5689
diff changeset
2840 # handle most common type first
5998
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2841 self.value = u2s(val)
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2842 elif isinstance(val, type([])):
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2843 # then lists of strings
776ca681f925 flake8 cleanups
John Rouillard <rouilj@ieee.org>
parents: 5987
diff changeset
2844 self.value = [u2s(v) for v in val]
8530
36be91f671d0 bug: fix case where null json value for datetime fails
John Rouillard <rouilj@ieee.org>
parents: 8472
diff changeset
2845 elif val is None:
36be91f671d0 bug: fix case where null json value for datetime fails
John Rouillard <rouilj@ieee.org>
parents: 8472
diff changeset
2846 self.value = None
5689
2c516d113620 Fix encoding for incoming json requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5687
diff changeset
2847 else:
5690
4aae822e2cb4 Added a few comments and a test that fails with the pre-patched code
John Rouillard <rouilj@ieee.org>
parents: 5689
diff changeset
2848 # then stringify anything else (int, float)
5689
2c516d113620 Fix encoding for incoming json requests
Ralf Schlatterbeck <rsc@runtux.com>
parents: 5687
diff changeset
2849 self.value = str(val)
5643
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2850
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2851 def __getitem__(self, index):
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2852 '''Return an FsValue created from the value of self.json_dict[index]
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2853 '''
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2854 return self.FsValue(index, self.json_dict[index])
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2855
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2856 def __contains__(self, index):
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2857 ''' implement: 'foo' in DICT '''
a60cbbcc9309 Added support for accepting application/json payload in addition to
John Rouillard <rouilj@ieee.org>
parents: 5639
diff changeset
2858 return index in self.json_dict

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