def test_updateRecord(self):
        directory = getRootResource(config).getDirectory()
        guid = "eee28807-a8c5-46c8-a558-a08281c558a7"

        (yield updateRecord(True, directory, "locations",
            guid=guid, fullName="Test User", shortNames=["testuser",],)
        )
        try:
            (yield updateRecord(True, directory, "locations",
                guid=guid, fullName="Test User", shortNames=["testuser",],)
            )
        except DirectoryError:
            # We're expecting an error for trying to create a record with
            # an existing GUID
            pass
        else:
            raise self.failureException("Duplicate guid expected")

        record = directory.recordWithGUID(guid)
        self.assertTrue(record is not None)
        self.assertEquals(record.fullName, "Test User")
        self.assertTrue(record.autoSchedule)

        (yield updateRecord(False, directory, "locations",
            guid=guid, fullName="Changed", shortNames=["testuser",],)
        )
        record = directory.recordWithGUID(guid)
        self.assertTrue(record is not None)
        self.assertEquals(record.fullName, "Changed")

        directory.destroyRecord("locations", guid=guid)
        record = directory.recordWithGUID(guid)
        self.assertTrue(record is None)
예제 #2
0
 def __init__(self, store):
     """
     @param store: an already opened store
     """
     self.store = store
     from twistedcaldav.config import config
     self.davRootResource = getRootResource(config, self.store)
     self.directory = self.davRootResource.getDirectory()
예제 #3
0
    def setUp(self):
        yield super(StoreTestCase, self).setUp()

        yield self.buildStoreAndDirectory()

        self.rootResource = getRootResource(config, self.store)
        self.actualRoot = self.rootResource.resource.resource
        self.site = Site(self.actualRoot)

        yield self.populate()
예제 #4
0
파일: util.py 프로젝트: nunb/calendarserver
    def setUp(self):
        yield super(StoreTestCase, self).setUp()

        yield self.buildStoreAndDirectory()

        self.rootResource = getRootResource(config, self.store)
        self.actualRoot = self.rootResource.resource.resource
        self.site = Site(self.actualRoot)

        yield self.populate()
예제 #5
0
    def __init__(self, settings, mailer):
        self.settings = settings
        self.mailer = mailer

        rootResource = getRootResource(config,
            (
                ("inbox", IMIPInvitationInboxResource, (mailer,), "basic"),
            )
        )

        self.factory = HTTPFactory(server.Site(rootResource))
        self.server = internet.TCPServer(settings['MailGatewayPort'],
            self.factory)
예제 #6
0
    def setUp(self):
        yield super(PurgePrincipalTests, self).setUp()
        self._sqlCalendarStore = yield buildStore(self, self.notifierFactory)
        yield self.populate()

        self.patch(config.DirectoryService.params, "xmlFile",
            os.path.join(
                os.path.dirname(__file__), "purge", "accounts.xml"
            )
        )
        self.patch(config.ResourceService.params, "xmlFile",
            os.path.join(
                os.path.dirname(__file__), "purge", "resources.xml"
            )
        )
        self.rootResource = getRootResource(config, self._sqlCalendarStore)
        self.directory = self.rootResource.getDirectory()

        txn = self._sqlCalendarStore.newTransaction()

        # Add attachment to attachment.ics
        self._sqlCalendarStore._dropbox_ok = True
        home = (yield txn.calendarHomeWithUID(self.uid))
        calendar = (yield home.calendarWithName("calendar1"))
        event = (yield calendar.calendarObjectWithName("attachment.ics"))
        attachment = (yield event.createAttachmentWithName("attachment.txt"))
        t = attachment.store(MimeType("text", "x-fixture"))
        t.write("attachment")
        t.write(" text")
        (yield t.loseConnection())
        self._sqlCalendarStore._dropbox_ok = False

        # Share calendars each way
        home2 = (yield txn.calendarHomeWithUID(self.uid2))
        calendar2 = (yield home2.calendarWithName("calendar2"))
        self.sharedName = (yield calendar2.shareWith(home, _BIND_MODE_WRITE))
        self.sharedName2 = (yield calendar.shareWith(home2, _BIND_MODE_WRITE))

        (yield txn.commit())

        txn = self._sqlCalendarStore.newTransaction()
        home = (yield txn.calendarHomeWithUID(self.uid))
        calendar2 = (yield home.childWithName(self.sharedName))
        self.assertNotEquals(calendar2, None)
        home2 = (yield txn.calendarHomeWithUID(self.uid2))
        calendar1 = (yield home2.childWithName(self.sharedName2))
        self.assertNotEquals(calendar1, None)
        (yield txn.commit())
