Esempio n. 1
0
    async def readIncidentResource(
        self, request: IRequest, eventID: str, number: int
    ) -> KleinRenderable:
        """
        Incident endpoint.
        """
        event = Event(id=eventID)

        await self.config.authProvider.authorizeRequest(
            request, event, Authorization.readIncidents
        )

        try:
            number = int(number)
        except ValueError:
            return notFoundResponse(request)

        try:
            incident = await self.config.store.incidentWithNumber(
                event, number
            )
        except NoSuchIncidentError:
            return notFoundResponse(request)

        data = (
            jsonTextFromObject(jsonObjectFromModelObject(incident))
            .encode("utf-8")
        )

        return jsonBytes(request, data)
Esempio n. 2
0
    async def listIncidentReportsResource(
        self, request: IRequest
    ) -> KleinRenderable:
        """
        Incident reports endpoint.
        """
        store = self.config.store

        eventID = queryValue(request, "event")
        incidentNumberText = queryValue(request, "incident")

        if eventID is None:
            return invalidQueryResponse(request, "event")

        if eventID == incidentNumberText == "":
            await self.config.authProvider.authorizeRequest(
                request, None, Authorization.readIncidentReports
            )
            incidentReports = await store.detachedIncidentReports()

        else:
            try:
                event = Event(id=eventID)
            except ValueError:
                return invalidQueryResponse(
                    request, "event", eventID
                )

            await self.config.authProvider.authorizeRequest(
                request, event, Authorization.readIncidents
            )

            if incidentNumberText is None:
                incidentReports = await store.incidentReports(event=event)
            else:
                try:
                    incidentNumber = int(incidentNumberText)
                except ValueError:
                    return invalidQueryResponse(
                        request, "incident", incidentNumberText
                    )

                incidentReports = (
                    await store.incidentReportsAttachedToIncident(
                        event=event, incidentNumber=incidentNumber
                    )
                )

        stream = buildJSONArray(
            jsonTextFromObject(
                jsonObjectFromModelObject(incidentReport)
            ).encode("utf-8")
            for incidentReport in incidentReports
        )

        writeJSONStream(request, stream, None)
        return None
Esempio n. 3
0
    async def listIncidentReportsResource(
            self, request: IRequest) -> KleinRenderable:
        """
        Incident reports endpoint.
        """
        store = self.config.store

        eventID = queryValue(request, "event")
        incidentNumberText = queryValue(request, "incident")

        if eventID is None:
            return invalidQueryResponse(request, "event")

        if incidentNumberText is None:
            return invalidQueryResponse(request, "incident")

        if eventID == incidentNumberText == "":
            await self.config.authProvider.authorizeRequest(
                request, None, Authorization.readIncidentReports)
            incidentReports = await store.detachedIncidentReports()

        else:
            try:
                event = Event(id=eventID)
            except ValueError:
                return invalidQueryResponse(request, "event", eventID)

            try:
                incidentNumber = int(incidentNumberText)
            except ValueError:
                return invalidQueryResponse(request, "incident",
                                            incidentNumberText)

            await self.config.authProvider.authorizeRequest(
                request, event, Authorization.readIncidents)
            incidentReports = await store.incidentReportsAttachedToIncident(
                event=event, incidentNumber=incidentNumber)

        stream = buildJSONArray(
            jsonTextFromObject(jsonObjectFromModelObject(
                incidentReport)).encode("utf-8")
            for incidentReport in incidentReports)

        writeJSONStream(request, stream, None)
        return None
Esempio n. 4
0
    async def personnelData(self) -> Tuple[Iterable[bytes], str]:
        """
        Data for personnel endpoint.
        """
        try:
            personnel = await self.config.dms.personnel()
        except DMSError as e:
            self._log.error("Unable to vend personnel: {failure}", failure=e)
            personnel = ()

        return (
            buildJSONArray(
                jsonTextFromObject(jsonObjectFromModelObject(ranger)).encode(
                    "utf-8"
                )
                for ranger in personnel
            ),
            str(hash(personnel)),
        )
