Config UI: add provider auth subject to login errors (#25342)

This commit is contained in:
andig 2025-11-20 19:02:18 +01:00 • committed by GitHub
parent 5aadb01eae
commit 1f0bd92518
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 58 additions and 32 deletions

View file

@ -18,9 +18,6 @@ var ErrSponsorRequired = errors.New("sponsorship required, see https://docs.evcc
// ErrMissingCredentials indicates that user/password are missing
var ErrMissingCredentials = backoff.Permanent(errors.New("missing user/password credentials"))
// ErrLoginRequired indicates that retrieving tokens credentials waits for login
var ErrLoginRequired = backoff.Permanent(errors.New("login required"))
// ErrMissingToken indicates that access/refresh tokens are missing
var ErrMissingToken = backoff.Permanent(errors.New("missing token credentials"))
@ -30,6 +27,22 @@ var ErrOutdated = errors.New("outdated")
// ErrTimeout is the error returned when a timeout happened
var ErrTimeout error = errors.New("timeout")
// LoginRequiredError creates a login error for given auth provider
func LoginRequiredError(providerAuth string) error {
return backoff.Permanent(&ErrLoginRequired{
ProviderAuth: providerAuth,
})
}
// ErrLoginRequired indicates that retrieving tokens credentials waits for login
type ErrLoginRequired struct {
ProviderAuth string
}
func (err *ErrLoginRequired) Error() string {
return "login required"
}
// ErrAsleep indicates that vehicle is asleep. Caller may chose to wake up the vehicle and retry.
var ErrAsleep error = errAsleep{}

View file

@ -160,7 +160,7 @@ func (o *OAuth) Token() (*oauth2.Token, error) {
defer o.mu.Unlock()
if o.token == nil {
return nil, api.ErrMissingToken
return nil, api.LoginRequiredError(o.subject)
}
if o.token.Valid() {

View file

@ -21,7 +21,7 @@ func TestOAuth(t *testing.T) {
require.NoError(t, err)
token, err := ts.Token()
require.ErrorContains(t, err, "missing token credentials")
require.ErrorContains(t, err, "login required")
require.False(t, token.Valid())
require.Equal(t, 0, storerCalled)

View file

@ -26,7 +26,6 @@ import (
"github.com/evcc-io/evcc/util/logstash"
"github.com/gorilla/mux"
"github.com/itchyny/gojq"
"go.yaml.in/yaml/v4"
"golang.org/x/text/language"
)
@ -82,35 +81,12 @@ func jsonHandler(h http.Handler) http.Handler {
}
func jsonWrite(w http.ResponseWriter, data any) {
if err := json.NewEncoder(w).Encode(data); err != nil {
log.ERROR.Printf("httpd: failed to encode JSON: %v", err)
}
json.NewEncoder(w).Encode(data)
}
func jsonError(w http.ResponseWriter, status int, err error) {
w.WriteHeader(status)
res := struct {
Error string `json:"error"`
Line int `json:"line,omitempty"`
IsAuthError bool `json:"isAuthError,omitempty"`
}{
Error: err.Error(),
IsAuthError: errors.Is(err, api.ErrLoginRequired) || errors.Is(err, api.ErrMissingToken),
}
var (
ype *yaml.ParserError
yue *yaml.UnmarshalError
)
switch {
case errors.As(err, &ype):
res.Line = ype.Line
case errors.As(err, &yue):
res.Line = yue.Line
}
jsonWrite(w, res)
jsonWrite(w, util.ErrorAsJson(err))
}
func handler[T any](conv func(string) (T, error), set func(T) error, get func() T) http.HandlerFunc {

36
util/error.go Normal file
View file

@ -0,0 +1,36 @@
package util
import (
"errors"
"github.com/evcc-io/evcc/api"
"go.yaml.in/yaml/v4"
)
// ErrorAsJson returns an error as json-formattable struct
func ErrorAsJson(err error) any {
res := struct {
Error string `json:"error"`
Line int `json:"line,omitempty"`
LoginRequired string `json:"loginRequired,omitempty"`
}{
Error: err.Error(),
}
if ae := new(api.ErrLoginRequired); errors.As(err, &ae) {
res.LoginRequired = ae.ProviderAuth
}
var (
ype *yaml.ParserError
yue *yaml.UnmarshalError
)
switch {
case errors.As(err, &ype):
res.Line = ype.Line
case errors.As(err, &yue):
res.Line = yue.Line
}
return res
}

View file

@ -29,5 +29,6 @@ func TokenExtra(t *oauth2.Token, key string) string {
}
func tokenError(err error) bool {
return errors.Is(err, api.ErrLoginRequired) || errors.Is(err, api.ErrMissingToken)
ae := new(api.ErrLoginRequired)
return errors.As(err, &ae)
}