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)
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()
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()
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)
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())
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()
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()
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
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
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)
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)
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
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
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")
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)
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()
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()
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()