예제 #7
0
    def setUp(self):
        yield super(StoreTestCase, self).setUp()

        self.configure()

        self._sqlCalendarStore = yield buildCalendarStore(self, self.notifierFactory, directoryFromConfig(config))
        self.rootResource = getRootResource(config, self._sqlCalendarStore)
        self.directory = self._sqlCalendarStore.directoryService()

        self.principalsResource = DirectoryPrincipalProvisioningResource("/principals/", self.directory)
        self.site.resource.putChild("principals", self.principalsResource)
        self.calendarCollection = DirectoryCalendarHomeProvisioningResource(self.directory, "/calendars/", self._sqlCalendarStore)
        self.site.resource.putChild("calendars", self.calendarCollection)
        self.addressbookCollection = DirectoryAddressBookHomeProvisioningResource(self.directory, "/addressbooks/", self._sqlCalendarStore)
        self.site.resource.putChild("addressbooks", self.addressbookCollection)

        yield self.populate()
예제 #8
0
    def setUp(self):

        yield super(RecipientCopy, self).setUp()
        self._sqlCalendarStore = yield buildStore(self, self.notifierFactory)
        yield self.populate()

        self.patch(config.DirectoryService.params, "xmlFile",
            os.path.join(
                os.path.dirname(__file__), "accounts.xml"
            )
        )
        self.patch(config.ResourceService.params, "xmlFile",
            os.path.join(
                os.path.dirname(__file__), "resources.xml"
            )
        )
        self.rootResource = getRootResource(config, self._sqlCalendarStore)
        self.directory = self.rootResource.getDirectory()
예제 #9
0
 def rootResource(self):
     try:
         rootResource = getRootResource(config, self._store)
     except OSError, e:
         if e.errno == ENOENT:
             # Trying to re-write resources.xml but its parent directory does
             # not exist.  The server's never been started, so we're missing
             # state required to do any work.  (Plus, what would be the point
             # of purging stuff from a server that's completely empty?)
             raise ConfigurationError(
                 "It appears that the server has never been started.\n"
                 "Please start it at least once before purging anything.")
         elif e.errno == EACCES:
             # Trying to re-write resources.xml but it is not writable by the
             # current user.  This most likely means we're in a system
             # configuration and the user doesn't have sufficient privileges
             # to do the other things the tool might need to do either.
             raise ConfigurationError("You must run this tool as root.")
         else:
             raise
예제 #10
0
 def rootResource(self):
     try:
         from twistedcaldav.config import config
         rootResource = getRootResource(config, self.store)
     except OSError, e:
         if e.errno == ENOENT:
             # Trying to re-write resources.xml but its parent directory does
             # not exist.  The server's never been started, so we're missing
             # state required to do any work.
             raise ConfigurationError(
                 "It appears that the server has never been started.\n"
                 "Please start it at least once before running this tool.")
         elif e.errno == EACCES:
             # Trying to re-write resources.xml but it is not writable by the
             # current user.  This most likely means we're in a system
             # configuration and the user doesn't have sufficient privileges
             # to do the other things the tool might need to do either.
             raise ConfigurationError("You must run this tool as root.")
         else:
             raise
예제 #11
0
 def rootResource(self):
     try:
         from twistedcaldav.config import config
         rootResource = getRootResource(config, self.store)
     except OSError, e:
         if e.errno == ENOENT:
             # Trying to re-write resources.xml but its parent directory does
             # not exist.  The server's never been started, so we're missing
             # state required to do any work.
             raise ConfigurationError(
                 "It appears that the server has never been started.\n"
                 "Please start it at least once before running this tool.")
         elif e.errno == EACCES:
             # Trying to re-write resources.xml but it is not writable by the
             # current user.  This most likely means we're in a system
             # configuration and the user doesn't have sufficient privileges
             # to do the other things the tool might need to do either.
             raise ConfigurationError("You must run this tool as root.")
         else:
             raise
예제 #12
0
def shared_main(configFileName, method, *args, **kwds):

    try:
        loadConfig(configFileName)

        # Shed privileges
        if config.UserName and config.GroupName and os.getuid() == 0:
            uid = getpwnam(config.UserName).pw_uid
            gid = getgrnam(config.GroupName).gr_gid
            switchUID(uid, uid, gid)

        os.umask(config.umask)

        try:
            rootResource = getRootResource(config)
            directory = rootResource.getDirectory()
        except DirectoryError, e:
            print "Error: %s" % (e,)
            return
        setupMemcached(config)
        setupNotifications(config)
예제 #13
0
def makeAgentService(store):
    """
    Returns a service which will process GatewayAMPCommands, using a socket
    file descripter acquired by launchd

    @param store: an already opened store
    @returns: service
    """
    from twisted.internet import reactor

    sockets = getLaunchDSocketFDs() 
    fd = sockets["AgentSocket"][0]
    
    family = socket.AF_INET
    endpoint = AdoptedStreamServerEndpoint(reactor, fd, family)

    from twistedcaldav.config import config
    davRootResource = getRootResource(config, store)
    directory = davRootResource.getDirectory()

    def becameInactive():
        log.warn("Agent inactive; shutting down")
        reactor.stop()

    inactivityDetector = InactivityDetector(reactor,
        config.AgentInactivityTimeoutSeconds, becameInactive)
    root = Resource()
    root.putChild("gateway", AgentGatewayResource(store,
        davRootResource, directory, inactivityDetector))

    realmName = "/Local/Default"
    portal = Portal(AgentRealm(root, ["com.apple.calendarserver"]),
        [DirectoryServiceChecker(realmName)])
    credentialFactory = CustomDigestCredentialFactory("md5", realmName)
    wrapper = HTTPAuthSessionWrapper(portal, [credentialFactory])

    site = Site(wrapper)

    return StreamServerEndpointService(endpoint, site)
예제 #14
0
    def makeService(self, options):

        #
        # The task sidecar doesn't care about system SACLs
        #
        config.EnableSACLs = False

        #
        # Change default log level to "info" as its useful to have
        # that during startup
        #
        oldLogLevel = logLevelForNamespace(None)
        setLogLevelForNamespace(None, "info")

        rootResource = getRootResource(config)

        service = CalDAVTaskService(rootResource)

        # Change log level back to what it was before
        setLogLevelForNamespace(None, oldLogLevel)

        return service
예제 #15
0
    def setUp(self):
        super(DeprovisionTestCase, self).setUp()

        testRootPath = FilePath(__file__).sibling("deprovision")
        template = testRootPath.child("caldavd.plist").getContent()

        newConfig = template % {
            "ServerRoot" : os.path.abspath(config.ServerRoot),
        }
        configFilePath = FilePath(os.path.join(config.ConfigRoot, "caldavd.plist"))
        configFilePath.setContent(newConfig)

        self.configFileName = configFilePath.path
        config.load(self.configFileName)

        origUsersFile = FilePath(__file__).sibling(
            "deprovision").child("users-groups.xml")
        copyUsersFile = FilePath(config.DataRoot).child("accounts.xml")
        origUsersFile.copyTo(copyUsersFile)

        origResourcesFile = FilePath(__file__).sibling(
            "deprovision").child("resources-locations.xml")
        copyResourcesFile = FilePath(config.DataRoot).child("resources.xml")
        origResourcesFile.copyTo(copyResourcesFile)

        origAugmentFile = FilePath(__file__).sibling(
            "deprovision").child("augments.xml")
        copyAugmentFile = FilePath(config.DataRoot).child("augments.xml")
        origAugmentFile.copyTo(copyAugmentFile)

        self.rootResource = getRootResource(config)
        self.directory = self.rootResource.getDirectory()

        # Make sure trial puts the reactor in the right state, by letting it
        # run one reactor iteration.  (Ignore me, please.)
        d = Deferred()
        reactor.callLater(0, d.callback, True)
        return d
