safing-portmaster/status/provider.go
2021-02-11 13:07:02 +01:00

97 lines
2.4 KiB
Go

package status
import (
"fmt"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/runtime"
"github.com/safing/portmaster/netenv"
)
var (
pushUpdate runtime.PushFunc
)
func setupRuntimeProvider() (err error) {
// register the system status getter
//
statusProvider := runtime.SimpleValueGetterFunc(func(_ string) ([]record.Record, error) {
return []record.Record{buildSystemStatus()}, nil
})
pushUpdate, err = runtime.Register("system/status", statusProvider)
if err != nil {
return err
}
// register the selected security level setter
//
levelProvider := runtime.SimpleValueSetterFunc(setSelectedSecurityLevel)
_, err = runtime.Register("system/security-level", levelProvider)
if err != nil {
return err
}
return nil
}
// setSelectedSecurityLevel updates the selected security level.
func setSelectedSecurityLevel(r record.Record) (record.Record, error) {
var upd *SelectedSecurityLevelRecord
if r.IsWrapped() {
upd = new(SelectedSecurityLevelRecord)
if err := record.Unwrap(r, upd); err != nil {
return nil, err
}
} else {
// TODO(ppacher): this can actually never happen
// as we're write-only and ValueProvider.Set() should
// only ever be called from the HTTP API (so r must be wrapped).
// Though, make sure we handle the case as well ...
var ok bool
upd, ok = r.(*SelectedSecurityLevelRecord)
if !ok {
return nil, fmt.Errorf("expected *SelectedSecurityLevelRecord but got %T", r)
}
}
if !IsValidSecurityLevel(upd.SelectedSecurityLevel) {
return nil, fmt.Errorf("invalid security level: %d", upd.SelectedSecurityLevel)
}
if SelectedSecurityLevel() != upd.SelectedSecurityLevel {
setSelectedLevel(upd.SelectedSecurityLevel)
triggerAutopilot()
}
return r, nil
}
// buildSystemStatus build a new system status record.
func buildSystemStatus() *SystemStatusRecord {
status := &SystemStatusRecord{
ActiveSecurityLevel: ActiveSecurityLevel(),
SelectedSecurityLevel: SelectedSecurityLevel(),
ThreatMitigationLevel: getHighestMitigationLevel(),
CaptivePortal: netenv.GetCaptivePortal(),
OnlineStatus: netenv.GetOnlineStatus(),
}
status.CreateMeta()
status.SetKey("runtime:system/status")
return status
}
// pushSystemStatus pushes a new system status via
// the runtime database.
func pushSystemStatus() {
if pushUpdate == nil {
return
}
record := buildSystemStatus()
record.Lock()
defer record.Unlock()
pushUpdate(record)
}