Browse Source

userHttpController tests complete

Matthew R Kasun 4 years ago
parent
commit
2e5511a0ab
3 changed files with 356 additions and 222 deletions
  1. 110 155
      controllers/userHttpController.go
  2. 189 7
      controllers/userHttpController_test.go
  3. 57 60
      models/structs.go

+ 110 - 155
controllers/userHttpController.go

@@ -36,7 +36,6 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 	//Auth request consists of Mac Address and Password (from node that is authorizing
 	//Auth request consists of Mac Address and Password (from node that is authorizing
 	//in case of Master, auth is ignored and mac is set to "mastermac"
 	//in case of Master, auth is ignored and mac is set to "mastermac"
 	var authRequest models.UserAuthParams
 	var authRequest models.UserAuthParams
-	var result models.User
 	var errorResponse = models.ErrorResponse{
 	var errorResponse = models.ErrorResponse{
 		Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
 		Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
 	}
 	}
@@ -44,74 +43,74 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 	decoder := json.NewDecoder(request.Body)
 	decoder := json.NewDecoder(request.Body)
 	decoderErr := decoder.Decode(&authRequest)
 	decoderErr := decoder.Decode(&authRequest)
 	defer request.Body.Close()
 	defer request.Body.Close()
-
 	if decoderErr != nil {
 	if decoderErr != nil {
 		returnErrorResponse(response, request, errorResponse)
 		returnErrorResponse(response, request, errorResponse)
 		return
 		return
-	} else {
+	}
+
+	jwt, err := VerifyAuthRequest(authRequest)
+	if err != nil {
 		errorResponse.Code = http.StatusBadRequest
 		errorResponse.Code = http.StatusBadRequest
-		if authRequest.UserName == "" {
-			errorResponse.Message = "W1R3: Username can't be empty"
-			returnErrorResponse(response, request, errorResponse)
-			return
-		} else if authRequest.Password == "" {
-			errorResponse.Message = "W1R3: Password can't be empty"
-			returnErrorResponse(response, request, errorResponse)
-			return
-		} else {
-
-			//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
-			collection := mongoconn.Client.Database("netmaker").Collection("users")
-			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-			var err = collection.FindOne(ctx, bson.M{"username": authRequest.UserName}).Decode(&result)
-
-			defer cancel()
-
-			if err != nil {
-				errorResponse.Message = "W1R3: User " + authRequest.UserName + " not found."
-				returnErrorResponse(response, request, errorResponse)
-				return
-			}
-
-			//compare password from request to stored password in database
-			//might be able to have a common hash (certificates?) and compare those so that a password isn't passed in in plain text...
-			//TODO: Consider a way of hashing the password client side before sending, or using certificates
-			err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password))
-			if err != nil {
-				errorResponse = models.ErrorResponse{
-					Code: http.StatusUnauthorized, Message: "W1R3: Wrong Password.",
-				}
-				returnErrorResponse(response, request, errorResponse)
-				return
-			} else {
-				//Create a new JWT for the node
-				tokenString, _ := functions.CreateUserJWT(authRequest.UserName, result.IsAdmin)
-
-				if tokenString == "" {
-					returnErrorResponse(response, request, errorResponse)
-					return
-				}
-
-				var successResponse = models.SuccessResponse{
-					Code:    http.StatusOK,
-					Message: "W1R3: Device " + authRequest.UserName + " Authorized",
-					Response: models.SuccessfulUserLoginResponse{
-						AuthToken: tokenString,
-						UserName:  authRequest.UserName,
-					},
-				}
-				//Send back the JWT
-				successJSONResponse, jsonError := json.Marshal(successResponse)
-
-				if jsonError != nil {
-					returnErrorResponse(response, request, errorResponse)
-					return
-				}
-				response.Header().Set("Content-Type", "application/json")
-				response.Write(successJSONResponse)
-			}
-		}
+		errorResponse.Message = err.Error()
+		returnErrorResponse(response, request, errorResponse)
+	}
+
+	if jwt == "" {
+		returnErrorResponse(response, request, errorResponse)
+		return
+	}
+
+	var successResponse = models.SuccessResponse{
+		Code:    http.StatusOK,
+		Message: "W1R3: Device " + authRequest.UserName + " Authorized",
+		Response: models.SuccessfulUserLoginResponse{
+			AuthToken: jwt,
+			UserName:  authRequest.UserName,
+		},
+	}
+	//Send back the JWT
+	successJSONResponse, jsonError := json.Marshal(successResponse)
+
+	if jsonError != nil {
+		returnErrorResponse(response, request, errorResponse)
+		return
 	}
 	}