예제 #16
0
    def setUp(self):
        super(InboundTests, self).setUp()

        self.store = yield buildStore(self, None)
        self.patch(config.DirectoryService.params, "xmlFile", xmlFile)
        self.root = getRootResource(config, self.store)
        self.directory = self.root.getDirectory()
        self.receiver = MailReceiver(self.store, self.directory)
        self.retriever = MailRetriever(self.store, self.directory,
            ConfigDict({
                "Type" : "pop",
                "UseSSL" : False,
                "Server" : "example.com",
                "Port" : 123,
            })
        )

        def decorateTransaction(txn):
            txn._rootResource = self.root
            txn._mailRetriever = self.retriever

        self.store.callWithNewTransactions(decorateTransaction)
        module = getModule(__name__)
        self.dataPath = module.filePath.sibling("data")
예제 #17
0
    def makeService_Slave(self, options):
        #
        # Change default log level to "info" as its useful to have
        # that during startup
        #
        oldLogLevel = logLevelForNamespace(None)
        setLogLevelForNamespace(None, "info")

        additional = []
        if config.Scheduling.iMIP.Enabled:
            additional.append(("inbox", IMIPReplyInboxResource, [], "basic"))
        rootResource = getRootResource(config, additional)

        #
        # Configure the service
        #
        self.log_info("Setting up service")

        if config.ProcessType == "Slave":
            if config.ControlSocket:
                mode = "AF_UNIX"
                id = config.ControlSocket
                self.log_info("Logging via AF_UNIX: %s" % (id,))
            else:
                mode = "IF_INET"
                id = int(config.ControlPort)
                self.log_info("Logging via AF_INET: %d" % (id,))

            logObserver = AMPCommonAccessLoggingObserver(mode, id)

        elif config.ProcessType == "Single":
            # Make sure no old socket files are lying around.
            self.deleteStaleSocketFiles()

            logObserver = RotatingFileAccessLoggingObserver(
                config.AccessLogFile,
            )

        self.log_info("Configuring access log observer: %s" % (logObserver,))

        service = CalDAVService(logObserver)

        site = Site(rootResource)

        httpFactory = LimitingHTTPFactory(
            site,
            maxRequests=config.MaxRequests,
            maxAccepts=config.MaxAccepts,
            betweenRequestsTimeOut=config.IdleConnectionTimeOut,
            vary=True,
        )
        if config.RedirectHTTPToHTTPS:
            redirectFactory = LimitingHTTPFactory(
                SSLRedirectRequest,
                maxRequests=config.MaxRequests,
                maxAccepts=config.MaxAccepts,
                betweenRequestsTimeOut=config.IdleConnectionTimeOut,
                vary=True,
            )

        def updateFactory(configDict):
            httpFactory.maxRequests = configDict.MaxRequests
            httpFactory.maxAccepts = configDict.MaxAccepts
            if config.RedirectHTTPToHTTPS:
                redirectFactory.maxRequests = configDict.MaxRequests
                redirectFactory.maxAccepts = configDict.MaxAccepts

        config.addPostUpdateHooks((updateFactory,))

        if config.InheritFDs or config.InheritSSLFDs:
            # Inherit sockets to call accept() on them individually.

            for fd in config.InheritSSLFDs:
                fd = int(fd)

                try:
                    contextFactory = self.createContextFactory()
                except SSLError, e:
                    log.error("Unable to set up SSL context factory: %s" % (e,))
                else:
                    MaxAcceptSSLServer(
                        fd, httpFactory,
                        contextFactory,
                        backlog=config.ListenBacklog,
                        inherit=True
                    ).setServiceParent(service)

            for fd in config.InheritFDs:
                fd = int(fd)

                if config.RedirectHTTPToHTTPS:
                    self.log_info("Redirecting to HTTPS port %s" % (config.SSLPort,))
                    useFactory = redirectFactory
                else:
                    useFactory = httpFactory

                MaxAcceptTCPServer(
                    fd, useFactory,
                    backlog=config.ListenBacklog,
                    inherit=True
                ).setServiceParent(service)
