diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index fb643a6df..1ede0bd9b 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -234,12 +234,6 @@ type User struct { DisplayName string // if non-empty overrides Login field ProfilePicURL string // if non-empty overrides Login field Created time.Time - - // Old, unused fields... - // TODO(bradfitz): remove, once verifying old clients don't need them. - - LoginName string `json:"-"` // not stored, filled from Login // TODO REMOVE - Logins []LoginID } // Login is a user from a specific identity provider, not associated with any diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 78da0aea6..d282719b7 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -26,7 +26,6 @@ func (src *User) Clone() *User { } dst := new(User) *dst = *src - dst.Logins = append(src.Logins[:0:0], src.Logins...) return dst } @@ -36,8 +35,6 @@ var _UserCloneNeedsRegeneration = User(struct { DisplayName string ProfilePicURL string Created time.Time - LoginName string - Logins []LoginID }{}) // Clone makes a deep copy of Node. @@ -302,7 +299,6 @@ func (src *RegisterResponse) Clone() *RegisterResponse { } dst := new(RegisterResponse) *dst = *src - dst.User = *src.User.Clone() dst.NodeKeySignature = append(src.NodeKeySignature[:0:0], src.NodeKeySignature...) return dst } diff --git a/tailcfg/tailcfg_test.go b/tailcfg/tailcfg_test.go index 9f8c418a1..b9a204ead 100644 --- a/tailcfg/tailcfg_test.go +++ b/tailcfg/tailcfg_test.go @@ -666,7 +666,6 @@ func TestCloneUser(t *testing.T) { u *User }{ {"nil_logins", &User{}}, - {"zero_logins", &User{Logins: make([]LoginID, 0)}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index 1c5fda627..774a18258 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -66,12 +66,10 @@ func (v *UserView) UnmarshalJSON(b []byte) error { return nil } -func (v UserView) ID() UserID { return v.ж.ID } -func (v UserView) DisplayName() string { return v.ж.DisplayName } -func (v UserView) ProfilePicURL() string { return v.ж.ProfilePicURL } -func (v UserView) Created() time.Time { return v.ж.Created } -func (v UserView) LoginName() string { return v.ж.LoginName } -func (v UserView) Logins() views.Slice[LoginID] { return views.SliceOf(v.ж.Logins) } +func (v UserView) ID() UserID { return v.ж.ID } +func (v UserView) DisplayName() string { return v.ж.DisplayName } +func (v UserView) ProfilePicURL() string { return v.ж.ProfilePicURL } +func (v UserView) Created() time.Time { return v.ж.Created } // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _UserViewNeedsRegeneration = User(struct { @@ -79,8 +77,6 @@ var _UserViewNeedsRegeneration = User(struct { DisplayName string ProfilePicURL string Created time.Time - LoginName string - Logins []LoginID }{}) // View returns a readonly view of Node. @@ -637,7 +633,7 @@ func (v *RegisterResponseView) UnmarshalJSON(b []byte) error { return nil } -func (v RegisterResponseView) User() UserView { return v.ж.User.View() } +func (v RegisterResponseView) User() User { return v.ж.User } func (v RegisterResponseView) Login() Login { return v.ж.Login } func (v RegisterResponseView) NodeKeyExpired() bool { return v.ж.NodeKeyExpired } func (v RegisterResponseView) MachineAuthorized() bool { return v.ж.MachineAuthorized } diff --git a/tstest/integration/testcontrol/testcontrol.go b/tstest/integration/testcontrol/testcontrol.go index a6b2e1828..92f74e244 100644 --- a/tstest/integration/testcontrol/testcontrol.go +++ b/tstest/integration/testcontrol/testcontrol.go @@ -6,6 +6,7 @@ package testcontrol import ( "bytes" + "cmp" "context" "encoding/binary" "encoding/json" @@ -476,13 +477,22 @@ func (s *Server) AddFakeNode() { // TODO: send updates to other (non-fake?) nodes } -func (s *Server) AllUsers() (users []*tailcfg.User) { +func (s *Server) allUserProfiles() (res []tailcfg.UserProfile) { s.mu.Lock() defer s.mu.Unlock() - for _, u := range s.users { - users = append(users, u.Clone()) + for k, u := range s.users { + up := tailcfg.UserProfile{ + ID: u.ID, + DisplayName: u.DisplayName, + } + if login, ok := s.logins[k]; ok { + up.LoginName = login.LoginName + up.ProfilePicURL = cmp.Or(up.ProfilePicURL, login.ProfilePicURL) + up.DisplayName = cmp.Or(up.DisplayName, login.DisplayName) + } + res = append(res, up) } - return users + return res } func (s *Server) AllNodes() (nodes []*tailcfg.Node) { @@ -523,9 +533,7 @@ func (s *Server) getUser(nodeKey key.NodePublic) (*tailcfg.User, *tailcfg.Login) } user := &tailcfg.User{ ID: id, - LoginName: loginName, DisplayName: displayName, - Logins: []tailcfg.LoginID{login.ID}, } s.users[nodeKey] = user s.logins[nodeKey] = login @@ -1001,13 +1009,7 @@ func (s *Server) MapResponse(req *tailcfg.MapRequest) (res *tailcfg.MapResponse, sort.Slice(res.Peers, func(i, j int) bool { return res.Peers[i].ID < res.Peers[j].ID }) - for _, u := range s.AllUsers() { - res.UserProfiles = append(res.UserProfiles, tailcfg.UserProfile{ - ID: u.ID, - LoginName: u.LoginName, - DisplayName: u.DisplayName, - }) - } + res.UserProfiles = s.allUserProfiles() v4Prefix := netip.PrefixFrom(netaddr.IPv4(100, 64, uint8(tailcfg.NodeID(user.ID)>>8), uint8(tailcfg.NodeID(user.ID))), 32) v6Prefix := netip.PrefixFrom(tsaddr.Tailscale4To6(v4Prefix.Addr()), 128)