+	response.Header().Set("Content-Type", "application/json")
+	response.Write(successJSONResponse)
+}
+
+func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
+	var result models.User
+	if authRequest.UserName == "" {
+		return "", errors.New("Username can't be empty")
+	} else if authRequest.Password == "" {
+		return "", errors.New("Password can't be empty")
+	}
+	//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
+	collection := mongoconn.Client.Database("netmaker").Collection("users")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	var err = collection.FindOne(ctx, bson.M{"username": authRequest.UserName}).Decode(&result)
+
+	defer cancel()
+	if err != nil {
+		return "", errors.New("User " + authRequest.UserName + " not found")
+	}
+	// This is a a useless test as cannot create user that is not an an admin
+	if !result.IsAdmin {
+		return "", errors.New("User is not an admin")
+	}
+
+	//compare password from request to stored password in database
+	//might be able to have a common hash (certificates?) and compare those so that a password isn't passed in in plain text...
+	//TODO: Consider a way of hashing the password client side before sending, or using certificates
+	err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password))
+	if err != nil {
+		return "", errors.New("Wrong Password")
+	}
+
+	//Create a new JWT for the node
+	tokenString, _ := functions.CreateUserJWT(authRequest.UserName, true)
+	return tokenString, nil
 }
 }
 
 
 //The middleware for most requests to the API
 //The middleware for most requests to the API
@@ -132,50 +131,43 @@ func authorizeUser(next http.Handler) http.HandlerFunc {
 
 
 		//get the auth token
 		//get the auth token
 		bearerToken := r.Header.Get("Authorization")
 		bearerToken := r.Header.Get("Authorization")
-
-		var tokenSplit = strings.Split(bearerToken, " ")
-
-		//I put this in in case the user doesn't put in a token at all (in which case it's empty)
-		//There's probably a smarter way of handling this.
-		var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd"
-
-		if len(tokenSplit) > 1 {
-			authToken = tokenSplit[1]
-		} else {
-			errorResponse = models.ErrorResponse{
-				Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
-			}
+		err := ValidateToken(bearerToken)
+		if err != nil {
 			returnErrorResponse(w, r, errorResponse)
 			returnErrorResponse(w, r, errorResponse)
 			return
 			return
 		}
 		}
+		next.ServeHTTP(w, r)
+	}
+}
 
 
-		//This checks if
-		//A: the token is the master password
-		//B: the token corresponds to a mac address, and if so, which one
-		//TODO: There's probably a better way of dealing with the "master token"/master password. Plz Halp.
-		username, _, err := functions.VerifyUserToken(authToken)
+func ValidateToken(token string) error {
+	var tokenSplit = strings.Split(token, " ")
 
 
-		if err != nil {
-			errorResponse = models.ErrorResponse{
-				Code: http.StatusUnauthorized, Message: "W1R3: Error Verifying Auth Token.",
-			}
-			returnErrorResponse(w, r, errorResponse)
-			return
-		}
+	//I put this in in case the user doesn't put in a token at all (in which case it's empty)
+	//There's probably a smarter way of handling this.
+	var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd"
+
+	if len(tokenSplit) > 1 {
+		authToken = tokenSplit[1]
+	} else {
+		return errors.New("Missing Auth Token.")
+	}
 
 
-		isAuthorized := username != ""
+	//This checks if
+	//A: the token is the master password
+	//B: the token corresponds to a mac address, and if so, which one
+	//TODO: There's probably a better way of dealing with the "master token"/master password. Plz Halp.
+	username, _, err := functions.VerifyUserToken(authToken)
+	if err != nil {
+		return errors.New("Error Verifying Auth Token")
+	}
 
 
-		if !isAuthorized {
-			errorResponse = models.ErrorResponse{
-				Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
-			}
-			returnErrorResponse(w, r, errorResponse)
-			return
-		} else {
-			//If authorized, this function passes along it's request and output to the appropriate route function.
-			next.ServeHTTP(w, r)
-		}
+	isAuthorized := username != ""
+	if !isAuthorized {
+		return errors.New("You are unauthorized to access this endpoint.")
 	}
 	}