Esempio n. 5
0
    async def personnelData(self) -> Tuple[Iterable[bytes], str]:
        """
        Data for personnel endpoint.
        """
        try:
            personnel = await self.config.dms.personnel()
        except DMSError as e:
            self._log.error("Unable to vend personnel: {failure}", failure=e)
            personnel = ()

        return (
            buildJSONArray(
                jsonTextFromObject(
                    jsonObjectFromModelObject(ranger)
                ).encode("utf-8")
                for ranger in personnel
            ),
            str(hash(personnel)),
        )
Esempio n. 6
0
    async def readIncidentReportResource(self, request: IRequest,
                                         number: int) -> KleinRenderable:
        """
        Incident report endpoint.
        """
        try:
            number = int(number)
        except ValueError:
            self.config.authProvider.authenticateRequest(request)
            return notFoundResponse(request)

        incidentReport = await self.config.store.incidentReportWithNumber(
            number)

        await self.config.authProvider.authorizeRequestForIncidentReport(
            request, incidentReport)

        text = jsonTextFromObject(jsonObjectFromModelObject(incidentReport))

        return jsonBytes(request, text.encode("utf-8"))
Esempio n. 7
0
    async def listIncidentsResource(
        self, request: IRequest, eventID: str
    ) -> None:
        """
        Incident list endpoint.
        """
        event = Event(id=eventID)

        await self.config.authProvider.authorizeRequest(
            request, event, Authorization.readIncidents
        )

        stream = buildJSONArray(
            jsonTextFromObject(
                jsonObjectFromModelObject(incident)
            ).encode("utf-8")
            for incident in await self.config.store.incidents(event)
        )

        writeJSONStream(request, stream, None)
        return None
Esempio n. 8
0
    async def listIncidentsResource(
        self, request: IRequest, eventID: str
    ) -> None:
        """
        Incident list endpoint.
        """
        event = Event(id=eventID)
        del eventID

        await self.config.authProvider.authorizeRequest(
            request, event, Authorization.readIncidents
        )

        stream = buildJSONArray(
            jsonTextFromObject(jsonObjectFromModelObject(incident)).encode(
                "utf-8"
            )
            for incident in await self.config.store.incidents(event)
        )

        writeJSONStream(request, stream, None)
        return None
Esempio n. 9
0
    async def readIncidentReportResource(
        self, request: IRequest, number: int
    ) -> KleinRenderable:
        """
        Incident report endpoint.
        """
        try:
            number = int(number)
        except ValueError:
            self.config.authProvider.authenticateRequest(request)
            return notFoundResponse(request)

        incidentReport = await self.config.store.incidentReportWithNumber(
            number
        )

        await self.config.authProvider.authorizeRequestForIncidentReport(
            request, incidentReport
        )

        text = jsonTextFromObject(jsonObjectFromModelObject(incidentReport))

        return jsonBytes(request, text.encode("utf-8"))
