Ejemplo n.º 1
0
    def doWork(self):

        try:
            home = (yield self.transaction.calendarHomeWithResourceID(self.homeResourceID))
            resource = (yield home.objectResourceWithID(self.resourceID))
            attendeeAddress = yield calendarUserFromCalendarUserUID(home.uid(), self.transaction)
            attendee = attendeeAddress.record.canonicalCalendarUserAddress()
            calendar = (yield resource.componentForUser())
            organizer = calendar.validOrganizerForScheduling()

            # Deserialize "" as None
            changedRids = map(lambda x: DateTime.parseText(x) if x else None, self.changedRids.split(",")) if self.changedRids else None

            log.debug("ScheduleReplyWork - running for ID: {id}, UID: {uid}, attendee: {att}", id=self.workID, uid=calendar.resourceUID(), att=attendee)

            # We need to get the UID lock for implicit processing.
            yield NamedLock.acquire(self.transaction, "ImplicitUIDLock:%s" % (hashlib.md5(calendar.resourceUID()).hexdigest(),))

            itipmsg = iTipGenerator.generateAttendeeReply(calendar, attendee, changedRids=changedRids)

            # Send scheduling message and process response
            response = (yield self.sendToOrganizer(home, "REPLY", itipmsg, attendee, organizer))
            responses, all_delivered = self.extractSchedulingResponse((response,))
            if not all_delivered:
                changed = yield self.handleSchedulingResponse(responses, calendar, False)
                if changed:
                    yield resource._setComponentInternal(calendar, internal_state=ComponentUpdateState.ATTENDEE_ITIP_UPDATE)

            self._dequeued()

        except Exception, e:
            # FIXME: calendar may not be set here!
            log.debug("ScheduleReplyWork - exception ID: {id}, UID: '{uid}', {err}", id=self.workID, uid=calendar.resourceUID(), err=str(e))
            raise
Ejemplo n.º 2
0
    def doWork(self):

        try:
            home = (yield self.transaction.calendarHomeWithResourceID(
                self.homeResourceID))
            resource = (yield home.objectResourceWithID(self.resourceID))
            attendeeAddress = yield calendarUserFromCalendarUserUID(
                home.uid(), self.transaction)
            attendee = attendeeAddress.record.canonicalCalendarUserAddress()
            calendar = (yield resource.componentForUser())
            organizer = calendar.validOrganizerForScheduling()

            # Deserialize "" as None
            changedRids = map(
                lambda x: DateTime.parseText(x) if x else None,
                self.changedRids.split(",")) if self.changedRids else None

            log.debug(
                "ScheduleReplyWork - running for ID: {id}, UID: {uid}, attendee: {att}",
                id=self.workID,
                uid=calendar.resourceUID(),
                att=attendee)

            # We need to get the UID lock for implicit processing.
            yield NamedLock.acquire(
                self.transaction, "ImplicitUIDLock:%s" %
                (hashlib.md5(calendar.resourceUID()).hexdigest(), ))

            itipmsg = iTipGenerator.generateAttendeeReply(
                calendar, attendee, changedRids=changedRids)

            # Send scheduling message and process response
            response = (yield self.sendToOrganizer(home, "REPLY", itipmsg,
                                                   attendee, organizer))
            responses, all_delivered = self.extractSchedulingResponse(
                (response, ))
            if not all_delivered:
                changed = yield self.handleSchedulingResponse(
                    responses, calendar, False)
                if changed:
                    yield resource._setComponentInternal(
                        calendar,
                        internal_state=ComponentUpdateState.
                        ATTENDEE_ITIP_UPDATE)

            self._dequeued()

        except Exception, e:
            # FIXME: calendar may not be set here!
            log.debug(
                "ScheduleReplyWork - exception ID: {id}, UID: '{uid}', {err}",
                id=self.workID,
                uid=calendar.resourceUID(),
                err=str(e))
            raise
Ejemplo n.º 3
0
    def doWork(self):

        try:
            home = (yield self.transaction.calendarHomeWithResourceID(
                self.homeResourceID))
            attendeeAddress = yield calendarUserFromCalendarUserUID(
                home.uid(), self.transaction)
            attendee = attendeeAddress.record.canonicalCalendarUserAddress()
            calendar = Component.fromString(self.icalendarText)
            organizer = calendar.validOrganizerForScheduling()

            log.debug(
                "ScheduleReplyCancelWork - running for ID: {id}, UID: {uid}, attendee: {att}",
                id=self.workID,
                uid=calendar.resourceUID(),
                att=attendee)

            # We need to get the UID lock for implicit processing.
            yield NamedLock.acquire(
                self.transaction, "ImplicitUIDLock:%s" %
                (hashlib.md5(calendar.resourceUID()).hexdigest(), ))

            itipmsg = iTipGenerator.generateAttendeeReply(calendar,
                                                          attendee,
                                                          force_decline=True)

            # Send scheduling message - no need to process response as original resource is gone
            yield self.sendToOrganizer(home, "CANCEL", itipmsg, attendee,
                                       organizer)

            self._dequeued()

        except Exception, e:
            log.debug(
                "ScheduleReplyCancelWork - exception ID: {id}, UID: '{uid}', {err}",
                id=self.workID,
                uid=calendar.resourceUID(),
                err=str(e))
            raise
Ejemplo n.º 4
0
    def doWork(self):

        try:
            home = (yield self.transaction.calendarHomeWithResourceID(self.homeResourceID))
            attendeeAddress = yield calendarUserFromCalendarUserUID(home.uid(), self.transaction)
            attendee = attendeeAddress.record.canonicalCalendarUserAddress()
            calendar = Component.fromString(self.icalendarText)
            organizer = calendar.validOrganizerForScheduling()

            log.debug("ScheduleReplyCancelWork - running for ID: {id}, UID: {uid}, attendee: {att}", id=self.workID, uid=calendar.resourceUID(), att=attendee)

            # We need to get the UID lock for implicit processing.
            yield NamedLock.acquire(self.transaction, "ImplicitUIDLock:%s" % (hashlib.md5(calendar.resourceUID()).hexdigest(),))

            itipmsg = iTipGenerator.generateAttendeeReply(calendar, attendee, force_decline=True)

            # Send scheduling message - no need to process response as original resource is gone
            yield self.sendToOrganizer(home, "CANCEL", itipmsg, attendee, organizer)

            self._dequeued()

        except Exception, e:
            log.debug("ScheduleReplyCancelWork - exception ID: {id}, UID: '{uid}', {err}", id=self.workID, uid=calendar.resourceUID(), err=str(e))
            raise
