summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPapoteur <papoteur@mageia.org>2023-10-27 19:39:17 +0200
committerPapoteur <papoteur@mageia.org>2023-10-27 19:39:17 +0200
commitff5c617a429bccf8fe7226e22d76794338ef0116 (patch)
tree4b9c7f66221ca0bc5a96fafc6e179d57ac59a9c0
downloadmga-advisor-ff5c617a429bccf8fe7226e22d76794338ef0116.tar
mga-advisor-ff5c617a429bccf8fe7226e22d76794338ef0116.tar.gz
mga-advisor-ff5c617a429bccf8fe7226e22d76794338ef0116.tar.bz2
mga-advisor-ff5c617a429bccf8fe7226e22d76794338ef0116.tar.xz
mga-advisor-ff5c617a429bccf8fe7226e22d76794338ef0116.zip
Initial commit
-rw-r--r--form.ui249
-rw-r--r--mga-advisor.py185
2 files changed, 434 insertions, 0 deletions
diff --git a/form.ui b/form.ui
new file mode 100644
index 0000000..2663c25
--- /dev/null
+++ b/form.ui
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Widget</class>
+ <widget class="QWidget" name="Widget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>814</width>
+ <height>622</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Widget</string>
+ </property>
+ <widget class="QWidget" name="verticalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>-1</x>
+ <y>-1</y>
+ <width>811</width>
+ <height>601</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Mageia Advisories Editor</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="group_type">
+ <property name="title">
+ <string>Type:</string>
+ </property>
+ <widget class="QRadioButton" name="bugfix_rb">
+ <property name="geometry">
+ <rect>
+ <x>50</x>
+ <y>0</y>
+ <width>99</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Bug fix</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="security_rb">
+ <property name="geometry">
+ <rect>
+ <x>230</x>
+ <y>0</y>
+ <width>99</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Security</string>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Bug report number</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="bug_le">
+ <property name="inputMask">
+ <string notr="true"/>
+ </property>
+ <property name="placeholderText">
+ <string>bug number</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="retrieve_pb">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Retrieve info</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Subject</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="subject_le">
+ <property name="placeholderText">
+ <string>subject</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="description_te">
+ <property name="documentTitle">
+ <string>Drescription</string>
+ </property>
+ <property name="lineWrapColumnOrWidth">
+ <number>72</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QListWidget" name="list_src"/>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QPushButton" name="add_src_pb">
+ <property name="text">
+ <string>Add source</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="remove_src_pb">
+ <property name="text">
+ <string>Remove source</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QListWidget" name="list_ref"/>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QPushButton" name="add_ref_pb">
+ <property name="text">
+ <string>Add reference</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="remove_ref_pb">
+ <property name="text">
+ <string>Remove reference</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QListWidget" name="list_cve"/>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QPushButton" name="add_cve_pb">
+ <property name="text">
+ <string>Add CVE</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="remove_cve_pb">
+ <property name="text">
+ <string>Remove CVE</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QPushButton" name="cancel_pb">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="preview_pb">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="export_pb">
+ <property name="text">
+ <string>Export</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mga-advisor.py b/mga-advisor.py
new file mode 100644
index 0000000..4869407
--- /dev/null
+++ b/mga-advisor.py
@@ -0,0 +1,185 @@
+# This Python file uses the following encoding: utf-8
+import os
+from pathlib import Path
+import sys
+import yaml
+import textwrap
+import re
+
+from PySide6.QtWidgets import QApplication, QWidget, QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QComboBox, QTextEdit
+from PySide6.QtCore import QFile, QDate, QDir
+from PySide6.QtUiTools import QUiLoader
+
+
+class LineDialog(QDialog):
+ def __init__(self, title, init="", parent=None):
+ super().__init__(parent)
+ self.setWindowTitle(title)
+ self.name_ql = QLineEdit()
+ self.name_ql.setText(init)
+ apply_bt = QPushButton("Apply")
+ layout = QHBoxLayout()
+ layout.addWidget(self.name_ql)
+ layout.addWidget(apply_bt)
+ self.setLayout(layout)
+ apply_bt.clicked.connect(self.apply)
+
+ def apply(self):
+ self.accept()
+
+class SrcDialog(QDialog):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setWindowTitle("Add source")
+ self.name_ql = QLineEdit()
+ self.release = QComboBox()
+ self.release.addItems(["9", "8"])
+ self.repo = QComboBox()
+ self.repo.addItems(["core", "nonfree", "tainted"])
+ apply_bt = QPushButton("Apply")
+ layout = QHBoxLayout()
+ layout.addWidget(self.release)
+ layout.addWidget(self.repo)
+ layout.addWidget(self.name_ql)
+ layout.addWidget(apply_bt)
+ self.setLayout(layout)
+ apply_bt.clicked.connect(self.apply)
+
+ def apply(self):
+ self.accept()
+
+class Widget(QWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.load_ui()
+ self.setWindowTitle("Mageia advisor")
+
+ def load_ui(self):
+ loader = QUiLoader()
+ path = Path(__file__).resolve().parent / "form.ui"
+ ui_file = QFile(path)
+ ui_file.open(QFile.ReadOnly)
+ self.ui = loader.load(ui_file, self)
+ ui_file.close()
+ self.ui.retrieve_pb.clicked.connect(self.retrieve)
+ self.ui.add_cve_pb.clicked.connect(self.add_cve)
+ self.ui.remove_cve_pb.clicked.connect(self.remove_cve)
+ self.ui.add_src_pb.clicked.connect(self.add_src)
+ self.ui.remove_src_pb.clicked.connect(self.remove_src)
+ self.ui.add_ref_pb.clicked.connect(self.add_reference)
+ self.ui.remove_ref_pb.clicked.connect(self.remove_reference)
+ self.ui.export_pb.clicked.connect(self.export)
+ self.ui.cancel_pb.clicked.connect(self.cancel)
+ self.ui.preview_pb.clicked.connect(self.preview)
+ self.ui.bug_le.editingFinished.connect(self.valid_number)
+
+ def retrieve(self):
+ print("Action retrieve")
+
+ def add_src(self):
+ dl = SrcDialog()
+ name = dl.exec()
+ self.ui.list_src.addItem(
+ " ".join((dl.release.currentText(),
+ dl.repo.currentText(),
+ self.sanitize_line(dl.name_ql.text())
+ ))
+ )
+
+ def remove_src(self):
+ self.ui.list_src.takeItem(self.ui.list_src.currentRow())
+
+ def add_reference(self):
+ dl = LineDialog("Add reference")
+ dl.exec()
+ self.ui.list_ref.addItem(self.sanitize_line(dl.name_ql.text()))
+
+
+ def remove_reference(self):
+ self.ui.list_ref.takeItem(self.ui.list_ref.currentRow())
+
+ def add_cve(self):
+ init_value = f"CVE-{QDate.currentDate().year()}-"
+ dl = LineDialog("Add CVE", init=init_value)
+ dl.exec()
+ self.ui.list_cve.addItem(self.sanitize_line(dl.name_ql.text()))
+
+ def remove_cve(self):
+ self.ui.list_cve.takeItem(self.ui.list_cve.currentRow())
+
+ def adv_text(self):
+ data = {}
+ if self.ui.bugfix_rb.isEnabled():
+ data['type'] = 'bugfix'
+ if self.ui.security_rb.isEnabled():
+ data['type'] = 'security'
+ if len(self.ui.description_te.toPlainText()) != 0:
+ data['description'] = self.ui.description_te.toPlainText()
+ if self.ui.subject_le.text() != "":
+ data['subject'] = self.sanitize_line(self.ui.subject_le.text())
+ cves = []
+ n = 0
+ for n in range(0, self.ui.list_cve.count()):
+ cves.append(self.ui.list_cve.item(n).text())
+ if n != 0:
+ data['CVE'] = cves
+ srcs = {}
+ n = 0
+ for n in range(0, self.ui.list_src.count()):
+ release, repo, name = self.ui.list_src.item(n).text().split(" ")
+ if not release in srcs.keys():
+ srcs[release] = {}
+ srcs[release][repo] = []
+ else:
+ if not repo in srcs[release].keys():
+ srcs[release][repo] = []
+ srcs[release][repo].append(name)
+ if n != 0:
+ data['src'] = srcs
+ refs = []
+ n = 0
+ for n in range(0, self.ui.list_ref.count()):
+ refs.append(self.ui.list_ref.item(n).text())
+ if n != 0:
+ data['references'] = refs
+ return yaml.dump(data, default_flow_style=False)
+
+ def export(self):
+ if QDir().mkpath(QDir().homePath() + "/mageia-advisories/advisories"):
+ if self.ui.bug_le.text() != "":
+ #TODO check that it exists
+ with open(f"{QDir().homePath()}/mageia-advisories/advisories/{self.ui.bug_le.text()}.adv", 'w') as f:
+ f.write(self.adv_text())
+
+ def cancel(self):
+ self.close()
+
+ def preview(self):
+ dl = QDialog()
+ dl.setWindowTitle("Advisory preview")
+ te = QTextEdit()
+ te.setPlainText(self.adv_text())
+ te.setReadOnly(True)
+ te.setMinimumSize(600, 0)
+ ok_bt = QPushButton("OK")
+ layout = QVBoxLayout()
+ layout.addWidget(te)
+ layout.addWidget(ok_bt)
+ dl.setLayout(layout)
+ ok_bt.clicked.connect(dl.close)
+ dl.exec()
+
+ def sanitize_line(self, line):
+ if len(line) != 0:
+ return line.splitlines()[0].strip()
+ else:
+ return ""
+
+ def valid_number(self):
+ self.ui.bug_le.setText(re.sub('\D', '', self.ui.bug_le.text()))
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ widget = Widget()
+ widget.show()
+ sys.exit(app.exec())