[feature][flatpak] registering Flathub at system level

This commit is contained in:
Vinícius Moreira
2020-01-13 14:41:01 -03:00
parent 9f15b1b244
commit 8dd114da85
13 changed files with 84 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
from typing import List from typing import List, Tuple
from bauh.api.abstract.view import MessageType, ViewComponent from bauh.api.abstract.view import MessageType, ViewComponent
@@ -65,3 +65,9 @@ class ProcessWatcher:
""" """
:return: if the use requested to stop the process. :return: if the use requested to stop the process.
""" """
def request_root_password(self) -> Tuple[str, bool]:
"""
asks the root password for the user
:return: a tuple with the typed password and if it is valid
"""

View File

@@ -4,7 +4,6 @@ from threading import Thread
import urllib3 import urllib3
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication from PyQt5.QtWidgets import QApplication
from bauh import __version__, __app_name__, app_args, ROOT_DIR from bauh import __version__, __app_name__, app_args, ROOT_DIR
@@ -15,7 +14,7 @@ from bauh.view.core.controller import GenericSoftwareManager
from bauh.view.core.downloader import AdaptableFileDownloader from bauh.view.core.downloader import AdaptableFileDownloader
from bauh.view.qt.systray import TrayIcon from bauh.view.qt.systray import TrayIcon
from bauh.view.qt.window import ManageWindow from bauh.view.qt.window import ManageWindow
from bauh.view.util import util, logs, resource, translation from bauh.view.util import util, logs, translation
from bauh.view.util.cache import DefaultMemoryCacheFactory, CacheCleaner from bauh.view.util.cache import DefaultMemoryCacheFactory, CacheCleaner
from bauh.view.util.disk import DefaultDiskCacheLoaderFactory from bauh.view.util.disk import DefaultDiskCacheLoaderFactory
from bauh.view.util.translation import I18n from bauh.view.util.translation import I18n

5
bauh/commons/user.py Normal file
View File

@@ -0,0 +1,5 @@
import os
def is_root():
return os.getuid() == 0

View File

@@ -9,6 +9,7 @@ from bauh.api.abstract.handler import ProcessWatcher
from bauh.api.abstract.model import PackageHistory, PackageUpdate, SoftwarePackage, PackageSuggestion, \ from bauh.api.abstract.model import PackageHistory, PackageUpdate, SoftwarePackage, PackageSuggestion, \
SuggestionPriority SuggestionPriority
from bauh.api.abstract.view import MessageType from bauh.api.abstract.view import MessageType
from bauh.commons import user
from bauh.commons.html import strip_html, bold from bauh.commons.html import strip_html, bold
from bauh.commons.system import SystemProcess, ProcessHandler, SimpleProcess from bauh.commons.system import SystemProcess, ProcessHandler, SimpleProcess
from bauh.gems.flatpak import flatpak, SUGGESTIONS_FILE, CONFIG_FILE from bauh.gems.flatpak import flatpak, SUGGESTIONS_FILE, CONFIG_FILE
@@ -67,7 +68,7 @@ class FlatpakManager(SoftwareManager):
remote_level = 'user' remote_level = 'user'
else: else:
remote_level = 'user' remote_level = 'user'
flatpak.set_default_remotes(remote_level) ProcessHandler().handle_simple(flatpak.set_default_remotes(remote_level))
return remote_level return remote_level
@@ -264,8 +265,28 @@ class FlatpakManager(SoftwareManager):
deny_label=self.i18n['yes'].capitalize()) deny_label=self.i18n['yes'].capitalize())
pkg.installation = 'user' if user_level else 'system' pkg.installation = 'user' if user_level else 'system'
remotes = flatpak.list_remotes()
handler = ProcessHandler(watcher) handler = ProcessHandler(watcher)
if pkg.installation == 'user' and not remotes['user']:
handler.handle_simple(flatpak.set_default_remotes('user'))
elif pkg.installation == 'system' and not remotes['system']:
if user.is_root():
handler.handle_simple(flatpak.set_default_remotes('system'))
else:
user_password, valid = watcher.request_root_password()
if not valid:
watcher.print('Operation aborted')
return False
else:
if not handler.handle_simple(flatpak.set_default_remotes('system', user_password)):
watcher.show_message(title=self.i18n['error'].capitalize(),
body=self.i18n['flatpak.remotes.system_flathub.error'],
type_=MessageType.ERROR)
watcher.print("Operation cancelled")
return False
if pkg.installation == 'user': if pkg.installation == 'user':
if not handler.handle_simple(flatpak.register_flathub('user')): if not handler.handle_simple(flatpak.register_flathub('user')):
return False return False
@@ -318,7 +339,7 @@ class FlatpakManager(SoftwareManager):
loader.join() loader.join()
for app in to_update: for app in to_update:
updates.append(PackageUpdate(pkg_id='{}:{}'.format(app.id, app.branch), updates.append(PackageUpdate(pkg_id='{}:{}:{}'.format(app.id, app.branch, app.installation),
pkg_type='flatpak', pkg_type='flatpak',
version=app.version)) version=app.version))

