♻️ Replaces xerrors to errors package
This commit is contained in:
parent
54de0d1dcb
commit
f1245f334f
|
@ -9,7 +9,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
http "github.com/valyala/fasthttp"
|
http "github.com/valyala/fasthttp"
|
||||||
"golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Me is a URL user identifier.
|
// Me is a URL user identifier.
|
||||||
|
@ -22,87 +21,79 @@ type Me struct {
|
||||||
func ParseMe(raw string) (*Me, error) {
|
func ParseMe(raw string) (*Me, error) {
|
||||||
me := http.AcquireURI()
|
me := http.AcquireURI()
|
||||||
if err := me.Parse(nil, []byte(raw)); err != nil {
|
if err := me.Parse(nil, []byte(raw)); err != nil {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: err.Error(),
|
err.Error(),
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme := string(me.Scheme())
|
scheme := string(me.Scheme())
|
||||||
if scheme != "http" && scheme != "https" {
|
if scheme != "http" && scheme != "https" {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile URL MUST have either an https or http scheme",
|
"profile URL MUST have either an https or http scheme",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
path := string(me.PathOriginal())
|
path := string(me.PathOriginal())
|
||||||
if path == "" || strings.Contains(path, "/.") || strings.Contains(path, "/..") {
|
if path == "" || strings.Contains(path, "/.") || strings.Contains(path, "/..") {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile URL MUST contain a path component (/ is a valid path), MUST NOT " +
|
"profile URL MUST contain a path component (/ is a valid path), MUST NOT contain single-dot "+
|
||||||
"contain single-dot or double-dot path segments",
|
"or double-dot path segments",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if me.Hash() != nil {
|
if me.Hash() != nil {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile URL MUST NOT contain a fragment component",
|
"profile URL MUST NOT contain a fragment component",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if me.Username() != nil || me.Password() != nil {
|
if me.Username() != nil || me.Password() != nil {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile URL MUST NOT contain a username or password component",
|
"profile URL MUST NOT contain a username or password component",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
domain := string(me.Host())
|
domain := string(me.Host())
|
||||||
if domain == "" {
|
if domain == "" {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile host name MUST be a domain name",
|
"profile host name MUST be a domain name",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, port, _ := net.SplitHostPort(domain); port != "" {
|
if _, port, _ := net.SplitHostPort(domain); port != "" {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile MUST NOT contain a port",
|
"profile MUST NOT contain a port",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if net.ParseIP(domain) != nil {
|
if net.ParseIP(domain) != nil {
|
||||||
return nil, Error{
|
return nil, NewError(
|
||||||
Code: ErrorCodeInvalidRequest,
|
ErrorCodeInvalidRequest,
|
||||||
Description: "profile MUST NOT be ipv4 or ipv6 addresses",
|
"profile MUST NOT be ipv4 or ipv6 addresses",
|
||||||
URI: "https://indieauth.net/source/#user-profile-url",
|
"https://indieauth.net/source/#user-profile-url",
|
||||||
State: "",
|
"",
|
||||||
frame: xerrors.Caller(1),
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Me{me: me}, nil
|
return &Me{me: me}, nil
|
||||||
|
|
|
@ -2,11 +2,10 @@ package memory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"source.toby3d.me/website/indieauth/internal/domain"
|
"source.toby3d.me/website/indieauth/internal/domain"
|
||||||
"source.toby3d.me/website/indieauth/internal/token"
|
"source.toby3d.me/website/indieauth/internal/token"
|
||||||
)
|
)
|
||||||
|
@ -25,7 +24,7 @@ func NewMemoryTokenRepository(store *sync.Map) token.Repository {
|
||||||
|
|
||||||
func (repo *memoryTokenRepository) Create(ctx context.Context, accessToken *domain.Token) error {
|
func (repo *memoryTokenRepository) Create(ctx context.Context, accessToken *domain.Token) error {
|
||||||
t, err := repo.Get(ctx, accessToken.AccessToken)
|
t, err := repo.Get(ctx, accessToken.AccessToken)
|
||||||
if err != nil && !xerrors.Is(err, token.ErrNotExist) {
|
if err != nil && !errors.Is(err, token.ErrNotExist) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@ package usecase
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/lestrrat-go/jwx/jwa"
|
"github.com/lestrrat-go/jwx/jwa"
|
||||||
"github.com/lestrrat-go/jwx/jwt"
|
"github.com/lestrrat-go/jwx/jwt"
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"source.toby3d.me/website/indieauth/internal/domain"
|
"source.toby3d.me/website/indieauth/internal/domain"
|
||||||
"source.toby3d.me/website/indieauth/internal/session"
|
"source.toby3d.me/website/indieauth/internal/session"
|
||||||
|
@ -15,16 +15,16 @@ import (
|
||||||
|
|
||||||
type tokenUseCase struct {
|
type tokenUseCase struct {
|
||||||
sessions session.Repository
|
sessions session.Repository
|
||||||
config *domain.Config
|
|
||||||
tokens token.Repository
|
tokens token.Repository
|
||||||
|
config *domain.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTokenUseCase(tokens token.Repository, sessions session.Repository, config *domain.Config) token.UseCase {
|
func NewTokenUseCase(tokens token.Repository, sessions session.Repository, config *domain.Config) token.UseCase {
|
||||||
jwt.RegisterCustomField("scope", make(domain.Scopes, 0))
|
jwt.RegisterCustomField("scope", make(domain.Scopes, 0))
|
||||||
|
|
||||||
return &tokenUseCase{
|
return &tokenUseCase{
|
||||||
sessions: sessions,
|
|
||||||
config: config,
|
config: config,
|
||||||
|
sessions: sessions,
|
||||||
tokens: tokens,
|
tokens: tokens,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ func (useCase *tokenUseCase) Exchange(ctx context.Context, opts token.ExchangeOp
|
||||||
|
|
||||||
// NOTE(toby3d): If the authorization code was issued with no scope, the
|
// NOTE(toby3d): If the authorization code was issued with no scope, the
|
||||||
// token endpoint MUST NOT issue an access token, as empty scopes are
|
// token endpoint MUST NOT issue an access token, as empty scopes are
|
||||||
// invalid per Section 3.3 of OAuth 2.0 RFC6749.
|
// invalid (RFC 6749 section 3.3).
|
||||||
if session.Scope.IsEmpty() {
|
if session.Scope.IsEmpty() {
|
||||||
return nil, nil, token.ErrEmptyScope
|
return nil, nil, token.ErrEmptyScope
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func (useCase *tokenUseCase) Exchange(ctx context.Context, opts token.ExchangeOp
|
||||||
|
|
||||||
func (useCase *tokenUseCase) Verify(ctx context.Context, accessToken string) (*domain.Token, error) {
|
func (useCase *tokenUseCase) Verify(ctx context.Context, accessToken string) (*domain.Token, error) {
|
||||||
find, err := useCase.tokens.Get(ctx, accessToken)
|
find, err := useCase.tokens.Get(ctx, accessToken)
|
||||||
if err != nil && !xerrors.Is(err, token.ErrNotExist) {
|
if err != nil && !errors.Is(err, token.ErrNotExist) {
|
||||||
return nil, fmt.Errorf("cannot check token in store: %w", err)
|
return nil, fmt.Errorf("cannot check token in store: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,12 +100,8 @@ func (useCase *tokenUseCase) Verify(ctx context.Context, accessToken string) (*d
|
||||||
return nil, fmt.Errorf("cannot validate JWT token: %w", err)
|
return nil, fmt.Errorf("cannot validate JWT token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := &domain.Token{
|
result := new(domain.Token)
|
||||||
Scope: nil,
|
result.AccessToken = accessToken
|
||||||
ClientID: nil,
|
|
||||||
Me: nil,
|
|
||||||
AccessToken: accessToken,
|
|
||||||
}
|
|
||||||
result.ClientID, _ = domain.ParseClientID(tkn.Issuer())
|
result.ClientID, _ = domain.ParseClientID(tkn.Issuer())
|
||||||
result.Me, _ = domain.ParseMe(tkn.Subject())
|
result.Me, _ = domain.ParseMe(tkn.Subject())
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue