Selaa lähdekoodia

Merge branch 'develop' of https://github.com/gravitl/netmaker into NET-1615

abhishek9686 10 kuukautta sitten
vanhempi
commit
9331431a4e

+ 1 - 1
cli/cmd/user/groups.go

@@ -56,7 +56,7 @@ var userGroupCreateCmd = &cobra.Command{
 	Short: "create user group",
 	Long:  `create user group`,
 	Run: func(cmd *cobra.Command, args []string) {
-		fmt.Println("CLI doesn't support creation of groups currently. Visit the dashboard to create one or refer to our api documentation https://docs.v2.netmaker.io/reference")
+		fmt.Println("CLI doesn't support creation of groups currently. Visit the dashboard to create one or refer to our api documentation https://docs.netmaker.io/api")
 	},
 }
 

+ 1 - 1
cli/cmd/user/roles.go

@@ -58,7 +58,7 @@ var userRoleCreateCmd = &cobra.Command{
 	Short: "create user role",
 	Long:  `create user role`,
 	Run: func(cmd *cobra.Command, args []string) {
-		fmt.Println("CLI doesn't support creation of roles currently. Visit the dashboard to create one or refer to our api documentation https://docs.v2.netmaker.io/reference")
+		fmt.Println("CLI doesn't support creation of roles currently. Visit the dashboard to create one or refer to our api documentation https://docs.netmaker.io/api")
 	},
 }
 

+ 2 - 0
config/config.go

@@ -100,6 +100,8 @@ type ServerConfig struct {
 	SmtpHost                   string        `json:"smtp_host"`
 	SmtpPort                   int           `json:"smtp_port"`
 	MetricInterval             string        `yaml:"metric_interval"`
+	ManageDNS                  bool          `yaml:"manage_dns"`
+	DefaultDomain              string        `yaml:"default_domain"`
 }
 
 // SQLConfig - Generic SQL Config

+ 48 - 0
controllers/dns.go

@@ -11,6 +11,7 @@ import (
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/servercfg"
 )
 
