Skip to content

Commit

Permalink
feat: support setup api (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
amalucelli authored Mar 8, 2023
1 parent 7bddae1 commit ce6a0d6
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 0 deletions.
8 changes: 8 additions & 0 deletions nextdns/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ type Client struct {
// Services for the Rewrites.
Rewrites RewritesService

// Services for the Setup.
Setup SetupService
SetupLinkedIP SetupLinkedIPService

// Debug mode for the HTTP requests.
Debug bool
}
Expand Down Expand Up @@ -161,6 +165,10 @@ func New(opts ...ClientOption) (*Client, error) {
// Initialize the services for the Rewrites.
c.Rewrites = NewRewritesService(c)

// Initialize the services for the Setup.
c.Setup = NewSetupService(c)
c.SetupLinkedIP = NewSetupLinkedIPService(c)

return c, nil
}

Expand Down
67 changes: 67 additions & 0 deletions nextdns/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package nextdns

import (
"context"
"fmt"
"net/http"

"github.com/pkg/errors"
)

// setupAPIPath is the HTTP path for the setup API.
const setupAPIPath = "setup"

// Setup represents the setup settings.
type Setup struct {
Ipv4 []string `json:"ipv4"`
Ipv6 []string `json:"ipv6"`
LinkedIP *SetupLinkedIP `json:"linkedIp"`
Dnscrypt string `json:"dnscrypt"`
}

// GetSetupRequest encapsulates the request for getting the setup settings.
type GetSetupRequest struct {
ProfileID string
}

// SetupService is an interface for communicating with the NextDNS setup API endpoint.
type SetupService interface {
Get(context.Context, *GetSetupRequest) (*Setup, error)
}

// setupResponse represents the setup settings response.
type setupResponse struct {
Setup *Setup `json:"data"`
}

// setupService represents the NextDNS setup service.
type setupService struct {
client *Client
}

var _ SetupService = &setupService{}

// NewSetupService returns a new NextDNS setup service.
// nolint: revive
func NewSetupService(client *Client) *setupService {
return &setupService{
client: client,
}
}

// Get returns the setup settings of a profile.
func (s *setupService) Get(ctx context.Context, request *GetSetupRequest) (*Setup, error) {
path := fmt.Sprintf("%s/%s", profileAPIPath(request.ProfileID), setupAPIPath)
req, err := s.client.newRequest(http.MethodGet, path, nil)
if err != nil {
return nil, errors.Wrap(err, "error creating request to get the setup settings")
}

response := setupResponse{}
err = s.client.do(ctx, req, &response)
if err != nil {
return nil, errors.Wrap(err, "error making a request to get the setup settings")
}

return response.Setup, nil
}
89 changes: 89 additions & 0 deletions nextdns/setup_linkedip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package nextdns

import (
"context"
"fmt"
"net/http"

"github.com/pkg/errors"
)

// setupLinkedIPAPIPath is the HTTP path for the setup linked IP API.
const setupLinkedIPAPIPath = "setup/linkedip"

type SetupLinkedIP struct {
Servers []string `json:"servers"`
IP string `json:"ip"`
Ddns string `json:"ddns"`
UpdateToken string `json:"updateToken"`
}

// GetSetupLinkedIPRequest encapsulates the request for getting the setup linked ip settings of a profile.
type GetSetupLinkedIPRequest struct {
ProfileID string
}

// UpdateSetupLinkedIPRequest encapsulates the request for updating the setup linked ip of a profile.
type UpdateSetupLinkedIPRequest struct {
ProfileID string
SetupLinkedIP *SetupLinkedIP
}

// SetupLinkedIPService is an interface for communicating with the NextDNS setup linked ip API endpoint.
type SetupLinkedIPService interface {
Get(context.Context, *GetSetupLinkedIPRequest) (*SetupLinkedIP, error)
Update(context.Context, *UpdateSetupLinkedIPRequest) error
}

// SetupLinkedIPResponse represents the setup linked ip response.
type setupLinkedIPResponse struct {
SetupLinkedIP *SetupLinkedIP `json:"data"`
}

// SetupLinkedIPService represents the NextDNS setup linked ip service.
type setupLinkedIPService struct {
client *Client
}

var _ SetupLinkedIPService = &setupLinkedIPService{}

// NewSetupLinkedIPService returns a new NextDNS setup linked ip service.
// nolint: revive
func NewSetupLinkedIPService(client *Client) *setupLinkedIPService {
return &setupLinkedIPService{
client: client,
}
}

// Get returns the setup linked ip of a profile.
func (s *setupLinkedIPService) Get(ctx context.Context, request *GetSetupLinkedIPRequest) (*SetupLinkedIP, error) {
path := fmt.Sprintf("%s/%s", profileAPIPath(request.ProfileID), setupLinkedIPAPIPath)
req, err := s.client.newRequest(http.MethodGet, path, nil)
if err != nil {
return nil, errors.Wrap(err, "error creating request to get the setup linked ip settings")
}

response := setupLinkedIPResponse{}
err = s.client.do(ctx, req, &response)
if err != nil {
return nil, errors.Wrap(err, "error making a request to get the setup linked ip settings")
}

return response.SetupLinkedIP, nil
}

// Update updates the setup linked ip of a profile.
func (s *setupLinkedIPService) Update(ctx context.Context, request *UpdateSetupLinkedIPRequest) error {
path := fmt.Sprintf("%s/%s", profileAPIPath(request.ProfileID), setupLinkedIPAPIPath)
req, err := s.client.newRequest(http.MethodPatch, path, request.SetupLinkedIP)
if err != nil {
return errors.Wrap(err, "error creating request to update the setup linked ip settings")
}

err = s.client.do(ctx, req, nil)
if err != nil {
return errors.Wrap(err, "error making a request to update the setup linked ip settings")
}

return nil
}
77 changes: 77 additions & 0 deletions nextdns/setup_linkedip_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package nextdns

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"github.com/matryer/is"
)

