From 6a1e281ebb8b75c2512ad4001afb1edb9a77eee6 Mon Sep 17 00:00:00 2001 From: Maxim Lebedev Date: Wed, 16 Feb 2022 01:07:39 +0500 Subject: [PATCH] :art: Format of the exist code before refactoring --- internal/auth/delivery/http/auth_http.go | 4 +- internal/auth/delivery/http/auth_http_test.go | 2 +- internal/domain/action.go | 7 +- internal/domain/client_id.go | 8 +- internal/domain/code_challenge_method.go | 24 +++--- internal/domain/grant_type.go | 10 ++- internal/domain/me.go | 6 +- internal/domain/metadata.go | 49 ++++++++++- internal/domain/response_type.go | 11 ++- internal/domain/scope.go | 20 +++-- internal/domain/url.go | 22 ++++- .../metadata/delivery/http/metadata_http.go | 82 ++++++------------- .../delivery/http/metadata_http_test.go | 17 +--- internal/token/delivery/http/token_http.go | 14 ++-- main.go | 40 ++++++++- 15 files changed, 192 insertions(+), 124 deletions(-) diff --git a/internal/auth/delivery/http/auth_http.go b/internal/auth/delivery/http/auth_http.go index 246d167..ba80009 100644 --- a/internal/auth/delivery/http/auth_http.go +++ b/internal/auth/delivery/http/auth_http.go @@ -159,12 +159,12 @@ func (h *RequestHandler) Register(r *router.Router) { middleware.LogFmt(), } - r.GET("/authorize", chain.RequestHandler(h.handleRender)) + r.GET("/authorize", chain.RequestHandler(h.handleAuthorize)) r.POST("/api/authorize", chain.RequestHandler(h.handleVerify)) r.POST("/authorize", chain.RequestHandler(h.handleExchange)) } -func (h *RequestHandler) handleRender(ctx *http.RequestCtx) { +func (h *RequestHandler) handleAuthorize(ctx *http.RequestCtx) { ctx.SetContentType(common.MIMETextHTMLCharsetUTF8) tags, _, _ := language.ParseAcceptLanguage(string(ctx.Request.Header.Peek(http.HeaderAcceptLanguage))) diff --git a/internal/auth/delivery/http/auth_http_test.go b/internal/auth/delivery/http/auth_http_test.go index 9e78802..aa6caac 100644 --- a/internal/auth/delivery/http/auth_http_test.go +++ b/internal/auth/delivery/http/auth_http_test.go @@ -35,7 +35,7 @@ type Dependencies struct { store *sync.Map } -func TestRender(t *testing.T) { +func TestAuthorize(t *testing.T) { t.Parallel() deps := NewDependencies(t) diff --git a/internal/domain/action.go b/internal/domain/action.go index 0ada4fd..eaedf16 100644 --- a/internal/domain/action.go +++ b/internal/domain/action.go @@ -1,4 +1,3 @@ -//nolint: dupl package domain import ( @@ -44,7 +43,7 @@ func ParseAction(uid string) (Action, error) { func (a *Action) UnmarshalForm(v []byte) error { action, err := ParseAction(string(v)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("Action: UnmarshalForm: %w", err) } *a = action @@ -56,12 +55,12 @@ func (a *Action) UnmarshalForm(v []byte) error { func (a *Action) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("Action: UnmarshalJSON: %w", err) } action, err := ParseAction(src) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("Action: UnmarshalJSON: %w", err) } *a = action diff --git a/internal/domain/client_id.go b/internal/domain/client_id.go index f5f3667..4b41165 100644 --- a/internal/domain/client_id.go +++ b/internal/domain/client_id.go @@ -107,7 +107,7 @@ func ParseClientID(src string) (*ClientID, error) { func TestClientID(tb testing.TB) *ClientID { tb.Helper() - clientID, err := ParseClientID("https://app.example.com/") + clientID, err := ParseClientID("https://indieauth.example.com/") if err != nil { tb.Fatal(err) } @@ -119,7 +119,7 @@ func TestClientID(tb testing.TB) *ClientID { func (cid *ClientID) UnmarshalForm(v []byte) error { clientID, err := ParseClientID(string(v)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("ClientID: UnmarshalForm: %w", err) } *cid = *clientID @@ -131,12 +131,12 @@ func (cid *ClientID) UnmarshalForm(v []byte) error { func (cid *ClientID) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("ClientID: UnmarshalJSON: %w", err) } clientID, err := ParseClientID(src) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("ClientID: UnmarshalJSON: %w", err) } *cid = *clientID diff --git a/internal/domain/code_challenge_method.go b/internal/domain/code_challenge_method.go index b72c733..eb5fd84 100644 --- a/internal/domain/code_challenge_method.go +++ b/internal/domain/code_challenge_method.go @@ -35,15 +35,13 @@ var ( } CodeChallengeMethodMD5 = CodeChallengeMethod{ - uid: "MD5", - //nolint: gosec // support old clients - hash: md5.New(), + uid: "MD5", + hash: md5.New(), //nolint: gosec // support old clients } CodeChallengeMethodS1 = CodeChallengeMethod{ - uid: "S1", - //nolint: gosec // support old clients - hash: sha1.New(), + uid: "S1", + hash: sha1.New(), //nolint: gosec // support old clients } CodeChallengeMethodS256 = CodeChallengeMethod{ @@ -64,7 +62,7 @@ var ErrCodeChallengeMethodUnknown error = NewError( ) //nolint: gochecknoglobals // maps cannot be constants -var slugsMethods = map[string]CodeChallengeMethod{ +var uidsMethods = map[string]CodeChallengeMethod{ CodeChallengeMethodMD5.uid: CodeChallengeMethodMD5, CodeChallengeMethodPLAIN.uid: CodeChallengeMethodPLAIN, CodeChallengeMethodS1.uid: CodeChallengeMethodS1, @@ -75,7 +73,7 @@ var slugsMethods = map[string]CodeChallengeMethod{ // ParseCodeChallengeMethod parse string identifier of code challenge method // into struct enum. func ParseCodeChallengeMethod(uid string) (CodeChallengeMethod, error) { - if method, ok := slugsMethods[strings.ToUpper(uid)]; ok { + if method, ok := uidsMethods[strings.ToUpper(uid)]; ok { return method, nil } @@ -86,7 +84,7 @@ func ParseCodeChallengeMethod(uid string) (CodeChallengeMethod, error) { func (ccm *CodeChallengeMethod) UnmarshalForm(v []byte) error { method, err := ParseCodeChallengeMethod(string(v)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("CodeChallengeMethod: UnmarshalForm: %w", err) } *ccm = method @@ -98,12 +96,12 @@ func (ccm *CodeChallengeMethod) UnmarshalForm(v []byte) error { func (ccm *CodeChallengeMethod) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("CodeChallengeMethod: UnmarshalJSON: %w", err) } method, err := ParseCodeChallengeMethod(src) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("CodeChallengeMethod: UnmarshalJSON: %w", err) } *ccm = method @@ -111,6 +109,10 @@ func (ccm *CodeChallengeMethod) UnmarshalJSON(v []byte) error { return nil } +func (ccm CodeChallengeMethod) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(ccm.uid)), nil +} + // String returns string representation of code challenge method. func (ccm CodeChallengeMethod) String() string { return ccm.uid diff --git a/internal/domain/grant_type.go b/internal/domain/grant_type.go index e56e203..c1595e2 100644 --- a/internal/domain/grant_type.go +++ b/internal/domain/grant_type.go @@ -46,7 +46,7 @@ func ParseGrantType(uid string) (GrantType, error) { func (gt *GrantType) UnmarshalForm(src []byte) error { responseType, err := ParseGrantType(string(src)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("GrantType: UnmarshalForm: %w", err) } *gt = responseType @@ -58,12 +58,12 @@ func (gt *GrantType) UnmarshalForm(src []byte) error { func (gt *GrantType) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("GrantType: UnmarshalJSON: %w", err) } responseType, err := ParseGrantType(src) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("GrantType: UnmarshalJSON: %w", err) } *gt = responseType @@ -71,6 +71,10 @@ func (gt *GrantType) UnmarshalJSON(v []byte) error { return nil } +func (gt GrantType) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(gt.uid)), nil +} + // String returns string representation of grant type. func (gt GrantType) String() string { return gt.uid diff --git a/internal/domain/me.go b/internal/domain/me.go index adf044c..af3c31f 100644 --- a/internal/domain/me.go +++ b/internal/domain/me.go @@ -115,7 +115,7 @@ func TestMe(tb testing.TB, src string) *Me { func (m *Me) UnmarshalForm(v []byte) error { me, err := ParseMe(string(v)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("Me: UnmarshalForm: %w", err) } *m = *me @@ -127,12 +127,12 @@ func (m *Me) UnmarshalForm(v []byte) error { func (m *Me) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("Me: UnmarshalJSON: %w", err) } me, err := ParseMe(src) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("Me: UnmarshalJSON: %w", err) } *m = *me diff --git a/internal/domain/metadata.go b/internal/domain/metadata.go index 6d62fb5..3707bf4 100644 --- a/internal/domain/metadata.go +++ b/internal/domain/metadata.go @@ -1,5 +1,7 @@ package domain +import "testing" + //nolint: tagliatelle // https://indieauth.net/source/#indieauth-server-metadata type Metadata struct { // The server's issuer identifier. The issuer identifier is a URL that @@ -10,7 +12,7 @@ type Metadata struct { // issuer URL could be https://example.com/, or for a metadata URL of // https://example.com/wp-json/indieauth/1.0/metadata, the issuer URL // could be https://example.com/wp-json/indieauth/1.0 - Issuer *URL `json:"issuer"` + Issuer *ClientID `json:"issuer"` // The Authorization Endpoint. AuthorizationEndpoint *URL `json:"authorization_endpoint"` @@ -60,3 +62,48 @@ type Metadata struct { // WARN(toby3d): experimental Microsub *URL `json:"microsub,omitempty"` } + +// TestMetadata returns valid random generated Metadata for tests. +func TestMetadata(tb testing.TB) *Metadata { + tb.Helper() + + return &Metadata{ + Issuer: TestClientID(tb), + AuthorizationEndpoint: TestURL(tb, "https://indieauth.example.com/auth"), + TokenEndpoint: TestURL(tb, "https://indieauth.example.com/token"), + ScopesSupported: Scopes{ + ScopeBlock, + ScopeChannels, + ScopeCreate, + ScopeDelete, + ScopeDraft, + ScopeEmail, + ScopeFollow, + ScopeMedia, + ScopeMute, + ScopeProfile, + ScopeRead, + ScopeUpdate, + }, + ResponseTypesSupported: []ResponseType{ + ResponseTypeCode, + ResponseTypeID, + }, + GrantTypesSupported: []GrantType{ + GrantTypeAuthorizationCode, + GrantTypeTicket, + }, + ServiceDocumentation: TestURL(tb, "https://indieauth.net/draft/"), + CodeChallengeMethodsSupported: []CodeChallengeMethod{ + CodeChallengeMethodMD5, + CodeChallengeMethodPLAIN, + CodeChallengeMethodS1, + CodeChallengeMethodS256, + CodeChallengeMethodS512, + }, + AuthorizationResponseIssParameterSupported: true, + TicketEndpoint: TestURL(tb, "https://auth.example.org/ticket"), + Micropub: TestURL(tb, "https://example.com/micropub"), + Microsub: TestURL(tb, "https://example.com/microsub"), + } +} diff --git a/internal/domain/response_type.go b/internal/domain/response_type.go index 506ed50..a46fb96 100644 --- a/internal/domain/response_type.go +++ b/internal/domain/response_type.go @@ -1,4 +1,3 @@ -//nolint: dupl package domain import ( @@ -51,7 +50,7 @@ func ParseResponseType(uid string) (ResponseType, error) { func (rt *ResponseType) UnmarshalForm(src []byte) error { responseType, err := ParseResponseType(string(src)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("ResponseType: UnmarshalForm: %w", err) } *rt = responseType @@ -63,12 +62,12 @@ func (rt *ResponseType) UnmarshalForm(src []byte) error { func (rt *ResponseType) UnmarshalJSON(v []byte) error { uid, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("ResponseType: UnmarshalJSON: %w", err) } responseType, err := ParseResponseType(uid) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("ResponseType: UnmarshalJSON: %w", err) } *rt = responseType @@ -76,6 +75,10 @@ func (rt *ResponseType) UnmarshalJSON(v []byte) error { return nil } +func (rt ResponseType) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(rt.uid)), nil +} + // String returns string representation of response type. func (rt ResponseType) String() string { return rt.uid diff --git a/internal/domain/scope.go b/internal/domain/scope.go index d812b51..c4ac14d 100644 --- a/internal/domain/scope.go +++ b/internal/domain/scope.go @@ -81,6 +81,15 @@ func ParseScope(uid string) (Scope, error) { return ScopeUndefined, fmt.Errorf("%w: %s", ErrScopeUnknown, uid) } +func (s Scope) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(s.uid)), nil +} + +// String returns string representation of scope. +func (s Scope) String() string { + return s.uid +} + // UnmarshalForm implements custom unmarshler for form values. func (s *Scopes) UnmarshalForm(v []byte) error { scopes := make(Scopes, 0) @@ -88,7 +97,7 @@ func (s *Scopes) UnmarshalForm(v []byte) error { for _, rawScope := range strings.Fields(string(v)) { scope, err := ParseScope(rawScope) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("Scopes: UnmarshalForm: %w", err) } if scopes.Has(scope) { @@ -107,7 +116,7 @@ func (s *Scopes) UnmarshalForm(v []byte) error { func (s *Scopes) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("Scopes: UnmarshalJSON: %w", err) } result := make(Scopes, 0) @@ -115,7 +124,7 @@ func (s *Scopes) UnmarshalJSON(v []byte) error { for _, rawScope := range strings.Fields(src) { scope, err := ParseScope(rawScope) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("Scopes: UnmarshalJSON: %w", err) } if result.Has(scope) { @@ -141,11 +150,6 @@ func (s Scopes) MarshalJSON() ([]byte, error) { return []byte(strconv.Quote(strings.Join(scopes, " "))), nil } -// String returns string representation of scope. -func (s Scope) String() string { - return s.uid -} - // String returns string representation of scopes. func (s Scopes) String() string { scopes := make([]string, len(s)) diff --git a/internal/domain/url.go b/internal/domain/url.go index d281e33..c922c41 100644 --- a/internal/domain/url.go +++ b/internal/domain/url.go @@ -14,7 +14,7 @@ type URL struct { *http.URI } -// ParseURL parse strings as URL. +// ParseURL parse string as URL. func ParseURL(src string) (*URL, error) { u := http.AcquireURI() if err := u.Parse(nil, []byte(src)); err != nil { @@ -24,6 +24,16 @@ func ParseURL(src string) (*URL, error) { return &URL{URI: u}, nil } +// MustParseURL parse string as URL or panic. +func MustParseURL(src string) *URL { + uri, err := ParseURL(src) + if err != nil { + panic("MustParseURL: " + err.Error()) + } + + return uri +} + // TestURL returns URL of provided input for tests. func TestURL(tb testing.TB, src string) *URL { tb.Helper() @@ -40,7 +50,7 @@ func TestURL(tb testing.TB, src string) *URL { func (u *URL) UnmarshalForm(v []byte) error { url, err := ParseURL(string(v)) if err != nil { - return fmt.Errorf("UnmarshalForm: %w", err) + return fmt.Errorf("URL: UnmarshalForm: %w", err) } *u = *url @@ -52,12 +62,12 @@ func (u *URL) UnmarshalForm(v []byte) error { func (u *URL) UnmarshalJSON(v []byte) error { src, err := strconv.Unquote(string(v)) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("URL: UnmarshalJSON: %w", err) } url, err := ParseURL(src) if err != nil { - return fmt.Errorf("UnmarshalJSON: %w", err) + return fmt.Errorf("URL: UnmarshalJSON: %w", err) } *u = *url @@ -65,6 +75,10 @@ func (u *URL) UnmarshalJSON(v []byte) error { return nil } +func (u URL) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(u.String())), nil +} + // URL returns url.URL representation of URL. func (u URL) URL() *url.URL { if u.URI == nil { diff --git a/internal/metadata/delivery/http/metadata_http.go b/internal/metadata/delivery/http/metadata_http.go index 9866841..bff07b9 100644 --- a/internal/metadata/delivery/http/metadata_http.go +++ b/internal/metadata/delivery/http/metadata_http.go @@ -23,39 +23,39 @@ type ( // metadata URL of // https://example.com/wp-json/indieauth/1.0/metadata, the // issuer URL could be https://example.com/wp-json/indieauth/1.0 - Issuer string `json:"issuer"` + Issuer *domain.ClientID `json:"issuer"` // The Authorization Endpoint. - AuthorizationEndpoint string `json:"authorization_endpoint"` + AuthorizationEndpoint *domain.URL `json:"authorization_endpoint"` // The Token Endpoint. - TokenEndpoint string `json:"token_endpoint"` + TokenEndpoint *domain.URL `json:"token_endpoint"` - // JSON array containing scope values supported by the + // JSON array containing scope values supported by the // IndieAuth server. Servers MAY choose not to advertise some // supported scope values even when this parameter is used. - ScopesSupported []string `json:"scopes_supported,omitempty"` + ScopesSupported []domain.Scope `json:"scopes_supported,omitempty"` // JSON array containing the response_type values supported. // This differs from RFC8414 in that this parameter is OPTIONAL // and that, if omitted, the default is code. - ResponseTypesSupported []string `json:"response_types_supported,omitempty"` + ResponseTypesSupported []domain.ResponseType `json:"response_types_supported,omitempty"` // JSON array containing grant type values supported. If // omitted, the default value differs from RFC8414 and is // authorization_code. - GrantTypesSupported []string `json:"grant_types_supported,omitempty"` + GrantTypesSupported []domain.GrantType `json:"grant_types_supported,omitempty"` // URL of a page containing human-readable information that // developers might need to know when using the server. This // might be a link to the IndieAuth spec or something more // personal to your implementation. - ServiceDocumentation string `json:"service_documentation,omitempty"` + ServiceDocumentation *domain.URL `json:"service_documentation,omitempty"` // JSON array containing the methods supported for PKCE. This // parameter differs from RFC8414 in that it is not optional as // PKCE is REQUIRED. - CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"` + CodeChallengeMethodsSupported []domain.CodeChallengeMethod `json:"code_challenge_methods_supported"` // Boolean parameter indicating whether the authorization server // provides the iss parameter. If omitted, the default value is @@ -68,52 +68,13 @@ type ( } RequestHandler struct { - config *domain.Config + metadata *domain.Metadata } ) -// DefaultMetadataResponse contains all supported types by default. -//nolint: gochecknoglobals // structs cannot be constants -var DefaultMetadataResponse = MetadataResponse{ - AuthorizationEndpoint: "", - AuthorizationResponseIssParameterSupported: true, - CodeChallengeMethodsSupported: []string{ - domain.CodeChallengeMethodMD5.String(), - domain.CodeChallengeMethodPLAIN.String(), - domain.CodeChallengeMethodS1.String(), - domain.CodeChallengeMethodS256.String(), - domain.CodeChallengeMethodS512.String(), - }, - GrantTypesSupported: []string{ - domain.GrantTypeAuthorizationCode.String(), - domain.GrantTypeTicket.String(), - }, - Issuer: "", - ResponseTypesSupported: []string{ - domain.ResponseTypeCode.String(), - domain.ResponseTypeID.String(), - }, - ScopesSupported: []string{ - domain.ScopeBlock.String(), - domain.ScopeChannels.String(), - domain.ScopeCreate.String(), - domain.ScopeDelete.String(), - domain.ScopeDraft.String(), - domain.ScopeEmail.String(), - domain.ScopeFollow.String(), - domain.ScopeMedia.String(), - domain.ScopeMute.String(), - domain.ScopeProfile.String(), - domain.ScopeRead.String(), - domain.ScopeUpdate.String(), - }, - ServiceDocumentation: "https://indieauth.net/source/", - TokenEndpoint: "", -} - -func NewRequestHandler(config *domain.Config) *RequestHandler { +func NewRequestHandler(metadata *domain.Metadata) *RequestHandler { return &RequestHandler{ - config: config, + metadata: metadata, } } @@ -126,12 +87,17 @@ func (h *RequestHandler) Register(r *router.Router) { } func (h *RequestHandler) read(ctx *http.RequestCtx) { - resp := DefaultMetadataResponse - resp.Issuer = h.config.Server.GetRootURL() - resp.AuthorizationEndpoint = resp.Issuer + "authorize" - resp.TokenEndpoint = resp.Issuer + "token" - ctx.SetStatusCode(http.StatusOK) - ctx.SetContentType(common.MIMEApplicationJSON) - _ = json.NewEncoder(ctx).Encode(&resp) + ctx.SetContentType(common.MIMEApplicationJSONCharsetUTF8) + _ = json.NewEncoder(ctx).Encode(&MetadataResponse{ + Issuer: h.metadata.Issuer, + AuthorizationEndpoint: h.metadata.AuthorizationEndpoint, + TokenEndpoint: h.metadata.TokenEndpoint, + ScopesSupported: h.metadata.ScopesSupported, + ResponseTypesSupported: h.metadata.ResponseTypesSupported, + GrantTypesSupported: h.metadata.GrantTypesSupported, + ServiceDocumentation: h.metadata.ServiceDocumentation, + CodeChallengeMethodsSupported: h.metadata.CodeChallengeMethodsSupported, + AuthorizationResponseIssParameterSupported: h.metadata.AuthorizationResponseIssParameterSupported, + }) } diff --git a/internal/metadata/delivery/http/metadata_http_test.go b/internal/metadata/delivery/http/metadata_http_test.go index e3f444d..2b0dd4e 100644 --- a/internal/metadata/delivery/http/metadata_http_test.go +++ b/internal/metadata/delivery/http/metadata_http_test.go @@ -1,7 +1,6 @@ package http_test import ( - "reflect" "testing" "github.com/fasthttp/router" @@ -17,8 +16,8 @@ func TestMetadata(t *testing.T) { t.Parallel() r := router.New() - cfg := domain.TestConfig(t) - delivery.NewRequestHandler(cfg).Register(r) + metadata := domain.TestMetadata(t) + delivery.NewRequestHandler(metadata).Register(r) client, _, cleanup := httptest.New(t, r.Handler) t.Cleanup(cleanup) @@ -36,15 +35,7 @@ func TestMetadata(t *testing.T) { result := new(delivery.MetadataResponse) if err = json.Unmarshal(body, result); err != nil { - t.Fatal(err) - } - - expResult := delivery.DefaultMetadataResponse - expResult.Issuer = cfg.Server.GetRootURL() - expResult.AuthorizationEndpoint = expResult.Issuer + "authorize" - expResult.TokenEndpoint = expResult.Issuer + "token" - - if !reflect.DeepEqual(*result, expResult) { - t.Errorf("Unmarshal(%s) = %+v, want %+v", body, result, expResult) + e := err.(*json.SyntaxError) + t.Fatalf("%s#ERROR#%s", body[:e.Offset], body[e.Offset:]) } } diff --git a/internal/token/delivery/http/token_http.go b/internal/token/delivery/http/token_http.go index 4500813..a5d4f37 100644 --- a/internal/token/delivery/http/token_http.go +++ b/internal/token/delivery/http/token_http.go @@ -39,8 +39,8 @@ type ( TokenExchangeResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` - Scope string `json:"scope"` - Me string `json:"me"` + Scope domain.Scopes `json:"scope"` + Me *domain.Me `json:"me"` Profile *TokenProfileResponse `json:"profile,omitempty"` } @@ -176,8 +176,8 @@ func (h *RequestHandler) handleExchange(ctx *http.RequestCtx) { resp := &TokenExchangeResponse{ AccessToken: token.AccessToken, TokenType: "Bearer", - Scope: token.Scope.String(), - Me: token.Me.String(), + Scope: token.Scope, + Me: token.Me, Profile: nil, } @@ -269,9 +269,9 @@ func (h *RequestHandler) handleTicket(ctx *http.RequestCtx) { _ = encoder.Encode(TokenExchangeResponse{ AccessToken: tkn.AccessToken, TokenType: "Bearer", - Scope: tkn.Scope.String(), - Me: tkn.Me.String(), - Profile: nil, + Scope: tkn.Scope, + Me: tkn.Me, + Profile: nil, // TODO(toby3d) }) } diff --git a/main.go b/main.go index c887fe8..a85730e 100644 --- a/main.go +++ b/main.go @@ -279,7 +279,45 @@ func NewApp(opts NewAppOptions) *App { func (app *App) Register(r *router.Router) { tickethttpdelivery.NewRequestHandler(app.tickets, app.matcher, config).Register(r) healthhttpdelivery.NewRequestHandler().Register(r) - metadatahttpdelivery.NewRequestHandler(config).Register(r) + metadatahttpdelivery.NewRequestHandler(&domain.Metadata{ + Issuer: indieAuthClient.ID, + AuthorizationEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "authorize"), + TokenEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "token"), + ScopesSupported: domain.Scopes{ + domain.ScopeBlock, + domain.ScopeChannels, + domain.ScopeCreate, + domain.ScopeDelete, + domain.ScopeDraft, + domain.ScopeEmail, + domain.ScopeFollow, + domain.ScopeMedia, + domain.ScopeMute, + domain.ScopeProfile, + domain.ScopeRead, + domain.ScopeUpdate, + }, + ResponseTypesSupported: []domain.ResponseType{ + domain.ResponseTypeCode, + domain.ResponseTypeID, + }, + GrantTypesSupported: []domain.GrantType{ + domain.GrantTypeAuthorizationCode, + domain.GrantTypeTicket, + }, + ServiceDocumentation: domain.MustParseURL("https://indieauth.net/source/"), + CodeChallengeMethodsSupported: []domain.CodeChallengeMethod{ + domain.CodeChallengeMethodMD5, + domain.CodeChallengeMethodPLAIN, + domain.CodeChallengeMethodS1, + domain.CodeChallengeMethodS256, + domain.CodeChallengeMethodS512, + }, + AuthorizationResponseIssParameterSupported: true, + TicketEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "ticket"), + Micropub: nil, + Microsub: nil, + }).Register(r) tokenhttpdelivery.NewRequestHandler(app.tokens, app.tickets).Register(r) clienthttpdelivery.NewRequestHandler(clienthttpdelivery.NewRequestHandlerOptions{ Client: indieAuthClient,