Ejemplo n.º 5
0
def importCollectionComponent(store, component):
    """
    Import a component representing a collection (e.g. VCALENDAR) into the
    store.

    The homeUID and collection resource name the component will be imported
    into is derived from the SOURCE property on the VCALENDAR (which must
    be present).  The code assumes it will be a URI with slash-separated parts
    with the penultimate part specifying the homeUID and the last part
    specifying the calendar resource name.  The NAME property will be used
    to set the DAV:display-name, while the COLOR property will be used to set
    calendar-color.

    Subcomponents (e.g. VEVENTs) are grouped into resources by UID.  Objects
    which have a UID already in use within the home will be skipped.

    @param store: The db store to add the component to
    @type store: L{IDataStore}
    @param component: The component to store
    @type component: L{twistedcaldav.ical.Component}
    """

    sourceURI = component.propertyValue("SOURCE")
    if not sourceURI:
        raise ImportException("Calendar is missing SOURCE property")

    ownerUID, collectionResourceName = sourceURI.strip("/").split("/")[-2:]

    dir = store.directoryService()
    ownerRecord = yield dir.recordWithUID(ownerUID)
    if not ownerRecord:
        raise ImportException("{} is not in the directory".format(ownerUID))

    # Set properties on the collection
    txn = store.newTransaction()
    home = yield txn.calendarHomeWithUID(ownerUID, create=True)
    collection = yield home.childWithName(collectionResourceName)
    if not collection:
        print("Creating calendar: {}".format(collectionResourceName))
        collection = yield home.createChildWithName(collectionResourceName)
    for propertyName, element in (
        ("NAME", davxml.DisplayName),
        ("COLOR", customxml.CalendarColor),
    ):
        value = component.propertyValue(propertyName)
        if value is not None:
            setCollectionPropertyValue(collection, element, value)
            print(
                "Setting {name} to {value}".format(name=propertyName, value=value)
            )
    yield txn.commit()

    # Populate the collection; NB we use a txn for each object, and we might
    # want to batch them?
    groupedComponents = Component.componentsFromComponent(component)
    for groupedComponent in groupedComponents:

        try:
            uid = list(groupedComponent.subcomponents())[0].propertyValue("UID")
        except:
            continue

        # If event is unscheduled or the organizer matches homeUID, store the
        # component

        print("Event UID: {}".format(uid))
        storeDirectly = True
        organizer = groupedComponent.getOrganizer()
        if organizer is not None:
            organizerRecord = yield dir.recordWithCalendarUserAddress(organizer)
            if organizerRecord is None:
                # Organizer does not exist, so skip this event
                continue
            else:
                if ownerRecord.uid != organizerRecord.uid:
                    # Owner is not the organizer
                    storeDirectly = False

        if storeDirectly:
            resourceName = "{}.ics".format(str(uuid.uuid4()))
            try:
                yield storeComponentInHomeAndCalendar(
                    store, groupedComponent, ownerUID, collectionResourceName,
                    resourceName
                )
                print("Imported: {}".format(uid))
            except UIDExistsError:
                # That event is already in the home
                print("Skipping since UID already exists: {}".format(uid))

            except Exception, e:
                print(
                    "Failed to import due to: {error}\n{comp}".format(
                        error=e,
                        comp=groupedComponent
                    )
                )

        else:
            # Owner is an attendee, not the organizer
            # Apply the PARTSTATs from the import and from the possibly
            # existing event (existing event takes precedence) to the
            # organizer's copy.

            # Put the attendee copy into the right calendar now otherwise it
            # could end up on the default calendar when the change to the
            # organizer's copy causes an attendee update
            resourceName = "{}.ics".format(str(uuid.uuid4()))
            try:
                yield storeComponentInHomeAndCalendar(
                    store, groupedComponent, ownerUID, collectionResourceName,
                    resourceName, asAttendee=True
                )
                print("Imported: {}".format(uid))
            except UIDExistsError:
                # No need since the event is already in the home
                pass

            # Now use the iTip reply processing to update the organizer's copy
            # with the PARTSTATs from the component we're restoring.
            attendeeCUA = ownerRecord.canonicalCalendarUserAddress()
            organizerCUA = organizerRecord.canonicalCalendarUserAddress()
            processor = ImplicitProcessor()
            newComponent = iTipGenerator.generateAttendeeReply(groupedComponent, attendeeCUA, method="X-RESTORE")
            if newComponent is not None:
                txn = store.newTransaction()
                yield processor.doImplicitProcessing(
                    txn,
                    newComponent,
                    LocalCalendarUser(attendeeCUA, ownerRecord),
                    LocalCalendarUser(organizerCUA, organizerRecord)
                )
                yield txn.commit()
