#!/usr/bin/python3 import os import subprocess from typing import Union class Pass: def __init__(self): self.top_dir: str = os.environ.get('PASSWORD_STORE_DIR') self.is_init = False if not self.top_dir: self.top_dir = os.environ.get('HOME') + '/.password-store' if os.path.isdir(self.top_dir): self.set_paths_on_init() def delete_password(self, path: str): """delete_password. :param path: str """ command1: list[str] = ['/usr/bin/pass', 'rm', '-f', path] run_command(command1) self.move_up() self.cur_paths = self.get_pass_paths() self.cur_passwords = self.get_pass_passwords() def get_pass_path_from_index(self, index: int, path_type: str = "path") -> str: """get_pass_path_from_index. :param index: int :param path_type: str, default: "path" """ if path_type == "password": result: str = self.cur_passwords[index] else: result: str = self.cur_paths[index] return result.replace(self.top_dir, '').replace('.gpg', '') def get_pass_passwords(self) -> list[str]: """get_pass_passwords.""" passwords: list[str] = list() for m_file in os.listdir(self.cur_dir): if m_file.endswith(".gpg"): passwords.append(os.path.join(self.cur_dir, m_file)) passwords = sorted(passwords) return passwords def get_pass_paths(self) -> list[str]: """get_pass_paths.""" dirs: list[str] = list() if self.cur_dir != self.top_dir: dirs.append(self.cur_dir) for c_dir in os.listdir(self.cur_dir): if os.path.isdir(os.path.join(self.cur_dir, c_dir)) and c_dir != ".git": dirs.append(os.path.join(self.cur_dir, c_dir)) dirs = sorted(dirs) return dirs def move_up(self) -> bool: """move_up.""" if self.cur_dir == self.top_dir: return True if not os.path.isdir(self.cur_dir): self.cur_dir = os.path.abspath(os.path.join(self.cur_dir, os.pardir)) self.move_up() return True def pass_init(self, gpg_key: str, git_repo: Union[None, str] = None): """pass_init. """ if git_repo: run_command(['/usr/bin/git', 'clone', git_repo, self.top_dir]) else: run_command(['/usr/bin/pass', 'init', gpg_key]) self.set_paths_on_init() def save_to_pass(self, password, path, full_path): command1: list[str] = ['/bin/echo', password.rstrip("\n")] command2: list[str] = ['/usr/bin/pass', 'insert', '-m', path] run_command(command1, command2) self.cur_paths = sorted([full_path] + self.cur_paths) self.cur_passwords = self.get_pass_passwords() def set_paths_on_init(self): """set_paths_on_init. """ self.cur_dir: str = self.top_dir self.cur_paths: list[str] = self.get_pass_paths() self.cur_passwords: list[str] = self.get_pass_passwords() self.is_init = True def copy_to_clipboard(text) -> tuple[Union[str, bytes], Union[str, bytes]]: """copy_to_clipboard. :param text: """ clip_command = ['/usr/bin/wl-copy'] if not os.path.isfile(clip_command[0]): clip_command = ['xclip', '-selection', 'c'] password: str = text.split('\n')[0] command1: list[str] = ['/bin/echo', password] command2: list[str] = clip_command result: tuple[Union[str, bytes], Union[str, bytes]] = run_command(command1, command2) return result def get_password_from_path(pass_path) -> str: """get_password_from_path. :param pass_path: """ result: tuple[Union[str, bytes], Union[str, bytes]] = run_command(['/usr/bin/pass', 'show', pass_path]) if type(result[0]) == type(bytes()): password: str = result[0].decode() else: password: str = result[0] return password def pass_pull(): """pass_pull. """ run_command(['/usr/bin/pass', 'git', 'pull']) def pass_push(): """pass_push. """ run_command(['/usr/bin/pass', 'git', 'push']) def run_command(command1, command2=None) -> tuple[Union[str, bytes], Union[str, bytes]]: """Run a command on system and capture result :param command1: :param command2: """ process1: subprocess.Popen = subprocess.Popen(command1, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # If there is a second command it is taken to be a pipeline if command2: subprocess.Popen(command2, shell=False, stdin=process1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE) process1.stdout.close() return process1.communicate()