def adminReplPost(handler, p_code): def makeStr(v): if isinstance(v, list): return "<ul>%s</ul>" % ''.join("<li>%s</li>" % item for item in v) return str(v) handler.wrappers = False p_code = re.sub('^!([A-Za-z]+)$', 'from \\1 import \\1', p_code) match = re.match('!([A-Za-z ]+)$', p_code) if match: parts = match.group(1).split(' ') res = [] for part in parts: w = ResponseWriter() adminReplPost(handler, "!%s" % part) res.append(fromJS(w.done())) print toJS(res) done() if 'admin-repl' not in handler.session: print toJS({'code': highlightCode(p_code), 'stdout': '', 'stderr': ['Session Expired', 'REPL session no longer exists'], 'vars': {}}) done() writer = ResponseWriter() try: Event.repl(handler, p_code) exec compile(p_code, '<admin repl>', 'single') in handler.session['admin-repl'] stderr = '' except: stderr = map(str, [sys.exc_info()[0].__name__, sys.exc_info()[1]]) stdout = writer.done() vars = sorted([(k, pformat(v), makeStr(v)) for (k, v) in handler.session['admin-repl'].items() if k != '__builtins__'], lambda (k1, v1, vs1), (k2, v2, vs2): cmp(k1, k2)) print toJS({'code': highlightCode(p_code), 'stdout': stdout, 'stderr': stderr, 'vars': vars})
def __str__(self): writer = ResponseWriter() try: self.out() finally: rtn = writer.done() return rtn
def entry(rev, oldRev, describeTask, icon, color, text): useRev = oldRev or rev print "<div class=\"revision-entry\" style=\"border-color: %s\" assigned=\"%s\">" % (color, ' '.join(user.username for user in rev.assigned)) print "<div class=\"type\"><img class=\"bullet\" src=\"/static/images/%s\"> %s</div>" % (icon, text) print "<div class=\"timestamp\">%s by %s</div>" % (tsToDate(rev.timestamp).strftime('%H:%M:%S'), userStr(rev)) print "<div class=\"body\">" if describeTask: print "<a href=\"/tasks/%d\">%s</a>, assigned to %s<br>" % (rev.id, useRev.safe.name, ', '.join(userStr(useRev, user) for user in sorted(useRev.assigned))) w = ResponseWriter() yield text = w.done().strip() # Show hours change if oldRev: hoursDiff = rev.hours - oldRev.hours if hoursDiff != 0: # Skip it if we moved to an end state and zeroed the hours if oldRev.status == rev.status or rev.status not in ('canceled', 'complete', 'deferred', 'split') or rev.hours != 0: if text != '': text += '. ' text += "Hours %s by <span class=\"hours-%s\">%d</span> to %d" % ('increased' if hoursDiff > 0 else 'decreased', 'up' if hoursDiff > 0 else 'down', abs(hoursDiff), rev.hours) print text print "</div>" print "</div>"
def adminInfo(handler): handler.title('Information') requirePriv(handler, 'Admin') print "<div class=\"info\">" print "<h3>Uptime</h3>" loadTime = getLoadtime() print "Started %s<br>" % loadTime print "Up for %s<br>" % timesince(loadTime) print "Total requests: %d<br>" % server().getTotalRequests() print "<form method=\"post\" action=\"/admin/restart\">" print Button('Restart', type = 'submit').negative() print "</form>" print "<h3>Threads</h3>" print "<table border=\"1\" cellspacing=\"0\" cellpadding=\"4\">" print "<tr><th>ID</th><th class=\"main\">Name</th><th>Alive</th><th>Daemon</th></tr>" for thread in sorted(threads(), key = lambda thread: thread.name): print "<tr><td>%s</td><td>" % ('None' if thread.ident is None else "%x" % abs(thread.ident)) print thread.name print "<br>" try: print CollapsibleBox('Traceback', formatTrace(traceback.extract_stack(sys._current_frames()[thread.ident]))) except Exception: pass print "</td><td class=\"%s\"> </td><td class=\"%s\"> </td></tr>" % ('yes' if thread.isAlive() else 'no', 'yes' if thread.daemon else 'no') print "</table>" print "<h3>Locks</h3>" print "<table border=\"1\" cellspacing=\"0\" cellpadding=\"4\">" print "<tr><th class=\"main\">Name</th><th>Available</th><th>Reentrant</th></tr>" for (name, lock) in sorted(locks.iteritems()): print "<tr><td>" print name avail = lock.avail() if not avail: print "<br>" writer = ResponseWriter() try: owner, tb = lock.owner, lock.tb name = ("%x" % abs(owner)) if owner else 'None' #TODO Is there no O(1) way to do this? for thread in threads(): if thread.ident == owner: name = "%s (%x)" % (thread.name, abs(owner)) break print "Owned by: <b>%s</b><br><br>" % name if tb: print "Acquisition traceback:<br>" print formatTrace(tb) print "<br>" print "Current traceback:<br>" print formatTrace(traceback.extract_stack(sys._current_frames()[owner])) except Exception, e: writer.clear() print "<i>(Unable to retrieve stack trace)</i>" print CollapsibleBox('Ownership', writer.done()) print "</td><td class=\"%s\">%s</td><td class=\"%s\"> </td></tr>" % ('yes' if avail else 'no', ' ' if avail else (lock.owner or '???'), 'yes' if lock.reentrant() else 'no')
def run(self): writer = ResponseWriter() lock = server().block_requests() try: self.fn() self.log = writer.done() except Exception, e: writer.done() self.log = "<div style=\"font-weight: bold; color: #f00\">%s</div>" % stripTags(str(e))
def __str__(self): w = ResponseWriter() print "<table class=\"list\">" if self.headers: print "<tr><th class=\"left\">%s</th><th class=\"right\">%s</th></tr>" % self.headers for element in self.elements: print "<tr><td class=\"left\">%s</td><td class=\"right\">%s</td></tr>" % element print "</table>" return w.done()
def getLogString(self): writer = ResponseWriter() print "default sprint tab: %s" % self.defaultSprintTab print "default tasks tab: %s" % self.defaultTasksTab print "backlog styles:" for k, v in self.backlogStyles.iteritems(): print " %s: %s" % (k, v) print "messages:" for k, v in self.messages.iteritems(): print " %s: %s" % (k, v) return writer.done()
def __str__(self): w = ResponseWriter() if self.label: print "%s " % self.label print "<div class=\"task-progress-total\" style=\"position: relative; top: 5px\">" if self.pcnt > 0: print "<div class=\"progress-current%s\" style=\"width: %d%%;\">" % (" %s" % self.cls, min(self.pcnt, 100)) print "<span class=\"progress-percentage\">%d/%d hours (%s%%)</span>" % (self.amt, self.total, '∞' if self.pcnt == inf else "%d" % self.pcnt) if self.pcnt > 0: print "</div>" print "</div>" return w.done().replace("\n", "")
def prefs(handler): handler.title('Preferences') requirePriv(handler, 'User') prefs = handler.session['user'].getPrefs() print "<script src=\"/static/prefs.js\" type=\"text/javascript\"></script>" print InfoBox('', id = 'post-status', close = True) print "<form method=\"post\" action=\"/prefs\">" print InfoBox("Note", "Your password and avatar are controlled from <a href=\"/users/%s\">your profile</a>" % handler.session['user'].username) print "<a name=\"default-sprint-tab\"></a>" print "<h3>Default Sprint Tab</h3>" print "Which tab you're taken to when following links in the project list:<br><br>" print "<select name=\"default_sprint_tab\">" for tab in sprintTabs().group('').values(): print "<option value=\"%s\"%s>%s</option>" % (tab.name, ' selected' if tab.name == prefs.defaultSprintTab else '', tab.getDisplayName()) print "</select>" print "<a name=\"default-tasks-tab\"></a>" print "<h3>Default Tasks Tab</h3>" print "Which tab you're taken to when adding a new backlog task:<br><br>" print "<select name=\"default_tasks_tab\">" for tab in taskTabs.group('').values(): print "<option value=\"%s\"%s>%s</option>" % (tab.name, ' selected' if tab.name == prefs.defaultTasksTab else '', tab.getDisplayName()) print "</select>" print "<h3>Backlog Style</h3>" print "How each task on the backlog is styled, based on status:<br><br>" select = ResponseWriter() print "<select name=\"backlog_style[%s]\">" for name in backlogStyles: print "<option value=\"%s\">%s</option>" % (name, name.title()) print "</select>" select = select.done() tbl = LRTable() for statusBlock in statusMenu: for name in statusBlock: val = prefs.backlogStyles[name] tbl[statuses[name].text] = (select % name).replace("<option value=\"%s\">" % val, "<option value=\"%s\" selected>" % val) print tbl print "<h3>Messages</h3>" print "Which events will automatically notify you via system message:<br><br>" for name, desc in messageTypes: print "<input type=\"checkbox\" name=\"messages[%s]\" id=\"messages[%s]\"%s><label for=\"messages[%s]\">%s</label><br>" % (name, name, ' checked' if prefs.messages[name] else '', name, desc) print "<br>" print Button('Save', id = 'save-button', type = 'button').positive() print "</form>"
def __str__(self): w = ResponseWriter() try: print "<table%s>" % {True: "", False: " class=\"%s\"" % self.cls}[self.cls == None] widths = Table.extend(self.widths, self.cols, None) if self.headers: print "<tr>" + ''.join(["<th>%s</th>" % x for x in Table.extend(self.headers, self.cols, ' ')]) + "</tr>" for i in range(len(self.elements)): ext = Table.extend(self.elements[i], self.cols, ' ') print "<tr>" + ''.join(["<td%s>%s</td>" % (" style=\"width: %s\"" % widths[i] if widths[i] else "", ext[i]) for i in range(self.cols)]) + "</tr>" print "</table>" return w.done() except: w.done() raise
def requestDone(self): if self.wrappers: types = ["less", "css", "js"] includes = {type: [] for type in types} handler = getattr(self, "handler", None) if handler and "statics" in handler: for key in ensureIter(handler["statics"]): for type in types: if isfile("static/%s.%s" % (key, type)): includes[type].append("/static/%s.%s" % (key, type)) writer = ResponseWriter() header(self, includes) sys.stdout.write(self.response) footer(self) self.response = writer.done()
def __str__(self): writer = ResponseWriter() print "<div class=\"box blue rounded login\">" print "<div class=\"title\">Login</div>" print "<span class=\"boxBody\">" print "<form method=\"post\" action=\"/login\">" print "<input type=\"hidden\" name=\"redir\" value=\"%s\">" % (self.redir or '/{{path}}?{{get-args}}') print "<table style=\"margin-left: 30px;\" class=\"list\">" print "<tr><td class=\"left\">Username:</td><td class=\"right\"><input type=\"text\" name=\"username\" class=\"username defaultfocus\"></td></tr>" print "<tr><td class=\"left\">Password:</td><td class=\"right\"><input type=\"password\" name=\"password\" class=\"password\"> <a class=\"resetpw\" href=\"/resetpw/:mail\">(Forgot password)</a></td></tr>" print "<tr><td class=\"left\">Verification Code:</td><td class=\"right\"><input type=\"text\" name=\"verification\" class=\"code\" maxlength=\"6\" size=\"6\"><br><small>(This is only necessary if you've enabled two-factor authentication)</small></td></tr>" print "<tr><td class=\"left\"> </td><td class=\"right\"><button type=\"submit\">Login</button></td></tr>" print "</table>" print "</form>" print "</span>" print "</div>" return writer.done()
def requestDone(self): if isinstance(self.log, LogEntry): self.log.save() if self.wrappers: types = ['less', 'css', 'js'] includes = {type: [] for type in types} handler = getattr(self, 'handler', None) if handler and 'statics' in handler: for key in ensureList(handler['statics']): for type in types: if isfile("static/%s.%s" % (key, type)): includes[type].append("/static/%s.%s" % (key, type)) writer = ResponseWriter() header(self, includes) print self.response footer(self) self.response = writer.done()
def run(handler, p_command, p_path, p_mode = ''): handler.wrappers = False if not handler.session['user']: print toJS({'error': 'You must be logged in to use the shell'}) return # This is already checked in the "su" command, but could be spoofed by the user if p_mode == 'admin' and not (handler.session['user'].hasPrivilege('Admin') or ('impersonator' in handler.session and handler.session['impersonator'].hasPrivilege('Admin'))): print toJS({'error': "You need the Admin privilege"}) return if 'shell' not in handler.session: # Shell context handler.session['shell'] = {} handler.session['shell']['handler'] = handler; handler.session['shell']['path'] = p_path handler.session['shell']['mode'] = p_mode parts = split(p_command) testCommands = filterCommands(parts, p_mode) if len(testCommands) == 0: print toJS({'error': 'Unrecognized command'}) elif len(testCommands) > 1: print toJS({'error': 'Ambiguous command'}) else: syntax, fn, doc = testCommands[0] args = [y for (x, y) in zip(syntax, parts) if x == '_'] w = ResponseWriter() mode = None rtn = {} try: mode = fn(handler.session['shell'], *args) except CommandError, e: w.done() print toJS({'error': str(e)}) return except Redirect, e: rtn['redirect'] = e.target
def __str__(self): w = ResponseWriter() try: print "<div class=\"tabs-container\">" print "<ul class=\"nav nav-tabs\">" for tab in self.tabs.group('').values(): if self.tabs.group(tab.name): tab.outGroup(self.fmt, self.whr, self.tabs.group(tab.name)) else: tab.out(self.fmt, self.whr == tab) # The current tab isn't in the list if self.whr is not None and (self.whr.base, self.whr.name) not in self.tabs: self.whr.out(self.fmt, True) print "</ul>" print "<div class=\"clear\"></div>" if self.tabs.afterContent: print "<div class=\"after-content\">%s</div>" % self.tabs.afterContent print "</div>" return w.done() except: w.done() raise
def requestDone(self): if self.wrappers: types = ['less', 'css', 'js'] includes = {type: [] for type in types} handler = getattr(self, 'handler', None) if handler and 'statics' in handler: for key in ensureList(handler['statics']): for type in types: if isfile(f"static/{key}.{type}"): includes[type].append(f"/static/{key}.{type}") if handler and 'view' in handler: includes['js'].append(f"/views/{handler['view']}.js") includes['less'].append(f"/views/{handler['view']}.less") with ResponseWriter(storageType = bytes) as writer: view = getattr(self, 'view', None) data = self.preprocessViewData(getattr(self, 'viewData', {})) header(self, includes, view) sys.stdout.write(self.response) footer(self, data, view) self.response = writer.done()
def showBacklog(handler, id, search = None, devEdit = False): requirePriv(handler, 'User') id = int(id) sprint = Sprint.load(id) if not sprint or sprint.isHidden(handler.session['user']): ErrorBox.die('Sprints', "No sprint with ID <b>%d</b>" % id) elif not sprint.canView(handler.session['user']): ErrorBox.die('Private', "You must be a sprint member to view this sprint") # Redirect to search help page if searched for empty string if search == '': redirect('/help/search') handler.title(sprint.safe.name) drawNavArrows(sprint, handler.session['user'], '') tasks = sprint.getTasks() editable = sprint.canEdit(handler.session['user']) or (devEdit and isDevMode(handler)) search = Search(sprint, search) print "<script src=\"/settings/sprints.js\" type=\"text/javascript\"></script>" print "<script type=\"text/javascript\">" print "var sprintid = %d;" % id print "var currentUser = %s;" % toJS(handler.session['user'].username if handler.session['user'] else None) print "var totalTasks = %d;" % len(tasks) # True is a placeholder for the dynamic tokens (status, assigned) print "var searchTokens = %s;" % toJS(filter(None, [search.getBaseString() if search.hasBaseString() else None] + [True] + ["%s:%s" % (filt.getKey(), filt.value) for filt in search.getAll() if filt.getKey() not in ('status', 'assigned')])) print "var searchDescriptions = %s;" % toJS(filter(None, ["matching %s" % search.getBaseString() if search.hasBaseString() else None] + [True] + [filt.description() for filt in search.getAll()])) print "TaskTable.init({link_hours_status: %s});" % toJS(not sprint.isPlanning()) print "$('document').ready(function() {" if search.has('assigned'): print " $('%s').addClass('selected');" % ', '.join("#filter-assigned a[assigned=\"%s\"]" % user.username for user in search.get('assigned').users + ([handler.session['user']] if search.get('assigned').currentUser else [])) if search.has('status'): print " $('%s').addClass('selected');" % ', '.join("#filter-status a[status=\"%s\"]" % status.name for status in search.get('status').statuses) print " apply_filters();" print "});" print "</script>" print "<div id=\"selected-task-box\">" print "<span></span>" print Button('history', id = 'selected-history').positive() print Button('highlight', id = 'selected-highlight').positive() print Button('mass edit', id = 'selected-edit').positive() print Button('cancel', id = 'selected-cancel') #.negative() print "</div>" print "<div class=\"backlog-tabs\">" print tabs(sprint, 'backlog') print "<input type=\"text\" id=\"search\" value=\"%s\">" % search.getFullString().replace('"', '"') print "</div>" undelay(handler) print InfoBox('Loading...', id = 'post-status', close = True) avail = Availability(sprint) if sprint.isActive() else None dayStart = Weekday.today().date() print "<div id=\"filter-assigned\">" print "<a class=\"fancy danger\" href=\"#\"><img src=\"/static/images/cross.png\"> None</a>" for member in sorted(sprint.members): cls = ['fancy'] if not sprint.isPlanning() and avail and avail.get(member, dayStart) == 0: cls.append('away') print "<a class=\"%s\" assigned=\"%s\" href=\"/sprints/%d?search=assigned:%s\"><img src=\"%s\"> %s</a>" % (' '.join(cls), member.username, id, member.username, member.getAvatar(16), member.username) print "</div><br>" print "<div id=\"filter-status\">" print "<a class=\"fancy danger\" href=\"#\"><img src=\"/static/images/cross.png\"> None</a>" for status in sorted(statuses.values()): print "<a class=\"fancy\" status=\"%s\" href=\"/sprints/%d?search=status:%s\"><img src=\"%s\">%s</a>" % (status.name, id, status.name.replace(' ', '-'), status.getIcon(), status.text) print "</div><br>" if handler.session['user'].hasPrivilege('Admin') and 'deleted' in sprint.flags: print "<form method=\"post\" action=\"/admin/projects/%d/cancel-deletion/%d\">" % (sprint.project.id, sprint.id) print WarningBox("This sprint is flagged for deletion during nightly cleanup. %s" % Button('Cancel').mini().post()) print "</form>" if sprint.isPlanning(): if sprint.isActive(): print InfoBox("Today is <b>sprint planning</b> — tasks aren't finalized until the end of the day") else: daysTillPlanning = (tsToDate(sprint.start) - getNow()).days + 1 print InfoBox("The sprint has <b>not begun</b> — planning is %s. All changes are considered to have been made midnight of plan day" % ('tomorrow' if daysTillPlanning == 1 else "in %d days" % daysTillPlanning)) elif sprint.isReview(): print InfoBox("Today is <b>sprint review</b> — this is the last day to make changes to the backlog. All open tasks will be deferred at the end of the day") elif not sprint.isOver(): noHours = filter(lambda task: task.stillOpen() and task.hours == 0, tasks) if noHours != []: print WarningBox("There are <a href=\"/sprints/%d?search=status:not-started,in-progress,blocked hours:0\">open tasks with no hour estimate</a>" % sprint.id) tasks = search.filter(tasks) if isDevMode(handler): print Button('#all-tasks borders', "javascript:$('#all-tasks, #all-tasks tr td').css('border', '1px solid #f00').css('border-collapse', 'collapse');").negative() if not editable: print Button('make editable', "/sprints/%d?devEdit" % id).negative() elif devEdit: print Button('make uneditable', "/sprints/%d" % id).negative() print "<div class=\"debugtext\">" print "start: %d (%s)<br>" % (sprint.start, tsToDate(sprint.start)) print "end: %d (%s)<br>" % (sprint.end, tsToDate(sprint.end)) print "</div>" showing = ResponseWriter() print "<span id=\"task-count\"></span>" # save-search href set by update_task_count() print "<a class=\"save-search\"><img src=\"/static/images/save.png\" title=\"Save search\"></a>" print "<a class=\"cancel-search\" href=\"/sprints/%d\"><img src=\"/static/images/cross.png\" title=\"Clear search\"></a>" % id showing = showing.done() print TaskTable(sprint, editable = editable, tasks = tasks, tableID = 'all-tasks', dateline = showing, taskClasses = {task: ['highlight'] for task in (search.get('highlight').tasks if search.has('highlight') else [])}, debug = isDevMode(handler), groupActions = True, taskModActions = True, index = True, goal = True, status = True, name = True, assigned = True, historicalHours = True, hours = True, devEdit = devEdit)
def newTaskMany(handler, group, assigned=None): handler.title("New Tasks") requirePriv(handler, "User") id = int(group) body = "" if "many-upload" in handler.session: body = handler.session["many-upload"] del handler.session["many-upload"] elif assigned: body = "[%s]\n" % stripTags(assigned) defaultGroup = Group.load(id) if not defaultGroup or defaultGroup.sprint.isHidden(handler.session["user"]): ErrorBox.die("Invalid Group", "No group with ID <b>%d</b>" % id) sprint = defaultGroup.sprint print '<script src="/static/jquery.typing-0.2.0.min.js" type="text/javascript"></script>' print '<script type="text/javascript">' nextURL = "/sprints/%d" % sprint.id if assigned: nextURL += "?search=assigned:%s" % stripTags(assigned.replace(" ", ",")) print "next_url = %s;" % toJS(nextURL) print "TaskTable.init();" print "</script>" print tabs.format(id).where("many") if not (sprint.isActive() or sprint.isPlanning()): ErrorBox.die("Sprint Closed", "Unable to modify inactive sprint") elif not sprint.canEdit(handler.session["user"]): ErrorBox.die("Permission Denied", "You don't have permission to modify this sprint") help = ResponseWriter() print "Each line needs to match the following syntax. Unparseable lines generate an error message in the preview and must be resolved before saving" print "<ul>" print "<li><b>X</b> — A single character changes the field separator to that character. The exception is #, which starts a comment. The default field separator is |, so that's used in the examples here</li>" print '<li><b>X...X:</b> — A line ending in a colon is a group name. All tasks after that line will be added to that group. If no group of that name exists, it will be created (the preview will label that group as "(NEW)"). A blank line switches back to the default group, which is the group you clicked the new task button on, %s' % defaultGroup.safe.name print "<li><b>X...X|X...X[|X...X[|X...X]]</b> — 2-4 fields are a new task. The fields can appear in any order:<ul>" print "<li><b>name</b> — The name of the task</li>" print "<li><b>hours</b> — The number of hours this task will take</li>" print "<li><b>assignee</b> — The person assigned to this task. If multiple people, separate usernames with spaces. This field is optional as long as <b>status</b> is also omitted; it defaults to the current user if a sprint member, or the scrummaster otherwise, unless overridden (see below)</li>" print '<li><b>status</b> — The initial status of the task. This field is optional; it defaults to "not started"</li>' print "</ul></li>" print "<li><b>[X...X]</b> — A username (or space-separated list of usernames) wrapped in brackets makes that user or group the default assignee for all tasks that don't specify an assignee</li>" print "<li><b>#...</b> — A line starting with a hash character is a comment, and is ignored. You can only comment out entire lines; a hash within a line does not start a comment at that point</li>" print "</ul>" print "You can also use the form above the textarea to upload a text file. The file will be used to fill the textarea, so it should match the syntax described above" print CollapsibleBox("Help", help.done()) print CollapsibleBox( "Groups", "<ul>%s</ul>" % "".join( "<li>%s</li>" % ("<b>%s</b> (default)" if group == defaultGroup else "%s") % group.safe.name for group in sprint.getGroups() ), ) print '<form id="upload-tasks" method="post" enctype="multipart/form-data" action="/tasks/new/many/upload?group=%d">' % defaultGroup.id print '<input type="file" name="data"><br><br>' print "</form>" print '<form id="write-tasks" method="post" action="/tasks/new/many?group=%d">' % defaultGroup.id print '<textarea id="many-body" name="body" class="defaultfocus">%s</textarea>' % body print '<div id="preview"></div>' print InfoBox("Loading...", id="post-status", close=True) print '<div id="new-task-many-buttons">' print Button("Save All", id="save-button", type="button").positive() print Button("Cancel", id="cancel-button", type="button").negative() print "</div>" print "</form>"