예제 #18
0
    def processInboxItems(self):
        """
        When data is migrated from a non-implicit scheduling server there can
        be inbox items that clients have not yet processed.  This method
        runs those inbox items through the implicit scheduling mechanism.
        """

        inboxItemsList = os.path.join(self.config.DataRoot, INBOX_ITEMS)
        if os.path.exists(inboxItemsList):

            log.info("Starting inbox item processing.")

            root = getRootResource(self.config, self.store)
            directory = root.getDirectory()
            principalCollection = directory.principalCollection

            inboxItems = set()
            with open(inboxItemsList) as input:
                for inboxItem in input:
                    inboxItem = inboxItem.strip()
                    inboxItems.add(inboxItem)

            try:
                itemsToProcess = list(inboxItems)
                totalItems = len(itemsToProcess)
                ignoreUUIDs = set()
                for ctr, inboxItem in enumerate(itemsToProcess):
                    log.info("Processing %d/%d inbox item: %s" % (ctr + 1, totalItems, inboxItem,))
                    ignore, uuid, ignore, fileName = inboxItem.rsplit("/", 3)

                    if uuid in ignoreUUIDs:
                        log.debug("Ignored inbox item - uuid ignored: %s" % (inboxItem,))
                        inboxItems.remove(inboxItem)
                        continue

                    record = yield directory.recordWithUID(uuid)
                    if record is None:
                        log.debug("Ignored inbox item - no record: %s" % (inboxItem,))
                        inboxItems.remove(inboxItem)
                        ignoreUUIDs.add(uuid)
                        continue

                    principal = yield principalCollection.principalForRecord(record)
                    if principal is None or not isinstance(principal, DirectoryCalendarPrincipalResource):
                        log.debug("Ignored inbox item - no principal: %s" % (inboxItem,))
                        inboxItems.remove(inboxItem)
                        ignoreUUIDs.add(uuid)
                        continue

                    request = FakeRequest(root, "PUT", None)
                    request.noAttendeeRefresh = True  # tell scheduling to skip refresh
                    request.checkedSACL = True
                    request.authnUser = request.authzUser = principal

                    # The request may end up with an associated transaction and we must make sure that is
                    # either committed or aborted, so use try/finally to handle that case.
                    txnCommitted = False
                    try:
                        calendarHome = yield principal.calendarHome(request)
                        if calendarHome is None:
                            log.debug("Ignored inbox item - no calendar home: %s" % (inboxItem,))
                            inboxItems.remove(inboxItem)
                            ignoreUUIDs.add(uuid)
                            continue

                        inbox = yield calendarHome.getChild("inbox")
                        if inbox is not None and inbox.exists():

                            inboxItemResource = yield inbox.getChild(fileName)
                            if inboxItemResource is not None and inboxItemResource.exists():

                                uri = "/calendars/__uids__/%s/inbox/%s" % (uuid, fileName)
                                request.path = uri
                                request._rememberResource(inboxItemResource, uri)

                                try:
                                    txnCommitted = yield self.processInboxItem(
                                        root,
                                        directory,
                                        principal,
                                        request,
                                        inbox,
                                        inboxItemResource,
                                        uuid,
                                        uri
                                    )
                                except Exception, e:
                                    log.error(
                                        "Error processing inbox item: %s (%s)"
                                        % (inboxItem, e)
                                    )
                            else:
                                log.debug("Ignored inbox item - no resource: %s" % (inboxItem,))
                        else:
                            log.debug("Ignored inbox item - no inbox: %s" % (inboxItem,))

                        inboxItems.remove(inboxItem)

                    finally:
                        if not txnCommitted and hasattr(request, "_newStoreTransaction"):
                            request._newStoreTransaction.abort()
