Skip to content
Open
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
30 changes: 30 additions & 0 deletions internal/ent/schema/validator/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package validator

import (
"errors"
"fmt"
)

// ErrInvalidIPAddr is an error raised when provided IP Address is invalid
var ErrInvalidIPAddr = errors.New("ip Address is invalid")

// InvalidIPAddrError returns Error Invalid IP Address
func InvalidIPAddrError(ip string) error {
return fmt.Errorf("%w: %s", ErrInvalidIPAddr, ip)
}

// ErrInvalidIPPref is an error raised when provided IP Block Prefix is invalid
var ErrInvalidIPPref = errors.New("ip block prefix is invalid")

// InvalidIPPrefError returns Error Invalid IP Block Prefix
func InvalidIPPrefError(prefix string) error {
return fmt.Errorf("%w: %s", ErrInvalidIPPref, prefix)
}

// ErrIPAddrOutsideBlock is an error raised when provided IP Address is not part of the IP Block
var ErrIPAddrOutsideBlock = errors.New("ip address is invalid for IP Block Prefix")

// IPAddrOutsideBlockError returns Error IP Address doesn't belong to the IP Block
func IPAddrOutsideBlockError(block string, ip string) error {
return fmt.Errorf("%w: ip address: %s, ip block %s", ErrIPAddrOutsideBlock, ip, block)
}
35 changes: 20 additions & 15 deletions internal/ent/schema/validator/validate.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package validator

import (
"errors"
"fmt"
"net"

"net/netip"

"github.com/3th1nk/cidr"
)

// IPAddr returns error if IP address is NOT valid
Expand All @@ -16,14 +17,6 @@ func IPAddr(ip string) error {
return InvalidIPAddrError(ip)
}

// ErrInvalidIPAddr is an error raised when provided IP Address is invalid
var ErrInvalidIPAddr = errors.New("provided IP Address is invalid")

// InvalidIPAddrError returns Error Invalid IP Address
func InvalidIPAddrError(ip string) error {
return fmt.Errorf("error %w: %s", ErrInvalidIPAddr, ip)
}

