Mercurial > p > roundup > code
diff roundup/cgi/templating.py @ 2649:1df7d4a41da4
Buncha stuff (sorry about the large checkin):
- Permissions may now be defined on a per-property basis
- added "Create" Permission. Replaces the "Web"- and "Email Registration"
Permissions.
- added option to turn off registration confirmation via email
("instant_registration" in config)
Migrated the user edit/view permission to use check code.
Fixed a buncha stuff in the default templates. Needs a thorough review
though.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Wed, 28 Jul 2004 02:29:46 +0000 |
| parents | b01eca163779 |
| children | 17bab083c8a0 |
line wrap: on
line diff
--- a/roundup/cgi/templating.py Tue Jul 27 11:36:01 2004 +0000 +++ b/roundup/cgi/templating.py Wed Jul 28 02:29:46 2004 +0000 @@ -262,17 +262,10 @@ } # add in the item if there is one if client.nodeid: - if classname == 'user': - c['context'] = HTMLUser(client, classname, client.nodeid, - anonymous=1) - else: - c['context'] = HTMLItem(client, classname, client.nodeid, - anonymous=1) + c['context'] = HTMLItem(client, classname, client.nodeid, + anonymous=1) elif client.db.classes.has_key(classname): - if classname == 'user': - c['context'] = HTMLUserClass(client, classname, anonymous=1) - else: - c['context'] = HTMLClass(client, classname, anonymous=1) + c['context'] = HTMLClass(client, classname, anonymous=1) return c class RoundupPageTemplate(PageTemplate.PageTemplate): @@ -328,15 +321,9 @@ if m: cl = m.group('cl') self._client.db.getclass(cl) - if cl == 'user': - klass = HTMLUser - else: - klass = HTMLItem - return klass(self._client, cl, m.group('id')) + return HTMLItem(self._client, cl, m.group('id')) else: self._client.db.getclass(item) - if item == 'user': - return HTMLUserClass(self._client, item) return HTMLClass(self._client, item) def __getattr__(self, attr): @@ -350,10 +337,7 @@ l.sort() m = [] for item in l: - if item == 'user': - m.append(HTMLUserClass(self._client, item)) - else: - m.append(HTMLClass(self._client, item)) + m.append(HTMLClass(self._client, item)) return m def lookupIds(db, prop, ids, fail_ok=0, num_re=re.compile('^-?\d+$')): @@ -386,42 +370,6 @@ l.append(entry) return l -class HTMLPermissions: - ''' Helpers that provide answers to commonly asked Permission questions. - ''' - def is_edit_ok(self): - ''' Is the user allowed to Edit the current class? - ''' - return self._db.security.hasPermission('Edit', self._client.userid, - self._classname) - - def is_view_ok(self): - ''' Is the user allowed to View the current class? - ''' - return self._db.security.hasPermission('View', self._client.userid, - self._classname) - - def is_only_view_ok(self): - ''' Is the user only allowed to View (ie. not Edit) the current class? - ''' - return self.is_view_ok() and not self.is_edit_ok() - - def view_check(self): - ''' Raise the Unauthorised exception if the user's not permitted to - view this class. - ''' - if not self.is_view_ok(): - raise Unauthorised("view", self._classname, - translator=self._client.translator) - - def edit_check(self): - ''' Raise the Unauthorised exception if the user's not permitted to - edit this class. - ''' - if not self.is_edit_ok(): - raise Unauthorised("edit", self._classname, - translator=self._client.translator) - def input_html4(**attrs): """Generate an 'input' (html4) element with given attributes""" return '<input %s>'%' '.join(['%s="%s"'%item for item in attrs.items()]) @@ -453,6 +401,32 @@ _ = gettext +class HTMLPermissions: + + def view_check(self): + ''' Raise the Unauthorised exception if the user's not permitted to + view this class. + ''' + if not self.is_view_ok(): + raise Unauthorised("view", self._classname, + translator=self._client.translator) + + def create_check(self): + ''' Raise the Unauthorised exception if the user's not permitted to + create items of this class. + ''' + if not self.is_create_ok(): + raise Unauthorised("create", self._classname, + translator=self._client.translator) + + def edit_check(self): + ''' Raise the Unauthorised exception if the user's not permitted to + edit items of this class. + ''' + if not self.is_edit_ok(): + raise Unauthorised("edit", self._classname, + translator=self._client.translator) + class HTMLClass(HTMLInputMixin, HTMLPermissions): ''' Accesses through a class (either through *class* or *db.<classname>*) ''' @@ -469,6 +443,25 @@ HTMLInputMixin.__init__(self) + def is_edit_ok(self): + ''' Is the user allowed to Create the current class? + ''' + return self._db.security.hasPermission('Create', self._client.userid, + self._classname) + + def is_view_ok(self): + ''' Is the user allowed to View the current class? + ''' + if self._db.security.hasPermission('View', self._client.userid, + self._classname): + return 1 + return self.is_create_ok() + + def is_only_view_ok(self): + ''' Is the user only allowed to View (ie. not Create) the current class? + ''' + return self.is_view_ok() and not self.is_create_ok() + def __repr__(self): return '<HTMLClass(0x%x) %s>'%(id(self), self.classname) @@ -534,12 +527,7 @@ if not isinstance(itemid, type(1)) and not num_re.match(itemid): itemid = self._klass.lookup(itemid) - if self.classname == 'user': - klass = HTMLUser - else: - klass = HTMLItem - - return klass(self._client, self.classname, itemid) + return HTMLItem(self._client, self.classname, itemid) def properties(self, sort=1): ''' Return HTMLProperty for all of this class' properties. @@ -561,17 +549,12 @@ def list(self, sort_on=None): ''' List all items in this class. ''' - if self.classname == 'user': - klass = HTMLUser - else: - klass = HTMLItem - # get the list and sort it nicely l = self._klass.list() sortfunc = make_sort_function(self._db, self.classname, sort_on) l.sort(sortfunc) - l = [klass(self._client, self.classname, x) for x in l] + l = [HTMLItem(self._client, self.classname, x) for x in l] return l def csv(self): @@ -615,11 +598,7 @@ filterspec = request.filterspec sort = request.sort group = request.group - if self.classname == 'user': - klass = HTMLUser - else: - klass = HTMLItem - l = [klass(self._client, self.classname, x) + l = [HTMLItem(self._client, self.classname, x) for x in self._klass.filter(None, filterspec, sort, group)] return l @@ -683,7 +662,7 @@ } return pt.render(self._client, self.classname, req, **args) -class HTMLItem(HTMLInputMixin, HTMLPermissions): +class _HTMLItem(HTMLInputMixin, HTMLPermissions): ''' Accesses through an *item* ''' def __init__(self, client, classname, nodeid, anonymous=0): @@ -699,6 +678,25 @@ HTMLInputMixin.__init__(self) + def is_edit_ok(self): + ''' Is the user allowed to Edit the current class? + ''' + return self._db.security.hasPermission('Edit', self._client.userid, + self._classname, itemid=self._nodeid) + + def is_view_ok(self): + ''' Is the user allowed to View the current class? + ''' + if self._db.security.hasPermission('View', self._client.userid, + self._classname, itemid=self._nodeid): + return 1 + return self.is_edit_ok() + + def is_only_view_ok(self): + ''' Is the user only allowed to View (ie. not Edit) the current class? + ''' + return self.is_view_ok() and not self.is_edit_ok() + def __repr__(self): return '<HTMLItem(0x%x) %s %s>'%(id(self), self._classname, self._nodeid) @@ -1010,66 +1008,26 @@ url = '%s%s/%s'%(self._classname, self._nodeid, name) return urllib.quote(url) - -class HTMLUserPermission: - - def is_edit_ok(self): - ''' Is the user allowed to Edit the current class? - Also check whether this is the current user's info. - ''' - return self._user_perm_check('Edit') - - def is_view_ok(self): - ''' Is the user allowed to View the current class? - Also check whether this is the current user's info. - ''' - return self._user_perm_check('View') - - def _user_perm_check(self, type): - # some users may view / edit all users - s = self._db.security - userid = self._client.userid - if s.hasPermission(type, userid, self._classname): - return 1 - - # users may view their own info - is_anonymous = self._db.user.get(userid, 'username') == 'anonymous' - if getattr(self, '_nodeid', None) == userid and not is_anonymous: - return 1 - - # may anonymous users register? (so, they need to be anonymous, - # need the Web Rego permission, and not trying to view an item) - rego = s.hasPermission('Web Registration', userid, self._classname) - rego = rego and self._client.template == 'register' - if is_anonymous and rego and getattr(self, '_nodeid', None) is None: - return 1 - - # nope, no access here - return 0 - -class HTMLUserClass(HTMLUserPermission, HTMLClass): - pass - -class HTMLUser(HTMLUserPermission, HTMLItem): - ''' Accesses through the *user* (a special case of item) +class _HTMLUser(_HTMLItem): + '''Add ability to check for permissions on users. ''' - def __init__(self, client, classname, nodeid, anonymous=0): - HTMLItem.__init__(self, client, 'user', nodeid, anonymous) - self._default_classname = client.classname - - # used for security checks - self._security = client.db.security - _marker = [] def hasPermission(self, permission, classname=_marker): - ''' Determine if the user has the Permission. + '''Determine if the user has the Permission. - The class being tested defaults to the template's class, but may - be overidden for this test by suppling an alternate classname. + The class being tested defaults to the template's class, but may + be overidden for this test by suppling an alternate classname. ''' if classname is self._marker: - classname = self._default_classname - return self._security.hasPermission(permission, self._nodeid, classname) + classname = self._client.classname + return self._client.db.security.hasPermission(permission, + self._nodeid, classname) + +def HTMLItem(client, classname, nodeid, anonymous=0): + if classname == 'user': + return _HTMLUser(client, classname, nodeid, anonymous) + else: + return _HTMLItem(client, classname, nodeid, anonymous) class HTMLProperty(HTMLInputMixin, HTMLPermissions): ''' String, Number, Date, Interval HTMLProperty @@ -1116,24 +1074,23 @@ return self._value is not None def is_edit_ok(self): - ''' Is the user allowed to Edit the current class? + '''Should the user be allowed to use an edit form field for this + property. Check "Create" for new items, or "Edit" for existing + ones. ''' - thing = HTMLDatabase(self._client)[self._classname] if self._nodeid: - # this is a special-case for the User class where permission's - # on a per-item basis :( - thing = thing.getItem(self._nodeid) - return thing.is_edit_ok() + return self._db.security.hasPermission('Edit', self._client.userid, + self._classname, self._name, self._nodeid) + return self._db.security.hasPermission('Create', self._client.userid, + self._classname, self._name) def is_view_ok(self): ''' Is the user allowed to View the current class? ''' - thing = HTMLDatabase(self._client)[self._classname] - if self._nodeid: - # this is a special-case for the User class where permission's - # on a per-item basis :( - thing = thing.getItem(self._nodeid) - return thing.is_view_ok() + if self._db.security.hasPermission('View', self._client.userid, + self._classname, self._name, self._nodeid): + return 1 + return self.is_edit_ok() class StringHTMLProperty(HTMLProperty): hyper_re = re.compile(r'((?P<url>\w{3,6}://\S+)|' @@ -1551,11 +1508,7 @@ #print 'Link.getattr', (self, attr, self._value) if not self._value: raise AttributeError, "Can't access missing value" - if self._prop.classname == 'user': - klass = HTMLUser - else: - klass = HTMLItem - i = klass(self._client, self._prop.classname, self._value) + i = HTMLItem(self._client, self._prop.classname, self._value) return getattr(i, attr) def plain(self, escape=0): @@ -1688,11 +1641,7 @@ ''' #print 'Multi.getitem', (self, num) value = self._value[num] - if self._prop.classname == 'user': - klass = HTMLUser - else: - klass = HTMLItem - return klass(self._client, self._prop.classname, value) + return HTMLItem(self._client, self._prop.classname, value) def __contains__(self, value): ''' Support the "in" operator. We have to make sure the passed-in @@ -1709,11 +1658,8 @@ ''' l = self._value[:] l.reverse() - if self._prop.classname == 'user': - klass = HTMLUser - else: - klass = HTMLItem - return [klass(self._client, self._prop.classname, value) for value in l] + return [HTMLItem(self._client, self._prop.classname, value) + for value in l] def plain(self, escape=0): ''' Render a "plain" representation of the property @@ -1865,7 +1811,7 @@ - "form" the CGI form as a cgi.FieldStorage - "env" the CGI environment variables - "base" the base URL for this instance - - "user" a HTMLUser instance for this user + - "user" a HTMLItem instance for this user - "classname" the current classname (possibly None) - "template" the current template (suffix, also possibly None) @@ -1888,7 +1834,7 @@ self.form = client.form self.env = client.env self.base = client.base - self.user = HTMLUser(client, 'user', client.userid) + self.user = HTMLItem(client, 'user', client.userid) # store the current class name and action self.classname = client.classname @@ -2220,10 +2166,7 @@ item = self._sequence[index + self.first] if self.classname: # map the item ids to instances - if self.classname == 'user': - item = HTMLUser(self.client, self.classname, item) - else: - item = HTMLItem(self.client, self.classname, item) + item = HTMLItem(self.client, self.classname, item) self.current_item = item return item
