Config UI: add provider auth subject to login errors (#25342)
This commit is contained in:
parent
5aadb01eae
commit
1f0bd92518
6 changed files with 58 additions and 32 deletions
19
api/error.go
19
api/error.go
|
|
@ -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{}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
36
util/error.go
Normal 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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue