tailcfg: reintroduce UserProfile.Groups
This change reintroduces UserProfile.Groups, a slice that contains
the ACL-defined and synced groups that a user is a member of.
The slice will only be non-nil for clients with the node attribute
see-groups, and will only contain groups that the client is allowed
to see as per the app payload of the see-groups node attribute.
For example:
```
"nodeAttrs": [
{
"target": ["tag:dev"],
"app": {
"tailscale.com/see-groups": [{"groups": ["group:dev"]}]
}
},
[...]
]
```
UserProfile.Groups will also be gated by a feature flag for the time
being.
Updates tailscale/corp#31529
Signed-off-by: Gesa Stupperich <gesa@tailscale.com>
This commit is contained in:
committed by
Gesa Stupperich
parent
ac74dfa5cd
commit
6a19995f13
+9
-1
@@ -282,6 +282,13 @@ type UserProfile struct {
|
||||
LoginName string // "alice@smith.com"; for display purposes only (provider is not listed)
|
||||
DisplayName string // "Alice Smith"
|
||||
ProfilePicURL string `json:",omitzero"`
|
||||
|
||||
// Groups is a subset of SCIM groups (e.g. "engineering@example.com")
|
||||
// or group names in the tailnet policy document (e.g. "group:eng")
|
||||
// that contain this user and that the coordination server was
|
||||
// configured to report to this node.
|
||||
// The list is always sorted when loaded from storage.
|
||||
Groups []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (p *UserProfile) Equal(p2 *UserProfile) bool {
|
||||
@@ -294,7 +301,8 @@ func (p *UserProfile) Equal(p2 *UserProfile) bool {
|
||||
return p.ID == p2.ID &&
|
||||
p.LoginName == p2.LoginName &&
|
||||
p.DisplayName == p2.DisplayName &&
|
||||
p.ProfilePicURL == p2.ProfilePicURL
|
||||
p.ProfilePicURL == p2.ProfilePicURL &&
|
||||
slices.Equal(p.Groups, p2.Groups)
|
||||
}
|
||||
|
||||
// RawMessage is a raw encoded JSON value. It implements Marshaler and
|
||||
|
||||
@@ -620,6 +620,7 @@ func (src *UserProfile) Clone() *UserProfile {
|
||||
}
|
||||
dst := new(UserProfile)
|
||||
*dst = *src
|
||||
dst.Groups = append(src.Groups[:0:0], src.Groups...)
|
||||
return dst
|
||||
}
|
||||
|
||||
@@ -629,6 +630,7 @@ var _UserProfileCloneNeedsRegeneration = UserProfile(struct {
|
||||
LoginName string
|
||||
DisplayName string
|
||||
ProfilePicURL string
|
||||
Groups []string
|
||||
}{})
|
||||
|
||||
// Clone makes a deep copy of VIPService.
|
||||
|
||||
+10
-2
@@ -2505,8 +2505,15 @@ func (v UserProfileView) ID() UserID { return v.ж.ID }
|
||||
func (v UserProfileView) LoginName() string { return v.ж.LoginName }
|
||||
|
||||
// "Alice Smith"
|
||||
func (v UserProfileView) DisplayName() string { return v.ж.DisplayName }
|
||||
func (v UserProfileView) ProfilePicURL() string { return v.ж.ProfilePicURL }
|
||||
func (v UserProfileView) DisplayName() string { return v.ж.DisplayName }
|
||||
func (v UserProfileView) ProfilePicURL() string { return v.ж.ProfilePicURL }
|
||||
|
||||
// Groups is a subset of SCIM groups (e.g. "engineering@example.com")
|
||||
// or group names in the tailnet policy document (e.g. "group:eng")
|
||||
// that contain this user and that the coordination server was
|
||||
// configured to report to this node.
|
||||
// The list is always sorted when loaded from storage.
|
||||
func (v UserProfileView) Groups() views.Slice[string] { return views.SliceOf(v.ж.Groups) }
|
||||
func (v UserProfileView) Equal(v2 UserProfileView) bool { return v.ж.Equal(v2.ж) }
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
@@ -2515,6 +2522,7 @@ var _UserProfileViewNeedsRegeneration = UserProfile(struct {
|
||||
LoginName string
|
||||
DisplayName string
|
||||
ProfilePicURL string
|
||||
Groups []string
|
||||
}{})
|
||||
|
||||
// View returns a read-only view of VIPService.
|
||||
|
||||
Reference in New Issue
Block a user