mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 01:14:15 +02:00
115 lines
3.6 KiB
Python
115 lines
3.6 KiB
Python
import os
|
|
from typing import Tuple
|
|
|
|
from PyQt5.QtCore import Qt
|
|
from PyQt5.QtGui import QCursor, QIcon
|
|
from PyQt5.QtWidgets import QInputDialog, QLineEdit, QDialogButtonBox, QApplication
|
|
|
|
from bauh.api.abstract.context import ApplicationContext
|
|
from bauh.api.abstract.view import MessageType
|
|
from bauh.commons.system import new_subprocess
|
|
from bauh.view.core.config import read_config
|
|
from bauh.view.qt import css
|
|
from bauh.view.qt.components import QtComponentsManager
|
|
from bauh.view.qt.dialog import show_message
|
|
from bauh.view.util import util
|
|
from bauh.view.util.translation import I18n
|
|
|
|
ACTION_ASK_ROOT = 99
|
|
|
|
|
|
def is_root():
|
|
return os.getuid() == 0
|
|
|
|
|
|
def ask_root_password(context: ApplicationContext, i18n: I18n,
|
|
app_config: dict = None,
|
|
comp_manager: QtComponentsManager = None) -> Tuple[str, bool]:
|
|
|
|
cur_config = read_config() if not app_config else app_config
|
|
store_password = bool(cur_config['store_root_password'])
|
|
|
|
if store_password and context.root_password and validate_password(context.root_password):
|
|
return context.root_password, True
|
|
|
|
diag = QInputDialog(flags=Qt.CustomizeWindowHint | Qt.WindowTitleHint)
|
|
diag.setStyleSheet("""QLineEdit { border-radius: 5px; font-size: 16px; border: 1px solid lightblue }""")
|
|
diag.setInputMode(QInputDialog.TextInput)
|
|
diag.setTextEchoMode(QLineEdit.Password)
|
|
diag.setWindowIcon(util.get_default_icon()[1])
|
|
diag.setWindowTitle(i18n['popup.root.title'])
|
|
diag.setLabelText('')
|
|
diag.setOkButtonText(i18n['popup.root.continue'].capitalize())
|
|
diag.setCancelButtonText(i18n['popup.button.cancel'].capitalize())
|
|
|
|
bt_box = [c for c in diag.children() if isinstance(c, QDialogButtonBox)][0]
|
|
|
|
for bt in bt_box.buttons():
|
|
if bt_box.buttonRole(bt) == QDialogButtonBox.AcceptRole:
|
|
bt.setStyleSheet(css.OK_BUTTON)
|
|
|
|
bt.setCursor(QCursor(Qt.PointingHandCursor))
|
|
bt.setIcon(QIcon())
|
|
|
|
diag.resize(400, 200)
|
|
|
|
if comp_manager:
|
|
comp_manager.save_states(state_id=ACTION_ASK_ROOT, only_visible=True)
|
|
comp_manager.disable_visible()
|
|
|
|
for attempt in range(3):
|
|
|
|
ok = diag.exec_()
|
|
|
|
if ok:
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
valid = validate_password(diag.textValue())
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
if not valid:
|
|
body = i18n['popup.root.bad_password.body']
|
|
|
|
if attempt == 2:
|
|
body += '. ' + i18n['popup.root.bad_password.last_try']
|
|
|
|
show_message(title=i18n['popup.root.bad_password.title'],
|
|
body=body,
|
|
type_=MessageType.ERROR)
|
|
ok = False
|
|
diag.setTextValue('')
|
|
|
|
if ok:
|
|
if store_password:
|
|
context.root_password = diag.textValue()
|
|
|
|
if comp_manager:
|
|
comp_manager.restore_state(ACTION_ASK_ROOT)
|
|
|
|
return diag.textValue(), ok
|
|
else:
|
|
break
|
|
|
|
if comp_manager:
|
|
comp_manager.restore_state(ACTION_ASK_ROOT)
|
|
|
|
return '', False
|
|
|
|
|
|
def validate_password(password: str) -> bool:
|
|
clean = new_subprocess(['sudo', '-k']).stdout
|
|
echo = new_subprocess(['echo', password], stdin=clean).stdout
|
|
|
|
validate = new_subprocess(['sudo', '-S', '-v'], stdin=echo)
|
|
|
|
for o in validate.stdout:
|
|
pass
|
|
|
|
for o in validate.stderr:
|
|
if o:
|
|
line = o.decode()
|
|
|
|
if 'incorrect password attempt' in line:
|
|
return False
|
|
|
|
return True
|