def test_delete_user_bans(self): user_id_bytes = uuid.uuid4().bytes user_id = base64_url_encode(uuid.uuid4().bytes) # by id ban1 = self.bans.create_ban(user_id=user_id) ban2 = self.bans.create_ban(user_id=user_id) self.assertIsNotNone(self.bans.get_ban(ban1.id)) self.assertIsNotNone(self.bans.get_ban(ban2.id)) self.bans.delete_user_bans(user_id) self.assertIsNone(self.bans.get_ban(ban1.id)) self.assertIsNone(self.bans.get_ban(ban2.id)) # by id_bytes ban1 = self.bans.create_ban(user_id=user_id) ban2 = self.bans.create_ban(user_id=user_id) self.assertIsNotNone(self.bans.get_ban(ban1.id)) self.assertIsNotNone(self.bans.get_ban(ban2.id)) self.bans.delete_user_bans(user_id) self.assertIsNone(self.bans.get_ban(ban1.id)) self.assertIsNone(self.bans.get_ban(ban2.id)) self.assert_invalid_id_raises(self.bans.delete_user_bans)
def generate_or_parse_id(id): if not id: id_bytes = uuid.uuid4().bytes id = base64_url_encode(id_bytes) else: id, id_bytes = parse_id(id) return (id, id_bytes)
def setUp(self): if db_url: engine = create_engine(db_url) else: engine = create_engine('sqlite:///:memory:') self.bans = Bans( engine, install=True, db_prefix=base64_url_encode(uuid.uuid4().bytes), )
def parse_id(id): if isinstance(id, bytes): id_bytes = id id = base64_url_encode(id) elif isinstance(id, str): if re.compile(r'[^a-zA-Z0-9_\-]').search(id): raise ValueError('String contained non-base64_url characters') id_bytes = base64_url_decode(id) else: raise TypeError return (id, id_bytes)
def test_update_ban(self): # update_ban instantiates a Ban object so anything that raises in # test_ban_class_create_get_and_defaults should raise ban = self.bans.create_ban() # update_ban can receive a base64_url string properties = { 'creation_time': 1111111111, 'remote_origin': ip_address('1.2.3.4'), 'scope': 'scope1', 'reason': 'Reason1', 'note': 'note1', 'expiration_time': 2222222222, 'view_time': 1234567890, 'user_id': base64_url_encode(uuid.uuid4().bytes), 'created_by_user_id': base64_url_encode(uuid.uuid4().bytes), } self.bans.update_ban(ban.id, **properties) ban = self.bans.get_ban(ban.id_bytes) for key, value in properties.items(): self.assertEqual(getattr(ban, key), value) # update_ban can receive bytes-like properties = { 'creation_time': 2222222222, 'remote_origin': ip_address('2.3.4.5'), 'scope': 'scope2', 'reason': 'Reason2', 'note': 'note2', 'expiration_time': 3456789012, 'view_time': 2345678901, 'user_id': base64_url_encode(uuid.uuid4().bytes), 'created_by_user_id': base64_url_encode(uuid.uuid4().bytes), } self.bans.update_ban(ban.id_bytes, **properties) ban = self.bans.get_ban(ban.id_bytes) for key, value in properties.items(): self.assertEqual(getattr(ban, key), value) self.assert_invalid_id_raises(self.bans.update_ban)
def id_property(self, class_name, create, property): # id can be specified from bytes-like expected_id_bytes = uuid.uuid4().bytes expected_id = base64_url_encode(expected_id_bytes) # instantiate directly instance = class_name(**{property: expected_id_bytes}) instance_id_bytes = getattr(instance, property + '_bytes') instance_id = getattr(instance, property) self.assertEqual(expected_id_bytes, instance_id_bytes) self.assertEqual(expected_id, instance_id) # create in db object = create(**{property: expected_id_bytes}) object_id_bytes = getattr(object, property + '_bytes') object_id = getattr(object, property) self.assertEqual(expected_id_bytes, object_id_bytes) self.assertEqual(expected_id, object_id) # id can be specified from a base64_url string expected_id_bytes = uuid.uuid4().bytes expected_id = base64_url_encode(expected_id_bytes) # instantiate directly instance = class_name(**{property: expected_id}) instance_id_bytes = getattr(instance, property + '_bytes') instance_id = getattr(instance, property) self.assertEqual(expected_id_bytes, instance_id_bytes) self.assertEqual(expected_id, instance_id) # create in db object = create(**{property: expected_id}) object_id_bytes = getattr(object, property + '_bytes') object_id = getattr(object, property) self.assertEqual(expected_id_bytes, object_id_bytes) self.assertEqual(expected_id, object_id) self.assert_invalid_id_raises( lambda input: class_name(**{property: input}) ) self.assert_invalid_id_raises( lambda input: create(**{property: input}) )
def register_local( self, account_name, passphrase, passphrase_confirmation, remote_origin, useragent, ): errors = [] if not account_name: errors.append('Missing account name') else: account_name_bytes = account_name.encode() account_name_hash = base64_url_encode( hashlib.sha256(account_name_bytes).digest() ) authentications = self.search_authentications( filter={'values': account_name_hash + ';%'} ) if 0 < len(authentications.items()): self.access_log.create_log( scope='authentication_collision', ) errors.append('Account name unavailable') if not passphrase: errors.append('Missing passphrase') else: if self.config['minimum_pass_length'] > len(passphrase): errors.append( 'Passphrase must be at least {} characters'.format( str(self.config['minimum_pass_length']) ) ) elif not passphrase_confirmation: errors.append('Missing passphrase confirmation') elif passphrase != passphrase_confirmation: errors.append('Passphrase and confirmation did not match') if errors: return errors value = account_name_hash + ';' + pass_context.hash(passphrase) try: self.register('local', value, remote_origin, useragent) except ValueError as e: return [str(e)] return []
def test_parse_id(self): for invalid_input in [ 'contains non base64_url characters $%^~', ['list'], {'dict': 'ionary'}, ]: with self.assertRaises(Exception): id, id_bytes = parse_id(invalid_input) expected_bytes = uuid.uuid4().bytes expected_string = base64_url_encode(expected_bytes) # from bytes id, id_bytes = parse_id(expected_bytes) self.assertEqual(id_bytes, expected_bytes) self.assertEqual(id, expected_string) # from string id, id_bytes = parse_id(expected_string) self.assertEqual(id, expected_string) self.assertEqual(id_bytes, expected_bytes)
def test_anonymize_user(self): user_id = base64_url_encode(uuid.uuid4().bytes) ban = self.bans.create_ban(user_id=user_id) self.assertIsNotNone(self.bans.get_ban(ban.id)) self.assertEqual(user_id, self.bans.get_ban(ban.id).user_id) new_id_bytes = self.bans.anonymize_user(user_id) self.assertEqual(0, self.bans.count_bans(filter={'user_ids': user_id})) # assert bans still exist, but with the new user id self.assertIsNotNone( self.bans.search_bans(filter={'user_ids': new_id_bytes}) ) self.assertEqual( 1, self.bans.count_bans(filter={'user_ids': new_id_bytes}), ) self.assertNotEqual(user_id, self.bans.get_ban(ban.id).user_id)
def sign_in_local(self, account_name, passphrase, remote_origin, useragent): errors = [] if not account_name: errors.append('Missing account name') if not passphrase: errors.append('Missing passphrase') if errors: return errors account_name_bytes = account_name.encode() account_name_hash = base64_url_encode( hashlib.sha256(account_name_bytes).digest() ) authentications = self.search_authentications( filter={'values': account_name_hash + ';%'} ) if not authentications.values(): self.access_log.create_log(scope='sign_in_attempt') self.access_log.create_log( scope='sign_in_failure_account_name_not_found', ) return ['Incorrect account name or passphrase'] authentication = authentications.values()[0] pass_hash = authentication.value.split(';')[1] if not pass_context.verify( passphrase, pass_hash, ): self.access_log.create_log(scope='sign_in_attempt') self.access_log.create_log(scope='sign_in_failure_incorrect_pass') return ['Incorrect account name or passphrase'] self.sign_in(authentication.user, remote_origin, useragent) return []
def test_update_medium(self): # update_medium instantiates a Medium object so anything that raises in # test_medium_class_create_get_and_defaults should raise medium = self.media.create_medium() user1_id = base64_url_encode(uuid.uuid4().bytes) user2_id = base64_url_encode(uuid.uuid4().bytes) # update_medium can receive a base64_url string properties = { 'upload_time': 1000000000, 'creation_time': 1111111111, 'touch_time': 1234567890, 'uploader_remote_origin': ip_address('1.2.3.4'), 'uploader_id': user1_id, 'owner_id': user1_id, 'status': MediumStatus.COPYRIGHT, 'protection': MediumProtection.GROUPS, 'searchability': MediumSearchability.PUBLIC, 'group_bits': int(1).to_bytes(2, 'big'), 'mime': 'test1', 'size': 1000, 'data1': 1, 'data2': 2, 'data3': 3, 'data4': 4, 'data5': 5, 'data6': 6, } self.media.update_medium(medium.id, **properties) medium = self.media.get_medium(medium.id_bytes) for key, value in properties.items(): self.assertEqual(getattr(medium, key), value) # update_medium can receive bytes-like properties = { 'upload_time': 1999999999, 'creation_time': 2222222222, 'touch_time': 2345678901, 'uploader_remote_origin': ip_address('2.3.4.5'), 'uploader_id': user2_id, 'owner_id': user2_id, 'status': MediumStatus.FORBIDDEN, 'protection': MediumProtection.PRIVATE, 'searchability': MediumSearchability.PUBLIC, 'group_bits': int(2).to_bytes(2, 'big'), 'mime': 'test2', 'size': 2000, 'data1': 7, 'data2': 8, 'data3': 9, 'data4': 10, 'data5': 11, 'data6': 12, } self.media.update_medium(medium.id_bytes, **properties) medium = self.media.get_medium(medium.id_bytes) for key, value in properties.items(): self.assertEqual(getattr(medium, key), value) self.assert_invalid_id_raises(self.media.update_medium)