🎨 Format code of domains
This commit is contained in:
parent
257759e47c
commit
4127eca29d
|
@ -76,7 +76,7 @@ func (c *Client) ValidateRedirectURI(redirectURI *URL) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *Client) GetName() string {
|
||||
func (c Client) GetName() string {
|
||||
if len(c.Name) < 1 {
|
||||
return ""
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ func (c *Client) GetName() string {
|
|||
return c.Name[0]
|
||||
}
|
||||
|
||||
func (c *Client) GetURL() *URL {
|
||||
func (c Client) GetURL() *URL {
|
||||
if len(c.URL) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ func (c *Client) GetURL() *URL {
|
|||
return c.URL[0]
|
||||
}
|
||||
|
||||
func (c *Client) GetLogo() *URL {
|
||||
func (c Client) GetLogo() *URL {
|
||||
if len(c.Logo) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ var (
|
|||
localhostIPv6 = netaddr.MustParseIP("::1")
|
||||
)
|
||||
|
||||
//nolint: funlen
|
||||
func NewClientID(raw string) (*ClientID, error) {
|
||||
clientID := http.AcquireURI()
|
||||
if err := clientID.Parse(nil, []byte(raw)); err != nil {
|
||||
|
@ -146,16 +147,20 @@ func (cid *ClientID) UnmarshalJSON(v []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cid ClientID) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.Quote(cid.String())), nil
|
||||
}
|
||||
|
||||
// URI returns copy of parsed *fasthttp.URI.
|
||||
// This copy MUST be released via fasthttp.ReleaseURI.
|
||||
func (cid *ClientID) URI() *http.URI {
|
||||
func (cid ClientID) URI() *http.URI {
|
||||
u := http.AcquireURI()
|
||||
cid.clientID.CopyTo(u)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
func (cid *ClientID) URL() *url.URL {
|
||||
func (cid ClientID) URL() *url.URL {
|
||||
return &url.URL{
|
||||
Scheme: string(cid.clientID.Scheme()),
|
||||
Host: string(cid.clientID.Host()),
|
||||
|
@ -167,6 +172,6 @@ func (cid *ClientID) URL() *url.URL {
|
|||
}
|
||||
|
||||
// String returns string representation of client ID.
|
||||
func (cid *ClientID) String() string {
|
||||
func (cid ClientID) String() string {
|
||||
return cid.clientID.String()
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ type (
|
|||
|
||||
ConfigJWT struct {
|
||||
Expiry time.Duration `yaml:"expiry"` // 1h
|
||||
Secret interface{} `yaml:"secret"`
|
||||
Secret string `yaml:"secret"`
|
||||
Algorithm string `yaml:"algorithm"` // HS256
|
||||
NonceLength int `yaml:"nonceLength"` // 22
|
||||
}
|
||||
|
@ -64,23 +64,6 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
// GetAddress return host:port address.
|
||||
func (cs *ConfigServer) GetAddress() string {
|
||||
return net.JoinHostPort(cs.Host, cs.Port)
|
||||
}
|
||||
|
||||
// GetRootURL returns generated from template RootURL.
|
||||
func (cs *ConfigServer) GetRootURL() string {
|
||||
return fasttemplate.ExecuteString(cs.RootURL, `{{`, `}}`, map[string]interface{}{
|
||||
"domain": cs.Domain,
|
||||
"host": cs.Host,
|
||||
"port": cs.Port,
|
||||
"protocol": cs.Protocol,
|
||||
"staticRootPath": cs.StaticRootPath,
|
||||
"staticUrlPrefix": cs.StaticURLPrefix,
|
||||
})
|
||||
}
|
||||
|
||||
// TestConfig returns a valid *viper.Viper with the generated test data filled in.
|
||||
func TestConfig(tb testing.TB) *Config {
|
||||
tb.Helper()
|
||||
|
@ -111,7 +94,7 @@ func TestConfig(tb testing.TB) *Config {
|
|||
JWT: ConfigJWT{
|
||||
Expiry: time.Hour,
|
||||
NonceLength: 22,
|
||||
Secret: []byte("hackme"),
|
||||
Secret: "hackme",
|
||||
Algorithm: "HS256",
|
||||
},
|
||||
IndieAuth: ConfigIndieAuth{
|
||||
|
@ -123,3 +106,20 @@ func TestConfig(tb testing.TB) *Config {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetAddress return host:port address.
|
||||
func (cs ConfigServer) GetAddress() string {
|
||||
return net.JoinHostPort(cs.Host, cs.Port)
|
||||
}
|
||||
|
||||
// GetRootURL returns generated from template RootURL.
|
||||
func (cs ConfigServer) GetRootURL() string {
|
||||
return fasttemplate.ExecuteString(cs.RootURL, `{{`, `}}`, map[string]interface{}{
|
||||
"domain": cs.Domain,
|
||||
"host": cs.Host,
|
||||
"port": cs.Port,
|
||||
"protocol": cs.Protocol,
|
||||
"staticRootPath": cs.StaticRootPath,
|
||||
"staticUrlPrefix": cs.StaticURLPrefix,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ type Me struct {
|
|||
me *http.URI
|
||||
}
|
||||
|
||||
//nolint: funlen
|
||||
func NewMe(raw string) (*Me, error) {
|
||||
me := http.AcquireURI()
|
||||
if err := me.Parse(nil, []byte(raw)); err != nil {
|
||||
|
@ -137,9 +138,13 @@ func (m *Me) UnmarshalJSON(v []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m Me) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.Quote(m.String())), nil
|
||||
}
|
||||
|
||||
// URI returns copy of parsed Me in *fasthttp.URI representation.
|
||||
// This copy MUST be released via fasthttp.ReleaseURI.
|
||||
func (m *Me) URI() *http.URI {
|
||||
func (m Me) URI() *http.URI {
|
||||
if m.me == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -151,7 +156,7 @@ func (m *Me) URI() *http.URI {
|
|||
}
|
||||
|
||||
// URL returns copy of parsed Me in *url.URL representation.
|
||||
func (m *Me) URL() *url.URL {
|
||||
func (m Me) URL() *url.URL {
|
||||
if m.me == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -167,7 +172,7 @@ func (m *Me) URL() *url.URL {
|
|||
}
|
||||
|
||||
// String returns string representation of Me.
|
||||
func (m *Me) String() string {
|
||||
func (m Me) String() string {
|
||||
if m.me == nil {
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -15,24 +15,18 @@ type ResponseType struct {
|
|||
|
||||
//nolint: gochecknoglobals // NOTE(toby3d): structs cannot be constants
|
||||
var (
|
||||
ResponseTypeUndefined ResponseType = ResponseType{
|
||||
slug: "",
|
||||
}
|
||||
ResponseTypeUndefined ResponseType = ResponseType{slug: ""}
|
||||
|
||||
// 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 = ResponseType{
|
||||
slug: "id",
|
||||
}
|
||||
ResponseTypeID ResponseType = ResponseType{slug: "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 = ResponseType{
|
||||
slug: "code",
|
||||
}
|
||||
ResponseTypeCode ResponseType = ResponseType{slug: "code"}
|
||||
)
|
||||
|
||||
var ErrResponseTypeUnknown = errors.New("unknown grant type")
|
||||
|
|
|
@ -42,9 +42,7 @@ var (
|
|||
// which include the following properties: name, `photo, url.
|
||||
//
|
||||
// NOTE(toby3d): https://indieauth.net/source/#profile-information
|
||||
ScopeProfile = Scope{
|
||||
slug: "profile",
|
||||
}
|
||||
ScopeProfile = Scope{slug: "profile"}
|
||||
|
||||
// This scope requests access to the user's email address in the
|
||||
// following property: email.
|
||||
|
@ -54,9 +52,7 @@ var (
|
|||
// and must be requested along with the profile scope if desired.
|
||||
//
|
||||
// NOTE(toby3d): https://indieauth.net/source/#profile-information
|
||||
ScopeEmail = Scope{
|
||||
slug: "email",
|
||||
}
|
||||
ScopeEmail = Scope{slug: "email"}
|
||||
)
|
||||
|
||||
//nolint: gochecknoglobals // NOTE(toby3d): maps cannot be constants
|
||||
|
@ -85,29 +81,19 @@ func ParseScope(slug string) (Scope, error) {
|
|||
}
|
||||
|
||||
// UnmarshalForm parses the value of the form key into the Scope domain.
|
||||
func (s *Scope) UnmarshalForm(v []byte) (err error) {
|
||||
scope, err := ParseScope(string(v))
|
||||
if err != nil {
|
||||
return fmt.Errorf("scope: %w", err)
|
||||
func (s *Scopes) UnmarshalForm(v []byte) error {
|
||||
scopes := make(Scopes, 0)
|
||||
|
||||
for _, rawScope := range strings.Fields(string(v)) {
|
||||
scope, err := ParseScope(rawScope)
|
||||
if err != nil {
|
||||
return fmt.Errorf("scopes: %w", err)
|
||||
}
|
||||
|
||||
*s = append(scopes, scope)
|
||||
}
|
||||
|
||||
*s = scope
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Scope) UnmarshalJSON(v []byte) error {
|
||||
src, err := strconv.Unquote(string(v))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scope, err := ParseScope(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("scope: %w", err)
|
||||
}
|
||||
|
||||
*s = scope
|
||||
*s = scopes
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,19 +6,47 @@ import (
|
|||
"github.com/goccy/go-json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
http "github.com/valyala/fasthttp"
|
||||
|
||||
"source.toby3d.me/toby3d/form"
|
||||
"source.toby3d.me/website/indieauth/internal/domain"
|
||||
)
|
||||
|
||||
func TestScopes_UnmarshalForm(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Set("scope", "read update delete")
|
||||
|
||||
result := struct {
|
||||
Scope domain.Scopes
|
||||
}{
|
||||
Scope: make(domain.Scopes, 0),
|
||||
}
|
||||
|
||||
require.NoError(t, form.Unmarshal(args, &result))
|
||||
assert.Equal(t, "read update delete", result.Scope.String())
|
||||
}
|
||||
|
||||
func TestScopes_UnmarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
result := &struct {
|
||||
Scope domain.Scopes `json:"scope"`
|
||||
}{}
|
||||
require.NoError(t, json.Unmarshal([]byte(`{"scope": "read update delete"}`), result))
|
||||
|
||||
for _, scope := range []domain.Scope{domain.ScopeRead, domain.ScopeUpdate, domain.ScopeDelete} {
|
||||
assert.Contains(t, result.Scope, scope)
|
||||
}
|
||||
result := make(map[string]domain.Scopes)
|
||||
require.NoError(t, json.Unmarshal([]byte(`{"scope":"read update delete"}`), &result))
|
||||
assert.Equal(t, domain.Scopes{domain.ScopeRead, domain.ScopeUpdate, domain.ScopeDelete}, result["scope"])
|
||||
}
|
||||
|
||||
func TestScopes_MarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
result, err := json.Marshal(map[string]domain.Scopes{
|
||||
"scope": {
|
||||
domain.ScopeEmail,
|
||||
domain.ScopeProfile,
|
||||
domain.ScopeRead,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, `{"scope":"email profile read"}`, string(result))
|
||||
}
|
||||
|
|
|
@ -28,14 +28,14 @@ type (
|
|||
Issuer *ClientID
|
||||
NonceLength int
|
||||
Scope Scopes
|
||||
Secret interface{}
|
||||
Secret []byte
|
||||
Subject *Me
|
||||
}
|
||||
)
|
||||
|
||||
var DefaultNewTokenOptions = NewTokenOptions{
|
||||
NonceLength: 32,
|
||||
Algorithm: "HS256",
|
||||
NonceLength: 32,
|
||||
}
|
||||
|
||||
func NewToken(opts NewTokenOptions) (*Token, error) {
|
||||
|
@ -83,7 +83,7 @@ func NewToken(opts NewTokenOptions) (*Token, error) {
|
|||
func TestToken(tb testing.TB) *Token {
|
||||
tb.Helper()
|
||||
|
||||
nonce, err := random.String(42)
|
||||
nonce, err := random.String(22)
|
||||
require.NoError(tb, err)
|
||||
|
||||
t := jwt.New()
|
||||
|
@ -98,7 +98,7 @@ func TestToken(tb testing.TB) *Token {
|
|||
|
||||
// NOTE(toby3d): required
|
||||
t.Set(jwt.IssuerKey, cid.String())
|
||||
t.Set(jwt.SubjectKey, me.me.String())
|
||||
t.Set(jwt.SubjectKey, me.String())
|
||||
// TODO(toby3d): t.Set(jwt.AudienceKey, nil)
|
||||
t.Set(jwt.ExpirationKey, now.Add(1*time.Hour))
|
||||
t.Set(jwt.NotBeforeKey, now.Add(-1*time.Hour))
|
||||
|
@ -121,7 +121,7 @@ func TestToken(tb testing.TB) *Token {
|
|||
}
|
||||
|
||||
// SetAuthHeader writes an Access Token to the request header.
|
||||
func (t *Token) SetAuthHeader(r *http.Request) {
|
||||
func (t Token) SetAuthHeader(r *http.Request) {
|
||||
if t.AccessToken == "" {
|
||||
return
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ func (t *Token) SetAuthHeader(r *http.Request) {
|
|||
r.Header.Set(http.HeaderAuthorization, t.String())
|
||||
}
|
||||
|
||||
func (t *Token) String() string {
|
||||
func (t Token) String() string {
|
||||
if t.AccessToken == "" {
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ func (u *URL) UnmarshalJSON(v []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *URL) URL() *url.URL {
|
||||
func (u URL) URL() *url.URL {
|
||||
if u.URI == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue