Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a (b)ack option to 'Is this a valid secret?' Closes Issue #63 #72

Merged
merged 8 commits into from
Sep 11, 2018
15 changes: 12 additions & 3 deletions detect_secrets/core/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .color import BashColor
from .color import Color
from .potential_secret import PotentialSecret
from .bidirectional_iterator import BidirectionalIterator


class SecretNotFoundOnSpecifiedLineError(Exception):
Expand All @@ -29,7 +30,8 @@ def audit_baseline(baseline_filename):

current_secret_index = 0
results = defaultdict(list)
for filename, secret, total in _secret_generator(original_baseline):
secret_iterator = BidirectionalIterator(list(_secret_generator(original_baseline)))
for filename, secret, total in secret_iterator:
_clear_screen()

if 'is_secret' not in secret:
Expand All @@ -43,7 +45,7 @@ def audit_baseline(baseline_filename):
total,
original_baseline['plugins_used'],
)
decision = _get_user_decision()
decision = _get_user_decision(can_step_back=secret_iterator.can_step_back())
except SecretNotFoundOnSpecifiedLineError:
decision = _get_user_decision(prompt_secret_decision=False)
else:
Expand All @@ -54,6 +56,9 @@ def audit_baseline(baseline_filename):
if decision == 'q':
print('Quitting...')
break

if decision == 'b':
secret_iterator.step_back_on_next_iteration()

_handle_user_decision(decision, secret)
results[filename].append(secret)
Expand Down Expand Up @@ -174,14 +179,16 @@ def _print_context(filename, secret, count, total, plugin_settings): # pragma:
raise error_obj


def _get_user_decision(prompt_secret_decision=True):
def _get_user_decision(prompt_secret_decision=True, can_step_back=False):
"""
:type prompt_secret_decision: bool
:param prompt_secret_decision: if False, won't ask to label secret.
"""
allowable_user_input = ['s', 'q']
if prompt_secret_decision:
allowable_user_input.extend(['y', 'n'])
if can_step_back:
allowable_user_input.append('b')

user_input = None
while user_input not in allowable_user_input:
Expand All @@ -192,6 +199,8 @@ def _get_user_decision(prompt_secret_decision=True):
user_input_string = 'Is this a valid secret? (y)es, (n)o, '
else:
user_input_string = 'What would you like to do? '
if 'b' in allowable_user_input:
user_input_string += '(b)ack, '
user_input_string += '(s)kip, (q)uit: '

user_input = input(user_input_string)
Expand Down
31 changes: 31 additions & 0 deletions detect_secrets/core/bidirectional_iterator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class BidirectionalIterator(object):
def __init__(self, collection):
self.collection = collection
self.index = -1 #starts on -1, as index is increased _before_ getting result
self.step_back_once = False

def __next__(self):
try:
if self.step_back_once:
self.index -= 1
self.step_back_once = False
if self.index < 0:
raise StopIteration
else:
self.index += 1
result = self.collection[self.index]
cleborys marked this conversation as resolved.
Show resolved Hide resolved
except IndexError:
raise StopIteration
return result

def next(self):
Copy link
Collaborator

@KevinHock KevinHock Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Looping should call the __next__ method directly, so no need for a next method 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added next to be python2 compatible (it was renamed form next to __next__ from python2 to 3).
However, this does not feel very clean - perhaps you know of a better way? :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha! Very good point, I only tested on Python 3. My bad. I am impressed by how thorough you are 👍

self.__next__()

def step_back_on_next_iteration(self):
self.step_back_once = True

def can_step_back(self):
return self.index > 0

def __iter__(self):
return self