瀏覽代碼

add superadmin role, apis to create superadmin user

Abhishek Kondur 2 年之前
父節點
當前提交
11655dfdd6
共有 7 個文件被更改,包括 68 次插入67 次删除
  1. 5 5
      auth/auth.go
  2. 1 1
      controllers/network_test.go
  3. 16 17
      controllers/user.go
  4. 24 23
      controllers/user_test.go
  5. 6 6
      functions/helpers_test.go
  6. 10 10
      logic/auth.go
  7. 6 5
      models/structs.go

+ 5 - 5
auth/auth.go

@@ -238,7 +238,7 @@ func HandleHeadlessSSO(w http.ResponseWriter, r *http.Request) {
 // == private methods ==
 // == private methods ==
 
 
 func addUser(email string) error {
 func addUser(email string) error {
-	var hasAdmin, err = logic.HasAdmin()
+	var hasSuperAdmin, err = logic.HasSuperAdmin()
 	if err != nil {
 	if err != nil {
 		logger.Log(1, "error checking for existence of admin user during OAuth login for", email, "; user not added")
 		logger.Log(1, "error checking for existence of admin user during OAuth login for", email, "; user not added")
 		return err
 		return err
@@ -251,11 +251,11 @@ func addUser(email string) error {
 		UserName: email,
 		UserName: email,
 		Password: newPass,
 		Password: newPass,
 	}
 	}
-	if !hasAdmin { // must be first attempt, create an admin
-		if err = logic.CreateAdmin(&newUser); err != nil {
-			logger.Log(1, "error creating admin from user,", email, "; user not added")
+	if !hasSuperAdmin { // must be first attempt, create a superadmin
+		if err = logic.CreateSuperAdmin(&newUser); err != nil {
+			logger.Log(1, "error creating super admin from user,", email, "; user not added")
 		} else {
 		} else {
-			logger.Log(1, "admin created from user,", email, "; was first user added")
+			logger.Log(1, "superadmin created from user,", email, "; was first user added")
 		}
 		}
 	} else { // otherwise add to db as admin..?
 	} else { // otherwise add to db as admin..?
 		// TODO: add ability to add users with preemptive permissions
 		// TODO: add ability to add users with preemptive permissions

+ 1 - 1
controllers/network_test.go

@@ -25,7 +25,7 @@ var netHost models.Host
 func TestMain(m *testing.M) {
 func TestMain(m *testing.M) {
 	database.InitializeDatabase()
 	database.InitializeDatabase()
 	defer database.CloseDB()
 	defer database.CloseDB()
-	logic.CreateAdmin(&models.User{
+	logic.CreateSuperAdmin(&models.User{
 		UserName: "admin",
 		UserName: "admin",
 		Password: "password",
 		Password: "password",
 		IsAdmin:  true,
 		IsAdmin:  true,

+ 16 - 17
controllers/user.go

@@ -23,9 +23,8 @@ var (
 var verifyJWT = logic.VerifyJWT
 var verifyJWT = logic.VerifyJWT
 
 
 func userHandlers(r *mux.Router) {
 func userHandlers(r *mux.Router) {
-
-	r.HandleFunc("/api/users/adm/hasadmin", hasAdmin).Methods(http.MethodGet)
-	r.HandleFunc("/api/users/adm/createadmin", createAdmin).Methods(http.MethodPost)
+	r.HandleFunc("/api/users/adm/hassuperadmin", hasSuperAdmin).Methods(http.MethodGet)
+	r.HandleFunc("/api/users/adm/createsuperadmin", createSuperAdmin).Methods(http.MethodPost)
 	r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
 	r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
 	r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(updateUser)))).Methods(http.MethodPut)
 	r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(updateUser)))).Methods(http.MethodPut)
 	r.HandleFunc("/api/users/networks/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUserNetworks))).Methods(http.MethodPut)
 	r.HandleFunc("/api/users/networks/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUserNetworks))).Methods(http.MethodPut)
@@ -112,7 +111,7 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 	response.Write(successJSONResponse)
 	response.Write(successJSONResponse)
 }
 }
 
 
-// swagger:route GET /api/users/adm/hasadmin user hasAdmin
+// swagger:route GET /api/users/adm/hassuperadmin user hasSuperAdmin
 //
 //
 // Checks whether the server has an admin.
 // Checks whether the server has an admin.
 //
 //
@@ -123,18 +122,18 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 //
 //
 //			Responses:
 //			Responses:
 //				200: successResponse
 //				200: successResponse
-func hasAdmin(w http.ResponseWriter, r *http.Request) {
+func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
 
 
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 
 
-	hasadmin, err := logic.HasAdmin()
+	hasSuperAdmin, err := logic.HasSuperAdmin()
 	if err != nil {
 	if err != nil {
 		logger.Log(0, "failed to check for admin: ", err.Error())
 		logger.Log(0, "failed to check for admin: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
 
 
-	json.NewEncoder(w).Encode(hasadmin)
+	json.NewEncoder(w).Encode(hasSuperAdmin)
 
 
 }
 }
 
 
@@ -194,7 +193,7 @@ func getUsers(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(users)
 	json.NewEncoder(w).Encode(users)
 }
 }
 
 
-// swagger:route POST /api/users/adm/createadmin user createAdmin
+// swagger:route POST /api/users/adm/createsuperadmin user createAdmin
 //
 //
 // Make a user an admin.
 // Make a user an admin.
 //
 //
@@ -205,15 +204,15 @@ func getUsers(w http.ResponseWriter, r *http.Request) {
 //
 //
 //			Responses:
 //			Responses:
 //				200: userBodyResponse
 //				200: userBodyResponse
-func createAdmin(w http.ResponseWriter, r *http.Request) {
+func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 
 
-	var admin models.User
+	var u models.User
 
 
-	err := json.NewDecoder(r.Body).Decode(&admin)
+	err := json.NewDecoder(r.Body).Decode(&u)
 	if err != nil {
 	if err != nil {
 
 
-		logger.Log(0, admin.UserName, "error decoding request body: ",
+		logger.Log(0, u.UserName, "error decoding request body: ",
 			err.Error())
 			err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 		return
@@ -224,16 +223,16 @@ func createAdmin(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
-	err = logic.CreateAdmin(&admin)
+	err = logic.CreateSuperAdmin(&u)
 	if err != nil {
 	if err != nil {
-		logger.Log(0, admin.UserName, "failed to create admin: ",
+		logger.Log(0, u.UserName, "failed to create admin: ",
 			err.Error())
 			err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 		return
 	}
 	}
 
 
-	logger.Log(1, admin.UserName, "was made a new admin")
-	json.NewEncoder(w).Encode(logic.ToReturnUser(admin))
+	logger.Log(1, u.UserName, "was made a super admin")
+	json.NewEncoder(w).Encode(logic.ToReturnUser(u))
 }
 }
 
 
 // swagger:route POST /api/users/{username} user createUser
 // swagger:route POST /api/users/{username} user createUser
@@ -428,7 +427,7 @@ func updateUserAdm(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 		return
 	}
 	}
-	if !user.IsAdmin {
+	if !user.IsAdmin && !user.IsSuperAdmin {
 		logger.Log(0, username, "not an admin user")
 		logger.Log(0, username, "not an admin user")
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not a admin user"), "badrequest"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not a admin user"), "badrequest"))
 	}
 	}

+ 24 - 23
controllers/user_test.go

@@ -2,13 +2,14 @@ package controller
 
 
 import (
 import (
 	"bytes"
 	"bytes"
-	"github.com/go-jose/go-jose/v3/json"
-	"github.com/gorilla/mux"
 	"io"
 	"io"
 	"net/http"
 	"net/http"
 	"net/http/httptest"
 	"net/http/httptest"
 	"testing"
 	"testing"
 
 
+	"github.com/go-jose/go-jose/v3/json"
+	"github.com/gorilla/mux"
+
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
 
 
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
@@ -47,7 +48,7 @@ func TestCreateAdminNoHashedPassword(t *testing.T) {
 	rec, req := prepareUserRequest(t, user, "")
 	rec, req := prepareUserRequest(t, user, "")
 
 
 	// test response
 	// test response
-	createAdmin(rec, req)
+	createSuperAdmin(rec, req)
 	assertUserNameButNoPassword(t, rec.Body, user.UserName)
 	assertUserNameButNoPassword(t, rec.Body, user.UserName)
 }
 }
 
 
@@ -101,7 +102,7 @@ func TestUpdateUserNoHashedPassword(t *testing.T) {
 
 
 func TestUpdateUserAdmNoHashedPassword(t *testing.T) {
 func TestUpdateUserAdmNoHashedPassword(t *testing.T) {
 	// prepare existing user base
 	// prepare existing user base
-	user1 := models.User{UserName: "dio", Password: "brando", IsAdmin: true}
+	user1 := models.User{UserName: "dio", Password: "brando", IsSuperAdmin: true}
 	haveOnlyOneUser(t, user1)
 	haveOnlyOneUser(t, user1)
 
 
 	// prepare request
 	// prepare request
@@ -126,8 +127,8 @@ func prepareUserRequest(t *testing.T, userForBody models.User, userNameForParam
 func haveOnlyOneUser(t *testing.T, user models.User) {
 func haveOnlyOneUser(t *testing.T, user models.User) {
 	deleteAllUsers(t)
 	deleteAllUsers(t)
 	var err error
 	var err error
-	if user.IsAdmin {
-		err = logic.CreateAdmin(&user)
+	if user.IsSuperAdmin {
+		err = logic.CreateSuperAdmin(&user)
 	} else {
 	} else {
 		err = logic.CreateUser(&user)
 		err = logic.CreateUser(&user)
 	}
 	}
@@ -142,7 +143,7 @@ func assertUserNameButNoPassword(t *testing.T, r io.Reader, userName string) {
 	assert.Empty(t, resp.Password)
 	assert.Empty(t, resp.Password)
 }
 }
 
 
-func TestHasAdmin(t *testing.T) {
+func TestHasSuperAdmin(t *testing.T) {
 	// delete all current users
 	// delete all current users
 	users, _ := logic.GetUsers()
 	users, _ := logic.GetUsers()
 	for _, user := range users {
 	for _, user := range users {
@@ -151,31 +152,31 @@ func TestHasAdmin(t *testing.T) {
 		assert.True(t, success)
 		assert.True(t, success)
 	}
 	}
 	t.Run("NoUser", func(t *testing.T) {
 	t.Run("NoUser", func(t *testing.T) {
-		found, err := logic.HasAdmin()
+		found, err := logic.HasSuperAdmin()
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.False(t, found)
 		assert.False(t, found)
 	})
 	})
-	t.Run("No admin user", func(t *testing.T) {
-		var user = models.User{UserName: "noadmin", Password: "password"}
+	t.Run("No superadmin user", func(t *testing.T) {
+		var user = models.User{UserName: "nosuperadmin", Password: "password"}
 		err := logic.CreateUser(&user)
 		err := logic.CreateUser(&user)
 		assert.Nil(t, err)
 		assert.Nil(t, err)
-		found, err := logic.HasAdmin()
+		found, err := logic.HasSuperAdmin()
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.False(t, found)
 		assert.False(t, found)
 	})
 	})
-	t.Run("admin user", func(t *testing.T) {
-		var user = models.User{UserName: "admin", Password: "password", IsAdmin: true}
+	t.Run("superadmin user", func(t *testing.T) {
+		var user = models.User{UserName: "superadmin", Password: "password", IsSuperAdmin: true}
 		err := logic.CreateUser(&user)
 		err := logic.CreateUser(&user)
 		assert.Nil(t, err)
 		assert.Nil(t, err)
-		found, err := logic.HasAdmin()
+		found, err := logic.HasSuperAdmin()
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.True(t, found)
 		assert.True(t, found)
 	})
 	})
-	t.Run("multiple admins", func(t *testing.T) {
-		var user = models.User{UserName: "admin1", Password: "password", IsAdmin: true}
+	t.Run("multiple superadmins", func(t *testing.T) {
+		var user = models.User{UserName: "superadmin1", Password: "password", IsSuperAdmin: true}
 		err := logic.CreateUser(&user)
 		err := logic.CreateUser(&user)
 		assert.Nil(t, err)
 		assert.Nil(t, err)
-		found, err := logic.HasAdmin()
+		found, err := logic.HasSuperAdmin()
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.True(t, found)
 		assert.True(t, found)
 	})
 	})
@@ -195,20 +196,20 @@ func TestCreateUser(t *testing.T) {
 	})
 	})
 }
 }
 
 
-func TestCreateAdmin(t *testing.T) {
+func TestCreateSuperAdmin(t *testing.T) {
 	deleteAllUsers(t)
 	deleteAllUsers(t)
 	var user models.User
 	var user models.User
-	t.Run("NoAdmin", func(t *testing.T) {
+	t.Run("NoSuperAdmin", func(t *testing.T) {
 		user.UserName = "admin"
 		user.UserName = "admin"
 		user.Password = "password"
 		user.Password = "password"
-		err := logic.CreateAdmin(&user)
+		err := logic.CreateSuperAdmin(&user)
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 	})
 	})
-	t.Run("AdminExists", func(t *testing.T) {
+	t.Run("SuperAdminExists", func(t *testing.T) {
 		user.UserName = "admin2"
 		user.UserName = "admin2"
 		user.Password = "password1"
 		user.Password = "password1"
-		err := logic.CreateAdmin(&user)
-		assert.EqualError(t, err, "admin user already exists")
+		err := logic.CreateSuperAdmin(&user)
+		assert.EqualError(t, err, "superadmin user already exists")
 	})
 	})
 }
 }
 
 

+ 6 - 6
functions/helpers_test.go

@@ -25,12 +25,12 @@ var (
 func TestMain(m *testing.M) {
 func TestMain(m *testing.M) {
 	database.InitializeDatabase()
 	database.InitializeDatabase()
 	defer database.CloseDB()
 	defer database.CloseDB()
-	logic.CreateAdmin(&models.User{
-		UserName: "admin",
-		Password: "password",
-		IsAdmin:  true,
-		Networks: []string{},
-		Groups:   []string{},
+	logic.CreateSuperAdmin(&models.User{
+		UserName:     "superadmin",
+		Password:     "password",
+		IsSuperAdmin: true,
+		Networks:     []string{},
+		Groups:       []string{},
 	})
 	})
 	peerUpdate := make(chan *models.Node)
 	peerUpdate := make(chan *models.Node)
 	go logic.ManageZombies(context.Background(), peerUpdate)
 	go logic.ManageZombies(context.Background(), peerUpdate)

+ 10 - 10
logic/auth.go

@@ -17,8 +17,8 @@ import (
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
 )
 )
 
 
-// HasAdmin - checks if server has an admin
-func HasAdmin() (bool, error) {
+// HasSuperAdmin - checks if server has an superadmin/owner
+func HasSuperAdmin() (bool, error) {
 
 
 	collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
 	collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
 	if err != nil {
 	if err != nil {
@@ -34,7 +34,7 @@ func HasAdmin() (bool, error) {
 		if err != nil {
 		if err != nil {
 			continue
 			continue
 		}
 		}
-		if user.IsAdmin {
+		if user.IsSuperAdmin {
 			return true, nil
 			return true, nil
 		}
 		}
 	}
 	}
@@ -142,17 +142,17 @@ func CreateUser(user *models.User) error {
 	return nil
 	return nil
 }
 }
 
 
-// CreateAdmin - creates an admin user
-func CreateAdmin(admin *models.User) error {
-	hasadmin, err := HasAdmin()
+// CreateSuperAdmin - creates an super admin user
+func CreateSuperAdmin(u *models.User) error {
+	hassuperadmin, err := HasSuperAdmin()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	if hasadmin {
-		return errors.New("admin user already exists")
+	if hassuperadmin {
+		return errors.New("superadmin user already exists")
 	}
 	}
-	admin.IsAdmin = true
-	return CreateUser(admin)
+	u.IsSuperAdmin = true
+	return CreateUser(u)
 }
 }
 
 
 // VerifyAuthRequest - verifies an auth request
 // VerifyAuthRequest - verifies an auth request

+ 6 - 5
models/structs.go

@@ -24,11 +24,12 @@ type AuthParams struct {
 
 
 // User struct - struct for Users
 // User struct - struct for Users
 type User struct {
 type User struct {
-	UserName string   `json:"username" bson:"username" validate:"min=3,max=40,in_charset|email"`
-	Password string   `json:"password" bson:"password" validate:"required,min=5"`
-	Networks []string `json:"networks" bson:"networks"`
-	IsAdmin  bool     `json:"isadmin" bson:"isadmin"`
-	Groups   []string `json:"groups" bson:"groups" yaml:"groups"`
+	UserName     string   `json:"username" bson:"username" validate:"min=3,max=40,in_charset|email"`
+	Password     string   `json:"password" bson:"password" validate:"required,min=5"`
+	Networks     []string `json:"networks" bson:"networks"`
+	IsAdmin      bool     `json:"isadmin" bson:"isadmin"`
+	IsSuperAdmin bool     `json:"super_admin"`
+	Groups       []string `json:"groups" bson:"groups" yaml:"groups"`
 }
 }
 
 
 // ReturnUser - return user struct
 // ReturnUser - return user struct