Merged with head branch
[be.git] / interfaces / web / Bugs-Everywhere-Web / beweb / controllers.py
1 import logging
2
3 import cherrypy
4 import turbogears
5 from turbogears import controllers, expose, validate, redirect, identity
6
7 from libbe.bugdir import tree_root, NoRootEntry
8 from config import projects
9 from prest import PrestHandler, provide_action
10
11
12 from beweb import json
13
14 log = logging.getLogger("beweb.controllers")
15
16 def project_tree(project):
17     try:
18         return tree_root(projects[project][1])
19     except KeyError:
20         raise Exception("Unknown project %s" % project)
21
22 def comment_url(project, bug, comment, **kwargs):
23     return turbogears.url("/project/%s/bug/%s/comment/%s" %
24                           (project, bug, comment), kwargs)
25
26 class Comment(PrestHandler):
27     @identity.require( identity.has_permission("editbugs"))
28     @provide_action("action", "New comment")
29     def new_comment(self, comment_data, comment, *args, **kwargs):
30         bug_tree = project_tree(comment_data['project'])
31         bug = bug_tree.get_bug(comment_data['bug'])
32         comment = new_comment(bug, "")
33         comment.From = identity.current.user.userId
34         comment.content_type = "text/restructured"
35         comment.save()
36         raise cherrypy.HTTPRedirect(comment_url(comment=comment.uuid, 
37                                     **comment_data))
38
39     @identity.require( identity.has_permission("editbugs"))
40     @provide_action("action", "Reply")
41     def reply_comment(self, comment_data, comment, *args, **kwargs):
42         bug_tree = project_tree(comment_data['project'])
43         bug = bug_tree.get_bug(comment_data['bug'])
44         reply_comment = new_comment(bug, "")
45         reply_comment.From = identity.current.user.userId
46         reply_comment.in_reply_to = comment.uuid
47         reply_comment.save()
48         reply_data = dict(comment_data)
49         del reply_data["comment"]
50         raise cherrypy.HTTPRedirect(comment_url(comment=reply_comment.uuid, 
51                                     **reply_data))
52
53     @identity.require( identity.has_permission("editbugs"))
54     @provide_action("action", "Update")
55     def update(self, comment_data, comment, comment_body, *args, **kwargs):
56         comment.body = comment_body
57         comment.save()
58         raise cherrypy.HTTPRedirect(bug_url(comment_data['project'], 
59                                             comment_data['bug']))
60
61     def instantiate(self, project, bug, comment):
62         bug_tree = project_tree(project)
63         bug = bug_tree.get_bug(bug)
64         return bug.get_comment(comment)
65
66     def dispatch(self, comment_data, comment, *args, **kwargs):
67         return self.edit_comment(comment_data['project'], comment)
68
69     @turbogears.expose(html="beweb.templates.edit_comment")
70     def edit_comment(self, project, comment):
71         return {"comment": comment, "project_id": project}
72
73 class Bug(PrestHandler):
74     comment = Comment()
75     @turbogears.expose(html="beweb.templates.edit_bug")
76     def index(self, project, bug):
77         return {"bug": bug, "project_id": project}
78     
79     def dispatch(self, bug_data, bug, *args, **kwargs):
80         if bug is None:
81             return self.list(bug_data['project'], **kwargs)
82         else:
83             return self.index(bug_data['project'], bug)
84
85     @turbogears.expose(html="beweb.templates.bugs")
86     def list(self, project, sort_by=None, show_closed=False, action=None, 
87              search=None):
88         if action == "New bug":
89             self.new_bug()
90         if show_closed == "False":
91             show_closed = False
92         bug_tree = project_tree(project)
93         bugs = list(bug_tree.list())
94         if sort_by is None:
95             bugs.sort()
96         return {"project_id"      : project,
97                 "project_name"    : projects[project][0],
98                 "bugs"            : bugs,
99                 "show_closed"     : show_closed,
100                 "search"          : search,
101                }
102
103     @identity.require( identity.has_permission("editbugs"))
104     @provide_action("action", "New bug")
105     def new_bug(self, bug_data, bug, **kwargs):
106         bug = project_tree(bug_data['project']).new_bug()
107         bug.creator = identity.current.user.userId
108         bug.save()
109         raise cherrypy.HTTPRedirect(bug_url(bug_data['project'], bug.uuid))
110
111     @identity.require( identity.has_permission("editbugs"))
112     @provide_action("action", "Update")
113     def update(self, bug_data, bug, status, severity, summary, assigned, 
114                action):
115         bug.status = status
116         bug.severity = severity
117         bug.summary = summary
118         if assigned == "":
119             assigned = None
120         bug.assigned = assigned
121         bug.save()
122 #        bug.rcs.precommit(bug.path)
123 #        bug.rcs.commit(bug.path, "Auto-commit")
124 #        bug.rcs.postcommit(bug.path)
125         raise cherrypy.HTTPRedirect(bug_list_url(bug_data["project"]))
126
127     def instantiate(self, project, bug):
128         return project_tree(project).get_bug(bug)
129
130     @provide_action("action", "New comment")
131     def new_comment(self, bug_data, bug, *args, **kwargs):
132         try:
133             self.update(bug_data, bug, *args, **kwargs)
134         except cherrypy.HTTPRedirect:
135             pass
136         return self.comment.new_comment(bug_data, comment=None, *args, 
137                                          **kwargs)
138
139
140 def project_url(project_id=None):
141     project_url = "/project/"
142     if project_id is not None:
143         project_url += "%s/" % project_id
144     return turbogears.url(project_url)
145
146 def bug_url(project_id, bug_uuid=None):
147     bug_url = "/project/%s/bug/" % project_id
148     if bug_uuid is not None:
149         bug_url += "%s/" % bug_uuid
150     return turbogears.url(bug_url)
151
152 def bug_list_url(project_id, show_closed=False, search=None):
153     bug_url = "/project/%s/bug/?show_closed=%s" % (project_id, 
154                                                    str(show_closed))
155     if search is not None:
156         bug_url = "%s&search=%s" % (bug_url, search)
157     return turbogears.url(str(bug_url))
158
159
160 class Project(PrestHandler):
161     bug = Bug()
162     @turbogears.expose(html="beweb.templates.projects")
163     def dispatch(self, project_data, project, *args, **kwargs):
164         if project is not None:
165             raise cherrypy.HTTPRedirect(bug_url(project)) 
166         else:
167             return {"projects": projects}
168
169     def instantiate(self, project):
170         return project
171
172
173 class Root(controllers.Root):
174     prest = PrestHandler()
175     prest.project = Project()
176     @turbogears.expose()
177     def index(self):
178         raise cherrypy.HTTPRedirect(project_url()) 
179
180     @expose(template="beweb.templates.login")
181     def login(self, forward_url=None, previous_url=None, *args, **kw):
182
183         if not identity.current.anonymous and identity.was_login_attempted():
184             raise redirect(forward_url)
185
186         forward_url=None
187         previous_url= cherrypy.request.path
188
189         if identity.was_login_attempted():
190             msg=_("The credentials you supplied were not correct or "\
191                    "did not grant access to this resource.")
192         elif identity.get_identity_errors():
193             msg=_("You must provide your credentials before accessing "\
194                    "this resource.")
195         else:
196             msg=_("Please log in.")
197             forward_url= cherrypy.request.headers.get("Referer", "/")
198         cherrypy.response.status=403
199         return dict(message=msg, previous_url=previous_url, logging_in=True,
200                     original_parameters=cherrypy.request.params,
201                     forward_url=forward_url)
202
203     @expose()
204     def logout(self):
205         identity.current.logout()
206         raise redirect("/")
207
208     @turbogears.expose('beweb.templates.about')
209     def about(self, *paths, **kwargs):
210         return {}
211
212     @turbogears.expose()
213     def default(self, *args, **kwargs):
214         return self.prest.default(*args, **kwargs)
215
216     def _cp_on_error(self):
217         import traceback, StringIO
218         bodyFile = StringIO.StringIO()
219         traceback.print_exc(file = bodyFile)
220         trace_text = bodyFile.getvalue()
221         try:
222             raise
223         except cherrypy.NotFound:
224             self.handle_error('Not Found', str(e), trace_text, '404 Not Found')
225
226         except NoRootEntry, e:
227             self.handle_error('Project Misconfiguration', str(e), trace_text)
228
229         except Exception, e:
230             self.handle_error('Internal server error', str(e), trace_text)
231
232     def handle_error(self, heading, body, traceback=None, 
233                      status='500 Internal Server Error'):
234         cherrypy.response.headerMap['Status'] = status 
235         cherrypy.response.body = [self.errorpage(heading, body, traceback)]
236         
237
238     @turbogears.expose(html='beweb.templates.error')
239     def errorpage(self, heading, body, traceback):
240         return {'heading': heading, 'body': body, 'traceback': traceback}