Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/eynopv/lac/pkg/param"
"github.com/eynopv/lac/pkg/printer"
"github.com/eynopv/lac/pkg/request"
"github.com/eynopv/lac/pkg/request/authentication"
"github.com/eynopv/lac/pkg/utils"
"github.com/eynopv/lac/pkg/validators"
)
Expand All @@ -33,7 +34,7 @@ func runCommandFunction(
os.Exit(1)
}

auth, err := request.NewAuth(requestTemplate)
auth, err := authentication.NewAuth(requestTemplate)
if err != nil {
fmt.Println(err)
os.Exit(1)
Expand All @@ -47,7 +48,7 @@ func runRequest(
variables map[string]interface{},
headers map[string]string,
client *client.Client,
auth request.Auth,
auth authentication.Auth,
) {
resolvedHeaders := map[string]request.StringOrStringList{}
for key, value := range headers {
Expand Down
18 changes: 18 additions & 0 deletions docs/json-schemas/request.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@
"auth": {
"description": "Request authentication",
"oneOf": [
{
"type": "object",
"description": "API authentication",
"properties": {
"type": {
"const": "api"
},
"header": {
"type": "string",
"description": "Header for api authentication"
},
"key": {
"type": "string",
"description": "Key for api authentication"
}
},
"required": ["type", "header", "key"]
},
{
"type": "object",
"description": "Basic authentication",
Expand Down
2 changes: 2 additions & 0 deletions internal/errorsx/errorsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import "errors"

var ErrAuthUnknown = errors.New("unknown auth type")
var ErrAuthParse = errors.New("failed to parse auth")
var ErrApiAuthParse = errors.New("failed to parse api auth")
var ErrApiAuthInvalid = errors.New("header and key are required")
var ErrBasicAuthParse = errors.New("failed to parse basic auth")
var ErrBasicAuthInvalid = errors.New("username and password are required")
var ErrBearerAuthParse = errors.New("failed to parse bearer auth")
Expand Down
3 changes: 2 additions & 1 deletion pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/eynopv/lac/pkg/printer"
"github.com/eynopv/lac/pkg/request"
"github.com/eynopv/lac/pkg/request/authentication"
"github.com/eynopv/lac/pkg/result"
)

Expand All @@ -30,7 +31,7 @@ func NewClient(config *ClientConfig) *Client {
}
}

func (c *Client) Do(r *request.Request, auth request.Auth) (*result.Result, error) {
func (c *Client) Do(r *request.Request, auth authentication.Auth) (*result.Result, error) {
request, err := r.ToHttpRequest()
if err != nil {
return nil, err
Expand Down
128 changes: 0 additions & 128 deletions pkg/request/authentication.go

This file was deleted.

47 changes: 47 additions & 0 deletions pkg/request/authentication/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package authentication

import (
"encoding/json"
"fmt"
"net/http"

"github.com/eynopv/lac/internal/errorsx"
"github.com/eynopv/lac/pkg/request"
"gopkg.in/yaml.v3"
)

type ApiAuth struct {
Header string `json:"header" yaml:"header"`
Key string `json:"key" yaml:"key"`
}

func NewApiAuth(t *request.Template) (*ApiAuth, error) {
var wrapper struct {
Auth *ApiAuth `json:"auth" yaml:"auth"`
}

bs := []byte(*t)

err := json.Unmarshal(bs, &wrapper)
if err != nil {
err = yaml.Unmarshal(bs, &wrapper)
}

if err != nil {
return nil, fmt.Errorf("%w: %v", errorsx.ErrApiAuthParse, err)
}

if wrapper.Auth != nil && (wrapper.Auth.Header == "" || wrapper.Auth.Key == "") {
return nil, errorsx.ErrApiAuthInvalid
}

return wrapper.Auth, nil
}

func (a *ApiAuth) Apply(r *http.Request) {
r.Header.Set(a.Header, a.Key)
}

func (a *ApiAuth) GetType() AuthType {
return Api
}
82 changes: 82 additions & 0 deletions pkg/request/authentication/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package authentication

import (
"net/http"
"testing"

"github.com/eynopv/lac/internal/assert"
"github.com/eynopv/lac/pkg/request"
)

func TestNewApiAuth(t *testing.T) {
t.Run("yaml", func(t *testing.T) {
template := request.Template(`
auth:
header: x-api-key
key: helloworld
`)

auth, err := NewApiAuth(&template)

assert.NoError(t, err)
assert.NotNil(t, auth)
assert.Equal(t, auth.Header, "x-api-key")
assert.Equal(t, auth.Key, "helloworld")
})

t.Run("json", func(t *testing.T) {
template := request.Template(`
{
"auth": {
"header": "x-api-key",
"key": "helloworld"
}
}
`)

auth, err := NewApiAuth(&template)

assert.NoError(t, err)
assert.NotNil(t, auth)
assert.Equal(t, auth.Header, "x-api-key")
assert.Equal(t, auth.Key, "helloworld")
})

t.Run("invalid", func(t *testing.T) {
template := request.Template("this is invalid template")

auth, err := NewApiAuth(&template)

assert.Error(t, err)
assert.Nil(t, auth)
})

t.Run("template without auth", func(t *testing.T) {
template := request.Template(`
{
"hello": "world"
}
`)

auth, err := NewApiAuth(&template)

assert.NoError(t, err)
assert.True(t, auth == nil)
})
}

func TestApiAuthApply(t *testing.T) {
apiAuth := ApiAuth{
Header: "x-api-key",
Key: "helloworld",
}

request, err := http.NewRequest(http.MethodGet, "", nil)

assert.NotNil(t, request)
assert.NoError(t, err)

apiAuth.Apply(request)

assert.Equal(t, request.Header.Get("X-Api-Key"), "helloworld")
}
59 changes: 59 additions & 0 deletions pkg/request/authentication/authentication.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package authentication

import (
"encoding/json"
"fmt"
"net/http"

"gopkg.in/yaml.v3"

"github.com/eynopv/lac/internal/errorsx"
"github.com/eynopv/lac/pkg/request"
)

type AuthType string

const (
Api AuthType = "api"
Basic AuthType = "basic"
Bearer AuthType = "bearer"
)

type Auth interface {
Apply(r *http.Request)
GetType() AuthType
}

type AuthBase struct {
Type AuthType `json:"type" yaml:"type"`
}

func NewAuth(t *request.Template) (Auth, error) {
var wrapper struct {
Auth *AuthBase `json:"auth" yaml:"auth"`
}

bs := []byte(*t)

err := json.Unmarshal(bs, &wrapper)
if err != nil {
if err = yaml.Unmarshal(bs, &wrapper); err != nil {
return nil, fmt.Errorf("%w: %v", errorsx.ErrAuthParse, err)
}
}

if wrapper.Auth == nil {
return nil, nil
}

switch wrapper.Auth.Type {
case Api:
return NewApiAuth(t)
case Basic:
return NewBasicAuth(t)
case Bearer:
return NewBearerAuth(t)
default:
return nil, errorsx.ErrAuthUnknown
}
}
Loading