mirror of
https://github.com/juanfont/headscale.git
synced 2025-06-24 01:16:14 +02:00
types/node: make user pointer
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
b87bb35004
commit
d3005b1d4f
@ -193,8 +193,8 @@ func (h *Headscale) handleRegisterWithAuthKey(
|
|||||||
|
|
||||||
nodeToRegister := types.Node{
|
nodeToRegister := types.Node{
|
||||||
Hostname: regReq.Hostinfo.Hostname,
|
Hostname: regReq.Hostinfo.Hostname,
|
||||||
UserID: pak.User.ID,
|
UserID: ptr.To(pak.User.ID),
|
||||||
User: pak.User,
|
User: ptr.To(pak.User),
|
||||||
MachineKey: machineKey,
|
MachineKey: machineKey,
|
||||||
NodeKey: regReq.NodeKey,
|
NodeKey: regReq.NodeKey,
|
||||||
Hostinfo: regReq.Hostinfo,
|
Hostinfo: regReq.Hostinfo,
|
||||||
@ -204,9 +204,9 @@ func (h *Headscale) handleRegisterWithAuthKey(
|
|||||||
// TODO(kradalby): This should not be set on the node,
|
// TODO(kradalby): This should not be set on the node,
|
||||||
// they should be looked up through the key, which is
|
// they should be looked up through the key, which is
|
||||||
// attached to the node.
|
// attached to the node.
|
||||||
ForcedTags: pak.Proto().GetAclTags(),
|
Tags: pak.Proto().GetAclTags(),
|
||||||
AuthKey: pak,
|
AuthKey: pak,
|
||||||
AuthKeyID: &pak.ID,
|
AuthKeyID: &pak.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !regReq.Expiry.IsZero() {
|
if !regReq.Expiry.IsZero() {
|
||||||
|
@ -96,7 +96,7 @@ func TestIPAllocatorSequential(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.1"),
|
IPv4: nap("100.64.0.1"),
|
||||||
IPv6: nap("fd7a:115c:a1e0::1"),
|
IPv6: nap("fd7a:115c:a1e0::1"),
|
||||||
})
|
})
|
||||||
@ -124,7 +124,7 @@ func TestIPAllocatorSequential(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.2"),
|
IPv4: nap("100.64.0.2"),
|
||||||
IPv6: nap("fd7a:115c:a1e0::2"),
|
IPv6: nap("fd7a:115c:a1e0::2"),
|
||||||
})
|
})
|
||||||
@ -314,7 +314,7 @@ func TestBackfillIPAddresses(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.1"),
|
IPv4: nap("100.64.0.1"),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ func TestBackfillIPAddresses(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv6: nap("fd7a:115c:a1e0::1"),
|
IPv6: nap("fd7a:115c:a1e0::1"),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ func TestBackfillIPAddresses(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.1"),
|
IPv4: nap("100.64.0.1"),
|
||||||
IPv6: nap("fd7a:115c:a1e0::1"),
|
IPv6: nap("fd7a:115c:a1e0::1"),
|
||||||
})
|
})
|
||||||
@ -388,7 +388,7 @@ func TestBackfillIPAddresses(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.1"),
|
IPv4: nap("100.64.0.1"),
|
||||||
IPv6: nap("fd7a:115c:a1e0::1"),
|
IPv6: nap("fd7a:115c:a1e0::1"),
|
||||||
})
|
})
|
||||||
@ -412,19 +412,19 @@ func TestBackfillIPAddresses(t *testing.T) {
|
|||||||
db.DB.Save(&user)
|
db.DB.Save(&user)
|
||||||
|
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.1"),
|
IPv4: nap("100.64.0.1"),
|
||||||
})
|
})
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.2"),
|
IPv4: nap("100.64.0.2"),
|
||||||
})
|
})
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.3"),
|
IPv4: nap("100.64.0.3"),
|
||||||
})
|
})
|
||||||
db.DB.Save(&types.Node{
|
db.DB.Save(&types.Node{
|
||||||
User: user,
|
User: &user,
|
||||||
IPv4: nap("100.64.0.4"),
|
IPv4: nap("100.64.0.4"),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ func SetTags(
|
|||||||
) error {
|
) error {
|
||||||
if len(tags) == 0 {
|
if len(tags) == 0 {
|
||||||
// if no tags are provided, we remove all forced tags
|
// if no tags are provided, we remove all forced tags
|
||||||
if err := tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("forced_tags", "[]").Error; err != nil {
|
if err := tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("tags", "[]").Error; err != nil {
|
||||||
return fmt.Errorf("removing tags: %w", err)
|
return fmt.Errorf("removing tags: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ func SetTags(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("forced_tags", string(b)).Error; err != nil {
|
if err := tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("tags", string(b)).Error; err != nil {
|
||||||
return fmt.Errorf("updating tags: %w", err)
|
return fmt.Errorf("updating tags: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,12 +376,13 @@ func (hsdb *HSDatabase) HandleNodeFromAuthPath(
|
|||||||
// Why not always?
|
// Why not always?
|
||||||
// Registration of expired node with different user
|
// Registration of expired node with different user
|
||||||
if reg.Node.ID != 0 &&
|
if reg.Node.ID != 0 &&
|
||||||
reg.Node.UserID != user.ID {
|
reg.Node.UserID != nil &&
|
||||||
|
*reg.Node.UserID != user.ID {
|
||||||
return nil, ErrDifferentRegisteredUser
|
return nil, ErrDifferentRegisteredUser
|
||||||
}
|
}
|
||||||
|
|
||||||
reg.Node.UserID = user.ID
|
reg.Node.UserID = &user.ID
|
||||||
reg.Node.User = *user
|
reg.Node.User = user
|
||||||
reg.Node.RegisterMethod = registrationMethod
|
reg.Node.RegisterMethod = registrationMethod
|
||||||
|
|
||||||
if nodeExpiry != nil {
|
if nodeExpiry != nil {
|
||||||
@ -435,7 +436,6 @@ func RegisterNode(tx *gorm.DB, node types.Node, ipv4 *netip.Addr, ipv6 *netip.Ad
|
|||||||
Str("node", node.Hostname).
|
Str("node", node.Hostname).
|
||||||
Str("machine_key", node.MachineKey.ShortString()).
|
Str("machine_key", node.MachineKey.ShortString()).
|
||||||
Str("node_key", node.NodeKey.ShortString()).
|
Str("node_key", node.NodeKey.ShortString()).
|
||||||
Str("user", node.User.Username()).
|
|
||||||
Msg("Registering node")
|
Msg("Registering node")
|
||||||
|
|
||||||
// If the a new node is registered with the same machine key, to the same user,
|
// If the a new node is registered with the same machine key, to the same user,
|
||||||
@ -463,7 +463,6 @@ func RegisterNode(tx *gorm.DB, node types.Node, ipv4 *netip.Addr, ipv6 *netip.Ad
|
|||||||
Str("node", node.Hostname).
|
Str("node", node.Hostname).
|
||||||
Str("machine_key", node.MachineKey.ShortString()).
|
Str("machine_key", node.MachineKey.ShortString()).
|
||||||
Str("node_key", node.NodeKey.ShortString()).
|
Str("node_key", node.NodeKey.ShortString()).
|
||||||
Str("user", node.User.Username()).
|
|
||||||
Msg("Node authorized again")
|
Msg("Node authorized again")
|
||||||
|
|
||||||
return &node, nil
|
return &node, nil
|
||||||
|
@ -43,7 +43,7 @@ func (s *Suite) TestGetNode(c *check.C) {
|
|||||||
MachineKey: machineKey.Public(),
|
MachineKey: machineKey.Public(),
|
||||||
NodeKey: nodeKey.Public(),
|
NodeKey: nodeKey.Public(),
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ func (s *Suite) TestGetNodeByID(c *check.C) {
|
|||||||
MachineKey: machineKey.Public(),
|
MachineKey: machineKey.Public(),
|
||||||
NodeKey: nodeKey.Public(),
|
NodeKey: nodeKey.Public(),
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ func (s *Suite) TestHardDeleteNode(c *check.C) {
|
|||||||
MachineKey: machineKey.Public(),
|
MachineKey: machineKey.Public(),
|
||||||
NodeKey: nodeKey.Public(),
|
NodeKey: nodeKey.Public(),
|
||||||
Hostname: "testnode3",
|
Hostname: "testnode3",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
}
|
}
|
||||||
trx := db.DB.Save(&node)
|
trx := db.DB.Save(&node)
|
||||||
@ -127,7 +127,7 @@ func (s *Suite) TestListPeers(c *check.C) {
|
|||||||
MachineKey: machineKey.Public(),
|
MachineKey: machineKey.Public(),
|
||||||
NodeKey: nodeKey.Public(),
|
NodeKey: nodeKey.Public(),
|
||||||
Hostname: "testnode" + strconv.Itoa(index),
|
Hostname: "testnode" + strconv.Itoa(index),
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ func (s *Suite) TestExpireNode(c *check.C) {
|
|||||||
MachineKey: machineKey.Public(),
|
MachineKey: machineKey.Public(),
|
||||||
NodeKey: nodeKey.Public(),
|
NodeKey: nodeKey.Public(),
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
Expiry: &time.Time{},
|
Expiry: &time.Time{},
|
||||||
@ -206,7 +206,7 @@ func (s *Suite) TestSetTags(c *check.C) {
|
|||||||
MachineKey: machineKey.Public(),
|
MachineKey: machineKey.Public(),
|
||||||
NodeKey: nodeKey.Public(),
|
NodeKey: nodeKey.Public(),
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ func (s *Suite) TestSetTags(c *check.C) {
|
|||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
node, err = db.getNode(types.UserID(user.ID), "testnode")
|
node, err = db.getNode(types.UserID(user.ID), "testnode")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
c.Assert(node.ForcedTags, check.DeepEquals, sTags)
|
c.Assert(node.Tags, check.DeepEquals, sTags)
|
||||||
|
|
||||||
// assign duplicate tags, expect no errors but no doubles in DB
|
// assign duplicate tags, expect no errors but no doubles in DB
|
||||||
eTags := []string{"tag:bar", "tag:test", "tag:unknown", "tag:test"}
|
eTags := []string{"tag:bar", "tag:test", "tag:unknown", "tag:test"}
|
||||||
@ -229,7 +229,7 @@ func (s *Suite) TestSetTags(c *check.C) {
|
|||||||
node, err = db.getNode(types.UserID(user.ID), "testnode")
|
node, err = db.getNode(types.UserID(user.ID), "testnode")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
c.Assert(
|
c.Assert(
|
||||||
node.ForcedTags,
|
node.Tags,
|
||||||
check.DeepEquals,
|
check.DeepEquals,
|
||||||
[]string{"tag:bar", "tag:test", "tag:unknown"},
|
[]string{"tag:bar", "tag:test", "tag:unknown"},
|
||||||
)
|
)
|
||||||
@ -239,7 +239,7 @@ func (s *Suite) TestSetTags(c *check.C) {
|
|||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
node, err = db.getNode(types.UserID(user.ID), "testnode")
|
node, err = db.getNode(types.UserID(user.ID), "testnode")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
c.Assert(node.ForcedTags, check.DeepEquals, []string{})
|
c.Assert(node.Tags, check.DeepEquals, []string{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHeadscale_generateGivenName(t *testing.T) {
|
func TestHeadscale_generateGivenName(t *testing.T) {
|
||||||
@ -451,7 +451,7 @@ func TestAutoApproveRoutes(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: tt.routes,
|
RoutableIPs: tt.routes,
|
||||||
@ -467,13 +467,13 @@ func TestAutoApproveRoutes(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "taggednode",
|
Hostname: "taggednode",
|
||||||
UserID: taggedUser.ID,
|
UserID: &taggedUser.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: tt.routes,
|
RoutableIPs: tt.routes,
|
||||||
},
|
},
|
||||||
ForcedTags: []string{"tag:exit"},
|
Tags: []string{"tag:exit"},
|
||||||
IPv4: ptr.To(netip.MustParseAddr("100.64.0.2")),
|
IPv4: ptr.To(netip.MustParseAddr("100.64.0.2")),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = adb.DB.Save(&nodeTagged).Error
|
err = adb.DB.Save(&nodeTagged).Error
|
||||||
@ -612,7 +612,7 @@ func TestListEphemeralNodes(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test",
|
Hostname: "test",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
@ -622,7 +622,7 @@ func TestListEphemeralNodes(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "ephemeral",
|
Hostname: "ephemeral",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pakEph.ID),
|
AuthKeyID: ptr.To(pakEph.ID),
|
||||||
}
|
}
|
||||||
@ -665,7 +665,7 @@ func TestRenameNode(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test",
|
Hostname: "test",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
}
|
}
|
||||||
@ -675,7 +675,7 @@ func TestRenameNode(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test",
|
Hostname: "test",
|
||||||
UserID: user2.ID,
|
UserID: &user2.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
}
|
}
|
||||||
@ -765,7 +765,7 @@ func TestListPeers(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test1",
|
Hostname: "test1",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
}
|
}
|
||||||
@ -775,7 +775,7 @@ func TestListPeers(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test2",
|
Hostname: "test2",
|
||||||
UserID: user2.ID,
|
UserID: &user2.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
}
|
}
|
||||||
@ -849,7 +849,7 @@ func TestListNodes(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test1",
|
Hostname: "test1",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
}
|
}
|
||||||
@ -859,7 +859,7 @@ func TestListNodes(t *testing.T) {
|
|||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
Hostname: "test2",
|
Hostname: "test2",
|
||||||
UserID: user2.ID,
|
UserID: &user2.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ func TestCannotDeleteAssignedPreAuthKey(t *testing.T) {
|
|||||||
node := types.Node{
|
node := types.Node{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Hostname: "testest",
|
Hostname: "testest",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(key.ID),
|
AuthKeyID: ptr.To(key.ID),
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/juanfont/headscale/hscontrol/util"
|
"github.com/juanfont/headscale/hscontrol/util"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -192,7 +193,7 @@ func (hsdb *HSDatabase) GetUserByName(name string) (*types.User, error) {
|
|||||||
// ListNodesByUser gets all the nodes in a given user.
|
// ListNodesByUser gets all the nodes in a given user.
|
||||||
func ListNodesByUser(tx *gorm.DB, uid types.UserID) (types.Nodes, error) {
|
func ListNodesByUser(tx *gorm.DB, uid types.UserID) (types.Nodes, error) {
|
||||||
nodes := types.Nodes{}
|
nodes := types.Nodes{}
|
||||||
if err := tx.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where(&types.Node{UserID: uint(uid)}).Find(&nodes).Error; err != nil {
|
if err := tx.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where(&types.Node{UserID: ptr.To(uint(uid))}).Find(&nodes).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +212,7 @@ func AssignNodeToUser(tx *gorm.DB, node *types.Node, uid types.UserID) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
node.User = *user
|
node.User = user
|
||||||
if result := tx.Save(&node); result.Error != nil {
|
if result := tx.Save(&node); result.Error != nil {
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func (s *Suite) TestDestroyUserErrors(c *check.C) {
|
|||||||
node := types.Node{
|
node := types.Node{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: user.ID,
|
UserID: &user.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
@ -110,17 +110,17 @@ func (s *Suite) TestSetMachineUser(c *check.C) {
|
|||||||
node := types.Node{
|
node := types.Node{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Hostname: "testnode",
|
Hostname: "testnode",
|
||||||
UserID: oldUser.ID,
|
UserID: &oldUser.ID,
|
||||||
RegisterMethod: util.RegisterMethodAuthKey,
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
AuthKeyID: ptr.To(pak.ID),
|
AuthKeyID: ptr.To(pak.ID),
|
||||||
}
|
}
|
||||||
trx := db.DB.Save(&node)
|
trx := db.DB.Save(&node)
|
||||||
c.Assert(trx.Error, check.IsNil)
|
c.Assert(trx.Error, check.IsNil)
|
||||||
c.Assert(node.UserID, check.Equals, oldUser.ID)
|
c.Assert(*node.UserID, check.Equals, oldUser.ID)
|
||||||
|
|
||||||
err = db.AssignNodeToUser(&node, types.UserID(newUser.ID))
|
err = db.AssignNodeToUser(&node, types.UserID(newUser.ID))
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
c.Assert(node.UserID, check.Equals, newUser.ID)
|
c.Assert(*node.UserID, check.Equals, newUser.ID)
|
||||||
c.Assert(node.User.Name, check.Equals, newUser.Name)
|
c.Assert(node.User.Name, check.Equals, newUser.Name)
|
||||||
|
|
||||||
err = db.AssignNodeToUser(&node, 9584849)
|
err = db.AssignNodeToUser(&node, 9584849)
|
||||||
@ -128,6 +128,6 @@ func (s *Suite) TestSetMachineUser(c *check.C) {
|
|||||||
|
|
||||||
err = db.AssignNodeToUser(&node, types.UserID(newUser.ID))
|
err = db.AssignNodeToUser(&node, types.UserID(newUser.ID))
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
c.Assert(node.UserID, check.Equals, newUser.ID)
|
c.Assert(*node.UserID, check.Equals, newUser.ID)
|
||||||
c.Assert(node.User.Name, check.Equals, newUser.Name)
|
c.Assert(node.User.Name, check.Equals, newUser.Name)
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,7 @@ func nodesToProto(polMan policy.PolicyManager, isLikelyConnected *xsync.MapOf[ty
|
|||||||
tags = append(tags, tag)
|
tags = append(tags, tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp.ValidTags = lo.Uniq(append(tags, node.ForcedTags...))
|
resp.ValidTags = lo.Uniq(append(tags, node.Tags...))
|
||||||
resp.SubnetRoutes = util.PrefixesToString(append(pr.PrimaryRoutes(node.ID), node.ExitRoutes()...))
|
resp.SubnetRoutes = util.PrefixesToString(append(pr.PrimaryRoutes(node.ID), node.ExitRoutes()...))
|
||||||
response[index] = resp
|
response[index] = resp
|
||||||
}
|
}
|
||||||
@ -819,7 +819,7 @@ func (api headscaleV1APIServer) DebugCreateNode(
|
|||||||
NodeKey: key.NewNode().Public(),
|
NodeKey: key.NewNode().Public(),
|
||||||
MachineKey: key.NewMachine().Public(),
|
MachineKey: key.NewMachine().Public(),
|
||||||
Hostname: request.GetName(),
|
Hostname: request.GetName(),
|
||||||
User: *user,
|
User: user,
|
||||||
|
|
||||||
Expiry: &time.Time{},
|
Expiry: &time.Time{},
|
||||||
LastSeen: &time.Time{},
|
LastSeen: &time.Time{},
|
||||||
|
@ -104,11 +104,16 @@ func generateUserProfiles(
|
|||||||
) []tailcfg.UserProfile {
|
) []tailcfg.UserProfile {
|
||||||
userMap := make(map[uint]*types.User)
|
userMap := make(map[uint]*types.User)
|
||||||
ids := make([]uint, 0, len(userMap))
|
ids := make([]uint, 0, len(userMap))
|
||||||
userMap[node.User.ID] = &node.User
|
var tagged bool
|
||||||
ids = append(ids, node.User.ID)
|
if node.IsUserOwned() {
|
||||||
for _, peer := range peers {
|
userMap[node.User.ID] = node.User
|
||||||
userMap[peer.User.ID] = &peer.User
|
ids = append(ids, node.User.ID)
|
||||||
ids = append(ids, peer.User.ID)
|
for _, peer := range peers {
|
||||||
|
userMap[peer.User.ID] = peer.User
|
||||||
|
ids = append(ids, peer.User.ID)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tagged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
slices.Sort(ids)
|
slices.Sort(ids)
|
||||||
@ -120,6 +125,10 @@ func generateUserProfiles(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tagged {
|
||||||
|
profiles = append(profiles, types.TaggedDevices.TailscaleUserProfile())
|
||||||
|
}
|
||||||
|
|
||||||
return profiles
|
return profiles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ func TestDNSConfigMapResponse(t *testing.T) {
|
|||||||
mach := func(hostname, username string, userid uint) *types.Node {
|
mach := func(hostname, username string, userid uint) *types.Node {
|
||||||
return &types.Node{
|
return &types.Node{
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
UserID: userid,
|
UserID: &userid,
|
||||||
User: types.User{
|
User: &types.User{
|
||||||
Name: username,
|
Name: username,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -128,15 +128,15 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
DiscoKey: mustDK(
|
DiscoKey: mustDK(
|
||||||
"discokey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084",
|
"discokey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084",
|
||||||
),
|
),
|
||||||
IPv4: iap("100.64.0.1"),
|
IPv4: iap("100.64.0.1"),
|
||||||
Hostname: "mini",
|
Hostname: "mini",
|
||||||
GivenName: "mini",
|
GivenName: "mini",
|
||||||
UserID: user1.ID,
|
UserID: &user1.ID,
|
||||||
User: user1,
|
User: &user1,
|
||||||
ForcedTags: []string{},
|
Tags: []string{},
|
||||||
AuthKey: &types.PreAuthKey{},
|
AuthKey: &types.PreAuthKey{},
|
||||||
LastSeen: &lastSeen,
|
LastSeen: &lastSeen,
|
||||||
Expiry: &expire,
|
Expiry: &expire,
|
||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: []netip.Prefix{
|
RoutableIPs: []netip.Prefix{
|
||||||
tsaddr.AllIPv4(),
|
tsaddr.AllIPv4(),
|
||||||
@ -205,16 +205,16 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
DiscoKey: mustDK(
|
DiscoKey: mustDK(
|
||||||
"discokey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084",
|
"discokey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084",
|
||||||
),
|
),
|
||||||
IPv4: iap("100.64.0.2"),
|
IPv4: iap("100.64.0.2"),
|
||||||
Hostname: "peer1",
|
Hostname: "peer1",
|
||||||
GivenName: "peer1",
|
GivenName: "peer1",
|
||||||
UserID: user2.ID,
|
UserID: &user2.ID,
|
||||||
User: user2,
|
User: &user2,
|
||||||
ForcedTags: []string{},
|
Tags: []string{},
|
||||||
LastSeen: &lastSeen,
|
LastSeen: &lastSeen,
|
||||||
Expiry: &expire,
|
Expiry: &expire,
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
Hostinfo: &tailcfg.Hostinfo{},
|
||||||
CreatedAt: created,
|
CreatedAt: created,
|
||||||
}
|
}
|
||||||
|
|
||||||
tailPeer1 := &tailcfg.Node{
|
tailPeer1 := &tailcfg.Node{
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/juanfont/headscale/hscontrol/policy"
|
"github.com/juanfont/headscale/hscontrol/policy"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/samber/lo"
|
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
)
|
)
|
||||||
@ -72,14 +71,6 @@ func tailNode(
|
|||||||
return nil, fmt.Errorf("tailNode, failed to create FQDN: %s", err)
|
return nil, fmt.Errorf("tailNode, failed to create FQDN: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tags []string
|
|
||||||
for _, tag := range node.RequestTags() {
|
|
||||||
if polMan.NodeCanHaveTag(node, tag) {
|
|
||||||
tags = append(tags, tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tags = lo.Uniq(append(tags, node.ForcedTags...))
|
|
||||||
|
|
||||||
routes := primaryRouteFunc(node.ID)
|
routes := primaryRouteFunc(node.ID)
|
||||||
allowed := append(node.Prefixes(), routes...)
|
allowed := append(node.Prefixes(), routes...)
|
||||||
allowed = append(allowed, node.ExitRoutes()...)
|
allowed = append(allowed, node.ExitRoutes()...)
|
||||||
@ -91,8 +82,6 @@ func tailNode(
|
|||||||
Name: hostname,
|
Name: hostname,
|
||||||
Cap: capVer,
|
Cap: capVer,
|
||||||
|
|
||||||
User: tailcfg.UserID(node.UserID),
|
|
||||||
|
|
||||||
Key: node.NodeKey,
|
Key: node.NodeKey,
|
||||||
KeyExpiry: keyExpiry.UTC(),
|
KeyExpiry: keyExpiry.UTC(),
|
||||||
|
|
||||||
@ -109,12 +98,20 @@ func tailNode(
|
|||||||
|
|
||||||
Online: node.IsOnline,
|
Online: node.IsOnline,
|
||||||
|
|
||||||
Tags: tags,
|
Tags: node.Tags,
|
||||||
|
|
||||||
MachineAuthorized: !node.IsExpired(),
|
MachineAuthorized: !node.IsExpired(),
|
||||||
Expired: node.IsExpired(),
|
Expired: node.IsExpired(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if node.IsUserOwned() {
|
||||||
|
tNode.User = tailcfg.UserID(*node.UserID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.IsTagged() {
|
||||||
|
tNode.User = tailcfg.UserID(types.TaggedDevices.ID)
|
||||||
|
}
|
||||||
|
|
||||||
tNode.CapMap = tailcfg.NodeCapMap{
|
tNode.CapMap = tailcfg.NodeCapMap{
|
||||||
tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{},
|
tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{},
|
||||||
tailcfg.CapabilityAdmin: []tailcfg.RawMessage{},
|
tailcfg.CapabilityAdmin: []tailcfg.RawMessage{},
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTailNode(t *testing.T) {
|
func TestTailNode(t *testing.T) {
|
||||||
@ -70,7 +71,6 @@ func TestTailNode(t *testing.T) {
|
|||||||
HomeDERP: 0,
|
HomeDERP: 0,
|
||||||
LegacyDERPString: "127.3.3.40:0",
|
LegacyDERPString: "127.3.3.40:0",
|
||||||
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
||||||
Tags: []string{},
|
|
||||||
MachineAuthorized: true,
|
MachineAuthorized: true,
|
||||||
|
|
||||||
CapMap: tailcfg.NodeCapMap{
|
CapMap: tailcfg.NodeCapMap{
|
||||||
@ -97,14 +97,13 @@ func TestTailNode(t *testing.T) {
|
|||||||
IPv4: iap("100.64.0.1"),
|
IPv4: iap("100.64.0.1"),
|
||||||
Hostname: "mini",
|
Hostname: "mini",
|
||||||
GivenName: "mini",
|
GivenName: "mini",
|
||||||
UserID: 0,
|
UserID: ptr.To(uint(0)),
|
||||||
User: types.User{
|
User: &types.User{
|
||||||
Name: "mini",
|
Name: "mini",
|
||||||
},
|
},
|
||||||
ForcedTags: []string{},
|
AuthKey: &types.PreAuthKey{},
|
||||||
AuthKey: &types.PreAuthKey{},
|
LastSeen: &lastSeen,
|
||||||
LastSeen: &lastSeen,
|
Expiry: &expire,
|
||||||
Expiry: &expire,
|
|
||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: []netip.Prefix{
|
RoutableIPs: []netip.Prefix{
|
||||||
tsaddr.AllIPv4(),
|
tsaddr.AllIPv4(),
|
||||||
@ -156,8 +155,6 @@ func TestTailNode(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
Created: created,
|
Created: created,
|
||||||
|
|
||||||
Tags: []string{},
|
|
||||||
|
|
||||||
LastSeen: &lastSeen,
|
LastSeen: &lastSeen,
|
||||||
MachineAuthorized: true,
|
MachineAuthorized: true,
|
||||||
|
|
||||||
@ -184,7 +181,6 @@ func TestTailNode(t *testing.T) {
|
|||||||
HomeDERP: 0,
|
HomeDERP: 0,
|
||||||
LegacyDERPString: "127.3.3.40:0",
|
LegacyDERPString: "127.3.3.40:0",
|
||||||
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
||||||
Tags: []string{},
|
|
||||||
MachineAuthorized: true,
|
MachineAuthorized: true,
|
||||||
|
|
||||||
CapMap: tailcfg.NodeCapMap{
|
CapMap: tailcfg.NodeCapMap{
|
||||||
|
@ -567,7 +567,9 @@ func (nodes Nodes) DebugString() string {
|
|||||||
func (node Node) DebugString() string {
|
func (node Node) DebugString() string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
fmt.Fprintf(&sb, "%s(%s):\n", node.Hostname, node.ID)
|
fmt.Fprintf(&sb, "%s(%s):\n", node.Hostname, node.ID)
|
||||||
fmt.Fprintf(&sb, "\tUser: %s (%d, %q)\n", node.User.Display(), node.User.ID, node.User.Username())
|
if node.IsUserOwned() {
|
||||||
|
fmt.Fprintf(&sb, "\tUser: %s (%d, %q)\n", node.User.Display(), node.User.ID, node.User.Username())
|
||||||
|
}
|
||||||
fmt.Fprintf(&sb, "\tTags: %v\n", node.Tags)
|
fmt.Fprintf(&sb, "\tTags: %v\n", node.Tags)
|
||||||
fmt.Fprintf(&sb, "\tIPs: %v\n", node.IPs())
|
fmt.Fprintf(&sb, "\tIPs: %v\n", node.IPs())
|
||||||
fmt.Fprintf(&sb, "\tApprovedRoutes: %v\n", node.ApprovedRoutes)
|
fmt.Fprintf(&sb, "\tApprovedRoutes: %v\n", node.ApprovedRoutes)
|
||||||
|
@ -2,11 +2,12 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/juanfont/headscale/hscontrol/policy/matcher"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/juanfont/headscale/hscontrol/policy/matcher"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||||
@ -139,7 +140,7 @@ func TestNodeFQDN(t *testing.T) {
|
|||||||
name: "no-dnsconfig-with-username",
|
name: "no-dnsconfig-with-username",
|
||||||
node: Node{
|
node: Node{
|
||||||
GivenName: "test",
|
GivenName: "test",
|
||||||
User: User{
|
User: &User{
|
||||||
Name: "user",
|
Name: "user",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -150,7 +151,7 @@ func TestNodeFQDN(t *testing.T) {
|
|||||||
name: "all-set",
|
name: "all-set",
|
||||||
node: Node{
|
node: Node{
|
||||||
GivenName: "test",
|
GivenName: "test",
|
||||||
User: User{
|
User: &User{
|
||||||
Name: "user",
|
Name: "user",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -160,7 +161,7 @@ func TestNodeFQDN(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "no-given-name",
|
name: "no-given-name",
|
||||||
node: Node{
|
node: Node{
|
||||||
User: User{
|
User: &User{
|
||||||
Name: "user",
|
Name: "user",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -179,7 +180,7 @@ func TestNodeFQDN(t *testing.T) {
|
|||||||
name: "no-dnsconfig",
|
name: "no-dnsconfig",
|
||||||
node: Node{
|
node: Node{
|
||||||
GivenName: "test",
|
GivenName: "test",
|
||||||
User: User{
|
User: &User{
|
||||||
Name: "user",
|
Name: "user",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -18,6 +18,16 @@ import (
|
|||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TaggedDevices is a special user that is used to
|
||||||
|
// populate the tagged devices in the Tailscale MapResponse.
|
||||||
|
var TaggedDevices = User{
|
||||||
|
// This ID is arbitrarily chosen, it is naively high to avoid
|
||||||
|
// and conflicts with other IDs.
|
||||||
|
Model: gorm.Model{ID: 2147455555},
|
||||||
|
Name: "tagged-devices",
|
||||||
|
DisplayName: "Tagged Devices",
|
||||||
|
}
|
||||||
|
|
||||||
type UserID uint64
|
type UserID uint64
|
||||||
|
|
||||||
type Users []User
|
type Users []User
|
||||||
|
Loading…
Reference in New Issue
Block a user