a314aab7ec
* Add support for Web Push Notifications when users receive a new Message or Friend Request on the main website. * Users opt in or out of this on their Notification Settings. They can also individually opt out of Message and Friend Request push notifications.
211 lines
5.2 KiB
Go
211 lines
5.2 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/encryption/coldstorage"
|
|
"code.nonshy.com/nonshy/website/pkg/encryption/keygen"
|
|
"code.nonshy.com/nonshy/website/pkg/log"
|
|
"github.com/SherClockHolmes/webpush-go"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// Version of the config format - when new fields are added, it will attempt
|
|
// to write the settings.toml to disk so new defaults populate.
|
|
var currentVersion = 4
|
|
|
|
// Current loaded settings.json
|
|
var Current = DefaultVariable()
|
|
|
|
// Variable configuration attributes (loaded from settings.json).
|
|
type Variable struct {
|
|
Version int
|
|
BaseURL string
|
|
AdminEmail string
|
|
CronAPIKey string
|
|
Mail Mail
|
|
Redis Redis
|
|
Database Database
|
|
BareRTC BareRTC
|
|
Maintenance Maintenance
|
|
Encryption Encryption
|
|
WebPush WebPush
|
|
Turnstile Turnstile
|
|
UseXForwardedFor bool
|
|
}
|
|
|
|
// DefaultVariable returns the default settings.json data.
|
|
func DefaultVariable() Variable {
|
|
return Variable{
|
|
BaseURL: "http://localhost:8080",
|
|
Mail: Mail{
|
|
Enabled: false,
|
|
Host: "localhost",
|
|
Port: 25,
|
|
From: "no-reply@localhost",
|
|
},
|
|
Redis: Redis{
|
|
Host: "localhost",
|
|
Port: 6379,
|
|
},
|
|
Database: Database{
|
|
SQLite: "database.sqlite",
|
|
Postgres: "host=localhost user=nonshy password=nonshy dbname=nonshy port=5679 sslmode=disable TimeZone=America/Los_Angeles",
|
|
},
|
|
CronAPIKey: uuid.New().String(),
|
|
}
|
|
}
|
|
|
|
// LoadSettings loads the settings.json file or, if not existing, creates it with the default settings.
|
|
func LoadSettings() {
|
|
var writeSettings bool
|
|
|
|
if _, err := os.Stat(SettingsPath); !os.IsNotExist(err) {
|
|
log.Info("Loading settings from %s", SettingsPath)
|
|
content, err := os.ReadFile(SettingsPath)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("LoadSettings: couldn't read settings.json: %s", err))
|
|
}
|
|
|
|
var v Variable
|
|
err = json.Unmarshal(content, &v)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("LoadSettings: couldn't parse settings.json: %s", err))
|
|
}
|
|
|
|
Current = v
|
|
} else {
|
|
WriteSettings()
|
|
log.Warn("NOTICE: Created default settings.json file - review it and configure mail servers and database!")
|
|
}
|
|
|
|
// If there is no DB configured, exit now.
|
|
if !Current.Database.IsSQLite && !Current.Database.IsPostgres {
|
|
log.Error("No database configured in settings.json. Choose SQLite or Postgres and update the DB connector string!")
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Initialize the AES encryption key.
|
|
if len(Current.Encryption.AESKey) == 0 {
|
|
log.Warn("NOTICE: rolling a random 32-byte (256-bit) AES encryption key for the settings file")
|
|
aesKey, err := keygen.NewAESKey()
|
|
if err != nil {
|
|
log.Error("Couldn't generate AES key: %s", err)
|
|
os.Exit(1)
|
|
}
|
|
Current.Encryption.AESKey = aesKey
|
|
writeSettings = true
|
|
}
|
|
|
|
// Initialize the cold storage RSA keys.
|
|
if len(Current.Encryption.ColdStorageRSAPublicKey) == 0 {
|
|
x509publicKey, err := coldstorage.Initialize()
|
|
if err != nil {
|
|
log.Error("Initializing cold storage: %s", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Store the public key in the settings.json.
|
|
Current.Encryption.ColdStorageRSAPublicKey = x509publicKey
|
|
writeSettings = true
|
|
}
|
|
|
|
// Initialize the VAPID keys for Web Push Notification.
|
|
if len(Current.WebPush.VAPIDPublicKey) == 0 {
|
|
privateKey, publicKey, err := webpush.GenerateVAPIDKeys()
|
|
if err != nil {
|
|
log.Error("Initializing VAPID keys for Web Push: %s", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
Current.WebPush.VAPIDPrivateKey = privateKey
|
|
Current.WebPush.VAPIDPublicKey = publicKey
|
|
writeSettings = true
|
|
}
|
|
|
|
// Have we added new config fields? Save the settings.json.
|
|
if Current.Version != currentVersion || writeSettings {
|
|
log.Warn("New options are available for your settings.json file. Your settings will be re-saved now.")
|
|
Current.Version = currentVersion
|
|
if err := WriteSettings(); err != nil {
|
|
log.Error("Couldn't write your settings.json file: %s", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// WriteSettings will commit the settings.json to disk.
|
|
func WriteSettings() error {
|
|
log.Error("Note: initial settings.json was written to disk.")
|
|
|
|
var buf bytes.Buffer
|
|
enc := json.NewEncoder(&buf)
|
|
enc.SetIndent("", " ")
|
|
err := enc.Encode(Current)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("WriteSettings: couldn't marshal settings: %s", err))
|
|
}
|
|
|
|
return os.WriteFile(SettingsPath, buf.Bytes(), 0600)
|
|
}
|
|
|
|
// Mail settings.
|
|
type Mail struct {
|
|
Enabled bool
|
|
Host string // localhost
|
|
Port int // 25
|
|
From string // noreply@localhost
|
|
Username string // SMTP credentials
|
|
Password string
|
|
}
|
|
|
|
// Redis settings.
|
|
type Redis struct {
|
|
Host string
|
|
Port int
|
|
DB int
|
|
}
|
|
|
|
// Database settings.
|
|
type Database struct {
|
|
IsSQLite bool
|
|
IsPostgres bool
|
|
SQLite string
|
|
Postgres string
|
|
}
|
|
|
|
// BareRTC chat room settings.
|
|
type BareRTC struct {
|
|
JWTSecret string
|
|
URL string
|
|
}
|
|
|
|
// Maintenance mode settings.
|
|
type Maintenance struct {
|
|
PauseSignup bool
|
|
PauseLogin bool
|
|
PauseChat bool
|
|
PauseInteraction bool
|
|
}
|
|
|
|
// Encryption settings.
|
|
type Encryption struct {
|
|
AESKey []byte
|
|
ColdStorageRSAPublicKey []byte
|
|
}
|
|
|
|
// WebPush settings.
|
|
type WebPush struct {
|
|
VAPIDPublicKey string
|
|
VAPIDPrivateKey string
|
|
}
|
|
|
|
// Turnstile (Cloudflare CAPTCHA) settings.
|
|
type Turnstile struct {
|
|
Enabled bool
|
|
SiteKey string
|
|
SecretKey string
|
|
}
|