-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from JacquesBeets/feature/adding-front-end
UI creation for service management
- Loading branch information
Showing
35 changed files
with
11,690 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
name: Build and Release | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
|
||
jobs: | ||
build: | ||
runs-on: windows-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set version | ||
run: echo "VERSION=0.0.${{ github.run_number }}" >> $env:GITHUB_ENV | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: 1.21 | ||
|
||
- name: Build Go binary | ||
run: | | ||
cd backend | ||
go build -o ../WinSenseConnect.exe | ||
- name: Set up Node.js | ||
uses: actions/setup-node@v2 | ||
with: | ||
node-version: '18' | ||
|
||
- name: Build Nuxt3 frontend | ||
run: | | ||
cd frontend | ||
npm ci | ||
npm run generate | ||
- name: Package release | ||
run: | | ||
mkdir release | ||
copy WinSenseConnect.exe release\ | ||
copy config.template.json release\config.json | ||
xcopy /E /I frontend\.output\public release\frontend | ||
- name: Create Release | ||
id: create_release | ||
uses: actions/create-release@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
tag_name: v${{ env.VERSION }} | ||
release_name: Release v${{ env.VERSION }} | ||
draft: false | ||
prerelease: false | ||
|
||
- name: Upload Release Asset | ||
uses: actions/upload-release-asset@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
upload_url: ${{ steps.create_release.outputs.upload_url }} | ||
asset_path: ./release | ||
asset_name: WinSenseConnect-v${{ env.VERSION }}.zip | ||
asset_content_type: application/zip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# /frontend | ||
/scripts/*.ps1 | ||
*.exe | ||
*.log | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"files.associations": { | ||
"*.css": "tailwindcss" | ||
}, | ||
"editor.quickSuggestions": { | ||
"strings": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/rs/cors" | ||
) | ||
|
||
func (p *program) startHTTPServer() { | ||
p.logger.Debug("Starting HTTP server") | ||
r := p.router | ||
|
||
exePath, err := os.Executable() | ||
if err != nil { | ||
p.logger.Error(fmt.Sprintf("Failed to get executable path: %v", err)) | ||
} | ||
staticPath := filepath.Join(filepath.Dir(exePath), "frontend/.output/public") | ||
|
||
// API endpoints | ||
r.HandleFunc("/api/config", p.handleGetConfig).Methods("GET") | ||
r.HandleFunc("/api/config", p.handleUpdateConfig).Methods("POST") | ||
r.HandleFunc("/api/scripts", p.handleListScripts).Methods("GET") | ||
r.HandleFunc("/api/scripts", p.handleAddScript).Methods("POST") | ||
// Serve static files (our UI) - this will be added at build time from our Nuxt frontend | ||
r.PathPrefix("/").Handler(http.FileServer(http.Dir(staticPath))) | ||
|
||
// CORS Middleware | ||
corsHandler := cors.New(cors.Options{ | ||
AllowedOrigins: []string{"*"}, | ||
AllowedMethods: []string{"GET", "POST", "OPTIONS"}, | ||
AllowedHeaders: []string{"Content-Type", "Authorization"}, | ||
ExposedHeaders: []string{"Link"}, | ||
AllowCredentials: true, | ||
MaxAge: 300, // Maximum value not ignored by any of major browsers | ||
}).Handler(r) | ||
|
||
p.logger.Debug("Listening on port 8077") | ||
http.ListenAndServe("0.0.0.0:8077", corsHandler) | ||
} | ||
|
||
func (p *program) handleGetConfig(w http.ResponseWriter, r *http.Request) { | ||
p.logger.Debug("Handling /api/config GET request") | ||
err := json.NewEncoder(w).Encode(p.config) | ||
if err != nil { | ||
p.logger.Error(fmt.Sprintf("Failed to encode config: %v", err)) | ||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
return | ||
} | ||
} | ||
|
||
func (p *program) handleUpdateConfig(w http.ResponseWriter, r *http.Request) { | ||
p.logger.Debug("Handling /api/config POST request") | ||
var newConfig Config | ||
json.NewDecoder(r.Body).Decode(&newConfig) | ||
// Write new config to file | ||
// This will later be saved in a db | ||
} | ||
|
||
func (p *program) handleListScripts(w http.ResponseWriter, r *http.Request) { | ||
p.logger.Debug("Handling /api/scripts GET request") | ||
files, _ := filepath.Glob(filepath.Join(p.scriptDir, "*.ps1")) | ||
json.NewEncoder(w).Encode(files) | ||
} | ||
|
||
func (p *program) handleAddScript(w http.ResponseWriter, r *http.Request) { | ||
p.logger.Debug("Handling /api/scripts POST request") | ||
// Logic to add new powershell scripts | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"os/exec" | ||
"time" | ||
|
||
"github.com/shirou/gopsutil/v4/cpu" | ||
"github.com/shirou/gopsutil/v4/disk" | ||
"github.com/shirou/gopsutil/v4/host" | ||
"github.com/shirou/gopsutil/v4/mem" | ||
"github.com/shirou/gopsutil/v4/net" | ||
"github.com/shirou/gopsutil/v4/sensors" | ||
) | ||
|
||
type SensorData struct { | ||
Timestamp time.Time `json:"timestamp"` | ||
CPUUsage float64 `json:"cpu_usage"` | ||
CPUInfo cpu.InfoStat `json:"cpu_info"` | ||
MemoryUsage float64 `json:"memory_usage"` | ||
DiskUsage float64 `json:"disk_usage"` | ||
Uptime uint64 `json:"uptime"` | ||
DiskPartitions []disk.PartitionStat `json:"disk_partitions"` | ||
NetConnections []net.ConnectionStat `json:"net_connections"` | ||
Users []host.UserStat `json:"users"` | ||
Sensors []sensors.TemperatureStat `json:"sensors"` | ||
CPUTemperature float64 `json:"cpu_temperature"` | ||
} | ||
|
||
type TemperatureData struct { | ||
Temperature float64 `json:"Temperature"` | ||
} | ||
|
||
func collectSensorData() (SensorData, error) { | ||
data := SensorData{ | ||
Timestamp: time.Now(), | ||
} | ||
|
||
// CPU Usage | ||
cpuPercent, err := cpu.Percent(time.Second, false) | ||
if err == nil && len(cpuPercent) > 0 { | ||
data.CPUUsage = cpuPercent[0] | ||
} | ||
|
||
// CPU Info | ||
cpuInfo, err := cpu.Info() | ||
if err == nil && len(cpuInfo) > 0 { | ||
data.CPUInfo = cpuInfo[0] | ||
} | ||
|
||
// Memory Usage | ||
memInfo, err := mem.VirtualMemory() | ||
if err == nil { | ||
data.MemoryUsage = memInfo.UsedPercent | ||
} | ||
|
||
// Disk Usage | ||
diskInfo, err := disk.Usage("C:") | ||
if err == nil { | ||
data.DiskUsage = diskInfo.UsedPercent | ||
} | ||
|
||
// Disk Partitions | ||
partitions, err := disk.Partitions(false) | ||
if err == nil { | ||
data.DiskPartitions = partitions | ||
} | ||
|
||
// Net | ||
netConnections, err := net.Connections("all") | ||
if err == nil { | ||
data.NetConnections = netConnections | ||
} | ||
|
||
// Uptime | ||
hostInfo, err := host.Info() | ||
if err == nil { | ||
data.Uptime = hostInfo.Uptime | ||
} | ||
|
||
// Users | ||
users, err := host.Users() | ||
if err == nil { | ||
data.Users = users | ||
} | ||
|
||
// Sensors | ||
sensors, err := sensors.TemperaturesWithContext(context.Background()) | ||
if err == nil { | ||
data.Sensors = sensors | ||
} | ||
|
||
// CPU Temperature | ||
temp, err := getCPUTemperature() | ||
if err == nil { | ||
data.CPUTemperature = temp | ||
} else { | ||
fmt.Printf("Failed to get CPU temperature: %v\n", err) | ||
} | ||
|
||
return data, nil | ||
} | ||
|
||
func getCPUTemperature() (float64, error) { | ||
cmd := exec.Command("powershell", "-Command", ` | ||
$temp = Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace "root/wmi" | Select-Object -First 1 | ||
if ($temp) { | ||
$celsius = ($temp.CurrentTemperature / 10) - 273.15 | ||
ConvertTo-Json @{ Temperature = [math]::Round($celsius, 2) } | ||
} else { | ||
ConvertTo-Json @{ Temperature = $null } | ||
} | ||
`) | ||
|
||
output, err := cmd.Output() | ||
if err != nil { | ||
return 0, fmt.Errorf("failed to execute PowerShell command: %v", err) | ||
} | ||
|
||
var tempData TemperatureData | ||
err = json.Unmarshal(output, &tempData) | ||
if err != nil { | ||
return 0, fmt.Errorf("failed to parse temperature data: %v", err) | ||
} | ||
|
||
if tempData.Temperature == 0 { | ||
return 0, fmt.Errorf("temperature data not available") | ||
} | ||
|
||
return tempData.Temperature, nil | ||
} |
Oops, something went wrong.