import logging import cherrypy import turbogears from turbogears import controllers, expose, validate, redirect, identity from libbe.bugdir import tree_root, NoRootEntry from config import projects from prest import PrestHandler, provide_action from beweb import json log = logging.getLogger("beweb.controllers") def project_tree(project): try: return tree_root(projects[project][1]) except KeyError: raise Exception("Unknown project %s" % project) def comment_url(project, bug, comment, **kwargs): return turbogears.url("/project/%s/bug/%s/comment/%s" % (project, bug, comment), kwargs) class Comment(PrestHandler): @identity.require( identity.has_permission("editbugs")) @provide_action("action", "New comment") def new_comment(self, comment_data, comment, *args, **kwargs): bug_tree = project_tree(comment_data['project']) bug = bug_tree.get_bug(comment_data['bug']) comment = new_comment(bug, "") comment.From = identity.current.user.userId comment.content_type = "text/restructured" comment.save() raise cherrypy.HTTPRedirect(comment_url(comment=comment.uuid, **comment_data)) @identity.require( identity.has_permission("editbugs")) @provide_action("action", "Reply") def reply_comment(self, comment_data, comment, *args, **kwargs): bug_tree = project_tree(comment_data['project']) bug = bug_tree.get_bug(comment_data['bug']) reply_comment = new_comment(bug, "") reply_comment.From = identity.current.user.userId reply_comment.in_reply_to = comment.uuid reply_comment.save() reply_data = dict(comment_data) del reply_data["comment"] raise cherrypy.HTTPRedirect(comment_url(comment=reply_comment.uuid, **reply_data)) @identity.require( identity.has_permission("editbugs")) @provide_action("action", "Update") def update(self, comment_data, comment, comment_body, *args, **kwargs): comment.body = comment_body comment.save() raise cherrypy.HTTPRedirect(bug_url(comment_data['project'], comment_data['bug'])) def instantiate(self, project, bug, comment): bug_tree = project_tree(project) bug = bug_tree.get_bug(bug) return bug.get_comment(comment) def dispatch(self, comment_data, comment, *args, **kwargs): return self.edit_comment(comment_data['project'], comment) @turbogears.expose(html="beweb.templates.edit_comment") def edit_comment(self, project, comment): return {"comment": comment, "project_id": project} class Bug(PrestHandler): comment = Comment() @turbogears.expose(html="beweb.templates.edit_bug") def index(self, project, bug): return {"bug": bug, "project_id": project} def dispatch(self, bug_data, bug, *args, **kwargs): if bug is None: return self.list(bug_data['project'], **kwargs) else: return self.index(bug_data['project'], bug) @turbogears.expose(html="beweb.templates.bugs") def list(self, project, sort_by=None, show_closed=False, action=None, search=None): if action == "New bug": self.new_bug() if show_closed == "False": show_closed = False bug_tree = project_tree(project) bugs = list(bug_tree.list()) if sort_by is None: bugs.sort() return {"project_id" : project, "project_name" : projects[project][0], "bugs" : bugs, "show_closed" : show_closed, "search" : search, } @identity.require( identity.has_permission("editbugs")) @provide_action("action", "New bug") def new_bug(self, bug_data, bug, **kwargs): bug = project_tree(bug_data['project']).new_bug() bug.creator = identity.current.user.userId bug.save() raise cherrypy.HTTPRedirect(bug_url(bug_data['project'], bug.uuid)) @identity.require( identity.has_permission("editbugs")) @provide_action("action", "Update") def update(self, bug_data, bug, status, severity, summary, assigned, action): bug.status = status bug.severity = severity bug.summary = summary if assigned == "": assigned = None bug.assigned = assigned bug.save() # bug.vcs.precommit(bug.path) # bug.vcs.commit(bug.path, "Auto-commit") # bug.vcs.postcommit(bug.path) raise cherrypy.HTTPRedirect(bug_list_url(bug_data["project"])) def instantiate(self, project, bug): return project_tree(project).get_bug(bug) @provide_action("action", "New comment") def new_comment(self, bug_data, bug, *args, **kwargs): try: self.update(bug_data, bug, *args, **kwargs) except cherrypy.HTTPRedirect: pass return self.comment.new_comment(bug_data, comment=None, *args, **kwargs) def project_url(project_id=None): project_url = "/project/" if project_id is not None: project_url += "%s/" % project_id return turbogears.url(project_url) def bug_url(project_id, bug_uuid=None): bug_url = "/project/%s/bug/" % project_id if bug_uuid is not None: bug_url += "%s/" % bug_uuid return turbogears.url(bug_url) def bug_list_url(project_id, show_closed=False, search=None): bug_url = "/project/%s/bug/?show_closed=%s" % (project_id, str(show_closed)) if search is not None: bug_url = "%s&search=%s" % (bug_url, search) return turbogears.url(str(bug_url)) class Project(PrestHandler): bug = Bug() @turbogears.expose(html="beweb.templates.projects") def dispatch(self, project_data, project, *args, **kwargs): if project is not None: raise cherrypy.HTTPRedirect(bug_url(project)) else: return {"projects": projects} def instantiate(self, project): return project class Root(controllers.Root): prest = PrestHandler() prest.project = Project() @turbogears.expose() def index(self): raise cherrypy.HTTPRedirect(project_url()) @expose(template="beweb.templates.login") def login(self, forward_url=None, previous_url=None, *args, **kw): if not identity.current.anonymous and identity.was_login_attempted(): raise redirect(forward_url) forward_url=None previous_url= cherrypy.request.path if identity.was_login_attempted(): msg=_("The credentials you supplied were not correct or "\ "did not grant access to this resource.") elif identity.get_identity_errors(): msg=_("You must provide your credentials before accessing "\ "this resource.") else: msg=_("Please log in.") forward_url= cherrypy.request.headers.get("Referer", "/") cherrypy.response.status=403 return dict(message=msg, previous_url=previous_url, logging_in=True, original_parameters=cherrypy.request.params, forward_url=forward_url) @expose() def logout(self): identity.current.logout() raise redirect("/") @turbogears.expose('beweb.templates.about') def about(self, *paths, **kwargs): return {} @turbogears.expose() def default(self, *args, **kwargs): return self.prest.default(*args, **kwargs) def _cp_on_error(self): import traceback, StringIO bodyFile = StringIO.StringIO() traceback.print_exc(file = bodyFile) trace_text = bodyFile.getvalue() try: raise except cherrypy.NotFound: self.handle_error('Not Found', str(e), trace_text, '404 Not Found') except NoRootEntry, e: self.handle_error('Project Misconfiguration', str(e), trace_text) except Exception, e: self.handle_error('Internal server error', str(e), trace_text) def handle_error(self, heading, body, traceback=None, status='500 Internal Server Error'): cherrypy.response.headerMap['Status'] = status cherrypy.response.body = [self.errorpage(heading, body, traceback)] @turbogears.expose(html='beweb.templates.error') def errorpage(self, heading, body, traceback): return {'heading': heading, 'body': body, 'traceback': traceback}