Beispiel #1
0
    def recv_set_delegates(self, txn, request):
        """
        Process a set delegates cross-pod request. Request arguments as per L{send_set_delegates}.

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

        delegator = yield txn.directoryService().recordWithUID(request["uid"])
        if delegator is None or not delegator.thisServer():
            raise FailedCrossPodRequestError(
                "Cross-pod delegate not on this server: {}".format(
                    delegator.uid))

        delegates = []
        for uid in request["delegates"]:
            delegate = yield txn.directoryService().recordWithUID(uid)
            if delegate is None:
                raise FailedCrossPodRequestError(
                    "Cross-pod delegate missing on this server: {}".format(
                        uid))
            delegates.append(delegate)

        yield Delegates.setDelegates(txn, delegator, delegates,
                                     request["read-write"])
Beispiel #2
0
    def validRequest(self, source_uid, destination_uid):
        """
        Verify that the specified uids are valid for the request and return the
        matching directory records.

        @param source_uid: UID for the user on whose behalf the request is being made
        @type source_uid: C{str}
        @param destination_uid: UID for the user to whom the request is being sent
        @type destination_uid: C{str}

        @return: L{Deferred} resulting in C{tuple} of L{IStoreDirectoryRecord}
        """

        source = yield self.store.directoryService().recordWithUID(source_uid)
        if source is None:
            raise DirectoryRecordNotFoundError("Cross-pod source: {}".format(source_uid))
        if not source.thisServer():
            raise FailedCrossPodRequestError("Cross-pod source not on this server: {}".format(source_uid))

        destination = yield self.store.directoryService().recordWithUID(destination_uid)
        if destination is None:
            raise DirectoryRecordNotFoundError("Cross-pod destination: {}".format(destination_uid))
        if destination.thisServer():
            raise FailedCrossPodRequestError("Cross-pod destination on this server: {}".format(destination_uid))

        returnValue((source, destination,))
Beispiel #3
0
    def processRequestStream(self, data, stream):
        """
        Process the request.

        @param data: the JSON data to process
        @type data: C{dict}

        @return: a L{tuple} of content-type and name, if successful, else a
            L{dict} for a JSON result
        @rtype: L{tuple} of (L{str}, L{str}), or L{dict}
        """
        # Must have a dict with an "action" key
        try:
            action = data["action"]
        except (KeyError, TypeError) as e:
            log.error(
                "JSON data must have an object as its root with an "
                "'action' attribute: {error}\n{json}",
                error=e,
                json=data)
            raise FailedCrossPodRequestError(
                "JSON data must have an object as its root with an "
                "'action' attribute: {}\n{}".format(e, data))

        method = "recv_{}".format(action.replace("-", "_"))
        if not hasattr(self, method):
            log.error("Unsupported action: {action}", action=action)
            raise FailedCrossPodRequestError(
                "Unsupported action: {}".format(action))

        # Need a transaction to work with
        txn = self.store.newTransaction(repr("Conduit request"))

        # Do the actual request processing
        try:
            result = (yield getattr(self, method)(txn, data, stream))
        except Exception as e:
            # Send the exception over to the other side
            yield txn.abort()
            log.error("Failed action: {action}, {error}",
                      action=action,
                      error=e)
            result = {
                "result": "exception",
                "class": ".".join((
                    e.__class__.__module__,
                    e.__class__.__name__,
                )),
                "details": str(e),
            }

        else:
            yield txn.commit()

        returnValue(result)
Beispiel #4
0
    def sendRequestToServer(self, txn, server, data, stream=None, streamType=None):

        request = self.conduitRequestClass(server, data, stream, streamType)
        try:
            response = (yield request.doRequest(txn))
        except Exception as e:
            raise FailedCrossPodRequestError("Failed cross-pod request: {}".format(e))
        if response["result"] == "exception":
            raise namedClass(response["class"])(response["details"])
        elif response["result"] != "ok":
            raise FailedCrossPodRequestError("Cross-pod request failed: {}".format(response))
        else:
            returnValue(response.get("value"))
Beispiel #5
0
    def send_get_delegators(self, txn, server, delegate, readWrite):
        """
        Get delegators from another pod.

        @param txn: transaction to use
        @type txn: L{CommonStoreTransaction}
        @param server: server to query
        @type server: L{Server}
        @param delegate: delegate to lookup
        @type delegate: L{DirectoryRecord}
        @param readWrite: if True, read and write access delegates are returned;
            read-only access otherwise
        """
        if not delegate.thisServer():
            raise FailedCrossPodRequestError(
                "Cross-pod destination on this server: {}".format(
                    delegate.uid))

        request = {
            "action": "get-delegators",
            "uid": delegate.uid,
            "read-write": readWrite,
        }
        response = yield self.sendRequestToServer(txn, server, request)
        returnValue(set(response))
Beispiel #6
0
    def recv_shareinvite(self, txn, request):
        """
        Process a sharing invite cross-pod request. Request arguments as per L{send_shareinvite}.

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

        # Sharee home on this pod must exist (create if needed)
        shareeHome = yield txn.homeWithUID(request["type"],
                                           request["sharee"],
                                           create=True)
        if shareeHome is None or shareeHome.external():
            raise FailedCrossPodRequestError("Invalid sharee UID specified")

        # Create a share
        yield shareeHome.processExternalInvite(
            request["owner"],
            request["owner_id"],
            request["owner_name"],
            request["share_id"],
            request["mode"],
            request["summary"],
            request["properties"],
            supported_components=request.get("supported-components"))
