Code

- Add explicit "Search" permissions, see Security Fix below.
[roundup.git] / share / roundup / templates / devel / schema.py
2 #
3 # TRACKER SCHEMA
4 #
6 # Class automatically gets these properties:
7 #   creation = Date()
8 #   activity = Date()
9 #   creator = Link('user')
10 #   actor = Link('user')
13 # This is the repository class, then you can see/edit repositories in pages like
14 # "http://tracker/url/vcs_repo1"
15 vcs_repo = Class(db, "vcs_repo",
16 name=String(),
17 host=String(),
18 path=String(),
19 webview_url=String())
20 vcs_repo.setkey('name')
22 # Stores revision data, lets you see/edit revisions in pages like
23 # "http://tracker/url/vcs_rev1". The vcs_rev.item.html template is currently
24 # broken, but this works fine without it.
25 vcs_rev = Class(db, "vcs_rev",
26 repository=Link('vcs_repo'),
27 revision=String())
31 # Component
32 component = Class(db, 'component',
33                   name=String(),
34                   description=String(),
35                   order=Number(),
36                   assign_to=Link('user'))
37 component.setkey('name')
39 # Version
40 version = Class(db, 'version',
41                 name=String(),
42                 description=String(),
43                 order=Number())
44 version.setkey('name')
46 # Severity
47 severity = Class(db, 'severity',
48                  name=String(),
49                  description=String(),
50                  order=Number())
51 severity.setkey('name')
53 # Priority
54 priority = Class(db, 'priority',
55                  name=String(),
56                  description=String(),
57                  order=Number())
58 priority.setkey('name')
60 # Status
61 status = Class(db, "status",
62                name=String(),
63                description=String(),
64                order=Number())
65 status.setkey("name")
67 # Resolution
68 resolution = Class(db, "resolution",
69                    name=String(),
70                    description=String(),
71                    order=Number())
72 resolution.setkey('name')
74 # Keyword
75 keyword = Class(db, "keyword",
76                 name=String(),
77                 description=String())
78 keyword.setkey("name")
79                 
81 # User-defined saved searches
82 query = Class(db, "query",
83               klass=String(),
84               name=String(),
85               url=String(),
86               private_for=Link('user'))
88 # add any additional database schema configuration here
90 user = Class(db, "user",
91              username=String(),
92              password=Password(),
93              address=String(),
94              realname=String(),
95              phone=String(),
96              organisation=String(),
97              alternate_addresses=String(),
98              queries=Multilink('query'),
99              roles=String(),     # comma-separated string of Role names
100              timezone=String(),
101              vcs_name=String())
103 user.setkey("username")
105 # Permissions for revision creation and repository viewing.
106 for role in ('User',):
107     db.security.addPermissionToRole(role, 'Create', 'vcs_rev')
108     db.security.addPermissionToRole(role, 'View', 'vcs_repo')
110 # FileClass automatically gets this property in addition to the Class ones:
111 #   content = String()    [saved to disk in <tracker home>/db/files/]
112 #   type = String()       [MIME type of the content, default 'text/plain']
113 msg = FileClass(db, "msg",
114                 author=Link("user", do_journal='no'),
115                 recipients=Multilink("user", do_journal='no'),
116                 date=Date(),
117                 summary=String(),
118                 files=Multilink("file"),
119                 messageid=String(),
120                 inreplyto=String(),
121                 revision=Link("vcs_rev"))
123 # File
124 file = FileClass(db, "file",
125                 name=String(),
126                 description=String(indexme='yes'))
128 # Patch
129 patch = FileClass(db, "patch",
130                   name=String(),
131                   description=String(indexme='yes'),
132                   repository=String(),
133                   revision=String())
135 # Bug Type
136 bug_type = Class(db, 'bug_type',
137                  name=String(),
138                  description=String(),
139                  order=Number())
140 bug_type.setkey('name')
142 # IssueClass automatically gets these properties in addition to the Class ones:
143 #   title = String()
144 #   messages = Multilink("msg")
145 #   files = Multilink("file")
146 #   patches = Multilink("patches")
147 #   nosy = Multilink("user")
148 #   superseder = Multilink("issue")
149 bug = IssueClass(db, "bug",
150                  type=Link('bug_type'),
151                  components=Multilink('component'),
152                  versions=Multilink('version'),
153                  severity=Link('severity'),
154                  priority=Link('priority'),
155                  dependencies=Multilink('bug'),
156                  assignee=Link('user'),
157                  status=Link('status'),
158                  resolution=Link('resolution'),
159                  superseder=Link('bug'),
160                  keywords=Multilink('keyword'))
162 # Task Type
163 task_type = Class(db, 'task_type',
164                  name=String(),
165                  description=String(),
166                  order=Number())
167 task_type.setkey('name')
169 # IssueClass automatically gets these properties in addition to the Class ones:
170 #   title = String()
171 #   messages = Multilink("msg")
172 #   files = Multilink("file")
173 #   nosy = Multilink("user")
174 #   superseder = Multilink("issue")
175 task = IssueClass(db, "task",
176                   type=Link('task_type'),
177                   components=Multilink('component'),
178                   priority=Link('priority'),
179                   dependencies=Multilink('task'),
180                   assignee=Multilink('user'),
181                   status=Link('status'),
182                   resolution=Link('resolution'),
183                   solves=Link('bug'))
185 milestone = IssueClass(db, "milestone",
186                        bugs=Multilink("bug"),
187                        tasks=Multilink("task"),
188                        status=Link("status"),
189                        release_date=String())
192 # TRACKER SECURITY SETTINGS
194 # See the configuration and customisation document for information
195 # about security setup.
197 db.security.addRole(name='Developer', description='A developer')
198 db.security.addRole(name='Coordinator', description='A coordinator')
201 # REGULAR USERS
203 # Give the regular users access to the web and email interface
204 for r in 'User', 'Developer', 'Coordinator':
205     db.security.addPermissionToRole(r, 'Web Access')
206     db.security.addPermissionToRole(r, 'Email Access')
208 ##########################
209 # User permissions
210 ##########################
212 for cl in ('severity', 'component',
213            'version', 'priority', 'status', 'resolution',
214            'bug_type', 'bug', 'task_type', 'task', 'milestone',
215            'keyword', 'file', 'msg'):
216     db.security.addPermissionToRole('User', 'View', cl)
217     db.security.addPermissionToRole('Anonymous', 'View', cl)
218     db.security.addPermissionToRole('User', 'Create', cl)
219     
221 def may_edit_file(db, userid, itemid):
222     return userid == db.file.get(itemid, "creator")
224 p = db.security.addPermission(name='Edit', klass='file', check=may_edit_file,
225     description="User is allowed to remove their own files")
226 db.security.addPermissionToRole('User', p)
228 p = db.security.addPermission(name='Create', klass='bug',
229                               properties=('title', 'bug_type',
230                                           'components', 'versions',
231                                           'severity',
232                                           'messages', 'files', 'nosy'),
233                               description='User can report and discuss bugs')
234 db.security.addPermissionToRole('User', p)
236 p = db.security.addPermission(name='Edit', klass='bug',
237                               properties=('title', 'bug_type',
238                                           'components', 'versions',
239                                           'severity',
240                                           'messages', 'files', 'nosy'),
241                               description='User can report and discuss bugs')
242 db.security.addPermissionToRole('User', p)
244 p = db.security.addPermission(name='Create', klass='task',
245                               properties=('title', 'task_type',
246                                           'components',
247                                           'messages', 'files', 'nosy'),
248                               description='Developer can create and discuss tasks')
249 db.security.addPermissionToRole('Developer', p)
251 p = db.security.addPermission(name='Edit', klass='task',
252                               properties=('title', 'task_type',
253                                           'components',
254                                           'messages', 'files', 'nosy'),
255                               description='Developer can create and discuss tasks')
256 db.security.addPermissionToRole('Developer', p)
258 p = db.security.addPermission(name='Create', klass='milestone',
259                               description='Coordinator can create and discuss milestones')
260 db.security.addPermissionToRole('Coordinator', p)
262 p = db.security.addPermission(name='Edit', klass='milestone',
263                               description='Coordinator can create and discuss milestones')
264 db.security.addPermissionToRole('Coordinator', p)
267 ##########################
268 # Developer permissions
269 ##########################
270 for cl in ('bug_type', 'severity', 'component',
271            'version', 'priority', 'status', 'resolution',
272            'bug', 'file', 'msg', 'keyword'):
273     db.security.addPermissionToRole('Developer', 'View', cl)
275 for cl in ('bug', 'file', 'msg', 'keyword'):
276     db.security.addPermissionToRole('Developer', 'Edit', cl)
277     db.security.addPermissionToRole('Developer', 'Create', cl)
280 ##########################
281 # Coordinator permissions
282 ##########################
283 for cl in ('bug_type', 'task_type', 'severity', 'component',
284            'version', 'priority', 'status', 'resolution', 'bug', 'task', 'file', 'msg'):
285     db.security.addPermissionToRole('Coordinator', 'View', cl)
286     db.security.addPermissionToRole('Coordinator', 'Edit', cl)
287     db.security.addPermissionToRole('Coordinator', 'Create', cl)
289 # May users view other user information? Comment these lines out
290 # if you don't want them to
291 db.security.addPermissionToRole('User', 'View', 'user')
292 db.security.addPermissionToRole('Developer', 'View', 'user')
293 db.security.addPermissionToRole('Coordinator', 'View', 'user')
295 # Allow Coordinator to edit any user, including their roles.
296 db.security.addPermissionToRole('Coordinator', 'Edit', 'user')
297 db.security.addPermissionToRole('Coordinator', 'Web Roles')
299 # Users should be able to edit their own details -- this permission is
300 # limited to only the situation where the Viewed or Edited item is their own.
301 def own_record(db, userid, itemid):
302     '''Determine whether the userid matches the item being accessed.'''
303     return userid == itemid
304 p = db.security.addPermission(name='View', klass='user', check=own_record,
305     description="User is allowed to view their own user details")
306 for r in 'User', 'Developer', 'Coordinator':
307     db.security.addPermissionToRole(r, p)
308 p = db.security.addPermission(name='Edit', klass='user', check=own_record,
309     description="User is allowed to edit their own user details",
310     properties=('username', 'password',
311                 'address', 'realname',
312                 'phone', 'organization',
313                 'alternate_addresses',
314                 'queries',
315                 'timezone')) # Note: 'roles' excluded - users should not be able to edit their own roles. 
316 for r in 'User', 'Developer':
317     db.security.addPermissionToRole(r, p)
319 # Users should be able to edit and view their own queries. They should also
320 # be able to view any marked as not private. They should not be able to
321 # edit others' queries, even if they're not private
322 def view_query(db, userid, itemid):
323     private_for = db.query.get(itemid, 'private_for')
324     if not private_for: return True
325     return userid == private_for
326 def edit_query(db, userid, itemid):
327     return userid == db.query.get(itemid, 'creator')
328 p = db.security.addPermission(name='View', klass='query', check=view_query,
329     description="User is allowed to view their own and public queries")
330 p = db.security.addPermission(name='Search', klass='query')
331 db.security.addPermissionToRole('User', p)
332 for r in 'User', 'Developer', 'Coordinator':
333     db.security.addPermissionToRole(r, p)
334 p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
335     description="User is allowed to edit their queries")
336 for r in 'User', 'Developer', 'Coordinator':
337     db.security.addPermissionToRole(r, p)
338 p = db.security.addPermission(name='Create', klass='query',
339     description="User is allowed to create queries")
340 for r in 'User', 'Developer', 'Coordinator':
341     db.security.addPermissionToRole(r, p)
345 # ANONYMOUS USER PERMISSIONS
347 # Let anonymous users access the web interface. Note that almost all
348 # trackers will need this Permission. The only situation where it's not
349 # required is in a tracker that uses an HTTP Basic Authenticated front-end.
350 db.security.addPermissionToRole('Anonymous', 'Web Access')
352 # Let anonymous users access the email interface (note that this implies
353 # that they will be registered automatically, hence they will need the
354 # "Create" user Permission below)
355 # This is disabled by default to stop spam from auto-registering users on
356 # public trackers.
357 #db.security.addPermissionToRole('Anonymous', 'Email Access')
359 # Assign the appropriate permissions to the anonymous user's Anonymous
360 # Role. Choices here are:
361 # - Allow anonymous users to register
362 db.security.addPermissionToRole('Anonymous', 'Create', 'user')
364 # Allow anonymous users access to view issues (and the related, linked
365 # information).
367 for cl in 'bug', 'task', 'milestone', 'severity', 'status', 'resolution', 'msg', 'file':
368     db.security.addPermissionToRole('Anonymous', 'View', cl)
370 # [OPTIONAL]
371 # Allow anonymous users access to create or edit "issue" items (and the
372 # related file and message items)
373 #for cl in 'issue', 'file', 'msg':
374 #   db.security.addPermissionToRole('Anonymous', 'Create', cl)
375 #   db.security.addPermissionToRole('Anonymous', 'Edit', cl)
378 # vim: set filetype=python sts=4 sw=4 et si :