Skip to content

Commit

Permalink
mqtt config updated. toasts, restart after update, small bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
JacquesBeets committed Oct 6, 2024
1 parent 81073b1 commit 1719ea9
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 28 deletions.
85 changes: 71 additions & 14 deletions backend/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"time"

_ "github.com/mattn/go-sqlite3"
Expand Down Expand Up @@ -43,17 +44,17 @@ func NewDB() (*DB, error) {
func (db *DB) InitSchema(logger *Logger) error {
// Drop tables if they exist
// logger.Debug("Dropping tables if they exist...")
// _, err := db.Exec(`DROP TABLE IF EXISTS configs`)
// if err != nil {
// return err
// _, dropErr := db.Exec(`DROP TABLE IF EXISTS configs`)
// if dropErr != nil {
// return dropErr
// }
// _, err = db.Exec(`DROP TABLE IF EXISTS script_configs`)
// if err != nil {
// return err
// _, dropErr = db.Exec(`DROP TABLE IF EXISTS script_configs`)
// if dropErr != nil {
// return dropErr
// }
// _, err = db.Exec(`DROP TABLE IF EXISTS sensor_configs`)
// if err != nil {
// return err
// _, dropErr = db.Exec(`DROP TABLE IF EXISTS sensor_configs`)
// if dropErr != nil {
// return dropErr
// }

// Create tables
Expand Down Expand Up @@ -109,17 +110,57 @@ func (db *DB) InitSchema(logger *Logger) error {
INSERT INTO configs (id, broker_address, username, password, client_id, topic, log_level, script_timeout, created_at, updated_at)
VALUES (1, 'tcp://0.0.0.0:1883', 'your_username', 'your_password', 'my-windows-automation-service', 'windows/commands', 'debug', 300, '2023-07-01 12:00:00', '2023-07-01 12:00:00');
INSERT INTO script_configs (id, name, script_path, script_timeout, run_as_user, created_at, updated_at)
VALUES (1, 'test_notification', 'test_notification.ps1', 300, true, '2023-07-01 12:00:00', '2023-07-01 12:00:00');
INSERT INTO sensor_configs (id, name, enabled, interval, sensor_topic, created_at, updated_at)
VALUES (1, 'cpu_usage', false, 60, 'windows/sensors/cpu_usage', '2023-07-01 12:00:00', '2023-07-01 12:00:00');
`)
if err != nil {
return err
}
}

err = db.AddScriptsFromDir()
return err
}

func (db *DB) AddScriptsFromDir() error {
exePath, err := os.Executable()
if err != nil {
return fmt.Errorf("failed to get executable path: %v", err)
}
dir := filepath.Join(filepath.Dir(exePath), "scripts")

files, err := os.ReadDir(dir)
if err != nil {
return fmt.Errorf("failed to read directory: %v", err)
}

for _, file := range files {
if file.IsDir() {
continue
}

// Check if db has script with same script path
var script ScriptConfig
err := db.QueryRow("SELECT id, name, script_path, run_as_user, script_timeout, created_at, updated_at FROM script_configs WHERE script_path = ?", file.Name()).Scan(&script)
// split file name into name and extension
filename := strings.Split(file.Name(), ".")[0]

if err == sql.ErrNoRows {
// If not, add it
script := ScriptConfig{
Name: filename,
ScriptPath: file.Name(),
RunAsUser: true,
ScriptTimeout: 300,
}
err = db.CreateScriptConfig(&script)
if err != nil {
return fmt.Errorf("failed to create script config: %v", err)
}
}
}
return nil
}

func (db *DB) GetConfig() (*Config, error) {
var configModel ConfigModel

Expand All @@ -145,7 +186,7 @@ func (db *DB) GetConfig() (*Config, error) {
}
configsScriptArray := make(map[string]ScriptConfig)
for _, config := range *configsScript {
configsScriptArray[config.ScriptPath] = config
configsScriptArray[config.Name] = config
}

configsSensor, err := db.GetSensorConfigs()
Expand Down Expand Up @@ -288,3 +329,19 @@ func (db *DB) CreateSensorConfig(sensorConfig *SensorConfig) error {
)
return err
}

func (db *DB) CreateScriptConfig(scriptConf *ScriptConfig) error {
now := time.Now()
_, err := db.Exec(`
INSERT INTO script_configs (
name, script_path, run_as_user, script_timeout, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?)`,
scriptConf.Name,
scriptConf.ScriptPath,
scriptConf.RunAsUser,
scriptConf.ScriptTimeout,
now,
now,
)
return err
}
12 changes: 12 additions & 0 deletions backend/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func (p *program) startHTTPServer() {
r.HandleFunc("/api/config", p.handleUpdateConfig).Methods("POST")
r.HandleFunc("/api/scripts", p.handleListScripts).Methods("GET")
r.HandleFunc("/api/scripts", p.handleAddScript).Methods("POST")
r.HandleFunc("/api/restart", p.handleRestartService).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)))

Expand Down Expand Up @@ -81,3 +82,14 @@ func (p *program) handleAddScript(w http.ResponseWriter, r *http.Request) {
p.logger.Debug("Handling /api/scripts POST request")
// Logic to add new powershell scripts
}

func (p *program) handleRestartService(w http.ResponseWriter, r *http.Request) {
p.logger.Debug("Handling /api/restart POST request")
err := p.restartService()
if err != nil {
p.logger.Error(fmt.Sprintf("Failed to restart service: %v", err))
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
17 changes: 17 additions & 0 deletions backend/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,20 @@ func (p *program) executeScript(scriptPath string, runAsUser bool) (string, erro
return p.runAsLocalSystem(scriptPath)
}
}

func (p *program) restartService() error {
p.logger.Debug("Restarting service")
err := p.Stop(nil)
if err != nil {
return fmt.Errorf("failed to stop service: %v", err)
}
// clear mqtt client
p.mqttClient = nil
time.Sleep(time.Second * 5)
p.logger.Debug("Service stopped, restarting...")
err = p.Start(nil)
if err != nil {
return fmt.Errorf("failed to start service: %v", err)
}
return nil
}
29 changes: 26 additions & 3 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@nuxtjs/tailwindcss": "^6.12.1",
"nuxt": "^3.13.0",
"vue": "latest",
"vue-router": "latest"
"vue-router": "latest",
"vue3-toastify": "^0.2.2"
}
}
54 changes: 44 additions & 10 deletions frontend/pages/config/mqtt.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<form @submit.prevent="saveConfig" class="max-w-3xl mx-auto">
<form class="max-w-3xl mx-auto">
<h1 class="text-3xl font-bold mb-6">MQTT Configuration</h1>
<div class="form-control">
<label for="brokerAddress">Broker Address</label>
Expand Down Expand Up @@ -34,24 +34,58 @@
<input type="number" id="scriptTimeout" v-model="config.script_timeout" />
</div>
<div class="form-control">
<button class="btn-primary ml-auto" type="submit">Save</button>
<button @click.stop="saveConfig" class="btn-primary ml-auto" :disabled="isSaving">
{{ isSaving ? 'Saving...' : 'Save' }}
</button>
</div>
</form>
</template>

<script setup>
const config = ref({})
const { $toast } = useNuxtApp()
const config = ref({})
const isSaving = ref(false)
const {data: configData} = await useFetch('http://localhost:8077/api/config')
config.value = JSON.parse(configData.value)
const { data: configData } = await useFetch('http://localhost:8077/api/config')
if (configData.value) {
config.value = JSON.parse(configData.value)
console.log(config.value)
const saveConfig = () => {
const data = JSON.stringify(config.value)
useFetch('http://localhost:8077/api/config', {
} else {
console.error('Failed to fetch configuration')
$toast.error('Failed to load configuration')
}
const saveConfig = async () => {
isSaving.value = true
try {
const { error: saveError } = await useFetch('http://localhost:8077/api/config', {
method: 'POST',
body: data
body: config.value
})
if (saveError.value) {
throw new Error('Failed to save configuration')
}
$toast.success('Configuration saved successfully, Restarting service...')
// Restart the service
const { error: restartError } = await useFetch('http://localhost:8077/api/restart', {
method: 'POST'
})
if (restartError.value) {
throw new Error('Failed to restart service')
}
$toast.success('Service restarted successfully')
} catch (error) {
console.error('Error:', error)
$toast.error(error.message)
} finally {
isSaving.value = false
}
}
</script>
10 changes: 10 additions & 0 deletions frontend/plugins/toast.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Vue3Toastify, { toast } from 'vue3-toastify';
import 'vue3-toastify/dist/index.css';

export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Vue3Toastify, { autoClose: 2000 });

return {
provide: { toast },
};
});

0 comments on commit 1719ea9

Please sign in to comment.