def test_move_success(self): params = get_synced_params() cmd = folder.FolderMoveCommand() user_folder = next( iter([ x for x in params.folder_cache.values() if x.type == 'user_folder' ])) shared_folder = next( iter([ x for x in params.folder_cache.values() if x.type == 'shared_folder' ])) root_record_uid = next(iter(params.subfolder_record_cache[''])) sf_record_uid = next( iter(params.subfolder_record_cache[shared_folder.uid])) KeeperApiHelper.communicate_expect(['move']) cmd.execute(params, src=root_record_uid, dst=user_folder.uid) self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect(['move']) cmd.execute(params, src=sf_record_uid, dst=user_folder.name) self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect(['move']) cmd.execute(params, src=root_record_uid, dst=user_folder.uid) self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_search_command(self): params = get_synced_params() cmd = record.SearchCommand() with mock.patch('builtins.print'): cmd.execute(params, pattern='.*') cmd.execute(params, pattern='Non-existing-name')
def test_share_record(self): params = get_synced_params() record_uid = next( iter([ x['record_uid'] for x in params.meta_data_cache.values() if x['can_share'] ])) cmd = register.ShareRecordCommand() TestRegister.expected_commands.extend(['record_share_update']) cmd.execute(params, email=['*****@*****.**'], action='grant', can_share=False, can_edit=True, record=record_uid) self.assertEqual(len(TestRegister.expected_commands), 0) TestRegister.expected_commands.extend(['record_share_update']) cmd.execute(params, email=['*****@*****.**'], action='owner', can_share=False, can_edit=True, record=record_uid) self.assertEqual(len(TestRegister.expected_commands), 0) TestRegister.expected_commands.extend(['record_share_update']) cmd.execute(params, email=['*****@*****.**'], action='revoke', record=record_uid) self.assertEqual(len(TestRegister.expected_commands), 0)
def test_convert_to_folders(self): params = get_synced_params() KeeperApiHelper.communicate_expect(['convert_to_folders']) result = convert_to_folders(params) self.assertTrue(KeeperApiHelper.is_expect_empty()) self.assertTrue(result)
def test_add_command(self): params = get_synced_params() cmd = recordv2.RecordAddCommand() with mock.patch('keepercommander.api.sync_down'): KeeperApiHelper.communicate_expect(['record_add']) cmd.execute(params, force=True, title='New Record') self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect(['record_add']) cmd.execute(params, login='******', password='******', url='url', custom='name1: value 1, name2: value 2', title='New Record') self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect(['record_add']) cmd.execute(params, login='******', password='******', url='url', custom=[{ 'name1': 'value 1', 'name2': 'value 2' }], title='New Record') self.assertTrue(KeeperApiHelper.is_expect_empty()) with mock.patch('builtins.input', return_value='Input Data'): KeeperApiHelper.communicate_expect(['record_add']) cmd.execute(params, force=True, title='New Record') self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_export_import(self): params_export = get_synced_params() cmd_export = commands.RecordExportCommand() param_import = get_connected_params() cmd_import = commands.RecordImportCommand() json_text = '' def mock_write(text): nonlocal json_text json_text += text def mock_read(): nonlocal json_text return json_text with mock.patch('keepercommander.api.sync_down'), mock.patch('builtins.open', mock.mock_open()) as m_open: m_open.return_value.write = mock_write cmd_export.execute(params_export, format='json', name='json') with mock.patch('keepercommander.api.sync_down'), mock.patch('builtins.open', mock.mock_open()) as m_open: m_open.return_value.read = mock_read self.communicate_mock.side_effect = None self.communicate_mock.return_value = { 'result': 'success', 'result_code': '', 'message': '' } with mock.patch('os.path.isfile', return_value=True): cmd_import.execute(param_import, format='json', name='json')
def test_delete_user_folder(self): params = get_synced_params() cmd = folder.FolderRemoveCommand() user_folder = next( iter([ x for x in params.folder_cache.values() if x.type == 'user_folder' ])) def pre_delete(rq): self.assertEqual(rq['command'], 'pre_delete') return { 'pre_delete_response': { 'would_delete': { 'deletion_summary': ['1 Personal Folder'] }, 'pre_delete_token': 'token' } } with mock.patch('builtins.print'), mock.patch( 'keepercommander.commands.folder.user_choice') as mock_choice: mock_choice.return_value = 'n' KeeperApiHelper.communicate_expect([pre_delete]) cmd.execute(params, pattern=[user_folder.name]) self.assertTrue(KeeperApiHelper.is_expect_empty()) mock_choice.return_value = 'y' KeeperApiHelper.communicate_expect([pre_delete, 'delete']) cmd.execute(params, pattern=[user_folder.name]) self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_delete_shared_folder(self): params = get_synced_params() cmd = folder.FolderRemoveCommand() shared_folder = next( iter([ x for x in params.folder_cache.values() if x.type == 'shared_folder' ])) def shared_folder_update(rq): requests = [{ 'command': 'shared_folder_update', 'operation': 'delete', 'shared_folder_uid': shared_folder.uid }] self.assertEqual(rq['command'], 'execute') self.assertEqual(rq['requests'], requests) KeeperApiHelper.communicate_expect([shared_folder_update]) cmd.execute(params, force=True, pattern=[shared_folder.name]) self.assertTrue(KeeperApiHelper.is_expect_empty()) with mock.patch( 'keepercommander.commands.folder.user_choice') as mock_choice: mock_choice.return_value = 'y' KeeperApiHelper.communicate_expect([shared_folder_update]) cmd.execute(params, pattern=[shared_folder.name]) self.assertTrue(KeeperApiHelper.is_expect_empty()) mock_choice.return_value = 'n' cmd.execute(params, pattern=[shared_folder.name])
def test_sync_remove_team_shared_folder(self): params = get_synced_params() teams_to_delete = [x['team_uid'] for x in params.team_cache.values()] sf_to_delete = [ x['shared_folder_uid'] for x in params.shared_folder_cache.values() ] def sync_down_removed_teams_and_shared_folders(rq): self.assertEqual(rq['command'], 'sync_down') return { 'revision': vault_env.revision + 1, 'removed_shared_folders': sf_to_delete, 'removed_teams': teams_to_delete } KeeperApiHelper.communicate_expect( [sync_down_removed_teams_and_shared_folders]) sync_down(params) self.assertTrue(KeeperApiHelper.is_expect_empty()) self.assertEqual(len(params.record_cache), 2) self.assertEqual(len(params.shared_folder_cache), 0) self.assertEqual(len(params.team_cache), 0) self.assert_key_unencrypted(params)
def test_list(self): params = get_synced_params() cmd = folder.FolderListCommand() with mock.patch('builtins.print'), mock.patch('keepercommander.api.get_record_shares'): cmd.execute(params) cmd.execute(params, detail=True)
def test_get_shared_folder_uid(self): params = get_synced_params() cmd = record.RecordGetUidCommand() shared_folder_uid = next(iter(params.shared_folder_cache)) with mock.patch('builtins.print'): cmd.execute(params, uid=shared_folder_uid) cmd.execute(params, format='json', uid=shared_folder_uid)
def test_tree(self): params = get_synced_params() cmd = folder.FolderTreeCommand() with mock.patch('builtins.print'): cmd.execute(params) with self.assertRaises(CommandError): cmd.execute(params, folder='Invalid')
def test_change_directory(self): params = get_synced_params() cmd = folder.FolderCdCommand() folder_name = next(iter([x['name_unencrypted'] for x in params.shared_folder_cache.values()])) owd = params.current_folder cmd.execute(params, folder=folder_name) self.assertNotEqual(owd, params.current_folder)
def test_get_team_uid(self): params = get_synced_params() cmd = recordv2.RecordGetUidCommand() team_uid = next(iter(params.team_cache)) with mock.patch('builtins.print'): cmd.execute(params, uid=team_uid) cmd.execute(params, format='json', uid=team_uid)
def test_get_record_uid(self): params = get_synced_params() cmd = recordv2.RecordGetUidCommand() record_uid = next(iter(params.subfolder_record_cache[''])) with mock.patch('builtins.print'), mock.patch( 'keepercommander.api.get_record_shares'): cmd.execute(params, uid=record_uid) cmd.execute(params, format='json', uid=record_uid)
def test_shared_list_command(self): params = get_synced_params() cmd = record.RecordListSfCommand() with mock.patch('builtins.print') as mock_print: cmd.execute(params, pattern='folder') mock_print.assert_called() mock_print.reset_mock() cmd.execute(params, pattern='INVALID') mock_print.assert_not_called()
def test_upload_attachment_command(self): params = get_synced_params() cmd = recordv2.RecordUploadAttachmentCommand() record_uid = next( iter([ x['record_uid'] for x in params.record_cache.values() if len(x['extra_unencrypted']) > 10 ])) rec = api.get_record(params, record_uid) with self.assertRaises(CommandError): cmd.execute(params, record=rec.title) def request_upload(rq): self.assertEqual(rq['command'], 'request_upload') return { 'file_uploads': [{ 'max_size': 1000000, 'url': 'https://keepersecurity.com/uploads/', 'success_status_code': 201, 'file_id': 'ABCDEF%.2d' % x, 'file_parameter': 'file', 'parameters': { 'a': 'b' } } for x in range((rq.get('file_count') or 0) + (rq.get('thumbnail_count') or 0))] } def request_http_post(url, **kwargs): attachment = mock.Mock() attachment.status_code = 201 return attachment with mock.patch('requests.post', side_effect=request_http_post), \ mock.patch('builtins.open', mock.mock_open(read_data=b'data')) as m_open, \ mock.patch('os.path.isfile', return_value=True), \ mock.patch('os.path.getsize') as mock_getsize: m_open.return_value.tell = lambda: 4 mock_getsize.return_value = 1000000000 with self.assertRaises(CommandError): KeeperApiHelper.communicate_expect([request_upload]) cmd.execute(params, file=['file.data'], record=record_uid) self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect( [request_upload, 'record_update']) m_open.return_value.tell = lambda: 4 mock_getsize.return_value = 1000 cmd.execute(params, file=['file.data'], record=record_uid) self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_make_folder(self): params = get_synced_params() cmd = folder.FolderMakeCommand() def is_user_folder(rq): self.assertEqual(rq['command'], 'folder_add') self.assertEqual(rq['folder_type'], 'user_folder') def is_shared_folder(rq): self.assertEqual(rq['command'], 'folder_add') self.assertEqual(rq['folder_type'], 'shared_folder') def is_shared_folder_folder(rq): self.assertEqual(rq['command'], 'folder_add') self.assertEqual(rq['folder_type'], 'shared_folder_folder') KeeperApiHelper.communicate_expect([is_user_folder]) cmd.execute(params, user_folder=True, folder='New Folder') KeeperApiHelper.communicate_expect([is_shared_folder]) cmd.execute(params, shared_folder=True, folder='New Shared Folder') with mock.patch( 'keepercommander.commands.folder.user_choice') as mock_choice: mock_choice.return_value = 'n' KeeperApiHelper.communicate_expect([is_user_folder]) cmd.execute(params, folder='New Folder') self.assertTrue(KeeperApiHelper.is_expect_empty()) mock_choice.return_value = 'y' KeeperApiHelper.communicate_expect([is_shared_folder]) cmd.execute(params, folder='New Shared Folder') self.assertTrue(KeeperApiHelper.is_expect_empty()) with mock.patch('builtins.input') as mock_input: mock_choice.return_value = 'n' mock_input.return_value = 'New Personal Folder' KeeperApiHelper.communicate_expect([is_user_folder]) cmd.execute(params) self.assertTrue(KeeperApiHelper.is_expect_empty()) shared_folder = next( iter([ x for x in params.folder_cache.values() if x.type == 'shared_folder' ])) with self.assertLogs(level=logging.WARNING): cmd.execute(params, folder=shared_folder.name) params.current_folder = shared_folder.uid KeeperApiHelper.communicate_expect([is_shared_folder_folder]) cmd.execute(params, folder='New SubFolder') self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_share_folder(self): params = get_synced_params() shared_folder_uid = next(iter([x['shared_folder_uid'] for x in params.shared_folder_cache.values()])) cmd = register.ShareFolderCommand() TestRegister.expected_commands.extend(['shared_folder_update']) cmd.execute(params, action='grant', user=['*****@*****.**'], manage_records=True, manage_users=False, folder=shared_folder_uid) self.assertEqual(len(TestRegister.expected_commands), 0) TestRegister.expected_commands.extend(['shared_folder_update']) cmd.execute(params, action='revoke', user=['*****@*****.**'], folder=shared_folder_uid) self.assertEqual(len(TestRegister.expected_commands), 0)
def test_append_notes_command(self): params = get_synced_params() cmd = recordv2.RecordAppendNotesCommand() record_uid = next(iter(params.subfolder_record_cache[''])) with mock.patch('keepercommander.api.update_record'): cmd.execute(params, notes='notes', record=record_uid) with mock.patch('builtins.input', return_value='data'): cmd.execute(params, record=record_uid) with self.assertRaises(CommandError): cmd.execute(params, notes='notes', record='invalid')
def test_move_invalid_input(self): params = get_synced_params() cmd = folder.FolderMoveCommand() user_folder = next(iter([x for x in params.folder_cache.values() if x.type == 'user_folder'])) # shared_folder = next(iter([x for x in params.folder_cache.values() if x.type == 'shared_folder'])) root_record_uid = next(iter(params.subfolder_record_cache[''])) with self.assertRaises(CommandError): cmd.execute(params, src='Invalid Record', dst=user_folder.uid) cmd.execute(params, src=root_record_uid, dst='Invalid Folder') cmd.execute(params, src=user_folder.uid, dst=user_folder.uid)
def test_delete_attachment_command(self): params = get_synced_params() cmd = recordv2.RecordDeleteAttachmentCommand() record_uid = next( iter([ x['record_uid'] for x in params.record_cache.values() if len(x['extra_unencrypted']) > 10 ])) rec = api.get_record(params, record_uid) KeeperApiHelper.communicate_expect(['record_update']) cmd.execute(params, name=[rec.attachments[0]['id']], record=rec.title) self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_search_records(self): params = get_synced_params() records = api.search_records(params, '') self.assertEqual(len(records), len(params.record_cache)) records = api.search_records(params, 'RECORD') self.assertEqual(len(records), len(params.record_cache)) records = api.search_records(params, 'Record 1') self.assertEqual(len(records), 1) records = api.search_records(params, 'INVALID') self.assertEqual(len(records), 0)
def test_search_shared_folders(self): params = get_synced_params() sfs = api.search_shared_folders(params, '') self.assertEqual(len(sfs), len(params.shared_folder_cache)) sfs = api.search_shared_folders(params, 'folder') self.assertEqual(len(sfs), len(params.shared_folder_cache)) sfs = api.search_shared_folders(params, '1') self.assertEqual(len(sfs), 1) sfs = api.search_shared_folders(params, 'INVALID') self.assertEqual(len(sfs), 0)
def test_search_teams(self): params = get_synced_params() teams = api.search_teams(params, '') self.assertEqual(len(teams), len(params.team_cache)) teams = api.search_shared_folders(params, 'team') self.assertEqual(len(teams), len(params.shared_folder_cache)) teams = api.search_shared_folders(params, '1') self.assertEqual(len(teams), 1) teams = api.search_shared_folders(params, 'INVALID') self.assertEqual(len(teams), 0)
def test_remove_command_from_root(self): params = get_synced_params() cmd = recordv2.RecordRemoveCommand() record_uid = next(iter(params.subfolder_record_cache[''])) rec = api.get_record(params, record_uid) def pre_delete_command(rq): self.assertEqual(rq['command'], 'pre_delete') return { 'pre_delete_response': { 'would_delete': { 'deletion_summary': ['delete all'] }, 'pre_delete_token': 'token' } } with mock.patch('keepercommander.commands.recordv2.user_choice' ) as choice_mock: choice_mock.return_value = KeyboardInterrupt() KeeperApiHelper.communicate_expect([pre_delete_command, 'delete']) cmd.execute(params, force=True, record=rec.record_uid) self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect([pre_delete_command, 'delete']) cmd.execute(params, force=True, record=rec.title) self.assertTrue(KeeperApiHelper.is_expect_empty()) with mock.patch('builtins.print'): choice_mock.return_value = 'y' KeeperApiHelper.communicate_expect( [pre_delete_command, 'delete']) cmd.execute(params, record=rec.record_uid) self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect( [pre_delete_command, 'delete']) cmd.execute(params, record=rec.title) self.assertTrue(KeeperApiHelper.is_expect_empty()) choice_mock.return_value = 'n' KeeperApiHelper.communicate_expect([pre_delete_command]) cmd.execute(params, record=rec.record_uid) self.assertTrue(KeeperApiHelper.is_expect_empty()) KeeperApiHelper.communicate_expect([pre_delete_command]) cmd.execute(params, record=rec.title) self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_record_list_command(self): params = get_synced_params() cmd = record.RecordListCommand() with mock.patch('builtins.print') as mock_print, mock.patch( 'keepercommander.api.get_record_shares') as mock_shares: cmd.execute(params, pattern='record') mock_print.assert_called() mock_shares.assert_called() mock_print.reset_mock() mock_shares.reset_mock() cmd.execute(params, pattern='INVALID') mock_print.assert_not_called() mock_shares.assert_not_called()
def test_download_attachment_command(self): params = get_synced_params() cmd = recordv2.RecordDownloadAttachmentCommand() records = [ x for x in params.record_cache.values() if len(x['extra_unencrypted']) > 10 ] rec = records[0] record_uid = rec['record_uid'] extra = json.loads(rec['extra_unencrypted'].decode('utf-8')) attachments = { } # type: dict[any, tuple[attachment.AttachmentDownloadRequest, bytes]] for file in extra['files']: atta_id = file['id'] # type: str key = utils.base64_url_decode(file['key']) body_encoded = crypto.encrypt_aes_v1(os.urandom(file['size']), key) rq = attachment.AttachmentDownloadRequest() rq.title = 'Title' rq.url = f'https://keepersecurity.com/files/{atta_id}' rq.is_gcm_encrypted = False rq.encryption_key = key attachments[atta_id] = (rq, body_encoded) def prepare_download(params, record_uid): return (x[0] for x in attachments.values()) def requests_get(url, **kwargs): body = next( (x[1] for x in attachments.values() if x[0].url == url), None) if not body: raise Exception(f'URL \"{url}\" not found.') rs = mock.Mock() rs.status_code = 200 stream = io.BytesIO(body) rs.raw = stream rs.__enter__ = mock.Mock(return_value=rs) rs.__exit__ = mock.Mock(return_value=None) return rs with mock.patch('keepercommander.attachment.prepare_attachment_download', side_effect=prepare_download), \ mock.patch('requests.get', side_effect=requests_get), \ mock.patch('builtins.open', mock.mock_open()), \ mock.patch('os.path.abspath', return_value='/file_name'): cmd.execute(params, record=record_uid)
def test_add_command_check_request(self): params = get_synced_params() cmd = record.RecordAddCommand() def check_record(rq): rq['command'] = 'record_add' record_key = api.decrypt_data(rq['record_key'], self.vault_env.data_key) data_bytes = api.decrypt_data(rq['data'], record_key) data = json.loads(data_bytes.decode('utf-8')) self.assertEqual(data['title'], 'data') self.assertEqual(data['title'], data['link']) self.assertEqual(data['secret1'], data['secret2']) self.assertEqual(len(data['custom']), 2) with mock.patch('builtins.input', return_value='data'): KeeperApiHelper.communicate_expect([check_record]) cmd.execute(params, custom='name1: value 1, name2: value 2') self.assertTrue(KeeperApiHelper.is_expect_empty())
def test_sync_remove_owned_records(self): params = get_synced_params() len_before = len(params.record_cache) records_to_delete = [x['record_uid'] for x in params.meta_data_cache.values() if x['owner']] def sync_down_removed_records(rq): self.assertEqual(rq['command'], 'sync_down') return { 'revision': vault_env.revision + 1, 'removed_records': records_to_delete } KeeperApiHelper.communicate_expect([sync_down_removed_records]) sync_down(params) self.assertTrue(KeeperApiHelper.is_expect_empty()) self.assertEqual(len(params.record_cache), len_before - len(records_to_delete)) self.assert_key_unencrypted(params)