comparison roundup/cgi/actions.py @ 2032:5a7ec0c63095

fixes to some unit tests, and a cleanup
author Richard Jones <richard@users.sourceforge.net>
date Fri, 20 Feb 2004 03:48:16 +0000
parents bcb21e5722b8
children d124af927369
comparison
equal deleted inserted replaced
2031:bcb21e5722b8 2032:5a7ec0c63095
12 'NewItemAction'] 12 'NewItemAction']
13 13
14 # used by a couple of routines 14 # used by a couple of routines
15 chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' 15 chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
16 16
17 class Action: 17 class Action:
18 def __init__(self, client): 18 def __init__(self, client):
19 self.client = client 19 self.client = client
20 self.form = client.form 20 self.form = client.form
21 self.db = client.db 21 self.db = client.db
22 self.nodeid = client.nodeid 22 self.nodeid = client.nodeid
23 self.template = client.template 23 self.template = client.template
24 self.classname = client.classname 24 self.classname = client.classname
25 self.userid = client.userid 25 self.userid = client.userid
26 self.base = client.base 26 self.base = client.base
27 self.user = client.user 27 self.user = client.user
28 28
29 def execute(self): 29 def execute(self):
30 """Execute the action specified by this object.""" 30 """Execute the action specified by this object."""
31 self.permission() 31 self.permission()
32 self.handle() 32 self.handle()
33 33
38 38
39 True by default. If the permissionType attribute is a string containing 39 True by default. If the permissionType attribute is a string containing
40 a simple permission, check whether the user has that permission. 40 a simple permission, check whether the user has that permission.
41 Subclasses must also define the name attribute if they define 41 Subclasses must also define the name attribute if they define
42 permissionType. 42 permissionType.
43 43
44 Despite having this permission, users may still be unauthorised to 44 Despite having this permission, users may still be unauthorised to
45 perform parts of actions. It is up to the subclasses to detect this. 45 perform parts of actions. It is up to the subclasses to detect this.
46 """ 46 """
47 if (self.permissionType and 47 if (self.permissionType and
48 not self.hasPermission(self.permissionType)): 48 not self.hasPermission(self.permissionType)):
49 49 info = {'action': self.name, 'classname': self.classname}
50 raise Unauthorised, _('You do not have permission to %s the %s class.' % 50 raise Unauthorised, _('You do not have permission to '
51 (self.name, self.classname)) 51 '%(action)s the %(classname)s class.')%info
52 52
53 def hasPermission(self, permission): 53 def hasPermission(self, permission):
54 """Check whether the user has 'permission' on the current class.""" 54 """Check whether the user has 'permission' on the current class."""
55 return self.db.security.hasPermission(permission, self.client.userid, 55 return self.db.security.hasPermission(permission, self.client.userid,
56 self.client.classname) 56 self.client.classname)
57 57
58 class ShowAction(Action): 58 class ShowAction(Action):
59 def handle(self, typere=re.compile('[@:]type'), 59 def handle(self, typere=re.compile('[@:]type'),
60 numre=re.compile('[@:]number')): 60 numre=re.compile('[@:]number')):
61 """Show a node of a particular class/id.""" 61 """Show a node of a particular class/id."""
73 class RetireAction(Action): 73 class RetireAction(Action):
74 name = 'retire' 74 name = 'retire'
75 permissionType = 'Edit' 75 permissionType = 'Edit'
76 76
77 def handle(self): 77 def handle(self):
78 """Retire the context item.""" 78 """Retire the context item."""
79 # if we want to view the index template now, then unset the nodeid 79 # if we want to view the index template now, then unset the nodeid
80 # context info (a special-case for retire actions on the index page) 80 # context info (a special-case for retire actions on the index page)
81 nodeid = self.nodeid 81 nodeid = self.nodeid
82 if self.template == 'index': 82 if self.template == 'index':
83 self.client.nodeid = None 83 self.client.nodeid = None
96 'classname': self.classname.capitalize(), 'itemid': nodeid}) 96 'classname': self.classname.capitalize(), 'itemid': nodeid})
97 97
98 class SearchAction(Action): 98 class SearchAction(Action):
99 name = 'search' 99 name = 'search'
100 permissionType = 'View' 100 permissionType = 'View'
101 101
102 def handle(self, wcre=re.compile(r'[\s,]+')): 102 def handle(self, wcre=re.compile(r'[\s,]+')):
103 """Mangle some of the form variables. 103 """Mangle some of the form variables.
104 104
105 Set the form ":filter" variable based on the values of the filter 105 Set the form ":filter" variable based on the values of the filter
106 variables - if they're set to anything other than "dontcare" then add 106 variables - if they're set to anything other than "dontcare" then add
111 111
112 Split any String query values on whitespace and comma. 112 Split any String query values on whitespace and comma.
113 113
114 """ 114 """
115 self.fakeFilterVars() 115 self.fakeFilterVars()
116 queryname = self.getQueryName() 116 queryname = self.getQueryName()
117 117
118 # handle saving the query params 118 # handle saving the query params
119 if queryname: 119 if queryname:
120 # parse the environment and figure what the query _is_ 120 # parse the environment and figure what the query _is_
121 req = templating.HTMLRequest(self.client) 121 req = templating.HTMLRequest(self.client)
163 if len(l) > 1 or l[0] != v: 163 if len(l) > 1 or l[0] != v:
164 self.form.value.remove(self.form[key]) 164 self.form.value.remove(self.form[key])
165 # replace the single value with the split list 165 # replace the single value with the split list
166 for v in l: 166 for v in l:
167 self.form.value.append(cgi.MiniFieldStorage(key, v)) 167 self.form.value.append(cgi.MiniFieldStorage(key, v))
168 168
169 self.form.value.append(cgi.MiniFieldStorage('@filter', key)) 169 self.form.value.append(cgi.MiniFieldStorage('@filter', key))
170 170
171 FV_QUERYNAME = re.compile(r'[@:]queryname') 171 FV_QUERYNAME = re.compile(r'[@:]queryname')
172 def getQueryName(self): 172 def getQueryName(self):
173 for key in self.form.keys(): 173 for key in self.form.keys():
176 return '' 176 return ''
177 177
178 class EditCSVAction(Action): 178 class EditCSVAction(Action):
179 name = 'edit' 179 name = 'edit'
180 permissionType = 'Edit' 180 permissionType = 'Edit'
181 181
182 def handle(self): 182 def handle(self):
183 """Performs an edit of all of a class' items in one go. 183 """Performs an edit of all of a class' items in one go.
184 184
185 The "rows" CGI var defines the CSV-formatted entries for the class. New 185 The "rows" CGI var defines the CSV-formatted entries for the class. New
186 nodes are identified by the ID 'X' (or any other non-existent ID) and 186 nodes are identified by the ID 'X' (or any other non-existent ID) and
268 268
269 # all OK 269 # all OK
270 self.db.commit() 270 self.db.commit()
271 271
272 self.client.ok_message.append(_('Items edited OK')) 272 self.client.ok_message.append(_('Items edited OK'))
273 273
274 class _EditAction(Action): 274 class _EditAction(Action):
275 def isEditingSelf(self): 275 def isEditingSelf(self):
276 """Check whether a user is editing his/her own details.""" 276 """Check whether a user is editing his/her own details."""
277 return (self.nodeid == self.userid 277 return (self.nodeid == self.userid
278 and self.db.user.get(self.nodeid, 'username') != 'anonymous') 278 and self.db.user.get(self.nodeid, 'username') != 'anonymous')
279 279
280 def editItemPermission(self, props): 280 def editItemPermission(self, props):
281 """Determine whether the user has permission to edit this item. 281 """Determine whether the user has permission to edit this item.
282 282
283 Base behaviour is to check the user can edit this class. If we're 283 Base behaviour is to check the user can edit this class. If we're
284 editing the "user" class, users are allowed to edit their own details. 284 editing the "user" class, users are allowed to edit their own details.
442 if userActivity: 442 if userActivity:
443 return userActivity < nodeActivity 443 return userActivity < nodeActivity
444 444
445 def handleCollision(self): 445 def handleCollision(self):
446 self.client.template = 'collision' 446 self.client.template = 'collision'
447 447
448 def handle(self): 448 def handle(self):
449 """Perform an edit of an item in the database. 449 """Perform an edit of an item in the database.
450 450
451 See parsePropsFromForm and _editnodes for special variables. 451 See parsePropsFromForm and _editnodes for special variables.
452 452
453 """ 453 """
454 if self.detectCollision(self.lastUserActivity(), self.lastNodeActivity()): 454 if self.detectCollision(self.lastUserActivity(), self.lastNodeActivity()):
455 self.handleCollision() 455 self.handleCollision()
456 return 456 return
457 457
478 urllib.quote(self.template)) 478 urllib.quote(self.template))
479 if self.nodeid is None: 479 if self.nodeid is None:
480 req = templating.HTMLRequest(self) 480 req = templating.HTMLRequest(self)
481 url += '&' + req.indexargs_href('', {})[1:] 481 url += '&' + req.indexargs_href('', {})[1:]
482 raise Redirect, url 482 raise Redirect, url
483 483
484 class NewItemAction(_EditAction): 484 class NewItemAction(_EditAction):
485 def handle(self): 485 def handle(self):
486 ''' Add a new item to the database. 486 ''' Add a new item to the database.
487 487
488 This follows the same form as the EditItemAction, with the same 488 This follows the same form as the EditItemAction, with the same
510 510
511 # redirect to the new item's page 511 # redirect to the new item's page
512 raise Redirect, '%s%s%s?@ok_message=%s&@template=%s'%(self.base, 512 raise Redirect, '%s%s%s?@ok_message=%s&@template=%s'%(self.base,
513 self.classname, self.nodeid, urllib.quote(messages), 513 self.classname, self.nodeid, urllib.quote(messages),
514 urllib.quote(self.template)) 514 urllib.quote(self.template))
515 515
516 class PassResetAction(Action): 516 class PassResetAction(Action):
517 def handle(self): 517 def handle(self):
518 """Handle password reset requests. 518 """Handle password reset requests.
519 519
520 Presence of either "name" or "address" generates email. Presence of 520 Presence of either "name" or "address" generates email. Presence of
521 "otk" performs the reset. 521 "otk" performs the reset.
522 522
523 """ 523 """
524 if self.form.has_key('otk'): 524 if self.form.has_key('otk'):
525 # pull the rego information out of the otk database 525 # pull the rego information out of the otk database
526 otk = self.form['otk'].value 526 otk = self.form['otk'].value
527 uid = self.db.otks.get(otk, 'uid') 527 uid = self.db.otks.get(otk, 'uid')
619 # pull the rego information out of the otk database 619 # pull the rego information out of the otk database
620 self.userid = self.db.confirm_registration(self.form['otk'].value) 620 self.userid = self.db.confirm_registration(self.form['otk'].value)
621 except (ValueError, KeyError), message: 621 except (ValueError, KeyError), message:
622 self.client.error_message.append(str(message)) 622 self.client.error_message.append(str(message))
623 return 623 return
624 624
625 # log the new user in 625 # log the new user in
626 self.client.user = self.db.user.get(self.userid, 'username') 626 self.client.user = self.db.user.get(self.userid, 'username')
627 # re-open the database for real, using the user 627 # re-open the database for real, using the user
628 self.client.opendb(self.client.user) 628 self.client.opendb(self.client.user)
629 629
643 self.userid, urllib.quote(message)) 643 self.userid, urllib.quote(message))
644 644
645 class RegisterAction(Action): 645 class RegisterAction(Action):
646 name = 'register' 646 name = 'register'
647 permissionType = 'Web Registration' 647 permissionType = 'Web Registration'
648 648
649 def handle(self): 649 def handle(self):
650 """Attempt to create a new user based on the contents of the form 650 """Attempt to create a new user based on the contents of the form
651 and then set the cookie. 651 and then set the cookie.
652 652
653 Return 1 on successful login. 653 Return 1 on successful login.
654 """ 654 """
655 props = self.client.parsePropsFromForm(create=1)[0][('user', None)] 655 props = self.client.parsePropsFromForm(create=1)[0][('user', None)]
656 656
657 # registration isn't allowed to supply roles 657 # registration isn't allowed to supply roles
658 if props.has_key('roles'): 658 if props.has_key('roles'):
659 raise Unauthorised, _("It is not permitted to supply roles " 659 raise Unauthorised, _("It is not permitted to supply roles "
660 "at registration.") 660 "at registration.")
661 661
662 username = props['username'] 662 username = props['username']
663 try: 663 try:
664 self.db.user.lookup(username) 664 self.db.user.lookup(username)
665 self.client.error_message.append(_('Error: A user with the ' 665 self.client.error_message.append(_('Error: A user with the '

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