🎨 Improved enum domains representations

This commit is contained in:
Maxim Lebedev 2022-07-28 23:07:37 +05:00
parent 80ba1868bd
commit 80937fbb8d
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
19 changed files with 183 additions and 170 deletions

View File

@ -338,10 +338,10 @@ func NewAuthAuthorizationRequest() *AuthAuthorizationRequest {
return &AuthAuthorizationRequest{
ClientID: new(domain.ClientID),
CodeChallenge: "",
CodeChallengeMethod: domain.CodeChallengeMethodUndefined,
CodeChallengeMethod: domain.CodeChallengeMethodUnd,
Me: new(domain.Me),
RedirectURI: new(domain.URL),
ResponseType: domain.ResponseTypeUndefined,
ResponseType: domain.ResponseTypeUnd,
Scope: make(domain.Scopes, 0),
State: "",
}
@ -374,11 +374,11 @@ func NewAuthVerifyRequest() *AuthVerifyRequest {
Authorize: "",
ClientID: new(domain.ClientID),
CodeChallenge: "",
CodeChallengeMethod: domain.CodeChallengeMethodUndefined,
CodeChallengeMethod: domain.CodeChallengeMethodUnd,
Me: new(domain.Me),
Provider: "",
RedirectURI: new(domain.URL),
ResponseType: domain.ResponseTypeUndefined,
ResponseType: domain.ResponseTypeUnd,
Scope: make(domain.Scopes, 0),
State: "",
}

View File

@ -76,7 +76,7 @@ func (uc *authUseCase) Exchange(ctx context.Context, opts auth.ExchangeOptions)
}
if session.CodeChallenge != "" &&
session.CodeChallengeMethod != domain.CodeChallengeMethodUndefined &&
session.CodeChallengeMethod != domain.CodeChallengeMethodUnd &&
!session.CodeChallengeMethod.Validate(session.CodeChallenge, opts.CodeVerifier) {
return nil, nil, auth.ErrMismatchPKCE
}

View File