View File

@@ -6,7 +6,7 @@ from io import StringIO
from typing import List, Dict, Set from typing import List, Dict, Set
from bauh.api.exception import NoInternetException from bauh.api.exception import NoInternetException
from bauh.commons.system import new_subprocess, run_cmd, new_root_subprocess, SimpleProcess from bauh.commons.system import new_subprocess, run_cmd, new_root_subprocess, SimpleProcess, SystemProcess
BASE_CMD = 'flatpak' BASE_CMD = 'flatpak'
RE_SEVERAL_SPACES = re.compile(r'\s+') RE_SEVERAL_SPACES = re.compile(r'\s+')
@@ -343,8 +343,9 @@ def install(app_id: str, origin: str, installation: str):
return new_subprocess([BASE_CMD, 'install', origin, app_id, '-y', '--{}'.format(installation)]) return new_subprocess([BASE_CMD, 'install', origin, app_id, '-y', '--{}'.format(installation)])
def set_default_remotes(installation: str): def set_default_remotes(installation: str, root_password: str = None) -> SimpleProcess:
run_cmd('{} remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo --{}'.format(BASE_CMD, installation)) cmd = [BASE_CMD, 'remote-add', '--if-not-exists', 'flathub', 'https://flathub.org/repo/flathub.flatpakrepo', '--{}'.format(installation)]
return SimpleProcess(cmd, root_password=root_password)
def has_remotes_set() -> bool: def has_remotes_set() -> bool:

View File

@@ -44,4 +44,5 @@ flatpak.info.translateurl=Traducció
flatpak.info.developername=desenvolupador flatpak.info.developername=desenvolupador
flatpak.install.install_level.title=Tipus d'instal·lació flatpak.install.install_level.title=Tipus d'instal·lació
flatpak.install.install_level.body=S'ha d'instal·lar {} per a tots els usuaris del dispositiu ( sistema ) ? flatpak.install.install_level.body=S'ha d'instal·lar {} per a tots els usuaris del dispositiu ( sistema ) ?
flatpak.install.bad_install_level.body=Valor invàlid per a {field} al fitxer de configuració {file} flatpak.install.bad_install_level.body=Valor invàlid per a {field} al fitxer de configuració {file}
flatpak.remotes.system_flathub.error=No s'ha pogut afegir Flathub com a dipòsit del sistema ( remote )

View File

@@ -43,4 +43,5 @@ flatpak.history.date=Datum
flatpak.history.commit=Commit flatpak.history.commit=Commit
flatpak.install.install_level.title=Installationstyp flatpak.install.install_level.title=Installationstyp
flatpak.install.install_level.body=Sollte {} für alle Gerätebenutzer installiert werden ( system ) ? flatpak.install.install_level.body=Sollte {} für alle Gerätebenutzer installiert werden ( system ) ?
flatpak.install.bad_install_level.body=Ungültiger Wert für {field} in der Konfigurationsdatei {file} flatpak.install.bad_install_level.body=Ungültiger Wert für {field} in der Konfigurationsdatei {file}
flatpak.remotes.system_flathub.error=Flathub konnte nicht als System-Repository ( remote ) hinzugefügt werden