Beispiel #7
0
    def send_set_delegates(self, txn, delegator, delegates, readWrite):
        """
        Set delegates for delegator on another pod.

        @param txn: transaction to use
        @type txn: L{CommonStoreTransaction}
        @param delegator: delegator to set
        @type delegator: L{DirectoryRecord}
        @param delegates: delegates to set
        @type delegates: L{list} of L{DirectoryRecord}
        @param readWrite: if True, read and write access delegates are returned;
            read-only access otherwise
        """
        if delegator.thisServer():
            raise FailedCrossPodRequestError(
                "Cross-pod destination on this server: {}".format(
                    delegator.uid))

        request = {
            "action": "set-delegates",
            "uid": delegator.uid,
            "delegates": [delegate.uid for delegate in delegates],
            "read-write": readWrite,
        }
        yield self.sendRequestToServer(txn, delegator.server(), request)
Beispiel #8
0
    def processRequest(self, data):
        """
        Process the request.

        @param data: the JSON data to process
        @type data: C{dict}
        """
        # Must have a dict with an "action" key
        try:
            action = data["action"]
        except (KeyError, TypeError) as e:
            log.error("JSON data must have an object as its root with an 'action' attribute: {ex}\n{json}", ex=e, json=data)
            raise FailedCrossPodRequestError("JSON data must have an object as its root with an 'action' attribute: {}\n{}".format(e, data,))

        if action == "ping":
            result = {"result": "ok"}
            returnValue(result)

        method = "recv_{}".format(action.replace("-", "_"))
        if not hasattr(self, method):
            log.error("Unsupported action: {action}", action=action)
            raise FailedCrossPodRequestError("Unsupported action: {}".format(action))

        # Need a transaction to work with
        txn = self.store.newTransaction(repr("Conduit request"))

        # Do the actual request processing
        try:
            value = (yield getattr(self, method)(txn, data))
            result = {"result": "ok"}
            if value is not None:
                result["value"] = value

        except Exception as e:
            # Send the exception over to the other side
            yield txn.abort()
            log.error("Failed action: {action}, {ex}", action=action, ex=e)
            result = {
                "result": "exception",
                "class": ".".join((e.__class__.__module__, e.__class__.__name__,)),
                "details": str(e),
            }

        else:
            yield txn.commit()

        returnValue(result)