@ -110,7 +110,7 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) {
return
}
if req.Error != domain.ErrorCodeUndefined {
if req.Error != domain.ErrorCodeUnd {
ctx.SetStatusCode(http.StatusUnauthorized)
web.WriteTemplate(ctx, &web.ErrorPage{
BaseOf: baseOf,

View File

@ -11,3 +11,5 @@ const (
MIMETextPlain string = "text/plain"
MIMETextPlainCharsetUTF8 string = MIMETextPlain + "; " + charsetUTF8
)
const Und string = "und"

View File

@ -3,7 +3,8 @@ package domain
import (
"fmt"
"strconv"
"strings"
"source.toby3d.me/toby3d/auth/internal/common"
)
// Action represent action for token endpoint supported by IndieAuth.
@ -16,27 +17,30 @@ type Action struct {
//nolint: gochecknoglobals // structs cannot be constants
var (
ActionUndefined = Action{uid: ""}
ActionUnd = Action{uid: ""} // "und"
// ActionRevoke represent action for revoke token.
ActionRevoke = Action{uid: "revoke"}
ActionRevoke = Action{uid: "revoke"} // "revoke"
// ActionTicket represent action for TicketAuth extension.
ActionTicket = Action{uid: "ticket"}
ActionTicket = Action{uid: "ticket"} // "ticket"
)
var ErrActionUnknown error = NewError(ErrorCodeInvalidRequest, "unknown action method", "")
var ErrActionSyntax error = NewError(ErrorCodeInvalidRequest, "unknown action method", "")
//nolint: gochecknoglobals
var uidsActions = map[string]Action{
ActionRevoke.uid: ActionRevoke,
ActionTicket.uid: ActionTicket,
}
// ParseAction parse string identifier of action into struct enum.
func ParseAction(uid string) (Action, error) {
switch strings.ToLower(uid) {
case ActionRevoke.uid:
return ActionRevoke, nil
case ActionTicket.uid:
return ActionTicket, nil
if action, ok := uidsActions[uid]; ok {
return action, nil
}
return ActionUndefined, fmt.Errorf("%w: %s", ErrActionUnknown, uid)
return ActionUnd, fmt.Errorf("%w: %s", ErrActionSyntax, uid)
}
// UnmarshalForm implements custom unmarshler for form values.
@ -70,5 +74,13 @@ func (a *Action) UnmarshalJSON(v []byte) error {
// String returns string representation of action.
func (a Action) String() string {
return a.uid
if a.uid != "" {
return a.uid
}
return common.Und
}
func (a Action) GoString() string {
return "domain.Action(" + a.String() + ")"
}

View File

@ -38,7 +38,7 @@ func TestAction_UnmarshalForm(t *testing.T) {
t.Parallel()
input := []byte("revoke")
result := domain.ActionUndefined
result := domain.ActionUnd
if err := result.UnmarshalForm(input); err != nil {
t.Fatalf("%+v", err)
@ -53,7 +53,7 @@ func TestAction_UnmarshalJSON(t *testing.T) {
t.Parallel()
input := []byte(`"revoke"`)
result := domain.ActionUndefined
result := domain.ActionUnd
if err := result.UnmarshalJSON(input); err != nil {
t.Fatalf("%+v", err)

View File

@ -11,6 +11,8 @@ import (
"hash"
"strconv"
"strings"
"source.toby3d.me/toby3d/auth/internal/common"
)
// CodeChallengeMethod represent a PKCE challenge method for validate verifier.
@ -18,41 +20,17 @@ import (
// NOTE(toby3d): Encapsulate enums in structs for extra compile-time safety:
// https://threedots.tech/post/safer-enums-in-go/#struct-based-enums
type CodeChallengeMethod struct {
hash hash.Hash
uid string
uid string
}
//nolint: gochecknoglobals // structs cannot be constants
var (
CodeChallengeMethodUndefined = CodeChallengeMethod{
uid: "",
hash: nil,
}
CodeChallengeMethodPLAIN = CodeChallengeMethod{
uid: "PLAIN",
hash: nil,
}
CodeChallengeMethodMD5 = CodeChallengeMethod{
uid: "MD5",
hash: md5.New(), //nolint: gosec // support old clients
}
CodeChallengeMethodS1 = CodeChallengeMethod{
uid: "S1",
hash: sha1.New(), //nolint: gosec // support old clients
}
CodeChallengeMethodS256 = CodeChallengeMethod{
uid: "S256",
hash: sha256.New(),
}
CodeChallengeMethodS512 = CodeChallengeMethod{
uid: "S512",
hash: sha512.New(),
}
CodeChallengeMethodUnd = CodeChallengeMethod{uid: ""} // "und"
CodeChallengeMethodPLAIN = CodeChallengeMethod{uid: "plain"} // "PLAIN"
CodeChallengeMethodMD5 = CodeChallengeMethod{uid: "md5"} // "MD5"
CodeChallengeMethodS1 = CodeChallengeMethod{uid: "s1"} // "S1"
CodeChallengeMethodS256 = CodeChallengeMethod{uid: "s256"} // "S256"
CodeChallengeMethodS512 = CodeChallengeMethod{uid: "s512"} // "S512"
)
var ErrCodeChallengeMethodUnknown error = NewError(
@ -63,22 +41,21 @@ var ErrCodeChallengeMethodUnknown error = NewError(
//nolint: gochecknoglobals // maps cannot be constants
var uidsMethods = map[string]CodeChallengeMethod{
CodeChallengeMethodMD5.uid: CodeChallengeMethodMD5,
CodeChallengeMethodPLAIN.uid: CodeChallengeMethodPLAIN,
CodeChallengeMethodS1.uid: CodeChallengeMethodS1,
CodeChallengeMethodS256.uid: CodeChallengeMethodS256,
CodeChallengeMethodS512.uid: CodeChallengeMethodS512,
CodeChallengeMethodUndefined.uid: CodeChallengeMethodUndefined,
CodeChallengeMethodMD5.uid: CodeChallengeMethodMD5,
CodeChallengeMethodPLAIN.uid: CodeChallengeMethodPLAIN,
CodeChallengeMethodS1.uid: CodeChallengeMethodS1,
CodeChallengeMethodS256.uid: CodeChallengeMethodS256,
CodeChallengeMethodS512.uid: CodeChallengeMethodS512,
}
// ParseCodeChallengeMethod parse string identifier of code challenge method
// into struct enum.
func ParseCodeChallengeMethod(uid string) (CodeChallengeMethod, error) {
if method, ok := uidsMethods[strings.ToUpper(uid)]; ok {
if method, ok := uidsMethods[strings.ToLower(uid)]; ok {
return method, nil
}
return CodeChallengeMethodUndefined, fmt.Errorf("%w: %s", ErrCodeChallengeMethodUnknown, uid)
return CodeChallengeMethodUnd, fmt.Errorf("%w: %s", ErrCodeChallengeMethodUnknown, uid)
}
// UnmarshalForm implements custom unmarshler for form values.
@ -113,26 +90,40 @@ func (ccm CodeChallengeMethod) MarshalJSON() ([]byte, error) {
// String returns string representation of code challenge method.
func (ccm CodeChallengeMethod) String() string {
return ccm.uid
if ccm.uid != "" {
return strings.ToUpper(ccm.uid)
}
return common.Und
}
func (ccm CodeChallengeMethod) GoString() string {
return "domain.CodeChallengeMethod(" + ccm.String() + ")"
}
// Validate checks for a match to the verifier with the hashed version of the
// challenge via the chosen method.
func (ccm CodeChallengeMethod) Validate(codeChallenge, verifier string) bool {
if ccm.uid == CodeChallengeMethodUndefined.uid {
return false
}
var h hash.Hash
if ccm.uid == CodeChallengeMethodPLAIN.uid {
switch ccm {
default:
return false
case CodeChallengeMethodPLAIN:
return codeChallenge == verifier
case CodeChallengeMethodMD5:
h = md5.New()
case CodeChallengeMethodS1:
h = sha1.New()
case CodeChallengeMethodS256:
h = sha256.New()
case CodeChallengeMethodS512:
h = sha512.New()
}
hash := ccm.hash
hash.Reset() // WARN(toby3d): even hash.New contains something.
if _, err := hash.Write([]byte(verifier)); err != nil {
if _, err := h.Write([]byte(verifier)); err != nil {
return false
}
return codeChallenge == base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
return codeChallenge == base64.RawURLEncoding.EncodeToString(h.Sum(nil))
}

View File

@ -25,11 +25,11 @@ func TestParseCodeChallengeMethod(t *testing.T) {
out domain.CodeChallengeMethod
expError bool
}{
{name: "invalid", in: "und", out: domain.CodeChallengeMethodUndefined, expError: true},
{name: "invalid", in: "und", out: domain.CodeChallengeMethodUnd, expError: true},
{name: "PLAIN", in: "plain", out: domain.CodeChallengeMethodPLAIN, expError: false},
{name: "MD5", in: "Md5", out: domain.CodeChallengeMethodMD5, expError: false},
{name: "S1", in: "S1", out: domain.CodeChallengeMethodS1, expError: false},
{name: "S256", in: "S256", out: domain.CodeChallengeMethodS256, expError: false},
{name: "S256", in: "s256", out: domain.CodeChallengeMethodS256, expError: false},
{name: "S512", in: "S512", out: domain.CodeChallengeMethodS512, expError: false},
} {
tc := tc
@ -57,7 +57,7 @@ func TestCodeChallengeMethod_UnmarshalForm(t *testing.T) {
t.Parallel()
input := []byte("S256")
result := domain.CodeChallengeMethodUndefined
result := domain.CodeChallengeMethodUnd
if err := result.UnmarshalForm(input); err != nil {
t.Fatalf("%+v", err)
@ -72,7 +72,7 @@ func TestCodeChallengeMethod_UnmarshalJSON(t *testing.T) {
t.Parallel()
input := []byte(`"S256"`)
result := domain.CodeChallengeMethodUndefined
result := domain.CodeChallengeMethodUnd
if err := result.UnmarshalJSON(input); err != nil {
t.Fatalf("%+v", err)
@ -131,7 +131,7 @@ func TestCodeChallengeMethod_Validate(t *testing.T) {
{name: "S1", in: domain.CodeChallengeMethodS1, hash: sha1.New(), expError: false},
{name: "S256", in: domain.CodeChallengeMethodS256, hash: sha256.New(), expError: false},
{name: "S512", in: domain.CodeChallengeMethodS512, hash: sha512.New(), expError: false},
{name: "undefined", in: domain.CodeChallengeMethodUndefined, hash: nil, expError: true},
{name: "Und", in: domain.CodeChallengeMethodUnd, hash: nil, expError: true},
} {
tc := tc
@ -141,7 +141,7 @@ func TestCodeChallengeMethod_Validate(t *testing.T) {
var codeChallenge string
switch tc.in {
case domain.CodeChallengeMethodUndefined, domain.CodeChallengeMethodPLAIN:
case domain.CodeChallengeMethodUnd, domain.CodeChallengeMethodPLAIN:
codeChallenge = verifier
default:
hash := tc.hash

View File

@ -79,3 +79,7 @@ func (e Email) String() string {
return e.user + "+" + e.subAddress + "@" + e.host
}
func (e Email) GoString() string {
return "domain.Email(" + e.String() + ")"
}

View File

@ -7,6 +7,8 @@ import (
http "github.com/valyala/fasthttp"
"golang.org/x/xerrors"
"source.toby3d.me/toby3d/auth/internal/common"
)
type (
@ -35,26 +37,19 @@ type (
// ErrorCode represent error code described in RFC 6749.
ErrorCode struct {
uid string
status int
uid string
}
)
var (
// ErrorCodeUndefined describes an unrecognized error code.
ErrorCodeUndefined = ErrorCode{
uid: "",
status: 0,
}
// ErrorCodeUnd describes an unrecognized error code.
ErrorCodeUnd = ErrorCode{uid: ""} // "und"
// ErrorCodeAccessDenied describes the access_denied error code.
//
// RFC 6749 section 4.1.2.1: The resource owner or authorization server
// denied the request.
ErrorCodeAccessDenied = ErrorCode{
uid: "access_denied",
status: 0, // TODO(toby3d)
}
ErrorCodeAccessDenied = ErrorCode{uid: "access_denied"} // "access_denied"
// ErrorCodeInvalidClient describes the invalid_client error code.
//
@ -70,10 +65,7 @@ var (
// HTTP 401 (Unauthorized) status code and include the
// "WWW-Authenticate" response header field matching the authentication
// scheme used by the client.
ErrorCodeInvalidClient = ErrorCode{
uid: "invalid_client",
status: 0, // TODO(toby3d)
}
ErrorCodeInvalidClient = ErrorCode{uid: "invalid_client"} // "invalid_client"
// ErrorCodeInvalidGrant describes the invalid_grant error code.
//
@ -81,10 +73,7 @@ var (
// authorization code, resource owner credentials) or refresh token is
// invalid, expired, revoked, does not match the redirection URI used in
// the authorization request, or was issued to another client.
ErrorCodeInvalidGrant = ErrorCode{
uid: "invalid_grant",
status: 0, // TODO(toby3d)
}
ErrorCodeInvalidGrant = ErrorCode{uid: "invalid_grant"} // "invalid_grant"
// ErrorCodeInvalidRequest describes the invalid_request error code.
//
@ -99,10 +88,7 @@ var (
// repeats a parameter, includes multiple credentials, utilizes more
// than one mechanism for authenticating the client, or is otherwise
// malformed.
ErrorCodeInvalidRequest = ErrorCode{
uid: "invalid_request",
status: http.StatusBadRequest,
}
ErrorCodeInvalidRequest = ErrorCode{uid: "invalid_request"} // "invalid_request"
// ErrorCodeInvalidScope describes the invalid_scope error code.
//
@ -111,10 +97,7 @@ var (
//
// RFC 6749 section 5.2: The requested scope is invalid, unknown,
// malformed, or exceeds the scope granted by the resource owner.
ErrorCodeInvalidScope = ErrorCode{
uid: "invalid_scope",
status: 0, // TODO(toby3d)
}
ErrorCodeInvalidScope = ErrorCode{uid: "invalid_scope"} // "invalid_scope"
// ErrorCodeServerError describes the server_error error code.
//
@ -122,10 +105,7 @@ var (
// unexpected condition that prevented it from fulfilling the request.
// (This error code is needed because a 500 Internal Server Error HTTP
// status code cannot be returned to the client via an HTTP redirect.)
ErrorCodeServerError = ErrorCode{
uid: "server_error",
status: 0, // TODO(toby3d)
}
ErrorCodeServerError = ErrorCode{uid: "server_error"} // "server_error"
// ErrorCodeTemporarilyUnavailable describes the temporarily_unavailable error code.
//
@ -134,10 +114,7 @@ var (
// maintenance of the server. (This error code is needed because a 503
// Service Unavailable HTTP status code cannot be returned to the client
// via an HTTP redirect.)
ErrorCodeTemporarilyUnavailable = ErrorCode{
uid: "temporarily_unavailable",
status: 0, // TODO(toby3d)
}
ErrorCodeTemporarilyUnavailable = ErrorCode{uid: "temporarily_unavailable"} // "temporarily_unavailable"
// ErrorCodeUnauthorizedClient describes the unauthorized_client error code.
//
@ -146,44 +123,29 @@ var (
//
// RFC 6749 section 5.2: The authenticated client is not authorized to
// use this authorization grant type.
ErrorCodeUnauthorizedClient = ErrorCode{
uid: "unauthorized_client",
status: 0, // TODO(toby3d)
}
ErrorCodeUnauthorizedClient = ErrorCode{uid: "unauthorized_client"} // "unauthorized_client"
// ErrorCodeUnsupportedGrantType describes the unsupported_grant_type error code.
//
// RFC 6749 section 5.2: The authorization grant type is not supported
// by the authorization server.
ErrorCodeUnsupportedGrantType = ErrorCode{
uid: "unsupported_grant_type",
status: 0, // TODO(toby3d)
}
ErrorCodeUnsupportedGrantType = ErrorCode{uid: "unsupported_grant_type"} // "unsupported_grant_type"
// ErrorCodeUnsupportedResponseType describes the unsupported_response_type error code.
//
// RFC 6749 section 4.1.2.1: The authorization server does not support
// obtaining an authorization code using this method.
ErrorCodeUnsupportedResponseType = ErrorCode{
uid: "unsupported_response_type",
status: 0, // TODO(toby3d)
}
ErrorCodeUnsupportedResponseType = ErrorCode{uid: "unsupported_response_type"} // "unsupported_response_type"
// ErrorCodeInvalidToken describes the invalid_token error code.
//
// IndieAuth: The access token provided is expired, revoked, or invalid.
ErrorCodeInvalidToken = ErrorCode{
uid: "invalid_token",
status: http.StatusUnauthorized,
}
ErrorCodeInvalidToken = ErrorCode{uid: "invalid_token"} // "invalid_token"
// ErrorCodeInsufficientScope describes the insufficient_scope error code.
//
// IndieAuth: The request requires higher privileges than provided.
ErrorCodeInsufficientScope = ErrorCode{
uid: "insufficient_scope",
status: http.StatusForbidden,
}
ErrorCodeInsufficientScope = ErrorCode{uid: "insufficient_scope"} // "insufficient_scope"
)
var ErrErrorCodeUnknown error = NewError(ErrorCodeInvalidRequest, "unknown error code", "")
@ -206,7 +168,15 @@ var uidsErrorCodes = map[string]ErrorCode{
// String returns a string representation of the error code.
func (ec ErrorCode) String() string {
return ec.uid
if ec.uid != "" {
return ec.uid
}
return common.Und
}
func (ec ErrorCode) GoString() string {
return "domain.ErrorCode(" + ec.String() + ")"
}
// UnmarshalForm implements custom unmarshler for form values.
@ -278,10 +248,10 @@ func (e Error) SetReirectURI(uri *http.URI) {
// NewError creates a new Error with the stack pointing to the function call
// line number.
//
// If no code or ErrorCodeUndefined is provided, ErrorCodeAccessDenied will be
// If no code or ErrorCodeUnd is provided, ErrorCodeAccessDenied will be
// used instead.
func NewError(code ErrorCode, description, uri string, requestState ...string) *Error {
if code == ErrorCodeUndefined {
if code == ErrorCodeUnd {
code = ErrorCodeAccessDenied
}

View File

@ -16,7 +16,7 @@ func TestErrorCode_UnmarshalForm(t *testing.T) {
t.Parallel()
input := []byte("access_denied")
result := domain.ErrorCodeUndefined
result := domain.ErrorCodeUnd
if err := result.UnmarshalForm(input); err != nil {
t.Fatalf("%+v", err)

View File

@ -4,6 +4,8 @@ import (
"fmt"
"strconv"
"strings"
"source.toby3d.me/toby3d/auth/internal/common"
)
// GrantType represent fixed grant_type parameter.
@ -16,9 +18,9 @@ type GrantType struct {
//nolint: gochecknoglobals // structs cannot be constants
var (
GrantTypeUndefined = GrantType{uid: ""}
GrantTypeAuthorizationCode = GrantType{uid: "authorization_code"}
GrantTypeRefreshToken = GrantType{uid: "refresh_token"}
GrantTypeUnd = GrantType{uid: ""} // "und"
GrantTypeAuthorizationCode = GrantType{uid: "authorization_code"} // "authorization_code"
GrantTypeRefreshToken = GrantType{uid: "refresh_token"} // "refresh_token"
// TicketAuth extension.
GrantTypeTicket = GrantType{uid: "ticket"}
@ -43,7 +45,7 @@ func ParseGrantType(uid string) (GrantType, error) {
return grantType, nil
}
return GrantTypeUndefined, fmt.Errorf("%w: %s", ErrGrantTypeUnknown, uid)
return GrantTypeUnd, fmt.Errorf("%w: %s", ErrGrantTypeUnknown, uid)
}
// UnmarshalForm implements custom unmarshler for form values.
@ -81,5 +83,13 @@ func (gt GrantType) MarshalJSON() ([]byte, error) {
// String returns string representation of grant type.
func (gt GrantType) String() string {
return gt.uid
if gt.uid != "" {
return gt.uid
}
return common.Und
}
func (gt GrantType) GoString() string {
return "domain.GrantType(" + gt.String() + ")"
}

View File

@ -38,7 +38,7 @@ func TestGrantType_UnmarshalForm(t *testing.T) {
t.Parallel()
input := []byte("authorization_code")
result := domain.GrantTypeUndefined
result := domain.GrantTypeUnd
if err := result.UnmarshalForm(input); err != nil {
t.Fatalf("%+v", err)
@ -53,7 +53,7 @@ func TestGrantType_UnmarshalJSON(t *testing.T) {
t.Parallel()
input := []byte(`"authorization_code"`)
result := domain.GrantTypeUndefined
result := domain.GrantTypeUnd
if err := result.UnmarshalJSON(input); err != nil {
t.Fatalf("%+v", err)

View File

@ -180,9 +180,13 @@ func (m Me) URL() *url.URL {
// String returns string representation of me.
func (m Me) String() string {
if m.id == nil {
return ""
if m.id != nil {
return m.id.String()
}
return m.id.String()
return ""
}
func (m Me) GoString() string {
return "domain.Me(" + m.String() + ")"
}

View File

@ -4,6 +4,8 @@ import (
"fmt"
"strconv"
"strings"
"source.toby3d.me/toby3d/auth/internal/common"
)
// NOTE(toby3d): Encapsulate enums in structs for extra compile-time safety:
@ -14,18 +16,18 @@ type ResponseType struct {
//nolint: gochecknoglobals // structs cannot be constants
var (
ResponseTypeUndefined = ResponseType{uid: ""}
ResponseTypeUnd = ResponseType{uid: ""} // "und"
// Deprecated(toby3d): Only accept response_type=code requests, and for
// backwards-compatible support, treat response_type=id requests as
// response_type=code requests:
// https://aaronparecki.com/2020/12/03/1/indieauth-2020#response-type
ResponseTypeID = ResponseType{uid: "id"}
ResponseTypeID = ResponseType{uid: "id"} // "id"
// Indicates to the authorization server that an authorization code
// should be returned as the response:
// https://indieauth.net/source/#authorization-request-li-1
ResponseTypeCode = ResponseType{uid: "code"}
ResponseTypeCode = ResponseType{uid: "code"} // "code"
)
var ErrResponseTypeUnknown error = NewError(
@ -43,7 +45,7 @@ func ParseResponseType(uid string) (ResponseType, error) {
return ResponseTypeID, nil
}
return ResponseTypeUndefined, fmt.Errorf("%w: %s", ErrResponseTypeUnknown, uid)
return ResponseTypeUnd, fmt.Errorf("%w: %s", ErrResponseTypeUnknown, uid)
}
// UnmarshalForm implements custom unmarshler for form values.
@ -81,5 +83,13 @@ func (rt ResponseType) MarshalJSON() ([]byte, error) {
// String returns string representation of response type.
func (rt ResponseType) String() string {
return rt.uid
if rt.uid != "" {
return rt.uid
}
return common.Und
}
func (rt ResponseType) GoString() string {
return "domain.ResponseType(" + rt.String() + ")"
}

View File

@ -38,7 +38,7 @@ func TestResponseType_UnmarshalForm(t *testing.T) {
t.Parallel()
input := []byte("code")
result := domain.ResponseTypeUndefined
result := domain.ResponseTypeUnd
if err := result.UnmarshalForm(input); err != nil {
t.Fatalf("%+v", err)
@ -53,7 +53,7 @@ func TestResponseType_UnmarshalJSON(t *testing.T) {
t.Parallel()
input := []byte(`"code"`)
result := domain.ResponseTypeUndefined
result := domain.ResponseTypeUnd
if err := result.UnmarshalJSON(input); err != nil {
t.Fatalf("%+v", err)

View File

@ -4,6 +4,8 @@ import (
"fmt"
"strconv"
"strings"
"source.toby3d.me/toby3d/auth/internal/common"
)
type (
@ -23,28 +25,28 @@ var ErrScopeUnknown error = NewError(ErrorCodeInvalidRequest, "unknown scope", "
//nolint: gochecknoglobals // structs cannot be constants
var (
ScopeUndefined = Scope{uid: ""}
ScopeUnd = Scope{uid: ""} // "und"
// https://indieweb.org/scope#Micropub_Scopes
ScopeCreate = Scope{uid: "create"}
ScopeDelete = Scope{uid: "delete"}
ScopeDraft = Scope{uid: "draft"}
ScopeMedia = Scope{uid: "media"}
ScopeUndelete = Scope{uid: "undelete"}
ScopeUpdate = Scope{uid: "update"}
ScopeCreate = Scope{uid: "create"} // "create"
ScopeDelete = Scope{uid: "delete"} // "delete"
ScopeDraft = Scope{uid: "draft"} // "draft"
ScopeMedia = Scope{uid: "media"} // "media"
ScopeUndelete = Scope{uid: "undelete"} // "undelete"
ScopeUpdate = Scope{uid: "update"} // "update"
// https://indieweb.org/scope#Microsub_Scopes
ScopeBlock = Scope{uid: "block"}
ScopeChannels = Scope{uid: "channels"}
ScopeFollow = Scope{uid: "follow"}
ScopeMute = Scope{uid: "mute"}
ScopeRead = Scope{uid: "read"}
ScopeBlock = Scope{uid: "block"} // "block"
ScopeChannels = Scope{uid: "channels"} // "channels"
ScopeFollow = Scope{uid: "follow"} // "follow"
ScopeMute = Scope{uid: "mute"} // "mute"
ScopeRead = Scope{uid: "read"} // "read"
// This scope requests access to the user's default profile information
// which include the following properties: name, photo, url.
//
// NOTE(toby3d): https://indieauth.net/source/#profile-information
ScopeProfile = Scope{uid: "profile"}
ScopeProfile = Scope{uid: "profile"} // "profile"
// This scope requests access to the user's email address in the
// following property: email.
@ -54,7 +56,7 @@ var (
// and must be requested along with the profile scope if desired.
//
// NOTE(toby3d): https://indieauth.net/source/#profile-information
ScopeEmail = Scope{uid: "email"}
ScopeEmail = Scope{uid: "email"} // "email"
)
//nolint: gochecknoglobals // maps cannot be constants
@ -80,7 +82,7 @@ func ParseScope(uid string) (Scope, error) {
return scope, nil
}
return ScopeUndefined, fmt.Errorf("%w: %s", ErrScopeUnknown, uid)
return ScopeUnd, fmt.Errorf("%w: %s", ErrScopeUnknown, uid)
}
func (s Scope) MarshalJSON() ([]byte, error) {
@ -89,7 +91,15 @@ func (s Scope) MarshalJSON() ([]byte, error) {
// String returns string representation of scope.
func (s Scope) String() string {
return s.uid
if s.uid != "" {
return s.uid
}
return common.Und
}
func (s Scope) GoString() string {
return "domain.Scope(" + s.String() + ")"
}
// UnmarshalForm implements custom unmarshler for form values.
@ -166,7 +176,7 @@ func (s Scopes) String() string {
// IsEmpty returns true if the set does not contain valid scope.
func (s Scopes) IsEmpty() bool {
for i := range s {
if s[i] == ScopeUndefined {
if s[i] == ScopeUnd {
continue
}

View File

@ -137,7 +137,7 @@ func TestScopes_String(t *testing.T) {
func TestScopes_IsEmpty(t *testing.T) {
t.Parallel()
scopes := domain.Scopes{domain.ScopeUndefined}
scopes := domain.Scopes{domain.ScopeUnd}
if result := scopes.IsEmpty(); !result {
t.Errorf("IsEmpty() = %t, want %t", result, true)
}

View File

@ -58,7 +58,7 @@ func (uc *tokenUseCase) Exchange(ctx context.Context, opts token.ExchangeOptions
return nil, nil, token.ErrMismatchRedirectURI
}
if session.CodeChallenge != "" && session.CodeChallengeMethod != domain.CodeChallengeMethodUndefined &&
if session.CodeChallenge != "" && session.CodeChallengeMethod != domain.CodeChallengeMethodUnd &&
!session.CodeChallengeMethod.Validate(session.CodeChallenge, opts.CodeVerifier) {
return nil, nil, token.ErrMismatchPKCE
}