def get_available_teams(rq): self.assertEqual(rq['command'], 'get_available_teams') return { 'teams': [{ 'team_uid': api.generate_record_uid(), 'team_name': 'Team 1' }, { 'team_uid': api.generate_record_uid(), 'team_name': 'Team 2' }] }
def prepare_record_add_or_update(update_flag, params, records): """ Find what records to import or update. If update_flag is False: If a 100% match is found for a record, then just skip requesting anything; it doesn't need to be changed. Otherwise import the record, risking creating an almost-duplicate. If update_flag is True: if a unique field match (on title, login, and url) is found, then request a change in password only. Do not update the TOTP custom field, even if it exists. """ recs_to_import_or_update = records del records preexisting_entire_record_hash = build_hash_dict(params, tokenize_full_preexisting_record) preexisting_partial_record_hash = build_hash_dict(params, tokenize_partial_preexisting_record) record_adds = [] record_updates = [] for rec_to_import_or_update in recs_to_import_or_update: perform_import_or_update = 'neither' full_hash_of_cur_rec = build_record_hash(rec_to_import_or_update, tokenize_full_import_record) partial_hash_of_cur_rec = build_record_hash(rec_to_import_or_update, tokenize_partial_import_record) # Decide what kind of operation is needed. if full_hash_of_cur_rec in preexisting_entire_record_hash: # We do not need to do a record update; we already have this record in its entirety. pass elif partial_hash_of_cur_rec in preexisting_partial_record_hash and update_flag: # This is a record to update instead of importing it. rec_to_import_or_update.uid = preexisting_partial_record_hash[partial_hash_of_cur_rec] perform_import_or_update = 'update' else: # Create a new UID for the new record, and signal that we need to do the import. # We do this conditionally for --update, and unconditionally for import without --update. rec_to_import_or_update.uid = api.generate_record_uid() perform_import_or_update = 'import' # Act on the selected operation. if perform_import_or_update == 'update': rec_req = construct_update_rec_req(params, preexisting_partial_record_hash, rec_to_import_or_update) # Schedule the record for later batch-update. record_updates.append(rec_req) elif perform_import_or_update == 'import': rec_req = construct_import_rec_req(params, preexisting_entire_record_hash, rec_to_import_or_update) # Schedule the record for later batch-addition. record_adds.append(rec_req) elif perform_import_or_update == 'neither': # Nothing to do. pass else: raise AssertionError('perform_import_or_update has a strange value: {}'.format(perform_import_or_update)) return record_adds, record_updates
def generate_data(): r1 = record.Record() r1.record_uid = api.generate_record_uid() r1.folder = 'Old Folder' r1.title = 'Record 1' r1.login = '******' r1.password = '******' r1.login_url = 'https://keepersecurity.com/1' r1.set_field('field1', 'value1') r1.notes = 'note1' r1.attachments = [{ 'name': 'Attachment 1', 'key': base64.urlsafe_b64encode( api.generate_aes_key()).decode('utf-8').rstrip('='), 'id': 'ABCDEFGH', 'size': 1000 }] r1.revision = 1 r1_key = register_record(r1, 1) r2 = record.Record() r2.record_uid = api.generate_record_uid() r2.title = 'Record 2' r2.login = '******' r2.password = '******' r2.login_url = 'https://keepersecurity.com/2' r2.set_field('field2', 'value2') r2.notes = 'note2' r2.revision = 2 r2_key = register_record(r2, 2) register_records_to_folder(None, [r1.record_uid, r2.record_uid]) r3 = record.Record() r3.record_uid = api.generate_record_uid() r3.title = 'Record 3' r3.login = '******' r3.password = '******' r3.login_url = 'https://keepersecurity.com/3' r3.revision = 3 r3_key = register_record(r3) sf1 = shared_folder.SharedFolder() sf1.shared_folder_uid = api.generate_record_uid() sf1.default_manage_records = False sf1.default_manage_users = False sf1.default_can_edit = False sf1.default_can_share = False sf1.name = 'Shared Folder 1' sf1_key = register_shared_folder(sf1, {r3.record_uid: r3_key}) register_records_to_folder(sf1.shared_folder_uid, [r3.record_uid]) _USER_FOLDER_SHARED_FOLDER.append( {'shared_folder_uid': sf1.shared_folder_uid}) t1 = team.Team() t1.team_uid = api.generate_record_uid() t1.name = 'Team 1' t1.restrict_edit = True t1.restrict_share = True t1.restrict_view = False register_team(t1, 1, {sf1.shared_folder_uid: sf1_key}) folder_key = api.generate_aes_key() _USER_FOLDERS.append({ 'folder_uid': api.generate_record_uid(), 'key_type': 1, 'user_folder_key': api.encrypt_aes(folder_key, _USER_DATA_KEY), 'revision': 200, 'type': 'user_folder', 'data': api.encrypt_aes( json.dumps({ 'name': 'User Folder 1' }).encode('utf-8'), folder_key) })
def test_enterprise_push_command(self): params = get_connected_params() api.query_enterprise(params) cmd = enterprise.EnterprisePushCommand() template_body = ''' [ { "title": "Record For ${user_name}", "login": "******", "password": "******", "login_url": "https://keepersecurity.com", "notes": "notes", "custom_fields": { "key1": "value1", "key2": "${user_email}" } }, { "title": "Empty record" } ]''' templates = json.loads(template_body) values = { 'user_name': api.generate_record_uid(), 'generate_password': api.generate_record_uid(), 'user_email': api.generate_record_uid() } cmd.enumerate_and_substitute_dict_fields(templates[0], values) cmd.enumerate_and_substitute_dict_fields(templates[1], values) self.assertEqual(templates[0]['title'], 'Record For {0}'.format(values['user_name'])) self.assertEqual(templates[0]['password'], values['generate_password']) self.assertEqual(templates[0]['custom_fields']['key2'], values['user_email']) self.assertEqual(templates[1]['title'], 'Empty record') with self.assertRaises(CommandError): cmd.execute(params, file='template.json') with self.assertRaises(CommandError): cmd.execute(params, user=[ent_env.user2_email]) def get_public_keys(_params, emails): for email in emails: emails[email] = vault_env.public_key with mock.patch('builtins.open', mock.mock_open(read_data=template_body)), \ mock.patch('os.path.abspath', return_value='template.json'), \ mock.patch('os.path.isfile', return_value=True), \ mock.patch('keepercommander.commands.enterprise.EnterpriseCommand.get_public_keys') as m_pk: m_pk.side_effect = get_public_keys TestEnterprise.expected_commands = ['execute'] cmd.execute(params, file='template.json', team=[ent_env.team1_name]) self.assertEqual(len(TestEnterprise.expected_commands), 0) TestEnterprise.expected_commands = ['execute'] cmd.execute(params, file='template.json', user=[ent_env.user2_email]) self.assertEqual(len(TestEnterprise.expected_commands), 0)
def prepare_record_add(params, records): record_hash = {} for r_uid in params.record_cache: rec = api.get_record(params, r_uid) h = hashlib.sha256() for token in tokenize_record(rec): h.update(token.encode()) record_hash[h.hexdigest()] = r_uid record_adds = [] for rec in records: h = hashlib.sha256() for token in tokenize_import_record(rec): h.update(token.encode()) r_hash = h.hexdigest() if r_hash in record_hash: rec.uid = record_hash[r_hash] else: rec.uid = api.generate_record_uid() record_hash[r_hash] = rec.uid record_key = os.urandom(32) rec_req = folder_pb2.RecordRequest() rec_req.recordUid = base64.urlsafe_b64decode(rec.uid + '==') rec_req.recordType = 0 rec_req.encryptedRecordKey = base64.urlsafe_b64decode( api.encrypt_aes(record_key, params.data_key) + '==') rec_req.howLongAgo = 0 rec_req.folderType = 1 folder_uid = None if rec.folders: folder_uid = rec.folders[0].uid if folder_uid: if folder_uid in params.folder_cache: folder = params.folder_cache[folder_uid] if folder.type in { BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType }: rec_req.folderUid = base64.urlsafe_b64decode( folder.uid + '==') rec_req.folderType = 2 if folder.type == BaseFolderNode.SharedFolderType else 3 sh_uid = folder.uid if folder.type == BaseFolderNode.SharedFolderType else folder.shared_folder_uid sf = params.shared_folder_cache[sh_uid] rec_req.encryptedRecordFolderKey = base64.urlsafe_b64decode( api.encrypt_aes( record_key, sf['shared_folder_key_unencrypted']) + '==') else: rec_req.folderType = 1 if folder.type != BaseFolderNode.RootFolderType: rec_req.folderUid = base64.urlsafe_b64decode( folder.uid + '==') custom_fields = [] totp = None if rec.custom_fields: for cf in rec.custom_fields: if cf == TWO_FACTOR_CODE: totp = rec.custom_fields[cf] else: custom_fields.append({ 'name': cf, 'value': rec.custom_fields[cf] }) data = { 'title': rec.title or '', 'secret1': rec.login or '', 'secret2': rec.password or '', 'link': rec.login_url or '', 'notes': rec.notes or '', 'custom': custom_fields } rec_req.recordData = base64.urlsafe_b64decode( api.encrypt_aes(json.dumps(data).encode('utf-8'), record_key) + '==') if totp: extra = { 'fields': [{ 'id': api.generate_record_uid(), 'field_type': 'totp', 'field_title': 'Two-Factor Code', 'type': 0, 'data': totp }] } rec_req.extra = base64.urlsafe_b64decode( api.encrypt_aes( json.dumps(extra).encode('utf-8'), record_key) + '==') record_adds.append(rec_req) return record_adds
def prepare_folder_add(params, folders, records): folder_hash = {} for f_uid in params.folder_cache: fol = params.folder_cache[f_uid] h = hashlib.md5() hs = '{0}|{1}'.format((fol.name or '').lower(), fol.parent_uid or '') h.update(hs.encode()) shared_folder_key = None if fol.type in { BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType }: sf_uid = fol.shared_folder_uid if fol.type == BaseFolderNode.SharedFolderFolderType else fol.uid if sf_uid in params.shared_folder_cache: shared_folder_key = params.shared_folder_cache[sf_uid][ 'shared_folder_key_unencrypted'] folder_hash[h.hexdigest()] = f_uid, fol.type, shared_folder_key folder_add = [] # type: [folder_pb2.FolderRequest] if folders: for fol in folders: skip_folder = False parent_uid = '' comps = list(path_components(fol.path)) for i in range(len(comps)): comp = comps[i] h = hashlib.md5() hs = '{0}|{1}'.format(comp.lower(), parent_uid) h.update(hs.encode()) digest = h.hexdigest() is_last = False if i == len(comps) - 1: is_last = True if digest not in folder_hash: folder_uid = api.generate_record_uid() folder_type = 'shared_folder' if is_last else 'user_folder' fol_req = folder_pb2.FolderRequest() fol_req.folderUid = base64.urlsafe_b64decode(folder_uid + '==') fol_req.folderType = 2 if folder_type == 'shared_folder' else 1 if parent_uid: fol_req.parentFolderUid = base64.urlsafe_b64decode( parent_uid + '==') folder_key = os.urandom(32) fol_req.encryptedFolderKey = base64.urlsafe_b64decode( api.encrypt_aes(folder_key, params.data_key) + '==') data = {'name': comp} fol_req.folderData = base64.urlsafe_b64decode( api.encrypt_aes( json.dumps(data).encode('utf-8'), folder_key) + '==') if folder_type == 'shared_folder': fol_req.sharedFolderFields.encryptedFolderName = base64.urlsafe_b64decode( api.encrypt_aes(comp.encode('utf-8'), folder_key) + '==') fol_req.sharedFolderFields.manageUsers = fol.manage_users fol_req.sharedFolderFields.manageRecords = fol.manage_records fol_req.sharedFolderFields.canEdit = fol.can_edit fol_req.sharedFolderFields.canShare = fol.can_share folder_add.append(fol_req) folder_hash[ digest] = folder_uid, folder_type, folder_key if folder_type == 'shared_folder' else None else: folder_uid, folder_type, folder_key = folder_hash[digest] if is_last: skip_folder = folder_type != 'shared_folder' else: skip_folder = folder_type != 'user_folder' parent_uid = folder_uid if skip_folder: break if records: for rec in records: if rec.folders: for fol in rec.folders: parent_uid = '' parent_shared_folder_uid = None parent_shared_folder_key = None parent_type = '' for is_domain in [True, False]: path = fol.domain if is_domain else fol.path if not path: continue comps = list(path_components(path)) for i in range(len(comps)): comp = comps[i] h = hashlib.md5() hs = '{0}|{1}'.format(comp.lower(), parent_uid) h.update(hs.encode()) digest = h.hexdigest() if digest not in folder_hash: is_shared = False if i == len(comps) - 1: is_shared = is_domain folder_uid = api.generate_record_uid() if not parent_type or parent_type == 'user_folder': folder_type = 'shared_folder' if is_shared else 'user_folder' else: folder_type = 'shared_folder_folder' fol_req = folder_pb2.FolderRequest() fol_req.folderUid = base64.urlsafe_b64decode( folder_uid + '==') fol_req.folderType = 2 if folder_type == 'shared_folder' else 3 if folder_type == 'shared_folder_folder' else 1 if parent_uid: fol_req.parentFolderUid = base64.urlsafe_b64decode( parent_uid + '==') if folder_type == 'shared_folder_folder' and parent_uid == parent_shared_folder_uid: fol_req.parentFolderUid = b'' folder_key = os.urandom(32) if folder_type == 'shared_folder_folder': fol_req.encryptedFolderKey = base64.urlsafe_b64decode( api.encrypt_aes( folder_key, parent_shared_folder_key or params.data_key) + '==') else: fol_req.encryptedFolderKey = base64.urlsafe_b64decode( api.encrypt_aes( folder_key, params.data_key) + '==') data = {'name': comp} fol_req.folderData = base64.urlsafe_b64decode( api.encrypt_aes( json.dumps(data).encode('utf-8'), folder_key) + '==') if folder_type == 'shared_folder': fol_req.sharedFolderFields.encryptedFolderName = base64.urlsafe_b64decode( api.encrypt_aes( comp.encode('utf-8'), folder_key) + '==') parent_shared_folder_key = folder_key parent_shared_folder_uid = folder_uid elif folder_type == 'shared_folder_folder': if parent_shared_folder_uid: fol_req.sharedFolderFolderFields.sharedFolderUid = base64.urlsafe_b64decode( parent_shared_folder_uid + '==') folder_add.append(fol_req) folder_hash[ digest] = folder_uid, folder_type, parent_shared_folder_key else: folder_uid, folder_type, parent_shared_folder_key = folder_hash[ digest] if folder_type == 'shared_folder': parent_shared_folder_uid = folder_uid parent_uid = folder_uid parent_type = folder_type fol.uid = parent_uid return folder_add
def prepare_record_add(params, records): record_hash = {} for r_uid in params.record_cache: rec = api.get_record(params, r_uid) h = hashlib.md5() hs = '{0}|{1}|{2}'.format(rec.title or '', rec.login or '', rec.password or '') h.update(hs.encode()) record_hash[h.hexdigest()] = r_uid record_adds = [] for rec in records: h = hashlib.md5() hs = '{0}|{1}|{2}'.format(rec.title or '', rec.login or '', rec.password or '') h.update(hs.encode()) rec_hash = h.hexdigest() record_uid = record_hash.get(rec_hash) if record_uid is None: record_key = os.urandom(32) record_uid = api.generate_record_uid() req = { 'command': 'record_add', 'record_uid': record_uid, 'record_type': 'password', 'record_key': api.encrypt_aes(record_key, params.data_key), 'how_long_ago': 0, 'folder_type': 'user_folder' } folder_uid = None if rec.folders: if len(rec.folders) > 0: folder_uid = rec.folders[0].uid if folder_uid: if folder_uid in params.folder_cache: folder = params.folder_cache[folder_uid] if folder.type in { BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType }: req['folder_uid'] = folder.uid req['folder_type'] = 'shared_folder' if folder.type == BaseFolderNode.SharedFolderType else 'shared_folder_folder' sh_uid = folder.uid if folder.type == BaseFolderNode.SharedFolderType else folder.shared_folder_uid sf = params.shared_folder_cache[sh_uid] req['folder_key'] = api.encrypt_aes( record_key, sf['shared_folder_key_unencrypted']) if 'key_type' not in sf: if 'teams' in sf: for team in sf['teams']: req['team_uid'] = team['team_uid'] if team['manage_records']: break else: req['folder_type'] = 'user_folder' if folder.type != BaseFolderNode.RootFolderType: req['folder_uid'] = folder.uid custom_fields = [] if rec.custom_fields: for cf in rec.custom_fields: custom_fields.append({ 'name': cf, 'value': rec.custom_fields[cf] }) data = { 'title': rec.title or '', 'secret1': rec.login or '', 'secret2': rec.password or '', 'link': rec.login_url or '', 'notes': rec.notes or '', 'custom': custom_fields } req['data'] = api.encrypt_aes( json.dumps(data).encode('utf-8'), record_key) record_adds.append(req) rec.uid = record_uid return record_adds
def prepare_folder_add(params, records): folder_hash = {} for f_uid in params.folder_cache: fol = params.folder_cache[f_uid] h = hashlib.md5() hs = '{0}|{1}'.format((fol.name or '').lower(), fol.parent_uid or '') h.update(hs.encode()) shared_folder_key = None if fol.type in { BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType }: sf_uid = fol.shared_folder_uid if fol.type == BaseFolderNode.SharedFolderFolderType else fol.uid if sf_uid in params.shared_folder_cache: shared_folder_key = params.shared_folder_cache[sf_uid][ 'shared_folder_key_unencrypted'] folder_hash[h.hexdigest()] = f_uid, fol.type, shared_folder_key folder_add = [] for rec in records: if rec.folders: for fol in rec.folders: parent_uid = '' parent_shared_folder_uid = None parent_shared_folder_key = None parent_type = BaseFolderNode.RootFolderType for is_domain in [True, False]: path = fol.domain if is_domain else fol.path if not path: continue comps = list(path_components(path)) for i in range(len(comps)): comp = comps[i] h = hashlib.md5() hs = '{0}|{1}'.format(comp.lower(), parent_uid) h.update(hs.encode()) digest = h.hexdigest() if digest not in folder_hash: is_shared = False if i == len(comps) - 1: is_shared = is_domain folder_uid = api.generate_record_uid() request = { 'command': 'folder_add', 'folder_uid': folder_uid } if parent_type in { BaseFolderNode.UserFolderType, BaseFolderNode.RootFolderType }: folder_type = 'shared_folder' if is_shared else 'user_folder' else: folder_type = 'shared_folder_folder' request['folder_type'] = folder_type encryption_key = params.data_key if request[ 'folder_type'] == 'shared_folder_folder' and parent_shared_folder_uid and parent_shared_folder_key: encryption_key = parent_shared_folder_key request[ 'shared_folder_uid'] = parent_shared_folder_uid folder_key = os.urandom(32) request['key'] = api.encrypt_aes( folder_key, encryption_key) if parent_type not in { BaseFolderNode.RootFolderType, BaseFolderNode.SharedFolderType }: request['parent_uid'] = parent_uid if request['folder_type'] == 'shared_folder': request['name'] = api.encrypt_aes( comp.encode('utf-8'), folder_key) parent_shared_folder_key = folder_key data = {'name': comp} request['data'] = api.encrypt_aes( json.dumps(data).encode('utf-8'), folder_key) folder_add.append(request) parent_uid = folder_uid parent_type = folder_type folder_hash[ digest] = parent_uid, parent_type, parent_shared_folder_key else: parent_uid, parent_type, parent_shared_folder_key = folder_hash[ digest] if parent_type == BaseFolderNode.SharedFolderType: parent_shared_folder_uid = parent_uid fol.uid = parent_uid return folder_add
def prepare_shared_folder_add(params, folders): folder_hash = {} for f_uid in params.folder_cache: fol = params.folder_cache[f_uid] h = hashlib.md5() hs = '{0}|{1}'.format((fol.name or '').lower(), fol.parent_uid or '') h.update(hs.encode()) shared_folder_key = None if fol.type in { BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType }: sf_uid = fol.shared_folder_uid if fol.type == BaseFolderNode.SharedFolderFolderType else fol.uid if sf_uid in params.shared_folder_cache: shared_folder_key = params.shared_folder_cache[sf_uid][ 'shared_folder_key_unencrypted'] folder_hash[h.hexdigest()] = f_uid, fol.type, shared_folder_key # public keys emails = {} for fol in folders: if fol.permissions: for perm in fol.permissions: if perm.name not in emails: _, email = parseaddr(perm.name) if email: if email != params.user: emails[email.lower()] = None if emails: request = {'command': "public_keys", 'key_owners': list(emails.keys())} try: rs = api.communicate(params, request) if 'public_keys' in rs: for pk in rs['public_keys']: if 'public_key' in pk: emails[pk['key_owner']] = pk['public_key'] except Exception as e: logging.debug(e) shared_folder_add = [] for fol in folders: skip_folder = False parent_uid = '' parent_type = '' parent_key = None comps = list(path_components(fol.path)) for i in range(len(comps)): comp = comps[i] h = hashlib.md5() hs = '{0}|{1}'.format(comp.lower(), parent_uid) h.update(hs.encode()) digest = h.hexdigest() is_last = False if i == len(comps) - 1: is_last = True if digest not in folder_hash: folder_uid = api.generate_record_uid() request = {'command': 'folder_add', 'folder_uid': folder_uid} folder_type = 'shared_folder' if is_last else 'user_folder' request['folder_type'] = folder_type encryption_key = params.data_key folder_key = os.urandom(32) request['key'] = api.encrypt_aes(folder_key, encryption_key) if parent_uid: request['parent_uid'] = parent_uid if folder_type == 'shared_folder': request['name'] = api.encrypt_aes(comp.encode('utf-8'), folder_key) data = {'name': comp} request['data'] = api.encrypt_aes( json.dumps(data).encode('utf-8'), folder_key) shared_folder_add.append(request) parent_uid = folder_uid parent_type = folder_type parent_key = folder_key folder_hash[ digest] = folder_uid, folder_type, folder_key if folder_type == 'shared_folder' else None else: parent_uid, parent_type, parent_key = folder_hash[digest] if is_last: skip_folder = parent_type != 'shared_folder' else: skip_folder = parent_type != 'user_folder' if skip_folder: break if not skip_folder and parent_type == 'shared_folder': request = { 'command': 'shared_folder_update', 'operation': 'update', 'pt': 'Commander', 'shared_folder_uid': parent_uid, 'force_update': True, 'default_manage_users': fol.manage_users, 'default_manage_records': fol.manage_records, 'default_can_edit': fol.can_edit, 'default_can_share': fol.can_share } if fol.permissions: for perm in fol.permissions: is_team = False if perm.uid and params.team_cache: is_team = perm.uid in params.team_cache else: _, email = parseaddr(perm.name) if not email: is_team = True if is_team: perm.uid = None for team in params.team_cache: if team['name'].lower() == perm.name.lower(): perm.uid = team['team_uid'] break if is_team: if perm.uid and perm.uid in params.team_cache: if 'add_teams' not in request: request['add_teams'] = [] team = params.team_cache[perm.uid] request['add_teams'].append({ 'team_uid': perm.uid, 'manage_users': perm.manage_users, 'manage_records': perm.manage_records, 'shared_folder_key': api.encrypt_aes(parent_key, team['team_key']) }) else: if 'add_users' not in request: request['add_users'] = [] email = perm.name.lower() if email == params.user.lower(): request['add_users'].append({ 'username': email, 'manage_users': perm.manage_users, 'manage_records': perm.manage_records, 'shared_folder_key': api.encrypt_aes(parent_key, params.data_key) }) elif email in emails: public_key = emails[email] if public_key: try: rsa_key = RSA.importKey( base64.urlsafe_b64decode(public_key + '==')) request['add_users'].append({ 'username': email, 'manage_users': perm.manage_users, 'manage_records': perm.manage_records, 'shared_folder_key': api.encrypt_rsa(parent_key, rsa_key) }) except: pass shared_folder_add.append(request) return shared_folder_add
import json from data_vault import VaultEnvironment from keepercommander import api, crypto, utils from keepercommander.params import KeeperParams _TREE_KEY = api.generate_aes_key() _ENTERPRISE_ID = 123 _VAULT_ENV = VaultEnvironment() _USE_DATA_KEY = True _TEAM_KEY = api.generate_aes_key() _TEAM1_UID = api.generate_record_uid() _TEAM2_UID = api.generate_record_uid() _TEAM1_NAME = 'Team 1' _TEAM2_NAME = 'Team 2' _NODE1_ID = (_ENTERPRISE_ID << 32) + 2 _NODE2_ID = (_ENTERPRISE_ID << 32) + 100 _USER1_ID = (_ENTERPRISE_ID << 32) + 201 _USER2_ID = (_ENTERPRISE_ID << 32) + 202 _USER2_EMAIL = '*****@*****.**' _ROLE1_ID = (_ENTERPRISE_ID << 32) + 301 _ROLE1_NAME = 'Role 1' _LAST_ID = 1000
def construct_import_rec_req(params, preexisting_record_hash, rec_to_import): """Build a rec_req for rec_to_import.""" r_hash = build_record_hash(record=rec_to_import, tokenize_gen=tokenize_full_import_record) if r_hash in preexisting_record_hash: # Nothing to do. We already have this identical record. return None else: rec_to_import.uid = api.generate_record_uid() preexisting_record_hash[r_hash] = rec_to_import.uid record_key = os.urandom(32) rec_req = folder_pb2.RecordRequest() rec_req.recordUid = base64.urlsafe_b64decode(rec_to_import.uid + '==') rec_req.recordType = 0 rec_req.encryptedRecordKey = base64.urlsafe_b64decode(api.encrypt_aes(record_key, params.data_key) + '==') rec_req.howLongAgo = 0 rec_req.folderType = 1 folder_uid = None if rec_to_import.folders: folder_uid = rec_to_import.folders[0].uid if folder_uid: if folder_uid in params.folder_cache: folder = params.folder_cache[folder_uid] if folder.type in {BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType}: rec_req.folderUid = base64.urlsafe_b64decode(folder.uid + '==') rec_req.folderType = 2 if folder.type == BaseFolderNode.SharedFolderType else 3 sh_uid = folder.uid if folder.type == BaseFolderNode.SharedFolderType else folder.shared_folder_uid sf = params.shared_folder_cache[sh_uid] rec_req.encryptedRecordFolderKey = base64.urlsafe_b64decode( api.encrypt_aes(record_key, sf['shared_folder_key_unencrypted']) + '==' ) else: rec_req.folderType = 1 if folder.type != BaseFolderNode.RootFolderType: rec_req.folderUid = base64.urlsafe_b64decode(folder.uid + '==') custom_fields = [] totp = None if rec_to_import.custom_fields: for cf in rec_to_import.custom_fields: if cf == TWO_FACTOR_CODE: totp = rec_to_import.custom_fields[cf] else: custom_fields.append({ 'name': cf, 'value': rec_to_import.custom_fields[cf] }) data = { 'title': rec_to_import.title or '', 'secret1': rec_to_import.login or '', 'secret2': rec_to_import.password or '', 'link': rec_to_import.login_url or '', 'notes': rec_to_import.notes or '', 'custom': custom_fields } rec_req.recordData = base64.urlsafe_b64decode(api.encrypt_aes(json.dumps(data).encode('utf-8'), record_key) + '==') if totp: extra = { 'fields': [ { 'id': api.generate_record_uid(), 'field_type': 'totp', 'field_title': 'Two-Factor Code', 'type': 0, 'data': totp }] } rec_req.extra = base64.urlsafe_b64decode(api.encrypt_aes(json.dumps(extra).encode('utf-8'), record_key) + '==') return rec_req