Browse Source

NET-1064: Improved Oauth SignUp message prompts (#2875)

* add pending users api

* insert user to pending users on first time oauth login

* add pending user check on headless login

* fix conflicting apis

* no records error

* add allowed emails domains for oauth singup to config

* check if user is allowed to signup

* improve oauth message prompts

* handle trial enddate  error logs
Abhishek K 1 year ago
parent
commit
b7c8b738d7
8 changed files with 47 additions and 30 deletions
  1. 2 2
      auth/azure-ad.go
  2. 30 5
      auth/error.go
  3. 2 2
      auth/github.go
  4. 2 2
      auth/google.go
  5. 2 2
      auth/oidc.go
  6. 7 15
      logic/telemetry.go
  7. 1 1
      migrate/migrate.go
  8. 1 1
      pro/trial.go

+ 2 - 2
auth/azure-ad.go

@@ -67,7 +67,7 @@ func handleAzureCallback(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	// check if user approval is already pending
 	// check if user approval is already pending
 	if logic.IsPendingUser(content.UserPrincipalName) {
 	if logic.IsPendingUser(content.UserPrincipalName) {
-		handleOauthUserNotAllowed(w)
+		handleOauthUserSignUpApprovalPending(w)
 		return
 		return
 	}
 	}
 	_, err = logic.GetUser(content.UserPrincipalName)
 	_, err = logic.GetUser(content.UserPrincipalName)
@@ -80,7 +80,7 @@ func handleAzureCallback(w http.ResponseWriter, r *http.Request) {
 				handleSomethingWentWrong(w)
 				handleSomethingWentWrong(w)
 				return
 				return
 			}
 			}
-			handleOauthUserNotAllowed(w)
+			handleFirstTimeOauthUserSignUp(w)
 			return
 			return
 		} else {
 		} else {
 			handleSomethingWentWrong(w)
 			handleSomethingWentWrong(w)

+ 30 - 5
auth/error.go

@@ -12,12 +12,26 @@ const oauthNotConfigured = `<!DOCTYPE html><html>
 
 
 const userNotAllowed = `<!DOCTYPE html><html>
 const userNotAllowed = `<!DOCTYPE html><html>
 <body>
 <body>
-<h3>Only Admins are allowed to access Dashboard.</h3>
-<h3>Furthermore, Admin has to approve your identity to have access to netmaker networks</h3>
-<p>Once your identity is approved, Non-Admins can access the netmaker networks using <a href="https://docs.netmaker.io/pro/rac.html" target="_blank" rel="noopener">RemoteAccessClient.</a></p>
+<h3>Only administrators can access the Dashboard. Please contact your administrator to elevate your account.</h3>
+<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>
 </body>
 </body>
 </html>
 </html>
 `
 `
+
+const userFirstTimeSignUp = `<!DOCTYPE html><html>
+<body>
+<h3>Thank you for signing up. Please contact your administrator for access.</h3>
+</body>
+</html>
+`
+
+const userSignUpApprovalPending = `<!DOCTYPE html><html>
+<body>
+<h3>Your account is yet to be approved. Please contact your administrator for access.</h3>
+</body>
+</html>
+`
+
 const userNotFound = `<!DOCTYPE html><html>
 const userNotFound = `<!DOCTYPE html><html>
 <body>
 <body>
 <h3>User Not Found.</h3>
 <h3>User Not Found.</h3>
@@ -26,13 +40,13 @@ const userNotFound = `<!DOCTYPE html><html>
 
 
 const somethingwentwrong = `<!DOCTYPE html><html>
 const somethingwentwrong = `<!DOCTYPE html><html>
 <body>
 <body>
-<h3>Something went wrong. Contact Admin</h3>
+<h3>Something went wrong. Contact Admin.</h3>
 </body>
 </body>
 </html>`
 </html>`
 
 
 const notallowedtosignup = `<!DOCTYPE html><html>
 const notallowedtosignup = `<!DOCTYPE html><html>
 <body>
 <body>
-<h3>You are not allowed to SignUp.</h3>
+<h3>Your email is not allowed. Please contact your administrator.</h3>
 </body>
 </body>
 </html>`
 </html>`
 
 
@@ -47,6 +61,17 @@ func handleOauthUserNotAllowed(response http.ResponseWriter) {
 	response.WriteHeader(http.StatusForbidden)
 	response.WriteHeader(http.StatusForbidden)
 	response.Write([]byte(userNotAllowed))
 	response.Write([]byte(userNotAllowed))
 }
 }
