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