Ejemplo n.º 6
0
def importCollectionComponent(store, component):
    """
    Import a component representing a collection (e.g. VCALENDAR) into the
    store.

    The homeUID and collection resource name the component will be imported
    into is derived from the SOURCE property on the VCALENDAR (which must
    be present).  The code assumes it will be a URI with slash-separated parts
    with the penultimate part specifying the homeUID and the last part
    specifying the calendar resource name.  The NAME property will be used
    to set the DAV:display-name, while the COLOR property will be used to set
    calendar-color.

    Subcomponents (e.g. VEVENTs) are grouped into resources by UID.  Objects
    which have a UID already in use within the home will be skipped.

    @param store: The db store to add the component to
    @type store: L{IDataStore}
    @param component: The component to store
    @type component: L{twistedcaldav.ical.Component}
    """

    sourceURI = component.propertyValue("SOURCE")
    if not sourceURI:
        raise ImportException("Calendar is missing SOURCE property")

    ownerUID, collectionResourceName = sourceURI.strip("/").split("/")[-2:]

    dir = store.directoryService()
    ownerRecord = yield dir.recordWithUID(ownerUID)
    if not ownerRecord:
        raise ImportException("{} is not in the directory".format(ownerUID))

    # Set properties on the collection
    txn = store.newTransaction()
    home = yield txn.calendarHomeWithUID(ownerUID, create=True)
    collection = yield home.childWithName(collectionResourceName)
    if not collection:
        print("Creating calendar: {}".format(collectionResourceName))
        collection = yield home.createChildWithName(collectionResourceName)
    for propertyName, element in (
        ("NAME", davxml.DisplayName),
        ("COLOR", customxml.CalendarColor),
    ):
        value = component.propertyValue(propertyName)
        if value is not None:
            setCollectionPropertyValue(collection, element, value)
            print("Setting {name} to {value}".format(name=propertyName,
                                                     value=value))
    yield txn.commit()

    # Populate the collection; NB we use a txn for each object, and we might
    # want to batch them?
    groupedComponents = Component.componentsFromComponent(component)
    for groupedComponent in groupedComponents:

        try:
            uid = list(
                groupedComponent.subcomponents())[0].propertyValue("UID")
        except:
            continue

        # If event is unscheduled or the organizer matches homeUID, store the
        # component

        print("Event UID: {}".format(uid))
        storeDirectly = True
        organizer = groupedComponent.getOrganizer()
        if organizer is not None:
            organizerRecord = yield dir.recordWithCalendarUserAddress(
                organizer)
            if organizerRecord is None:
                # Organizer does not exist, so skip this event
                continue
            else:
                if ownerRecord.uid != organizerRecord.uid:
                    # Owner is not the organizer
                    storeDirectly = False

        if storeDirectly:
            resourceName = "{}.ics".format(str(uuid.uuid4()))
            try:
                yield storeComponentInHomeAndCalendar(store, groupedComponent,
                                                      ownerUID,
                                                      collectionResourceName,
                                                      resourceName)
                print("Imported: {}".format(uid))
            except UIDExistsError:
                # That event is already in the home
                print("Skipping since UID already exists: {}".format(uid))

            except Exception, e:
                print("Failed to import due to: {error}\n{comp}".format(
                    error=e, comp=groupedComponent))

        else:
            # Owner is an attendee, not the organizer
            # Apply the PARTSTATs from the import and from the possibly
            # existing event (existing event takes precedence) to the
            # organizer's copy.

            # Put the attendee copy into the right calendar now otherwise it
            # could end up on the default calendar when the change to the
            # organizer's copy causes an attendee update
            resourceName = "{}.ics".format(str(uuid.uuid4()))
            try:
                yield storeComponentInHomeAndCalendar(store,
                                                      groupedComponent,
                                                      ownerUID,
                                                      collectionResourceName,
                                                      resourceName,
                                                      asAttendee=True)
                print("Imported: {}".format(uid))
            except UIDExistsError:
                # No need since the event is already in the home
                pass

            # Now use the iTip reply processing to update the organizer's copy
            # with the PARTSTATs from the component we're restoring.
            attendeeCUA = ownerRecord.canonicalCalendarUserAddress()
            organizerCUA = organizerRecord.canonicalCalendarUserAddress()
            processor = ImplicitProcessor()
            newComponent = iTipGenerator.generateAttendeeReply(
                groupedComponent, attendeeCUA, method="X-RESTORE")
            txn = store.newTransaction()
            yield processor.doImplicitProcessing(
                txn, newComponent, LocalCalendarUser(attendeeCUA, ownerRecord),
                LocalCalendarUser(organizerCUA, organizerRecord))
            yield txn.commit()