Beispiel #1
0
    def new_incident(self, request):
        if self.config.ReadOnly:
            set_response_header(
                request, HeaderName.contentType, ContentType.plain
            )
            request.setResponseCode(http.FORBIDDEN)
            return "Server is in read-only mode."

        incident = Incident.from_json_io(
            request.content, number=self.storage.next_incident_number()
        )

        # Edit report entrys to add author
        for entry in incident.report_entries:
            entry.author = self.avatarId.decode("utf-8")

        self.storage.write_incident(incident)

        request.setResponseCode(http.CREATED)

        request.setHeader(
            HeaderName.incidentNumber.value,
            incident.number
        )
        request.setHeader(
            HeaderName.location.value,
            url_for(request, "get_incident", {"number": incident.number})
        )

        return ""
Beispiel #2
0
 def notFoundHandler(f):
     f.trap(KeyError)
     request.setResponseCode(http.NOT_FOUND)
     set_response_header(
         request, HeaderName.contentType, ContentType.plain
     )
     return "Not found."
Beispiel #3
0
    def get_incident(self, request, number):
        # FIXME: For debugging
        #import time
        #time.sleep(0.3)

        set_response_header(
            request, HeaderName.etag,
            self.storage.etag_for_incident_with_number(number)
        )
        set_response_header(
            request, HeaderName.contentType, ContentType.JSON
        )

        if False:
            #
            # This is faster, but doesn't benefit from any cleanup or
            # validation code, so it's only OK if we know all data in the
            # store is clean by this server version's standards.
            #
            return self.storage.read_incident_with_number_raw(number)
        else:
            #
            # This parses the data from the store, validates it, then
            # re-serializes it.
            #
            incident = self.storage.read_incident_with_number(number)
            return incident.to_json_text()
Beispiel #4
0
 def list_incidents(self, request):
     #set_response_header(request, HeaderName.etag, "*") # FIXME
     set_response_header(request, HeaderName.contentType, ContentType.JSON)
     return to_json_text(sorted(
         incidents_from_query(self, request),
         cmp=lambda a, b: cmp(a[0], b[0]), reverse=True,
     ))
Beispiel #5
0
    def dispatchQueue(self, request):
        if not request.args:
            request.args["show_closed"] = ["false"]

        set_response_header(
            request, HeaderName.contentType, ContentType.HTML
        )
        return DispatchQueueElement(self)
Beispiel #6
0
 def ping(self, request):
     ack = "ack"
     set_response_header(
         request, HeaderName.etag, ack
     )
     set_response_header(
         request, HeaderName.contentType, ContentType.JSON
     )
     return to_json_text(ack)
Beispiel #7
0
    def doc_with_name(self, request, name):
        filePath = self.config.Resources.child("docs").child(name)

        if filePath.exists():
            if name.endswith(".xhtml"):
                set_response_header(request, HeaderName.contentType, ContentType.HTML)
                return FileElement(filePath)

        request.setResponseCode(http.NOT_FOUND)
        set_response_header(request, HeaderName.contentType, ContentType.plain)
        return "Not found."
Beispiel #8
0
 def links(self, request):
     #set_response_header(request, HeaderName.etag, ????)
     set_response_header(request, HeaderName.contentType, ContentType.JSON)
     return to_json_text([
         {JSON.name.value: name, JSON.url.value: value}
         for name, value in (
             ("Home page", "/"),
             ("Dispatch Queue", "/queue"),
             ("Daily Incident Summary (Table)", "/reports/daily"),
             ("Daily Incident Summary (Chart)", "/charts/daily"),
         )
     ])
Beispiel #9
0
    def list_rangers(self, request):
        set_response_header(request, HeaderName.etag, str(self.dms.rangers_updated))
        set_response_header(request, HeaderName.contentType, ContentType.JSON)

        d = self.dms.rangers()
        d.addCallback(lambda rangers:
            to_json_text(tuple(
                {
                    "handle": ranger.handle,
                    "name"  : ranger.name,
                    "status": ranger.status,
                }
                for ranger in rangers
            ))
        )

        return d              
Beispiel #10
0
 def list_incident_types(self, request):
     #set_response_header(request, HeaderName.etag, "*") # FIXME
     set_response_header(request, HeaderName.contentType, ContentType.JSON)
     return self.config.IncidentTypesJSON
Beispiel #11
0
 def shift_report(self, request):
     set_response_header(request, HeaderName.contentType, ContentType.HTML)
     return ShiftReportElement(self, "report_shift")
Beispiel #12
0
 def daily_chart(self, request):
     set_response_header(request, HeaderName.contentType, ContentType.HTML)
     return DailyReportElement(self, "chart_daily")
