1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-06-05 01:20:21 +02:00

types/node: make user pointer

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2025-05-21 17:22:30 +02:00
parent d3005b1d4f
commit 19add15927
No known key found for this signature in database
6 changed files with 550 additions and 381 deletions

View File

@ -17,6 +17,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/ptr"
"tailscale.com/util/must" "tailscale.com/util/must"
) )
@ -144,13 +145,15 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"), IPv6: ap("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
}, },
peers: types.Nodes{ peers: types.Nodes{
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"), IPv6: ap("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
}, },
}, },
want: []tailcfg.FilterRule{}, want: []tailcfg.FilterRule{},
@ -191,7 +194,8 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{ RoutableIPs: []netip.Prefix{
netip.MustParsePrefix("10.33.0.0/16"), netip.MustParsePrefix("10.33.0.0/16"),
@ -202,7 +206,8 @@ func TestReduceFilterRules(t *testing.T) {
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
@ -281,19 +286,22 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
peers: types.Nodes{ peers: types.Nodes{
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
// "internal" exit node // "internal" exit node
&types.Node{ &types.Node{
IPv4: ap("100.64.0.100"), IPv4: ap("100.64.0.100"),
IPv6: ap("fd7a:115c:a1e0::100"), IPv6: ap("fd7a:115c:a1e0::100"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: tsaddr.ExitRoutes(), RoutableIPs: tsaddr.ExitRoutes(),
}, },
@ -342,7 +350,8 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.100"), IPv4: ap("100.64.0.100"),
IPv6: ap("fd7a:115c:a1e0::100"), IPv6: ap("fd7a:115c:a1e0::100"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: tsaddr.ExitRoutes(), RoutableIPs: tsaddr.ExitRoutes(),
}, },
@ -351,12 +360,14 @@ func TestReduceFilterRules(t *testing.T) {
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
&types.Node{ &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
@ -449,7 +460,8 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.100"), IPv4: ap("100.64.0.100"),
IPv6: ap("fd7a:115c:a1e0::100"), IPv6: ap("fd7a:115c:a1e0::100"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: tsaddr.ExitRoutes(), RoutableIPs: tsaddr.ExitRoutes(),
}, },
@ -458,12 +470,14 @@ func TestReduceFilterRules(t *testing.T) {
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
&types.Node{ &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
@ -559,7 +573,8 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.100"), IPv4: ap("100.64.0.100"),
IPv6: ap("fd7a:115c:a1e0::100"), IPv6: ap("fd7a:115c:a1e0::100"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/16"), netip.MustParsePrefix("16.0.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/16"), netip.MustParsePrefix("16.0.0.0/16")},
}, },
@ -568,12 +583,14 @@ func TestReduceFilterRules(t *testing.T) {
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
&types.Node{ &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
@ -647,7 +664,8 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.100"), IPv4: ap("100.64.0.100"),
IPv6: ap("fd7a:115c:a1e0::100"), IPv6: ap("fd7a:115c:a1e0::100"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/8"), netip.MustParsePrefix("16.0.0.0/8")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/8"), netip.MustParsePrefix("16.0.0.0/8")},
}, },
@ -656,12 +674,14 @@ func TestReduceFilterRules(t *testing.T) {
&types.Node{ &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
&types.Node{ &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
@ -727,17 +747,19 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.100"), IPv4: ap("100.64.0.100"),
IPv6: ap("fd7a:115c:a1e0::100"), IPv6: ap("fd7a:115c:a1e0::100"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/24")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/24")},
}, },
ForcedTags: []string{"tag:access-servers"}, Tags: []string{"tag:access-servers"},
}, },
peers: types.Nodes{ peers: types.Nodes{
&types.Node{ &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
@ -793,13 +815,15 @@ func TestReduceFilterRules(t *testing.T) {
node: &types.Node{ node: &types.Node{
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: users[3], User: &users[3],
UserID: &users[3].ID,
}, },
peers: types.Nodes{ peers: types.Nodes{
&types.Node{ &types.Node{
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{p("172.16.0.0/24"), p("10.10.11.0/24"), p("10.10.12.0/24")}, RoutableIPs: []netip.Prefix{p("172.16.0.0/24"), p("10.10.11.0/24"), p("10.10.12.0/24")},
}, },
@ -848,17 +872,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -872,19 +899,22 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
}, },
@ -895,17 +925,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -919,14 +952,16 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
}, },
@ -937,17 +972,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -961,14 +999,16 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
}, },
@ -979,17 +1019,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -1003,14 +1046,16 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, UserID: ptr.To(uint(2)),
User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
}, },
}, },
}, },
@ -1021,17 +1066,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -1045,19 +1093,22 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
}, },
@ -1068,17 +1119,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -1092,19 +1146,22 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
}, },
@ -1115,17 +1172,20 @@ func TestReduceNodes(t *testing.T) {
&types.Node{ &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "joe"}, User: &types.User{Name: "joe", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: types.User{Name: "mickael"}, User: &types.User{Name: "mickael", Model: gorm.Model{ID: 3}},
UserID: ptr.To(uint(3)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -1133,7 +1193,8 @@ func TestReduceNodes(t *testing.T) {
node: &types.Node{ // current nodes node: &types.Node{ // current nodes
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "marc"}, User: &types.User{Name: "marc", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: nil, want: nil,
@ -1151,28 +1212,32 @@ func TestReduceNodes(t *testing.T) {
Hostname: "ts-head-upcrmb", Hostname: "ts-head-upcrmb",
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
IPv6: ap("fd7a:115c:a1e0::3"), IPv6: ap("fd7a:115c:a1e0::3"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
Hostname: "ts-unstable-rlwpvr", Hostname: "ts-unstable-rlwpvr",
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
IPv6: ap("fd7a:115c:a1e0::4"), IPv6: ap("fd7a:115c:a1e0::4"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 3, ID: 3,
Hostname: "ts-head-8w6paa", Hostname: "ts-head-8w6paa",
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
&types.Node{ &types.Node{
ID: 4, ID: 4,
Hostname: "ts-unstable-lys2ib", Hostname: "ts-unstable-lys2ib",
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
IPv6: ap("fd7a:115c:a1e0::2"), IPv6: ap("fd7a:115c:a1e0::2"),
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
rules: []tailcfg.FilterRule{ // list of all ACLRules registered rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@ -1194,7 +1259,8 @@ func TestReduceNodes(t *testing.T) {
Hostname: "ts-head-8w6paa", Hostname: "ts-head-8w6paa",
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: types.Nodes{ want: types.Nodes{
@ -1203,14 +1269,16 @@ func TestReduceNodes(t *testing.T) {
Hostname: "ts-head-upcrmb", Hostname: "ts-head-upcrmb",
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
IPv6: ap("fd7a:115c:a1e0::3"), IPv6: ap("fd7a:115c:a1e0::3"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
&types.Node{ &types.Node{
ID: 2, ID: 2,
Hostname: "ts-unstable-rlwpvr", Hostname: "ts-unstable-rlwpvr",
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
IPv6: ap("fd7a:115c:a1e0::4"), IPv6: ap("fd7a:115c:a1e0::4"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
}, },
@ -1222,13 +1290,15 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "peer1", Hostname: "peer1",
User: types.User{Name: "mini"}, User: &types.User{Name: "mini", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 2, ID: 2,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
Hostname: "peer2", Hostname: "peer2",
User: types.User{Name: "peer2"}, User: &types.User{Name: "peer2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -1244,7 +1314,8 @@ func TestReduceNodes(t *testing.T) {
ID: 0, ID: 0,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "mini", Hostname: "mini",
User: types.User{Name: "mini"}, User: &types.User{Name: "mini", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
want: []*types.Node{ want: []*types.Node{
@ -1252,7 +1323,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
Hostname: "peer2", Hostname: "peer2",
User: types.User{Name: "peer2"}, User: &types.User{Name: "peer2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
}, },
@ -1264,19 +1336,22 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "user1-2", Hostname: "user1-2",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 0, ID: 0,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "user1-1", Hostname: "user1-1",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 3, ID: 3,
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
Hostname: "user2-2", Hostname: "user2-2",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -1313,7 +1388,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
Hostname: "user-2-1", Hostname: "user-2-1",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: []*types.Node{ want: []*types.Node{
@ -1321,19 +1397,22 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "user1-2", Hostname: "user1-2",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 0, ID: 0,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "user1-1", Hostname: "user1-1",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 3, ID: 3,
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
Hostname: "user2-2", Hostname: "user2-2",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
}, },
@ -1345,19 +1424,22 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "user1-2", Hostname: "user1-2",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 2, ID: 2,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
Hostname: "user-2-1", Hostname: "user-2-1",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
{ {
ID: 3, ID: 3,
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
Hostname: "user2-2", Hostname: "user2-2",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -1394,7 +1476,8 @@ func TestReduceNodes(t *testing.T) {
ID: 0, ID: 0,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "user1-1", Hostname: "user1-1",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
want: []*types.Node{ want: []*types.Node{
@ -1402,19 +1485,22 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "user1-2", Hostname: "user1-2",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 2, ID: 2,
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
Hostname: "user-2-1", Hostname: "user-2-1",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
{ {
ID: 3, ID: 3,
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
Hostname: "user2-2", Hostname: "user2-2",
User: types.User{Name: "user2"}, User: &types.User{Name: "user2", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
}, },
@ -1426,13 +1512,15 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "user1", Hostname: "user1",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
{ {
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
}, },
@ -1453,7 +1541,8 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "user1", Hostname: "user1",
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
}, },
want: []*types.Node{ want: []*types.Node{
@ -1461,7 +1550,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
}, },
@ -1477,7 +1567,8 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
}, },
@ -1487,7 +1578,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "node", Hostname: "node",
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -1504,7 +1596,8 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
}, },
@ -1516,7 +1609,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "node", Hostname: "node",
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
}, },
@ -1528,7 +1622,8 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
}, },
@ -1538,7 +1633,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "node", Hostname: "node",
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -1555,7 +1651,8 @@ func TestReduceNodes(t *testing.T) {
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
Hostname: "node", Hostname: "node",
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
}, },
want: []*types.Node{ want: []*types.Node{
@ -1563,7 +1660,8 @@ func TestReduceNodes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")}, RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.99.0.0/16")},
}, },
@ -1599,28 +1697,28 @@ func TestSSHPolicyRules(t *testing.T) {
nodeUser1 := types.Node{ nodeUser1 := types.Node{
Hostname: "user1-device", Hostname: "user1-device",
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
UserID: 1, User: &users[0],
User: users[0], UserID: ptr.To(users[0].ID),
} }
nodeUser2 := types.Node{ nodeUser2 := types.Node{
Hostname: "user2-device", Hostname: "user2-device",
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
UserID: 2, User: &users[1],
User: users[1], UserID: ptr.To(users[1].ID),
} }
taggedServer := types.Node{ taggedServer := types.Node{
Hostname: "tagged-server", Hostname: "tagged-server",
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
UserID: 3, User: &users[2],
User: users[2], UserID: ptr.To(users[2].ID),
ForcedTags: []string{"tag:server"}, Tags: []string{"tag:server"},
} }
taggedClient := types.Node{ taggedClient := types.Node{
Hostname: "tagged-client", Hostname: "tagged-client",
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
UserID: 2, User: &users[1],
User: users[1], UserID: ptr.To(users[1].ID),
ForcedTags: []string{"tag:client"}, Tags: []string{"tag:client"},
} }
tests := []struct { tests := []struct {
@ -1986,7 +2084,8 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/24"), netip.MustParsePrefix("10.0.0.0/24"),
@ -2014,7 +2113,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/24"), netip.MustParsePrefix("10.0.0.0/24"),
@ -2040,7 +2139,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/24"), netip.MustParsePrefix("10.0.0.0/24"),
@ -2068,7 +2167,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/24"), netip.MustParsePrefix("10.0.0.0/24"),
@ -2095,7 +2194,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/24"), netip.MustParsePrefix("10.0.0.0/24"),
@ -2120,7 +2219,8 @@ func TestReduceRoutes(t *testing.T) {
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
IPv6: ap("fd7a:115c:a1e0::1"), IPv6: ap("fd7a:115c:a1e0::1"),
User: types.User{Name: "user1"}, User: &types.User{Name: "user1", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/24"), netip.MustParsePrefix("10.0.0.0/24"),
@ -2153,7 +2253,8 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), // Node IP IPv4: ap("100.64.0.2"), // Node IP
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2185,7 +2286,8 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2212,7 +2314,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "node"}, User: &types.User{Name: "node"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2240,7 +2342,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: types.User{Name: "node"}, User: &types.User{Name: "node"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2278,7 +2380,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), // node with IP 100.64.0.2 IPv4: ap("100.64.0.2"), // node with IP 100.64.0.2
User: types.User{Name: "node"}, User: &types.User{Name: "node"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2313,7 +2415,8 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 1, ID: 1,
IPv4: ap("100.64.0.1"), // router with IP 100.64.0.1 IPv4: ap("100.64.0.1"), // router with IP 100.64.0.1
User: types.User{Name: "router"}, User: &types.User{Name: "router", Model: gorm.Model{ID: 1}},
UserID: ptr.To(uint(1)),
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2355,7 +2458,8 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), // node IPv4: ap("100.64.0.2"), // node
User: types.User{Name: "node"}, User: &types.User{Name: "node", Model: gorm.Model{ID: 2}},
UserID: ptr.To(uint(2)),
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),
@ -2389,7 +2493,7 @@ func TestReduceRoutes(t *testing.T) {
node: &types.Node{ node: &types.Node{
ID: 2, ID: 2,
IPv4: ap("100.64.0.2"), // node IPv4: ap("100.64.0.2"), // node
User: types.User{Name: "node"}, User: &types.User{Name: "node"},
}, },
routes: []netip.Prefix{ routes: []netip.Prefix{
netip.MustParsePrefix("10.10.10.0/24"), netip.MustParsePrefix("10.10.10.0/24"),

View File

@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gorm.io/gorm" "gorm.io/gorm"
"tailscale.com/types/ptr"
) )
func TestNodeCanApproveRoute(t *testing.T) { func TestNodeCanApproveRoute(t *testing.T) {
@ -24,34 +25,34 @@ func TestNodeCanApproveRoute(t *testing.T) {
ID: 1, ID: 1,
Hostname: "user1-device", Hostname: "user1-device",
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
UserID: 1, UserID: ptr.To(uint(1)),
User: users[0], User: &users[0],
} }
exitNode := types.Node{ exitNode := types.Node{
ID: 2, ID: 2,
Hostname: "user2-device", Hostname: "user2-device",
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
UserID: 2, UserID: ptr.To(uint(2)),
User: users[1], User: &users[1],
} }
taggedNode := types.Node{ taggedNode := types.Node{
ID: 3, ID: 3,
Hostname: "tagged-server", Hostname: "tagged-server",
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
UserID: 3, UserID: ptr.To(uint(3)),
User: users[2], User: &users[2],
ForcedTags: []string{"tag:router"}, Tags: []string{"tag:router"},
} }
multiTagNode := types.Node{ multiTagNode := types.Node{
ID: 4, ID: 4,
Hostname: "multi-tag-node", Hostname: "multi-tag-node",
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
UserID: 2, UserID: ptr.To(uint(2)),
User: users[1], User: &users[1],
ForcedTags: []string{"tag:router", "tag:server"}, Tags: []string{"tag:router", "tag:server"},
} }
tests := []struct { tests := []struct {

View File

@ -359,7 +359,8 @@ func TestParsing(t *testing.T) {
}, },
&types.Node{ &types.Node{
IPv4: ap("200.200.200.200"), IPv4: ap("200.200.200.200"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
Hostinfo: &tailcfg.Hostinfo{}, Hostinfo: &tailcfg.Hostinfo{},
}, },
}) })

View File

@ -1,9 +1,10 @@
package v2 package v2
import ( import (
"github.com/juanfont/headscale/hscontrol/policy/matcher"
"testing" "testing"
"github.com/juanfont/headscale/hscontrol/policy/matcher"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/juanfont/headscale/hscontrol/types" "github.com/juanfont/headscale/hscontrol/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -17,8 +18,8 @@ func node(name, ipv4, ipv6 string, user types.User, hostinfo *tailcfg.Hostinfo)
Hostname: name, Hostname: name,
IPv4: ap(ipv4), IPv4: ap(ipv4),
IPv6: ap(ipv6), IPv6: ap(ipv6),
User: user, User: &user,
UserID: user.ID, UserID: &user.ID,
Hostinfo: hostinfo, Hostinfo: hostinfo,
} }
} }

View File

@ -189,7 +189,7 @@ func (u Username) Resolve(_ *Policy, users types.Users, nodes types.Nodes) (*net
} }
for _, node := range nodes { for _, node := range nodes {
if node.IsTagged() { if !node.IsUserOwned() {
continue continue
} }
@ -515,7 +515,7 @@ func (ag AutoGroup) Resolve(p *Policy, users types.Users, nodes types.Nodes) (*n
for _, node := range nodes { for _, node := range nodes {
// Skip if node has forced tags // Skip if node has forced tags
if len(node.ForcedTags) != 0 { if len(node.Tags) != 0 {
continue continue
} }
@ -548,7 +548,7 @@ func (ag AutoGroup) Resolve(p *Policy, users types.Users, nodes types.Nodes) (*n
for _, node := range nodes { for _, node := range nodes {
// Include if node has forced tags // Include if node has forced tags
if len(node.ForcedTags) != 0 { if len(node.Tags) != 0 {
node.AppendToIPSet(&build) node.AppendToIPSet(&build)
continue continue
} }

View File

@ -6,12 +6,13 @@ import (
"strings" "strings"
"testing" "testing"
"time"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"github.com/juanfont/headscale/hscontrol/types" "github.com/juanfont/headscale/hscontrol/types"
"github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go4.org/netipx" "go4.org/netipx"
@ -1064,33 +1065,40 @@ func TestResolvePolicy(t *testing.T) {
nodes: types.Nodes{ nodes: types.Nodes{
// Not matching other user // Not matching other user
{ {
User: users["notme"], User: ptr.To(users["notme"]),
UserID: ptr.To(users["notme"].ID),
IPv4: ap("100.100.101.1"), IPv4: ap("100.100.101.1"),
}, },
// Not matching forced tags // Not matching tags, usernames are ignored if a node is tagged
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
ForcedTags: []string{"tag:anything"}, UserID: ptr.To(users["testuser"].ID),
Tags: []string{"tag:anything"},
IPv4: ap("100.100.101.2"), IPv4: ap("100.100.101.2"),
}, },
// not matchin pak tag // not matchin pak tag
// since 0.27.0, tags are only considered when
// set directly on the node, not via pak.
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
AuthKey: &types.PreAuthKey{ AuthKey: &types.PreAuthKey{
Tags: []string{"alsotagged"}, Tags: []string{"alsotagged"},
}, },
IPv4: ap("100.100.101.3"), IPv4: ap("100.100.101.3"),
}, },
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
IPv4: ap("100.100.101.103"), IPv4: ap("100.100.101.103"),
}, },
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
IPv4: ap("100.100.101.104"), IPv4: ap("100.100.101.104"),
}, },
}, },
want: []netip.Prefix{mp("100.100.101.103/32"), mp("100.100.101.104/32")}, want: []netip.Prefix{mp("100.100.101.3/32"), mp("100.100.101.103/32"), mp("100.100.101.104/32")},
}, },
{ {
name: "group", name: "group",
@ -1098,29 +1106,45 @@ func TestResolvePolicy(t *testing.T) {
nodes: types.Nodes{ nodes: types.Nodes{
// Not matching other user // Not matching other user
{ {
User: users["notme"], User: ptr.To(users["notme"]),
UserID: ptr.To(users["notme"].ID),
IPv4: ap("100.100.101.4"), IPv4: ap("100.100.101.4"),
}, },
// Not matching forced tags // Not matching forced tags
{ {
User: users["groupuser"], User: ptr.To(users["groupuser"]),
ForcedTags: []string{"tag:anything"}, UserID: ptr.To(users["groupuser"].ID),
Tags: []string{"tag:anything"},
IPv4: ap("100.100.101.5"), IPv4: ap("100.100.101.5"),
}, },
// not matchin pak tag // not matchin pak tag
// since 0.27.0, tags are only considered when
// set directly on the node, not via pak.
{ {
User: users["groupuser"], User: ptr.To(users["groupuser"]),
UserID: ptr.To(users["groupuser"].ID),
AuthKey: &types.PreAuthKey{ AuthKey: &types.PreAuthKey{
Tags: []string{"tag:alsotagged"}, Tags: []string{"tag:alsotagged"},
}, },
IPv4: ap("100.100.101.6"), IPv4: ap("100.100.101.6"),
}, },
{ {
User: users["groupuser"], User: ptr.To(users["groupuser"]),
UserID: ptr.To(users["groupuser"].ID),
IPv4: ap("100.100.101.203"), IPv4: ap("100.100.101.203"),
}, },
// not matchin username because tagged
// since 0.27.0, tags are only considered when
// set directly on the node, not via pak.
{ {
User: users["groupuser"], User: ptr.To(users["groupuser"]),
UserID: ptr.To(users["groupuser"].ID),
Tags: []string{"tag:taggg"},
IPv4: ap("100.100.101.209"),
},
{
User: ptr.To(users["groupuser1"]),
UserID: ptr.To(users["groupuser1"].ID),
IPv4: ap("100.100.101.204"), IPv4: ap("100.100.101.204"),
}, },
}, },
@ -1130,7 +1154,7 @@ func TestResolvePolicy(t *testing.T) {
"group:othergroup": Usernames{"notmetoo"}, "group:othergroup": Usernames{"notmetoo"},
}, },
}, },
want: []netip.Prefix{mp("100.100.101.203/32"), mp("100.100.101.204/32")}, want: []netip.Prefix{mp("100.100.101.6/32"), mp("100.100.101.203/32")},
}, },
{ {
name: "tag", name: "tag",
@ -1138,12 +1162,13 @@ func TestResolvePolicy(t *testing.T) {
nodes: types.Nodes{ nodes: types.Nodes{
// Not matching other user // Not matching other user
{ {
User: users["notme"], User: ptr.To(users["notme"]),
UserID: ptr.To(users["notme"].ID),
IPv4: ap("100.100.101.9"), IPv4: ap("100.100.101.9"),
}, },
// Not matching forced tags // Not matching forced tags
{ {
ForcedTags: []string{"tag:anything"}, Tags: []string{"tag:anything"},
IPv4: ap("100.100.101.10"), IPv4: ap("100.100.101.10"),
}, },
// not matchin pak tag // not matchin pak tag
@ -1153,12 +1178,21 @@ func TestResolvePolicy(t *testing.T) {
}, },
IPv4: ap("100.100.101.11"), IPv4: ap("100.100.101.11"),
}, },
// Not matching forced tags // matching forced tags
{ {
ForcedTags: []string{"tag:test"}, Tags: []string{"tag:test"},
IPv4: ap("100.100.101.234"), IPv4: ap("100.100.101.234"),
}, },
// matching tag with user (user is ignored)
{
User: ptr.To(users["notme"]),
UserID: ptr.To(users["notme"].ID),
Tags: []string{"tag:test"},
IPv4: ap("100.100.101.109"),
},
// not matchin pak tag // not matchin pak tag
// since 0.27.0, tags are only considered when
// set directly on the node, not via pak.
{ {
AuthKey: &types.PreAuthKey{ AuthKey: &types.PreAuthKey{
Tags: []string{"tag:test"}, Tags: []string{"tag:test"},
@ -1168,7 +1202,7 @@ func TestResolvePolicy(t *testing.T) {
}, },
// TODO(kradalby): tests handling TagOwners + hostinfo // TODO(kradalby): tests handling TagOwners + hostinfo
pol: &Policy{}, pol: &Policy{},
want: []netip.Prefix{mp("100.100.101.234/32"), mp("100.100.101.239/32")}, want: []netip.Prefix{mp("100.100.101.109/32"), mp("100.100.101.234/32")},
}, },
{ {
name: "empty-policy", name: "empty-policy",
@ -1191,11 +1225,13 @@ func TestResolvePolicy(t *testing.T) {
toResolve: ptr.To(Group("group:testgroup")), toResolve: ptr.To(Group("group:testgroup")),
nodes: types.Nodes{ nodes: types.Nodes{
{ {
User: users["groupuser1"], User: ptr.To(users["groupuser1"]),
UserID: ptr.To(users["groupuser1"].ID),
IPv4: ap("100.100.101.203"), IPv4: ap("100.100.101.203"),
}, },
{ {
User: users["groupuser2"], User: ptr.To(users["groupuser2"]),
UserID: ptr.To(users["groupuser2"].ID),
IPv4: ap("100.100.101.204"), IPv4: ap("100.100.101.204"),
}, },
}, },
@ -1216,7 +1252,8 @@ func TestResolvePolicy(t *testing.T) {
toResolve: ptr.To(Username("invaliduser@")), toResolve: ptr.To(Username("invaliduser@")),
nodes: types.Nodes{ nodes: types.Nodes{
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
IPv4: ap("100.100.101.103"), IPv4: ap("100.100.101.103"),
}, },
}, },
@ -1227,7 +1264,7 @@ func TestResolvePolicy(t *testing.T) {
toResolve: tp("tag:invalid"), toResolve: tp("tag:invalid"),
nodes: types.Nodes{ nodes: types.Nodes{
{ {
ForcedTags: []string{"tag:test"}, Tags: []string{"tag:test"},
IPv4: ap("100.100.101.234"), IPv4: ap("100.100.101.234"),
}, },
}, },
@ -1248,18 +1285,21 @@ func TestResolvePolicy(t *testing.T) {
nodes: types.Nodes{ nodes: types.Nodes{
// Node with no tags (should be included) // Node with no tags (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
IPv4: ap("100.100.101.1"), IPv4: ap("100.100.101.1"),
}, },
// Node with forced tags (should be excluded) // Node with forced tags (should be excluded)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
ForcedTags: []string{"tag:test"}, UserID: ptr.To(users["testuser"].ID),
Tags: []string{"tag:test"},
IPv4: ap("100.100.101.2"), IPv4: ap("100.100.101.2"),
}, },
// Node with allowed requested tag (should be excluded) // Node with allowed requested tag (should be excluded)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:test"}, RequestTags: []string{"tag:test"},
}, },
@ -1267,7 +1307,8 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with non-allowed requested tag (should be included) // Node with non-allowed requested tag (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:notallowed"}, RequestTags: []string{"tag:notallowed"},
}, },
@ -1275,7 +1316,8 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with multiple requested tags, one allowed (should be excluded) // Node with multiple requested tags, one allowed (should be excluded)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:test", "tag:notallowed"}, RequestTags: []string{"tag:test", "tag:notallowed"},
}, },
@ -1283,7 +1325,8 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with multiple requested tags, none allowed (should be included) // Node with multiple requested tags, none allowed (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:notallowed1", "tag:notallowed2"}, RequestTags: []string{"tag:notallowed1", "tag:notallowed2"},
}, },
@ -1307,18 +1350,21 @@ func TestResolvePolicy(t *testing.T) {
nodes: types.Nodes{ nodes: types.Nodes{
// Node with no tags (should be excluded) // Node with no tags (should be excluded)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
IPv4: ap("100.100.101.1"), IPv4: ap("100.100.101.1"),
}, },
// Node with forced tag (should be included) // Node with forced tag (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
ForcedTags: []string{"tag:test"}, UserID: ptr.To(users["testuser"].ID),
Tags: []string{"tag:test"},
IPv4: ap("100.100.101.2"), IPv4: ap("100.100.101.2"),
}, },
// Node with allowed requested tag (should be included) // Node with allowed requested tag (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:test"}, RequestTags: []string{"tag:test"},
}, },
@ -1326,7 +1372,8 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with non-allowed requested tag (should be excluded) // Node with non-allowed requested tag (should be excluded)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:notallowed"}, RequestTags: []string{"tag:notallowed"},
}, },
@ -1334,7 +1381,8 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with multiple requested tags, one allowed (should be included) // Node with multiple requested tags, one allowed (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:test", "tag:notallowed"}, RequestTags: []string{"tag:test", "tag:notallowed"},
}, },
@ -1342,7 +1390,8 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with multiple requested tags, none allowed (should be excluded) // Node with multiple requested tags, none allowed (should be excluded)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
UserID: ptr.To(users["testuser"].ID),
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:notallowed1", "tag:notallowed2"}, RequestTags: []string{"tag:notallowed1", "tag:notallowed2"},
}, },
@ -1350,8 +1399,9 @@ func TestResolvePolicy(t *testing.T) {
}, },
// Node with multiple forced tags (should be included) // Node with multiple forced tags (should be included)
{ {
User: users["testuser"], User: ptr.To(users["testuser"]),
ForcedTags: []string{"tag:test", "tag:other"}, UserID: ptr.To(users["testuser"].ID),
Tags: []string{"tag:test", "tag:other"},
IPv4: ap("100.100.101.7"), IPv4: ap("100.100.101.7"),
}, },
}, },
@ -1414,23 +1464,26 @@ func TestResolveAutoApprovers(t *testing.T) {
nodes := types.Nodes{ nodes := types.Nodes{
{ {
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
}, },
{ {
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
{ {
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
{ {
IPv4: ap("100.64.0.4"), IPv4: ap("100.64.0.4"),
ForcedTags: []string{"tag:testtag"}, Tags: []string{"tag:testtag"},
}, },
{ {
IPv4: ap("100.64.0.5"), IPv4: ap("100.64.0.5"),
ForcedTags: []string{"tag:exittest"}, Tags: []string{"tag:exittest"},
}, },
} }
@ -1604,15 +1657,18 @@ func TestNodeCanApproveRoute(t *testing.T) {
nodes := types.Nodes{ nodes := types.Nodes{
{ {
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
}, },
{ {
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
{ {
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
} }
@ -1737,15 +1793,18 @@ func TestResolveTagOwners(t *testing.T) {
nodes := types.Nodes{ nodes := types.Nodes{
{ {
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
}, },
{ {
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
{ {
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
} }
@ -1822,15 +1881,18 @@ func TestNodeCanHaveTag(t *testing.T) {
nodes := types.Nodes{ nodes := types.Nodes{
{ {
IPv4: ap("100.64.0.1"), IPv4: ap("100.64.0.1"),
User: users[0], User: &users[0],
UserID: &users[0].ID,
}, },
{ {
IPv4: ap("100.64.0.2"), IPv4: ap("100.64.0.2"),
User: users[1], User: &users[1],
UserID: &users[1].ID,
}, },
{ {
IPv4: ap("100.64.0.3"), IPv4: ap("100.64.0.3"),
User: users[2], User: &users[2],
UserID: &users[2].ID,
}, },
} }