| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 | package modelsimport (	"context"	"math/rand"	"net"	"time"	"github.com/gravitl/netmaker/mongoconn"	"go.mongodb.org/mongo-driver/bson"	"go.mongodb.org/mongo-driver/bson/primitive")const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"var seededRand *rand.Rand = rand.New(	rand.NewSource(time.Now().UnixNano()))//node structtype Node struct {	ID                  primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`	Address             string             `json:"address" bson:"address" validate:"omitempty,ipv4"`	Address6            string             `json:"address6" bson:"address6" validate:"omitempty,ipv6"`	LocalAddress        string             `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`	Name                string             `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`	ListenPort          int32              `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`	PublicKey           string             `json:"publickey" bson:"publickey" validate:"required,base64"`	Endpoint            string             `json:"endpoint" bson:"endpoint" validate:"required,ip"`	PostUp              string             `json:"postup" bson:"postup"`	PostDown            string             `json:"postdown" bson:"postdown"`	AllowedIPs          []string             `json:"allowedips" bson:"allowedips"`	PersistentKeepalive int32              `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`	SaveConfig          *bool              `json:"saveconfig" bson:"saveconfig"`	AccessKey           string             `json:"accesskey" bson:"accesskey"`	Interface           string             `json:"interface" bson:"interface"`	LastModified        int64              `json:"lastmodified" bson:"lastmodified"`	KeyUpdateTimeStamp  int64              `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`	ExpirationDateTime  int64              `json:"expdatetime" bson:"expdatetime"`	LastPeerUpdate      int64              `json:"lastpeerupdate" bson:"lastpeerupdate"`	LastCheckIn         int64              `json:"lastcheckin" bson:"lastcheckin"`	MacAddress          string             `json:"macaddress" bson:"macaddress" validate:"required,mac,macaddress_unique"`	CheckInInterval     int32              `json:"checkininterval" bson:"checkininterval"`	Password            string             `json:"password" bson:"password" validate:"required,min=6"`	Network             string             `json:"network" bson:"network" validate:"network_exists"`	IsPending           bool               `json:"ispending" bson:"ispending"`	IsEgressGateway           bool               `json:"isegressgateway" bson:"isegressgateway"`	IsIngressGateway           bool               `json:"isingressgateway" bson:"isingressgateway"`	EgressGatewayRanges        []string             `json:"egressgatewayranges" bson:"egressgatewayranges"`	IngressGatewayRange        string             `json:"ingressgatewayrange" bson:"ingressgatewayrange"`	PostChanges         string             `json:"postchanges" bson:"postchanges"`        StaticIP         string             `json:"staticip" bson:"staticip"`        StaticPubKey         string             `json:"staticpubkey" bson:"staticpubkey"`}//node update struct --- only validations are differenttype NodeUpdate struct {	ID                  primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`	Address             string             `json:"address" bson:"address" validate:"omitempty,ip"`	Address6            string             `json:"address6" bson:"address6" validate:"omitempty,ipv6"`	LocalAddress        string             `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`	Name                string             `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`	ListenPort          int32              `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`	PublicKey           string             `json:"publickey" bson:"publickey" validate:"omitempty,base64"`	Endpoint            string             `json:"endpoint" bson:"endpoint" validate:"omitempty,ip"`	PostUp              string             `json:"postup" bson:"postup"`	PostDown            string             `json:"postdown" bson:"postdown"`	AllowedIPs          []string             `json:"allowedips" bson:"allowedips"`	PersistentKeepalive int32              `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`	SaveConfig          *bool              `json:"saveconfig" bson:"saveconfig"`	AccessKey           string             `json:"accesskey" bson:"accesskey"`	Interface           string             `json:"interface" bson:"interface"`	LastModified        int64              `json:"lastmodified" bson:"lastmodified"`	KeyUpdateTimeStamp  int64              `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`	ExpirationDateTime  int64              `json:"expdatetime" bson:"expdatetime"`	LastPeerUpdate      int64              `json:"lastpeerupdate" bson:"lastpeerupdate"`	LastCheckIn         int64              `json:"lastcheckin" bson:"lastcheckin"`	MacAddress          string             `json:"macaddress" bson:"macaddress" validate:"required,mac"`	CheckInInterval     int32              `json:"checkininterval" bson:"checkininterval"`	Password            string             `json:"password" bson:"password" validate:"omitempty,min=5"`	Network             string             `json:"network" bson:"network" validate:"network_exists"`	IsPending           bool               `json:"ispending" bson:"ispending"`	IsIngressGateway           bool               `json:"isingressgateway" bson:"isingressgateway"`	IsEgressGateway           bool               `json:"isegressgateway" bson:"isegressgateway"`        IngressGatewayRange        string             `json:"ingressgatewayrange" bson:"ingressgatewayrange"`	EgressGatewayRanges        []string             `json:"egressgatewayranges" bson:"egressgatewayranges"`	PostChanges         string             `json:"postchanges" bson:"postchanges"`	StaticIP         string             `json:"staticip" bson:"staticip"`	StaticPubKey         string             `json:"staticpubkey" bson:"staticpubkey"`}//Duplicated function for NodeUpdatesfunc (node *NodeUpdate) GetNetwork() (Network, error) {	var network Network	collection := mongoconn.NetworkDB	//collection := mongoconn.Client.Database("netmaker").Collection("networks")	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)	filter := bson.M{"netid": node.Network}	err := collection.FindOne(ctx, filter).Decode(&network)	defer cancel()	if err != nil {		//log.Fatal(err)		return network, err	}	return network, err}//TODO: Contains a fatal error return. Need to change//Used in contexts where it's not the Parent network.func (node *Node) GetNetwork() (Network, error) {	var network Network	//collection := mongoconn.NetworkDB	collection := mongoconn.Client.Database("netmaker").Collection("networks")	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)	filter := bson.M{"netid": node.Network}	err := collection.FindOne(ctx, filter).Decode(&network)	defer cancel()	if err != nil {		//log.Fatal(err)		return network, err	}	return network, err}//TODO://Not sure if below two methods are necessary. May want to revisitfunc (node *Node) SetLastModified() {	node.LastModified = time.Now().Unix()}func (node *Node) SetLastCheckIn() {	node.LastCheckIn = time.Now().Unix()}func (node *Node) SetLastPeerUpdate() {	node.LastPeerUpdate = time.Now().Unix()}func (node *Node) SetExpirationDateTime() {	node.ExpirationDateTime = time.Unix(33174902665, 0).Unix()}func (node *Node) SetDefaultName() {	if node.Name == "" {		nodeid := StringWithCharset(5, charset)		nodename := "node-" + nodeid		node.Name = nodename	}}//TODO: I dont know why this exists//This should exist on the node.go struct. I'm sure there was a reason?func (node *Node) SetDefaults() {	//TODO: Maybe I should make Network a part of the node struct. Then we can just query the Network object for stuff.	parentNetwork, _ := node.GetNetwork()	node.ExpirationDateTime = time.Unix(33174902665, 0).Unix()	if node.ListenPort == 0 {		node.ListenPort = parentNetwork.DefaultListenPort	}	if node.PostDown == "" {		//Empty because we dont set it		//may want to set it to something in the future	}	//TODO: This is dumb and doesn't work	//Need to change	if node.SaveConfig == nil {		if parentNetwork.DefaultSaveConfig != nil {			defaultsave := *parentNetwork.DefaultSaveConfig			node.SaveConfig = &defaultsave		}	}	if node.Interface == "" {		node.Interface = parentNetwork.DefaultInterface	}	if node.PersistentKeepalive == 0 {		node.PersistentKeepalive = parentNetwork.DefaultKeepalive	}	if node.PostUp == "" {		postup := parentNetwork.DefaultPostUp		node.PostUp = postup	}	if node.StaticIP == "" {		node.StaticIP = "no"	}        if node.StaticPubKey == "" {                node.StaticPubKey = "no"        }	node.CheckInInterval = parentNetwork.DefaultCheckInInterval}func StringWithCharset(length int, charset string) string {	b := make([]byte, length)	for i := range b {		b[i] = charset[seededRand.Intn(len(charset))]	}	return string(b)}//Check for valid IPv4 address//Note: We dont handle IPv6 AT ALL!!!!! This definitely is needed at some point//But for iteration 1, lets just stick to IPv4. Keep it simple stupid.func IsIpv4Net(host string) bool {	return net.ParseIP(host) != nil}
 |