diff --git a/keepercommander/commands/register.py b/keepercommander/commands/register.py index 1c1f5ed7b..fa41863b8 100644 --- a/keepercommander/commands/register.py +++ b/keepercommander/commands/register.py @@ -1240,6 +1240,8 @@ def get_sf_shares(): aram_enabled = True if shared_records: headers = ['record_owner', 'record_uid', 'record_title', 'shared_with', 'folder_path'] + if include_share_date: + headers.append('share_date') table = [] for uid, shared_record in shared_records.items(): share_events = include_share_date and aram_enabled and self.get_record_share_activities(params, uid) @@ -1258,19 +1260,23 @@ def get_sf_shares(): if show_team_users: share_info.append(f'{shared_record.owner} => Owner') for p in permissions: - is_direct_share = SharePermissions.SharePermissionsType.USER in p.types - share_date = self.get_date_for_share(share_events, p.to_name) if is_direct_share \ - else self.get_date_for_share_folder_record(share_events, next(iter(shared_record.sf_shares.keys()))) share_info.append(f'{p.get_target(show_team_users)} => {p.permissions_text}') - if share_date: - share_info.append(share_date) + if not include_share_date: + is_direct_share = SharePermissions.SharePermissionsType.USER in p.types + inline_date = self.get_date_for_share(share_events, p.to_name) if is_direct_share \ + else self.get_date_for_share_folder_record(share_events, next(iter(shared_record.sf_shares.keys()))) + if inline_date: + share_info.append(inline_date) if p.expiration > 0: dt = datetime.datetime.fromtimestamp(p.expiration // 1000) share_info.append('\t(expires on {0})'.format(str(dt))) share_info = '\n'.join(share_info) - table.append([shared_record.owner, shared_record.uid, shared_record.name, share_info, folder_paths]) + row = [shared_record.owner, shared_record.uid, shared_record.name, share_info, folder_paths] + if include_share_date: + row.append(self.get_record_share_date(share_events)) + table.append(row) if output_format != 'json': headers = [field_to_title(x) for x in headers] return dump_report_data( @@ -1400,6 +1406,18 @@ def get_date_for_share_folder_record(share_activity_list: list, shared_folder_ui return '\t(shared on {0})'.format(date_formatted) + @staticmethod + def get_record_share_date(share_events): + if not share_events: + return '' + share_types = ('share', 'record_share_outside_user', 'folder_add_record') + relevant = [e for e in share_events if e.get('audit_event_type') in share_types] + if not relevant: + return '' + earliest = min(relevant, key=lambda e: e['created']) + created = earliest['created'] + return time.strftime('%Y-%m-%d %H:%M UTC', time.gmtime(created // 1000)) + class RecordPermissionCommand(Command): def get_parser(self): diff --git a/keepercommander/commands/security_audit.py b/keepercommander/commands/security_audit.py index 7b0547ab6..225f9a4a1 100644 --- a/keepercommander/commands/security_audit.py +++ b/keepercommander/commands/security_audit.py @@ -228,7 +228,12 @@ def get_node_id(name_or_id): nodes = kwargs.get('node') or [] node_ids = [get_node_id(n) for n in nodes] - node_ids = [n for n in node_ids if n] + if nodes: + invalid_nodes = [n for n, nid in zip(nodes, node_ids) if not nid] + if invalid_nodes: + logging.error('Node(s) not found: %s', ', '.join(invalid_nodes)) + return + node_ids = [n for n in node_ids if n] score_type = kwargs.get('score_type', 'default') save_report = kwargs.get('save') or attempt_fix show_updated = save_report or kwargs.get('show_updated')