View File

@@ -43,4 +43,5 @@ flatpak.history.date=date
flatpak.history.commit=commit flatpak.history.commit=commit
flatpak.install.install_level.title=Installation type flatpak.install.install_level.title=Installation type
flatpak.install.install_level.body=Should {} be installed for all the device users ( system ) ? flatpak.install.install_level.body=Should {} be installed for all the device users ( system ) ?
flatpak.install.bad_install_level.body=Invalid value for {field} in the configuration file {file} flatpak.install.bad_install_level.body=Invalid value for {field} in the configuration file {file}
flatpak.remotes.system_flathub.error=It was not possible to add Flathub as a system repository ( remote )

View File

@@ -44,4 +44,5 @@ flatpak.info.translateurl=Traducción
flatpak.info.developername=desarrollador flatpak.info.developername=desarrollador
flatpak.install.install_level.title=Tipo de instalación flatpak.install.install_level.title=Tipo de instalación
flatpak.install.install_level.body=¿Debería {} estar instalado para todos los usuarios del dispositivo ( sistema )? flatpak.install.install_level.body=¿Debería {} estar instalado para todos los usuarios del dispositivo ( sistema )?
flatpak.install.bad_install_level.body=Valor inválido para {field} en el archivo de configuración {file} flatpak.install.bad_install_level.body=Valor inválido para {field} en el archivo de configuración {file}
flatpak.remotes.system_flathub.error=No fue posible agregar Flathub como repositorio del sistema ( remote )

View File

@@ -23,4 +23,5 @@ flatpak.info.installation.user=utente
flatpak.info.installation.system=sistema flatpak.info.installation.system=sistema
flatpak.install.install_level.title=Tipo di installazione flatpak.install.install_level.title=Tipo di installazione
flatpak.install.install_level.body={} deve essere installato per tutti gli utenti del dispositivo ( sistema ) ? flatpak.install.install_level.body={} deve essere installato per tutti gli utenti del dispositivo ( sistema ) ?
flatpak.install.bad_install_level.body=Valore non valido per {field} nel file di configurazione {file} flatpak.install.bad_install_level.body=Valore non valido per {field} nel file di configurazione {file}
flatpak.remotes.system_flathub.error=Non è stato possibile aggiungere Flathub come repository di sistema ( remote )

View File

@@ -44,4 +44,5 @@ flatpak.info.translateurl=tradução
flatpak.info.developername=desenvolvedor flatpak.info.developername=desenvolvedor
flatpak.install.install_level.title=Tipo de instalação flatpak.install.install_level.title=Tipo de instalação
flatpak.install.install_level.body={} deve ser instalado para todos os usuários desse dispositivo ( sistema ) ? flatpak.install.install_level.body={} deve ser instalado para todos os usuários desse dispositivo ( sistema ) ?
flatpak.install.bad_install_level.body=Valor inválido para {field} no arquivo de configuração {file} flatpak.install.bad_install_level.body=Valor inválido para {field} no arquivo de configuração {file}
flatpak.remotes.system_flathub.error=Não foi possível adicionar o Flathub como um repositório do sistema ( remote )

View File

