summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: bd2e611)
raw | patch | inline | side by side (parent: bd2e611)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 24 Jun 2003 04:16:35 +0000 (04:16 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 24 Jun 2003 04:16:35 +0000 (04:16 +0000) |
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1759 57a73879-2fb5-44c3-a270-3262357dd7e2
CHANGES.txt | patch | blob | history | |
roundup/cgi/client.py | patch | blob | history | |
templates/classic/detectors/userauditor.py | [new file with mode: 0644] | patch | blob |
templates/classic/html/issue.search.html | patch | blob | history | |
templates/classic/html/page.html | patch | blob | history | |
templates/minimal/detectors/userauditor.py | [new file with mode: 0644] | patch | blob |
diff --git a/CHANGES.txt b/CHANGES.txt
index 4f501b1e66539cb7096c6527b40fb6a021c4f829..4a2fa65b6baff0e99de862e95caf9d91676671fd 100644 (file)
--- a/CHANGES.txt
+++ b/CHANGES.txt
- handle New User creation (sf bug 754510)
- fix hackish message escaping (sf bug 757128)
- fix :required ordering problem (sf bug 740214)
+- audit some user properties for valid values (roles, address) (sf bugs
+ 742968 and 739653)
2003-06-10 0.6.0b3
diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index 09f866d51286f0994370b07bb7b1caaa8cc957fb..3c7e9f09aa69b6d5f7b0498b678675cbe3ed1cd8 100644 (file)
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
-# $Id: client.py,v 1.122 2003-06-24 03:58:57 richard Exp $
+# $Id: client.py,v 1.123 2003-06-24 04:16:35 richard Exp $
__doc__ = """
WWW request handler (also used in the stand-alone server).
# we'll store info about the individual class/item edit in these
all_required = {} # required props per class/item
- all_props = {} # props present per class/item
+ all_props = {} # props to set per class/item
+ got_props = {} # props received per class/item
all_propdef = {} # note - only one entry per class
all_links = [] # as many as are required
if not all_props.has_key(this):
all_props[this] = {}
props = all_props[this]
+ if not got_props.has_key(this):
+ got_props[this] = {}
# is this a link command?
if d['link']:
raise ValueError, _('Error with %s property: %s')%(
propname, msg)
+ # register that we got this property
+ if value:
+ got_props[this][propname] = 1
+
# get the old value
if nodeid and not nodeid.startswith('-'):
try:
s = []
for thing, required in all_required.items():
# register the values we got
- got = all_props.get(thing, {})
+ got = got_props.get(thing, {})
for entry in required[:]:
- if got.get(entry, ''):
+ if got.has_key(entry):
required.remove(entry)
# any required values not present?
diff --git a/templates/classic/detectors/userauditor.py b/templates/classic/detectors/userauditor.py
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (c) 2003 Richard Jones (richard@mechanicalcat.net)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#$Id: userauditor.py,v 1.1 2003-06-24 04:16:35 richard Exp $
+
+def audit_user_fields(db, cl, nodeid, newvalues):
+ ''' Make sure user properties are valid.
+
+ - email address has no spaces in it
+ - roles specified exist
+ '''
+ if newvalues.has_key('address') and ' ' in newvalues['address']:
+ raise ValueError, 'Email address must not contain spaces'
+
+ if newvalues.has_key('roles'):
+ roles = [x.lower().strip() for x in newvalues['roles'].split(',')]
+ for rolename in roles:
+ if not db.security.role.has_key(rolename):
+ raise ValueError, 'Role "%s" does not exist'%rolename
+
+
+def init(db):
+ # fire before changes are made
+ db.user.audit('set', audit_user_fields)
+ db.user.audit('create', audit_user_fields)
+
+# vim: set filetype=python ts=4 sw=4 et si
+#SHA: d4aea7465d4b7ca78de71ed9e73e09ce29b1b111
index 4f9112d9bbc1911dff74d05398e58af60f997be6..24563be1a825e330648f9ce2d645a849aada3514 100644 (file)
<input type="hidden" name=":action" value="search">
<table class="form" tal:define="
- cols python:'id activity priority title status assignedto'.split();
- defsort python:['activity'];
- defgroup python:['priority'];
- defdisp python:'id activity title status assignedto'.split()">
+ cols python:request.columns or 'id activity title status assignedto'.split();
+ sort_on python:request.sort[1] or 'activity';
+ group_on python:request.group[1] or 'priority';
+
+ search_input templates/page/macros/search_input;
+ column_input templates/page/macros/column_input;
+ sort_input templates/page/macros/sort_input;
+ group_input templates/page/macros/group_input;
+ search_select templates/page/macros/search_select;">
<tr>
<th class="header"> </th>
<th class="header">Group on</th>
</tr>
-<tr>
- <th>All text*:</th>
- <td><input name=":search_text"
- tal:attributes="value request/form/:search_text/value | nothing">
- </td>
- <td> </td>
- <td> </td>
- <td> </td>
-</tr>
-
-<tr>
- <th>Title:</th>
- <td><input name="title"></td>
- <td><input type="checkbox" name=":columns" value="title" checked></td>
- <td><input type="radio" name=":sort" value="title"></td>
- <td> </td>
-</tr>
-
-<tr>
- <th>Topic:</th>
- <td>
- <select name="topic">
- <option value="">don't care</option>
- <option value="">------------</option>
- <option tal:repeat="s db/keyword/list" tal:attributes="value s/name"
- tal:content="s/name">topic to filter on</option>
- </select>
- </td>
- <td><input type="checkbox" name=":columns" value="topic" checked></td>
- <td><input type="radio" name=":sort" value="topic"></td>
- <td><input type="radio" name=":group" value="topic"></td>
-</tr>
-
-<tr>
- <th>ID:</th>
- <td><input name="id"></td>
- <td><input type="checkbox" name=":columns" value="id" checked></td>
- <td><input type="radio" name=":sort" value="id"></td>
- <td> </td>
-</tr>
-
-<tr>
- <th>Creation date:</th>
- <td><input name="creation"></td>
- <td><input type="checkbox" name=":columns" value="creation"></td>
- <td><input type="radio" name=":sort" value="creation"></td>
- <td><input type="radio" name=":group" value="creation"></td>
-</tr>
-
-<tr>
- <th>Creator:</th>
- <td>
- <select name="creator">
- <option value="">don't care</option>
- <option tal:attributes="value request/user/id">created by me</option>
- <option value="-1">------------</option>
- <option tal:repeat="s db/user/list" tal:attributes="value s/id"
- tal:content="s/username">user to filter on</option>
- </select>
- </td>
- <td><input type="checkbox" name=":columns" value="creator" checked></td>
- <td><input type="radio" name=":sort" value="creator"></td>
- <td><input type="radio" name=":group" value="creator"></td>
-</tr>
-
-<tr>
- <th>Activity:</th>
- <td><input name="activity"></td>
- <td><input type="checkbox" name=":columns" value="activity" checked></td>
- <td><input type="radio" name=":sort" value="activity"></td>
- <td> </td>
-</tr>
-
-<tr>
- <th>Priority:</th>
- <td>
- <select name="priority">
- <option value="">don't care</option>
- <option value="-1">not selected</option>
- <option value="">------------</option>
- <option tal:repeat="s db/priority/list" tal:attributes="value s/id"
- tal:content="s/name">priority to filter on</option>
- </select>
- </td>
- <td><input type="checkbox" name=":columns" value="priority"></td>
- <td><input type="radio" name=":sort" value="priority"></td>
- <td><input type="radio" name=":group" value="priority"></td>
-</tr>
-
-<tr>
- <th>Status:</th>
- <td>
- <select name="status">
- <option value="">don't care</option>
- <option value="-1,1,2,3,4,5,6,7">not resolved</option>
- <option value="-1">not selected</option>
- <option value="">------------</option>
- <option tal:repeat="s db/status/list" tal:attributes="value s/id"
- tal:content="s/name">status to filter on</option>
- </select>
- </td>
- <td><input type="checkbox" name=":columns" value="status" checked></td>
- <td><input type="radio" name=":sort" value="status"></td>
- <td><input type="radio" name=":group" value="status"></td>
-</tr>
-
-<tr>
- <th>Assigned To:</th>
- <td>
- <select name="assignedto">
- <option value="">don't care</option>
- <option tal:attributes="value request/user/id">assigned to me</option>
- <option value="-1">unassigned</option>
- <option value="">------------</option>
- <option tal:repeat="s db/user/list" tal:attributes="value s/id"
- tal:content="s/username">user to filter on</option>
- </select>
- </td>
- <td><input type="checkbox" name=":columns" value="assignedto" checked></td>
- <td><input type="radio" name=":sort" value="assignedto"></td>
- <td><input type="radio" name=":group" value="assignedto"></td>
+<tr tal:define="name string::search_text">
+ <th>All text*:</th>
+ <td metal:use-macro="search_input"></td>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:title">
+ <th>Title:</th>
+ <td metal:use-macro="search_input"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:topic;
+ db_klass string:keyword;
+ db_content string:name;">
+ <th>Topic:</th>
+ <td metal:use-macro="search_select"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:id">
+ <th>ID:</th>
+ <td metal:use-macro="search_input"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:creation">
+ <th>Creation Date:</th>
+ <td metal:use-macro="search_input"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:creator;
+ db_klass string:user;
+ db_content string:username;">
+ <th>Creator:</th>
+ <td metal:use-macro="search_select">
+ <option metal:fill-slot="extra_options"
+ tal:attributes="value request/user/id">created by me</option>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:activity">
+ <th>Activity:</th>
+ <td metal:use-macro="search_input"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:priority;
+ db_klass string:priority;
+ db_content string:name;">
+ <th>Priority:</th>
+ <td metal:use-macro="search_select">
+ <option metal:fill-slot="extra_options" value="-1"
+ tal:attributes="selected python:value == '-1'">not selected</option>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:status;
+ db_klass string:status;
+ db_content string:name;">
+ <th>Status:</th>
+ <td metal:use-macro="search_select">
+ <tal:block metal:fill-slot="extra_options">
+ <option value="-1,1,2,3,4,5,6,7"
+ tal:attributes="selected python:value == '-1,1,2,3,4,5,6,7'">not resolved</option>
+ <option value="-1"
+ tal:attributes="selected python:value == '-1'">not selected</option>
+ </tal:block>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:assignedto;
+ db_klass string:user;
+ db_content string:username;">
+ <th>Assigned to:</th>
+ <td metal:use-macro="search_select">
+ <tal:block metal:fill-slot="extra_options">
+ <option tal:attributes="value request/user/id">assigned to me</option>
+ <option value="-1" tal:attributes="selected python:value == '-1'">unassigned</option>
+ </tal:block>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
</tr>
<tr>
<th>Pagesize:</th>
-<td><input type="text" name=":pagesize" size="3" value="50"></td>
+<td><input name=":pagesize" size="3" value="50"
+ tal:attributes="value request/form/:pagesize/value | default"></td>
</tr>
<tr>
<th>Start With:</th>
-<td><input type="text" name=":startwith" size="3" value="0"></td>
+<td><input name=":startwith" size="3" value="0"
+ tal:attributes="value request/form/:startwith/value | default"></td>
</tr>
<tr>
<th>Sort Descending:</th>
-<td><input type="checkbox" name=":sortdir" checked>
+<td><input type="checkbox" name=":sortdir"
+ tal:attributes="checked python:request.sort[0] == '-' or request.sort[0] is None">
</td>
+</tr>
<tr>
<th>Group Descending:</th>
-<td><input type="checkbox" name=":groupdir">
+<td><input type="checkbox" name=":groupdir"
+ tal:attributes="checked python:request.group[0] == '-'">
</td>
</tr>
<tr>
<th>Query name**:</th>
<td><input name=":queryname"
- tal:attributes="value request/form/:queryname/value | nothing">
-</td>
-</tr>
-
-<tr><td> </td>
-<td><input type="submit" value="Search"></td>
+ tal:attributes="value request/form/:queryname/value | default"></td>
</tr>
<tr><td> </td>
index 64b0116fa18d9e36f90679e6b4339ae332954a48..ee9a5038cae789bb07ddddbcad382d3e4f8cae78 100644 (file)
</body>
</html>
+
+<td metal:define-macro="search_input">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name">
+</td>
+
+<td metal:define-macro="search_select">
+ <select tal:attributes="name name"
+ tal:define="value python:request.form.getvalue(name)">
+ <option value="">don't care</option>
+ <tal:block metal:define-slot="extra_options"></tal:block>
+ <option value="">------------</option>
+ <option tal:repeat="s python:db[db_klass].list()"
+ tal:attributes="value s/id; selected python:value == s.id"
+ tal:content="python:s[db_content]"></option>
+ </select>
+</td>
+
+<td metal:define-macro="column_input">
+ <input type="checkbox" name=":columns"
+ tal:attributes="value name;
+ checked python:name in cols">
+</td>
+
+<td metal:define-macro="sort_input">
+ <input type="radio" name=":sort"
+ tal:attributes="value name;
+ checked python:name == sort_on">
+</td>
+
+<td metal:define-macro="group_input">
+ <input type="radio" name=":group"
+ tal:attributes="value name;
+ checked python:name == group_on">
diff --git a/templates/minimal/detectors/userauditor.py b/templates/minimal/detectors/userauditor.py
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (c) 2003 Richard Jones (richard@mechanicalcat.net)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#$Id: userauditor.py,v 1.1 2003-06-24 04:16:35 richard Exp $
+
+def audit_user_fields(db, cl, nodeid, newvalues):
+ ''' Make sure user properties are valid.
+
+ - email address has no spaces in it
+ - roles specified exist
+ '''
+ if newvalues.has_key('address') and ' ' in newvalues['address']:
+ raise ValueError, 'Email address must not contain spaces'
+
+ if newvalues.has_key('roles'):
+ roles = [x.lower().strip() for x in newvalues['roles'].split(',')]
+ for rolename in roles:
+ if not db.security.role.has_key(rolename):
+ raise ValueError, 'Role "%s" does not exist'%rolename
+
+
+def init(db):
+ # fire before changes are made
+ db.user.audit('set', audit_user_fields)
+ db.user.audit('create', audit_user_fields)
+
+# vim: set filetype=python ts=4 sw=4 et si
+#SHA: d4aea7465d4b7ca78de71ed9e73e09ce29b1b111