+func handleFirstTimeOauthUserSignUp(response http.ResponseWriter) {
+	response.Header().Set("Content-Type", "text/html; charset=utf-8")
+	response.WriteHeader(http.StatusForbidden)
+	response.Write([]byte(userFirstTimeSignUp))
+}
+
+func handleOauthUserSignUpApprovalPending(response http.ResponseWriter) {
+	response.Header().Set("Content-Type", "text/html; charset=utf-8")
+	response.WriteHeader(http.StatusForbidden)
+	response.Write([]byte(userSignUpApprovalPending))
+}
 
 
 func handleOauthUserNotAllowedToSignUp(response http.ResponseWriter) {
 func handleOauthUserNotAllowedToSignUp(response http.ResponseWriter) {
 	response.Header().Set("Content-Type", "text/html; charset=utf-8")
 	response.Header().Set("Content-Type", "text/html; charset=utf-8")

+ 2 - 2
auth/github.go

@@ -67,7 +67,7 @@ func handleGithubCallback(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	// check if user approval is already pending
 	// check if user approval is already pending
 	if logic.IsPendingUser(content.Login) {
 	if logic.IsPendingUser(content.Login) {
-		handleOauthUserNotAllowed(w)
+		handleOauthUserSignUpApprovalPending(w)
 		return
 		return
 	}
 	}
 	_, err = logic.GetUser(content.Login)
 	_, err = logic.GetUser(content.Login)
@@ -80,7 +80,7 @@ func handleGithubCallback(w http.ResponseWriter, r *http.Request) {
 				handleSomethingWentWrong(w)
 				handleSomethingWentWrong(w)
 				return
 				return
 			}
 			}
-			handleOauthUserNotAllowed(w)
+			handleFirstTimeOauthUserSignUp(w)
 			return
 			return
 		} else {
 		} else {
 			handleSomethingWentWrong(w)
 			handleSomethingWentWrong(w)

+ 2 - 2
auth/google.go

@@ -69,7 +69,7 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	// check if user approval is already pending
 	// check if user approval is already pending
 	if logic.IsPendingUser(content.Email) {
 	if logic.IsPendingUser(content.Email) {
-		handleOauthUserNotAllowed(w)
+		handleOauthUserSignUpApprovalPending(w)
 		return
 		return
 	}
 	}
 	_, err = logic.GetUser(content.Email)
 	_, err = logic.GetUser(content.Email)
@@ -82,7 +82,7 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 				handleSomethingWentWrong(w)
 				handleSomethingWentWrong(w)
 				return
 				return
 			}
 			}
-			handleOauthUserNotAllowed(w)
+			handleFirstTimeOauthUserSignUp(w)
 			return
 			return
 		} else {
 		} else {
 			handleSomethingWentWrong(w)
 			handleSomethingWentWrong(w)

+ 2 - 2
auth/oidc.go

@@ -80,7 +80,7 @@ func handleOIDCCallback(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	// check if user approval is already pending
 	// check if user approval is already pending
 	if logic.IsPendingUser(content.Email) {
 	if logic.IsPendingUser(content.Email) {
-		handleOauthUserNotAllowed(w)
+		handleOauthUserSignUpApprovalPending(w)
 		return
 		return
 	}
 	}
 	_, err = logic.GetUser(content.Email)
 	_, err = logic.GetUser(content.Email)
@@ -93,7 +93,7 @@ func handleOIDCCallback(w http.ResponseWriter, r *http.Request) {
 				handleSomethingWentWrong(w)
 				handleSomethingWentWrong(w)
 				return
 				return
 			}
 			}
-			handleOauthUserNotAllowed(w)
+			handleFirstTimeOauthUserSignUp(w)
 			return
 			return
 		} else {
 		} else {
 			handleSomethingWentWrong(w)
 			handleSomethingWentWrong(w)

+ 7 - 15
logic/telemetry.go

@@ -39,10 +39,7 @@ func sendTelemetry() error {
 		return err
 		return err
 	}
 	}
 	// get telemetry data
 	// get telemetry data