@@ -1,7 +1,7 @@
import re import re
import time import time
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import List, Type, Set from typing import List, Type, Set, Tuple
import requests import requests
from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtCore import QThread, pyqtSignal
@@ -28,11 +28,13 @@ class AsyncAction(QThread, ProcessWatcher):
signal_status = pyqtSignal(str) # changes the GUI status message signal_status = pyqtSignal(str) # changes the GUI status message
signal_substatus = pyqtSignal(str) # changes the GUI substatus message signal_substatus = pyqtSignal(str) # changes the GUI substatus message
signal_progress = pyqtSignal(int) signal_progress = pyqtSignal(int)
signal_root_password = pyqtSignal()
def __init__(self): def __init__(self):
super(AsyncAction, self).__init__() super(AsyncAction, self).__init__()
self.wait_confirmation = False self.wait_confirmation = False
self.confirmation_res = None self.confirmation_res = None
self.root_password = None
self.stop = False self.stop = False
def request_confirmation(self, title: str, body: str, components: List[InputViewComponent] = None, confirmation_label: str = None, deny_label: str = None) -> bool: def request_confirmation(self, title: str, body: str, components: List[InputViewComponent] = None, confirmation_label: str = None, deny_label: str = None) -> bool:
@@ -41,10 +43,22 @@ class AsyncAction(QThread, ProcessWatcher):
self.wait_user() self.wait_user()
return self.confirmation_res return self.confirmation_res
def request_root_password(self) -> Tuple[str, bool]:
self.wait_confirmation = True
self.signal_root_password.emit()
self.wait_user()
res = self.root_password
self.root_password = None
return res
def confirm(self, res: bool): def confirm(self, res: bool):
self.confirmation_res = res self.confirmation_res = res
self.wait_confirmation = False self.wait_confirmation = False
def set_root_password(self, password: str, valid: bool):
self.root_password = (password, valid)
self.wait_confirmation = False
def wait_user(self): def wait_user(self):
while self.wait_confirmation: while self.wait_confirmation:
time.sleep(0.01) time.sleep(0.01)

View File