func TestSetupLinkedIpGet(t *testing.T) {
c := is.New(t)

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
out := `
{
"data": {
"servers": [
"1.1.1.1",
"2.2.2.2"
],
"ip": "1.2.3.4",
"ddns": null,
"updateToken": "fobar"
}
}`
_, err := w.Write([]byte(out))
c.NoErr(err)
}))

client, err := New(WithBaseURL(ts.URL))
c.NoErr(err)

ctx := context.Background()

get, err := client.SetupLinkedIP.Get(ctx, &GetSetupLinkedIPRequest{
ProfileID: "abc123",
})
want := &SetupLinkedIP{
Servers: []string{
"1.1.1.1",
"2.2.2.2",
},
IP: "1.2.3.4",
Ddns: "",
UpdateToken: "fobar",
}

c.NoErr(err)
c.Equal(get, want)
}

func TestSetupLinkedIpUpdate(t *testing.T) {
c := is.New(t)

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
_, err := w.Write([]byte(""))
c.NoErr(err)
}))

client, err := New(WithBaseURL(ts.URL), WithDebug())
c.NoErr(err)

ctx := context.Background()
request := &UpdateSetupLinkedIPRequest{
ProfileID: "abc123",
SetupLinkedIP: &SetupLinkedIP{
Ddns: "foobar.no-ip.org",
},
}
err = client.SetupLinkedIP.Update(ctx, request)

c.NoErr(err)
}
73 changes: 73 additions & 0 deletions nextdns/setup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package nextdns

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"github.com/matryer/is"
)

func TestSetupGet(t *testing.T) {
c := is.New(t)

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
out := `
{
"data": {
"ipv4": [
"1.2.3.4"
],
"ipv6": [
"2a07:a8c0::ab:c123",
"2a07:a8c1::ab:c123"
],
"linkedIp": {
"servers": [
"1.1.1.1",
"2.2.2.2"
],
"ip": "1.2.3.4",
"ddns": null,
"updateToken": "fobar"
},
"dnscrypt": "sdns://foobar"
}
}`
_, err := w.Write([]byte(out))
c.NoErr(err)
}))

client, err := New(WithBaseURL(ts.URL))
c.NoErr(err)

ctx := context.Background()

get, err := client.Setup.Get(ctx, &GetSetupRequest{
ProfileID: "abc123",
})
want := &Setup{
Ipv4: []string{
"1.2.3.4",
},
Ipv6: []string{
"2a07:a8c0::ab:c123",
"2a07:a8c1::ab:c123",
},
LinkedIP: &SetupLinkedIP{
Servers: []string{
"1.1.1.1",
"2.2.2.2",
},
IP: "1.2.3.4",
Ddns: "",
UpdateToken: "fobar",
},
Dnscrypt: "sdns://foobar",
}

c.NoErr(err)
c.Equal(get, want)
}

0 comments on commit ce6a0d6

Please sign in to comment.