Beispiel #9
0
    def _getStoreObjectForRequest(self, txn, request):
        """
        Resolve the supplied JSON data to get a store object to operate on.
        """

        returnObject = txn
        classObject = None

        if "homeUID" in request:
            home = yield txn.homeWithUID(request["homeType"], request["homeUID"])
            if home is None:
                raise FailedCrossPodRequestError("Invalid owner UID specified")
            home._internalRequest = False
            returnObject = home
            if request.get("classMethod", False):
                classObject = home._childClass

        if "homeChildID" in request:
            homeChild = yield home.childWithID(request["homeChildID"])
            if homeChild is None:
                raise FailedCrossPodRequestError("Invalid home child specified")
            returnObject = homeChild
            if request.get("classMethod", False):
                classObject = homeChild._objectResourceClass
        elif "homeChildSharedID" in request:
            homeChild = yield home.childWithName(request["homeChildSharedID"])
            if homeChild is None:
                raise FailedCrossPodRequestError("Invalid home child specified")
            returnObject = homeChild
            if request.get("classMethod", False):
                classObject = homeChild._objectResourceClass

        if "objectResourceID" in request:
            objectResource = yield homeChild.objectResourceWithID(request["objectResourceID"])
            if objectResource is None:
                raise FailedCrossPodRequestError("Invalid object resource specified")
            returnObject = objectResource

        returnValue((returnObject, classObject,))
Beispiel #10
0
    def recv_dump_group_delegates(self, txn, request):
        """
        Process an delegators cross-pod request. Request arguments as per L{send_dump_group_delegates}.

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

        delegator = yield txn.directoryService().recordWithUID(request["uid"])
        if delegator is None or not delegator.thisServer():
            raise FailedCrossPodRequestError("Cross-pod delegate missing or on this server: {}".format(delegator.uid))

        results = yield txn.dumpGroupDelegatesLocal(delegator.uid)

        returnValue([[delegator_record.serialize(), group_record.serialize()] for delegator_record, group_record in results])
Beispiel #11
0
    def recv_get_delegates(self, txn, request):
        """
        Process an delegates cross-pod request. Request arguments as per L{send_get_delegates}.

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

        delegator = yield txn.directoryService().recordWithUID(request["uid"])
        if delegator is None or not delegator.thisServer():
            raise FailedCrossPodRequestError("Cross-pod delegate not on this server: {}".format(delegator.uid))

        delegates = yield Delegates._delegatesOfUIDs(txn, delegator, request["read-write"], request["expanded"])

        returnValue(list(delegates))
Beispiel #12
0
    def recv_dump_external_delegates(self, txn, request):
        """
        Process an delegators cross-pod request. Request arguments as per L{send_dump_external_delegates}.

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

        delegator = yield txn.directoryService().recordWithUID(request["uid"])
        if delegator is None or not delegator.thisServer():
            raise FailedCrossPodRequestError("Cross-pod delegate missing or on this server: {}".format(delegator.uid))

        delegates = yield txn.dumpExternalDelegatesLocal(delegator.uid)

        returnValue(self._to_serialize_list(delegates))
Beispiel #13
0
    def recv_get_delegators(self, txn, request):
        """
        Process an delegators cross-pod request. Request arguments as per L{send_get_delegators}.

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

        delegate = yield txn.directoryService().recordWithUID(request["uid"])
        if delegate is None or delegate.thisServer():
            raise FailedCrossPodRequestError("Cross-pod delegate missing or on this server: {}".format(delegate.uid))

        delegators = yield Delegates._delegatedToUIDs(txn, delegate, request["read-write"], onlyThisServer=True)

        returnValue(list(delegators))
