diff --git a/hscontrol/db/preauth_keys_test.go b/hscontrol/db/preauth_keys_test.go index c152959c..2c547b6e 100644 --- a/hscontrol/db/preauth_keys_test.go +++ b/hscontrol/db/preauth_keys_test.go @@ -96,7 +96,7 @@ func TestPreAuthKeyACLTags(t *testing.T) { require.NoError(t, err) require.Len(t, listedPaks, 1) - gotTags := listedPaks[0].Proto().GetAclTags() + gotTags := listedPaks[0].Tags slices.Sort(gotTags) assert.Equal(t, expectedTags, gotTags) }, diff --git a/hscontrol/types/api_key.go b/hscontrol/types/api_key.go index 3ad3450e..17854b44 100644 --- a/hscontrol/types/api_key.go +++ b/hscontrol/types/api_key.go @@ -3,10 +3,8 @@ package types import ( "time" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/util/zlog/zf" "github.com/rs/zerolog" - "google.golang.org/protobuf/types/known/timestamppb" ) // NewAPIKeyPrefixLength is the length of the prefix for new API keys. @@ -24,28 +22,6 @@ type APIKey struct { LastSeen *time.Time } -func (key *APIKey) Proto() *v1.ApiKey { - protoKey := v1.ApiKey{ - Id: key.ID, - } - - protoKey.Prefix = key.maskedPrefix() - - if key.Expiration != nil { - protoKey.Expiration = timestamppb.New(*key.Expiration) - } - - if key.CreatedAt != nil { - protoKey.CreatedAt = timestamppb.New(*key.CreatedAt) - } - - if key.LastSeen != nil { - protoKey.LastSeen = timestamppb.New(*key.LastSeen) - } - - return &protoKey -} - // maskedPrefix returns the API key prefix in masked format for safe logging. // SECURITY: Never log the full key or hash, only the masked prefix. func (k *APIKey) maskedPrefix() string { diff --git a/hscontrol/types/node.go b/hscontrol/types/node.go index b487c581..bec3550a 100644 --- a/hscontrol/types/node.go +++ b/hscontrol/types/node.go @@ -10,13 +10,11 @@ import ( "strings" "time" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/policy/matcher" "github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util/zlog/zf" "github.com/rs/zerolog" "go4.org/netipx" - "google.golang.org/protobuf/types/known/timestamppb" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" @@ -483,55 +481,6 @@ func (nodes Nodes) ContainsNodeKey(nodeKey key.NodePublic) bool { return false } -func (node *Node) Proto() *v1.Node { - nodeProto := &v1.Node{ - Id: uint64(node.ID), - MachineKey: node.MachineKey.String(), - - NodeKey: node.NodeKey.String(), - DiscoKey: node.DiscoKey.String(), - - // TODO(kradalby): replace list with v4, v6 field? - IpAddresses: node.IPsAsString(), - Name: node.Hostname, - GivenName: node.GivenName, - User: nil, // Will be set below based on node type - Tags: node.Tags, - Online: node.IsOnline != nil && *node.IsOnline, - - // Only ApprovedRoutes and AvailableRoutes is set here. SubnetRoutes has - // to be populated manually with PrimaryRoute, to ensure it includes the - // routes that are actively served from the node. - ApprovedRoutes: util.PrefixesToString(node.ApprovedRoutes), - AvailableRoutes: util.PrefixesToString(node.AnnouncedRoutes()), - - RegisterMethod: node.RegisterMethodToV1Enum(), - - CreatedAt: timestamppb.New(node.CreatedAt), - } - - // Set User field based on node ownership - // Note: User will be set to [TaggedDevices] in the gRPC layer (grpcv1.go) - // for proper [tailcfg.MapResponse] formatting - if node.User != nil { - nodeProto.User = node.User.Proto() - } - - if node.AuthKey != nil { - nodeProto.PreAuthKey = node.AuthKey.Proto() - } - - if node.LastSeen != nil { - nodeProto.LastSeen = timestamppb.New(*node.LastSeen) - } - - if node.Expiry != nil { - nodeProto.Expiry = timestamppb.New(*node.Expiry) - } - - return nodeProto -} - func (node *Node) GetFQDN(baseDomain string) (string, error) { if node.GivenName == "" { return "", fmt.Errorf("creating valid FQDN: %w", ErrNodeHasNoGivenName) @@ -684,19 +633,6 @@ func EndpointsChanged(oldEndpoints, newEndpoints []netip.AddrPort) bool { return !equalUnordered(oldEndpoints, newEndpoints, netip.AddrPort.Compare) } -func (node *Node) RegisterMethodToV1Enum() v1.RegisterMethod { - switch node.RegisterMethod { - case "authkey": - return v1.RegisterMethod_REGISTER_METHOD_AUTH_KEY - case "oidc": - return v1.RegisterMethod_REGISTER_METHOD_OIDC - case "cli": - return v1.RegisterMethod_REGISTER_METHOD_CLI - default: - return v1.RegisterMethod_REGISTER_METHOD_UNSPECIFIED - } -} - // ApplyPeerChange takes a [tailcfg.PeerChange] struct and updates the node. func (node *Node) ApplyPeerChange(change *tailcfg.PeerChange) { if change.Key != nil { @@ -998,15 +934,6 @@ func (nv NodeView) RequestTags() []string { return nv.Hostinfo().RequestTags().AsSlice() } -// Proto converts the [NodeView] to a protobuf representation. -func (nv NodeView) Proto() *v1.Node { - if !nv.Valid() { - return nil - } - - return nv.ж.Proto() -} - // HasIP reports if a node has a given IP address. func (nv NodeView) HasIP(i netip.Addr) bool { if !nv.Valid() { diff --git a/hscontrol/types/node_test.go b/hscontrol/types/node_test.go index 0bec4aef..3c8a5ba8 100644 --- a/hscontrol/types/node_test.go +++ b/hscontrol/types/node_test.go @@ -8,7 +8,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/policy/matcher" "github.com/juanfont/headscale/hscontrol/util" "tailscale.com/tailcfg" @@ -657,56 +656,6 @@ func TestApplyPeerChange(t *testing.T) { } } -func TestNodeRegisterMethodToV1Enum(t *testing.T) { - tests := []struct { - name string - node Node - want v1.RegisterMethod - }{ - { - name: "authkey", - node: Node{ - ID: 1, - RegisterMethod: util.RegisterMethodAuthKey, - }, - want: v1.RegisterMethod_REGISTER_METHOD_AUTH_KEY, - }, - { - name: "oidc", - node: Node{ - ID: 1, - RegisterMethod: util.RegisterMethodOIDC, - }, - want: v1.RegisterMethod_REGISTER_METHOD_OIDC, - }, - { - name: "cli", - node: Node{ - ID: 1, - RegisterMethod: util.RegisterMethodCLI, - }, - want: v1.RegisterMethod_REGISTER_METHOD_CLI, - }, - { - name: "unknown", - node: Node{ - ID: 0, - }, - want: v1.RegisterMethod_REGISTER_METHOD_UNSPECIFIED, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := tt.node.RegisterMethodToV1Enum() - - if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("RegisterMethodToV1Enum() unexpected result (-want +got):\n%s", diff) - } - }) - } -} - // TestHasNetworkChanges tests the [NodeView] method for detecting // when a node's network properties have changed. func TestHasNetworkChanges(t *testing.T) { diff --git a/hscontrol/types/preauth_key.go b/hscontrol/types/preauth_key.go index 3f789fdf..cf8d178a 100644 --- a/hscontrol/types/preauth_key.go +++ b/hscontrol/types/preauth_key.go @@ -3,11 +3,9 @@ package types import ( "time" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/util/zlog/zf" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "google.golang.org/protobuf/types/known/timestamppb" ) type PAKError string @@ -56,66 +54,6 @@ type PreAuthKeyNew struct { User *User // Can be nil for system-created tagged keys } -func (key *PreAuthKeyNew) Proto() *v1.PreAuthKey { - protoKey := v1.PreAuthKey{ - Id: key.ID, - Key: key.Key, - User: nil, // Will be set below if not nil - Reusable: key.Reusable, - Ephemeral: key.Ephemeral, - AclTags: key.Tags, - } - - if key.User != nil { - protoKey.User = key.User.Proto() - } - - if key.Expiration != nil { - protoKey.Expiration = timestamppb.New(*key.Expiration) - } - - if key.CreatedAt != nil { - protoKey.CreatedAt = timestamppb.New(*key.CreatedAt) - } - - return &protoKey -} - -func (key *PreAuthKey) Proto() *v1.PreAuthKey { - protoKey := v1.PreAuthKey{ - User: nil, // Will be set below if not nil - Id: key.ID, - Ephemeral: key.Ephemeral, - Reusable: key.Reusable, - Used: key.Used, - AclTags: key.Tags, - } - - if key.User != nil { - protoKey.User = key.User.Proto() - } - - // For new keys (with prefix/hash), show the prefix so users can identify the key - // For legacy keys (with plaintext key), show the full key for backwards compatibility - if masked := key.maskedPrefix(); masked != "" { - protoKey.Key = masked - } else if key.Key != "" { - // Legacy key - show full key for backwards compatibility - // TODO: Consider hiding this in a future major version - protoKey.Key = key.Key - } - - if key.Expiration != nil { - protoKey.Expiration = timestamppb.New(*key.Expiration) - } - - if key.CreatedAt != nil { - protoKey.CreatedAt = timestamppb.New(*key.CreatedAt) - } - - return &protoKey -} - // Validate checks if a pre auth key can be used. func (pak *PreAuthKey) Validate() error { if pak == nil { diff --git a/hscontrol/types/users.go b/hscontrol/types/users.go index 5fe45c6f..88b9707e 100644 --- a/hscontrol/types/users.go +++ b/hscontrol/types/users.go @@ -11,12 +11,10 @@ import ( "strconv" "strings" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util/zlog/zf" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "google.golang.org/protobuf/types/known/timestamppb" "gorm.io/gorm" "tailscale.com/tailcfg" ) @@ -192,28 +190,6 @@ func (u UserView) TailscaleUserProfile() tailcfg.UserProfile { return u.ж.TailscaleUserProfile() } -func (u *User) Proto() *v1.User { - // Use Name if set, otherwise fall back to Username() which provides - // a display-friendly identifier (Email > ProviderIdentifier > ID). - // This ensures OIDC users (who typically have empty Name) display - // their email, while CLI users retain their original Name. - name := u.Name - if name == "" { - name = u.Username() - } - - return &v1.User{ - Id: uint64(u.ID), - Name: name, - CreatedAt: timestamppb.New(u.CreatedAt), - DisplayName: u.DisplayName, - Email: u.Email, - ProviderId: u.ProviderIdentifier.String, - Provider: u.Provider, - ProfilePicUrl: u.ProfilePicURL, - } -} - // MarshalZerologObject implements [zerolog.LogObjectMarshaler] for safe logging. func (u *User) MarshalZerologObject(e *zerolog.Event) { if u == nil {