@@ -1,7 +1,5 @@
import logging import logging
import operator
import time import time
from functools import reduce
from pathlib import Path from pathlib import Path
from typing import List, Type, Set from typing import List, Type, Set
@@ -17,9 +15,10 @@ from bauh.api.abstract.controller import SoftwareManager
from bauh.api.abstract.model import SoftwarePackage, PackageAction from bauh.api.abstract.model import SoftwarePackage, PackageAction
from bauh.api.abstract.view import MessageType from bauh.api.abstract.view import MessageType
from bauh.api.http import HttpClient from bauh.api.http import HttpClient
from bauh.commons import user
from bauh.commons.html import bold from bauh.commons.html import bold
from bauh.view.core.controller import GenericSoftwareManager from bauh.view.core.controller import GenericSoftwareManager
from bauh.view.qt import dialog, commons, qt_utils from bauh.view.qt import dialog, commons, qt_utils, root
from bauh.view.qt.about import AboutDialog from bauh.view.qt.about import AboutDialog
from bauh.view.qt.apps_table import AppsTable, UpdateToggleButton from bauh.view.qt.apps_table import AppsTable, UpdateToggleButton
from bauh.view.qt.components import new_spacer, InputFilter, IconButton from bauh.view.qt.components import new_spacer, InputFilter, IconButton
@@ -27,7 +26,7 @@ from bauh.view.qt.confirmation import ConfirmationDialog
from bauh.view.qt.gem_selector import GemSelectorPanel from bauh.view.qt.gem_selector import GemSelectorPanel
from bauh.view.qt.history import HistoryDialog from bauh.view.qt.history import HistoryDialog
from bauh.view.qt.info import InfoDialog from bauh.view.qt.info import InfoDialog
from bauh.view.qt.root import is_root, ask_root_password from bauh.view.qt.root import ask_root_password
from bauh.view.qt.screenshots import ScreenshotsDialog from bauh.view.qt.screenshots import ScreenshotsDialog
from bauh.view.qt.styles import StylesComboBox from bauh.view.qt.styles import StylesComboBox
from bauh.view.qt.thread import UpdateSelectedApps, RefreshApps, UninstallApp, DowngradeApp, GetAppInfo, \ from bauh.view.qt.thread import UpdateSelectedApps, RefreshApps, UninstallApp, DowngradeApp, GetAppInfo, \
@@ -49,6 +48,7 @@ class ManageWindow(QWidget):
__BASE_HEIGHT__ = 400 __BASE_HEIGHT__ = 400
signal_user_res = pyqtSignal(bool) signal_user_res = pyqtSignal(bool)
signal_root_password = pyqtSignal(str, bool)
signal_table_update = pyqtSignal() signal_table_update = pyqtSignal()
def __init__(self, i18n: I18n, icon_cache: MemoryCache, manager: SoftwareManager, screen_size, config: dict, def __init__(self, i18n: I18n, icon_cache: MemoryCache, manager: SoftwareManager, screen_size, config: dict,
@@ -396,8 +396,10 @@ class ManageWindow(QWidget):
action.signal_status.connect(self._change_label_status) action.signal_status.connect(self._change_label_status)
action.signal_substatus.connect(self._change_label_substatus) action.signal_substatus.connect(self._change_label_substatus)
action.signal_progress.connect(self._update_process_progress) action.signal_progress.connect(self._update_process_progress)
action.signal_root_password.connect(self._ask_root_password)
self.signal_user_res.connect(action.confirm) self.signal_user_res.connect(action.confirm)
self.signal_root_password.connect(action.set_root_password)
return action return action
@@ -414,6 +416,12 @@ class ManageWindow(QWidget):
self.thread_animate_progress.animate() self.thread_animate_progress.animate()
self.signal_user_res.emit(res) self.signal_user_res.emit(res)
def _ask_root_password(self):
self.thread_animate_progress.pause()
password, valid = root.ask_root_password(self.i18n)
self.thread_animate_progress.animate()
self.signal_root_password.emit(password, valid)
def _show_message(self, msg: dict): def _show_message(self, msg: dict):
self.thread_animate_progress.pause() self.thread_animate_progress.pause()
dialog.show_message(title=msg['title'], body=msg['body'], type_=msg['type']) dialog.show_message(title=msg['title'], body=msg['body'], type_=msg['type'])
@@ -549,7 +557,7 @@ class ManageWindow(QWidget):
pwd = None pwd = None
requires_root = self.manager.requires_root('uninstall', app.model) requires_root = self.manager.requires_root('uninstall', app.model)
if not is_root() and requires_root: if not user.is_root() and requires_root:
pwd, ok = ask_root_password(self.i18n) pwd, ok = ask_root_password(self.i18n)
if not ok: if not ok:
@@ -865,7 +873,7 @@ class ManageWindow(QWidget):
widgets=[UpdateToggleButton(None, self, self.i18n, clickable=False)]): widgets=[UpdateToggleButton(None, self, self.i18n, clickable=False)]):
pwd = None pwd = None
if not is_root() and requires_root: if not user.is_root() and requires_root:
pwd, ok = ask_root_password(self.i18n) pwd, ok = ask_root_password(self.i18n)
if not ok: if not ok:
@@ -983,7 +991,7 @@ class ManageWindow(QWidget):
pwd = None pwd = None
requires_root = self.manager.requires_root('downgrade', pkgv.model) requires_root = self.manager.requires_root('downgrade', pkgv.model)
if not is_root() and requires_root: if not user.is_root() and requires_root:
pwd, ok = ask_root_password(self.i18n) pwd, ok = ask_root_password(self.i18n)
if not ok: if not ok:
@@ -1076,7 +1084,7 @@ class ManageWindow(QWidget):
pwd = None pwd = None
requires_root = self.manager.requires_root('install', pkg.model) requires_root = self.manager.requires_root('install', pkg.model)
if not is_root() and requires_root: if not user.is_root() and requires_root:
pwd, ok = ask_root_password(self.i18n) pwd, ok = ask_root_password(self.i18n)
if not ok: if not ok:
@@ -1131,7 +1139,7 @@ class ManageWindow(QWidget):
def execute_custom_action(self, pkg: PackageView, action: PackageAction): def execute_custom_action(self, pkg: PackageView, action: PackageAction):
pwd = None pwd = None
if not is_root() and action.requires_root: if not user.is_root() and action.requires_root:
pwd, ok = ask_root_password(self.i18n) pwd, ok = ask_root_password(self.i18n)
if not ok: if not ok: