Skip to content

Commit 9c4b25b

Browse files
committed
Added a new cgi action restore. The opposite of (and a clone of) the existing retire action.
1 parent 05a3def commit 9c4b25b

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

CHANGES.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ Features:
120120
keeping all the quoted parts. If leave_body_unchanged is set to
121121
new, even the signature on the email that starts a new issue will be
122122
preserved.
123-
123+
- New cgi action restore (RestoreAction) which reverses the effects of
124+
the retire action. Created while implementing fix for
125+
issue2550831. Requires restore permission in the schema. See
126+
upgrading.txt for migrating to 1.6.0 for details. (John Rouillard)
127+
124128
Fixed:
125129

126130
- issue1615201: Optionally restore the original (version 0.6) mailgw

roundup/cgi/actions.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
from roundup.exceptions import Reject, RejectRaw
1010
from roundup.anypy import urllib_
1111

12-
__all__ = ['Action', 'ShowAction', 'RetireAction', 'SearchAction',
12+
# Also add action to client.py::Client.actions property
13+
__all__ = ['Action', 'ShowAction', 'RetireAction', 'RestoreAction', 'SearchAction',
1314
'EditCSVAction', 'EditItemAction', 'PassResetAction',
1415
'ConfRegoAction', 'RegisterAction', 'LoginAction', 'LogoutAction',
1516
'NewItemAction', 'ExportCSVAction']
@@ -137,6 +138,38 @@ def handle(self):
137138
'classname': self.classname.capitalize(), 'itemid': itemid})
138139

139140

141+
class RestoreAction(Action):
142+
name = 'restore'
143+
permissionType = 'Edit'
144+
145+
def handle(self):
146+
"""Restore the context item."""
147+
# ensure modification comes via POST
148+
if self.client.env['REQUEST_METHOD'] != 'POST':
149+
raise Reject(self._('Invalid request'))
150+
151+
# if we want to view the index template now, then unset the itemid
152+
# context info (a special-case for retire actions on the index page)
153+
itemid = self.nodeid
154+
if self.template == 'index':
155+
self.client.nodeid = None
156+
157+
# check permission
158+
if not self.hasPermission('Restore', classname=self.classname,
159+
itemid=itemid):
160+
raise exceptions.Unauthorised(self._(
161+
'You do not have permission to restore %(class)s'
162+
) % {'class': self.classname})
163+
164+
# do the restore
165+
self.db.getclass(self.classname).restore(itemid)
166+
self.db.commit()
167+
168+
self.client.add_ok_message(
169+
self._('%(classname)s %(itemid)s has been restored')%{
170+
'classname': self.classname.capitalize(), 'itemid': itemid})
171+
172+
140173
class SearchAction(Action):
141174
name = 'search'
142175
permissionType = 'View'

roundup/cgi/client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,7 @@ def renderContext(self):
12421242
('login', actions.LoginAction),
12431243
('logout', actions.LogoutAction),
12441244
('search', actions.SearchAction),
1245+
('restore', actions.RestoreAction),
12451246
('retire', actions.RetireAction),
12461247
('show', actions.ShowAction),
12471248
('export_csv', actions.ExportCSVAction),

test/test_actions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ def testDontRetireAdminOrAnonymous(self):
8585
self.client.db.user.get = lambda a,b: 'anonymous'
8686
self.assertRaises(ValueError, RetireAction(self.client).handle)
8787

88+
class RestoreActionTestCase(ActionTestCase):
89+
# This is a copy of the RetireActionTestCase. But what do these
90+
# actually test? I see no actual db or retire call or
91+
# class id. Testing db level restore is covered in the
92+
# db_test_base as part of retire.
93+
def testRestoreAction(self):
94+
self.client.db.security.hasPermission = true
95+
self.client._ok_message = []
96+
RestoreAction(self.client).handle()
97+
self.assert_(len(self.client._ok_message) == 1)
98+
99+
def testNoPermission(self):
100+
self.assertRaises(Unauthorised, RestoreAction(self.client).execute)
101+
88102
class SearchActionTestCase(ActionTestCase):
89103
def setUp(self):
90104
ActionTestCase.setUp(self)

0 commit comments

Comments
 (0)