Esempio n. 10
0
    async def runCompare(
        cls, config: Configuration, options: CompareOptions
    ) -> None:
        importers = []  # type: List[JSONImporter]

        for inFile in options["inFiles"]:
            with inFile:
                cls.log.info("Reading export file...")
                importers.append(
                    JSONImporter.fromIO(store=config.store, io=inFile)
                )

        first = None

        for importer in importers:
            if first is None:
                first = importer
            else:
                cls.log.info("Comparing export files...")  # type: ignore[misc]

                imsDataA = first.imsData
                imsDataB = importer.imsData

                if imsDataA != imsDataB:

                    if imsDataA.incidentTypes != imsDataB.incidentTypes:
                        cls.log.error(
                            "Incident Types do not match: "
                            "{incidentTypesA} != {incidentTypesB}",
                            incidentTypesA=imsDataA.incidentTypes,
                            incidentTypesB=imsDataB.incidentTypes,
                        )

                    for eventDataA, eventDataB in zip(
                        sorted(imsDataA.events), sorted(imsDataB.events)
                    ):
                        if eventDataA.event != eventDataB.event:
                            cls.log.error(
                                "Events do not match: {eventsA} != {eventsB}",
                                eventsA=[e for e in imsDataA.events.event],
                                eventsB=[e for e in imsDataB.events.event],
                            )

                    for eventDataA, eventDataB in zip(
                        sorted(imsDataA.events), sorted(imsDataB.events)
                    ):
                        if eventDataA.access != eventDataB.access:
                            cls.log.error(
                                "Events ACLs do not match: {aclA} != {aclB}",
                                aclA=eventDataA.access,
                                aclB=eventDataB.access,
                            )

                        if (
                            eventDataA.concentricStreets
                            != eventDataB.concentricStreets
                        ):
                            cls.log.error(
                                "Events concentric streets do not match: "
                                "{streetsA} != {streetsB}",
                                streetsA=eventDataA.concentricStreets,
                                streetsB=eventDataB.concentricStreets,
                            )

                        if eventDataA.incidents != eventDataB.incidents:
                            cls.log.error(
                                "Events incidents do not match: {event}",
                                event=eventDataA.event,
                            )

                            numbersA = frozenset(
                                i.number for i in eventDataA.incidents
                            )
                            numbersB = frozenset(
                                i.number for i in eventDataB.incidents
                            )
                            if numbersA != numbersB:
                                cls.log.error(
                                    "Incident numbers do not match for event "
                                    "{event}",
                                    event=eventDataA.event,
                                )

                            for incidentA, incidentB in zip(
                                sorted(eventDataA.incidents),
                                sorted(eventDataB.incidents),
                            ):
                                if incidentA != incidentB:
                                    cls.log.error(
                                        "Incidents do not match for event "
                                        "{event}: {incidentA} != {incidentB}",
                                        event=eventDataA.event,
                                        incidentA=jsonObjectFromModelObject(
                                            incidentA
                                        ),
                                        incidentB=jsonObjectFromModelObject(
                                            incidentB
                                        ),
                                    )

                        if (
                            eventDataA.incidentReports
                            != eventDataB.incidentReports
                        ):
                            cls.log.error(
                                "Events incident reports do not match: "
                                "{event}",
                                event=eventDataA.event,
                            )

                    cls.log.error("Argh IMS data mismatch")

                    break

        cls.stop()
