Skip to content

Commit

Permalink
Refactored the analysis function, moved graphs to own package, minor …
Browse files Browse the repository at this point in the history
…fixes, analysis performance optimization, node limiter, start/middle/end queries rather than the convoluted mess that was before
  • Loading branch information
lkarlslund committed Nov 24, 2023
1 parent 827571b commit 6d7b57d
Show file tree
Hide file tree
Showing 19 changed files with 1,226 additions and 1,293 deletions.
452 changes: 452 additions & 0 deletions modules/analyze/analyzeobjects.go

Large diffs are not rendered by default.

73 changes: 36 additions & 37 deletions modules/analyze/export-graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@ package analyze
import (
"fmt"
"os"
"sort"

"github.com/lkarlslund/adalanche/modules/engine"
"github.com/lkarlslund/adalanche/modules/graph"
"github.com/lkarlslund/adalanche/modules/integrations/activedirectory"
"github.com/lkarlslund/adalanche/modules/version"
)

func ExportGraphViz(pg engine.Graph, filename string) error {
func ExportGraphViz(pg graph.Graph[*engine.Object, engine.EdgeBitmap], filename string) error {
df, _ := os.Create(filename)
defer df.Close()

fmt.Fprintln(df, "digraph G {")
for _, node := range pg.Nodes {
object := node.Object
for object, _ := range pg.Nodes() {
var formatting = ""
switch object.Type() {
case engine.ObjectTypeComputer:
Expand All @@ -25,8 +24,8 @@ func ExportGraphViz(pg engine.Graph, filename string) error {
fmt.Fprintf(df, " \"%v\" [label=\"%v\";%v];\n", object.ID(), object.OneAttr(activedirectory.Name), formatting)
}
fmt.Fprintln(df, "")
for _, connection := range pg.Connections {
fmt.Fprintf(df, " \"%v\" -> \"%v\" [label=\"%v\"];\n", connection.Source.ID(), connection.Target.ID(), connection.JoinedString())
for connection, edge := range pg.Edges() {
fmt.Fprintf(df, " \"%v\" -> \"%v\" [label=\"%v\"];\n", connection.Source, connection.Target, edge.JoinedString())
}
fmt.Fprintln(df, "}")

Expand Down Expand Up @@ -54,11 +53,11 @@ type CytoGraphData struct {
type CytoElements []CytoFlatElement

type CytoFlatElement struct {
Group string `json:"group"` // nodes or edges
Data MapStringInterface `json:"data"`
Group string `json:"group"` // nodes or edges
}

func GenerateCytoscapeJS(pg engine.Graph, alldetails bool) (CytoGraph, error) {
func GenerateCytoscapeJS(pg graph.Graph[*engine.Object, engine.EdgeBitmap], alldetails bool) (CytoGraph, error) {
g := CytoGraph{
FormatVersion: "1.0",
GeneratedBy: version.ProgramVersionShort(),
Expand All @@ -69,23 +68,23 @@ func GenerateCytoscapeJS(pg engine.Graph, alldetails bool) (CytoGraph, error) {
},
}

// Sort the nodes to get consistency
sort.Slice(pg.Nodes, func(i, j int) bool {
return pg.Nodes[i].Object.ID() < pg.Nodes[j].Object.ID()
})

// Sort the connections to get consistency
sort.Slice(pg.Connections, func(i, j int) bool {
return pg.Connections[i].Source.ID() < pg.Connections[j].Source.ID() ||
(pg.Connections[i].Source.ID() == pg.Connections[j].Source.ID() &&
pg.Connections[i].Target.ID() < pg.Connections[j].Target.ID())
})

g.Elements = make(CytoElements, len(pg.Nodes)+len(pg.Connections))
/*
// Sort the nodes to get consistency
sort.Slice(pg.Nodes, func(i, j int) bool {
return pg.Nodes[i].Node.ID() < pg.Nodes[j].Node.ID()
})
// Sort the connections to get consistency
sort.Slice(pg.Connections, func(i, j int) bool {
return pg.Connections[i].Source.ID() < pg.Connections[j].Source.ID() ||
(pg.Connections[i].Source.ID() == pg.Connections[j].Source.ID() &&
pg.Connections[i].Target.ID() < pg.Connections[j].Target.ID())
})
*/

g.Elements = make(CytoElements, pg.Order()+pg.Size())
var i int
for _, node := range pg.Nodes {
object := node.Object

for object, df := range pg.Nodes() {
newnode := CytoFlatElement{
Group: "nodes",
Data: map[string]any{
Expand All @@ -95,7 +94,7 @@ func GenerateCytoscapeJS(pg engine.Graph, alldetails bool) (CytoGraph, error) {
},
}

for key, value := range node.DynamicFields {
for key, value := range df {
newnode.Data[key] = value
}

Expand All @@ -111,19 +110,19 @@ func GenerateCytoscapeJS(pg engine.Graph, alldetails bool) (CytoGraph, error) {
}
}

if node.Target {
if df["target"] == true {
newnode.Data["_querytarget"] = true
}
if node.CanExpand != 0 {
newnode.Data["_canexpand"] = node.CanExpand
if df["canexpand"] != 0 {
newnode.Data["_canexpand"] = df["canexpand"]
}

g.Elements[i] = newnode

i++
}

for _, connection := range pg.Connections {
for connection, edge := range pg.Edges() {
cytoedge := CytoFlatElement{
Group: "edges",
Data: MapStringInterface{
Expand All @@ -133,12 +132,12 @@ func GenerateCytoscapeJS(pg engine.Graph, alldetails bool) (CytoGraph, error) {
},
}

for key, value := range connection.DynamicFields {
cytoedge.Data[key] = value
}
// for key, value := range edge.DynamicFields {
// cytoedge.Data[key] = value
// }

cytoedge.Data["_maxprob"] = connection.MaxProbability(connection.Source, connection.Target)
cytoedge.Data["methods"] = connection.StringSlice()
cytoedge.Data["_maxprob"] = edge.MaxProbability(connection.Source, connection.Target)
cytoedge.Data["methods"] = edge.StringSlice()

g.Elements[i] = cytoedge

Expand All @@ -148,7 +147,7 @@ func GenerateCytoscapeJS(pg engine.Graph, alldetails bool) (CytoGraph, error) {
return g, nil
}

func ExportCytoscapeJS(pg engine.Graph, filename string) error {
func ExportCytoscapeJS(pg graph.Graph[*engine.Object, engine.EdgeBitmap], filename string) error {
g, err := GenerateCytoscapeJS(pg, false)
if err != nil {
return err
Expand All @@ -163,7 +162,7 @@ func ExportCytoscapeJS(pg engine.Graph, filename string) error {
return err
}
defer df.Close()
df.Write(data)
_, err = df.Write(data)

return nil
return err
}
42 changes: 23 additions & 19 deletions modules/analyze/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,18 @@
<div id="analysis" class="collapse-panel p-1">
<form id="analysisoptionsform">
<div class="row justify-content-between">
<label class="col" for="querymode_group">Mode</label>
<label class="col" for="querymode_group">Query direction</label>
<div class="col btn-group btn-group-sm checkbox-button" id="querymode_group" role="group"
aria-label="Mode">
<input type="radio" name="mode" id="querymode_normal" class="btn-check" value="normal" autocomplete="off" checked />
<label class="btn btn-outline-primary btn-sm" for="querymode_normal">Normal</label>
<label class="btn btn-outline-primary btn-sm" for="querymode_normal">Incoming</label>
<input type="radio" name="mode" id="querymode_reverse" class="btn-check" value="reverse" autocomplete="off" />
<label class="btn btn-outline-primary btn-sm" for="querymode_reverse">Reverse</label>
<input type="radio" name="mode" id="querymode_sourcetarget" class="btn-check" value="sourcetarget" autocomplete="off" />
<label class="btn btn-outline-primary btn-sm" for="querymode_sourcetarget">SrcTgt</label>
<label class="btn btn-outline-primary btn-sm" for="querymode_reverse">Outgoing</label>
<!-- <input type="radio" name="mode" id="querymode_sourcetarget" class="btn-check" value="sourcetarget" autocomplete="off" />
<label class="btn btn-outline-primary btn-sm" for="querymode_sourcetarget">SrcTgt</label> -->
</div>
</div>

<div class="form-check">
<input class="form-check-input" id="force" type="checkbox" name="force" autocomplete="off"
preference="analysis.too.much.data.force" defaultpref=false>
<label class="form-check-label" for="force">Force too much data</label>
</div>

<div class="form-check">
<input class="form-check-input" id="prune" type="checkbox" name="prune" autocomplete="off"
preference="analysis.prune.islands" defaultpref=false>
Expand All @@ -137,6 +131,16 @@
<label class="form-check-label" for="backlinks">Include backlinks</label>
</div>

<div class="row">
<div class="col">
<label for="nodelimit" class="col-form-label">Node limit</label>
</div>
<div class="col">
<input id="nodelimit" type="number" name="nodelimit" min="100" max="5000" value="2000"
preference="analysis.node.limit" class="form-control text-right">
</div>
</div>

<div class="row">
<div class="col">
<label for="maxdepth" class="col-form-label">Analysis depth</label>
Expand Down Expand Up @@ -285,24 +289,24 @@
<form id="queryform" class="m-0">
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<button id="querybutton" class="nav-link active" data-bs-toggle="tab" data-bs-target="#query-pane" type="button">Query</button>
<button id="querybutton" class="nav-link active" data-bs-toggle="tab" data-bs-target="#startquery-pane" type="button">Start Query</button>
</li>
<li class="nav-item" role="presentation">
<button id="queryexcludebutton" class="nav-link" data-bs-toggle="tab" data-bs-target="#queryexclude-pane" type="button">Exclude</button>
<button id="queryexcludebutton" class="nav-link" data-bs-toggle="tab" data-bs-target="#middlequery-pane" type="button">Middle Query</button>
</li>
<li class="nav-item" role="presentation">
<button id="queryexcludelastbutton" class="nav-link" data-bs-toggle="tab" data-bs-target="#queryexcludelast-pane" type="button">Exclude Last</button>
<button id="queryexcludelastbutton" class="nav-link" data-bs-toggle="tab" data-bs-target="#endquery-pane" type="button">End Query</button>
</li>
</ul>
<div class="tab-content" id="query-tabs-content">
<div class="tab-pane active" id="query-pane">
<div class="tab-pane active" id="startquery-pane">
<textarea id="querytext" class="form-control mb-1" name="query" rows=4></textarea>
</div>
<div class="tab-pane" id="queryexclude-pane">
<textarea id="queryexclude" class="form-control mb-1" name="queryexclude" rows=4></textarea>
<div class="tab-pane" id="middlequery-pane">
<textarea id="queryexclude" class="form-control mb-1" name="middlequery" rows=4></textarea>
</div>
<div class="tab-pane" id="queryexcludelast-pane">
<textarea id="queryexcludelast" class="form-control mb-1" name="queryexcludelast" rows=4></textarea>
<div class="tab-pane" id="endquery-pane">
<textarea id="queryexcludelast" class="form-control mb-1" name="endquery" rows=4></textarea>
</div>
</div>
<div id="queryerror"></div>
Expand Down
5 changes: 2 additions & 3 deletions modules/analyze/preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package analyze
import (
"encoding/json"
"errors"
"io/ioutil"
"os"
"sync"
)
Expand All @@ -19,7 +18,7 @@ func (p *Prefs) Load() error {
defer prefmutex.Unlock()
p.data = make(map[string]any)

rawprefs, err := ioutil.ReadFile("preferences.json")
rawprefs, err := os.ReadFile("preferences.json")
if errors.Is(err, os.ErrNotExist) {
return nil
}
Expand All @@ -37,7 +36,7 @@ func (p *Prefs) Save() error {
if err != nil {
return err
}
err = ioutil.WriteFile("preferences.json", rawprefs, 0600)
err = os.WriteFile("preferences.json", rawprefs, 0600)
return err
}

Expand Down
13 changes: 8 additions & 5 deletions modules/analyze/webservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package analyze

import (
"embed"
"io"
"io/fs"
"io/ioutil"
"net/http"
"os"
"text/template"
Expand Down Expand Up @@ -97,16 +97,19 @@ func (w *webservice) Start(bind string, objs *engine.Objects, localhtml []string
w.Router.Path("/").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
indexfile, err := w.UnionFS.Open("index.html")
if err != nil {
ui.Fatal().Msgf("Could not open index.html: %v", err)
ui.Error().Msgf("Could not open index.html: %v", err)
}
rawindex, _ := ioutil.ReadAll(indexfile)
rawindex, _ := io.ReadAll(indexfile)
indextemplate := template.Must(template.New("index").Parse(string(rawindex)))

indextemplate.Execute(rw, struct {
err = indextemplate.Execute(rw, struct {
AdditionalHeaders []string
}{
AdditionalHeaders: w.AdditionalHeaders,
})
if err != nil {
ui.Error().Msgf("Could not render template index.html: %v", err)
}
})
w.Router.PathPrefix("/").Handler(http.FileServer(http.FS(w.UnionFS)))

Expand All @@ -126,7 +129,7 @@ func (w *webservice) ServeTemplate(rw http.ResponseWriter, req *http.Request, pa
if err != nil {
ui.Fatal().Msgf("Could not open template %v: %v", path, err)
}
rawtemplate, _ := ioutil.ReadAll(templatefile)
rawtemplate, _ := io.ReadAll(templatefile)
template, err := template.New(path).Parse(string(rawtemplate))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
Expand Down
Loading

0 comments on commit 6d7b57d

Please sign in to comment.