Beispiel #13
0
 def root(self, request):
     set_response_header(request, HeaderName.contentType, ContentType.HTML)
     return HomePageElement(self)
Beispiel #14
0
    def edit_incident(self, request, number):
        number = int(number)
        incident = self.storage.read_incident_with_number(number)

        #
        # Handle the changes requested by the client
        #
        edits_json = from_json_io(request.content)
        edits = Incident.from_json(edits_json, number=number, validate=False)

        user_entries = []

        system_messages = []
        state_changes = []

        def log_edit_value(key, old, new):
            if key is JSON.number:
                return

            if old == new:
                #print "Client submitted unchaged value for {0}: {1}".format(JSON.describe(key), new)
                return

            if key in JSON.states():
                state_changes.append((key, new))
                return

            system_messages.append(u"Changed {0} to: {1}".format(JSON.describe(key), new if new else u"<no value>"))

        def diff_set(key, old, new):
            old = frozenset(old if old else ())
            new = frozenset(new if new else ())
            unchanged = old & new
            removed = old ^ unchanged
            added = new ^ unchanged
            return added, removed

        def log_edit_set(key, added, removed):
            if added:
                system_messages.append(u"Added to {0}: {1}".format(JSON.describe(key), ", ".join(added)))
            if removed:
                system_messages.append(u"Removed from {0}: {1}".format(JSON.describe(key), ", ".join(removed)))

        for key in edits_json.keys():
            key = JSON.lookupByValue(key)

            if key is JSON.report_entries:
                if edits.report_entries is not None:
                    for entry in edits.report_entries:
                        # Edit report entries to add author
                        entry.author = self.avatarId.decode("utf-8")
                        user_entries.append(entry)
            elif key is JSON.location_name:
                if edits.location.name is not None:
                    log_edit_value(key, incident.location.name, edits.location.name)
                    incident.location.name = edits.location.name
            elif key is JSON.location_address:
                if edits.location.address is not None:
                    log_edit_value(key, incident.location.address, edits.location.address)
                    incident.location.address = edits.location.address
            elif key is JSON.ranger_handles:
                if edits.rangers is not None:
                    added, removed = diff_set(key, incident.rangers, edits.rangers)
                    log_edit_set(key, [r.handle for r in added], [r.handle for r in removed])
                    incident.rangers = edits.rangers
            elif key is JSON.incident_types:
                if edits.incident_types is not None:
                    log_edit_set(key, *diff_set(key, incident.incident_types, edits.incident_types))
                    incident.incident_types = edits.incident_types
            else:
                attr_name = key.name
                attr_value = getattr(edits, attr_name)

                if key in (JSON.created, JSON.dispatched, JSON.on_scene, JSON.closed):
                    if edits.created is None:
                        # If created is None, then we aren't editing state.
                        # (It would be weird if others were not None here.)
                        continue
                elif attr_value is None:
                    # None values should not cause edits.
                    continue

                log_edit_value(key, getattr(incident, attr_name), attr_value)

                setattr(incident, attr_name, attr_value)

        #
        # Figure out what to report about state changes
        #
        highest_change = None
        lowest_change = None
        for state_changed, state_time in state_changes:
            if state_time is None:
                if lowest_change is None or JSON.cmpStates(lowest_change, state_changed) > 0:
                    lowest_change = state_changed
            else:
                if highest_change is None or JSON.cmpStates(highest_change[0], state_changed) < 0:
                    highest_change = (state_changed, state_time)

        if highest_change is not None:
            system_messages.append(u"State changed to: {0}".format(JSON.describe(highest_change[0])))
        elif lowest_change is not None:
            # We need one state less than lowest_change
            last = None
            for state in JSON.states():
                if state == lowest_change:
                    break
                last = state
            system_messages.append(u"State changed to: {0}".format(JSON.describe(last)))

        #
        # Add system report entries, then user entries
        #
        if system_messages:
            incident.report_entries.append(
                ReportEntry(
                    author = self.avatarId.decode("utf-8"),
                    text = u"\n".join(system_messages),
                    system_entry = True,
                )
            )
        incident.report_entries.extend(user_entries)

        #
        # Write to disk
        #
        self.storage.write_incident(incident)

        #
        # Respond
        #
        set_response_header(request, HeaderName.contentType, ContentType.JSON)
        request.setResponseCode(http.OK)

        return "";
Beispiel #15
0
 def list_incidents(self, request):
     #set_response_header(request, HeaderName.etag, "*") # FIXME
     set_response_header(request, HeaderName.contentType, ContentType.JSON)
     return to_json_text(tuple(incidents_from_query(self, request)))
Beispiel #16
0
 def queue_incident(self, request, number):
     set_response_header(
         request, HeaderName.contentType, ContentType.HTML
     )
     return IncidentElement(self, number)