refactor to satisfy flak8

pull/14/head
scito 2 years ago committed by Roland Kurmann
parent 7f8250c0a6
commit 175e7c38e5

@ -0,0 +1,8 @@
[flake8]
ignore =
E701
exclude =
protobuf_generated_python
__pycache__
per-file-ignores =
extract_otp_secret_keys.py: F821, F401

@ -26,7 +26,7 @@ jobs:
# stop the build if there are Python syntax errors or undefined names # stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics flake8 . --count --exit-zero --max-complexity=10 --max-line-length=200 --statistics
- name: Test with pytest - name: Test with pytest
run: | run: |
pytest pytest

@ -49,17 +49,20 @@ import csv
import json import json
from urllib.parse import parse_qs, urlencode, urlparse, quote from urllib.parse import parse_qs, urlencode, urlparse, quote
from os import path, mkdir from os import path, mkdir
from re import sub, compile as rcompile from re import compile as rcompile
import protobuf_generated_python.google_auth_pb2 import protobuf_generated_python.google_auth_pb2
# https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf # https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf
def get_enum_name_by_number(parent, field_name): def get_enum_name_by_number(parent, field_name):
field_value = getattr(parent, field_name) field_value = getattr(parent, field_name)
return parent.DESCRIPTOR.fields_by_name[field_name].enum_type.values_by_number.get(field_value).name return parent.DESCRIPTOR.fields_by_name[field_name].enum_type.values_by_number.get(field_value).name
def convert_secret_from_bytes_to_base32_str(bytes): def convert_secret_from_bytes_to_base32_str(bytes):
return str(base64.b32encode(bytes), 'utf-8').replace('=', '') return str(base64.b32encode(bytes), 'utf-8').replace('=', '')
def save_qr(data, name): def save_qr(data, name):
global verbose global verbose
qr = QRCode() qr = QRCode()
@ -68,11 +71,13 @@ def save_qr(data, name):
if verbose: print('Saving to {}'.format(name)) if verbose: print('Saving to {}'.format(name))
img.save(name) img.save(name)
def print_qr(data): def print_qr(data):
qr = QRCode() qr = QRCode()
qr.add_data(data) qr.add_data(data)
qr.print_ascii() qr.print_ascii()
def parse_args(sys_args): def parse_args(sys_args):
arg_parser = argparse.ArgumentParser() arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--verbose', '-v', help='verbose output', action='store_true') arg_parser.add_argument('--verbose', '-v', help='verbose output', action='store_true')
@ -88,9 +93,11 @@ def parse_args(sys_args):
sys.exit(1) sys.exit(1)
return args return args
def sys_main(): def sys_main():
main(sys.argv[1:]) main(sys.argv[1:])
def main(sys_args): def main(sys_args):
global verbose, quiet global verbose, quiet
args = parse_args(sys_args) args = parse_args(sys_args)
@ -102,6 +109,7 @@ def main(sys_args):
write_csv(args, otps) write_csv(args, otps)
write_json(args, otps) write_json(args, otps)
def extract_otps(args): def extract_otps(args):
global verbose, quiet global verbose, quiet
quiet = args.quiet quiet = args.quiet
@ -115,7 +123,7 @@ def extract_otps(args):
if not line.startswith('otpauth-migration://'): print('\nWARN: line is not a otpauth-migration:// URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line)) if not line.startswith('otpauth-migration://'): print('\nWARN: line is not a otpauth-migration:// URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line))
parsed_url = urlparse(line) parsed_url = urlparse(line)
params = parse_qs(parsed_url.query) params = parse_qs(parsed_url.query)
if not 'data' in params: if 'data' not in params:
print('\nERROR: no data query parameter in input URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line)) print('\nERROR: no data query parameter in input URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line))
sys.exit(1) sys.exit(1)
data_encoded = params['data'][0] data_encoded = params['data'][0]
@ -135,7 +143,7 @@ def extract_otps(args):
if otp.issuer and not quiet: print('Issuer: {}'.format(otp.issuer)) if otp.issuer and not quiet: print('Issuer: {}'.format(otp.issuer))
otp_type = get_enum_name_by_number(otp, 'type') otp_type = get_enum_name_by_number(otp, 'type')
if not quiet: print('Type: {}'.format(otp_type)) if not quiet: print('Type: {}'.format(otp_type))
url_params = { 'secret': secret } url_params = {'secret': secret}
if otp.type == 1: url_params['counter'] = otp.counter if otp.type == 1: url_params['counter'] = otp.counter
if otp.issuer: url_params['issuer'] = otp.issuer if otp.issuer: url_params['issuer'] = otp.issuer
otp_url = 'otpauth://{}/{}?'.format('totp' if otp.type == 2 else 'hotp', quote(otp.name)) + urlencode(url_params) otp_url = 'otpauth://{}/{}?'.format('totp' if otp.type == 2 else 'hotp', quote(otp.name)) + urlencode(url_params)
@ -143,7 +151,7 @@ def extract_otps(args):
if args.printqr: if args.printqr:
print_qr(otp_url) print_qr(otp_url)
if args.saveqr: if args.saveqr:
if not(path.exists('qr')): mkdir('qr') if not (path.exists('qr')): mkdir('qr')
pattern = rcompile(r'[\W_]+') pattern = rcompile(r'[\W_]+')
file_otp_name = pattern.sub('', otp.name) file_otp_name = pattern.sub('', otp.name)
file_otp_issuer = pattern.sub('', otp.issuer) file_otp_issuer = pattern.sub('', otp.issuer)
@ -156,9 +164,10 @@ def extract_otps(args):
"issuer": otp.issuer, "issuer": otp.issuer,
"type": otp_type, "type": otp_type,
"url": otp_url "url": otp_url
}) })
return otps return otps
def write_csv(args, otps): def write_csv(args, otps):
global verbose, quiet global verbose, quiet
if args.csv and len(otps) > 0: if args.csv and len(otps) > 0:
@ -168,12 +177,14 @@ def write_csv(args, otps):
writer.writerows(otps) writer.writerows(otps)
if not quiet: print("Exported {} otps to csv".format(len(otps))) if not quiet: print("Exported {} otps to csv".format(len(otps)))
def write_json(args, otps): def write_json(args, otps):
global verbose, quiet global verbose, quiet
if args.json: if args.json:
with open(args.json, "w") as outfile: with open(args.json, "w") as outfile:
json.dump(otps, outfile, indent = 4) json.dump(otps, outfile, indent=4)
if not quiet: print("Exported {} otp entries to json".format(len(otps))) if not quiet: print("Exported {} otp entries to json".format(len(otps)))
if __name__ == '__main__': if __name__ == '__main__':
sys_main() sys_main()

