annotate roundup/rest.py @ 6354:b61de764c8cc

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

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