// IPBlockPref returns error if IP Block Prefix is NOT valid
func IPBlockPref(prefix string) error {
_, err := netip.ParsePrefix(prefix)
Expand All @@ -34,10 +27,22 @@ func IPBlockPref(prefix string) error {
return nil
}

// ErrInvalidIPPref is an error raised when provided IP Block Prefix is invalid
var ErrInvalidIPPref = errors.New("provided IP Block Prefix is invalid")
// PartOfBlock returns error if IP address is NOT part of the block given block's prefix
func PartOfBlock(ipBlockPref string, ipAdrr string) error {
c, _ := cidr.Parse(ipBlockPref)
belongsToBlock := false

c.Each(func(ip string) bool {
if ip == ipAdrr {
belongsToBlock = true
}

return true
})

if belongsToBlock {
return nil
}

// InvalidIPPrefError returns Error Invalid IP Block Prefix
func InvalidIPPrefError(prefix string) error {
return fmt.Errorf("error %w: %s", ErrInvalidIPPref, prefix)
return IPAddrOutsideBlockError(ipBlockPref, ipAdrr)
}
55 changes: 55 additions & 0 deletions internal/ent/schema/validator/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package validator

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestPartOfBlock(t *testing.T) {
type args struct {
ipBl string
ipAdrr string
}

tests := []struct {
name string
args args
wantErr bool
}{
{

name: "happy path",
args: args{
ipBl: "192.168.1.0/28",
ipAdrr: "192.168.1.13"},
wantErr: false,
},
{
name: "outside block",
args: args{
ipBl: "192.168.1.0/28",
ipAdrr: "192.168.1.25"},
wantErr: true,
},
{
name: "far from block",
args: args{
ipBl: "108.1.80.128/30",
ipAdrr: "192.168.10.12"},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := PartOfBlock(tt.args.ipBl, tt.args.ipAdrr)
if tt.wantErr {
assert.Error(t, err)
assert.ErrorContainsf(t, err, tt.args.ipAdrr, tt.args.ipBl)
} else {
assert.Nil(t, err)
}
})
}
}
14 changes: 14 additions & 0 deletions internal/graphapi/ipaddress.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 64 additions & 2 deletions internal/graphapi/ipaddress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ func Test_IPAddress_Lifecycle(t *testing.T) {
ctx = context.WithValue(ctx, permissions.CheckerCtxKey, permissions.DefaultAllowChecker)

ipbt := (&IPBlockTypeBuilder{}).MustNew(ctx)
ipb := (&IPBlockBuilder{IPBlockTypeID: ipbt.ID}).MustNew(ctx)
ipb := (&IPBlockBuilder{IPBlockTypeID: ipbt.ID, Prefix: "192.168.1.0/28"}).MustNew(ctx)

t.Run("Create", func(t *testing.T) {
ipa, err := client.CreateIPAddress(ctx, testclient.CreateIPAddressInput{
IP: gofakeit.IPv4Address(),
IP: "192.168.1.13",
NodeID: gidx.MustNewID(nodePrefix),
NodeOwnerID: gidx.MustNewID(ownerPrefix),
Reserved: newBool(true),
Expand Down Expand Up @@ -163,3 +163,65 @@ func Test_IPAddressable(t *testing.T) {
require.NoError(t, err)
assert.Len(t, addrs.Entities[0].IPAddresses, 0)
}

func Test_IPAddress_PartOfBlock_Succeess(t *testing.T) {
client := graphTestClient()
ctx := context.Background()

// Permit request
ctx = context.WithValue(ctx, permissions.CheckerCtxKey, permissions.DefaultAllowChecker)

ipbt := (&IPBlockTypeBuilder{}).MustNew(ctx)
ipb := (&IPBlockBuilder{IPBlockTypeID: ipbt.ID, Prefix: "192.168.1.0/28"}).MustNew(ctx)

t.Run("Create", func(t *testing.T) {
ipa, err := client.CreateIPAddress(ctx, testclient.CreateIPAddressInput{
IP: "192.168.1.13",
NodeID: gidx.MustNewID(nodePrefix),
NodeOwnerID: gidx.MustNewID(ownerPrefix),
Reserved: newBool(true),
IPBlockID: ipb.ID,
})

require.NoError(t, err)
require.NotNil(t, ipa)
})
}

func Test_IPAddress_PartOfBlock_Failure(t *testing.T) {
client := graphTestClient()
ctx := context.Background()

// Permit request
ctx = context.WithValue(ctx, permissions.CheckerCtxKey, permissions.DefaultAllowChecker)

ipbt := (&IPBlockTypeBuilder{}).MustNew(ctx)
ipb := (&IPBlockBuilder{IPBlockTypeID: ipbt.ID, Prefix: "192.168.1.0/28"}).MustNew(ctx)
ipb2 := (&IPBlockBuilder{IPBlockTypeID: ipbt.ID, Prefix: "108.1.80.128/30"}).MustNew(ctx)

t.Run("Create", func(t *testing.T) {
ipa, err := client.CreateIPAddress(ctx, testclient.CreateIPAddressInput{
IP: "192.168.1.25",
NodeID: gidx.MustNewID(nodePrefix),
NodeOwnerID: gidx.MustNewID(ownerPrefix),
Reserved: newBool(true),
IPBlockID: ipb.ID,
})

require.Error(t, err)
require.Nil(t, ipa)
})

t.Run("Create", func(t *testing.T) {
ipa, err := client.CreateIPAddress(ctx, testclient.CreateIPAddressInput{
IP: "192.168.10.12",
NodeID: gidx.MustNewID(nodePrefix),
NodeOwnerID: gidx.MustNewID(ownerPrefix),
Reserved: newBool(true),
IPBlockID: ipb2.ID,
})

require.Error(t, err)
require.Nil(t, ipa)
})
}