♻️ Simplify error usage in client package

This commit is contained in:
Maxim Lebedev 2022-01-30 00:49:28 +05:00
parent 2ca16a8fbb
commit 5848f98d95
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
5 changed files with 37 additions and 22 deletions

View File

@ -1,7 +1,7 @@
package http package http
import ( import (
"fmt" "errors"
"strings" "strings"
"github.com/fasthttp/router" "github.com/fasthttp/router"
@ -19,9 +19,11 @@ import (
type ( type (
CallbackRequest struct { CallbackRequest struct {
Code string `form:"code"` Iss *domain.ClientID `form:"iss"`
State string `form:"state"` Code string `form:"code"`
Iss *domain.ClientID `form:"iss"` Error string `form:"error"`
ErrorDescription string `form:"error_description"`
State string `form:"state"`
} }
NewRequestHandlerOptions struct { NewRequestHandlerOptions struct {
@ -92,6 +94,12 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) {
return return
} }
if req.Error != "" {
ctx.Error(req.ErrorDescription, http.StatusUnauthorized)
return
}
// TODO(toby3d): load and check state // TODO(toby3d): load and check state
if req.Iss.String() != h.client.ID.String() { if req.Iss.String() != h.client.ID.String() {
@ -100,7 +108,7 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) {
return return
} }
token, err := h.tokens.Exchange(ctx, token.ExchangeOptions{ token, _, err := h.tokens.Exchange(ctx, token.ExchangeOptions{
ClientID: h.client.ID, ClientID: h.client.ID,
RedirectURI: h.client.RedirectURI[0], RedirectURI: h.client.RedirectURI[0],
Code: req.Code, Code: req.Code,
@ -127,8 +135,14 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) {
} }
func (req *CallbackRequest) bind(ctx *http.RequestCtx) error { func (req *CallbackRequest) bind(ctx *http.RequestCtx) error {
indieAuthError := new(domain.Error)
if err := form.Unmarshal(ctx.QueryArgs(), req); err != nil { if err := form.Unmarshal(ctx.QueryArgs(), req); err != nil {
return fmt.Errorf("cannot unmarshal request: %w", err) if errors.As(err, indieAuthError) {
return indieAuthError
}
return domain.NewError(domain.ErrorCodeInvalidRequest, err.Error(), "")
} }
return nil return nil

View File

@ -2,7 +2,6 @@ package client
import ( import (
"context" "context"
"errors"
"source.toby3d.me/website/indieauth/internal/domain" "source.toby3d.me/website/indieauth/internal/domain"
) )
@ -11,4 +10,4 @@ type Repository interface {
Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error) Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error)
} }
var ErrNotExist = errors.New("client with the specified ID does not exist") var ErrNotExist error = domain.NewError(domain.ErrorCodeInvalidClient, "client with the specified ID does not exist", "")

View File

@ -15,17 +15,15 @@ type httpClientRepository struct {
client *http.Client client *http.Client
} }
const DefaultMaxRedirectsCount int = 10
const ( const (
DefaultMaxRedirectsCount int = 10
hApp string = "h-app"
hXApp string = "h-x-app"
propertyLogo string = "logo"
propertyName string = "name"
propertyURL string = "url"
relRedirectURI string = "redirect_uri" relRedirectURI string = "redirect_uri"
hApp string = "h-app"
hXApp string = "h-x-app"
propertyLogo string = "logo"
propertyName string = "name"
propertyURL string = "url"
) )
func NewHTTPClientRepository(c *http.Client) client.Repository { func NewHTTPClientRepository(c *http.Client) client.Repository {
@ -48,7 +46,7 @@ func (repo *httpClientRepository) Get(ctx context.Context, id *domain.ClientID)
} }
if resp.StatusCode() == http.StatusNotFound { if resp.StatusCode() == http.StatusNotFound {
return nil, client.ErrNotExist return nil, fmt.Errorf("%w: status on client page is not 200", client.ErrNotExist)
} }
client := &domain.Client{ client := &domain.Client{

View File

@ -2,6 +2,7 @@ package memory
import ( import (
"context" "context"
"fmt"
"path" "path"
"sync" "sync"
@ -30,12 +31,12 @@ func (repo *memoryClientRepository) Create(ctx context.Context, client *domain.C
func (repo *memoryClientRepository) Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error) { func (repo *memoryClientRepository) Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error) {
src, ok := repo.store.Load(path.Join(DefaultPathPrefix, id.String())) src, ok := repo.store.Load(path.Join(DefaultPathPrefix, id.String()))
if !ok { if !ok {
return nil, client.ErrNotExist return nil, fmt.Errorf("cannot find client in store: %w", client.ErrNotExist)
} }
c, ok := src.(*domain.Client) c, ok := src.(*domain.Client)
if !ok { if !ok {
return nil, client.ErrNotExist return nil, fmt.Errorf("cannot decode client from store: %w", client.ErrNotExist)
} }
return c, nil return c, nil

View File

@ -2,7 +2,6 @@ package client
import ( import (
"context" "context"
"errors"
"source.toby3d.me/website/indieauth/internal/domain" "source.toby3d.me/website/indieauth/internal/domain"
) )
@ -12,4 +11,8 @@ type UseCase interface {
Discovery(ctx context.Context, id *domain.ClientID) (*domain.Client, error) Discovery(ctx context.Context, id *domain.ClientID) (*domain.Client, error)
} }
var ErrInvalidMe = errors.New("invalid me") var ErrInvalidMe error = domain.NewError(
domain.ErrorCodeInvalidRequest,
"cannot fetch client endpoints on provided me",
"",
)