jp: password is now prompted if needed:
if password is not specified on command line, it is now prompted if it is needed to start a profile session or connect it. The password is prompted with echo disabled, so somebody seing the computer screen can't see the password. fix 207
This commit is contained in:
parent
5fbbd75f9f
commit
36ccde03b9
1 changed files with 58 additions and 11 deletions
|
|
@ -46,6 +46,7 @@ from sat.core import exceptions
|
|||
import sat_frontends.jp
|
||||
from sat_frontends.jp.loops import QuitException, getJPLoop
|
||||
from sat_frontends.jp.constants import Const as C
|
||||
from sat_frontends.bridge.bridge_frontend import BridgeException
|
||||
from sat_frontends.tools import misc
|
||||
import xml.etree.ElementTree as ET # FIXME: used temporarily to manage XMLUI
|
||||
from collections import OrderedDict
|
||||
|
|
@ -288,7 +289,7 @@ class Jp(object):
|
|||
"-p", "--profile", action="store", type=str, default='@DEFAULT@',
|
||||
help=_("Use PROFILE profile key (default: %(default)s)"))
|
||||
parent.add_argument(
|
||||
"--pwd", action="store", default='', metavar='PASSWORD',
|
||||
"--pwd", action="store", metavar='PASSWORD',
|
||||
help=_("Password used to connect profile, if necessary"))
|
||||
|
||||
profile_parent, profile_session_parent = (self.parents['profile'],
|
||||
|
|
@ -773,6 +774,54 @@ class Jp(object):
|
|||
|
||||
return dest_jids
|
||||
|
||||
async def a_pwd_input(self, msg=''):
|
||||
"""Like ainput but with echo disabled (useful for passwords)"""
|
||||
# we disable echo, code adapted from getpass standard module which has been
|
||||
# written by Piers Lauder (original), Guido van Rossum (Windows support and
|
||||
# cleanup) and Gregory P. Smith (tty support & GetPassWarning), a big thanks
|
||||
# to them (and for all the amazing work on Python).
|
||||
stdin_fd = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(sys.stdin)
|
||||
new = old[:]
|
||||
new[3] &= ~termios.ECHO
|
||||
tcsetattr_flags = termios.TCSAFLUSH
|
||||
if hasattr(termios, 'TCSASOFT'):
|
||||
tcsetattr_flags |= termios.TCSASOFT
|
||||
try:
|
||||
termios.tcsetattr(stdin_fd, tcsetattr_flags, new)
|
||||
pwd = await self.ainput(msg=msg)
|
||||
finally:
|
||||
termios.tcsetattr(stdin_fd, tcsetattr_flags, old)
|
||||
sys.stderr.flush()
|
||||
self.disp('')
|
||||
return pwd
|
||||
|
||||
async def connectOrPrompt(self, method, err_msg=None):
|
||||
"""Try to connect/start profile session and prompt for password if needed
|
||||
|
||||
@param method(callable): bridge method to either connect or start profile session
|
||||
It will be called with password as sole argument, use lambda to do the call
|
||||
properly
|
||||
@param err_msg(str): message to show if connection fail
|
||||
"""
|
||||
password = self.args.pwd
|
||||
while True:
|
||||
try:
|
||||
await method(password or '')
|
||||
except Exception as e:
|
||||
if ((isinstance(e, BridgeException)
|
||||
and e.classname == 'PasswordError'
|
||||
and self.args.pwd is None)):
|
||||
if password is not None:
|
||||
self.disp(A.color(C.A_WARNING, _("invalid password")))
|
||||
password = await self.a_pwd_input(
|
||||
_("please enter profile password:"))
|
||||
else:
|
||||
self.disp(err_msg.format(profile=self.profile, e=e), error=True)
|
||||
self.quit(C.EXIT_ERROR)
|
||||
else:
|
||||
break
|
||||
|
||||
async def connect_profile(self):
|
||||
"""Check if the profile is connected and do it if requested
|
||||
|
||||
|
|
@ -794,11 +843,10 @@ class Jp(object):
|
|||
pass
|
||||
else:
|
||||
if start_session:
|
||||
try:
|
||||
await self.bridge.profileStartSession(self.args.pwd, self.profile)
|
||||
except Exception as e:
|
||||
self.disp(_(f"Can't start {self.profile}'s session: {e}"), err=True)
|
||||
self.quit(1)
|
||||
await self.connectOrPrompt(
|
||||
lambda pwd: self.bridge.profileStartSession(pwd, self.profile),
|
||||
err_msg="Can't start {profile}'s session: {e}"
|
||||
)
|
||||
return
|
||||
elif not await self.bridge.profileIsSessionStarted(self.profile):
|
||||
if not self.args.connect:
|
||||
|
|
@ -816,11 +864,10 @@ class Jp(object):
|
|||
# creation/deletion)
|
||||
return
|
||||
elif self.args.connect is True: # if connection is asked, we connect the profile
|
||||
try:
|
||||
await self.bridge.connect(self.profile, self.args.pwd, {})
|
||||
except Exception as e:
|
||||
self.disp(_(f"Can't connect profile: {e}"), error=True)
|
||||
self.quit(1)
|
||||
await self.connectOrPrompt(
|
||||
lambda pwd: self.bridge.connect(self.profile, pwd, {}),
|
||||
err_msg = 'Can\'t connect profile "{profile!s}": {e}'
|
||||
)
|
||||
return
|
||||
else:
|
||||
if not await self.bridge.isConnected(self.profile):
|
||||
|
|
|
|||
Loading…
Reference in a new issue