Skip to content

Commit 6f8580b

Browse files
author
Richard Jones
committed
audit some user properties for valid values (roles, address)
[SF#742968] and [SF#739653]
1 parent c088667 commit 6f8580b

File tree

6 files changed

+262
-139
lines changed

6 files changed

+262
-139
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ are given with the most recent entry first.
88
- handle New User creation (sf bug 754510)
99
- fix hackish message escaping (sf bug 757128)
1010
- fix :required ordering problem (sf bug 740214)
11+
- audit some user properties for valid values (roles, address) (sf bugs
12+
742968 and 739653)
1113

1214

1315
2003-06-10 0.6.0b3

roundup/cgi/client.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: client.py,v 1.122 2003-06-24 03:58:57 richard Exp $
1+
# $Id: client.py,v 1.123 2003-06-24 04:16:35 richard Exp $
22

33
__doc__ = """
44
WWW request handler (also used in the stand-alone server).
@@ -1598,7 +1598,8 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
15981598

15991599
# we'll store info about the individual class/item edit in these
16001600
all_required = {} # required props per class/item
1601-
all_props = {} # props present per class/item
1601+
all_props = {} # props to set per class/item
1602+
got_props = {} # props received per class/item
16021603
all_propdef = {} # note - only one entry per class
16031604
all_links = [] # as many as are required
16041605

@@ -1662,6 +1663,8 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
16621663
if not all_props.has_key(this):
16631664
all_props[this] = {}
16641665
props = all_props[this]
1666+
if not got_props.has_key(this):
1667+
got_props[this] = {}
16651668

16661669
# is this a link command?
16671670
if d['link']:
@@ -1866,6 +1869,10 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
18661869
raise ValueError, _('Error with %s property: %s')%(
18671870
propname, msg)
18681871

1872+
# register that we got this property
1873+
if value:
1874+
got_props[this][propname] = 1
1875+
18691876
# get the old value
18701877
if nodeid and not nodeid.startswith('-'):
18711878
try:
@@ -1914,9 +1921,9 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
19141921
s = []
19151922
for thing, required in all_required.items():
19161923
# register the values we got
1917-
got = all_props.get(thing, {})
1924+
got = got_props.get(thing, {})
19181925
for entry in required[:]:
1919-
if got.get(entry, ''):
1926+
if got.has_key(entry):
19201927
required.remove(entry)
19211928

19221929
# any required values not present?
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright (c) 2003 Richard Jones ([email protected])
2+
#
3+
# Permission is hereby granted, free of charge, to any person obtaining a copy
4+
# of this software and associated documentation files (the "Software"), to deal
5+
# in the Software without restriction, including without limitation the rights
6+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
# copies of the Software, and to permit persons to whom the Software is
8+
# furnished to do so, subject to the following conditions:
9+
#
10+
# The above copyright notice and this permission notice shall be included in
11+
# all copies or substantial portions of the Software.
12+
#
13+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
# SOFTWARE.
20+
#
21+
#$Id: userauditor.py,v 1.1 2003-06-24 04:16:35 richard Exp $
22+
23+
def audit_user_fields(db, cl, nodeid, newvalues):
24+
''' Make sure user properties are valid.
25+
26+
- email address has no spaces in it
27+
- roles specified exist
28+
'''
29+
if newvalues.has_key('address') and ' ' in newvalues['address']:
30+
raise ValueError, 'Email address must not contain spaces'
31+
32+
if newvalues.has_key('roles'):
33+
roles = [x.lower().strip() for x in newvalues['roles'].split(',')]
34+
for rolename in roles:
35+
if not db.security.role.has_key(rolename):
36+
raise ValueError, 'Role "%s" does not exist'%rolename
37+
38+
39+
def init(db):
40+
# fire before changes are made
41+
db.user.audit('set', audit_user_fields)
42+
db.user.audit('create', audit_user_fields)
43+
44+
# vim: set filetype=python ts=4 sw=4 et si
45+
#SHA: d4aea7465d4b7ca78de71ed9e73e09ce29b1b111

templates/classic/html/issue.search.html

Lines changed: 125 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,15 @@ <h2>Issue searching</h2>
99
<input type="hidden" name=":action" value="search">
1010

1111
<table class="form" tal:define="
12-
cols python:'id activity priority title status assignedto'.split();
13-
defsort python:['activity'];
14-
defgroup python:['priority'];
15-
defdisp python:'id activity title status assignedto'.split()">
12+
cols python:request.columns or 'id activity title status assignedto'.split();
13+
sort_on python:request.sort[1] or 'activity';
14+
group_on python:request.group[1] or 'priority';
15+
16+
search_input templates/page/macros/search_input;
17+
column_input templates/page/macros/column_input;
18+
sort_input templates/page/macros/sort_input;
19+
group_input templates/page/macros/group_input;
20+
search_select templates/page/macros/search_select;">
1621

1722
<tr>
1823
<th class="header">&nbsp;</th>
@@ -22,159 +27,144 @@ <h2>Issue searching</h2>
2227
<th class="header">Group on</th>
2328
</tr>
2429

25-
<tr>
26-
<th>All text*:</th>
27-
<td><input name=":search_text"
28-
tal:attributes="value request/form/:search_text/value | nothing">
29-
</td>
30-
<td>&nbsp;</td>
31-
<td>&nbsp;</td>
32-
<td>&nbsp;</td>
33-
</tr>
34-
35-
<tr>
36-
<th>Title:</th>
37-
<td><input name="title"></td>
38-
<td><input type="checkbox" name=":columns" value="title" checked></td>
39-
<td><input type="radio" name=":sort" value="title"></td>
40-
<td>&nbsp;</td>
41-
</tr>
42-
43-
<tr>
44-
<th>Topic:</th>
45-
<td>
46-
<select name="topic">
47-
<option value="">don't care</option>
48-
<option value="">------------</option>
49-
<option tal:repeat="s db/keyword/list" tal:attributes="value s/name"
50-
tal:content="s/name">topic to filter on</option>
51-
</select>
52-
</td>
53-
<td><input type="checkbox" name=":columns" value="topic" checked></td>
54-
<td><input type="radio" name=":sort" value="topic"></td>
55-
<td><input type="radio" name=":group" value="topic"></td>
56-
</tr>
57-
58-
<tr>
59-
<th>ID:</th>
60-
<td><input name="id"></td>
61-
<td><input type="checkbox" name=":columns" value="id" checked></td>
62-
<td><input type="radio" name=":sort" value="id"></td>
63-
<td>&nbsp;</td>
64-
</tr>
65-
66-
<tr>
67-
<th>Creation date:</th>
68-
<td><input name="creation"></td>
69-
<td><input type="checkbox" name=":columns" value="creation"></td>
70-
<td><input type="radio" name=":sort" value="creation"></td>
71-
<td><input type="radio" name=":group" value="creation"></td>
72-
</tr>
73-
74-
<tr>
75-
<th>Creator:</th>
76-
<td>
77-
<select name="creator">
78-
<option value="">don't care</option>
79-
<option tal:attributes="value request/user/id">created by me</option>
80-
<option value="-1">------------</option>
81-
<option tal:repeat="s db/user/list" tal:attributes="value s/id"
82-
tal:content="s/username">user to filter on</option>
83-
</select>
84-
</td>
85-
<td><input type="checkbox" name=":columns" value="creator" checked></td>
86-
<td><input type="radio" name=":sort" value="creator"></td>
87-
<td><input type="radio" name=":group" value="creator"></td>
88-
</tr>
89-
90-
<tr>
91-
<th>Activity:</th>
92-
<td><input name="activity"></td>
93-
<td><input type="checkbox" name=":columns" value="activity" checked></td>
94-
<td><input type="radio" name=":sort" value="activity"></td>
95-
<td>&nbsp;</td>
96-
</tr>
97-
98-
<tr>
99-
<th>Priority:</th>
100-
<td>
101-
<select name="priority">
102-
<option value="">don't care</option>
103-
<option value="-1">not selected</option>
104-
<option value="">------------</option>
105-
<option tal:repeat="s db/priority/list" tal:attributes="value s/id"
106-
tal:content="s/name">priority to filter on</option>
107-
</select>
108-
</td>
109-
<td><input type="checkbox" name=":columns" value="priority"></td>
110-
<td><input type="radio" name=":sort" value="priority"></td>
111-
<td><input type="radio" name=":group" value="priority"></td>
112-
</tr>
113-
114-
<tr>
115-
<th>Status:</th>
116-
<td>
117-
<select name="status">
118-
<option value="">don't care</option>
119-
<option value="-1,1,2,3,4,5,6,7">not resolved</option>
120-
<option value="-1">not selected</option>
121-
<option value="">------------</option>
122-
<option tal:repeat="s db/status/list" tal:attributes="value s/id"
123-
tal:content="s/name">status to filter on</option>
124-
</select>
125-
</td>
126-
<td><input type="checkbox" name=":columns" value="status" checked></td>
127-
<td><input type="radio" name=":sort" value="status"></td>
128-
<td><input type="radio" name=":group" value="status"></td>
129-
</tr>
130-
131-
<tr>
132-
<th>Assigned To:</th>
133-
<td>
134-
<select name="assignedto">
135-
<option value="">don't care</option>
136-
<option tal:attributes="value request/user/id">assigned to me</option>
137-
<option value="-1">unassigned</option>
138-
<option value="">------------</option>
139-
<option tal:repeat="s db/user/list" tal:attributes="value s/id"
140-
tal:content="s/username">user to filter on</option>
141-
</select>
142-
</td>
143-
<td><input type="checkbox" name=":columns" value="assignedto" checked></td>
144-
<td><input type="radio" name=":sort" value="assignedto"></td>
145-
<td><input type="radio" name=":group" value="assignedto"></td>
30+
<tr tal:define="name string::search_text">
31+
<th>All text*:</th>
32+
<td metal:use-macro="search_input"></td>
33+
<td>&nbsp;</td>
34+
<td>&nbsp;</td>
35+
<td>&nbsp;</td>
36+
</tr>
37+
38+
<tr tal:define="name string:title">
39+
<th>Title:</th>
40+
<td metal:use-macro="search_input"></td>
41+
<td metal:use-macro="column_input"></td>
42+
<td metal:use-macro="sort_input"></td>
43+
<td>&nbsp;</td>
44+
</tr>
45+
46+
<tr tal:define="name string:topic;
47+
db_klass string:keyword;
48+
db_content string:name;">
49+
<th>Topic:</th>
50+
<td metal:use-macro="search_select"></td>
51+
<td metal:use-macro="column_input"></td>
52+
<td metal:use-macro="sort_input"></td>
53+
<td metal:use-macro="group_input"></td>
54+
</tr>
55+
56+
<tr tal:define="name string:id">
57+
<th>ID:</th>
58+
<td metal:use-macro="search_input"></td>
59+
<td metal:use-macro="column_input"></td>
60+
<td metal:use-macro="sort_input"></td>
61+
<td>&nbsp;</td>
62+
</tr>
63+
64+
<tr tal:define="name string:creation">
65+
<th>Creation Date:</th>
66+
<td metal:use-macro="search_input"></td>
67+
<td metal:use-macro="column_input"></td>
68+
<td metal:use-macro="sort_input"></td>
69+
<td metal:use-macro="group_input"></td>
70+
</tr>
71+
72+
<tr tal:define="name string:creator;
73+
db_klass string:user;
74+
db_content string:username;">
75+
<th>Creator:</th>
76+
<td metal:use-macro="search_select">
77+
<option metal:fill-slot="extra_options"
78+
tal:attributes="value request/user/id">created by me</option>
79+
</td>
80+
<td metal:use-macro="column_input"></td>
81+
<td metal:use-macro="sort_input"></td>
82+
<td metal:use-macro="group_input"></td>
83+
</tr>
84+
85+
<tr tal:define="name string:activity">
86+
<th>Activity:</th>
87+
<td metal:use-macro="search_input"></td>
88+
<td metal:use-macro="column_input"></td>
89+
<td metal:use-macro="sort_input"></td>
90+
<td>&nbsp;</td>
91+
</tr>
92+
93+
<tr tal:define="name string:priority;
94+
db_klass string:priority;
95+
db_content string:name;">
96+
<th>Priority:</th>
97+
<td metal:use-macro="search_select">
98+
<option metal:fill-slot="extra_options" value="-1"
99+
tal:attributes="selected python:value == '-1'">not selected</option>
100+
</td>
101+
<td metal:use-macro="column_input"></td>
102+
<td metal:use-macro="sort_input"></td>
103+
<td metal:use-macro="group_input"></td>
104+
</tr>
105+
106+
<tr tal:define="name string:status;
107+
db_klass string:status;
108+
db_content string:name;">
109+
<th>Status:</th>
110+
<td metal:use-macro="search_select">
111+
<tal:block metal:fill-slot="extra_options">
112+
<option value="-1,1,2,3,4,5,6,7"
113+
tal:attributes="selected python:value == '-1,1,2,3,4,5,6,7'">not resolved</option>
114+
<option value="-1"
115+
tal:attributes="selected python:value == '-1'">not selected</option>
116+
</tal:block>
117+
</td>
118+
<td metal:use-macro="column_input"></td>
119+
<td metal:use-macro="sort_input"></td>
120+
<td metal:use-macro="group_input"></td>
121+
</tr>
122+
123+
<tr tal:define="name string:assignedto;
124+
db_klass string:user;
125+
db_content string:username;">
126+
<th>Assigned to:</th>
127+
<td metal:use-macro="search_select">
128+
<tal:block metal:fill-slot="extra_options">
129+
<option tal:attributes="value request/user/id">assigned to me</option>
130+
<option value="-1" tal:attributes="selected python:value == '-1'">unassigned</option>
131+
</tal:block>
132+
</td>
133+
<td metal:use-macro="column_input"></td>
134+
<td metal:use-macro="sort_input"></td>
135+
<td metal:use-macro="group_input"></td>
146136
</tr>
147137

148138
<tr>
149139
<th>Pagesize:</th>
150-
<td><input type="text" name=":pagesize" size="3" value="50"></td>
140+
<td><input name=":pagesize" size="3" value="50"
141+
tal:attributes="value request/form/:pagesize/value | default"></td>
151142
</tr>
152143

153144
<tr>
154145
<th>Start With:</th>
155-
<td><input type="text" name=":startwith" size="3" value="0"></td>
146+
<td><input name=":startwith" size="3" value="0"
147+
tal:attributes="value request/form/:startwith/value | default"></td>
156148
</tr>
157149

158150
<tr>
159151
<th>Sort Descending:</th>
160-
<td><input type="checkbox" name=":sortdir" checked>
152+
<td><input type="checkbox" name=":sortdir"
153+
tal:attributes="checked python:request.sort[0] == '-' or request.sort[0] is None">
161154
</td>
155+
</tr>
162156

163157
<tr>
164158
<th>Group Descending:</th>
165-
<td><input type="checkbox" name=":groupdir">
159+
<td><input type="checkbox" name=":groupdir"
160+
tal:attributes="checked python:request.group[0] == '-'">
166161
</td>
167162
</tr>
168163

169164
<tr>
170165
<th>Query name**:</th>
171166
<td><input name=":queryname"
172-
tal:attributes="value request/form/:queryname/value | nothing">
173-
</td>
174-
</tr>
175-
176-
<tr><td>&nbsp;</td>
177-
<td><input type="submit" value="Search"></td>
167+
tal:attributes="value request/form/:queryname/value | default"></td>
178168
</tr>
179169

180170
<tr><td>&nbsp;</td>

0 commit comments

Comments
 (0)