def pts_diff(pts, path, kind): """ Compare two stores. """ try: remote = read_or_init_remote(path) other_pts = remote.get().with_path(pts.path) remote.to_path(path) except serde.exceptions.ValidationError: other_pts = PassTheSalt.from_path(path) diff_left = pts._diff(other_pts) diff_right = other_pts._diff(pts) if diff_left.labels(): echo('Local store has the following extra/modified secrets:') _pts_ls(diff_left, kind=kind, only_labels=True) if diff_right.labels(): if diff_left.labels(): echo() echo('Remote store has the following extra/modified secrets:') _pts_ls(diff_right, kind=kind, only_labels=True) if diff_left.labels() or diff_right.labels(): exit(1)
def test_cli_initializing(): runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke(cli, ['--path', 'passthesalt'], input='John Smith\npassword\npassword\n') assert result.exit_code == 0 assert 'Initializing PassTheSalt ...' in result.output assert 'Successfully initialized PassTheSalt!' in result.output pts = PassTheSalt.from_path('passthesalt') assert pts.config.owner == 'John Smith' assert pts.config.master assert pts.config.master.is_valid('password')
def test_pts_add_login(): runner = CliRunner() with runner.isolated_filesystem(): PassTheSalt().to_path('passthesalt') result = runner.invoke( cli, ['--path', 'passthesalt', 'add'], input='Example\nwww\nwww.test.com\ntest\n\ny\nn\n', ) assert result.exit_code == 0 assert "Stored 'Example'!" in result.output pts = PassTheSalt.from_path('passthesalt') assert isinstance(pts.get('Example'), Login) assert pts.get('Example').salt == 'www.test.com|test|0'
def test_pts_add_raw(): runner = CliRunner() with runner.isolated_filesystem(): PassTheSalt().to_path('passthesalt') result = runner.invoke( cli, ['--path', 'passthesalt', 'add', '--type', 'raw'], input='Example\nsalt\ny\nn\n', ) assert result.exit_code == 0 assert "Stored 'Example'!" in result.output pts = PassTheSalt.from_path('passthesalt') assert isinstance(pts.get('Example'), Generatable) assert pts.get('Example').salt == 'salt'
def test_pts_edit_encrypted_aborted(): def edit(data): return None with mock.patch('click.edit', edit): runner = CliRunner() with runner.isolated_filesystem(): pts = pts_edit_encrypted_setup() result = runner.invoke(cli, ['--path', 'passthesalt', 'edit'], input='Example\npassword\nn\n') assert result.exit_code == 1 assert result.output.endswith('Aborted!\n') pts = PassTheSalt.from_path('passthesalt').with_master('password') assert isinstance(pts.get('Example'), Encrypted) assert pts.get('Example').get() == 'verysecret'
def test_pts_edit_generatable_aborted(): def edit(data): return None with mock.patch('click.edit', edit): runner = CliRunner() with runner.isolated_filesystem(): pts = pts_edit_generatable_setup() result = runner.invoke(cli, ['--path', 'passthesalt', 'edit'], input='Example\nn\n') assert result.exit_code == 1 assert result.output.endswith('Aborted!\n') pts = PassTheSalt.from_path('passthesalt') assert isinstance(pts.get('Example'), Generatable) assert pts.get('Example').salt == 'salt'
def test_pts_edit_generatable(): def edit(data): return data.replace('salt = "salt"', 'salt = "test"') with mock.patch('click.edit', edit): runner = CliRunner() with runner.isolated_filesystem(): pts = pts_edit_generatable_setup() result = runner.invoke(cli, ['--path', 'passthesalt', 'edit'], input='Example\nn\n') assert result.exit_code == 0 assert "Updated 'Example'!\n" in result.output pts = PassTheSalt.from_path('passthesalt') assert isinstance(pts.get('Example'), Generatable) assert pts.get('Example').salt == 'test'
def test_pts_encrypt(): runner = CliRunner() with runner.isolated_filesystem(): pts = PassTheSalt(config=Config(master=Master('password'))) pts.to_path('passthesalt') result = runner.invoke( cli, ['--path', 'passthesalt', 'encrypt'], input='Example\nsecret\nsecret\npassword\n', ) assert result.exit_code == 0 assert "Stored 'Example'!" in result.output pts = PassTheSalt.from_path('passthesalt').with_master('password') assert isinstance(pts.get('Example'), Encrypted) assert pts.get('Example').get() == 'secret'
def cli(ctx, path): """ \b ____ ________ _____ ____ / __ \\____ _________/_ __/ /_ ___ / ___/____ _/ / /_ / /_/ / __ `/ ___/ ___// / / __ \\/ _ \\\\__ \\/ __ `/ / __/ / ____/ /_/ (__ |__ )/ / / / / / __/__/ / /_/ / / /_ /_/ \\__,_/____/____//_/ /_/ /_/\\___/____/\\__,_/_/\\__/ A deterministic password generation and password storage system. """ pts = None try: pts = (PassTheSalt.from_path(path).with_master( ask_user_for_master).with_path(path)) except OSError: pass # The only time pts is allowed to be None is if we are pulling a store. if ctx.invoked_subcommand != 'pull': if pts is None: echo('Initializing PassTheSalt ...') pts = PassTheSalt().with_master(ask_user_for_master).with_path( path) pts.config.owner = prompt('Please enter your name') pts.config.master = Master( prompt( 'Please enter the master password', confirmation_prompt=True, hide_input=True, )) pts.save() echo('Successfully initialized PassTheSalt!') elif ctx.invoked_subcommand is None: echo(ctx.get_help()) ctx.obj = pts or path