Ejemplo n.º 1
0
    def test_lookup(self):
        """
        Test that L{CalendarUser.hosted} returns the expected results.
        """

        txn = self.transactionUnderTest()
        cu = yield calendarUserFromCalendarUserAddress("urn:x-uid:user01", txn)
        yield self.commit()

        self.assertTrue(isinstance(cu, LocalCalendarUser))
        self.assertTrue(cu.hosted())
        self.assertTrue(cu.validOriginator())
        self.assertTrue(cu.validRecipient())

        txn = self.transactionUnderTest()
        cu = yield calendarUserFromCalendarUserAddress("mailto:[email protected]", txn)
        yield self.commit()

        self.assertTrue(isinstance(cu, InvalidCalendarUser))
        self.assertFalse(cu.hosted())
        self.assertFalse(cu.validOriginator())
        self.assertFalse(cu.validRecipient())

        txn = self.transactionUnderTest()
        cu = yield calendarUserFromCalendarUserAddress("urn:x-uid:user03", txn)
        yield self.commit()

        self.assertTrue(isinstance(cu, LocalCalendarUser))
        self.assertTrue(cu.hosted())
        self.assertTrue(cu.validOriginator())
        self.assertFalse(cu.validRecipient())
Ejemplo n.º 2
0
    def test_lookup(self):
        """
        Test that L{CalendarUser.hosted} returns the expected results.
        """

        txn = self.transactionUnderTest()
        cu = yield calendarUserFromCalendarUserAddress("urn:x-uid:user01", txn)
        yield self.commit()

        self.assertTrue(isinstance(cu, LocalCalendarUser))
        self.assertTrue(cu.hosted())
        self.assertTrue(cu.validOriginator())
        self.assertTrue(cu.validRecipient())

        txn = self.transactionUnderTest()
        cu = yield calendarUserFromCalendarUserAddress(
            "mailto:[email protected]", txn)
        yield self.commit()

        self.assertTrue(isinstance(cu, InvalidCalendarUser))
        self.assertFalse(cu.hosted())
        self.assertFalse(cu.validOriginator())
        self.assertFalse(cu.validRecipient())

        txn = self.transactionUnderTest()
        cu = yield calendarUserFromCalendarUserAddress("urn:x-uid:user03", txn)
        yield self.commit()

        self.assertTrue(isinstance(cu, LocalCalendarUser))
        self.assertTrue(cu.hosted())
        self.assertTrue(cu.validOriginator())
        self.assertFalse(cu.validRecipient())
Ejemplo n.º 3
0
    def test_one_event_event_details(self):
        """
        Test when the calendar is empty.
        """

        data = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
