mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-09 18:21:32 +09:00
all: apply golangci-lint autofixes
Go 1.27 allows setting promoted fields of embedded structs directly in composite literals, so gorm.Model wrappers go away. Plus strings.Cut, errors.AsType, reflect.TypeAssert and one gofumpt nit.
This commit is contained in:
committed by
Kristoffer Dalby
parent
2b64b9fe3a
commit
2c76d5c5b7
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/danielgtaylor/huma/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -217,7 +216,7 @@ func listUsersFiltered(b Backend, in *listUsersInput) ([]types.User, error) {
|
||||
return b.State.ListAllUsers()
|
||||
}
|
||||
|
||||
return b.State.ListUsersWithFilter(&types.User{Model: gorm.Model{ID: uint(id)}})
|
||||
return b.State.ListUsersWithFilter(&types.User{ID: uint(id)})
|
||||
default:
|
||||
return b.State.ListAllUsers()
|
||||
}
|
||||
|
||||
@@ -415,8 +415,8 @@ func TestConstraints(t *testing.T) {
|
||||
name: "no-oidc-duplicate-username-and-id",
|
||||
run: func(t *testing.T, db *gorm.DB) { //nolint:thelper
|
||||
user := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: "user1",
|
||||
ID: 1,
|
||||
Name: "user1",
|
||||
}
|
||||
user.ProviderIdentifier = sql.NullString{String: "http://test.com/user1", Valid: true}
|
||||
|
||||
@@ -424,8 +424,8 @@ func TestConstraints(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
user = types.User{
|
||||
Model: gorm.Model{ID: 2},
|
||||
Name: "user1",
|
||||
ID: 2,
|
||||
Name: "user1",
|
||||
}
|
||||
user.ProviderIdentifier = sql.NullString{String: "http://test.com/user1", Valid: true}
|
||||
|
||||
@@ -437,8 +437,8 @@ func TestConstraints(t *testing.T) {
|
||||
name: "no-oidc-duplicate-id",
|
||||
run: func(t *testing.T, db *gorm.DB) { //nolint:thelper
|
||||
user := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: "user1",
|
||||
ID: 1,
|
||||
Name: "user1",
|
||||
}
|
||||
user.ProviderIdentifier = sql.NullString{String: "http://test.com/user1", Valid: true}
|
||||
|
||||
@@ -446,8 +446,8 @@ func TestConstraints(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
user = types.User{
|
||||
Model: gorm.Model{ID: 2},
|
||||
Name: "user1.1",
|
||||
ID: 2,
|
||||
Name: "user1.1",
|
||||
}
|
||||
user.ProviderIdentifier = sql.NullString{String: "http://test.com/user1", Valid: true}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect
|
||||
|
||||
ret := f.Call(args)
|
||||
if !ret[0].IsNil() {
|
||||
if err, ok := ret[0].Interface().(error); ok {
|
||||
if err, ok := reflect.TypeAssert[error](ret[0]); ok {
|
||||
return decodingError(field.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,7 @@ func TestKeyHandler_UnsupportedCapVerDoesNotLeakKey(t *testing.T) {
|
||||
// errorAsHTTPError is a small local helper that unwraps an [HTTPError]
|
||||
// from an error chain.
|
||||
func errorAsHTTPError(err error) (HTTPError, bool) {
|
||||
var h HTTPError
|
||||
if errors.As(err, &h) {
|
||||
if h, ok := errors.AsType[HTTPError](err); ok {
|
||||
return h, true
|
||||
}
|
||||
|
||||
|
||||
@@ -11,19 +11,18 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/views"
|
||||
)
|
||||
|
||||
func TestApproveRoutesWithPolicy_NeverRemovesApprovedRoutes(t *testing.T) {
|
||||
user1 := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: "testuser",
|
||||
ID: 1,
|
||||
Name: "testuser",
|
||||
}
|
||||
user2 := types.User{
|
||||
Model: gorm.Model{ID: 2},
|
||||
Name: "otheruser",
|
||||
ID: 2,
|
||||
Name: "otheruser",
|
||||
}
|
||||
users := []types.User{user1, user2}
|
||||
|
||||
@@ -293,8 +292,8 @@ func TestApproveRoutesWithPolicy_NilAndEmptyCases(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s-policy-index%d", tt.name, i), func(t *testing.T) {
|
||||
// Create test user
|
||||
user := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: "test",
|
||||
ID: 1,
|
||||
Name: "test",
|
||||
}
|
||||
users := []types.User{user}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/key"
|
||||
)
|
||||
@@ -156,8 +155,8 @@ func TestApproveRoutesWithPolicy_NeverRemovesRoutes(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s-policy-index%d", tt.name, i), func(t *testing.T) {
|
||||
// Create test user
|
||||
user := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: tt.nodeUser,
|
||||
ID: 1,
|
||||
Name: tt.nodeUser,
|
||||
}
|
||||
users := []types.User{user}
|
||||
|
||||
@@ -283,8 +282,8 @@ func TestApproveRoutesWithPolicy_EdgeCases(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s-policy-index%d", tt.name, i), func(t *testing.T) {
|
||||
// Create test user
|
||||
user := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: "test",
|
||||
ID: 1,
|
||||
Name: "test",
|
||||
}
|
||||
users := []types.User{user}
|
||||
|
||||
@@ -326,8 +325,8 @@ func TestApproveRoutesWithPolicy_EdgeCases(t *testing.T) {
|
||||
|
||||
func TestApproveRoutesWithPolicy_NilPolicyManagerCase(t *testing.T) {
|
||||
user := types.User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
Name: "test",
|
||||
ID: 1,
|
||||
Name: "test",
|
||||
}
|
||||
|
||||
userID := user.ID
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -1134,11 +1133,11 @@ func TestReduceNodesFromPolicy(t *testing.T) {
|
||||
|
||||
func TestSSHPolicyRules(t *testing.T) {
|
||||
users := []types.User{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user3", Model: gorm.Model{ID: 3}},
|
||||
{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 4}},
|
||||
{Name: "bob", Email: "bob@example.com", Model: gorm.Model{ID: 5}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
{Name: "user3", ID: 3},
|
||||
{Name: "alice", Email: "alice@example.com", ID: 4},
|
||||
{Name: "bob", Email: "bob@example.com", ID: 5},
|
||||
}
|
||||
|
||||
// Create standard node setups used across tests
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/util/must"
|
||||
@@ -108,11 +107,11 @@ func TestTheInternet(t *testing.T) {
|
||||
|
||||
func TestReduceFilterRules(t *testing.T) {
|
||||
users := types.Users{
|
||||
types.User{Model: gorm.Model{ID: 1}, Name: "mickael"},
|
||||
types.User{Model: gorm.Model{ID: 2}, Name: "user1"},
|
||||
types.User{Model: gorm.Model{ID: 3}, Name: "user2"},
|
||||
types.User{Model: gorm.Model{ID: 4}, Name: "user100"},
|
||||
types.User{Model: gorm.Model{ID: 5}, Name: "user3"},
|
||||
types.User{ID: 1, Name: "mickael"},
|
||||
types.User{ID: 2, Name: "user1"},
|
||||
types.User{ID: 3, Name: "user2"},
|
||||
types.User{ID: 4, Name: "user100"},
|
||||
types.User{ID: 5, Name: "user3"},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
|
||||
@@ -9,14 +9,13 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestNodeCanApproveRoute(t *testing.T) {
|
||||
users := []types.User{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user3", Model: gorm.Model{ID: 3}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
{Name: "user3", ID: 3},
|
||||
}
|
||||
|
||||
// Create standard node setups used across tests
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go4.org/netipx"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -29,7 +28,7 @@ func aliasWithPorts(alias Alias, ports ...tailcfg.PortRange) AliasWithPorts {
|
||||
|
||||
func TestParsing(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "testuser"},
|
||||
{ID: 1, Name: "testuser"},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -390,8 +389,8 @@ func TestParsing(t *testing.T) {
|
||||
|
||||
func TestCompileSSHPolicy_UserMapping(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
}
|
||||
|
||||
// Create test nodes - use tagged nodes as SSH destinations
|
||||
@@ -638,10 +637,10 @@ func TestCompileSSHPolicy_UserMapping(t *testing.T) {
|
||||
|
||||
func TestCompileSSHPolicy_LocalpartMapping(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 1}},
|
||||
{Name: "bob", Email: "bob@example.com", Model: gorm.Model{ID: 2}},
|
||||
{Name: "charlie", Email: "charlie@other.com", Model: gorm.Model{ID: 3}},
|
||||
{Name: "dave", Model: gorm.Model{ID: 4}}, // CLI user, no email
|
||||
{Name: "alice", Email: "alice@example.com", ID: 1},
|
||||
{Name: "bob", Email: "bob@example.com", ID: 2},
|
||||
{Name: "charlie", Email: "charlie@other.com", ID: 3},
|
||||
{Name: "dave", ID: 4}, // CLI user, no email
|
||||
}
|
||||
|
||||
nodeTaggedServer := types.Node{
|
||||
@@ -836,10 +835,10 @@ func TestCompileSSHPolicy_LocalpartMapping(t *testing.T) {
|
||||
{
|
||||
name: "localpart with special chars in email",
|
||||
users: types.Users{
|
||||
{Name: "dave+sshuser", Email: "dave+sshuser@example.com", Model: gorm.Model{ID: 10}},
|
||||
{Name: "dave+sshuser", Email: "dave+sshuser@example.com", ID: 10},
|
||||
},
|
||||
nodes: func() types.Nodes {
|
||||
specialUser := types.User{Name: "dave+sshuser", Email: "dave+sshuser@example.com", Model: gorm.Model{ID: 10}}
|
||||
specialUser := types.User{Name: "dave+sshuser", Email: "dave+sshuser@example.com", ID: 10}
|
||||
n := types.Node{
|
||||
Hostname: "special-device",
|
||||
IPv4: createAddr("100.64.0.10"),
|
||||
@@ -880,10 +879,10 @@ func TestCompileSSHPolicy_LocalpartMapping(t *testing.T) {
|
||||
{
|
||||
name: "localpart excludes CLI users without email",
|
||||
users: types.Users{
|
||||
{Name: "dave", Model: gorm.Model{ID: 4}},
|
||||
{Name: "dave", ID: 4},
|
||||
},
|
||||
nodes: func() types.Nodes {
|
||||
cliUser := types.User{Name: "dave", Model: gorm.Model{ID: 4}}
|
||||
cliUser := types.User{Name: "dave", ID: 4}
|
||||
n := types.Node{
|
||||
Hostname: "dave-cli-device",
|
||||
IPv4: createAddr("100.64.0.5"),
|
||||
@@ -1005,8 +1004,8 @@ func TestCompileSSHPolicy_LocalpartMapping(t *testing.T) {
|
||||
|
||||
func TestCompileSSHPolicy_CheckAction(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
}
|
||||
|
||||
// Use tagged nodes for SSH user mapping tests
|
||||
@@ -1077,8 +1076,8 @@ func TestCompileSSHPolicy_CheckAction(t *testing.T) {
|
||||
// the accept rule appears first in the policy definition.
|
||||
func TestCompileSSHPolicy_CheckBeforeAcceptOrdering(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
}
|
||||
|
||||
nodeTaggedServer := types.Node{
|
||||
@@ -1153,8 +1152,8 @@ func TestCompileSSHPolicy_CheckBeforeAcceptOrdering(t *testing.T) {
|
||||
func TestSSHIntegrationReproduction(t *testing.T) {
|
||||
// Create users matching the integration test
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
}
|
||||
|
||||
// Create simple nodes for testing
|
||||
@@ -1218,7 +1217,7 @@ func TestSSHIntegrationReproduction(t *testing.T) {
|
||||
// to JSON and that the sshUsers field is not empty.
|
||||
func TestSSHJSONSerialization(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user1", ID: 1},
|
||||
}
|
||||
|
||||
uid := uint(1)
|
||||
@@ -1278,8 +1277,8 @@ func TestSSHJSONSerialization(t *testing.T) {
|
||||
|
||||
func TestCompileFilterRulesForNodeWithAutogroupSelf(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1439,8 +1438,8 @@ func TestCompileFilterRulesForNodeWithAutogroupSelf(t *testing.T) {
|
||||
// It also verifies that tag-to-tag rules work correctly.
|
||||
func TestTagUserMutualExclusivity(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1541,8 +1540,8 @@ func TestTagUserMutualExclusivity(t *testing.T) {
|
||||
// are valid and should produce filter rules.
|
||||
func TestUserToTagCrossIdentityGrant(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1626,8 +1625,8 @@ func TestAutogroupTagged(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1778,8 +1777,8 @@ func TestAutogroupSelfInSourceIsRejected(t *testing.T) {
|
||||
// are allowed (and only if they match the target user).
|
||||
func TestAutogroupSelfWithSpecificUserSource(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1845,9 +1844,9 @@ func TestAutogroupSelfWithSpecificUserSource(t *testing.T) {
|
||||
// as the target are allowed.
|
||||
func TestAutogroupSelfWithGroupSource(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1914,8 +1913,8 @@ func createAddr(ip string) *netip.Addr {
|
||||
// with autogroup:self in destinations.
|
||||
func TestSSHWithAutogroupSelfInDestination(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -1996,8 +1995,8 @@ func TestSSHWithAutogroupSelfInDestination(t *testing.T) {
|
||||
// can SSH (and only if they match the target user).
|
||||
func TestSSHWithAutogroupSelfAndSpecificUser(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -2051,9 +2050,9 @@ func TestSSHWithAutogroupSelfAndSpecificUser(t *testing.T) {
|
||||
// TestSSHWithAutogroupSelfAndGroup verifies SSH with group sources and autogroup:self destinations.
|
||||
func TestSSHWithAutogroupSelfAndGroup(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -2112,7 +2111,7 @@ func TestSSHWithAutogroupSelfAndGroup(t *testing.T) {
|
||||
// are excluded from both sources and destinations when autogroup:self is used.
|
||||
func TestSSHWithAutogroupSelfExcludesTaggedDevices(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{ID: 1, Name: "user1"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -2173,8 +2172,8 @@ func TestSSHWithAutogroupSelfExcludesTaggedDevices(t *testing.T) {
|
||||
// autogroup:self filtering only applies to autogroup:self destinations, not others.
|
||||
func TestSSHWithAutogroupSelfAndMixedDestinations(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -2246,9 +2245,9 @@ func TestSSHWithAutogroupSelfAndMixedDestinations(t *testing.T) {
|
||||
// registered nodes.
|
||||
func TestAutogroupSelfWithNonExistentUserInGroup(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "superadmin"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "admin"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "direction"},
|
||||
{ID: 1, Name: "superadmin"},
|
||||
{ID: 2, Name: "admin"},
|
||||
{ID: 3, Name: "direction"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -2600,7 +2599,7 @@ func TestMergeFilterRules(t *testing.T) {
|
||||
|
||||
func TestCompileSSHPolicy_CheckPeriodVariants(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user1", ID: 1},
|
||||
}
|
||||
|
||||
node := types.Node{
|
||||
@@ -2755,8 +2754,8 @@ func TestIPSetToPrincipals(t *testing.T) {
|
||||
|
||||
func TestSSHCheckParams(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Name: "user1", Model: gorm.Model{ID: 1}},
|
||||
{Name: "user2", Model: gorm.Model{ID: 2}},
|
||||
{Name: "user1", ID: 1},
|
||||
{Name: "user2", ID: 2},
|
||||
}
|
||||
|
||||
nodeUser1 := types.Node{
|
||||
@@ -2944,14 +2943,14 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
{
|
||||
name: "no entries",
|
||||
entries: nil,
|
||||
users: types.Users{{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 1}}},
|
||||
users: types.Users{{Name: "alice", Email: "alice@example.com", ID: 1}},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "single match",
|
||||
entries: []SSHUser{"localpart:*@example.com"},
|
||||
users: types.Users{
|
||||
{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 1}},
|
||||
{Name: "alice", Email: "alice@example.com", ID: 1},
|
||||
},
|
||||
want: map[uint]string{1: "alice"},
|
||||
},
|
||||
@@ -2959,7 +2958,7 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
name: "domain mismatch",
|
||||
entries: []SSHUser{"localpart:*@other.com"},
|
||||
users: types.Users{
|
||||
{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 1}},
|
||||
{Name: "alice", Email: "alice@example.com", ID: 1},
|
||||
},
|
||||
want: map[uint]string{},
|
||||
},
|
||||
@@ -2967,7 +2966,7 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
name: "case insensitive domain",
|
||||
entries: []SSHUser{"localpart:*@EXAMPLE.COM"},
|
||||
users: types.Users{
|
||||
{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 1}},
|
||||
{Name: "alice", Email: "alice@example.com", ID: 1},
|
||||
},
|
||||
want: map[uint]string{1: "alice"},
|
||||
},
|
||||
@@ -2975,7 +2974,7 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
name: "user without email skipped",
|
||||
entries: []SSHUser{"localpart:*@example.com"},
|
||||
users: types.Users{
|
||||
{Name: "cli-user", Model: gorm.Model{ID: 1}},
|
||||
{Name: "cli-user", ID: 1},
|
||||
},
|
||||
want: map[uint]string{},
|
||||
},
|
||||
@@ -2986,9 +2985,9 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
"localpart:*@other.com",
|
||||
},
|
||||
users: types.Users{
|
||||
{Name: "alice", Email: "alice@example.com", Model: gorm.Model{ID: 1}},
|
||||
{Name: "bob", Email: "bob@other.com", Model: gorm.Model{ID: 2}},
|
||||
{Name: "charlie", Email: "charlie@nope.com", Model: gorm.Model{ID: 3}},
|
||||
{Name: "alice", Email: "alice@example.com", ID: 1},
|
||||
{Name: "bob", Email: "bob@other.com", ID: 2},
|
||||
{Name: "charlie", Email: "charlie@nope.com", ID: 3},
|
||||
},
|
||||
want: map[uint]string{1: "alice", 2: "bob"},
|
||||
},
|
||||
@@ -2996,7 +2995,7 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
name: "special chars in local part",
|
||||
entries: []SSHUser{"localpart:*@example.com"},
|
||||
users: types.Users{
|
||||
{Name: "d", Email: "dave+ssh@example.com", Model: gorm.Model{ID: 1}},
|
||||
{Name: "d", Email: "dave+ssh@example.com", ID: 1},
|
||||
},
|
||||
want: map[uint]string{1: "dave+ssh"},
|
||||
},
|
||||
@@ -3015,11 +3014,11 @@ func TestResolveLocalparts(t *testing.T) {
|
||||
func TestGroupSourcesByUser(t *testing.T) {
|
||||
alice := types.User{
|
||||
Name: "alice", Email: "alice@example.com",
|
||||
Model: gorm.Model{ID: 1},
|
||||
ID: 1,
|
||||
}
|
||||
bob := types.User{
|
||||
Name: "bob", Email: "bob@example.com",
|
||||
Model: gorm.Model{ID: 2},
|
||||
ID: 2,
|
||||
}
|
||||
|
||||
nodeAlice := types.Node{
|
||||
@@ -3481,7 +3480,7 @@ func TestFilterAllowAllFix(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "testuser"},
|
||||
{ID: 1, Name: "testuser"},
|
||||
}
|
||||
nodes := types.Nodes{
|
||||
&types.Node{
|
||||
@@ -3586,7 +3585,7 @@ func TestCompileViaGrant(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "testuser"},
|
||||
{ID: 1, Name: "testuser"},
|
||||
}
|
||||
|
||||
allPorts := []ProtocolPort{
|
||||
@@ -3882,8 +3881,8 @@ func TestCompileGrantWithAutogroupSelf_GrantPaths(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
}
|
||||
|
||||
node1 := &types.Node{
|
||||
@@ -4089,7 +4088,7 @@ func TestDestinationsToNetPortRange_AutogroupInternet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "testuser"},
|
||||
{ID: 1, Name: "testuser"},
|
||||
}
|
||||
nodes := types.Nodes{
|
||||
&types.Node{
|
||||
|
||||
@@ -148,7 +148,7 @@ func expectedExitPeerVisibility(
|
||||
var seen []string
|
||||
|
||||
for _, peer := range capture.Netmap.Peers {
|
||||
peerName := strings.Split(peer.Name(), ".")[0]
|
||||
peerName, _, _ := strings.Cut(peer.Name(), ".")
|
||||
|
||||
if !exitAdvertisers[peerName] {
|
||||
continue
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
@@ -25,8 +24,8 @@ func TestIssue3233ViaInternetExitVisibility(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: "alice@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "bob", Email: "bob@headscale.net"},
|
||||
{ID: 1, Name: "alice", Email: "alice@headscale.net"},
|
||||
{ID: 2, Name: "bob", Email: "bob@headscale.net"},
|
||||
}
|
||||
|
||||
exitRoutes := []netip.Prefix{tsaddr.AllIPv4(), tsaddr.AllIPv6()}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -27,7 +26,7 @@ func TestIssue3267ViaGrantBroaderDestination(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: issue3267AliceEmail}, //nolint:goconst
|
||||
{ID: 1, Name: "alice", Email: issue3267AliceEmail}, //nolint:goconst
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -19,7 +18,7 @@ import (
|
||||
// as not needing a recompute.
|
||||
func TestNodeNeedsPeerRecompute(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"},
|
||||
{ID: 1, Name: "user1", Email: "user1@headscale.net"},
|
||||
}
|
||||
|
||||
const allowAll = `{"acls":[{"action":"accept","src":["*"],"dst":["*:*"]}]}`
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -19,8 +18,8 @@ import (
|
||||
// resolution is exercised across both.
|
||||
func nodeAttrsTestUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: "alice@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "bob", Email: "bob@example.org"},
|
||||
{ID: 1, Name: "alice", Email: "alice@example.com"},
|
||||
{ID: 2, Name: "bob", Email: "bob@example.org"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// TestPolicyManagerConcurrentReads is the correctness guard for the #3346 fix:
|
||||
@@ -22,9 +21,9 @@ import (
|
||||
// the lazy caches are written.
|
||||
func TestPolicyManagerConcurrentReads(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@headscale.net"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3", Email: "user3@headscale.net"},
|
||||
{ID: 1, Name: "user1", Email: "user1@headscale.net"},
|
||||
{ID: 2, Name: "user2", Email: "user2@headscale.net"},
|
||||
{ID: 3, Name: "user3", Email: "user3@headscale.net"},
|
||||
}
|
||||
|
||||
policy := `{
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/puzpuzpuz/xsync/v4"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
@@ -28,8 +27,8 @@ func node(name, ipv4, ipv6 string, user types.User) *types.Node {
|
||||
|
||||
func TestPolicyManager(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "testuser", Email: "testuser@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "otheruser", Email: "otheruser@headscale.net"},
|
||||
{ID: 1, Name: "testuser", Email: "testuser@headscale.net"},
|
||||
{ID: 2, Name: "otheruser", Email: "otheruser@headscale.net"},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -87,9 +86,9 @@ func TestPolicyManager(t *testing.T) {
|
||||
|
||||
func TestInvalidateAutogroupSelfCache(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@headscale.net"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3", Email: "user3@headscale.net"},
|
||||
{ID: 1, Name: "user1", Email: "user1@headscale.net"},
|
||||
{ID: 2, Name: "user2", Email: "user2@headscale.net"},
|
||||
{ID: 3, Name: "user3", Email: "user3@headscale.net"},
|
||||
}
|
||||
|
||||
//nolint:goconst // test-specific inline policy for clarity
|
||||
@@ -237,8 +236,8 @@ func TestInvalidateAutogroupSelfCache(t *testing.T) {
|
||||
// owning user from UserID, not from the User view.
|
||||
func TestSetNodesAutogroupSelfUnhydratedUser(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@headscale.net"},
|
||||
{ID: 1, Name: "user1", Email: "user1@headscale.net"},
|
||||
{ID: 2, Name: "user2", Email: "user2@headscale.net"},
|
||||
}
|
||||
|
||||
policy := `{
|
||||
@@ -305,7 +304,7 @@ func TestSetNodesAutogroupSelfUnhydratedUser(t *testing.T) {
|
||||
// autogroup:self destination is active.
|
||||
func TestSSHCheckParamsUnhydratedUserNoPanic(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"},
|
||||
{ID: 1, Name: "user1", Email: "user1@headscale.net"},
|
||||
}
|
||||
|
||||
policy := `{
|
||||
@@ -523,8 +522,8 @@ func TestInvalidateGlobalPolicyCache(t *testing.T) {
|
||||
// 1. BuildPeerMap uses unreduced compiled rules for determining peer relationships
|
||||
// 2. FilterForNode returns reduced compiled rules for packet filters.
|
||||
func TestAutogroupSelfReducedVsUnreducedRules(t *testing.T) {
|
||||
user1 := types.User{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"}
|
||||
user2 := types.User{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@headscale.net"}
|
||||
user1 := types.User{ID: 1, Name: "user1", Email: "user1@headscale.net"}
|
||||
user2 := types.User{ID: 2, Name: "user2", Email: "user2@headscale.net"}
|
||||
users := types.Users{user1, user2}
|
||||
|
||||
// Create two nodes
|
||||
@@ -600,8 +599,8 @@ func TestAutogroupSelfReducedVsUnreducedRules(t *testing.T) {
|
||||
// This ensures that autogroup:self doesn't interfere with other ACL rules.
|
||||
func TestAutogroupSelfWithOtherRules(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "test-1", Email: "test-1@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "test-2", Email: "test-2@example.com"},
|
||||
{ID: 1, Name: "test-1", Email: "test-1@example.com"},
|
||||
{ID: 2, Name: "test-2", Email: "test-2@example.com"},
|
||||
}
|
||||
|
||||
// test-1 has a regular device
|
||||
@@ -681,8 +680,8 @@ func TestAutogroupSelfWithOtherRules(t *testing.T) {
|
||||
// leaving nodes with stale filter rules until reconnect.
|
||||
func TestAutogroupSelfPolicyUpdateTriggersMapResponse(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "test-1", Email: "test-1@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "test-2", Email: "test-2@example.com"},
|
||||
{ID: 1, Name: "test-1", Email: "test-1@example.com"},
|
||||
{ID: 2, Name: "test-2", Email: "test-2@example.com"},
|
||||
}
|
||||
|
||||
test1Node := &types.Node{
|
||||
@@ -765,8 +764,8 @@ func TestAutogroupSelfPolicyUpdateTriggersMapResponse(t *testing.T) {
|
||||
// https://github.com/juanfont/headscale/issues/2389
|
||||
func TestTagPropagationToPeerMap(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@headscale.net"},
|
||||
{ID: 1, Name: "user1", Email: "user1@headscale.net"},
|
||||
{ID: 2, Name: "user2", Email: "user2@headscale.net"},
|
||||
}
|
||||
|
||||
// Policy: user2 can access tag:web nodes
|
||||
@@ -893,8 +892,8 @@ func TestTagPropagationToPeerMap(t *testing.T) {
|
||||
// BOTH admin and tagged node should see each other as peers.
|
||||
func TestAutogroupSelfWithAdminOverride(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "admin", Email: "admin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user1", Email: "user1@example.com"},
|
||||
{ID: 1, Name: "admin", Email: "admin@example.com"},
|
||||
{ID: 2, Name: "user1", Email: "user1@example.com"},
|
||||
}
|
||||
|
||||
// Admin has a regular device
|
||||
@@ -976,8 +975,8 @@ func TestAutogroupSelfWithAdminOverride(t *testing.T) {
|
||||
// This is the same behavior as the global filter path.
|
||||
func TestAutogroupSelfSymmetricVisibility(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@example.com"},
|
||||
{ID: 1, Name: "user1", Email: "user1@example.com"},
|
||||
{ID: 2, Name: "user2", Email: "user2@example.com"},
|
||||
}
|
||||
|
||||
// user1 has device A
|
||||
@@ -1059,10 +1058,10 @@ func TestAutogroupSelfSymmetricVisibility(t *testing.T) {
|
||||
// - All tagged nodes should be visible to users who can access them.
|
||||
func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "superadmin", Email: "superadmin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "admin", Email: "admin@example.com"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "direction", Email: "direction@example.com"},
|
||||
{Model: gorm.Model{ID: 4}, Name: "tagowner", Email: "tagowner@example.com"},
|
||||
{ID: 1, Name: "superadmin", Email: "superadmin@example.com"},
|
||||
{ID: 2, Name: "admin", Email: "admin@example.com"},
|
||||
{ID: 3, Name: "direction", Email: "direction@example.com"},
|
||||
{ID: 4, Name: "tagowner", Email: "tagowner@example.com"},
|
||||
}
|
||||
|
||||
// Create nodes:
|
||||
@@ -1229,8 +1228,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) {
|
||||
// visible to nodes that can access them.
|
||||
func TestEmptyFilterNodesStillVisible(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "admin", Email: "admin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "tagowner", Email: "tagowner@example.com"},
|
||||
{ID: 1, Name: "admin", Email: "admin@example.com"},
|
||||
{ID: 2, Name: "tagowner", Email: "tagowner@example.com"},
|
||||
}
|
||||
|
||||
adminDevice := &types.Node{
|
||||
@@ -1297,8 +1296,8 @@ func TestEmptyFilterNodesStillVisible(t *testing.T) {
|
||||
// tagged nodes AND their own devices.
|
||||
func TestAutogroupSelfCombinedWithTags(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "admin", Email: "admin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "tagowner", Email: "tagowner@example.com"},
|
||||
{ID: 1, Name: "admin", Email: "admin@example.com"},
|
||||
{ID: 2, Name: "tagowner", Email: "tagowner@example.com"},
|
||||
}
|
||||
|
||||
// Admin has two devices
|
||||
@@ -1393,7 +1392,7 @@ func TestAutogroupSelfCombinedWithTags(t *testing.T) {
|
||||
// Expected: node1 should be able to reach node2 via group:admin -> *:* rule.
|
||||
func TestIssue2990SameUserTaggedDevice(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@"},
|
||||
{ID: 1, Name: "user1", Email: "user1@"},
|
||||
}
|
||||
|
||||
// node1: user device (not tagged), belongs to user1
|
||||
@@ -1493,8 +1492,8 @@ func TestViaRoutesForPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1", Email: "user1@"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2", Email: "user2@"},
|
||||
{ID: 1, Name: "user1", Email: "user1@"},
|
||||
{ID: 2, Name: "user2", Email: "user2@"},
|
||||
}
|
||||
|
||||
t.Run("self_returns_empty", func(t *testing.T) {
|
||||
@@ -2102,7 +2101,7 @@ func TestBuildPeerMap_AutogroupInternetMakesExitNodeVisible(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: "alice@headscale.net"},
|
||||
{ID: 1, Name: "alice", Email: "alice@headscale.net"},
|
||||
}
|
||||
|
||||
aliceNode := node("alice-laptop", "100.64.0.10", "fd7a:115c:a1e0::a", users[0])
|
||||
@@ -2141,8 +2140,8 @@ func TestBuildPeerMap_AutogroupInternetMakesExitNodeVisible(t *testing.T) {
|
||||
// Reproduction for #3160: ambiguous user@ used to silently drop rules.
|
||||
func TestNewPolicyManager_DuplicateUsername(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 2}, Name: "yala"},
|
||||
{Model: gorm.Model{ID: 7}, Name: "yala", Email: "yala@yala.yala"},
|
||||
{ID: 2, Name: "yala"},
|
||||
{ID: 7, Name: "yala", Email: "yala@yala.yala"},
|
||||
}
|
||||
|
||||
polB := []byte(`{
|
||||
@@ -2164,7 +2163,7 @@ func TestNewPolicyManager_DuplicateUsername(t *testing.T) {
|
||||
// Missing-user tokens stay tolerant per #2863; only multi-match blocks load.
|
||||
func TestNewPolicyManager_UnknownUsernameTolerant(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice"},
|
||||
{ID: 1, Name: "alice"},
|
||||
}
|
||||
|
||||
polB := []byte(`{
|
||||
@@ -2178,8 +2177,8 @@ func TestNewPolicyManager_UnknownUsernameTolerant(t *testing.T) {
|
||||
// Rejected SetPolicy must keep the previous policy intact.
|
||||
func TestSetPolicy_DuplicateUsername(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 2}, Name: "yala"},
|
||||
{Model: gorm.Model{ID: 7}, Name: "yala", Email: "yala@yala.yala"},
|
||||
{ID: 2, Name: "yala"},
|
||||
{ID: 7, Name: "yala", Email: "yala@yala.yala"},
|
||||
}
|
||||
|
||||
good := []byte(`{
|
||||
@@ -2223,9 +2222,9 @@ func TestValidateUserReferences_EmptyUsersTolerant(t *testing.T) {
|
||||
// One case per AST site so a dropped walk fails the matching subtest.
|
||||
func TestValidateUserReferences_AllSites(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "dup"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "dup"},
|
||||
{ID: 1, Name: "alice"},
|
||||
{ID: 2, Name: "dup"},
|
||||
{ID: 3, Name: "dup"},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -2317,8 +2316,8 @@ func TestValidateUserReferences_AllSites(t *testing.T) {
|
||||
// IP-level grant.
|
||||
func TestPeerRelayGrantMakesRelayVisible(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: "alice@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "tagowner", Email: "tagowner@headscale.net"},
|
||||
{ID: 1, Name: "alice", Email: "alice@headscale.net"},
|
||||
{ID: 2, Name: "tagowner", Email: "tagowner@headscale.net"},
|
||||
}
|
||||
|
||||
// Helper for tagged nodes belonging to the tag-owner user.
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -44,9 +43,9 @@ var knownPolicyTesterDivergences = map[string]string{} //nolint:gosec // strings
|
||||
// minimal one is enough to make the runner go.
|
||||
func policyTesterCompatUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "odin", Email: "odin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "thor", Email: "thor@example.org"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "freya", Email: "freya@example.com"},
|
||||
{ID: 1, Name: "odin", Email: "odin@example.com"},
|
||||
{ID: 2, Name: "thor", Email: "thor@example.org"},
|
||||
{ID: 3, Name: "freya", Email: "freya@example.com"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// sshTestUsers/sshTestNodes are reused across the table below to keep
|
||||
@@ -22,9 +21,9 @@ import (
|
||||
// - prod (alice-created tagged node) → tag:prod
|
||||
func sshTestUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: "alice@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "bob", Email: "bob@headscale.net"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "thor", Email: "thor@example.org"},
|
||||
{ID: 1, Name: "alice", Email: "alice@headscale.net"},
|
||||
{ID: 2, Name: "bob", Email: "bob@headscale.net"},
|
||||
{ID: 3, Name: "thor", Email: "thor@example.org"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -45,9 +44,9 @@ func ptrAddr(s string) *netip.Addr {
|
||||
// norse-god names and nodes get original-151 pokémon names.
|
||||
func setupACLCompatUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "odin", Email: "odin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "thor", Email: "thor@example.org"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "freya", Email: "freya@example.com"},
|
||||
{ID: 1, Name: "odin", Email: "odin@example.com"},
|
||||
{ID: 2, Name: "thor", Email: "thor@example.org"},
|
||||
{ID: 3, Name: "freya", Email: "freya@example.com"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -39,9 +38,9 @@ import (
|
||||
// .
|
||||
func setupGrantsCompatUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "odin", Email: "odin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "thor", Email: "thor@example.org"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "freya", Email: "freya@example.com"},
|
||||
{ID: 1, Name: "odin", Email: "odin@example.com"},
|
||||
{ID: 2, Name: "thor", Email: "thor@example.org"},
|
||||
{ID: 3, Name: "freya", Email: "freya@example.com"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/views"
|
||||
)
|
||||
@@ -36,9 +35,9 @@ import (
|
||||
// tool's anonymizer rewrites the SaaS users into.
|
||||
func nodeAttrsCompatUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "odin", Email: "odin@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "thor", Email: "thor@example.org"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "freya", Email: "freya@example.com"},
|
||||
{ID: 1, Name: "odin", Email: "odin@example.com"},
|
||||
{ID: 2, Name: "thor", Email: "thor@example.org"},
|
||||
{ID: 3, Name: "freya", Email: "freya@example.com"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go4.org/netipx"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -81,16 +80,16 @@ func buildRoutesUsersAndNodes(
|
||||
users = make(types.Users, 0, len(topo.Users))
|
||||
for _, u := range topo.Users {
|
||||
users = append(users, types.User{
|
||||
Model: gorm.Model{ID: u.ID},
|
||||
ID: u.ID,
|
||||
Name: u.Name,
|
||||
Email: convertSaaSEmail(u.Email),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
users = types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "kratail2tid", Email: "kratail2tid@example.com"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "kristoffer", Email: "kristoffer@example.com"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "monitorpasskeykradalby", Email: "monitorpasskeykradalby@example.com"},
|
||||
{ID: 1, Name: "kratail2tid", Email: "kratail2tid@example.com"},
|
||||
{ID: 2, Name: "kristoffer", Email: "kristoffer@example.com"},
|
||||
{ID: 3, Name: "monitorpasskeykradalby", Email: "monitorpasskeykradalby@example.com"},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1455,7 +1454,7 @@ func TestRoutesCompatPeerAllowedIPs(t *testing.T) {
|
||||
|
||||
for _, nmPeer := range capture.Netmap.Peers {
|
||||
// Extract the short name from the FQDN.
|
||||
peerName := strings.Split(nmPeer.Name(), ".")[0]
|
||||
peerName, _, _ := strings.Cut(nmPeer.Name(), ".")
|
||||
|
||||
peer := findNodeByGivenName(nodes, peerName)
|
||||
if peer == nil {
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@@ -29,17 +28,17 @@ import (
|
||||
func setupSSHDataCompatUsers() types.Users {
|
||||
return types.Users{
|
||||
{
|
||||
Model: gorm.Model{ID: 1},
|
||||
ID: 1,
|
||||
Name: "odin",
|
||||
Email: "odin@example.com",
|
||||
},
|
||||
{
|
||||
Model: gorm.Model{ID: 2},
|
||||
ID: 2,
|
||||
Name: "thor",
|
||||
Email: "thor@example.org",
|
||||
},
|
||||
{
|
||||
Model: gorm.Model{ID: 3},
|
||||
ID: 3,
|
||||
Name: "freya",
|
||||
Email: "freya@example.com",
|
||||
},
|
||||
|
||||
@@ -7,15 +7,14 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// policyTestUsers/policyTestNodes are reused across the test cases below to
|
||||
// keep each table row focussed on the policy + tests under exercise.
|
||||
func policyTestUsers() types.Users {
|
||||
return types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "alice", Email: "alice@headscale.net"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "bob", Email: "bob@headscale.net"},
|
||||
{ID: 1, Name: "alice", Email: "alice@headscale.net"},
|
||||
{ID: 2, Name: "bob", Email: "bob@headscale.net"},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +350,7 @@ func TestNewPolicyManagerSkipsTests(t *testing.T) {
|
||||
// a `ip: tcp:80` grant).
|
||||
func TestRunTestsEmptyProtoMatchesDefaultProtocols(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "odin", Email: "odin@example.com"},
|
||||
{ID: 1, Name: "odin", Email: "odin@example.com"},
|
||||
}
|
||||
nodes := types.Nodes{
|
||||
{
|
||||
|
||||
@@ -2808,9 +2808,9 @@ func TestResolvePolicy(t *testing.T) {
|
||||
|
||||
func TestResolveAutoApprovers(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -3274,9 +3274,9 @@ func ipSetComparer(x, y *netipx.IPSet) bool {
|
||||
|
||||
func TestNodeCanApproveRoute(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -3407,9 +3407,9 @@ func TestNodeCanApproveRoute(t *testing.T) {
|
||||
|
||||
func TestResolveTagOwners(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -3507,9 +3507,9 @@ func TestResolveTagOwners(t *testing.T) {
|
||||
|
||||
func TestNodeCanHaveTag(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
nodes := types.Nodes{
|
||||
@@ -3786,9 +3786,9 @@ func TestNodeCanHaveTag(t *testing.T) {
|
||||
|
||||
func TestUserMatchesOwner(t *testing.T) {
|
||||
users := types.Users{
|
||||
{Model: gorm.Model{ID: 1}, Name: "user1"},
|
||||
{Model: gorm.Model{ID: 2}, Name: "user2"},
|
||||
{Model: gorm.Model{ID: 3}, Name: "user3"},
|
||||
{ID: 1, Name: "user1"},
|
||||
{ID: 2, Name: "user2"},
|
||||
{ID: 3, Name: "user3"},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// TestNodeIsTagged tests the [Node.IsTagged] method for determining if a node is tagged.
|
||||
@@ -285,7 +284,7 @@ func TestNodeOwnershipModel(t *testing.T) {
|
||||
// TestUserTypedID tests the TypedID() helper method.
|
||||
func TestUserTypedID(t *testing.T) {
|
||||
user := User{
|
||||
Model: gorm.Model{ID: 42},
|
||||
ID: 42,
|
||||
}
|
||||
|
||||
typedID := user.TypedID()
|
||||
|
||||
@@ -40,7 +40,7 @@ const (
|
||||
// Tagged nodes don't belong to a real user - the tag is their identity.
|
||||
// This special user ID is used when rendering tagged nodes in the Tailscale protocol.
|
||||
var TaggedDevices = User{
|
||||
Model: gorm.Model{ID: TaggedDevicesUserID},
|
||||
ID: TaggedDevicesUserID,
|
||||
Name: "tagged-devices",
|
||||
DisplayName: "Tagged Devices",
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
||||
|
||||
user := status.User[status.Self.UserID].LoginName
|
||||
|
||||
assert.Len(c, status.Peer, (testCase.want[user]))
|
||||
assert.Len(c, status.Peer, testCase.want[user])
|
||||
}, integrationutil.ScaledTimeout(10*time.Second), integrationutil.FastPoll, "Waiting for expected peer visibility")
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user