From 2c76d5c5b7f0bb9fce21fb16c865c7cf936c8bfa Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 25 Aug 2026 07:20:06 +0000 Subject: [PATCH] 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. --- hscontrol/api/v1/users.go | 3 +- hscontrol/db/db_test.go | 16 +-- hscontrol/db/text_serialiser.go | 2 +- hscontrol/handlers_test.go | 3 +- hscontrol/policy/policy_autoapprove_test.go | 13 +- .../policy/policy_route_approval_test.go | 13 +- hscontrol/policy/policy_test.go | 11 +- hscontrol/policy/policyutil/reduce_test.go | 11 +- hscontrol/policy/route_approval_test.go | 7 +- hscontrol/policy/v2/filter_test.go | 127 +++++++++--------- hscontrol/policy/v2/issue_3212_test.go | 2 +- hscontrol/policy/v2/issue_3233_test.go | 5 +- hscontrol/policy/v2/issue_3267_test.go | 3 +- hscontrol/policy/v2/node_recompute_test.go | 3 +- hscontrol/policy/v2/nodeattrs_test.go | 5 +- .../policy/v2/policy_concurrency_test.go | 7 +- hscontrol/policy/v2/policy_test.go | 85 ++++++------ .../policy/v2/policytester_compat_test.go | 7 +- hscontrol/policy/v2/sshtest_test.go | 7 +- .../v2/tailscale_acl_data_compat_test.go | 7 +- .../policy/v2/tailscale_grants_compat_test.go | 7 +- .../v2/tailscale_nodeattrs_compat_test.go | 7 +- .../v2/tailscale_routes_data_compat_test.go | 11 +- .../v2/tailscale_ssh_data_compat_test.go | 7 +- hscontrol/policy/v2/test_test.go | 7 +- hscontrol/policy/v2/types_test.go | 30 ++--- hscontrol/types/node_tags_test.go | 3 +- hscontrol/types/users.go | 2 +- integration/acl_test.go | 2 +- 29 files changed, 195 insertions(+), 218 deletions(-) diff --git a/hscontrol/api/v1/users.go b/hscontrol/api/v1/users.go index 9468d67a1..e437e6b4b 100644 --- a/hscontrol/api/v1/users.go +++ b/hscontrol/api/v1/users.go @@ -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() } diff --git a/hscontrol/db/db_test.go b/hscontrol/db/db_test.go index 7d654061b..cfc31ebdd 100644 --- a/hscontrol/db/db_test.go +++ b/hscontrol/db/db_test.go @@ -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} diff --git a/hscontrol/db/text_serialiser.go b/hscontrol/db/text_serialiser.go index c315772bc..14a996215 100644 --- a/hscontrol/db/text_serialiser.go +++ b/hscontrol/db/text_serialiser.go @@ -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) } } diff --git a/hscontrol/handlers_test.go b/hscontrol/handlers_test.go index 10f851f65..9eaae41ee 100644 --- a/hscontrol/handlers_test.go +++ b/hscontrol/handlers_test.go @@ -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 } diff --git a/hscontrol/policy/policy_autoapprove_test.go b/hscontrol/policy/policy_autoapprove_test.go index ed3fa9801..3f229ccd4 100644 --- a/hscontrol/policy/policy_autoapprove_test.go +++ b/hscontrol/policy/policy_autoapprove_test.go @@ -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} diff --git a/hscontrol/policy/policy_route_approval_test.go b/hscontrol/policy/policy_route_approval_test.go index 9e56337fc..2e8fdca94 100644 --- a/hscontrol/policy/policy_route_approval_test.go +++ b/hscontrol/policy/policy_route_approval_test.go @@ -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 diff --git a/hscontrol/policy/policy_test.go b/hscontrol/policy/policy_test.go index 408959772..1a490f670 100644 --- a/hscontrol/policy/policy_test.go +++ b/hscontrol/policy/policy_test.go @@ -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 diff --git a/hscontrol/policy/policyutil/reduce_test.go b/hscontrol/policy/policyutil/reduce_test.go index 4c722f919..33b7ce81b 100644 --- a/hscontrol/policy/policyutil/reduce_test.go +++ b/hscontrol/policy/policyutil/reduce_test.go @@ -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 { diff --git a/hscontrol/policy/route_approval_test.go b/hscontrol/policy/route_approval_test.go index 3d070a256..25a3b6e76 100644 --- a/hscontrol/policy/route_approval_test.go +++ b/hscontrol/policy/route_approval_test.go @@ -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 diff --git a/hscontrol/policy/v2/filter_test.go b/hscontrol/policy/v2/filter_test.go index b6afc8e08..2d99331db 100644 --- a/hscontrol/policy/v2/filter_test.go +++ b/hscontrol/policy/v2/filter_test.go @@ -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{ diff --git a/hscontrol/policy/v2/issue_3212_test.go b/hscontrol/policy/v2/issue_3212_test.go index e95b18ded..5bbfcaaf0 100644 --- a/hscontrol/policy/v2/issue_3212_test.go +++ b/hscontrol/policy/v2/issue_3212_test.go @@ -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 diff --git a/hscontrol/policy/v2/issue_3233_test.go b/hscontrol/policy/v2/issue_3233_test.go index 42c78891f..2fd049e61 100644 --- a/hscontrol/policy/v2/issue_3233_test.go +++ b/hscontrol/policy/v2/issue_3233_test.go @@ -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()} diff --git a/hscontrol/policy/v2/issue_3267_test.go b/hscontrol/policy/v2/issue_3267_test.go index 007ae09e9..b8bccc658 100644 --- a/hscontrol/policy/v2/issue_3267_test.go +++ b/hscontrol/policy/v2/issue_3267_test.go @@ -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 { diff --git a/hscontrol/policy/v2/node_recompute_test.go b/hscontrol/policy/v2/node_recompute_test.go index ed8c9db17..9688b3556 100644 --- a/hscontrol/policy/v2/node_recompute_test.go +++ b/hscontrol/policy/v2/node_recompute_test.go @@ -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":["*:*"]}]}` diff --git a/hscontrol/policy/v2/nodeattrs_test.go b/hscontrol/policy/v2/nodeattrs_test.go index c494024ed..a08c86b22 100644 --- a/hscontrol/policy/v2/nodeattrs_test.go +++ b/hscontrol/policy/v2/nodeattrs_test.go @@ -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"}, } } diff --git a/hscontrol/policy/v2/policy_concurrency_test.go b/hscontrol/policy/v2/policy_concurrency_test.go index b4b759f59..3ac55bc66 100644 --- a/hscontrol/policy/v2/policy_concurrency_test.go +++ b/hscontrol/policy/v2/policy_concurrency_test.go @@ -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 := `{ diff --git a/hscontrol/policy/v2/policy_test.go b/hscontrol/policy/v2/policy_test.go index 6a0d7ada9..a52194705 100644 --- a/hscontrol/policy/v2/policy_test.go +++ b/hscontrol/policy/v2/policy_test.go @@ -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. diff --git a/hscontrol/policy/v2/policytester_compat_test.go b/hscontrol/policy/v2/policytester_compat_test.go index 47f6e9559..57d00a938 100644 --- a/hscontrol/policy/v2/policytester_compat_test.go +++ b/hscontrol/policy/v2/policytester_compat_test.go @@ -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"}, } } diff --git a/hscontrol/policy/v2/sshtest_test.go b/hscontrol/policy/v2/sshtest_test.go index 1fa2dd055..92fcab900 100644 --- a/hscontrol/policy/v2/sshtest_test.go +++ b/hscontrol/policy/v2/sshtest_test.go @@ -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"}, } } diff --git a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go index ecf212947..031d1cca7 100644 --- a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go @@ -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"}, } } diff --git a/hscontrol/policy/v2/tailscale_grants_compat_test.go b/hscontrol/policy/v2/tailscale_grants_compat_test.go index b23b14ffc..49d042a64 100644 --- a/hscontrol/policy/v2/tailscale_grants_compat_test.go +++ b/hscontrol/policy/v2/tailscale_grants_compat_test.go @@ -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"}, } } diff --git a/hscontrol/policy/v2/tailscale_nodeattrs_compat_test.go b/hscontrol/policy/v2/tailscale_nodeattrs_compat_test.go index 9a2923a03..8809caedc 100644 --- a/hscontrol/policy/v2/tailscale_nodeattrs_compat_test.go +++ b/hscontrol/policy/v2/tailscale_nodeattrs_compat_test.go @@ -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"}, } } diff --git a/hscontrol/policy/v2/tailscale_routes_data_compat_test.go b/hscontrol/policy/v2/tailscale_routes_data_compat_test.go index 978977940..cb68aed43 100644 --- a/hscontrol/policy/v2/tailscale_routes_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_routes_data_compat_test.go @@ -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 { diff --git a/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go b/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go index a6cb27c20..b04e799fa 100644 --- a/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go @@ -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", }, diff --git a/hscontrol/policy/v2/test_test.go b/hscontrol/policy/v2/test_test.go index fc29f4835..9e892bcd1 100644 --- a/hscontrol/policy/v2/test_test.go +++ b/hscontrol/policy/v2/test_test.go @@ -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{ { diff --git a/hscontrol/policy/v2/types_test.go b/hscontrol/policy/v2/types_test.go index 19134e5b3..5a9530d8f 100644 --- a/hscontrol/policy/v2/types_test.go +++ b/hscontrol/policy/v2/types_test.go @@ -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 { diff --git a/hscontrol/types/node_tags_test.go b/hscontrol/types/node_tags_test.go index a401d71d8..e468604cd 100644 --- a/hscontrol/types/node_tags_test.go +++ b/hscontrol/types/node_tags_test.go @@ -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() diff --git a/hscontrol/types/users.go b/hscontrol/types/users.go index cc194aa49..ea5f3de1f 100644 --- a/hscontrol/types/users.go +++ b/hscontrol/types/users.go @@ -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", } diff --git a/integration/acl_test.go b/integration/acl_test.go index 6410a2214..f02320c1f 100644 --- a/integration/acl_test.go +++ b/integration/acl_test.go @@ -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") } })