BEGIN:VEVENT
UID:1234-5678
DTSTAMP:20080601T000000Z
DTSTART:%s
DTEND:%s
END:VEVENT
END:VCALENDAR
""" % (self.now_12H.getText(), self.now_13H.getText(),)

        yield self._createCalendarObject(data, "user01", "test.ics")
        calendar = (yield self.calendarUnderTest(home="user01", name="calendar_1"))
        fbinfo = FreebusyQuery.FBInfo([], [], [])
        timerange = Period(self.now, self.now_1D)
        event_details = []

        organizer = recipient = yield calendarUserFromCalendarUserAddress("mailto:[email protected]", self.transactionUnderTest())
        freebusy = FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange, event_details=event_details)
        freebusy.same_calendar_user = True
        result = yield freebusy.generateFreeBusyInfo([calendar, ], fbinfo)
        self.assertEqual(result, 1)
        self.assertEqual(fbinfo.busy, [Period(self.now_12H, self.now_13H), ])
        self.assertEqual(len(fbinfo.tentative), 0)
        self.assertEqual(len(fbinfo.unavailable), 0)
        self.assertEqual(len(event_details), 1)
        self.assertEqual(str(event_details[0]), str(tuple(Component.fromString(data).subcomponents())[0]))
Ejemplo n.º 4
0
    def test_freebusy(self):
        """
        Test that action=component works.
        """

        yield self.createShare("user01", "puser01")

        calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar")
        yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1))
        yield self.commitTransaction(0)

        fbstart = "{now:04d}0102T000000Z".format(**self.nowYear)
        fbend = "{now:04d}0103T000000Z".format(**self.nowYear)

        shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar")

        fbinfo = FreebusyQuery.FBInfo([], [], [])
        timerange = Period(DateTime.parseText(fbstart), DateTime.parseText(fbend))
        organizer = recipient = (yield calendarUserFromCalendarUserAddress("mailto:[email protected]", self.theTransactionUnderTest(1)))

        freebusy = FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange)
        matchtotal = (yield freebusy.generateFreeBusyInfo([shared, ], fbinfo))

        self.assertEqual(matchtotal, 1)
        self.assertEqual(fbinfo[0], [Period.parseText("{now:04d}0102T140000Z/PT1H".format(**self.nowYear)), ])
        self.assertEqual(len(fbinfo[1]), 0)
        self.assertEqual(len(fbinfo[2]), 0)
        yield self.commitTransaction(1)
Ejemplo n.º 5
0
    def checkAttendeeAsOriginator(self):
        """
        Check the validity of the ATTENDEE value as this is the originator of the iTIP message.
        Only local attendees are allowed for message originating from this server.
        """

        # Attendee's MUST be the request URI owner
        attendeeAddress = yield calendarUserFromCalendarUserAddress(self.attendee, self.txn)
        if attendeeAddress.hosted():
            if self.doingPOST is not None and attendeeAddress.record.uid != self.originator_uid:
                log.error("ATTENDEE in calendar data does not match owner of Outbox: {a}", a=self.attendee)
                raise HTTPError(
                    self.errorResponse(
                        responsecode.FORBIDDEN,
                        self.errorElements["attendee-denied"],
                        "Outbox does not belong to attendee",
                    )
                )
        else:
            log.error("Unknown ATTENDEE in calendar data: {a}", a=self.attendee)
            raise HTTPError(
                self.errorResponse(
                    responsecode.FORBIDDEN, self.errorElements["attendee-denied"], "No principal for attendee"
                )
            )
Ejemplo n.º 6
0
    def checkOriginator(self):
        """
        Check the validity of the Originator header. Extract the corresponding principal.
        """

        # Verify that Originator is a valid calendar user
        originatorAddress = yield calendarUserFromCalendarUserAddress(
            self.originator, self.txn)
        if not originatorAddress.hosted():
            # Local requests MUST have a principal.
            log.error(
                "Could not find principal for originator: {o}",
                o=self.originator,
            )
            raise HTTPError(
                self.errorResponse(
                    responsecode.FORBIDDEN,
                    self.errorElements["originator-denied"],
                    "No principal for originator",
                ))
        else:
            if not originatorAddress.validOriginator() or isinstance(
                    originatorAddress, OtherServerCalendarUser):
                log.error(
                    "Originator not enabled or hosted on this server: {o}",
                    o=self.originator,
                )
                raise HTTPError(
                    self.errorResponse(
                        responsecode.FORBIDDEN,
                        self.errorElements["originator-denied"],
                        "Originator cannot be scheduled",
                    ))

            self.originator = originatorAddress
Ejemplo n.º 7
0
    def checkOriginator(self):
        """
        Check the validity of the Originator header. Extract the corresponding principal.
        """

        # Verify that Originator is a valid calendar user
        originatorAddress = yield calendarUserFromCalendarUserAddress(self.originator, self.txn)
        if not originatorAddress.hosted():
            # Local requests MUST have a principal.
            log.error("Could not find principal for originator: {o}", o=self.originator)
            raise HTTPError(
                self.errorResponse(
                    responsecode.FORBIDDEN, self.errorElements["originator-denied"], "No principal for originator"
                )
            )
        else:
            if not originatorAddress.validOriginator() or isinstance(originatorAddress, OtherServerCalendarUser):
                log.error("Originator not enabled or hosted on this server: {o}", o=self.originator)
                raise HTTPError(
                    self.errorResponse(
                        responsecode.FORBIDDEN,
                        self.errorElements["originator-denied"],
                        "Originator cannot be scheduled",
                    )
                )

            self.originator = originatorAddress
Ejemplo n.º 8
0
    def checkAttendeeAsOriginator(self):
        """
        Check the validity of the ATTENDEE value as this is the originator of the iTIP message.
        Only local attendees are allowed for message originating from this server.
        """

        # Attendee's MUST be the request URI owner
        attendeeAddress = yield calendarUserFromCalendarUserAddress(
            self.attendee, self.txn)
        if attendeeAddress.hosted():
            if self.doingPOST is not None and attendeeAddress.record.uid != self.originator_uid:
                log.error(
                    "ATTENDEE in calendar data does not match owner of Outbox: {a}",
                    a=self.attendee,
                )
                raise HTTPError(
                    self.errorResponse(
                        responsecode.FORBIDDEN,
                        self.errorElements["attendee-denied"],
                        "Outbox does not belong to attendee",
                    ))
        else:
            log.error(
                "Unknown ATTENDEE in calendar data: {a}",
                a=self.attendee,
            )
            raise HTTPError(
                self.errorResponse(
                    responsecode.FORBIDDEN,
                    self.errorElements["attendee-denied"],
                    "No principal for attendee",
                ))
Ejemplo n.º 9
0
    def test_freebusy(self):
        """
        Test that action=component works.
        """

        yield self.createShare("user01", "puser01")

        calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar")
        yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1))
        yield self.commitTransaction(0)

        fbstart = "{now:04d}0102T000000Z".format(**self.nowYear)
        fbend = "{now:04d}0103T000000Z".format(**self.nowYear)

        shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar")

        fbinfo = FreebusyQuery.FBInfo([], [], [])
        timerange = Period(DateTime.parseText(fbstart), DateTime.parseText(fbend))
        organizer = recipient = (yield calendarUserFromCalendarUserAddress("mailto:[email protected]", self.theTransactionUnderTest(1)))

        freebusy = FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange)
        matchtotal = (yield freebusy.generateFreeBusyInfo([shared, ], fbinfo))

        self.assertEqual(matchtotal, 1)
        self.assertEqual(fbinfo[0], [Period.parseText("{now:04d}0102T140000Z/PT1H".format(**self.nowYear)), ])
        self.assertEqual(len(fbinfo[1]), 0)
        self.assertEqual(len(fbinfo[2]), 0)
        yield self.commitTransaction(1)
Ejemplo n.º 10
0
    def recv_freebusy(self, txn, request):
        """
        Process a freebusy cross-pod request. Message arguments as per L{send_freebusy}.

        @param request: request arguments
        @type request: C{dict}
        """

        # Operate on the L{CommonHomeChild}
        calresource, _ignore = yield self._getStoreObjectForRequest(
            txn, request)

        organizer = yield calendarUserFromCalendarUserAddress(
            request["organizer"], txn) if request["organizer"] else None
        recipient = yield calendarUserFromCalendarUserAddress(
            request["recipient"], txn) if request["recipient"] else None

        freebusy = FreebusyQuery(
            organizer=organizer,
            recipient=recipient,
            timerange=Period.parseText(request["timerange"]),
            excludeUID=request["excludeuid"],
            event_details=request["event_details"],
        )
        fbinfo = FreebusyQuery.FBInfo([], [], [])
        matchtotal = yield freebusy.generateFreeBusyInfo(
            [
                calresource,
            ],
            fbinfo,
            matchtotal=request["matchtotal"],
        )

        # Convert L{Period} objects to text for JSON response
        returnValue({
            "fbresults": [
                [item.getText() for item in fbinfo.busy],
                [item.getText() for item in fbinfo.tentative],
                [item.getText() for item in fbinfo.unavailable],
            ],
            "matchtotal":
            matchtotal,
        })
Ejemplo n.º 11
0
    def checkRecipients(self):
        """
        Check the validity of the Recipient header values. These must all be local as there
        is no concept of server-to-server relaying.
        """

        results = []
        for recipient in self.recipients:
            # Get the calendar user object for this recipient
            recipientAddress = yield calendarUserFromCalendarUserAddress(
                recipient, self.txn)

            # If no calendar user we may have a remote recipient but we should check whether
            # the address is one that ought to be on our server and treat that as a missing
            # user. Also if server-to-server is not enabled then remote addresses are not allowed.
            if not recipientAddress.hosted():
                localUser = (
                    yield
                    addressmapping.mapper.isCalendarUserInMyDomain(recipient))
                if localUser:
                    log.error(
                        "No record for calendar user address: {r}",
                        r=recipient,
                    )
                else:
                    log.error(
                        "Unknown calendar user address: {r}",
                        r=recipient,
                    )
                results.append(InvalidCalendarUser(recipient))
            else:
                # Map recipient to their inbox and cache on calendar user object
                inbox = None
                if recipientAddress.validRecipient():
                    if isinstance(recipientAddress, LocalCalendarUser):
                        recipient_home = yield self.txn.calendarHomeWithUID(
                            recipientAddress.record.uid, create=True)
                        if recipient_home:
                            inbox = (yield
                                     recipient_home.calendarWithName("inbox"))
                    else:
                        inbox = "dummy"
                    recipientAddress.inbox = inbox

                if inbox:
                    results.append(recipientAddress)
                else:
                    log.error(
                        "No scheduling for calendar user: {r}",
                        r=recipient,
                    )
                    results.append(InvalidCalendarUser(recipient))

        self.recipients = results
Ejemplo n.º 12
0
    def checkOrganizer(self):
        """
        Check the validity of the ORGANIZER value. ORGANIZER must be local.
        """

        # Verify that the ORGANIZER's cu address maps to a valid user
        organizer = self.calendar.getOrganizer()
        if organizer:
            organizerAddress = yield calendarUserFromCalendarUserAddress(organizer, self.txn)
            if organizerAddress.hosted():
                if organizerAddress.validOriginator():

                    # Only do this check for a freebusy request. A check for an invite needs
                    # to be handled later when we know whether a new invite is being added
                    # (which we reject) vs an update to an existing one (which we allow).
                    if self.checkForFreeBusy() and not organizerAddress.record.enabledAsOrganizer():
                        log.error("ORGANIZER not allowed to be an Organizer: {cal}", cal=self.calendar)
                        raise HTTPError(
                            self.errorResponse(
                                responsecode.FORBIDDEN,
                                self.errorElements["organizer-denied"],
                                "Organizer cannot schedule",
                            )
                        )

                    self.organizer = organizerAddress
                else:
                    log.error("No scheduling for ORGANIZER: {o}", o=organizer)
                    raise HTTPError(
                        self.errorResponse(
                            responsecode.FORBIDDEN, self.errorElements["organizer-denied"], "Organizer cannot schedule"
                        )
                    )
            else:
                localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(organizer))
                if localUser:
                    log.error("No principal for ORGANIZER in calendar data: {cal}", cal=self.calendar)
                    raise HTTPError(
                        self.errorResponse(
                            responsecode.FORBIDDEN, self.errorElements["organizer-denied"], "No principal for organizer"
                        )
                    )
                else:
                    self.organizer = organizerAddress
        else:
            log.error("ORGANIZER missing in calendar data: {cal}", cal=self.calendar)
            raise HTTPError(
                self.errorResponse(
                    responsecode.FORBIDDEN, self.errorElements["invalid-scheduling-message"], "Missing organizer"
                )
            )
Ejemplo n.º 13
0
    def recv_freebusy(self, txn, request):
        """
        Process a freebusy cross-pod request. Message arguments as per L{send_freebusy}.

        @param request: request arguments
        @type request: C{dict}
        """

        # Operate on the L{CommonHomeChild}
        calresource, _ignore = yield self._getStoreObjectForRequest(txn, request)

        organizer = yield calendarUserFromCalendarUserAddress(request["organizer"], txn) if request["organizer"] else None
        recipient = yield calendarUserFromCalendarUserAddress(request["recipient"], txn) if request["recipient"] else None

        freebusy = FreebusyQuery(
            organizer=organizer,
            recipient=recipient,
            timerange=Period.parseText(request["timerange"]),
            excludeUID=request["excludeuid"],
            event_details=request["event_details"],
        )
        fbinfo = FreebusyQuery.FBInfo([], [], [])
        matchtotal = yield freebusy.generateFreeBusyInfo(
            [calresource, ],
            fbinfo,
            matchtotal=request["matchtotal"],
        )

        # Convert L{Period} objects to text for JSON response
        returnValue({
            "fbresults": [
                [item.getText() for item in fbinfo.busy],
                [item.getText() for item in fbinfo.tentative],
                [item.getText() for item in fbinfo.unavailable],
            ],
            "matchtotal": matchtotal,
        })
Ejemplo n.º 14
0
    def checkRecipients(self):
        """
        Check the validity of the Recipient header values. These must all be local as there
        is no concept of server-to-server relaying.
        """

        results = []
        for recipient in self.recipients:
            # Get the calendar user object for this recipient
            recipientAddress = yield calendarUserFromCalendarUserAddress(recipient, self.txn)

            # If no calendar user we may have a remote recipient but we should check whether
            # the address is one that ought to be on our server and treat that as a missing
            # user. Also if server-to-server is not enabled then remote addresses are not allowed.
            if not recipientAddress.hosted():
                localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(recipient))
                if localUser:
                    log.error(
                        "No record for calendar user address: {r}",
                        r=recipient,
                    )
                else:
                    log.error(
                        "Unknown calendar user address: {r}",
                        r=recipient,
                    )
                results.append(InvalidCalendarUser(recipient))
            else:
                # Map recipient to their inbox and cache on calendar user object
                inbox = None
                if recipientAddress.validRecipient():
                    if isinstance(recipientAddress, LocalCalendarUser):
                        recipient_home = yield self.txn.calendarHomeWithUID(recipientAddress.record.uid, create=True)
                        if recipient_home:
                            inbox = (yield recipient_home.calendarWithName("inbox"))
                    else:
                        inbox = "dummy"
                    recipientAddress.inbox = inbox

                if inbox:
                    results.append(recipientAddress)
                else:
                    log.error(
                        "No scheduling for calendar user: {r}",
                        r=recipient,
                    )
                    results.append(InvalidCalendarUser(recipient))

        self.recipients = results
Ejemplo n.º 15
0
    def checkOrganizer(self):
        """
        Check the validity of the ORGANIZER value. ORGANIZER must be local.
        """

        # Verify that the ORGANIZER's cu address maps to a valid user
        organizer = self.calendar.getOrganizer()
        if organizer:
            organizerAddress = yield calendarUserFromCalendarUserAddress(organizer, self.txn)
            if organizerAddress.hosted():
                if organizerAddress.validOriginator():

                    # Only do this check for a freebusy request. A check for an invite needs
                    # to be handled later when we know whether a new invite is being added
                    # (which we reject) vs an update to an existing one (which we allow).
                    if self.checkForFreeBusy() and not organizerAddress.record.enabledAsOrganizer():
                        log.error("ORGANIZER not allowed to be an Organizer: {cal}", cal=self.calendar,)
                        raise HTTPError(self.errorResponse(
                            responsecode.FORBIDDEN,
                            self.errorElements["organizer-denied"],
                            "Organizer cannot schedule",
                        ))

                    self.organizer = organizerAddress
                else:
                    log.error("No scheduling for ORGANIZER: {o}", o=organizer,)
                    raise HTTPError(self.errorResponse(
                        responsecode.FORBIDDEN,
                        self.errorElements["organizer-denied"],
                        "Organizer cannot schedule",
                    ))
            else:
                localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(organizer))
                if localUser:
                    log.error("No principal for ORGANIZER in calendar data: {cal}", cal=self.calendar,)
                    raise HTTPError(self.errorResponse(
                        responsecode.FORBIDDEN,
                        self.errorElements["organizer-denied"],
                        "No principal for organizer",
                    ))
                else:
                    self.organizer = organizerAddress
        else:
            log.error("ORGANIZER missing in calendar data: {cal}", cal=self.calendar,)
            raise HTTPError(self.errorResponse(
                responsecode.FORBIDDEN,
                self.errorElements["invalid-scheduling-message"],
                "Missing organizer",
            ))
Ejemplo n.º 16
0
    def test_no_events(self):
        """
        Test when the calendar is empty.
        """

        calendar = (yield self.calendarUnderTest(home="user01", name="calendar_1"))
        fbinfo = FreebusyQuery.FBInfo([], [], [])
        timerange = Period(self.now, self.now_1D)

        organizer = recipient = yield calendarUserFromCalendarUserAddress("mailto:[email protected]", self.transactionUnderTest())
        freebusy = FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange)
        result = (yield freebusy.generateFreeBusyInfo([calendar, ], fbinfo))
        self.assertEqual(result, 0)
        self.assertEqual(len(fbinfo.busy), 0)
        self.assertEqual(len(fbinfo.tentative), 0)
        self.assertEqual(len(fbinfo.unavailable), 0)
Ejemplo n.º 17
0
    def test_one_event_event_details(self):
        """
        Test when the calendar is empty.
        """

        data = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
BEGIN:VEVENT
UID:1234-5678
DTSTAMP:20080601T000000Z
DTSTART:%s
DTEND:%s
END:VEVENT
END:VCALENDAR
""" % (
            self.now_12H.getText(),
            self.now_13H.getText(),
        )

        yield self._createCalendarObject(data, "user01", "test.ics")
        calendar = (yield self.calendarUnderTest(home="user01",
                                                 name="calendar_1"))
        fbinfo = FreebusyQuery.FBInfo([], [], [])
        timerange = Period(self.now, self.now_1D)
        event_details = []

        organizer = recipient = yield calendarUserFromCalendarUserAddress(
            "mailto:[email protected]", self.transactionUnderTest())
        freebusy = FreebusyQuery(organizer=organizer,
                                 recipient=recipient,
                                 timerange=timerange,
                                 event_details=event_details)
        freebusy.same_calendar_user = True
        result = yield freebusy.generateFreeBusyInfo([
            calendar,
        ], fbinfo)
        self.assertEqual(result, 1)
        self.assertEqual(fbinfo.busy, [
            Period(self.now_12H, self.now_13H),
        ])
        self.assertEqual(len(fbinfo.tentative), 0)
        self.assertEqual(len(fbinfo.unavailable), 0)
        self.assertEqual(len(event_details), 1)
        self.assertEqual(
            str(event_details[0]),
            str(tuple(Component.fromString(data).subcomponents())[0]))
Ejemplo n.º 18
0
    def test_no_events(self):
        """
        Test when the calendar is empty.
        """

        calendar = (yield self.calendarUnderTest(home="user01",
                                                 name="calendar_1"))
        fbinfo = FreebusyQuery.FBInfo([], [], [])
        timerange = Period(self.now, self.now_1D)

        organizer = recipient = yield calendarUserFromCalendarUserAddress(
            "mailto:[email protected]", self.transactionUnderTest())
        freebusy = FreebusyQuery(organizer=organizer,
                                 recipient=recipient,
                                 timerange=timerange)
        result = (yield freebusy.generateFreeBusyInfo([
            calendar,
        ], fbinfo))
        self.assertEqual(result, 0)
        self.assertEqual(len(fbinfo.busy), 0)
        self.assertEqual(len(fbinfo.tentative), 0)
        self.assertEqual(len(fbinfo.unavailable), 0)