annotate roundup/rest.py @ 5561:7aa7f779198b REST-rebased

Split all rest action into 2 type element uri and collection uri committer: Ralf Schlatterbeck <rsc@runtux.com>
author Chau Nguyen <dangchau1991@yahoo.com>
date Wed, 30 Jan 2019 10:26:33 +0100
parents 2cc07def1b3f
children 70df783c4c0b
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
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
8 import json
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
9 import pprint
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
10 from roundup import hyperdb
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
11 from roundup.cgi.templating import Unauthorised
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
12 from roundup import xmlrpc
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
13
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
14
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
15 class RestfulInstance(object):
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
16 """Dummy Handler for REST
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
17 """
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
18
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
19 def __init__(self, db):
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
20 # TODO: database, translator and instance.actions
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
21 self.db = db
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
22
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
23 def get_collection(self, class_name, input):
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
24 class_obj = self.db.getclass(class_name)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
25 prop_name = class_obj.labelprop()
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
26 result = [{'id': item_id, 'name': class_obj.get(item_id, prop_name)}
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
27 for item_id in class_obj.list()
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
28 if self.db.security.hasPermission('View', self.db.getuid(),
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
29 class_name, None, item_id)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
30 ]
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
31 result = json.JSONEncoder().encode(result)
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
32
5558
1bef1076ad12 Recognize both GET element uri and collection uri
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5557
diff changeset
33 return result
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
34
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
35 def get_element(self, class_name, item_id, input):
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
36 class_obj = self.db.getclass(class_name)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
37 props = class_obj.properties.keys()
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
38 props.sort() # sort properties
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
39 result = [(prop_name, class_obj.get(item_id, prop_name))
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
40 for prop_name in props
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
41 if self.db.security.hasPermission('View', self.db.getuid(),
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
42 class_name, prop_name,
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
43 item_id)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
44 ]
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
45 result = json.JSONEncoder().encode(dict(result))
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
46
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
47 return result
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
48
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
49 def post_collection(self, class_name, input):
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
50 if not self.db.security.hasPermission('Create', self.db.getuid(),
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
51 class_name):
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
52 raise Unauthorised('Permission to create %s denied' % class_name)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
53
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
54 class_obj = self.db.getclass(class_name)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
55
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
56 # convert types
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
57 props = xmlrpc.props_from_args(self.db, class_obj, input)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
58
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
59 # check for the key property
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
60 key = class_obj.getkey()
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
61 if key and key not in props:
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
62 raise xmlrpc.UsageError, 'Must provide the "%s" property.' % key
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
63
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
64 for key in props:
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
65 if not self.db.security.hasPermission('Create', self.db.getuid(),
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
66 class_name, property=key):
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
67 raise Unauthorised('Permission to create %s.%s denied' %
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
68 (class_name, key))
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
69
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
70 # do the actual create
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
71 try:
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
72 result = class_obj.create(**props)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
73 self.db.commit()
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
74 except (TypeError, IndexError, ValueError), message:
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
75 raise xmlrpc.UsageError, message
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
76 return result
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
77
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
78 def post_element(self, class_name, item_id, input):
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
79 raise NotImplementedError
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
80
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
81 def put_collection(self, class_name, input):
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
82 raise NotImplementedError
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
83
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
84 def put_element(self, class_name, item_id, input):
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
85 raise NotImplementedError
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
86
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
87 def delete_collection(self, class_name, input):
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
88 # TODO: should I allow user to delete the whole collection ?
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
89 raise NotImplementedError
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
90
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
91 def delete_element(self, class_name, item_id, input):
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
92 # TODO: BUG with DELETE without form data. Working with random data
5560
2cc07def1b3f use getattr instead of calling each function
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5559
diff changeset
93 # crash at line self.form = cgi.FieldStorage(fp=request.rfile, environ=env)
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
94 try:
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
95 self.db.destroynode(class_name, item_id)
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
96 result = 'OK'
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
97 except IndexError:
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
98 result = 'Error'
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
99
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
100 return result
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
101
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
102 def patch_collection(self, class_name, input):
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
103 raise NotImplementedError
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
104
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
105 def patch_element(self, class_name, item_id, input):
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
106 raise NotImplementedError
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
107
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
108 def dispatch(self, method, uri, input):
5558
1bef1076ad12 Recognize both GET element uri and collection uri
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5557
diff changeset
109 print "METHOD: " + method + " URI: " + uri
5556
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
110 print type(input)
d75aa88c2a99 Added RestInstance and calling rest from client.py
Chau Nguyen <dangchau1991@yahoo.com>
parents:
diff changeset
111 pprint.pprint(input)
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
112 # TODO: process input_form directly instead of making a new array
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
113 # TODO: rest server
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
114 # TODO: check roundup/actions.py
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
115 # TODO: if uri_path has more than 2 child, return 404
5559
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
116 # TODO: custom JSONEncoder to handle other data type
3d80e7752783 Added POST and DELETE
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5558
diff changeset
117 # TODO: catch all error and display error.
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
118
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
119 # PATH is split to multiple pieces
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
120 # 0 - rest
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
121 # 1 - resource
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
122
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
123 resource_uri = uri.split("/")[1]
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
124 input_data = ["%s=%s" % (item.name, item.value) for item in input]
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
125
5560
2cc07def1b3f use getattr instead of calling each function
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5559
diff changeset
126 try:
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
127 if resource_uri in self.db.classes:
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
128 output = getattr(self, "%s_collection" % method.lower())(resource_uri, input_data)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
129 else:
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
130 class_name, item_id = hyperdb.splitDesignator(resource_uri)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
131 output = getattr(self, "%s_element" % method.lower())(class_name, item_id, input_data)
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
132 except hyperdb.DesignatorError:
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
133 pass # invalid URI
5560
2cc07def1b3f use getattr instead of calling each function
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5559
diff changeset
134 except AttributeError:
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
135 raise NotImplementedError # Error: method is invalid
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
136
5561
7aa7f779198b Split all rest action into 2 type
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5560
diff changeset
137 print "Length: %s - Content(50 char): %s" % (len(output), output[:50])
5557
213a56c91471 Implement getting resource from database
Chau Nguyen <dangchau1991@yahoo.com>
parents: 5556
diff changeset
138 return output

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