From 90cb4603fbb4645c672697e2df589113f07a717f Mon Sep 17 00:00:00 2001 From: martiivGylden <martin.iversen@gyldendal.no> Date: Tue, 7 May 2024 13:55:10 +0200 Subject: [PATCH] Front end partially done, working on lists now --- components.py | 3 +- dashBoard.py | 155 ++++++++++++++++++++++++++-------------------- dashboardUtils.py | 6 +- diagramParser.py | 1 + main.py | 11 ++-- 5 files changed, 100 insertions(+), 76 deletions(-) diff --git a/components.py b/components.py index c79011f..c0bdb82 100644 --- a/components.py +++ b/components.py @@ -244,4 +244,5 @@ class Diagram(): self.consequences = {} self.attacks = {} self.dynamics = {} - self.indicators = {} \ No newline at end of file + self.indicators = {} + self.erComponents = {} \ No newline at end of file diff --git a/dashBoard.py b/dashBoard.py index 41e3dab..866792e 100644 --- a/dashBoard.py +++ b/dashBoard.py @@ -10,80 +10,101 @@ from components import Diagram import diagramParser as parse import dashboardUtils as utils + def openFile(): - fileName = filedialog.askopenfilename(initialdir= "/", - title= "Select lucidchart diagram file", - filetypes=(("CSV Diagram file", "*.csv"),) - ) - diagram = parse.parseDiagramFile(fileName) + """ + Function allows the user to select a diagram, and opens the scorecard resulting window + From here, the user can see the threats in the diagram and the associated indicators and architecture components + The user can also choose to sort by indicators + """ + #fileName = filedialog.askopenfilename(initialdir= "/",title= "Select lucidchart diagram file",filetypes=(("CSV Diagram file", "*.csv"),)) + #diagram = parse.parseDiagramFile(fileName) # Parse the diagram + s = ttk.Style() + s.theme_use('classic') + s.configure('Green.TFrame', background='Green',foreground="#1A323B", relief='raised') + s.configure('Red.TFrame', background='Red',foreground="#1A323B", relief='raised') + + + diagram = parse.parseDiagramFile("diagrams/TestIter2.csv") - top = Toplevel(guiRoot) - top.title("Result Window") - top.geometry("1600x900") - topFrame = Frame(top) - topFrame.grid() + # Defines the window for the scorecard + scorecardWindow = Toplevel(guiRoot) + scorecardWindow.title("Scorecard") + scorecardWindow.attributes("-fullscreen", True) - canvas = Canvas(topFrame, width=1450, height= 900) # Create Canvas to be able to scroll - canvas.grid() + windowHeigh = scorecardWindow.winfo_height() + windowWidth = scorecardWindow.winfo_width() - # Define scrollbar - scrollbar = Scrollbar(topFrame, orient="vertical", command=canvas.yview) - scrollbar.grid(row=0, column=1, sticky="ns") + mainFrame = ttk.Frame(scorecardWindow, height=windowHeigh, width=windowWidth) # * Defines the main frame of the window, should contain a socrecard in the top and a list of threats in the bottom + mainFrame.grid(row=0, column=0, sticky='nsew') # * Grid should sort the scorecard and the list of threats - canvas.configure(yscrollcommand=scrollbar.set) - canvas.bind( - '<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")) - ) + # Inside the scorecardFrame there should be text labels with header, and three different labels with values with information + # Additionally there should be two buttons, one for threat sorting and one for indicator sorting + headerLabel = Label(mainFrame, text="Scorecard", font=("Arial", 20)) - canvasFrame = createMetrics(diagram, canvas) - canvasFrame.grid_columnconfigure(0, weight=1) + relationshipNumber = len(diagram.threats)+len(diagram.consequences)+len(diagram.erComponents) + threatNumber = len(diagram.threats) + consequenceNumber = len(diagram.consequences) + architectureNumber = len(diagram.erComponents) - canvas.create_window((0,0), window=canvasFrame, anchor="nw") + descriptionString = "The diagrams have been successfully parsed! Below is the list of found threats, and their associated architecture components. These components are linked through the security indicators found between the threats and architecture components" + descriptionString2 = "Press the sort by indicators to swap to the indicator sorted veiw. This helps identify which metrics are important and which components they relate to." + descriptionLabel = ttk.Label(mainFrame, text=descriptionString, wraplength=0.4*windowWidth, font=("Arial", 15)) + description2Label = ttk.Label(mainFrame, text=descriptionString2, wraplength=0.4*windowWidth, font=("Arial", 15)) - rowIndex = 0 + sortThreatButton = Button(mainFrame, text="Sort by threats", command=lambda: createThreatView(diagram, mainFrame), width=2, height=3) + sortIndicatorButton = Button(mainFrame, text="Sort by indicators", command=lambda: createIndicatorView(diagram, mainFrame), width=2, height=3) - for threat in diagram.threats.values(): - - metrics, components = findMetrics(diagram, threat.componentID, "bowtie") - - threatFrame = Frame(top) - threatFrame.grid(row=rowIndex) - rowIndex +=1 - - l1 = Label(threatFrame, text= f"Threat ID: {threat.id} \n Threat description: {threat.threatSource}") - l2 = Label(threatFrame, text= f"Associated vulnerability: {threat.vulnerability}") - - listofIndicators = Listbox(threatFrame, font="Helvetica") - index = 1 - for metric in metrics: - listofIndicators.insert(index,metric) - index +=1 - - linkedComponents = Listbox(threatFrame, font="Helvetica") - index = 1 - for component in components: - linkedComponents.insert(index, component) - index +=1 - - l3 = Label(threatFrame, text= f"Observable indicators: {metrics}") + analyticsLabel = Label(mainFrame, text="Features", font=("Arial", 20, "bold")) + analyticsRow3 = Label(mainFrame, text=f"Number of indicators: {len(diagram.indicators)}", font=("Arial", 15)) + analyticsrow4 = Label(mainFrame, text=f"Number of relationships: {relationshipNumber}", font=("Arial", 15)) + analyticsRow5 = Label(mainFrame, text=f"Number of threats: {threatNumber}", font=("Arial", 15)) + analyticsRow6 = Label(mainFrame, text=f"Number of consequences: {consequenceNumber}", font=("Arial", 15)) + analyticsRow7 = Label(mainFrame, text=f"Number of architecture components: {architectureNumber}", font=("Arial", 15)) + + # Create the reult text + + paddingScorecardInfo = 18 + headerLabel.grid(row=0, column=0, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + descriptionLabel.grid(row=1, column=0, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo, rowspan=4, columnspan=2) + description2Label.grid(row=2, column=0, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo, rowspan=4, columnspan=2) + + #* Buttons + sortIndicatorButton.grid(row=7, column=0, sticky="nsew") + sortThreatButton.grid(row=7, column=1, sticky="nsew") + - l4 = Label(threatFrame, text = f"Linked Components: {components}") - - l1.config(font=("Helvetica", 20, "bold")) - l2.config(font=("Helvetica", 15)) - l3.config(font=("Helvetica", 15)) - l4.config(font=("Helvetica", 15)) - - l1.grid(row = 4, column = 0) - l2.grid(row=6, column = 0) - listofIndicators.grid(row=4, column=10) - linkedComponents.grid(row = 4, column = 15) - -def tempTestFunction(): + # * From this point to row 6 is the analytics matrix, padding is reduced to 10 + analyticsLabel.grid(row=0, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + + paddingScorecardInfo= 5 + + analyticsRow3.grid(row=2, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsrow4.grid(row=3, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsRow5.grid(row=4, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsRow6.grid(row=5, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + analyticsRow7.grid(row=6, column=1, sticky="nw", pady=paddingScorecardInfo, padx=paddingScorecardInfo) + + # Create frame for the list of either threat or indicator, Framelocation mainFrame row 2 + listFrame = customtkinter.CTkScrollableFrame(mainFrame, width= 0.9*windowWidth, height=0.5*windowHeigh, bg_color="#155E53") + listFrame.grid(row=8, column=0, columnspan=2 ,sticky="nsew") + + # Create the list of threats + createThreatView(diagram, mainFrame, 0.9*windowWidth) + + + +def createThreatView(diagram: Diagram, frame, canvasWidth): + pass + + + + +def createIndicatorView(): windowWidth = 1250 windowHeight = 1200 @@ -99,7 +120,7 @@ def tempTestFunction(): mainFrame.grid_rowconfigure(0, weight=1) canvasFrame = createMetrics(diagram, mainFrame, 1550) - + def createMetrics(diagram: Diagram, frame, canvasWidth): s = ttk.Style() @@ -115,7 +136,6 @@ def createMetrics(diagram: Diagram, frame, canvasWidth): scoreFrame = ttk.Frame(frame, height=100, width=canvasWidth, padding=10, style='Test.TFrame') scoreFrame.grid(padx=10, pady=25, sticky="nsew") - scoreFrame.grid_columnconfigure(0, weight=1) headerLabel = ttk.Label(scoreFrame, text="Diagram scorecard", font=("Helvetica", 25, "bold"), style="Head.TLabel") label1 = ttk.Label(scoreFrame, text=f"Diagrams parsed! Below is the list of found metrics along with the amount of relationships. Further down you will find the list of metrics with usage and associated components", wraplength=0.5*canvasWidth ,font=("Helvetica", 20), style="Test.TLabel") @@ -194,11 +214,12 @@ label3 = ttk.Label(guiRoot, text="BowTie risk diagram, Software supply chain arc label2.grid(column=1, row=4) label3.grid(column=1, row=5) -#labelWindow = Label(guiRoot, text="Please select CSV export file containing ER diagram, BowTie diagram and dynamics matrix", font=("Arial", 20)) -#buttonGetFile = Button(guiRoot, text="Select file", command=openFile, width=20, height=2) -#labelWindow.grid(column = 1, row = 1) -#buttonGetFile.grid(column = 1, row = 1) +labelWindow = Label(guiRoot, text="Please select CSV export file containing ER diagram, BowTie diagram and dynamics matrix", font=("Arial", 20)) +buttonGetFile = Button(guiRoot, text="Select file", command=openFile, width=20, height=2) +labelWindow.grid(column = 1, row = 1) +buttonGetFile.grid(column = 1, row = 1) + +openFile() -tempTestFunction() guiRoot.mainloop() diff --git a/dashboardUtils.py b/dashboardUtils.py index 8ade295..9288102 100644 --- a/dashboardUtils.py +++ b/dashboardUtils.py @@ -8,13 +8,13 @@ from components import * import diagramParser as parse -def createERLabel(top, metric: Metric, diagram: Diagram): +def createERLabel(top, indicator : Indicator, diagram: Diagram): s = ttk.Style() s.configure('ListFrame.TLabel', background='white', foreground="#1A323B", font=('Helvetica', 15, 'bold')) nameList = [] labelList = [] - for i in metric.erID: + for i in indicator.erID: for j in diagram.dynamics.values(): if j.type == "ER": if i in j.associatedERComponents.keys(): @@ -29,7 +29,7 @@ def createERLabel(top, metric: Metric, diagram: Diagram): labelList.append(label) return labelList -def createBowtieLabel(top, metric: Metric, diagram: Diagram): +def createBowtieLabel(top, indicator: Indicator, diagram: Diagram): s = ttk.Style() s.configure('ListFrame.TLabel', background='white', foreground="#1A323B", font=('Helvetica', 15, 'bold')) diff --git a/diagramParser.py b/diagramParser.py index 6dc19bd..7b979c9 100644 --- a/diagramParser.py +++ b/diagramParser.py @@ -127,6 +127,7 @@ def parseRelationshipComponentER(df: pd.DataFrame, diagram: component.Diagram, r # Add indicators to the ER component erComponent.linkedIndicators.update(indicatorList) erComponents[erComponent.id]= erComponent + diagram.erComponents[erComponent.id] = erComponent for i in indicatorList.keys(): # We need to update the indicators with the ER components and the reasoning for the indicator annotation diff --git a/main.py b/main.py index bce6a62..3734986 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,12 @@ import diagramParser as parse +import components as component -def main(): +def main(): + diagram:component.Diagram = parse.parseDiagramFile('diagrams/TestIter2.csv') # Parse the diagram + + + - dynamicMetricsBowtie = [] # List of metrics for the bowtie model - dynamicMetricsArchitecture = [] # List of metrics for the architecture - #parse.parseDiagramFile('diagrams/Thesis Bow-Tie and architecture - Meta model-2.csv') # Parse the diagram - diagram = parse.parseDiagramFile('diagrams/TestIter2.csv') # Parse the diagram if __name__=="__main__": -- GitLab