+
+	return nil
 }
 }
 
 
 func HasAdmin() (bool, error) {
 func HasAdmin() (bool, error) {
@@ -249,10 +241,19 @@ func getUser(w http.ResponseWriter, r *http.Request) {
 }
 }
 
 
 func CreateUser(user models.User) (models.User, error) {
 func CreateUser(user models.User) (models.User, error) {
+	hasadmin, err := HasAdmin()
+	if hasadmin {
+		return models.User{}, errors.New("Admin already Exists")
+	}
+
+	user.IsAdmin = true
+	err = ValidateUser("create", user)
+	if err != nil {
+		return models.User{}, err
+	}
 
 
 	//encrypt that password so we never see it again
 	//encrypt that password so we never see it again
 	hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 5)
 	hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 5)
-
 	if err != nil {
 	if err != nil {
 		return user, err
 		return user, err
 	}
 	}
@@ -271,9 +272,7 @@ func CreateUser(user models.User) (models.User, error) {
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
 	// insert our node to the node db.
 	// insert our node to the node db.
-	result, err := collection.InsertOne(ctx, user)
-	_ = result
-
+	_, err = collection.InsertOne(ctx, user)
 	defer cancel()
 	defer cancel()
 
 
 	return user, err
 	return user, err
@@ -282,34 +281,11 @@ func CreateUser(user models.User) (models.User, error) {
 func createAdmin(w http.ResponseWriter, r *http.Request) {
 func createAdmin(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 
 
-	var errorResponse = models.ErrorResponse{
-		Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
-	}
-
-	hasadmin, err := HasAdmin()
-
-	if hasadmin {
-		errorResponse = models.ErrorResponse{
-			Code: http.StatusUnauthorized, Message: "W1R3: Admin already exists! ",
-		}
-		returnErrorResponse(w, r, errorResponse)
-		return
-	}
-
 	var admin models.User
 	var admin models.User
-
 	//get node from body of request
 	//get node from body of request
 	_ = json.NewDecoder(r.Body).Decode(&admin)
 	_ = json.NewDecoder(r.Body).Decode(&admin)
 
 
-	admin.IsAdmin = true
-
-	err = ValidateUser("create", admin)
-	if err != nil {
-		json.NewEncoder(w).Encode(err)
-		return
-	}
-
-	admin, err = CreateUser(admin)
+	admin, err := CreateUser(admin)
 	if err != nil {
 	if err != nil {
 		json.NewEncoder(w).Encode(err)
 		json.NewEncoder(w).Encode(err)
 		return
 		return
@@ -320,6 +296,11 @@ func createAdmin(w http.ResponseWriter, r *http.Request) {
 
 
 func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 
 
+	err := ValidateUser("update", userchange)
+	if err != nil {
+		return models.User{}, err
+	}
+
 	queryUser := user.UserName
 	queryUser := user.UserName
 
 
 	if userchange.UserName != "" {
 	if userchange.UserName != "" {
@@ -367,7 +348,7 @@ func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 
 
 	defer cancel()
 	defer cancel()
 
 
-	return userupdate, errN
+	return user, errN
 }
 }
 
 
 func updateUser(w http.ResponseWriter, r *http.Request) {
 func updateUser(w http.ResponseWriter, r *http.Request) {
@@ -393,15 +374,6 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
-	userchange.IsAdmin = true
-
-	err = ValidateUser("update", userchange)
-
-	if err != nil {
-		json.NewEncoder(w).Encode(err)
-		return
-	}
-
 	user, err = UpdateUser(userchange, user)
 	user, err = UpdateUser(userchange, user)
 
 
 	if err != nil {
 	if err != nil {
@@ -458,23 +430,6 @@ func deleteUser(w http.ResponseWriter, r *http.Request) {
 func ValidateUser(operation string, user models.User) error {
 func ValidateUser(operation string, user models.User) error {
 
 
 	v := validator.New()
 	v := validator.New()
-
-	_ = v.RegisterValidation("username_unique", func(fl validator.FieldLevel) bool {
-		_, err := GetUser(user.UserName)
-		return err == nil || operation == "update"
-	})
-
-	_ = v.RegisterValidation("username_valid", func(fl validator.FieldLevel) bool {
-		isvalid := functions.NameInNodeCharSet(user.UserName)
-		return isvalid
-	})
-
-	_ = v.RegisterValidation("password_check", func(fl validator.FieldLevel) bool {
-		notEmptyCheck := user.Password != ""
-		goodLength := len(user.Password) > 5
-		return (notEmptyCheck && goodLength) || operation == "update"
-	})
-
 	err := v.Struct(user)
 	err := v.Struct(user)
 
 
 	if err != nil {
 	if err != nil {

+ 189 - 7
controllers/userHttpController_test.go

@@ -13,9 +13,6 @@ import (
 
 
 func TestMain(m *testing.M) {
 func TestMain(m *testing.M) {
 	mongoconn.ConnectDatabase()
 	mongoconn.ConnectDatabase()
-	//var waitgroup sync.WaitGroup
-	//waitgroup.Add(1)
-	//go controller.HandleRESTRequests(&waitgroup)
 	var gconf models.GlobalConfig
 	var gconf models.GlobalConfig
 	gconf.ServerGRPC = "localhost:8081"
 	gconf.ServerGRPC = "localhost:8081"
 	gconf.PortGRPC = "50051"
 	gconf.PortGRPC = "50051"
@@ -28,17 +25,49 @@ func TestMain(m *testing.M) {
 	if err != nil {
 	if err != nil {
 		panic("could not create config store")
 		panic("could not create config store")
 	}
 	}
-
-	//wait for http server to start
-	//time.Sleep(time.Second * 1)
 	os.Exit(m.Run())
 	os.Exit(m.Run())
 }
 }
 
 
+func TestHasAdmin(t *testing.T) {
+	_, err := DeleteUser("admin")
+	assert.Nil(t, err)
+	user := models.User{"admin", "admin", true}
+	_, err = CreateUser(user)
+	assert.Nil(t, err, err)
+	t.Run("AdminExists", func(t *testing.T) {
+		found, err := HasAdmin()
+		assert.Nil(t, err, err)
+		assert.True(t, found)
+	})
+	t.Run("NoUser", func(t *testing.T) {
+		_, err := DeleteUser("admin")
+		assert.Nil(t, err, err)
+		found, err := HasAdmin()
+		assert.Nil(t, err, err)
+		assert.False(t, found)
+	})
+}
+
+func TestCreateUser(t *testing.T) {
+	user := models.User{"admin", "admin", true}
+	t.Run("NoUser", func(t *testing.T) {
+		_, err := DeleteUser("admin")
+		assert.Nil(t, err, err)
+		admin, err := CreateUser(user)
+		assert.Nil(t, err, err)
+		assert.Equal(t, user.UserName, admin.UserName)
+	})
+	t.Run("AdminExists", func(t *testing.T) {
+		_, err := CreateUser(user)
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "Admin already Exists", err.Error())
+	})
+}
+
 func TestDeleteUser(t *testing.T) {
 func TestDeleteUser(t *testing.T) {
 	hasadmin, err := HasAdmin()
 	hasadmin, err := HasAdmin()
 	assert.Nil(t, err, err)
 	assert.Nil(t, err, err)
 	if !hasadmin {
 	if !hasadmin {
-		//if !adminExists() {
 		user := models.User{"admin", "admin", true}
 		user := models.User{"admin", "admin", true}
 		_, err := CreateUser(user)
 		_, err := CreateUser(user)
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
@@ -47,6 +76,7 @@ func TestDeleteUser(t *testing.T) {
 		deleted, err := DeleteUser("admin")
 		deleted, err := DeleteUser("admin")
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
 		assert.True(t, deleted)
 		assert.True(t, deleted)
+		t.Log(deleted, err)
 	})
 	})
 	t.Run("NonExistantUser", func(t *testing.T) {
 	t.Run("NonExistantUser", func(t *testing.T) {
 		deleted, err := DeleteUser("admin")
 		deleted, err := DeleteUser("admin")
@@ -54,3 +84,155 @@ func TestDeleteUser(t *testing.T) {
 		assert.False(t, deleted)
 		assert.False(t, deleted)
 	})
 	})
 }
 }
+
+func TestValidateUser(t *testing.T) {
+	var user models.User
+	t.Run("ValidCreate", func(t *testing.T) {
+		user.UserName = "admin"
+		user.Password = "validpass"
+		err := ValidateUser("create", user)
+		assert.Nil(t, err, err)
+	})
+	t.Run("ValidUpdate", func(t *testing.T) {
+		user.UserName = "admin"
+		user.Password = "admin"
+		err := ValidateUser("update", user)
+		assert.Nil(t, err, err)
+	})
+	t.Run("InvalidUserName", func(t *testing.T) {
+		user.UserName = "invalid*"
+		err := ValidateUser("update", user)
+		assert.NotNil(t, err, err)
+	})
+	t.Run("ShortUserName", func(t *testing.T) {
+		user.UserName = "12"
+		err := ValidateUser("create", user)
+		assert.NotNil(t, err, err)
+	})
+	t.Run("EmptyPassword", func(t *testing.T) {
+		user.Password = ""
+		err := ValidateUser("create", user)
+		assert.NotNil(t, err, err)
+	})
+	t.Run("ShortPassword", func(t *testing.T) {
+		user.Password = "123"
+		err := ValidateUser("create", user)
+		assert.NotNil(t, err, err)
+	})
+}
+
+func TestGetUser(t *testing.T) {
+	user := models.User{"admin", "admin", true}
+	t.Run("UserExisits", func(t *testing.T) {
+		_, err := CreateUser(user)
+		assert.Nil(t, err, err)
+		admin, err := GetUser("admin")
+		assert.Nil(t, err, err)
+		assert.Equal(t, user.UserName, admin.UserName)
+	})
+	t.Run("NonExistantUser", func(t *testing.T) {
+		_, err := DeleteUser("admin")
+		assert.Nil(t, err, err)
+		admin, err := GetUser("admin")
+		assert.Equal(t, "mongo: no documents in result", err.Error())
+		assert.Equal(t, "", admin.UserName)
+	})
+}
+
+func TestUpdateUser(t *testing.T) {
+	user := models.User{"admin", "admin", true}
+	newuser := models.User{"hello", "world", true}
+	t.Run("UserExisits", func(t *testing.T) {
+		_, err := DeleteUser("admin")
+		_, err = CreateUser(user)
+		assert.Nil(t, err, err)
+		admin, err := UpdateUser(newuser, user)
+		assert.Nil(t, err, err)
+		assert.Equal(t, newuser.UserName, admin.UserName)
+	})
+	t.Run("NonExistantUser", func(t *testing.T) {
+		_, err := DeleteUser("hello")
+		assert.Nil(t, err, err)
+		_, err = UpdateUser(newuser, user)
+		assert.Equal(t, "mongo: no documents in result", err.Error())
+	})
+}
+
+func TestValidateToken(t *testing.T) {
+	t.Run("EmptyToken", func(t *testing.T) {
+		err := ValidateToken("")
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "Missing Auth Token.", err.Error())
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		err := ValidateToken("Bearer: badtoken")
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "Error Verifying Auth Token", err.Error())
+	})
+	t.Run("InvalidUser", func(t *testing.T) {
+		t.Skip()
+		//need authorization
+	})
+	t.Run("ValidToken", func(t *testing.T) {
+		err := ValidateToken("Bearer: secretkey")
+		assert.Nil(t, err, err)
+	})
+}
+
+func TestVerifyAuthRequest(t *testing.T) {
+	var authRequest models.UserAuthParams
+	t.Run("EmptyUserName", func(t *testing.T) {
+		authRequest.UserName = ""
+		authRequest.Password = "Password"
+		jwt, err := VerifyAuthRequest(authRequest)
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "", jwt)
+		assert.Equal(t, "Username can't be empty", err.Error())
+	})
+	t.Run("EmptyPassword", func(t *testing.T) {
+		authRequest.UserName = "admin"
+		authRequest.Password = ""
+		jwt, err := VerifyAuthRequest(authRequest)
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "", jwt)
+		assert.Equal(t, "Password can't be empty", err.Error())
+	})
+	t.Run("NonExistantUser", func(t *testing.T) {
+		_, err := DeleteUser("admin")
+		authRequest.UserName = "admin"
+		authRequest.Password = "password"
+		jwt, err := VerifyAuthRequest(authRequest)
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "", jwt)
+		assert.Equal(t, "User admin not found", err.Error())
+	})
+	t.Run("Non-Admin", func(t *testing.T) {
+		//can't create a user that is not a an admin
+		t.Skip()
+		user := models.User{"admin", "admin", false}
+		_, err := CreateUser(user)
+		assert.Nil(t, err)
+		authRequest := models.UserAuthParams{"admin", "admin"}
+		jwt, err := VerifyAuthRequest(authRequest)
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "", jwt)
+		assert.Equal(t, "User is not an admin", err.Error())
+	})
+	t.Run("WrongPassword", func(t *testing.T) {
+		_, err := DeleteUser("admin")
+		user := models.User{"admin", "admin", true}
+		_, err = CreateUser(user)
+		assert.Nil(t, err)
+		authRequest := models.UserAuthParams{"admin", "badpass"}
+		jwt, err := VerifyAuthRequest(authRequest)
+		assert.NotNil(t, err, err)
+		assert.Equal(t, "", jwt)
+		assert.Equal(t, "Wrong Password", err.Error())
+	})
+	t.Run("Success", func(t *testing.T) {
+		authRequest := models.UserAuthParams{"admin", "admin"}
+		jwt, err := VerifyAuthRequest(authRequest)
+		assert.Nil(t, err, err)
+		assert.NotNil(t, jwt)
+	})
+}

+ 57 - 60
models/structs.go

@@ -3,112 +3,109 @@ package models
 import jwt "github.com/dgrijalva/jwt-go"
 import jwt "github.com/dgrijalva/jwt-go"
 
 
 type AuthParams struct {
 type AuthParams struct {
-    MacAddress    string `json:"macaddress"`
-    Password string `json:"password"`
+	MacAddress string `json:"macaddress"`
+	Password   string `json:"password"`
 }
 }
 
 
 type User struct {
 type User struct {
-    UserName string `json:"username" bson:"username" validate:username_valid,username_unique,min=3`
-    Password string `json:"password" bson:"password" validate:password_check`
-    IsAdmin bool `json:"isadmin" bson:"isadmin"`
+	UserName string `json:"username" bson:"username" validate:"alphanum,min=3"`
+	Password string `json:"password" bson:"password" validate:"required,min=5"`
+	IsAdmin  bool   `json:"isadmin" bson:"isadmin"`
 }
 }
 
 
 type UserAuthParams struct {
 type UserAuthParams struct {
-    UserName    string `json:"username"`
-    Password string `json:"password"`
+	UserName string `json:"username"`
+	Password string `json:"password"`
 }
 }
 
 
 type UserClaims struct {
 type UserClaims struct {
-    IsAdmin bool
-    UserName string
-    jwt.StandardClaims
+	IsAdmin  bool
+	UserName string
+	jwt.StandardClaims
 }
 }
 
 
 type SuccessfulUserLoginResponse struct {
 type SuccessfulUserLoginResponse struct {
-    UserName     string
-    AuthToken string
+	UserName  string
+	AuthToken string
 }
 }
 
 
 // Claims is  a struct that will be encoded to a JWT.
 // Claims is  a struct that will be encoded to a JWT.
 // jwt.StandardClaims is an embedded type to provide expiry time
 // jwt.StandardClaims is an embedded type to provide expiry time
 type Claims struct {
 type Claims struct {
-    Network string
-    MacAddress string
-    jwt.StandardClaims
+	Network    string
+	MacAddress string
+	jwt.StandardClaims
 }
 }
 
 
 // SuccessfulLoginResponse is struct to send the request response
 // SuccessfulLoginResponse is struct to send the request response
 type SuccessfulLoginResponse struct {
 type SuccessfulLoginResponse struct {
-    MacAddress     string
-    AuthToken string
+	MacAddress string
+	AuthToken  string
 }
 }
 
 
 type ErrorResponse struct {
 type ErrorResponse struct {
-    Code    int
-    Message string
+	Code    int
+	Message string
 }
 }
 
 
 type NodeAuth struct {
 type NodeAuth struct {
-    Network    string
-    Password string
-    MacAddress string
+	Network    string
+	Password   string
+	MacAddress string
 }
 }
 
 
 // SuccessResponse is struct for sending error message with code.
 // SuccessResponse is struct for sending error message with code.
 type SuccessResponse struct {
 type SuccessResponse struct {
-    Code     int
-    Message  string
-    Response interface{}
+	Code     int
+	Message  string
+	Response interface{}
 }
 }
 
 
 type AccessKey struct {
 type AccessKey struct {
-    Name string `json:"name" bson:"name"`
-    Value string `json:"value" bson:"value"`
-    AccessString string `json:"accessstring" bson:"accessstring"`
-    Uses int `json:"uses" bson:"uses"`
+	Name         string `json:"name" bson:"name"`
+	Value        string `json:"value" bson:"value"`
+	AccessString string `json:"accessstring" bson:"accessstring"`
+	Uses         int    `json:"uses" bson:"uses"`
 }
 }
 
 
 type DisplayKey struct {
 type DisplayKey struct {
-    Name string `json:"name" bson:"name"`
-    Uses int `json:"uses" bson:"uses"`
+	Name string `json:"name" bson:"name"`
+	Uses int    `json:"uses" bson:"uses"`
 }
 }
 
 
 type GlobalConfig struct {
 type GlobalConfig struct {
-    Name string `json:"name" bson:"name"`
-    PortGRPC string `json:"portgrpc" bson:"portgrpc"`
-    ServerGRPC string `json:"servergrpc" bson:"servergrpc"`
+	Name       string `json:"name" bson:"name"`
+	PortGRPC   string `json:"portgrpc" bson:"portgrpc"`
+	ServerGRPC string `json:"servergrpc" bson:"servergrpc"`
 }
 }
 
 
-
-type CheckInResponse struct{
-    Success bool `json:"success" bson:"success"`
-    NeedPeerUpdate bool `json:"needpeerupdate" bson:"needpeerupdate"`
-    NeedConfigUpdate bool `json:"needconfigupdate" bson:"needconfigupdate"`
-    NeedKeyUpdate bool `json:"needkeyupdate" bson:"needkeyupdate"`
-    NeedDelete bool `json:"needdelete" bson:"needdelete"`
-    NodeMessage string `json:"nodemessage" bson:"nodemessage"`
-    IsPending bool `json:"ispending" bson:"ispending"`
+type CheckInResponse struct {
+	Success          bool   `json:"success" bson:"success"`
+	NeedPeerUpdate   bool   `json:"needpeerupdate" bson:"needpeerupdate"`
+	NeedConfigUpdate bool   `json:"needconfigupdate" bson:"needconfigupdate"`
+	NeedKeyUpdate    bool   `json:"needkeyupdate" bson:"needkeyupdate"`
+	NeedDelete       bool   `json:"needdelete" bson:"needdelete"`
+	NodeMessage      string `json:"nodemessage" bson:"nodemessage"`
+	IsPending        bool   `json:"ispending" bson:"ispending"`
 }
 }
 
 
 type PeersResponse struct {
 type PeersResponse struct {
-    PublicKey string `json:"publickey" bson:"publickey"`
-    Endpoint string `json:"endpoint" bson:"endpoint"`
-    Address string `json:"address" bson:"address"`
-    LocalAddress string `json:"localaddress" bson:"localaddress"`
-    IsGateway bool `json:"isgateway" bson:"isgateway"`
-    GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
-    ListenPort int32 `json:"listenport" bson:"listenport"`
-    KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
+	PublicKey    string `json:"publickey" bson:"publickey"`
+	Endpoint     string `json:"endpoint" bson:"endpoint"`
+	Address      string `json:"address" bson:"address"`
+	LocalAddress string `json:"localaddress" bson:"localaddress"`
+	IsGateway    bool   `json:"isgateway" bson:"isgateway"`
+	GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
+	ListenPort   int32  `json:"listenport" bson:"listenport"`
+	KeepAlive    int32  `json:"persistentkeepalive" bson:"persistentkeepalive"`
 }
 }
 
 
 type GatewayRequest struct {
 type GatewayRequest struct {
-    NodeID string `json:"nodeid" bson:"nodeid"`
-    NetID string `json:"netid" bson:"netid"`
-    RangeString string `json:"rangestring" bson:"rangestring"`
-    Ranges []string `json:"ranges" bson:"ranges"`
-    Interface string `json:"interface" bson:"interface"`
-    PostUp string `json:"postup" bson:"postup"`
-    PostDown string `json:"postdown" bson:"postdown"`
+	NodeID      string   `json:"nodeid" bson:"nodeid"`
+	NetID       string   `json:"netid" bson:"netid"`
+	RangeString string   `json:"rangestring" bson:"rangestring"`
+	Ranges      []string `json:"ranges" bson:"ranges"`
+	Interface   string   `json:"interface" bson:"interface"`
+	PostUp      string   `json:"postup" bson:"postup"`
+	PostDown    string   `json:"postdown" bson:"postdown"`
 }
 }
-
-