Esempio n. 11
0
    async def newIncidentReportResource(
        self, request: IRequest, eventID: str
    ) -> KleinRenderable:
        """
        New incident report endpoint.
        """
        event = Event(id=eventID)
        del eventID

        await self.config.authProvider.authorizeRequest(
            request, event, Authorization.writeIncidentReports
        )

        try:
            json = objectFromJSONBytesIO(request.content)
        except JSONDecodeError as e:
            return invalidJSONResponse(request, e)

        if json.get(IncidentReportJSONKey.event.value, event.id) != event.id:
            return badRequestResponse(
                "Event ID mismatch: "
                f"{json[IncidentReportJSONKey.event.value]} != {event.id}"
            )
        if json.get(IncidentReportJSONKey.incidentNumber.value):
            return badRequestResponse(
                "New incident report may not be attached to an incident: "
                f"{json[IncidentReportJSONKey.incidentNumber.value]}"
            )

        author = request.user.shortNames[0]
        now = DateTime.now(TimeZone.utc)
        jsonNow = jsonObjectFromModelObject(now)

        # Set JSON event id
        # Set JSON incident report number to 0
        # Set JSON incident report created time to now

        for incidentReportKey in (
            IncidentReportJSONKey.number,
            IncidentReportJSONKey.created,
        ):
            if incidentReportKey.value in json:
                return badRequestResponse(
                    request,
                    f"New incident report may not specify "
                    f"{incidentReportKey.value}",
                )

        json[IncidentReportJSONKey.event.value] = event.id
        json[IncidentReportJSONKey.number.value] = 0
        json[IncidentReportJSONKey.created.value] = jsonNow

        # If not provided, set JSON report entries to an empty list

        if IncidentReportJSONKey.reportEntries.value not in json:
            json[IncidentReportJSONKey.reportEntries.value] = []

        # Set JSON report entry created time to now
        # Set JSON report entry author
        # Set JSON report entry automatic=False

        for entryJSON in json[IncidentReportJSONKey.reportEntries.value]:
            for reportEntryKey in (
                ReportEntryJSONKey.created,
                ReportEntryJSONKey.author,
                ReportEntryJSONKey.automatic,
            ):
                if reportEntryKey.value in entryJSON:
                    return badRequestResponse(
                        request,
                        f"New report entry may not specify "
                        f"{reportEntryKey.value}",
                    )

            entryJSON[ReportEntryJSONKey.created.value] = jsonNow
            entryJSON[ReportEntryJSONKey.author.value] = author
            entryJSON[ReportEntryJSONKey.automatic.value] = False

        # Deserialize JSON incident report

        try:
            incidentReport = modelObjectFromJSONObject(json, IncidentReport)
        except JSONCodecError as e:
            return badRequestResponse(request, str(e))

        # Store the incident report

        incidentReport = await self.config.store.createIncidentReport(
            incidentReport, author
        )

        self._log.info(
            "User {author} created new incident report "
            "#{incidentReport.number} via JSON",
            author=author,
            incidentReport=incidentReport,
        )
        self._log.debug(
            "New incident report: {json}",
            json=jsonObjectFromModelObject(incidentReport),
        )

        request.setHeader("Incident-Report-Number", str(incidentReport.number))
        request.setHeader(
            HeaderName.location.value,
            f"{URLs.incidentNumber.asText()}/{incidentReport.number}",
        )
        return noContentResponse(request)
Esempio n. 12
0
    async def newIncidentResource(
        self, request: IRequest, eventID: str
    ) -> KleinRenderable:
        """
        New incident endpoint.
        """
        event = Event(id=eventID)
        del eventID

        await self.config.authProvider.authorizeRequest(
            request, event, Authorization.writeIncidents
        )

        try:
            json = objectFromJSONBytesIO(request.content)
        except JSONDecodeError as e:
            return invalidJSONResponse(request, e)

        author = request.user.shortNames[0]
        now = DateTime.now(TimeZone.utc)
        jsonNow = jsonObjectFromModelObject(now)

        # Set JSON incident number to 0
        # Set JSON incident created time to now

        for incidentKey in (
            IncidentJSONKey.number,
            IncidentJSONKey.created,
        ):
            if incidentKey.value in json:
                return badRequestResponse(
                    request, f"New incident may not specify {incidentKey.value}"
                )

        json[IncidentJSONKey.number.value] = 0
        json[IncidentJSONKey.created.value] = jsonNow

        # If not provided, set JSON event, state to new, priority to normal

        if IncidentJSONKey.event.value not in json:
            json[IncidentJSONKey.event.value] = event.id

        if IncidentJSONKey.state.value not in json:
            json[IncidentJSONKey.state.value] = IncidentStateJSONValue.new.value

        if IncidentJSONKey.priority.value not in json:
            json[
                IncidentJSONKey.priority.value
            ] = IncidentPriorityJSONValue.normal.value

        # If not provided, set JSON handles, types, entries,
        # incident report numbers to an empty list

        for incidentKey in (
            IncidentJSONKey.rangerHandles,
            IncidentJSONKey.incidentTypes,
            IncidentJSONKey.reportEntries,
            IncidentJSONKey.incidentReportNumbers,
        ):
            if incidentKey.value not in json:
                json[incidentKey.value] = []

        # Set JSON report entry created time to now
        # Set JSON report entry author
        # Set JSON report entry automatic=False

        for entryJSON in json[IncidentJSONKey.reportEntries.value]:
            for reportEntryKey in (
                ReportEntryJSONKey.created,
                ReportEntryJSONKey.author,
                ReportEntryJSONKey.automatic,
            ):
                if reportEntryKey.value in entryJSON:
                    return badRequestResponse(
                        request,
                        f"New report entry may not specify "
                        f"{reportEntryKey.value}",
                    )

            entryJSON[ReportEntryJSONKey.created.value] = jsonNow
            entryJSON[ReportEntryJSONKey.author.value] = author
            entryJSON[ReportEntryJSONKey.automatic.value] = False

        # Deserialize JSON incident

        try:
            incident = modelObjectFromJSONObject(json, Incident)
        except JSONCodecError as e:
            return badRequestResponse(request, str(e))

        # Validate data

        if incident.event != event:
            return badRequestResponse(
                request,
                f"Incident's event {incident.event} does not match event in "
                f"URL {event}",
            )

        # Store the incident

        incident = await self.config.store.createIncident(incident, author)

        self._log.info(
            "User {author} created new incident #{incident.number} via JSON",
            author=author,
            incident=incident,
        )
        self._log.debug(
            "New incident: {json}", json=jsonObjectFromModelObject(incident)
        )

        request.setHeader("Incident-Number", str(incident.number))
        request.setHeader(
            HeaderName.location.value,
            f"{URLs.incidentNumber.asText()}/{incident.number}",
        )
        return noContentResponse(request)
