|
|
@ -3,13 +3,14 @@
|
|
|
|
A mobile first interface for the standard unix password manager written in python
|
|
|
|
A mobile first interface for the standard unix password manager written in python
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
|
|
|
|
import tempfile
|
|
|
|
from typing import Union
|
|
|
|
from typing import Union
|
|
|
|
|
|
|
|
|
|
|
|
import wx
|
|
|
|
import wx
|
|
|
|
import wx.lib.scrolledpanel as scrolled
|
|
|
|
import wx.lib.scrolledpanel as scrolled
|
|
|
|
import gnupg
|
|
|
|
import gnupg
|
|
|
|
|
|
|
|
|
|
|
|
from pass_handler import Pass, copy_to_clipboard, get_password_from_path, pass_pull, pass_push
|
|
|
|
from pass_handler import Pass, copy_to_clipboard, get_password_from_path, pass_pull, pass_push, run_command
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PassUi(wx.Frame):
|
|
|
|
class PassUi(wx.Frame):
|
|
|
@ -42,6 +43,7 @@ class PassUi(wx.Frame):
|
|
|
|
:param kw:
|
|
|
|
:param kw:
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
super().__init__(*args, **kw)
|
|
|
|
super().__init__(*args, **kw)
|
|
|
|
|
|
|
|
self.file_str: str = str()
|
|
|
|
self.pass_handler: Pass = Pass()
|
|
|
|
self.pass_handler: Pass = Pass()
|
|
|
|
self.gpg_handler: gnupg.GPG = gnupg.GPG()
|
|
|
|
self.gpg_handler: gnupg.GPG = gnupg.GPG()
|
|
|
|
self.gpg_key: str = str()
|
|
|
|
self.gpg_key: str = str()
|
|
|
@ -98,12 +100,16 @@ class PassUi(wx.Frame):
|
|
|
|
self.sizer.Add(choice, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
self.sizer.Add(choice, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
select_label: str = "Select New GPG Key"
|
|
|
|
select_label: str = "Select New GPG Key"
|
|
|
|
gpg_btn: wx.Button = wx.Button(self.pnl, label=select_label)
|
|
|
|
gpg_btn: wx.Button = wx.Button(self.pnl, label=select_label)
|
|
|
|
init_btn: wx.Button = wx.Button(self.pnl, label="Init Local Password Store")
|
|
|
|
|
|
|
|
self.sizer.Add(gpg_btn, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
self.sizer.Add(gpg_btn, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
self.sizer.Add(init_btn, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
|
|
|
|
self.Bind(wx.EVT_BUTTON,
|
|
|
|
self.Bind(wx.EVT_BUTTON,
|
|
|
|
lambda event: self.gpg_button_clicked(), gpg_btn)
|
|
|
|
lambda event: self.gpg_button_clicked(), gpg_btn)
|
|
|
|
if self.gpg_key:
|
|
|
|
if self.gpg_key:
|
|
|
|
|
|
|
|
init_btn: wx.Button = wx.Button(self.pnl, label="Init Local Password Store")
|
|
|
|
|
|
|
|
git_btn: wx.Button = wx.Button(self.pnl, label="Init Git Password Store")
|
|
|
|
|
|
|
|
self.sizer.Add(init_btn, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
|
|
|
|
self.sizer.Add(git_btn, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
|
|
|
|
self.Bind(wx.EVT_BUTTON,
|
|
|
|
|
|
|
|
lambda event: self.git_button_clicked(), git_btn)
|
|
|
|
self.Bind(wx.EVT_BUTTON,
|
|
|
|
self.Bind(wx.EVT_BUTTON,
|
|
|
|
lambda event: self.init_button_clicked(), init_btn)
|
|
|
|
lambda event: self.init_button_clicked(), init_btn)
|
|
|
|
|
|
|
|
|
|
|
@ -170,6 +176,14 @@ class PassUi(wx.Frame):
|
|
|
|
btn.SetFont(font)
|
|
|
|
btn.SetFont(font)
|
|
|
|
return btn
|
|
|
|
return btn
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def git_button_clicked(self):
|
|
|
|
|
|
|
|
"""git_button_clicked.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
git_repo: str = self.show_git_picker()
|
|
|
|
|
|
|
|
# self.pass_handler.pass_init(self.gpg_key, git_repo)
|
|
|
|
|
|
|
|
# self.add_buttons()
|
|
|
|
|
|
|
|
|
|
|
|
def gpg_button_clicked(self):
|
|
|
|
def gpg_button_clicked(self):
|
|
|
|
"""gpg_button_clicked.
|
|
|
|
"""gpg_button_clicked.
|
|
|
|
|
|
|
|
|
|
|
@ -181,11 +195,11 @@ class PassUi(wx.Frame):
|
|
|
|
uid_list.append(uid)
|
|
|
|
uid_list.append(uid)
|
|
|
|
self.show_choice(uid_list, "Select GNUPG Key")
|
|
|
|
self.show_choice(uid_list, "Select GNUPG Key")
|
|
|
|
|
|
|
|
|
|
|
|
def init_button_clicked(self):
|
|
|
|
def init_button_clicked(self, repo: Union[str, None] = None):
|
|
|
|
"""init_button_clicked.
|
|
|
|
"""init_button_clicked.
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
self.pass_handler.pass_init(self.gpg_key)
|
|
|
|
self.pass_handler.pass_init(self.gpg_key, repo)
|
|
|
|
self.add_buttons()
|
|
|
|
self.add_buttons()
|
|
|
|
|
|
|
|
|
|
|
|
def password_button_clicked(self, index: int):
|
|
|
|
def password_button_clicked(self, index: int):
|
|
|
@ -381,6 +395,50 @@ class PassUi(wx.Frame):
|
|
|
|
n_btn)
|
|
|
|
n_btn)
|
|
|
|
self.add_push_pull()
|
|
|
|
self.add_push_pull()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@redraw
|
|
|
|
|
|
|
|
def show_git_picker(self):
|
|
|
|
|
|
|
|
widget_list: list[Union[wx.StaticText, wx.TextCtrl, wx.Button]] = list()
|
|
|
|
|
|
|
|
widget_list.append(wx.StaticText(self.pnl, label='Username:'))
|
|
|
|
|
|
|
|
widget_list.append(wx.TextCtrl(self.pnl))
|
|
|
|
|
|
|
|
widget_list.append(wx.StaticText(self.pnl, label='Password:'))
|
|
|
|
|
|
|
|
widget_list.append(wx.TextCtrl(self.pnl, style=wx.TE_PASSWORD))
|
|
|
|
|
|
|
|
widget_list.append(wx.StaticText(self.pnl, label='Protocol:'))
|
|
|
|
|
|
|
|
widget_list.append(wx.Choice(self.pnl, choices=['https', 'git', 'git+ssh']))
|
|
|
|
|
|
|
|
widget_list[5].SetSelection(0)
|
|
|
|
|
|
|
|
widget_list.append(wx.StaticText(self.pnl, label='Hostname:'))
|
|
|
|
|
|
|
|
widget_list.append(wx.TextCtrl(self.pnl, value='example.org'))
|
|
|
|
|
|
|
|
widget_list.append(wx.StaticText(self.pnl, label='Port:'))
|
|
|
|
|
|
|
|
widget_list.append(wx.TextCtrl(self.pnl, value='443'))
|
|
|
|
|
|
|
|
widget_list.append(wx.StaticText(self.pnl, label='Path to repo:'))
|
|
|
|
|
|
|
|
widget_list.append(wx.TextCtrl(self.pnl, value='/'))
|
|
|
|
|
|
|
|
widget_list.append(wx.Button(self.pnl, label="Submit"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for widget in widget_list:
|
|
|
|
|
|
|
|
self.sizer.Add(widget, 0, wx.EXPAND) # pylint: disable=no-member
|
|
|
|
|
|
|
|
self.Bind(wx.EVT_BUTTON, lambda event, m_widgets=widget_list: self.git_submit_btn_clicked(m_widgets),
|
|
|
|
|
|
|
|
widget_list[12])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def git_submit_btn_clicked(self, widget_list) -> str:
|
|
|
|
|
|
|
|
default_ports = {'git': 9418, 'git+ssh': 22, 'https': 443}
|
|
|
|
|
|
|
|
user: str = widget_list[1].GetLineText(0)
|
|
|
|
|
|
|
|
password: str = widget_list[3].GetLineText(0)
|
|
|
|
|
|
|
|
protocol: str = widget_list[5].GetString(widget_list[5].GetSelection())
|
|
|
|
|
|
|
|
host: str = widget_list[7].GetLineText(0)
|
|
|
|
|
|
|
|
port: str = widget_list[9].GetLineText(0)
|
|
|
|
|
|
|
|
path: str = widget_list[11].GetLineText(0)
|
|
|
|
|
|
|
|
if not port:
|
|
|
|
|
|
|
|
port = default_ports[protocol]
|
|
|
|
|
|
|
|
self.file_str = 'protocol={}\nhost={}:{}{}\nusername=\npassword={}\n'.format(protocol, host, port, path, user,
|
|
|
|
|
|
|
|
password)
|
|
|
|
|
|
|
|
timeout_in_sec = 24 * 60 * 60
|
|
|
|
|
|
|
|
temp_tuple = tempfile.mkstemp(text=self.file_str)
|
|
|
|
|
|
|
|
run_command(['/usr/bin/git', 'credential-store', '--file', temp_tuple[1]])
|
|
|
|
|
|
|
|
run_command(
|
|
|
|
|
|
|
|
['/usr/bin/git', 'config', 'credential.helper', 'cache --timeout={}'.format(timeout_in_sec)])
|
|
|
|
|
|
|
|
os.unlink(temp_tuple[1])
|
|
|
|
|
|
|
|
self.init_button_clicked('{}://{}:{}{}'.format(protocol, host, port, path))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
if __name__ == '__main__':
|
|
|
|
# When this module is run (not imported) then create the app, the
|
|
|
|
# When this module is run (not imported) then create the app, the
|
|
|
|
# frame, show it, and start the event loop.
|
|
|
|
# frame, show it, and start the event loop.
|
|
|
|