Mercurial > p > roundup > code
comparison roundup/rest.py @ 5604:ed02a1e0aa5d REST-rebased
Fix actions
Permission for retire in roundup/actions.py was with 'Edit' permission,
not 'Retire' permission. Add a 'restore' action to roundup/actions.py.
Both are now correctly used in rest.py and xmlrpc.py (the latter had
some errors when printint error messages).
Also reworked the rest implementation: Despite the warnings in the
roundup API in hyperdb.py the DELETE http method would *destroy* and not
*retire* an item. This has been fixed. We also do not allow retire of a
complete class (although this was implemented) because this seems to
dangerous and we see no use-case.
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Wed, 30 Jan 2019 14:12:27 +0100 |
| parents | c40d04915e23 |
| children | aa4c271514ae |
comparison
equal
deleted
inserted
replaced
| 5603:79da1ca2f94b | 5604:ed02a1e0aa5d |
|---|---|
| 241 | 241 |
| 242 def __init__(self, client, db): | 242 def __init__(self, client, db): |
| 243 self.client = client | 243 self.client = client |
| 244 self.db = db | 244 self.db = db |
| 245 self.translator = client.translator | 245 self.translator = client.translator |
| 246 self.actions = client.instance.actions.copy() | 246 # This used to be initialized from client.instance.actions which |
| 247 self.actions.update({'retire': actions.Retire}) | 247 # would include too many actions that do not make sense in the |
| 248 # REST-API context, so for now we only permit the retire and | |
| 249 # restore actions. | |
| 250 self.actions = dict (retire = actions.Retire, restore = actions.Restore) | |
| 248 | 251 |
| 249 protocol = 'http' | 252 protocol = 'http' |
| 250 host = self.client.env['HTTP_HOST'] | 253 host = self.client.env['HTTP_HOST'] |
| 251 tracker = self.client.env['TRACKER_NAME'] | 254 tracker = self.client.env['TRACKER_NAME'] |
| 252 self.base_path = '%s://%s/%s/rest' % (protocol, host, tracker) | 255 self.base_path = '%s://%s/%s/rest' % (protocol, host, tracker) |
| 714 return 200, result | 717 return 200, result |
| 715 | 718 |
| 716 @Routing.route("/data/<:class_name>", 'DELETE') | 719 @Routing.route("/data/<:class_name>", 'DELETE') |
| 717 @_data_decorator | 720 @_data_decorator |
| 718 def delete_collection(self, class_name, input): | 721 def delete_collection(self, class_name, input): |
| 719 """DELETE all objects in a class | 722 """DELETE (retire) all objects in a class |
| 723 There is currently no use-case, so this is disabled and | |
| 724 always returns Unauthorised. | |
| 720 | 725 |
| 721 Args: | 726 Args: |
| 722 class_name (string): class name of the resource (Ex: issue, msg) | 727 class_name (string): class name of the resource (Ex: issue, msg) |
| 723 input (list): the submitted form of the user | 728 input (list): the submitted form of the user |
| 724 | 729 |
| 726 int: http status code 200 (OK) | 731 int: http status code 200 (OK) |
| 727 dict: | 732 dict: |
| 728 status (string): 'ok' | 733 status (string): 'ok' |
| 729 count (int): number of deleted objects | 734 count (int): number of deleted objects |
| 730 """ | 735 """ |
| 736 raise Unauthorised('Deletion of a whole class disabled') | |
| 731 if class_name not in self.db.classes: | 737 if class_name not in self.db.classes: |
| 732 raise NotFound('Class %s not found' % class_name) | 738 raise NotFound('Class %s not found' % class_name) |
| 733 if not self.db.security.hasPermission( | 739 if not self.db.security.hasPermission( |
| 734 'Delete', self.db.getuid(), class_name | 740 'Retire', self.db.getuid(), class_name |
| 735 ): | 741 ): |
| 736 raise Unauthorised('Permission to delete %s denied' % class_name) | 742 raise Unauthorised('Permission to delete %s denied' % class_name) |
| 737 | 743 |
| 738 class_obj = self.db.getclass(class_name) | 744 class_obj = self.db.getclass(class_name) |
| 739 for item_id in class_obj.list(): | 745 for item_id in class_obj.list(): |
| 740 if not self.db.security.hasPermission( | 746 if not self.db.security.hasPermission( |
| 741 'Delete', self.db.getuid(), class_name, itemid=item_id | 747 'Retire', self.db.getuid(), class_name, itemid=item_id |
| 742 ): | 748 ): |
| 743 raise Unauthorised( | 749 raise Unauthorised( |
| 744 'Permission to delete %s %s denied' % (class_name, item_id) | 750 'Permission to retire %s %s denied' % (class_name, item_id) |
| 745 ) | 751 ) |
| 746 | 752 |
| 747 count = len(class_obj.list()) | 753 count = len(class_obj.list()) |
| 748 for item_id in class_obj.list(): | 754 for item_id in class_obj.list(): |
| 749 self.db.destroynode(class_name, item_id) | 755 class_obj.retire (item_id) |
| 750 | 756 |
| 751 self.db.commit() | 757 self.db.commit() |
| 752 result = { | 758 result = { |
| 753 'status': 'ok', | 759 'status': 'ok', |
| 754 'count': count | 760 'count': count |
| 757 return 200, result | 763 return 200, result |
| 758 | 764 |
| 759 @Routing.route("/data/<:class_name>/<:item_id>", 'DELETE') | 765 @Routing.route("/data/<:class_name>/<:item_id>", 'DELETE') |
| 760 @_data_decorator | 766 @_data_decorator |
| 761 def delete_element(self, class_name, item_id, input): | 767 def delete_element(self, class_name, item_id, input): |
| 762 """DELETE an object in a class | 768 """DELETE (retire) an object in a class |
| 763 | 769 |
| 764 Args: | 770 Args: |
| 765 class_name (string): class name of the resource (Ex: issue, msg) | 771 class_name (string): class name of the resource (Ex: issue, msg) |
| 766 item_id (string): id of the resource (Ex: 12, 15) | 772 item_id (string): id of the resource (Ex: 12, 15) |
| 767 input (list): the submitted form of the user | 773 input (list): the submitted form of the user |
| 771 dict: | 777 dict: |
| 772 status (string): 'ok' | 778 status (string): 'ok' |
| 773 """ | 779 """ |
| 774 if class_name not in self.db.classes: | 780 if class_name not in self.db.classes: |
| 775 raise NotFound('Class %s not found' % class_name) | 781 raise NotFound('Class %s not found' % class_name) |
| 782 class_obj = self.db.classes [class_name] | |
| 776 if not self.db.security.hasPermission( | 783 if not self.db.security.hasPermission( |
| 777 'Delete', self.db.getuid(), class_name, itemid=item_id | 784 'Retire', self.db.getuid(), class_name, itemid=item_id |
| 778 ): | 785 ): |
| 779 raise Unauthorised( | 786 raise Unauthorised( |
| 780 'Permission to delete %s %s denied' % (class_name, item_id) | 787 'Permission to retire %s %s denied' % (class_name, item_id) |
| 781 ) | 788 ) |
| 782 | 789 |
| 783 self.db.destroynode(class_name, item_id) | 790 class_obj.retire (item_id) |
| 784 self.db.commit() | 791 self.db.commit() |
| 785 result = { | 792 result = { |
| 786 'status': 'ok' | 793 'status': 'ok' |
| 787 } | 794 } |
| 788 | 795 |