Esempio n. 13
0
    async def newIncidentReportResource(
        self, request: IRequest
    ) -> KleinRenderable:
        """
        New incident report endpoint.
        """
        await self.config.authProvider.authorizeRequest(
            request, None, Authorization.writeIncidentReports
        )

        try:
            json = objectFromJSONBytesIO(request.content)
        except JSONDecodeError as e:
            return invalidJSONResponse(request, e)

        author = request.user.shortNames[0]
        now = DateTime.now(TimeZone.utc)
        jsonNow = jsonObjectFromModelObject(now)

        # Set JSON incident report number to 0
        # Set JSON incident report created time to now

        for incidentReportKey in (
            IncidentReportJSONKey.number,
            IncidentReportJSONKey.created,
        ):
            if incidentReportKey.value in json:
                return badRequestResponse(
                    request,
                    f"New incident report may not specify "
                    f"{incidentReportKey.value}"
                )

        json[IncidentReportJSONKey.number.value] = 0
        json[IncidentReportJSONKey.created.value] = jsonNow

        # If not provided, set JSON report entries to an empty list

        if IncidentReportJSONKey.reportEntries.value not in json:
            json[IncidentReportJSONKey.reportEntries.value] = []

        # Set JSON report entry created time to now
        # Set JSON report entry author
        # Set JSON report entry automatic=False

        for entryJSON in json[IncidentReportJSONKey.reportEntries.value]:
            for reportEntryKey in (
                ReportEntryJSONKey.created,
                ReportEntryJSONKey.author,
                ReportEntryJSONKey.automatic,
            ):
                if reportEntryKey.value in entryJSON:
                    return badRequestResponse(
                        request,
                        f"New report entry may not specify "
                        f"{reportEntryKey.value}"
                    )

            entryJSON[ReportEntryJSONKey.created.value] = jsonNow
            entryJSON[ReportEntryJSONKey.author.value] = author
            entryJSON[ReportEntryJSONKey.automatic.value] = False

        # Deserialize JSON incident report

        try:
            incidentReport = modelObjectFromJSONObject(json, IncidentReport)
        except JSONCodecError as e:
            return badRequestResponse(request, str(e))

        # Store the incident report

        incidentReport = await self.config.store.createIncidentReport(
            incidentReport, author
        )

        self._log.info(
            "User {author} created new incident report "
            "#{incidentReport.number} via JSON",
            author=author, incidentReport=incidentReport
        )
        self._log.debug(
            "New incident report: {json}",
            json=jsonObjectFromModelObject(incidentReport),
        )

        request.setHeader("Incident-Report-Number", incidentReport.number)
        request.setHeader(
            HeaderName.location.value,
            f"{URLs.incidentNumber.asText()}/{incidentReport.number}"
        )
        return noContentResponse(request)
