class DPSClientSingleDirectoryTest(unittest.TestCase): """ Tests the client against a single directory service (as opposed to the augmented, aggregated structure you get from directoryFromConfig(), which is tested in the class below) """ def setUp(self): # The "local" directory service self.directory = DirectoryService(None) # The "remote" directory service if testMode == "xml": # Need a copy as it might change path = FilePath(os.path.join(os.path.dirname(__file__), "test.xml")) copy = FilePath(self.mktemp()) path.copyTo(copy) remoteDirectory = CalendarXMLDirectoryService(copy) elif testMode == "od": remoteDirectory = CalendarODDirectoryService() # Connect the two services directly via an IOPump client = AMP() server = DirectoryProxyAMPProtocol(remoteDirectory) pump = returnConnected(server, client) # Replace the normal _getConnection method with one that bypasses any # actual networking self.patch(self.directory, "_getConnection", lambda: succeed(client)) # Wrap the normal _sendCommand method with one that flushes the IOPump # afterwards origCall = self.directory._sendCommand def newCall(*args, **kwds): d = origCall(*args, **kwds) pump.flush() return d self.patch(self.directory, "_sendCommand", newCall) @inlineCallbacks def test_uid(self): record = (yield self.directory.recordWithUID(testUID)) self.assertTrue(testShortName in record.shortNames) @inlineCallbacks def test_shortName(self): record = (yield self.directory.recordWithShortName(RecordType.user, testShortName)) self.assertEquals(record.uid, testUID) @inlineCallbacks def test_guid(self): if testMode == "od": record = (yield self.directory.recordWithGUID(testUID)) self.assertTrue(testShortName in record.shortNames) @inlineCallbacks def test_recordType(self): if testMode != "od": records = (yield self.directory.recordsWithRecordType(RecordType.user)) self.assertEquals(len(records), 9) @inlineCallbacks def test_emailAddress(self): if testMode == "xml": records = (yield self.directory.recordsWithEmailAddress( u"*****@*****.**")) self.assertEquals(len(records), 1) self.assertEquals(records[0].shortNames, [u"cdaboo"]) @inlineCallbacks def test_recordsMatchingTokens(self): records = (yield self.directory.recordsMatchingTokens([u"anche"])) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_anyType(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), (u"fullNames", "morgen", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields(fields, operand=Operand.OR, recordType=None)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("sagen" in matchingShortNames) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_oneType(self): fields = ((u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields( fields, operand=Operand.OR, recordType=RecordType.user)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) # This location should *not* appear in the results self.assertFalse("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_unsupportedField(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), # This should be ignored: (u"foo", "bar", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields(fields, operand=Operand.OR, recordType=None)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_nonUnicode(self): fields = ((u"guid", uuid.UUID("A3B1158F-0564-4F5B-81E4-A89EA5FF81B0"), MatchFlags.caseInsensitive, MatchType.equals), ) records = (yield self.directory.recordsMatchingFields(fields, operand=Operand.OR, recordType=None)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertFalse("wsanchez" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_not(self): fields = ((u"fullNames", "anche", MatchFlags.NOT | MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields(fields, operand=Operand.OR, recordType=None)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("sagen" in matchingShortNames) self.assertTrue("dre" not in matchingShortNames) self.assertTrue("wsanchez" not in matchingShortNames) self.assertTrue("sanchezoffice" not in matchingShortNames) @inlineCallbacks def test_recordsFromMatchExpression(self): expression = MatchExpression(FieldName.uid, testUID, MatchType.equals, MatchFlags.none) records = yield self.directory.recordsFromExpression(expression) self.assertEquals(len(records), 1) test_recordsFromMatchExpression.todo = "Won't work until we can serialize expressions" @inlineCallbacks def test_members(self): group = yield self.directory.recordWithUID(u"__calendar-dev__") members = yield group.members() self.assertEquals(len(members), 5) @inlineCallbacks def test_groups(self): # No need to use group cacher as the XML service directly supports # groups() record = yield self.directory.recordWithUID(u"__sagen__") groups = yield record.groups() self.assertEquals(len(groups), 1) @inlineCallbacks def test_group_changes(self): group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 5) # Add new member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__cdaboo__") yield group.addMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 6) # Add existing member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__wsanchez__") yield group.addMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 6) # Remove existing member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__cdaboo__") yield group.removeMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 5) # Remove missing member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__cdaboo__") yield group.removeMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 5) @inlineCallbacks def test_verifyPlaintextPassword(self): expectations = ( (testPassword, True), # Correct ("wrong", False), # Incorrect ("wrong\xc3\xa5", False), # Incorrect ) record = (yield self.directory.recordWithShortName(RecordType.user, testShortName)) for password, answer in expectations: authenticated = (yield record.verifyPlaintextPassword(password)) self.assertEquals(authenticated, answer) @inlineCallbacks def test_verifyHTTPDigest(self): expectations = ( (testPassword, True), # Correct ("wrong", False) # Incorrect ) record = (yield self.directory.recordWithShortName(RecordType.user, testShortName)) realm = "host.example.com" nonce = "128446648710842461101646794502" algorithm = "md5" uri = "http://host.example.com" method = "GET" for password, answer in expectations: for qop, nc, cnonce in ( ("", "", ""), ("auth", "00000001", "/rrD6TqPA3lHRmg+fw/vyU6oWoQgzK7h9yWrsCmv/lE="), ): response = calcResponse( calcHA1(algorithm, testShortName, realm, password, nonce, cnonce), calcHA2(algorithm, method, uri, qop, None), algorithm, nonce, nc, cnonce, qop) authenticated = (yield record.verifyHTTPDigest( testShortName, realm, uri, nonce, cnonce, algorithm, nc, qop, response, method)) self.assertEquals(authenticated, answer)
class DPSClientSingleDirectoryTest(unittest.TestCase): """ Tests the client against a single directory service (as opposed to the augmented, aggregated structure you get from directoryFromConfig(), which is tested in the class below) """ def setUp(self): # The "local" directory service self.directory = DirectoryService(None) # The "remote" directory service if testMode == "xml": # Need a copy as it might change path = FilePath(os.path.join(os.path.dirname(__file__), "test.xml")) copy = FilePath(self.mktemp()) path.copyTo(copy) remoteDirectory = CalendarXMLDirectoryService(copy) elif testMode == "od": remoteDirectory = CalendarODDirectoryService() # Connect the two services directly via an IOPump client = AMP() server = DirectoryProxyAMPProtocol(remoteDirectory) pump = returnConnected(server, client) # Replace the normal _getConnection method with one that bypasses any # actual networking self.patch(self.directory, "_getConnection", lambda: succeed(client)) # Wrap the normal _sendCommand method with one that flushes the IOPump # afterwards origCall = self.directory._sendCommand def newCall(*args, **kwds): d = origCall(*args, **kwds) pump.flush() return d self.patch(self.directory, "_sendCommand", newCall) @inlineCallbacks def test_uid(self): record = (yield self.directory.recordWithUID(testUID)) self.assertTrue(testShortName in record.shortNames) @inlineCallbacks def test_shortName(self): record = (yield self.directory.recordWithShortName( RecordType.user, testShortName )) self.assertEquals(record.uid, testUID) @inlineCallbacks def test_guid(self): if testMode == "od": record = (yield self.directory.recordWithGUID(testUID)) self.assertTrue(testShortName in record.shortNames) @inlineCallbacks def test_recordType(self): if testMode != "od": records = (yield self.directory.recordsWithRecordType( RecordType.user )) self.assertEquals(len(records), 9) @inlineCallbacks def test_emailAddress(self): if testMode == "xml": records = (yield self.directory.recordsWithEmailAddress( u"*****@*****.**" )) self.assertEquals(len(records), 1) self.assertEquals(records[0].shortNames, [u"cdaboo"]) @inlineCallbacks def test_recordsMatchingTokens(self): records = (yield self.directory.recordsMatchingTokens( [u"anche"] )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_anyType(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), (u"fullNames", "morgen", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields( fields, operand=Operand.OR, recordType=None )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("sagen" in matchingShortNames) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_oneType(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields( fields, operand=Operand.OR, recordType=RecordType.user )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) # This location should *not* appear in the results self.assertFalse("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_unsupportedField(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), # This should be ignored: (u"foo", "bar", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.directory.recordsMatchingFields( fields, operand=Operand.OR, recordType=None )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_nonUnicode(self): fields = ( (u"guid", uuid.UUID("A3B1158F-0564-4F5B-81E4-A89EA5FF81B0"), MatchFlags.caseInsensitive, MatchType.equals), ) records = (yield self.directory.recordsMatchingFields( fields, operand=Operand.OR, recordType=None )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertFalse("wsanchez" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_not(self): fields = ( ( u"fullNames", "anche", MatchFlags.NOT | MatchFlags.caseInsensitive, MatchType.contains ), ) records = (yield self.directory.recordsMatchingFields( fields, operand=Operand.OR, recordType=None )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("sagen" in matchingShortNames) self.assertTrue("dre" not in matchingShortNames) self.assertTrue("wsanchez" not in matchingShortNames) self.assertTrue("sanchezoffice" not in matchingShortNames) @inlineCallbacks def test_recordsFromMatchExpression(self): expression = MatchExpression( FieldName.uid, testUID, MatchType.equals, MatchFlags.none ) records = yield self.directory.recordsFromExpression(expression) self.assertEquals(len(records), 1) test_recordsFromMatchExpression.todo = "Won't work until we can serialize expressions" @inlineCallbacks def test_members(self): group = yield self.directory.recordWithUID(u"__calendar-dev__") members = yield group.members() self.assertEquals(len(members), 5) @inlineCallbacks def test_groups(self): # No need to use group cacher as the XML service directly supports # groups() record = yield self.directory.recordWithUID(u"__sagen__") groups = yield record.groups() self.assertEquals(len(groups), 1) @inlineCallbacks def test_group_changes(self): group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 5) # Add new member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__cdaboo__") yield group.addMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 6) # Add existing member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__wsanchez__") yield group.addMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 6) # Remove existing member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__cdaboo__") yield group.removeMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 5) # Remove missing member group = yield self.directory.recordWithUID(u"__twisted__") user = yield self.directory.recordWithUID(u"__cdaboo__") yield group.removeMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__twisted__") members = yield group.members() self.assertEquals(len(members), 5) @inlineCallbacks def test_verifyPlaintextPassword(self): expectations = ( (testPassword, True), # Correct ("wrong", False) # Incorrect ) record = ( yield self.directory.recordWithShortName( RecordType.user, testShortName ) ) for password, answer in expectations: authenticated = (yield record.verifyPlaintextPassword(password)) self.assertEquals(authenticated, answer) @inlineCallbacks def test_verifyHTTPDigest(self): expectations = ( (testPassword, True), # Correct ("wrong", False) # Incorrect ) record = ( yield self.directory.recordWithShortName( RecordType.user, testShortName ) ) realm = "host.example.com" nonce = "128446648710842461101646794502" algorithm = "md5" uri = "http://host.example.com" method = "GET" for password, answer in expectations: for qop, nc, cnonce in ( ("", "", ""), ("auth", "00000001", "/rrD6TqPA3lHRmg+fw/vyU6oWoQgzK7h9yWrsCmv/lE="), ): response = calcResponse( calcHA1(algorithm, testShortName, realm, password, nonce, cnonce), calcHA2(algorithm, method, uri, qop, None), algorithm, nonce, nc, cnonce, qop) authenticated = ( yield record.verifyHTTPDigest( testShortName, realm, uri, nonce, cnonce, algorithm, nc, qop, response, method ) ) self.assertEquals(authenticated, answer)
class DPSClientAugmentedAggregateDirectoryTest(StoreTestCase): """ Similar to the above tests, but in the context of the directory structure that directoryFromConfig() returns """ wsanchezUID = u"6423F94A-6B76-4A3A-815B-D52CFD77935D" @inlineCallbacks def setUp(self): yield super(DPSClientAugmentedAggregateDirectoryTest, self).setUp() # The "local" directory service self.client = DirectoryService(None) # The "remote" directory service remoteDirectory = self.directory # Connect the two services directly via an IOPump client = AMP() server = DirectoryProxyAMPProtocol(remoteDirectory) pump = returnConnected(server, client) # Replace the normal _getConnection method with one that bypasses any # actual networking self.patch(self.client, "_getConnection", lambda: succeed(client)) # Wrap the normal _sendCommand method with one that flushes the IOPump # afterwards origCall = self.client._sendCommand def newCall(*args, **kwds): d = origCall(*args, **kwds) pump.flush() return d self.patch(self.client, "_sendCommand", newCall) def configure(self): """ Override configuration hook to turn on wiki. """ super(DPSClientAugmentedAggregateDirectoryTest, self).configure() self.patch(config.Authentication.Wiki, "Enabled", True) @inlineCallbacks def test_setAutoScheduleMode(self): """ Verify setAutoSchedule works across DPS """ record = yield self.client.recordWithUID( u"75EA36BE-F71B-40F9-81F9-CF59BF40CA8F") # Defaults to automatic self.assertEquals(record.autoScheduleMode, AutoScheduleMode.acceptIfFreeDeclineIfBusy) # Change it to accept-if-busy yield record.setAutoScheduleMode(AutoScheduleMode.acceptIfFree) # Refetch it record = yield self.client.recordWithUID( u"75EA36BE-F71B-40F9-81F9-CF59BF40CA8F") # Verify it's changed self.assertEquals(record.autoScheduleMode, AutoScheduleMode.acceptIfFree) @inlineCallbacks def test_uid(self): record = (yield self.client.recordWithUID(self.wsanchezUID)) self.assertTrue(u"wsanchez" in record.shortNames) @inlineCallbacks def test_shortName(self): record = (yield self.client.recordWithShortName(RecordType.user, u"wsanchez")) self.assertEquals(record.uid, self.wsanchezUID) @inlineCallbacks def test_guid(self): record = yield self.client.recordWithGUID(self.wsanchezUID) self.assertTrue(u"wsanchez" in record.shortNames) @inlineCallbacks def test_recordType(self): records = (yield self.client.recordsWithRecordType(RecordType.user)) self.assertEquals(len(records), 244) @inlineCallbacks def test_emailAddress(self): records = ( yield self.client.recordsWithEmailAddress(u"*****@*****.**")) self.assertEquals(len(records), 1) self.assertEquals(records[0].shortNames, [u"wsanchez"]) @inlineCallbacks def test_recordsMatchingTokens(self): records = (yield self.client.recordsMatchingTokens([u"anche"])) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) @inlineCallbacks def test_recordsMatchingTokensWithContext(self): testData = [ # ( # tokens, # context, # short names expected to be in results, # short names not expected to be in results # ), ( [u"an"], "user", # just users (u"dre", u"wsanchez"), (u"transporter", u"managers"), ), ( [u"an"], "group", # just groups (u"managers", ), (u"dre", u"wsanchez", u"transporter"), ), ( [u"an"], "location", # just locations (u"sanchezoffice", ), (u"dre", u"wsanchez", u"transporter", u"managers"), ), ( [u"an"], "resource", # just resources (u"transporter", u"ftlcpu"), (u"dre", u"wsanchez", u"managers", u"sanchezoffice"), ), ( [u"an"], "attendee", # just users, groups, resources (u"dre", u"wsanchez", u"managers", u"transporter", u"ftlcpu"), (u"sanchezoffice", ), ), ( [u"an"], None, # any type (u"dre", u"wsanchez", u"managers", u"sanchezoffice", u"transporter", u"ftlcpu"), (), ), ] for tokens, context, expected, unexpected in testData: # print("Tokens", tokens, "context", context) records = yield self.directory.recordsMatchingTokens( tokens, context) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) for name in expected: self.assertTrue(name in matchingShortNames) for name in unexpected: self.assertFalse(name in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_anyType(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), (u"fullNames", "morgen", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.client.recordsMatchingFields(fields, operand=Operand.OR, recordType=None)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("sagen" in matchingShortNames) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_oneType(self): fields = ((u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.client.recordsMatchingFields( fields, operand=Operand.OR, recordType=RecordType.user)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) # This location should *not* appear in the results self.assertFalse("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_unsupportedField(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), # This should be ignored: (u"foo", "bar", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.client.recordsMatchingFields(fields, operand=Operand.OR, recordType=None)) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsFromMatchExpression(self): expression = MatchExpression(FieldName.uid, u"wsanchez", MatchType.equals, MatchFlags.none) records = yield self.client.recordsFromExpression(expression) self.assertEquals(len(records), 1) test_recordsFromMatchExpression.todo = "Won't work until we can serialize expressions" @inlineCallbacks def test_members(self): group = yield self.client.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) group = yield self.client.recordWithUID(u"emptygroup") members = yield group.members() self.assertEquals(len(members), 0) @inlineCallbacks def test_expandedMemberUIDs(self): group = yield self.client.recordWithUID(u"__top_group_1__") memberUIDs = yield group.expandedMemberUIDs() self.assertEquals( set(memberUIDs), set([ u'__wsanchez1__', u'__cdaboo1__', u'__glyph1__', u'__sagen1__' ])) @inlineCallbacks def test_groups(self): # A group must first be "refreshed" into the DB otherwise we won't # consider it for group memberships txn = self.store.newTransaction() groupCacher = GroupCacher(self.directory) yield groupCacher.refreshGroup(txn, u"__sub_group_1__") yield txn.commit() # record = yield self.client.recordWithUID(u"__sagen1__") # FIXME: this call hangs during unit tests, but not in a real server: # groups = yield record.groups() # self.assertEquals(len(groups), 1) test_groups.todo = "Figure out why this hangs" @inlineCallbacks def test_group_changes(self): group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) # Add new member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__cdaboo1__") yield group.addMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 4) # Add existing member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__wsanchez1__") yield group.addMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 4) # Remove existing member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__cdaboo1__") yield group.removeMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) # Remove missing member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__cdaboo1__") yield group.removeMembers((user, )) yield self.directory.updateRecords((group, ), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) @inlineCallbacks def test_verifyPlaintextPassword(self): expectations = ( (u"zehcnasw", True), # Correct ("wrong", False) # Incorrect ) record = (yield self.client.recordWithShortName(RecordType.user, u"wsanchez")) for password, answer in expectations: authenticated = (yield record.verifyPlaintextPassword(password)) self.assertEquals(authenticated, answer) @inlineCallbacks def test_verifyHTTPDigest(self): expectations = ( (u"zehcnasw", True), # Correct ("wrong", False) # Incorrect ) record = (yield self.client.recordWithShortName(RecordType.user, u"wsanchez")) realm = "host.example.com" nonce = "128446648710842461101646794502" algorithm = "md5" uri = "http://host.example.com" method = "GET" for password, answer in expectations: for qop, nc, cnonce in ( ("", "", ""), ("auth", "00000001", "/rrD6TqPA3lHRmg+fw/vyU6oWoQgzK7h9yWrsCmv/lE="), ): response = calcResponse( calcHA1(algorithm, u"wsanchez", realm, password, nonce, cnonce), calcHA2(algorithm, method, uri, qop, None), algorithm, nonce, nc, cnonce, qop) authenticated = (yield record.verifyHTTPDigest( u"wsanchez", realm, uri, nonce, cnonce, algorithm, nc, qop, response, method)) self.assertEquals(authenticated, answer)
class DPSClientAugmentedAggregateDirectoryTest(StoreTestCase): """ Similar to the above tests, but in the context of the directory structure that directoryFromConfig() returns """ wsanchezUID = u"6423F94A-6B76-4A3A-815B-D52CFD77935D" @inlineCallbacks def setUp(self): yield super(DPSClientAugmentedAggregateDirectoryTest, self).setUp() # The "local" directory service self.client = DirectoryService(None) # The "remote" directory service remoteDirectory = self.directory # Connect the two services directly via an IOPump client = AMP() server = DirectoryProxyAMPProtocol(remoteDirectory) pump = returnConnected(server, client) # Replace the normal _getConnection method with one that bypasses any # actual networking self.patch(self.client, "_getConnection", lambda: succeed(client)) # Wrap the normal _sendCommand method with one that flushes the IOPump # afterwards origCall = self.client._sendCommand def newCall(*args, **kwds): d = origCall(*args, **kwds) pump.flush() return d self.patch(self.client, "_sendCommand", newCall) def configure(self): """ Override configuration hook to turn on wiki. """ super(DPSClientAugmentedAggregateDirectoryTest, self).configure() self.patch(config.Authentication.Wiki, "Enabled", True) @inlineCallbacks def test_uid(self): record = (yield self.client.recordWithUID(self.wsanchezUID)) self.assertTrue(u"wsanchez" in record.shortNames) @inlineCallbacks def test_shortName(self): record = (yield self.client.recordWithShortName( RecordType.user, u"wsanchez" )) self.assertEquals(record.uid, self.wsanchezUID) @inlineCallbacks def test_guid(self): record = yield self.client.recordWithGUID(self.wsanchezUID) self.assertTrue(u"wsanchez" in record.shortNames) @inlineCallbacks def test_recordType(self): records = (yield self.client.recordsWithRecordType( RecordType.user )) self.assertEquals(len(records), 244) @inlineCallbacks def test_emailAddress(self): records = (yield self.client.recordsWithEmailAddress( u"*****@*****.**" )) self.assertEquals(len(records), 1) self.assertEquals(records[0].shortNames, [u"wsanchez"]) @inlineCallbacks def test_recordsMatchingTokens(self): records = (yield self.client.recordsMatchingTokens( [u"anche"] )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) @inlineCallbacks def test_recordsMatchingTokensWithContext(self): testData = [ # ( # tokens, # context, # short names expected to be in results, # short names not expected to be in results # ), ( [u"an"], "user", # just users (u"dre", u"wsanchez"), (u"transporter", u"managers"), ), ( [u"an"], "group", # just groups (u"managers",), (u"dre", u"wsanchez", u"transporter"), ), ( [u"an"], "location", # just locations (u"sanchezoffice",), (u"dre", u"wsanchez", u"transporter", u"managers"), ), ( [u"an"], "resource", # just resources (u"transporter", u"ftlcpu"), (u"dre", u"wsanchez", u"managers", u"sanchezoffice"), ), ( [u"an"], "attendee", # just users, groups, resources ( u"dre", u"wsanchez", u"managers", u"transporter", u"ftlcpu" ), (u"sanchezoffice",), ), ( [u"an"], None, # any type ( u"dre", u"wsanchez", u"managers", u"sanchezoffice", u"transporter", u"ftlcpu" ), (), ), ] for tokens, context, expected, unexpected in testData: # print("Tokens", tokens, "context", context) records = yield self.directory.recordsMatchingTokens( tokens, context ) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) for name in expected: self.assertTrue(name in matchingShortNames) for name in unexpected: self.assertFalse(name in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_anyType(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), (u"fullNames", "morgen", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.client.recordsMatchingFields( fields, operand=Operand.OR, recordType=None )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("sagen" in matchingShortNames) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_oneType(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.client.recordsMatchingFields( fields, operand=Operand.OR, recordType=RecordType.user )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) # This location should *not* appear in the results self.assertFalse("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsMatchingFields_unsupportedField(self): fields = ( (u"fullNames", "anche", MatchFlags.caseInsensitive, MatchType.contains), # This should be ignored: (u"foo", "bar", MatchFlags.caseInsensitive, MatchType.contains), ) records = (yield self.client.recordsMatchingFields( fields, operand=Operand.OR, recordType=None )) matchingShortNames = set() for r in records: for shortName in r.shortNames: matchingShortNames.add(shortName) self.assertTrue("dre" in matchingShortNames) self.assertTrue("wsanchez" in matchingShortNames) self.assertTrue("sanchezoffice" in matchingShortNames) @inlineCallbacks def test_recordsFromMatchExpression(self): expression = MatchExpression( FieldName.uid, u"wsanchez", MatchType.equals, MatchFlags.none ) records = yield self.client.recordsFromExpression(expression) self.assertEquals(len(records), 1) test_recordsFromMatchExpression.todo = "Won't work until we can serialize expressions" @inlineCallbacks def test_members(self): group = yield self.client.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) group = yield self.client.recordWithUID(u"emptygroup") members = yield group.members() self.assertEquals(len(members), 0) @inlineCallbacks def test_expandedMemberUIDs(self): group = yield self.client.recordWithUID(u"__top_group_1__") memberUIDs = yield group.expandedMemberUIDs() self.assertEquals( set(memberUIDs), set( [u'__wsanchez1__', u'__cdaboo1__', u'__glyph1__', u'__sagen1__'] ) ) @inlineCallbacks def test_groups(self): # A group must first be "refreshed" into the DB otherwise we won't # consider it for group memberships txn = self.store.newTransaction() groupCacher = GroupCacher(self.directory) yield groupCacher.refreshGroup(txn, u"__sub_group_1__") yield txn.commit() # record = yield self.client.recordWithUID(u"__sagen1__") # FIXME: this call hangs during unit tests, but not in a real server: # groups = yield record.groups() # self.assertEquals(len(groups), 1) test_groups.todo = "Figure out why this hangs" @inlineCallbacks def test_group_changes(self): group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) # Add new member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__cdaboo1__") yield group.addMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 4) # Add existing member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__wsanchez1__") yield group.addMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 4) # Remove existing member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__cdaboo1__") yield group.removeMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) # Remove missing member group = yield self.directory.recordWithUID(u"__top_group_1__") user = yield self.directory.recordWithUID(u"__cdaboo1__") yield group.removeMembers((user,)) yield self.directory.updateRecords((group,), False) group = yield self.directory.recordWithUID(u"__top_group_1__") members = yield group.members() self.assertEquals(len(members), 3) @inlineCallbacks def test_verifyPlaintextPassword(self): expectations = ( (u"zehcnasw", True), # Correct ("wrong", False) # Incorrect ) record = ( yield self.client.recordWithShortName( RecordType.user, u"wsanchez" ) ) for password, answer in expectations: authenticated = (yield record.verifyPlaintextPassword(password)) self.assertEquals(authenticated, answer) @inlineCallbacks def test_verifyHTTPDigest(self): expectations = ( (u"zehcnasw", True), # Correct ("wrong", False) # Incorrect ) record = ( yield self.client.recordWithShortName( RecordType.user, u"wsanchez" ) ) realm = "host.example.com" nonce = "128446648710842461101646794502" algorithm = "md5" uri = "http://host.example.com" method = "GET" for password, answer in expectations: for qop, nc, cnonce in ( ("", "", ""), ("auth", "00000001", "/rrD6TqPA3lHRmg+fw/vyU6oWoQgzK7h9yWrsCmv/lE="), ): response = calcResponse( calcHA1(algorithm, u"wsanchez", realm, password, nonce, cnonce), calcHA2(algorithm, method, uri, qop, None), algorithm, nonce, nc, cnonce, qop) authenticated = ( yield record.verifyHTTPDigest( u"wsanchez", realm, uri, nonce, cnonce, algorithm, nc, qop, response, method ) ) self.assertEquals(authenticated, answer)