Beispiel #14
0
    def recv_shareuninvite(self, txn, request):
        """
        Process a sharing uninvite cross-pod request. Request arguments as per L{send_shareuninvite}.

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

        # Sharee home on this pod must already exist
        shareeHome = yield txn.homeWithUID(request["type"], request["sharee"])
        if shareeHome is None or shareeHome.external():
            FailedCrossPodRequestError("Invalid sharee UID specified")

        # Remove a share
        yield shareeHome.processExternalUninvite(
            request["owner"],
            request["owner_id"],
            request["share_id"],
        )
Beispiel #15
0
    def recv_sharereply(self, txn, request):
        """
        Process a sharing reply cross-pod request. Request arguments as per L{send_sharereply}.

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

        # Sharer home on this pod must already exist
        ownerHome = yield txn.homeWithUID(request["type"], request["owner"])
        if ownerHome is None or ownerHome.external():
            FailedCrossPodRequestError("Invalid owner UID specified")

        # Process a reply
        yield ownerHome.processExternalReply(request["owner"],
                                             request["sharee"],
                                             request["share_id"],
                                             request["status"],
                                             summary=request.get("summary"))
Beispiel #16
0
    def send_dump_external_delegates(self, txn, delegator):
        """
        Get L{ExternalDelegateGroupsRecord} from another pod.

        @param txn: transaction to use
        @type txn: L{CommonStoreTransaction}
        @param delegator: delegate to lookup
        @type delegator: L{DirectoryRecord}
        @param readWrite: if True, read and write access delegates are returned;
            read-only access otherwise
        """
        if delegator.thisServer():
            raise FailedCrossPodRequestError("Cross-pod destination on this server: {}".format(delegator.uid))

        request = {
            "action": "dump-external-delegates",
            "uid": delegator.uid,
        }
        response = yield self.sendRequestToServer(txn, delegator.server(), request)
        returnValue(response)
Beispiel #17
0
 def _objectResourceWithName(self, name):
     raise FailedCrossPodRequestError()
Beispiel #18
0
 def _iCalendarRolledup(self, request):
     raise FailedCrossPodRequestError()
Beispiel #19
0
    def _getStoreObjectForRequest(self, txn, request):
        """
        Resolve the supplied JSON data to get a store object to operate on.
        """

        returnObject = txn
        classObject = None

        if "allowDisabledHome" in request:
            txn._allowDisabled = True

        if "homeUID" in request:
            home = yield txn.homeWithUID(request["homeType"],
                                         request["homeUID"])
            if home is None:
                raise FailedCrossPodRequestError("Invalid owner UID specified")
            home._internalRequest = False
            returnObject = home
            if request.get("classMethod", False):
                classObject = home._childClass

        if "homeChildID" in request:
            homeChild = yield home.childWithID(request["homeChildID"])
            if homeChild is None:
                raise FailedCrossPodRequestError(
                    "Invalid home child specified")
            returnObject = homeChild
            if request.get("classMethod", False):
                classObject = homeChild._objectResourceClass
        elif "homeChildSharedID" in request:
            homeChild = yield home.childWithName(request["homeChildSharedID"])
            if homeChild is None:
                # Raise NonExistentExternalShare here so we can indicate to the other pod
                # that it has a bogus share and it can fix itself
                raise NonExistentExternalShare("Invalid home child specified")
            returnObject = homeChild
            if request.get("classMethod", False):
                classObject = homeChild._objectResourceClass

        if "objectResourceID" in request:
            objectResource = yield homeChild.objectResourceWithID(
                request["objectResourceID"])
            if objectResource is None:
                raise FailedCrossPodRequestError(
                    "Invalid object resource specified")
            returnObject = objectResource

        if "notificationUID" in request:
            notification = yield txn.notificationsWithUID(
                request["notificationUID"])
            if notification is None:
                # See if a home exists (even a disabled one) - if so create the notification home
                txn._allowDisabled = True
                for storeType in (ECALENDARTYPE, EADDRESSBOOKTYPE):
                    home = yield txn.homeWithUID(storeType,
                                                 request["notificationUID"])
                    if home is not None:
                        notification = yield txn.notificationsWithUID(
                            request["notificationUID"], create=True)
                        break
                else:
                    # If no home at all - it is an error
                    raise FailedCrossPodRequestError(
                        "Invalid notification UID specified")

            notification._internalRequest = False
            returnObject = notification
            if request.get("classMethod", False):
                classObject = NotificationObject

        returnValue((
            returnObject,
            classObject,
        ))