Esempio n. 14
0
    async def newIncidentResource(
        self, request: IRequest, eventID: str
    ) -> KleinRenderable:
        """
        New incident endpoint.
        """
        event = Event(id=eventID)

        await self.config.authProvider.authorizeRequest(
            request, event, Authorization.writeIncidents
        )

        try:
            json = objectFromJSONBytesIO(request.content)
        except JSONDecodeError as e:
            return invalidJSONResponse(request, e)

        author = request.user.shortNames[0]
        now = DateTime.now(TimeZone.utc)
        jsonNow = jsonObjectFromModelObject(now)

        # Set JSON incident number to 0
        # Set JSON incident created time to now

        for incidentKey in (
            IncidentJSONKey.number,
            IncidentJSONKey.created,
        ):
            if incidentKey.value in json:
                return badRequestResponse(
                    request,
                    f"New incident may not specify {incidentKey.value}"
                )

        json[IncidentJSONKey.number.value] = 0
        json[IncidentJSONKey.created.value] = jsonNow

        # If not provided, set JSON event, state to new, priority to normal

        if IncidentJSONKey.event.value not in json:
            json[IncidentJSONKey.event.value] = event.id

        if IncidentJSONKey.state.value not in json:
            json[IncidentJSONKey.state.value] = (
                IncidentStateJSONValue.new.value
            )

        if IncidentJSONKey.priority.value not in json:
            json[IncidentJSONKey.priority.value] = (
                IncidentPriorityJSONValue.normal.value
            )

        # If not provided, set JSON handles, types, entries,
        # incident report numbers to an empty list

        for incidentKey in (
            IncidentJSONKey.rangerHandles,
            IncidentJSONKey.incidentTypes,
            IncidentJSONKey.reportEntries,
            IncidentJSONKey.incidentReportNumbers,
        ):
            if incidentKey.value not in json:
                json[incidentKey.value] = []

        # Set JSON report entry created time to now
        # Set JSON report entry author
        # Set JSON report entry automatic=False

        for entryJSON in json[IncidentJSONKey.reportEntries.value]:
            for reportEntryKey in (
                ReportEntryJSONKey.created,
                ReportEntryJSONKey.author,
                ReportEntryJSONKey.automatic,
            ):
                if reportEntryKey.value in entryJSON:
                    return badRequestResponse(
                        request,
                        f"New report entry may not specify "
                        f"{reportEntryKey.value}"
                    )

            entryJSON[ReportEntryJSONKey.created.value] = jsonNow
            entryJSON[ReportEntryJSONKey.author.value] = author
            entryJSON[ReportEntryJSONKey.automatic.value] = False

        # Deserialize JSON incident

        try:
            incident = modelObjectFromJSONObject(json, Incident)
        except JSONCodecError as e:
            return badRequestResponse(request, str(e))

        # Validate data

        if incident.event != event:
            return badRequestResponse(
                request,
                f"Incident's event {incident.event} does not match event in "
                f"URL {event}"
            )

        # Store the incident

        incident = await self.config.store.createIncident(incident, author)

        self._log.info(
            "User {author} created new incident #{incident.number} via JSON",
            author=author, incident=incident
        )
        self._log.debug(
            "New incident: {json}", json=jsonObjectFromModelObject(incident)
        )

        request.setHeader("Incident-Number", incident.number)
        request.setHeader(
            HeaderName.location.value,
            f"{URLs.incidentNumber.asText()}/{incident.number}"
        )
        return noContentResponse(request)