예제 #19
0
    def setUp(self):
        super(PurgeOldEventsTestCase, self).setUp()

        config.DirectoryService.params['xmlFile'] = os.path.join(os.path.dirname(__file__), "purge", "accounts.xml")
        self.rootResource = getRootResource(config)
        self.directory = self.rootResource.getDirectory()
예제 #20
0
    def processInboxItems(self):
        """
        When data is migrated from a non-implicit scheduling server there can
        be inbox items that clients have not yet processed.  This method
        runs those inbox items through the implicit scheduling mechanism.
        """

        inboxItemsList = os.path.join(self.config.DataRoot, INBOX_ITEMS)
        if os.path.exists(inboxItemsList):

            log.info("Starting inbox item processing.")

            root = getRootResource(self.config, self.store)
            directory = root.getDirectory()
            principalCollection = directory.principalCollection

            inboxItems = set()
            with open(inboxItemsList) as input:
                for inboxItem in input:
                    inboxItem = inboxItem.strip()
                    inboxItems.add(inboxItem)

            try:
                itemsToProcess = list(inboxItems)
                totalItems = len(itemsToProcess)
                ignoreUUIDs = set()
                for ctr, inboxItem in enumerate(itemsToProcess):
                    log.info("Processing %d/%d inbox item: %s" % (ctr + 1, totalItems, inboxItem,))
                    ignore, uuid, ignore, fileName = inboxItem.rsplit("/", 3)

                    if uuid in ignoreUUIDs:
                        log.debug("Ignored inbox item - uuid ignored: %s" % (inboxItem,))
                        inboxItems.remove(inboxItem)
                        continue

                    record = directory.recordWithUID(uuid)
                    if record is None:
                        log.debug("Ignored inbox item - no record: %s" % (inboxItem,))
                        inboxItems.remove(inboxItem)
                        ignoreUUIDs.add(uuid)
                        continue

                    principal = principalCollection.principalForRecord(record)
                    if principal is None or not isinstance(principal, DirectoryCalendarPrincipalResource):
                        log.debug("Ignored inbox item - no principal: %s" % (inboxItem,))
                        inboxItems.remove(inboxItem)
                        ignoreUUIDs.add(uuid)
                        continue

                    request = FakeRequest(root, "PUT", None)
                    request.noAttendeeRefresh = True # tell scheduling to skip refresh
                    request.checkedSACL = True
                    request.authnUser = request.authzUser = element.Principal(
                        element.HRef.fromString("/principals/__uids__/%s/" % (uuid,))
                    )

                    # The request may end up with an associated transaction and we must make sure that is
                    # either committed or aborted, so use try/finally to handle that case.
                    txnCommitted = False
                    try:
                        calendarHome = yield principal.calendarHome(request)
                        if calendarHome is None:
                            log.debug("Ignored inbox item - no calendar home: %s" % (inboxItem,))
                            inboxItems.remove(inboxItem)
                            ignoreUUIDs.add(uuid)
                            continue

                        inbox = yield calendarHome.getChild("inbox")
                        if inbox is not None and inbox.exists():

                            inboxItemResource = yield inbox.getChild(fileName)
                            if inboxItemResource is not None and inboxItemResource.exists():

                                uri = "/calendars/__uids__/%s/inbox/%s" % (uuid, fileName)
                                request.path = uri
                                request._rememberResource(inboxItemResource, uri)

                                try:
                                    txnCommitted = yield self.processInboxItem(
                                        root,
                                        directory,
                                        principal,
                                        request,
                                        inbox,
                                        inboxItemResource,
                                        uuid,
                                        uri
                                    )
                                except Exception, e:
                                    log.error("Error processing inbox item: %s (%s)"
                                        % (inboxItem, e))
                            else:
                                log.debug("Ignored inbox item - no resource: %s" % (inboxItem,))
                        else:
                            log.debug("Ignored inbox item - no inbox: %s" % (inboxItem,))

                        inboxItems.remove(inboxItem)

                    finally:
                        if not txnCommitted and hasattr(request, "_newStoreTransaction"):
                            request._newStoreTransaction.abort()