ecodash/config.go
MassiveBox 52ba0ea4c1
Some checks failed
ci/woodpecker/manual/woodpecker Pipeline failed
Improve SQLite
- Now the cache isn't cleared and fetched from zero each update, but only when there's missing information for a day
- Fixed a bug that prevented new users from saving changes in the config

NOTE: Turns out that HomeAssistant's API only returns data for the last 10 days. Looks like we will have to improve the caching system to work around this.
2023-01-04 15:57:16 +01:00

132 lines
3.2 KiB
Go

package main
import (
"crypto/sha256"
"database/sql"
"encoding/json"
"errors"
"fmt"
"github.com/gofiber/fiber/v2"
_ "github.com/mattn/go-sqlite3"
"os"
"regexp"
"strings"
"time"
)
type Config struct {
db *sql.DB
HomeAssistant HomeAssistant `json:"home_assistant"`
Sensors Sensors `json:"sensors"`
Administrator Administrator `json:"administrator"`
Dashboard Dashboard `json:"dashboard"`
}
type HomeAssistant struct {
BaseURL string `json:"base_url"`
ApiKey string `json:"api_key"`
InstallationDate time.Time `json:"installation_date"`
}
type Sensors struct {
PolledSmartEnergySummation string `json:"polled_smart_energy_summation"`
FossilPercentage string `json:"fossil_percentage"`
}
type Administrator struct {
Username string `json:"username"`
PasswordHash string `json:"password_hash"`
}
type Dashboard struct {
Name string `json:"name"`
Theme string `json:"theme"`
FooterLinks []Link `json:"footer_links"`
HeaderLinks []Link `json:"header_links"`
}
func formatURL(url string) (string, error) {
// the URL we want is: protocol://hostname[:port] without a final /
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "http://" + url
}
if strings.HasSuffix(url, "/") {
url = url[0 : len(url)-1]
}
test := regexp.MustCompile(`(?m)https?:\/\/[^/]*`).ReplaceAllString(url, "")
if test != "" {
return "", errors.New("HomeAssistant base URL is badly formatted")
}
return url, nil
}
func loadConfig() (config Config, err error, isFirstRun bool) {
db, err := sql.Open("sqlite3", "./database.db")
if err != nil {
return Config{}, err, false
}
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS "cache" (
"time" NUMERIC NOT NULL,
"green_energy_percentage" REAL NOT NULL,
"energy_consumption" REAL NOT NULL,
PRIMARY KEY("time")
);`)
if err != nil {
return Config{}, err, false
}
var defaultConfig = Config{}
defaultConfig.Dashboard.Theme = "default"
defaultConfig.Dashboard.Name = "EcoDash"
defaultConfig.Dashboard.HeaderLinks = append(defaultConfig.Dashboard.HeaderLinks, Link{
Label: "Admin",
Destination: "/admin",
}, Link{
Label: "Docs",
Destination: "https://gitea.massivebox.net/massivebox/ecodash",
NewTab: true,
Primary: true,
})
defaultConfig.db = db
data, err := os.ReadFile("config.json")
if err != nil {
// if the data file doesn't exist, we consider it a first run
if os.IsNotExist(err) {
return defaultConfig, nil, true
}
return Config{}, err, false
}
// if the data file is empty, we consider it as a first run
if string(data) == "" {
return defaultConfig, nil, true
}
var conf Config
err = json.Unmarshal(data, &conf)
if err != nil {
return Config{}, err, false
}
conf.db = db
return conf, nil, false
}
// just a little utility function to SHA256 strings (for hashing passwords)
func hash(toHash string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(toHash)))
}
func (config Config) isAuthorized(c *fiber.Ctx) bool {
if config.Administrator.PasswordHash == "" {
return true
}
return c.Cookies("admin_username") == config.Administrator.Username && c.Cookies("admin_password_hash") == config.Administrator.PasswordHash
}