Mercurial > p > roundup > code
changeset 5599:a76d88673375 REST-rebased
Added Patch operator 'action'
.. to perform actions such as 'retire'
committer: Ralf Schlatterbeck <rsc@runtux.com>
| author | Chau Nguyen <dangchau1991@yahoo.com> |
|---|---|
| date | Wed, 30 Jan 2019 10:26:35 +0100 |
| parents | be81e8cca38c |
| children | e2c74d8121f3 |
| files | roundup/rest.py test/test_rest.py |
| diffstat | 2 files changed, 76 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/roundup/rest.py Wed Jan 30 10:26:35 2019 +0100 +++ b/roundup/rest.py Wed Jan 30 10:26:35 2019 +0100 @@ -16,6 +16,7 @@ from roundup import hyperdb from roundup import date +from roundup import actions from roundup.exceptions import * from roundup.cgi.exceptions import * @@ -230,6 +231,9 @@ def __init__(self, client, db): self.client = client self.db = db + self.translator = client.translator + self.actions = client.instance.actions.copy() + self.actions.update({'retire': actions.Retire}) protocol = 'http' host = self.client.env['HTTP_HOST'] @@ -856,33 +860,63 @@ op = self.__default_patch_op class_obj = self.db.getclass(class_name) - props = self.props_from_args(class_obj, input.value, item_id) + # if patch operation is action, call the action handler + action_args = [class_name + item_id] + if op == 'action': + # extract action_name and action_args from form fields + for form_field in input.value: + key = form_field.name + value = form_field.value + if key == "action_name": + name = value + elif key.startswith('action_args'): + action_args.append(value) + + if name in self.actions: + action_type = self.actions[name] + else: + raise UsageError( + 'action "%s" is not supported %s' % + (name, ','.join(self.actions.keys())) + ) + action = action_type(self.db, self.translator) + result = action.execute(*action_args) - for prop, value in props.iteritems(): - if not self.db.security.hasPermission( - 'Edit', self.db.getuid(), class_name, prop, item_id - ): - raise Unauthorised( - 'Permission to edit %s of %s%s denied' % - (prop, class_name, item_id) + result = { + 'id': item_id, + 'type': class_name, + 'link': self.base_path + class_name + item_id, + 'result': result + } + else: + # else patch operation is processing data + props = self.props_from_args(class_obj, input.value, item_id) + + for prop, value in props.iteritems(): + if not self.db.security.hasPermission( + 'Edit', self.db.getuid(), class_name, prop, item_id + ): + raise Unauthorised( + 'Permission to edit %s of %s%s denied' % + (prop, class_name, item_id) + ) + + props[prop] = self.patch_data( + op, class_obj.get(item_id, prop), props[prop] ) - props[prop] = self.patch_data( - op, class_obj.get(item_id, prop), props[prop] - ) + try: + result = class_obj.set(item_id, **props) + self.db.commit() + except (TypeError, IndexError, ValueError), message: + raise ValueError(message) - try: - result = class_obj.set(item_id, **props) - self.db.commit() - except (TypeError, IndexError, ValueError), message: - raise ValueError(message) - - result = { - 'id': item_id, - 'type': class_name, - 'link': self.base_path + class_name + item_id, - 'attribute': result - } + result = { + 'id': item_id, + 'type': class_name, + 'link': self.base_path + class_name + item_id, + 'attribute': result + } return 200, result @Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'PATCH')
--- a/test/test_rest.py Wed Jan 30 10:26:35 2019 +0100 +++ b/test/test_rest.py Wed Jan 30 10:26:35 2019 +0100 @@ -461,6 +461,25 @@ self.assertEqual(len(results['attributes']['nosy']), 0) self.assertEqual(results['attributes']['nosy'], []) + def testPatchAction(self): + """ + Test Patch Action 'Action' + """ + # create a new issue with userid 1 and 2 in the nosy list + issue_id = self.db.issue.create(title='foo') + + # execute action retire + form = cgi.FieldStorage() + form.list = [ + cgi.MiniFieldStorage('op', 'action'), + cgi.MiniFieldStorage('action_name', 'retire') + ] + results = self.server.patch_element('issue', issue_id, form) + self.assertEqual(self.dummy_client.response_code, 200) + + # verify the result + self.assertTrue(self.db.issue.is_retired(issue_id)) + def testPatchRemove(self): """ Test Patch Action 'Remove' only some element from a list