-	d, err := FetchTelemetryData()
-	if err != nil {
-		slog.Error("error fetching telemetry data", "error", err)
-	}
+	d := FetchTelemetryData()
 	// get tenant admin email
 	// get tenant admin email
 	adminEmail := os.Getenv("NM_EMAIL")
 	adminEmail := os.Getenv("NM_EMAIL")
 	client, err := posthog.NewWithConfig(posthog_pub_key, posthog.Config{Endpoint: posthog_endpoint})
 	client, err := posthog.NewWithConfig(posthog_pub_key, posthog.Config{Endpoint: posthog_endpoint})
@@ -82,7 +79,7 @@ func sendTelemetry() error {
 }
 }
 
 
 // FetchTelemetryData - fetches telemetry data: count of various object types in DB
 // FetchTelemetryData - fetches telemetry data: count of various object types in DB
-func FetchTelemetryData() (telemetryData, error) {
+func FetchTelemetryData() telemetryData {
 	var data telemetryData
 	var data telemetryData
 
 
 	data.IsPro = servercfg.IsPro
 	data.IsPro = servercfg.IsPro
@@ -92,21 +89,16 @@ func FetchTelemetryData() (telemetryData, error) {
 	data.Hosts = getDBLength(database.HOSTS_TABLE_NAME)
 	data.Hosts = getDBLength(database.HOSTS_TABLE_NAME)
 	data.Version = servercfg.GetVersion()
 	data.Version = servercfg.GetVersion()
 	data.Servers = getServerCount()
 	data.Servers = getServerCount()
-	nodes, err := GetAllNodes()
-	if err == nil {
-		data.Nodes = len(nodes)
-		data.Count = getClientCount(nodes)
-	}
-	endDate, err := GetTrialEndDate()
-	if err != nil {
-		logger.Log(0, "error getting trial end date", err.Error())
-	}
+	nodes, _ := GetAllNodes()
+	data.Nodes = len(nodes)
+	data.Count = getClientCount(nodes)
+	endDate, _ := GetTrialEndDate()
 	data.ProTrialEndDate = endDate
 	data.ProTrialEndDate = endDate
 	if endDate.After(time.Now()) {
 	if endDate.After(time.Now()) {
 		data.IsProTrial = true
 		data.IsProTrial = true
 	}
 	}
 	data.IsSaasTenant = servercfg.DeployedByOperator()
 	data.IsSaasTenant = servercfg.DeployedByOperator()
-	return data, err
+	return data
 }
 }
 
 
 // getServerCount returns number of servers from database
 // getServerCount returns number of servers from database

+ 1 - 1
migrate/migrate.go

@@ -177,7 +177,7 @@ func removeInterGw(egressRanges []string) ([]string, bool) {
 func updateAcls() {
 func updateAcls() {
 	// get all networks
 	// get all networks
 	networks, err := logic.GetNetworks()
 	networks, err := logic.GetNetworks()
-	if err != nil {
+	if err != nil && !database.IsEmptyRecord(err) {
 		slog.Error("acls migration failed. error getting networks", "error", err)
 		slog.Error("acls migration failed. error getting networks", "error", err)
 		return
 		return
 	}
 	}

+ 1 - 1
pro/trial.go

@@ -42,7 +42,7 @@ const trial_data_key = "trialdata"
 
 
 // stores trial end date
 // stores trial end date
 func initTrial() error {
 func initTrial() error {
-	telData, _ := logic.FetchTelemetryData()
+	telData := logic.FetchTelemetryData()
 	if telData.Hosts > 0 || telData.Networks > 0 || telData.Users > 0 {
 	if telData.Hosts > 0 || telData.Networks > 0 || telData.Users > 0 {
 		return nil // database is already populated, so skip creating trial
 		return nil // database is already populated, so skip creating trial
 	}
 	}