annotate roundup/rest.py @ 8220:818751637b77

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

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