@ -24,6 +24,7 @@ import os
import extract_otp_secret_keys import extract_otp_secret_keys
def test_extract_csv(): def test_extract_csv():
# Arrange # Arrange
cleanup() cleanup()
@ -35,11 +36,12 @@ def test_extract_csv():
expected_csv = read_csv('example_output.csv') expected_csv = read_csv('example_output.csv')
actual_csv = read_csv('test_example_output.csv') actual_csv = read_csv('test_example_output.csv')
assert actual_csv == actual_csv assert actual_csv == expected_csv
# Clean up # Clean up
cleanup() cleanup()
def test_extract_json(): def test_extract_json():
# Arrange # Arrange
cleanup() cleanup()
@ -55,13 +57,16 @@ def test_extract_json():
# Clean up # Clean up
cleanup() cleanup()
def cleanup(): def cleanup():
remove_file('test_example_output.csv') remove_file('test_example_output.csv')
remove_file('test_example_output.json') remove_file('test_example_output.json')
def remove_file(filename): def remove_file(filename):
if os.path.exists(filename): os.remove(filename) if os.path.exists(filename): os.remove(filename)
def read_csv(filename): def read_csv(filename):
"""Returns a list of lines.""" """Returns a list of lines."""
with open(filename, "r") as infile: with open(filename, "r") as infile:
@ -71,6 +76,7 @@ def read_csv(filename):
lines.append(line) lines.append(line)
return lines return lines
def read_json(filename): def read_json(filename):
"""Returns a list or a dictionary.""" """Returns a list or a dictionary."""
with open(filename, "r") as infile: with open(filename, "r") as infile:

@ -25,6 +25,7 @@ import os
import extract_otp_secret_keys import extract_otp_secret_keys
class TestExtract(unittest.TestCase): class TestExtract(unittest.TestCase):
def test_extract_csv(self): def test_extract_csv(self):
@ -53,9 +54,11 @@ class TestExtract(unittest.TestCase):
remove_file('test_example_output.csv') remove_file('test_example_output.csv')
remove_file('test_example_output.json') remove_file('test_example_output.json')
def remove_file(filename): def remove_file(filename):
if os.path.exists(filename): os.remove(filename) if os.path.exists(filename): os.remove(filename)
def read_csv(filename): def read_csv(filename):
"""Returns a list of lines.""" """Returns a list of lines."""
with open(filename, "r") as infile: with open(filename, "r") as infile:
@ -65,6 +68,7 @@ def read_csv(filename):
lines.append(line) lines.append(line)
return lines return lines
def read_json(filename): def read_json(filename):
"""Returns a list or a dictionary.""" """Returns a list or a dictionary."""
with open(filename, "r") as infile: with open(filename, "r") as infile:

Loading…
Cancel
Save