diff --git a/setoolsgui/apol.py b/setoolsgui/apol.py index 7827c2d0..6d2b8676 100644 --- a/setoolsgui/apol.py +++ b/setoolsgui/apol.py @@ -20,6 +20,7 @@ # will init the tab registry in widgets.tab for apol's analyses. # pylint: disable=unused-import from .widgets import (boolquery, + commonquery, constraintquery, fsusequery, genfsconquery, diff --git a/setoolsgui/widgets/commonquery.py b/setoolsgui/widgets/commonquery.py new file mode 100644 index 00000000..ea80de9d --- /dev/null +++ b/setoolsgui/widgets/commonquery.py @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: LGPL-2.1-only + +from PyQt6 import QtWidgets +import setools + +from . import criteria, models, tab + +__all__ = ("CommonQueryTab",) + + +class CommonQueryTab(tab.TableResultTabWidget): + + """A common permission set query.""" + + section = tab.AnalysisSection.Components + tab_title = "Common Permision Sets" + mlsonly = False + + def __init__(self, policy: setools.SELinuxPolicy, _, /, *, + parent: QtWidgets.QWidget | None = None) -> None: + + super().__init__(setools.CommonQuery(policy), None, enable_criteria=True, + enable_browser=True, parent=parent) + + self.setWhatsThis("Search common permission sets in an SELinux policy.") + + # + # Set up criteria widgets + # + name = criteria.CommonName("Name", self.query, "name", enable_regex=True, + parent=self.criteria_frame) + name.setToolTip("Search for common permission sets by name.") + name.setWhatsThis("
Search for common permission set by name.
") + + perms = criteria.PermissionCriteriaWidget("Permissions", self.query, "perms", + enable_equal=True) + perms.setToolTip("Search for common permission sets by permissions.") + perms.setWhatsThis("Search for common permission set by permissions.
") + + # Add widgets to layout + self.criteria_frame_layout.addWidget(name, 0, 0, 1, 1) + self.criteria_frame_layout.addWidget(perms, 0, 1, 1, 1) + self.criteria_frame_layout.addWidget(self.buttonBox, 1, 0, 1, 2) + + # Save widget references + self.criteria = (name, perms) + + # Set result table's model + self.table_results_model = models.CommonTable(self.table_results) + + # + # Set up browser + # + self.browser.setModel(models.CommonTable(self.browser, + data=sorted(self.query.policy.commons()))) + + +if __name__ == '__main__': + import sys + import warnings + import pprint + import logging + + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s|%(levelname)s|%(name)s|%(message)s') + warnings.simplefilter("default") + + app = QtWidgets.QApplication(sys.argv) + mw = QtWidgets.QMainWindow() + widget = CommonQueryTab(setools.SELinuxPolicy(), mw) + mw.setCentralWidget(widget) + mw.resize(1280, 1024) + whatsthis = QtWidgets.QWhatsThis.createAction(mw) + mw.menuBar().addAction(whatsthis) # type: ignore[union-attr] + mw.setStatusBar(QtWidgets.QStatusBar(mw)) + mw.show() + rc = app.exec() + pprint.pprint(widget.save()) + sys.exit(rc) diff --git a/setoolsgui/widgets/criteria/__init__.py b/setoolsgui/widgets/criteria/__init__.py index f3dad5f9..17da499c 100644 --- a/setoolsgui/widgets/criteria/__init__.py +++ b/setoolsgui/widgets/criteria/__init__.py @@ -4,6 +4,7 @@ from .boolean import * from .comboenum import * +from .common import * from .constraintype import * from .context import * from .fsuseruletype import * diff --git a/setoolsgui/widgets/criteria/common.py b/setoolsgui/widgets/criteria/common.py new file mode 100644 index 00000000..7e9a2f1e --- /dev/null +++ b/setoolsgui/widgets/criteria/common.py @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: LGPL-2.1-only + +from PyQt6 import QtCore, QtWidgets +import setools + +from .criteria import OptionsPlacement +from .name import NameCriteriaWidget + +# Regex for exact matches to roles +VALIDATE_EXACT = r"[A-Za-z0-9._-]*" + +__all__ = ("CommonName",) + + +class CommonName(NameCriteriaWidget): + + """ + Widget providing a QLineEdit that saves the input to the attributes + of the specified query. This supports inputs of common names. + """ + + indirect_toggled = QtCore.pyqtSignal(bool) + + def __init__(self, title: str, query: setools.PolicyQuery, attrname: str, /, *, + parent: QtWidgets.QWidget | None = None, + options_placement: OptionsPlacement = OptionsPlacement.RIGHT, + required: bool = False, enable_regex: bool = True): + + # Create completion list + completion = list[str](r.name for r in query.policy.commons()) + + super().__init__(title, query, attrname, completion, VALIDATE_EXACT, + enable_regex=enable_regex, required=required, parent=parent, + options_placement=options_placement) + + +if __name__ == '__main__': + import sys + import logging + import warnings + + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s|%(levelname)s|%(name)s|%(message)s') + warnings.simplefilter("default") + + q = setools.CommonQuery(setools.SELinuxPolicy()) + + app = QtWidgets.QApplication(sys.argv) + mw = QtWidgets.QMainWindow() + widget = CommonName("Test Common", q, "name", parent=mw) + widget.setToolTip("test tooltip") + widget.setWhatsThis("test whats this") + mw.setCentralWidget(widget) + mw.resize(widget.size()) + whatsthis = QtWidgets.QWhatsThis.createAction(mw) + mw.menuBar().addAction(whatsthis) # type: ignore[union-attr] + mw.setStatusBar(QtWidgets.QStatusBar(mw)) + mw.show() + sys.exit(app.exec()) diff --git a/setoolsgui/widgets/details/__init__.py b/setoolsgui/widgets/details/__init__.py index 0ed9be27..454ffab6 100644 --- a/setoolsgui/widgets/details/__init__.py +++ b/setoolsgui/widgets/details/__init__.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: LGPL-2.1-only from .boolean import * +from .common import * from .context import * from .objclass import * from .role import * diff --git a/setoolsgui/widgets/details/common.py b/setoolsgui/widgets/details/common.py new file mode 100644 index 00000000..9afab36c --- /dev/null +++ b/setoolsgui/widgets/details/common.py @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: LGPL-2.1-only +from PyQt6 import QtGui, QtWidgets +import setools + +from . import util + +__all__ = ('common_detail', 'common_detail_action', 'common_tooltip') + + +def common_detail(common: setools.Common, parent: QtWidgets.QWidget | None = None) -> None: + """Display a dialog with common details.""" + + util.display_object_details( + f"{common} Details", + f""" +{common}
+ +