annotate roundup/rest.py @ 6279:9ec3a9bc4ea5

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

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