@@ -24,6 +25,8 @@ func dnsHandlers(r *mux.Router) {
 		Methods(http.MethodGet)
 	r.HandleFunc("/api/dns/adm/{network}", logic.SecurityCheck(true, http.HandlerFunc(getDNS))).
 		Methods(http.MethodGet)
+	r.HandleFunc("/api/dns/adm/{network}/sync", logic.SecurityCheck(true, http.HandlerFunc(syncDNS))).
+		Methods(http.MethodPost)
 	r.HandleFunc("/api/dns/{network}", logic.SecurityCheck(true, http.HandlerFunc(createDNS))).
 		Methods(http.MethodPost)
 	r.HandleFunc("/api/dns/adm/pushdns", logic.SecurityCheck(true, http.HandlerFunc(pushDNS))).
@@ -147,6 +150,7 @@ func createDNS(w http.ResponseWriter, r *http.Request) {
 
 	var entry models.DNSEntry
 	var params = mux.Vars(r)
+	netID := params["network"]
 
 	_ = json.NewDecoder(r.Body).Decode(&entry)
 	entry.Network = params["network"]
@@ -176,6 +180,10 @@ func createDNS(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
+	if servercfg.GetManageDNS() {
+		mq.SendDNSSyncByNetwork(netID)
+	}
+
 	logger.Log(1, "new DNS record added:", entry.Name)
 	logger.Log(2, r.Header.Get("user"),
 		fmt.Sprintf("DNS entry is set: %+v", entry))
@@ -197,6 +205,7 @@ func deleteDNS(w http.ResponseWriter, r *http.Request) {
 
 	// get params
 	var params = mux.Vars(r)
+	netID := params["network"]
 	entrytext := params["domain"] + "." + params["network"]
 	err := logic.DeleteDNS(params["domain"], params["network"])
 
@@ -216,6 +225,10 @@ func deleteDNS(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
+	if servercfg.GetManageDNS() {
+		mq.SendDNSSyncByNetwork(netID)
+	}
+
 	json.NewEncoder(w).Encode(entrytext + " deleted.")
 
 }
@@ -264,3 +277,38 @@ func pushDNS(w http.ResponseWriter, r *http.Request) {
 	logger.Log(1, r.Header.Get("user"), "pushed DNS updates to nameserver")
 	json.NewEncoder(w).Encode("DNS Pushed to CoreDNS")
 }
+
+// @Summary     Sync DNS entries for a given network
+// @Router      /api/dns/adm/{network}/sync [post]
+// @Tags        DNS
+// @Accept      json
+// @Success     200 {string} string "DNS Sync completed successfully"
+// @Failure     400 {object} models.ErrorResponse
+// @Failure     500 {object} models.ErrorResponse
+func syncDNS(w http.ResponseWriter, r *http.Request) {
+	// Set header
+	w.Header().Set("Content-Type", "application/json")
+	if !servercfg.GetManageDNS() {
+		logic.ReturnErrorResponse(
+			w,
+			r,
+			logic.FormatError(errors.New("manage DNS is set to false"), "badrequest"),
+		)
+		return
+	}
+	var params = mux.Vars(r)
+	netID := params["network"]
+	k, err := logic.GetDNS(netID)
+	if err == nil && len(k) > 0 {
+		err = mq.PushSyncDNS(k)
+	}
+
+	if err != nil {
+		logger.Log(0, r.Header.Get("user"),
+			fmt.Sprintf("Failed to Sync DNS entries to network %s: %v", netID, err))
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	logger.Log(1, r.Header.Get("user"), "DNS Sync complelted successfully")
+	json.NewEncoder(w).Encode("DNS Sync completed successfully")
+}

+ 16 - 0
controllers/ext_client.go

@@ -287,6 +287,22 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) {
 	} else if gwnode.IngressDNS != "" {
 		defaultDNS = "DNS = " + gwnode.IngressDNS
 	}
+	if servercfg.GetManageDNS() {
+		if gwnode.Address6.IP != nil {
+			if defaultDNS == "" {
+				defaultDNS = "DNS = " + gwnode.Address6.IP.String()
+			} else {
+				defaultDNS = defaultDNS + ", " + gwnode.Address6.IP.String()
+			}
+		}
+		if gwnode.Address.IP != nil {
+			if defaultDNS == "" {
+				defaultDNS = "DNS = " + gwnode.Address.IP.String()
+			} else {
+				defaultDNS = defaultDNS + ", " + gwnode.Address.IP.String()
+			}
+		}
+	}
 
 	defaultMTU := 1420
 	if host.MTU != 0 {

+ 1 - 1
docs/Authentication.md

@@ -7,4 +7,4 @@ Call the api/users/adm/authenticate endpoint (see documentation below for detail
 
 Note: While a MasterKey exists (configurable via env var or config file), it should be considered a backup option, used only when server access is lost. By default, this key is "secret key," but it's crucial to change this and keep it secure in your instance.
 
-For more information on configuration and security best practices, refer to the [Netmaker documentation](https://docs.netmaker.org/index.html).
+For more information on configuration and security best practices, refer to the [Netmaker documentation](https://docs.netmaker.io/).

+ 6 - 6
go.mod

@@ -4,23 +4,23 @@ go 1.23
 
 require (
 	github.com/eclipse/paho.mqtt.golang v1.4.3
-	github.com/go-playground/validator/v10 v10.22.0
+	github.com/go-playground/validator/v10 v10.22.1
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/google/uuid v1.6.0
 	github.com/gorilla/handlers v1.5.2
 	github.com/gorilla/mux v1.8.1
 	github.com/lib/pq v1.10.9
-	github.com/mattn/go-sqlite3 v1.14.22
+	github.com/mattn/go-sqlite3 v1.14.24
 	github.com/rqlite/gorqlite v0.0.0-20240122221808-a8a425b1a6aa
 	github.com/seancfoley/ipaddress-go v1.7.0
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.9.0
 	github.com/txn2/txeh v1.5.5
-	golang.org/x/crypto v0.27.0
+	golang.org/x/crypto v0.28.0
 	golang.org/x/net v0.27.0 // indirect
 	golang.org/x/oauth2 v0.23.0
-	golang.org/x/sys v0.25.0 // indirect
-	golang.org/x/text v0.18.0 // indirect
+	golang.org/x/sys v0.26.0 // indirect
+	golang.org/x/text v0.19.0 // indirect
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20221104135756-97bc4ad4a1cb
 	gopkg.in/yaml.v3 v3.0.1
 )
@@ -28,7 +28,7 @@ require (
 require (
 	filippo.io/edwards25519 v1.1.0
 	github.com/c-robinson/iplib v1.0.8
-	github.com/posthog/posthog-go v1.2.21
+	github.com/posthog/posthog-go v1.2.24
 )
 
 require (

+ 12 - 12
go.sum

@@ -24,8 +24,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
-github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
+github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
@@ -54,14 +54,14 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
 github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
 github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
-github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
+github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/posthog/posthog-go v1.2.21 h1:p2ea0l+Qwtk+VC2LCAI87Dz36vwj9i+QHw5s6CpRikA=
-github.com/posthog/posthog-go v1.2.21/go.mod h1:uYC2l1Yktc8E+9FAHJ9QZG4vQf/NHJPD800Hsm7DzoM=
+github.com/posthog/posthog-go v1.2.24 h1:A+iG4saBJemo++VDlcWovbYf8KFFNUfrCoJtsc40RPA=
+github.com/posthog/posthog-go v1.2.24/go.mod h1:uYC2l1Yktc8E+9FAHJ9QZG4vQf/NHJPD800Hsm7DzoM=
 github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -88,8 +88,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
-golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
+golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
+golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -116,8 +116,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
-golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
+golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -129,8 +129,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
-golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
+golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

+ 3 - 2
logic/jwts.go

@@ -56,8 +56,9 @@ func CreateJWT(uuid string, macAddress string, network string) (response string,
 func CreateUserJWT(username string, role models.UserRoleID) (response string, err error) {
 	expirationTime := time.Now().Add(servercfg.GetServerConfig().JwtValidityDuration)
 	claims := &models.UserClaims{
-		UserName: username,
-		Role:     role,
+		UserName:       username,
+		Role:           role,
+		RacAutoDisable: servercfg.GetRacAutoDisable() && (role != models.SuperAdminRole && role != models.AdminRole),
 		RegisteredClaims: jwt.RegisteredClaims{
 			Issuer:    "Netmaker",
 			Subject:   fmt.Sprintf("user|%s", username),

+ 1 - 0
logic/peers.go

@@ -408,6 +408,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 		}
 	}
 
+	hostPeerUpdate.ManageDNS = servercfg.GetManageDNS()
 	return hostPeerUpdate, nil
 }
 

+ 2 - 2
models/dnsEntry.go

@@ -42,8 +42,8 @@ type DNSUpdate struct {
 
 // DNSEntry - a DNS entry represented as struct
 type DNSEntry struct {
-	Address  string `json:"address" validate:"ip"`
-	Address6 string `json:"address6"`
+	Address  string `json:"address" validate:"omitempty,ip"`
+	Address6 string `json:"address6" validate:"omitempty,ip"`
 	Name     string `json:"name" validate:"required,name_unique,min=1,max=192,whitespace"`
 	Network  string `json:"network" validate:"network_exists"`
 }

+ 1 - 0
models/mqtt.go

@@ -24,6 +24,7 @@ type HostPeerUpdate struct {
 	FwUpdate          FwUpdate              `json:"fw_update"`
 	ReplacePeers      bool                  `json:"replace_peers"`
 	EndpointDetection bool                  `json:"endpoint_detection"`
+	ManageDNS         bool                  `yaml:"manage_dns"`
 }
 
 type FwRule struct {

+ 2 - 0
models/structs.go

@@ -266,6 +266,8 @@ type ServerConfig struct {
 	IsPro          bool   `yaml:"isee" json:"Is_EE"`
 	TrafficKey     []byte `yaml:"traffickey"`
 	MetricInterval string `yaml:"metric_interval"`
+	ManageDNS      bool   `yaml:"manage_dns"`
+	DefaultDomain  string `yaml:"default_domain"`
 }
 
 // User.NameInCharset - returns if name is in charset below or not

+ 3 - 2
models/user_mgmt.go

@@ -180,8 +180,9 @@ type UserAuthParams struct {
 
 // UserClaims - user claims struct
 type UserClaims struct {
-	Role     UserRoleID
-	UserName string
+	Role           UserRoleID
+	UserName       string
+	RacAutoDisable bool
 	jwt.RegisteredClaims
 }
 

+ 56 - 0
mq/publishers.go

@@ -23,6 +23,10 @@ func PublishPeerUpdate(replacePeers bool) error {
 		return nil
 	}
 
+	if servercfg.GetManageDNS() {
+		sendDNSSync()
+	}
+
 	hosts, err := logic.GetAllHosts()
 	if err != nil {
 		logger.Log(1, "err getting all hosts", err.Error())
@@ -249,3 +253,55 @@ func sendPeers() {
 		}
 	}
 }
+
+func SendDNSSyncByNetwork(network string) error {
+
+	k, err := logic.GetDNS(network)
+	if err == nil && len(k) > 0 {
+		err = PushSyncDNS(k)
+		if err != nil {
+			slog.Warn("error publishing dns entry data for network ", network, err.Error())
+		}
+	}
+
+	return err
+}
+
+func sendDNSSync() error {
+
+	networks, err := logic.GetNetworks()
+	if err == nil && len(networks) > 0 {
+		for _, v := range networks {
+			k, err := logic.GetDNS(v.NetID)
+			if err == nil && len(k) > 0 {
+				err = PushSyncDNS(k)
+				if err != nil {
+					slog.Warn("error publishing dns entry data for network ", v.NetID, err.Error())
+				}
+			}
+		}
+		return nil
+	}
+	return err
+}
+
+func PushSyncDNS(dnsEntries []models.DNSEntry) error {
+	logger.Log(2, "----> Pushing Sync DNS")
+	data, err := json.Marshal(dnsEntries)
+	if err != nil {
+		return errors.New("failed to marshal DNS entries: " + err.Error())
+	}
+	if mqclient == nil || !mqclient.IsConnectionOpen() {
+		return errors.New("cannot publish ... mqclient not connected")
+	}
+	if token := mqclient.Publish(fmt.Sprintf("host/dns/sync/%s", dnsEntries[0].Network), 0, true, data); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
+		var err error
+		if token.Error() == nil {
+			err = errors.New("connection timeout")
+		} else {
+			err = token.Error()
+		}
+		return err
+	}
+	return nil
+}

+ 2 - 2
pro/auth/error.go

@@ -93,12 +93,12 @@ var htmlBaseTemplate = `<!DOCTYPE html>
 </html>`
 
 var oauthNotConfigured = fmt.Sprintf(htmlBaseTemplate, `<h2>Your Netmaker server does not have OAuth configured.</h2>
-<p>Please visit the docs <a href="https://docs.netmaker.org/oauth.html" target="_blank" rel="noopener">here</a> to learn how to.</p>`)
+<p>Please visit the docs <a href="https://docs.netmaker.io/docs/server-installation/integrating-oauth" target="_blank" rel="noopener">here</a> to learn how to.</p>`)
 
 var oauthStateInvalid = fmt.Sprintf(htmlBaseTemplate, `<h2>Invalid OAuth Session. Please re-try again.</h2>`)
 
 var userNotAllowed = fmt.Sprintf(htmlBaseTemplate, `<h2>Your account does not have access to the dashboard. Please contact your administrator for more information about your account.</h2>
-<p>Non-Admins can access the netmaker networks using <a href="https://docs.netmaker.io/pro/rac.html" target="_blank" rel="noopener">RemoteAccessClient.</a></p>`)
+<p>Non-Admins can access the netmaker networks using <a href="https://docs.netmaker.io/docs/remote-access-client-rac#downloadinstallation" target="_blank" rel="noopener">our Remote Access Client.</a></p>`)
 
 var userFirstTimeSignUp = fmt.Sprintf(htmlBaseTemplate, `<h2>Thank you for signing up. Please contact your administrator for access.</h2>`)
 

+ 1 - 1
pro/auth/templates.go

@@ -118,7 +118,7 @@ var ssoErrCallbackTemplate = template.Must(
 		<h4>Error reason: {.Verb}</h4>
 		<em>Your Netmaker server may not have SSO configured properly.</em>
 		<em>
-			Please visit the <a href="https://docs.netmaker.org/oauth.html" target="_blank" rel="noopener">docs</a> for more information.
+			Please visit the <a href="https://docs.netmaker.io/docs/server-installation/integrating-oauth" target="_blank" rel="noopener">docs</a> for more information.
 		</em>
 		<p>
 			If you feel this is a mistake, please contact your network administrator.

+ 3 - 2
pro/controllers/users.go

@@ -250,8 +250,9 @@ func inviteUsers(w http.ResponseWriter, r *http.Request) {
 			// Set E-Mail body. You can set plain text or html with text/html
 
 			e := email.UserInvitedMail{
-				BodyBuilder: &email.EmailBodyBuilderWithH1HeadlineAndImage{},
-				InviteURL:   invite.InviteURL,
+				BodyBuilder:    &email.EmailBodyBuilderWithH1HeadlineAndImage{},
+				InviteURL:      invite.InviteURL,
+				PlatformRoleID: invite.PlatformRoleID,
 			}
 			n := email.Notification{
 				RecipientMail: invite.Email,

+ 39 - 44
pro/email/invite.go

@@ -2,65 +2,60 @@ package email
 
 import (
 	"fmt"
+	"github.com/gravitl/netmaker/models"
+	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"github.com/gravitl/netmaker/servercfg"
 )
 
 // UserInvitedMail - mail for users that are invited to a tenant
 type UserInvitedMail struct {
-	BodyBuilder EmailBodyBuilder
-	InviteURL   string
+	BodyBuilder    EmailBodyBuilder
+	InviteURL      string
+	PlatformRoleID string
 }
 
 // GetSubject - gets the subject of the email
 func (UserInvitedMail) GetSubject(info Notification) string {
-	return "You're invited to join Netmaker"
+	return "Connect to Your Secure Network Using Netmaker"
 }
 
 // GetBody - gets the body of the email
 func (invite UserInvitedMail) GetBody(info Notification) string {
+	downloadLink := "https://www.netmaker.io/download"
+	supportEmail := "[email protected]"
+
+	dashboardURL := fmt.Sprintf("https://dashboard.%s", servercfg.GetNmBaseDomain())
 	if servercfg.DeployedByOperator() {
-		return invite.BodyBuilder.
-			WithParagraph("Hi there,").
-			WithParagraph("<br>").
-			WithParagraph("Great news! Your colleague has invited you to join their Netmaker SaaS Tenant.").
-			WithParagraph("Click the button to accept your invitation:").
-			WithParagraph("<br>").
-			WithParagraph(fmt.Sprintf("<a class=\"x-button\" href=\"%s\">Accept Invitation</a>", invite.InviteURL)).
-			WithParagraph("<br>").
-			WithParagraph("Why you'll love Netmaker:").
-			WithParagraph("<ul>").
-			WithParagraph("<li>Blazing-fast connections with our WireGuard®-powered mesh VPN</li>").
-			WithParagraph("<li>Seamless multi-cloud and hybrid-cloud networking</li>").
-			WithParagraph("<li>Automated Kubernetes networking across any infrastructure</li>").
-			WithParagraph("<li>Enterprise-grade security with simple management</li>").
-			WithParagraph("</ul>").
-			WithParagraph("Got questions? Our team is here to help you every step of the way.").
-			WithParagraph("<br>").
-			WithParagraph("Welcome aboard,").
-			WithParagraph("<h2>The Netmaker Team</h2>").
-			WithParagraph("P.S. Curious to learn more before accepting? Check out our quick start tutorial at <a href=\"https://netmaker.io/tutorials\">netmaker.io/tutorials</a>").
-			Build()
+		dashboardURL = fmt.Sprintf("%s/dashboard?tenant_id=%s", proLogic.GetAccountsUIHost(), servercfg.GetNetmakerTenantID())
+	}
+
+	content := invite.BodyBuilder.
+		WithParagraph("Hi,").
+		WithParagraph("You've been invited to access a secure network via Netmaker's Remote Access Client (RAC). Follow these simple steps to get connected:").
+		WithHtml("<ol>").
+		WithHtml(fmt.Sprintf("<li>Click <a href=\"%s\">here</a> to accept your invitation and setup your account.</li>", invite.InviteURL)).
+		WithHtml("<br>").
+		WithHtml(fmt.Sprintf("<li><a href=\"%s\">Download the Remote Access Client (RAC)</a>.</li>", downloadLink))
+
+	if invite.PlatformRoleID == models.AdminRole.String() || invite.PlatformRoleID == models.PlatformUser.String() {
+		content = content.
+			WithHtml("<br>").
+			WithHtml(fmt.Sprintf("<li>Access the <a href=\"%s\">Netmaker Dashboard</a> - use it to manage your network settings and view network status.</li>", dashboardURL))
+	}
+
+	connectionID := servercfg.GetNetmakerTenantID()
+	if !servercfg.DeployedByOperator() {
+		connectionID = fmt.Sprintf("api.%s", servercfg.GetNmBaseDomain())
 	}
 
-	return invite.BodyBuilder.
-		WithParagraph("Hi there,").
-		WithParagraph("<br>").
-		WithParagraph("Great news! Your colleague has invited you to join their Netmaker network.").
-		WithParagraph("Click the button to accept your invitation:").
-		WithParagraph("<br>").
-		WithParagraph(fmt.Sprintf("<a class=\"x-button\" href=\"%s\">Accept Invitation</a>", invite.InviteURL)).
-		WithParagraph("<br>").
-		WithParagraph("Why you'll love Netmaker:").
-		WithParagraph("<ul>").
-		WithParagraph("<li>Blazing-fast connections with our WireGuard®-powered mesh VPN</li>").
-		WithParagraph("<li>Seamless multi-cloud and hybrid-cloud networking</li>").
-		WithParagraph("<li>Automated Kubernetes networking across any infrastructure</li>").
-		WithParagraph("<li>Enterprise-grade security with simple management</li>").
-		WithParagraph("</ul>").
-		WithParagraph("Got questions? Our team is here to help you every step of the way.").
-		WithParagraph("<br>").
-		WithParagraph("Welcome aboard,").
-		WithParagraph("<h2>The Netmaker Team</h2>").
-		WithParagraph("P.S. Curious to learn more before accepting? Check out our quick start tutorial at <a href=\"https://netmaker.io/tutorials\">netmaker.io/tutorials</a>").
+	return content.
+		WithHtml("</ol>").
+		WithParagraph("Important Information:").
+		WithHtml("<ul>").
+		WithHtml(fmt.Sprintf("<li>When connecting through RAC, please enter your server connection ID: %s.</li>", connectionID)).
+		WithHtml("</ul>").
+		WithParagraph(fmt.Sprintf("If you have any questions or need assistance, please contact our support team at <a href=\"mailto:%s\">%s</a>.", supportEmail, supportEmail)).
+		WithParagraph("Best Regards,").
+		WithParagraph("The Netmaker Team").
 		Build()
 }

+ 129 - 521
pro/email/utils.go

@@ -4,27 +4,20 @@ import "strings"
 
 // mail related images hosted on github
 var (
-	nLogoTeal        = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/N_Teal.png"
 	netmakerLogoTeal = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/netmaker-logo-2.png"
-	netmakerMeshLogo = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/netmaker-mesh.png"
-	linkedinIcon     = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/linkedin2x.png"
-	discordIcon      = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/discord-logo-png-7617.png"
-	githubIcon       = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/Octocat.png"
-	mailIcon         = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/icons8-mail-24.png"
-	addressIcon      = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/icons8-address-16.png"
-	linkIcon         = "https://raw.githubusercontent.com/gravitl/netmaker/netmaker_logos/img/logos/icons8-hyperlink-64.png"
 )
 
 type EmailBodyBuilder interface {
 	WithHeadline(text string) EmailBodyBuilder
 	WithParagraph(text string) EmailBodyBuilder
+	WithHtml(text string) EmailBodyBuilder
 	WithSignature() EmailBodyBuilder
 	Build() string
 }
 
 type EmailBodyBuilderWithH1HeadlineAndImage struct {
 	headline     string
-	paragraphs   []string
+	bodyContent  []string
 	hasSignature bool
 }
 
@@ -34,7 +27,12 @@ func (b *EmailBodyBuilderWithH1HeadlineAndImage) WithHeadline(text string) Email
 }
 
 func (b *EmailBodyBuilderWithH1HeadlineAndImage) WithParagraph(text string) EmailBodyBuilder {
-	b.paragraphs = append(b.paragraphs, text)
+	b.bodyContent = append(b.bodyContent, styledParagraph(text))
+	return b
+}
+
+func (b *EmailBodyBuilderWithH1HeadlineAndImage) WithHtml(text string) EmailBodyBuilder {
+	b.bodyContent = append(b.bodyContent, text)
 	return b
 }
 
@@ -44,524 +42,134 @@ func (b *EmailBodyBuilderWithH1HeadlineAndImage) WithSignature() EmailBodyBuilde
 }
 
 func (b *EmailBodyBuilderWithH1HeadlineAndImage) Build() string {
-	// map paragraphs to styled paragraphs
-	styledParagraphsSlice := make([]string, len(b.paragraphs))
-	for i, paragraph := range b.paragraphs {
-		styledParagraphsSlice[i] = styledParagraph(paragraph)
-	}
-	// join styled paragraphs
-	styledParagraphsString := strings.Join(styledParagraphsSlice, "")
+	bodyContent := strings.Join(b.bodyContent, "")
 
-	signature := ""
-	if b.hasSignature {
-		signature = styledSignature()
-	}
+	// TODO: Edit design to add signature.
+	//signature := ""
+	//if b.hasSignature {
+	//	signature = styledSignature()
+	//}
 
 	return `
-		<!DOCTYPE html>
-		<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" lang="en">
-		<head>
-		    <title></title>
-		    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-		    <meta name="viewport" content="width=device-width,initial-scale=1">
-		    <!--[if mso]>
-		    <xml>
-		        <o:OfficeDocumentSettings>
-		            <o:PixelsPerInch>96</o:PixelsPerInch>
-		            <o:AllowPNG/>
-		        </o:OfficeDocumentSettings>
-		    </xml>
-		    <![endif]-->
-		    <style>
-		        *{box-sizing:border-box}body{margin:0;padding:0}a[x-apple-data-detectors]{color:inherit!important;text-decoration:inherit!important}#MessageViewBody a{color:inherit;text-decoration:none}p{line-height:inherit}.desktop_hide,.desktop_hide table{mso-hide:all;display:none;max-height:0;overflow:hidden}@media (max-width:720px){.desktop_hide table.icons-inner{display:inline-block!important}.icons-inner{text-align:center}.icons-inner td{margin:0 auto}.image_block img.big,.row-content{width:100%!important}.mobile_hide{display:none}.stack .column{width:100%;display:block}.mobile_hide{min-height:0;max-height:0;max-width:0;overflow:hidden;font-size:0}.desktop_hide,.desktop_hide table{display:table!important;max-height:none!important}} .x-button{background:#5E5DF0;border-radius:999px;box-shadow:#5E5DF0 0 10px 20px -10px;box-sizing:border-box;color:#FFFFFF !important;cursor:pointer;font-family:Inter,Helvetica,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Noto Color Emoji","Segoe UI Symbol","Android Emoji",EmojiSymbols,-apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans",sans-serif;font-size:16px;font-weight:700;line-height:24px;opacity:1;outline:0 solid transparent;padding:8px 18px;user-select:none;-webkit-user-select:none;touch-action:manipulation;width:fit-content;word-break:break-word;border:0;margin:20px 20px 20px 0px;text-decoration:none;}
-		    </style>
-		</head>
-		<body style="background-color:transparent;margin:0;padding:0;-webkit-text-size-adjust:none;text-size-adjust:none">
-		<table class="nl-container" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;background-color:transparent">
-		    <tbody>
-		    <tr>
-		        <td>
-		            <table class="row row-1" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="50%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="image_block block-2" width="100%" border="0" cellpadding="0" cellspacing="0"
-		                                           role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad" style="padding-left:15px;padding-right:15px;width:100%;padding-top:5px">
-		                                                <div class="alignment" align="left" style="line-height:10px"><a href="https://www.netmaker.io/" target="_blank" style="outline:none" tabindex="-1"><img class="big" src="` + netmakerLogoTeal + `"
-		                                                                                                                                                                                                        style="display:block;height:auto;border:0;width:333px;max-width:100%" width="333" alt="Netmaker" title="Netmaker"></a></div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                    <table class="divider_block block-3" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad" style="padding-bottom:10px;padding-left:5px;padding-right:5px;padding-top:10px">
-		                                                <div class="alignment" align="center">
-		                                                    <table border="0" cellpadding="0" cellspacing="0"
-		                                                           role="presentation" width="100%" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                        <tr>
-		                                                            <td class="divider_inner" style="font-size:1px;line-height:1px;border-top:0 solid #bbb"><span>&#8202;</span></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                                <td class="column column-2" width="50%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="empty_block block-2" width="100%" border="0"
-		                                           cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad" style="padding-right:0;padding-bottom:5px;padding-left:0;padding-top:5px">
-		                                                <div></div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table class="row row-2" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content stack" align="center"
-		                               border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;padding-left:10px;padding-right:10px;vertical-align:top;padding-top:10px;padding-bottom:10px;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="divider_block block-1" width="100%" border="0"
-		                                           cellpadding="10" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad">
-		                                                <div class="alignment" align="center">
-		                                                    <table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                        <tr>
-		                                                            <td class="divider_inner" style="font-size:1px;line-height:1px;border-top:0 solid #bbb"><span>&#8202;</span></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table
-		                    class="row row-3" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="50%"
-		                                    style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="divider_block block-2" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad" style="padding-bottom:20px;padding-left:20px;padding-right:20px;padding-top:25px">
-		                                                <div class="alignment" align="center">
-		                                                    <table border="0" cellpadding="0"
-		                                                           cellspacing="0" role="presentation" width="100%" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                        <tr>
-		                                                            <td class="divider_inner" style="font-size:1px;line-height:1px;border-top:0 solid #bbb"><span>&#8202;</span></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                    <table class="heading_block block-3" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad"
-		                                                style="padding-bottom:15px;padding-left:10px;padding-right:10px;padding-top:10px;text-align:center;width:100%">
-		                                                <h1 style="margin:0;color:#2b2d2d;direction:ltr;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:28px;font-weight:400;letter-spacing:normal;line-height:120%;text-align:left;margin-top:0;margin-bottom:0"><strong>` + b.headline + `</strong></h1>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                                <td class="column column-2" width="50%"
-		                                    style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="image_block block-2" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad" style="width:100%;padding-right:0;padding-left:0;padding-top:5px;padding-bottom:5px">
-		                                                <div class="alignment" align="center" style="line-height:10px"><img
-		                                                        src="` + netmakerMeshLogo + `" style="display:block;height:auto;border:0;width:350px;max-width:100%" width="350" alt="Netmaker Mesh"></div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table class="row row-4" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
-		                   style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;padding-top:5px;padding-bottom:5px;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="divider_block block-1" width="100%" border="0" cellpadding="10" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad">
-		                                                <div class="alignment" align="center">
-		                                                    <table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                        <tr>
-		                                                            <td class="divider_inner" style="font-size:1px;line-height:1px;border-top:0 solid #bbb"><span>&#8202;</span></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table class="row row-5" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
-		                               style="mso-table-lspace:0;mso-table-rspace:0;background-color:#0098a5;color:#000;border-top:2px solid transparent;border-right:2px solid transparent;border-left:2px solid transparent;border-bottom:2px solid transparent;border-radius:0;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%"
-		                                    style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;border-bottom:0 solid #000;border-left:0 solid #000;border-right:0 solid #000;border-top:0 solid #000;vertical-align:top;padding-top:25px;padding-bottom:25px">
-		                                    <table class="text_block block-3" width="100%" border="0"
-		                                           cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;word-break:break-word">
-		                                        <tr>
-		                                            <td class="pad" style="padding-bottom:10px;padding-left:50px;padding-right:50px;padding-top:10px">
-		                                                <div style="font-family:Verdana,sans-serif">
-		                                                    <div class="txtTinyMce-wrapper" style="font-size:12px;mso-line-height-alt:18px;color:#393d47;line-height:1.5;font-family:Verdana,Geneva,sans-serif">
-		
-		                                                        <p style="margin:0;font-size:12px;mso-line-height-alt:18px">&nbsp;</p>
-		                                                        ` + styledParagraphsString + `
-		                                                        <p style="margin:0;mso-line-height-alt:18px">&nbsp;</p>
-		                                                    </div>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table class="row row-6" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table
-		                                class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;padding-top:5px;padding-bottom:5px;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="divider_block block-1" width="100%" border="0"
-		                                           cellpadding="10" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad">
-		                                                <div class="alignment" align="center">
-		                                                    <table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                        <tr>
-		                                                            <td class="divider_inner" style="font-size:1px;line-height:1px;border-top:0 solid #bbb"><span>&#8202;</span></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table
-		                    class="row row-7" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;background-color:#f7fafe">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%"
-		                                    style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;padding-top:25px;padding-bottom:5px;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="divider_block block-1" width="100%" border="0" cellpadding="10" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad">
-		                                                <div class="alignment" align="center">
-		                                                    <table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%"
-		                                                           style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                        <tr>
-		                                                            <td class="divider_inner" style="font-size:1px;line-height:1px;border-top:0 solid #bbb"><span>&#8202;</span></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table class="row row-8" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;background-color:#090660">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table class="row-content stack"
-		                               align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;padding-top:5px;padding-bottom:5px;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="text_block block-1" width="100%" border="0" cellpadding="0" cellspacing="0"
-		                                           role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;word-break:break-word">
-		                                        <tr>
-		                                            <td class="pad" style="padding-bottom:10px;padding-left:50px;padding-right:50px;padding-top:10px">
-		                                                <div style="font-family:sans-serif">
-		                                                    <div class="txtTinyMce-wrapper" style="font-size:12px;mso-line-height-alt:18px;color:#6f7077;line-height:1.5;font-family:Arial,Helvetica Neue,Helvetica,sans-serif">
-		                                                        <p style="margin:0;font-size:12px;mso-line-height-alt:33px">
-		                                                            <span style="color:#ffffff;font-size:22px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Get In Touch With Us</span>
-		                                                        </p>
-		                                                    </div>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                    <table class="social_block block-2" width="100%" border="0" cellpadding="10" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad">
-		                                                <div class="alignment" style="text-align:center">
-		                                                    <table class="social-table"
-		                                                           width="114.49624060150376px" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;display:inline-block">
-		                                                        <tr>
-		                                                            <td style="padding:0 2px 0 2px"><a href="https://www.linkedin.com/company/netmaker-inc/" target="_blank"><img src="` + linkedinIcon + `" width="32" height="32" alt="Linkedin" title="linkedin" style="display:block;height:auto;border:0"></a></td>
-		                                                            <td
-		                                                                    style="padding:0 2px 0 2px"><a href="https://discord.gg/zRb9Vfhk8A" target="_blank"><img src="` + discordIcon + `" width="32" height="32" alt="Discord" title="Discord" style="display:block;height:auto;border:0"></a></td>
-		                                                            <td style="padding:0 2px 0 2px"><a href="https://github.com/gravitl/netmaker" target="_blank"><img
-		                                                                    src="` + githubIcon + `" width="38.49624060150376" height="32" alt="Github" title="Github" style="display:block;height:auto;border:0"></a></td>
-		                                                        </tr>
-		                                                    </table>
-		                                                </div>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		            <table class="row row-9" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                <tbody>
-		                <tr>
-		                    <td>
-		                        <table
-		                                class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0;color:#000;width:700px" width="700">
-		                            <tbody>
-		                            <tr>
-		                                <td class="column column-1" width="100%" style="mso-table-lspace:0;mso-table-rspace:0;font-weight:400;text-align:left;vertical-align:top;padding-top:5px;padding-bottom:5px;border-top:0;border-right:0;border-bottom:0;border-left:0">
-		                                    <table class="icons_block block-1" width="100%" border="0"
-		                                           cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                        <tr>
-		                                            <td class="pad" style="vertical-align:middle;padding-bottom:5px;padding-top:5px;text-align:center;color:#9d9d9d;font-family:inherit;font-size:15px">
-		                                                <table width="100%" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0;mso-table-rspace:0">
-		                                                    <tr>
-		                                                        <td class="alignment" style="vertical-align:middle;text-align:center">
-		                                                            <!--[if vml]>
-		                                                            <table align="left" cellpadding="0" cellspacing="0" role="presentation" style="display:inline-block;padding-left:0px;padding-right:0px;mso-table-lspace: 0pt;mso-table-rspace: 0pt;">
-		                                                            <![endif]--><!--[if !vml]><!-->
-		                                                            <table class="icons-inner" style="mso-table-lspace:0;mso-table-rspace:0;display:inline-block;margin-right:-4px;padding-left:0;padding-right:0" cellpadding="0" cellspacing="0" role="presentation">
-		                                                                <!--<![endif]-->
-		                                                            </table>
-		                                                        </td></tr>
-		                                                </table>
-		                                            </td>
-		                                        </tr>
-		                                    </table>
-		                                </td>
-		                            </tr>
-		                            </tbody>
-		                        </table>
-		                    </td>
-		                </tr>
-		                </tbody>
-		            </table>
-		        </td>
-		    </tr>
-		    </tbody>
-		</table>
-		<!-- End -->
-		</body>
-		` + signature + `
-		</html>`
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>Simple Transactional Email</title>
+    <style media="all" type="text/css">
+@media all {
+  .btn-primary table td:hover {
+    background-color: #ec0867 !important;
+  }
+
+  .btn-primary a:hover {
+    background-color: #ec0867 !important;
+    border-color: #ec0867 !important;
+  }
 }
+@media only screen and (max-width: 640px) {
+  .main p,
+.main td,
+.main span {
+    font-size: 16px !important;
+  }
 
-func styledSignature() string {
-	return `
-	<footer style="display:block">
-	<table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-	<tbody>
-	   <tr>
-		  <td>
-			 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-				<tbody>
-				   <tr>
-					  <td style="vertical-align: top;">
-						 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-							<tbody>
-							   <tr>
-								  <td class="sc-TOsTZ kjYrri" style="text-align: center;"><img src="` + nLogoTeal + `" role="presentation" width="130" class="sc-cHGsZl bHiaRe" style="max-width: 130px; display: block;"></td>
-							   </tr>
-							   <tr>
-								  <td height="30"></td>
-							   </tr>
-							   <tr>
-								  <td style="text-align: center;">
-									 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial; display: inline-block;">
-										<tbody>
-										   <tr style="text-align: center;">
-											  <td><a href="https://www.linkedin.com/company/netmaker-inc/" color="#6a78d1" class="sc-hzDkRC kpsoyz" style="display: inline-block; padding: 0px; background-color: rgb(106, 120, 209);"><img src="` + linkedinIcon + `" alt="Linkedin" color="#6a78d1" height="24" class="sc-bRBYWo ccSRck" style="background-color: rgb(106, 120, 209); max-width: 135px; display: block;"></a></td>
-											  <td width="5">
-												 <div></div>
-											  </td>
-										 
-                                    <td><a href="https://discord.gg/zRb9Vfhk8A" class="sc-hzDkRC kpsoyz" style="display: inline-block; padding: 0px;"><img src="` + discordIcon + `" alt="Discord" height="24" class="sc-bRBYWo ccSRck" style="max-width: 135px; display: block;"></a></td>
-                                    <td width="5">
-                                    <div></div>
-                                    </td>
-                              
-                                    <td><a href="https://github.com/gravitl/netmaker" class="sc-hzDkRC kpsoyz" style="display: inline-block; padding: 0px;"><img src="` + githubIcon + `" alt="Github" height="24" class="sc-bRBYWo ccSRck" style="max-width: 135px; display: block;"></a></td>
-                                    <td width="5">
-                                    <div></div>
-                                    </td>
-                                 </tr>
-										</tbody>
-									 </table>
-								  </td>
-							   </tr>
-							</tbody>
-						 </table>
-					  </td>
-					  <td width="46">
-						 <div></div>
-					  </td>
-					  <td style="padding: 0px; vertical-align: middle;">
-						 <h3 color="#000000" class="sc-fBuWsC eeihxG" style="margin: 0px; font-size: 18px; color: rgb(0, 0, 0);"><span>Alex</span><span>&nbsp;</span><span>Feiszli</span></h3>
-						 <p color="#000000" font-size="medium" class="sc-fMiknA bxZCMx" style="margin: 0px; color: rgb(0, 0, 0); font-size: 14px; line-height: 22px;"><span>Co-Founder &amp; CEO</span></p>
-						 <p color="#000000" font-size="medium" class="sc-dVhcbM fghLuF" style="margin: 0px; font-weight: 500; color: rgb(0, 0, 0); font-size: 14px; line-height: 22px;"><span>Netmaker</span></p>
-						 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial; width: 100%;">
-							<tbody>
-							   <tr>
-								  <td height="30"></td>
-							   </tr>
-							   <tr>
-								  <td color="#545af2" direction="horizontal" height="1" class="sc-jhAzac hmXDXQ" style="width: 100%; border-bottom: 1px solid rgb(84, 90, 242); border-left: none; display: block;"></td>
-							   </tr>
-							   <tr>
-								  <td height="30"></td>
-							   </tr>
-							</tbody>
-						 </table>
-						 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-							<tbody>
-							   <tr height="25" style="vertical-align: middle;">
-								  <td width="30" style="vertical-align: middle;">
-									 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-										<tbody>
-										   <tr>
-											  <td style="vertical-align: bottom;"><span width="11" class="sc-jlyJG bbyJzT" style="display: block"><img src="` + mailIcon + `" width="13" class="sc-iRbamj blSEcj" style="display: block;"></span></td>
-										   </tr>
-										</tbody>
-									 </table>
-								  </td>
-								  <td style="padding: 0px;"><a href="mailto:[email protected]" color="#000000" class="sc-gipzik iyhjGb" style="text-decoration: none; color: rgb(0, 0, 0); font-size: 12px;"><span>[email protected]</span></a></td>
-							   </tr>
-							   <tr height="25" style="vertical-align: middle;">
-								  <td width="30" style="vertical-align: middle;">
-									 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-										<tbody>
-										   <tr>
-											  <td style="vertical-align: bottom;"><span width="11" class="sc-jlyJG bbyJzT" style="display: block;"><img src="` + linkIcon + `" color="#545af2" width="13" class="sc-iRbamj blSEcj" style="display: block;"></span></td>
-										   </tr>
-										</tbody>
-									 </table>
-								  </td>
-								  <td style="padding: 0px;"><a href="https://www.netmaker.io/" color="#000000" class="sc-gipzik iyhjGb" style="text-decoration: none; color: rgb(0, 0, 0); font-size: 12px;"><span>https://www.netmaker.io/</span></a></td>
-							   </tr>
-							   <tr height="25" style="vertical-align: middle;">
-								  <td width="30" style="vertical-align: middle;">
-									 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-										<tbody>
-										   <tr>
-											  <td style="vertical-align: bottom;"><span width="11" class="sc-jlyJG bbyJzT" style="display: block;"><img src="` + addressIcon + `"  width="13" class="sc-iRbamj blSEcj" style="display: block;"></span></td>
-										   </tr>
-										</tbody>
-									 </table>
-								  </td>
-								  <td style="padding: 0px;"><span color="#000000" class="sc-csuQGl CQhxV" style="font-size: 12px; color: rgb(0, 0, 0);"><span>1465 Sand Hill Rd.Suite 2014, Candler, NC 28715</span></span></td>
-							   </tr>
-							</tbody>
-						 </table>
-						 <table cellpadding="0" cellspacing="0" class="sc-gPEVay eQYmiW" style="vertical-align: -webkit-baseline-middle; font-size: medium; font-family: Arial;">
-							<tbody>
-							   <tr>
-								  <td height="30"></td>
-							   </tr>
-							</tbody>
-						 </table>
-					  </td>
-				   </tr>
-				</tbody>
-			 </table>
-		  </td>
-	   </tr>
-	</tbody>
- </table>
-</footer>`
+  .wrapper {
+    padding: 8px !important;
+  }
+
+  .content {
+    padding: 0 !important;
+  }
+
+  .container {
+    padding: 0 !important;
+    padding-top: 8px !important;
+    width: 100% !important;
+  }
+
+  .main {
+    border-left-width: 0 !important;
+    border-radius: 0 !important;
+    border-right-width: 0 !important;
+  }
+
+  .btn table {
+    max-width: 100% !important;
+    width: 100% !important;
+  }
+
+  .btn a {
+    font-size: 16px !important;
+    max-width: 100% !important;
+    width: 100% !important;
+  }
 }
+@media all {
+  .ExternalClass {
+    width: 100%;
+  }
 
-func styledParagraph(text string) string {
-	return `<p style="margin:0;mso-line-height-alt:22.5px">
-	<span style="color:#ffffff;font-size:15px;">` + text + `</span>
-	</p>`
+  .ExternalClass,
+.ExternalClass p,
+.ExternalClass span,
+.ExternalClass font,
+.ExternalClass td,
+.ExternalClass div {
+    line-height: 100%;
+  }
+
+  .apple-link a {
+    color: inherit !important;
+    font-family: inherit !important;
+    font-size: inherit !important;
+    font-weight: inherit !important;
+    line-height: inherit !important;
+    text-decoration: none !important;
+  }
+
+  #MessageViewBody a {
+    color: inherit;
+    text-decoration: none;
+    font-size: inherit;
+    font-family: inherit;
+    font-weight: inherit;
+    line-height: inherit;
+  }
 }
+</style>
+  </head>
+  <body style="font-family: Helvetica, sans-serif; -webkit-font-smoothing: antialiased; font-size: 16px; line-height: 1.3; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; background-color: #f4f5f6; margin: 0; padding: 0;">
+    <table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f4f5f6; width: 100%;" width="100%" bgcolor="#f4f5f6">
+      <tr>
+        <td style="font-family: Helvetica, sans-serif; font-size: 16px; vertical-align: top;" valign="top">&nbsp;</td>
+        <td class="container" style="font-family: Helvetica, sans-serif; font-size: 16px; vertical-align: top; max-width: 600px; padding: 24px 0px 24px 0px; width: 600px; margin: 0 auto;" width="600" valign="top">
+          <div class="content" style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 600px; padding: 0;">
+
+            <!-- START CENTERED WHITE CONTAINER -->
+            <table role="presentation" border="0" cellpadding="0" cellspacing="0" class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background: #ffffff; border: 1px solid #eaebed; border-radius: 16px; width: 100%;" width="100%">
+
+              <!-- START MAIN CONTENT AREA -->
+              <tr>
+                <td class="wrapper" style="font-family: Helvetica, sans-serif; font-size: 16px; vertical-align: top; box-sizing: border-box; padding: 24px;" valign="top">
+                  <img src="` + netmakerLogoTeal + `" alt="Netmaker Logo" width="200" height="100" border="0" style="border:0; outline:none; text-decoration:none; display:block; margin-left: auto;">
+                  ` + bodyContent + `
+                </td>
+              </tr>
 
-func GetMailSignature() string {
-	return styledSignature()
+              <!-- END MAIN CONTENT AREA -->
+              </table>
+
+<!-- END CENTERED WHITE CONTAINER --></div>
+        </td>
+        <td style="font-family: Helvetica, sans-serif; font-size: 16px; vertical-align: top;" valign="top">&nbsp;</td>
+      </tr>
+    </table>
+  </body>
+</html>`
+}
+
+func styledParagraph(text string) string {
+	return `<p style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">` + text + `</p>`
 }

+ 2 - 0
scripts/netmaker.default.env

@@ -90,4 +90,6 @@ EMAIL_SENDER_PASSWORD=
 PEER_UPDATE_BATCH=true
 # batch peer update size when PEER_UPDATE_BATCH is enabled
 PEER_UPDATE_BATCH_SIZE=50
+# default domain for internal DNS lookup
+DEFAULT_DOMAIN=netmaker.hosted
 

+ 37 - 1
servercfg/serverconf.go

@@ -5,13 +5,14 @@ import (
 	"io"
 	"net/http"
 	"os"
+	"regexp"
 	"strconv"
 	"strings"
 	"time"
 
 	"github.com/gravitl/netmaker/config"
-
 	"github.com/gravitl/netmaker/models"
+	"golang.org/x/exp/slog"
 )
 
 // EmqxBrokerType denotes the broker type for EMQX MQTT
@@ -92,6 +93,8 @@ func GetServerConfig() config.ServerConfig {
 	cfg.JwtValidityDuration = GetJwtValidityDuration()
 	cfg.RacAutoDisable = GetRacAutoDisable()
 	cfg.MetricInterval = GetMetricInterval()
+	cfg.ManageDNS = GetManageDNS()
+	cfg.DefaultDomain = GetDefaultDomain()
 	return cfg
 }
 
@@ -136,6 +139,8 @@ func GetServerInfo() models.ServerConfig {
 	cfg.Version = GetVersion()
 	cfg.IsPro = IsPro
 	cfg.MetricInterval = GetMetricInterval()
+	cfg.ManageDNS = GetManageDNS()
+	cfg.DefaultDomain = GetDefaultDomain()
 	return cfg
 }
 
@@ -650,6 +655,37 @@ func GetMetricInterval() string {
 	return mi
 }
 
+// GetManageDNS - if manage DNS enabled or not
+func GetManageDNS() bool {
+	enabled := true
+	if os.Getenv("MANAGE_DNS") != "" {
+		enabled = os.Getenv("MANAGE_DNS") == "true"
+	}
+	return enabled
+}
+
+// GetDefaultDomain - get the default domain
+func GetDefaultDomain() string {
+	//default netmaker.hosted
+	domain := "netmaker.hosted"
+	if os.Getenv("DEFAULT_DOMAIN") != "" {
+		if validateDomain(os.Getenv("DEFAULT_DOMAIN")) {
+			domain = os.Getenv("DEFAULT_DOMAIN")
+		} else {
+			slog.Warn("invalid value, set to default domain: netmaker.hosted", "warn", os.Getenv("DEFAULT_DOMAIN"))
+		}
+	}
+	return domain
+}
+
+func validateDomain(domain string) bool {
+	domainPattern := `[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,62})*(\.[a-zA-Z][a-zA-Z0-9]{0,10}){1}`
+
+	exp := regexp.MustCompile("^" + domainPattern + "$")
+
+	return exp.MatchString(domain)
+}
+
 // GetBatchPeerUpdate - if batch peer update
 func GetBatchPeerUpdate() bool {
 	enabled := true

+ 29 - 0
servercfg/serverconf_test.go

@@ -0,0 +1,29 @@
+package servercfg
+
+import (
+	"testing"
+
+	"github.com/matryer/is"
+)
+
+func TestValidateDomain(t *testing.T) {
+
+	t.Run("", func(t *testing.T) {
+		is := is.New(t)
+		valid := validateDomain("netmaker.hosted")
+		is.Equal(valid, true)
+	})
+
+	t.Run("", func(t *testing.T) {
+		is := is.New(t)
+		valid := validateDomain("ipv4test1.hosted")
+		is.Equal(valid, true)
+	})
+
+	t.Run("", func(t *testing.T) {
+		is := is.New(t)
+		valid := validateDomain("ip_4?")
+		is.Equal(valid, false)
+	})
+
+}

+ 1 - 1
swagger.yaml

@@ -3098,7 +3098,7 @@ tags:
 
     Note: While a MasterKey exists (configurable via env var or config file), it should be considered a backup option, used only when server access is lost. By default, this key is "secret key," but it's crucial to change this and keep it secure in your instance.
 
-    For more information on configuration and security best practices, refer to the [Netmaker documentation](https://docs.netmaker.org/index.html).
+    For more information on configuration and security best practices, refer to the [Netmaker documentation](https://docs.netmaker.io/).
   name: Authentication
 - description: |
     Check out our [Pricing](https://www.netmaker.io/pricing). And Feel Free to [Contact Us](https://www.netmaker.io/contact) if you have any questions or need some clarifications.