Config UI: fix editing existing OAuth devices (#28012)
This commit is contained in:
parent
20de0b9da1
commit
b28be96d0a
8 changed files with 98 additions and 9 deletions
|
|
@ -279,6 +279,7 @@ func (s *HTTPd) RegisterSystemHandler(site *core.Site, pub publisher, cache *uti
|
|||
|
||||
routes := map[string]route{
|
||||
"auth": {"POST", "/auth", authHandler},
|
||||
"authmerged": {"POST", "/auth/{class:[a-z]+}/merge/{id:[0-9.]+}", authHandler},
|
||||
"templates": {"GET", "/templates/{class:[a-z]+}", templatesHandler},
|
||||
"products": {"GET", "/products/{class:[a-z]+}", productsHandler},
|
||||
"devices": {"GET", "/devices/{class:[a-z]+}", devicesConfigHandler},
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ func templateForConfig(class templates.Class, conf map[string]any) (templates.Te
|
|||
return templates.ByName(class, typ)
|
||||
}
|
||||
|
||||
// filterValidTemplateParams removes all configuration properties that are not part of the template definition
|
||||
func filterValidTemplateParams(tmpl *templates.Template, conf map[string]any) map[string]any {
|
||||
res := make(map[string]any)
|
||||
|
||||
|
|
@ -169,6 +170,32 @@ func mergeMasked(class templates.Class, conf, old map[string]any) (map[string]an
|
|||
})
|
||||
}
|
||||
|
||||
// deviceOther looks up a stored device's `Other` config by class and id.
|
||||
func deviceOther(class templates.Class, id int) (map[string]any, error) {
|
||||
name := config.NameForID(id)
|
||||
switch class {
|
||||
case templates.Charger:
|
||||
return deviceOtherFromHandler(name, config.Chargers())
|
||||
case templates.Meter:
|
||||
return deviceOtherFromHandler(name, config.Meters())
|
||||
case templates.Vehicle:
|
||||
return deviceOtherFromHandler(name, config.Vehicles())
|
||||
case templates.Tariff:
|
||||
return deviceOtherFromHandler(name, config.Tariffs())
|
||||
case templates.Messenger:
|
||||
return deviceOtherFromHandler(name, config.Messengers())
|
||||
}
|
||||
return nil, errors.New("unsupported class: " + class.String())
|
||||
}
|
||||
|
||||
func deviceOtherFromHandler[T any](name string, h config.Handler[T]) (map[string]any, error) {
|
||||
dev, err := h.ByName(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dev.Config().Other, nil
|
||||
}
|
||||
|
||||
func startDeviceTimeout() (context.Context, context.CancelFunc, chan struct{}) {
|
||||
done := make(chan struct{})
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/evcc-io/evcc/plugin/auth"
|
||||
|
|
@ -42,6 +43,38 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// when editing existing device, merge masked values with stored config
|
||||
if vars := mux.Vars(r); vars["class"] != "" && vars["id"] != "" {
|
||||
id, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
class, err := templates.ClassString(vars["class"])
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
old, err := deviceOther(class, id)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
merged, err := mergeMasked(class, cc.Other, old)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
cc.Other = merged
|
||||
}
|
||||
|
||||
// template is only needed by mergeMasked above; the auth decoder is strict
|
||||
delete(cc.Other, typeTemplate)
|
||||
|
||||
ts, err := auth.NewFromConfig(context.Background(), cc.Type, cc.Other)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusBadRequest, err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue