Browse Source

Merge branch 'develop' of github.com:gravitl/netmaker into develop

Matthew R Kasun 4 years ago
parent
commit
261f9d2649

+ 7 - 0
README.md

@@ -46,6 +46,8 @@ In future releases, we have plans to support other platforms such as Windows and
 
 
 ## Quick Start
 ## Quick Start
 
 
+[Video Tutorial](https://youtu.be/PWLPT320Ybo)
+
 #### Prereqs:
 #### Prereqs:
 1. A server with an IP reachable by your computers (a small ec2 instance or droplet would do just fine).
 1. A server with an IP reachable by your computers (a small ec2 instance or droplet would do just fine).
 2. Linux installed on the above server (we use Ubuntu, but anything that runs Docker should work).
 2. Linux installed on the above server (we use Ubuntu, but anything that runs Docker should work).
@@ -73,3 +75,8 @@ Netmaker's source code and all artifacts in this repository are freely available
 
 
 Email: [email protected]  
 Email: [email protected]  
 Discord: https://discord.gg/zRb9Vfhk8A
 Discord: https://discord.gg/zRb9Vfhk8A
+
+#### SUPPORT
+
+BTC: 3JE5ejpwu9i4vwA4rePkEDBEPpFY1xzJuN  
+ETH: 0xB6c5D23F2bE2100A5a2D337911A7Ef7575B4f91A

+ 1 - 1
controllers/authGrpc.go

@@ -121,7 +121,7 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.LoginRequest)
                 return nil, err
                 return nil, err
         } else {
         } else {
             //Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
             //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("wirecat").Collection("nodes")
+            collection := mongoconn.Client.Database("netmaker").Collection("nodes")
             ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
             ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
             var err = collection.FindOne(ctx, bson.M{ "macaddress": macaddress}).Decode(&result)
             var err = collection.FindOne(ctx, bson.M{ "macaddress": macaddress}).Decode(&result)
 
 

+ 7 - 7
controllers/common.go

@@ -21,7 +21,7 @@ func GetPeersList(groupName string) ([]models.PeersResponse, error) {
         var peers []models.PeersResponse
         var peers []models.PeersResponse
 
 
         //Connection mongoDB with mongoconn class
         //Connection mongoDB with mongoconn class
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -178,7 +178,7 @@ func UpdateNode(nodechange models.Node, node models.Node) (models.Node, error) {
     }
     }
 
 
         //collection := mongoconn.ConnectDB()
         //collection := mongoconn.ConnectDB()
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -228,7 +228,7 @@ func DeleteNode(macaddress string, group string) (bool, error)  {
 
 
 	deleted := false
 	deleted := false
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
 	filter := bson.M{"macaddress": macaddress, "group": group}
 	filter := bson.M{"macaddress": macaddress, "group": group}
 
 
@@ -254,7 +254,7 @@ func GetNode(macaddress string, group string) (models.Node, error) {
 
 
         var node models.Node
         var node models.Node
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -317,7 +317,7 @@ func CreateNode(node models.Node, groupName string) (models.Node, error) {
         }
         }
 
 
         // connect db
         // connect db
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
 
 
@@ -405,7 +405,7 @@ func SetGroupNodesLastModified(groupName string) error {
 
 
 	timestamp := time.Now().Unix()
 	timestamp := time.Now().Unix()
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -441,7 +441,7 @@ func TimestampNode(node models.Node, updatecheckin bool, updatepeers bool, updat
 		node.SetLastPeerUpdate()
 		node.SetLastPeerUpdate()
 	}
 	}
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 

+ 8 - 8
controllers/groupHttpController.go

@@ -147,7 +147,7 @@ func getGroupNodeNumber(w http.ResponseWriter, r *http.Request) {
 //maybe a functions/ folder and then a node.go, group.go, keys.go, misc.go
 //maybe a functions/ folder and then a node.go, group.go, keys.go, misc.go
 func GetGroupNodeNumber(groupName string) (int,  error){
 func GetGroupNodeNumber(groupName string) (int,  error){
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -175,7 +175,7 @@ func getGroup(w http.ResponseWriter, r *http.Request) {
 
 
         var group models.Group
         var group models.Group
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -285,7 +285,7 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
              haschange = true
              haschange = true
         }
         }
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -355,7 +355,7 @@ func deleteGroup(w http.ResponseWriter, r *http.Request) {
                 return
                 return
         }
         }
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         filter := bson.M{"nameid": params["groupname"]}
         filter := bson.M{"nameid": params["groupname"]}
 
 
@@ -406,7 +406,7 @@ func createGroup(w http.ResponseWriter, r *http.Request) {
         group.SetGroupLastModified()
         group.SetGroupLastModified()
 
 
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
 
 
@@ -458,7 +458,7 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
 
 
 	group.AccessKeys = append(group.AccessKeys, accesskey)
 	group.AccessKeys = append(group.AccessKeys, accesskey)
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -497,7 +497,7 @@ func getAccessKeys(w http.ResponseWriter, r *http.Request) {
         var group models.Group
         var group models.Group
         var keys []models.DisplayKey
         var keys []models.DisplayKey
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -549,7 +549,7 @@ func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
 		}
 		}
 	}
 	}
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 

+ 7 - 7
controllers/nodeHttpController.go

@@ -67,7 +67,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
        } else {
        } else {
 
 
             //Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
             //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("wirecat").Collection("nodes")
+            collection := mongoconn.Client.Database("netmaker").Collection("nodes")
             ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
             ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	    var err = collection.FindOne(ctx, bson.M{ "macaddress": authRequest.MacAddress, "ispending": false }).Decode(&result)
 	    var err = collection.FindOne(ctx, bson.M{ "macaddress": authRequest.MacAddress, "ispending": false }).Decode(&result)
 
 
@@ -237,7 +237,7 @@ func getPeerList(w http.ResponseWriter, r *http.Request) {
 	var params = mux.Vars(r)
 	var params = mux.Vars(r)
 
 
         //Connection mongoDB with mongoconn class
         //Connection mongoDB with mongoconn class
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -291,7 +291,7 @@ func getGroupNodes(w http.ResponseWriter, r *http.Request) {
 	var nodes []models.ReturnNode
 	var nodes []models.ReturnNode
 	var params = mux.Vars(r)
 	var params = mux.Vars(r)
 
 
-	collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+	collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -343,7 +343,7 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
 
 
         var nodes []models.ReturnNode
         var nodes []models.ReturnNode
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -404,7 +404,7 @@ func checkIn(w http.ResponseWriter, r *http.Request) {
 	//Retrieves node with DB Call which is inefficient. Let's just get the time and set it.
 	//Retrieves node with DB Call which is inefficient. Let's just get the time and set it.
 	//node = functions.GetNodeByMacAddress(params["group"], params["macaddress"])
 	//node = functions.GetNodeByMacAddress(params["group"], params["macaddress"])
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -463,7 +463,7 @@ func getLastModified(w http.ResponseWriter, r *http.Request) {
         var group models.Group
         var group models.Group
         var params = mux.Vars(r)
         var params = mux.Vars(r)
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -565,7 +565,7 @@ func uncordonNode(w http.ResponseWriter, r *http.Request) {
 		return
 		return
         }
         }
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 

+ 6 - 6
controllers/userHttpController.go

@@ -60,7 +60,7 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
         } else {
         } else {
 
 
             //Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
             //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("wirecat").Collection("users")
+            collection := mongoconn.Client.Database("netmaker").Collection("users")
             ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
             ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	    var err = collection.FindOne(ctx, bson.M{ "username": authRequest.UserName }).Decode(&result)
 	    var err = collection.FindOne(ctx, bson.M{ "username": authRequest.UserName }).Decode(&result)
 
 
@@ -179,7 +179,7 @@ func authorizeUser(next http.Handler) http.HandlerFunc {
 
 
 func HasAdmin() (bool, error){
 func HasAdmin() (bool, error){
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("users")
+        collection := mongoconn.Client.Database("netmaker").Collection("users")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -217,7 +217,7 @@ func GetUser(username string) (models.User, error) {
 
 
         var user models.User
         var user models.User
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("users")
+        collection := mongoconn.Client.Database("netmaker").Collection("users")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -265,7 +265,7 @@ func CreateUser(user models.User) (models.User, error) {
         }
         }
 
 
         // connect db
         // connect db
-        collection := mongoconn.Client.Database("wirecat").Collection("users")
+        collection := mongoconn.Client.Database("netmaker").Collection("users")
         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.
@@ -336,7 +336,7 @@ func UpdateUser(userchange models.User, user models.User) (models.User, error) {
         user.Password = userchange.Password
         user.Password = userchange.Password
     }
     }
         //collection := mongoconn.ConnectDB()
         //collection := mongoconn.ConnectDB()
-        collection := mongoconn.Client.Database("wirecat").Collection("users")
+        collection := mongoconn.Client.Database("netmaker").Collection("users")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -416,7 +416,7 @@ func DeleteUser(user string) (bool, error)  {
 
 
         deleted := false
         deleted := false
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("users")
+        collection := mongoconn.Client.Database("netmaker").Collection("users")
 
 
         filter := bson.M{"username": user}
         filter := bson.M{"username": user}
 
 

+ 1 - 1
docs/API.md

@@ -35,7 +35,7 @@
 **Authenticate User:** "/users/authenticate", "POST"  
 **Authenticate User:** "/users/authenticate", "POST"  
 
 
 *note: users API does not use /api/ because of  a weird bug. Will fix in  future release.
 *note: users API does not use /api/ because of  a weird bug. Will fix in  future release.
-**note: Only able to create Admin at this time. The "user" is only used by the [user interface](https://github.com/falconcat-inc/WireCat-UI) to authenticate the  single  admin user.
+**note: Only able to create Admin at this time. The "user" is only used by the [user interface](https://github.com/gravitl/netmaker-ui) to authenticate the  single  admin user.
 
 
 ### Files
 ### Files
 **Get File:** "/meshclient/files/{filename}", "GET"  
 **Get File:** "/meshclient/files/{filename}", "GET"  

+ 3 - 3
docs/GETTING_STARTED.md

@@ -2,8 +2,8 @@
 ### Server Setup
 ### Server Setup
  1. Get yourself a linux server and make sure it has a public IP.
  1. Get yourself a linux server and make sure it has a public IP.
  2. Deploy MongoDB `docker volume create mongovol && docker run -d --name mongodb -v mongovol:/data/db --network host -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=mongopass mongo --bind_ip 0.0.0.0 `
  2. Deploy MongoDB `docker volume create mongovol && docker run -d --name mongodb -v mongovol:/data/db --network host -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=mongopass mongo --bind_ip 0.0.0.0 `
- 3. Pull this repo: `git clone https://github.com/falconcat-inc/WireCat.git`
- 4. Switch to the directory and source the default env vars `cd WireCat && source defaultvars.sh`
+ 3. Pull this repo: `git clone https://github.com/gravitl/netmaker.git`
+ 4. Switch to the directory and source the default env vars `cd netmaker && source defaultvars.sh`
  5. Run the server: `go run ./`
  5. Run the server: `go run ./`
 ### Optional (For  Testing):  Create Groups and Nodes
 ### Optional (For  Testing):  Create Groups and Nodes
  
  
@@ -13,7 +13,7 @@
  4. Create Nodes: `./test/nodescreate.sh`
  4. Create Nodes: `./test/nodescreate.sh`
  5. Check to see if nodes were created: `curl -H "authorization: Bearer secretkey" localhost:8081/api/skynet/nodes | jq`
  5. Check to see if nodes were created: `curl -H "authorization: Bearer secretkey" localhost:8081/api/skynet/nodes | jq`
 ### UI Setup
 ### UI Setup
-Please see [this repo](https://github.com/falconcat-inc/WireCat-UI)  for instructions on setting up your UI.
+Please see [this repo](https://github.com/gravitl/netmaker-ui)  for instructions on setting up your UI.
 
 
 ### Agent  Setup
 ### Agent  Setup
 
 

+ 1 - 1
docs/ROADMAP.md

@@ -71,7 +71,7 @@
  - [ ] "Read Only" mode for nodes (can't update their settings centrally, only read)
  - [ ] "Read Only" mode for nodes (can't update their settings centrally, only read)
  
  
 **Agent:**
 **Agent:**
- - [ ] Do system calls instead of direct comma[this repo](https://github.com/falconcat-inc/WireCat-UI)nds
+ - [ ] Do system calls instead of direct commands [this repo](https://github.com/gravitl/netmaker-ui)
  - [ ] Add a prompt for easy setup
  - [ ] Add a prompt for easy setup
  - [ ] Make it work as a sidecar container!!!
  - [ ] Make it work as a sidecar container!!!
 
 

+ 10 - 10
functions/helpers.go

@@ -29,7 +29,7 @@ func IsFieldUnique(group string,  field string, value string) bool {
 	var node models.Node
 	var node models.Node
 	isunique := true
 	isunique := true
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
 	filter := bson.M{field: value, "group": group}
 	filter := bson.M{field: value, "group": group}
@@ -51,7 +51,7 @@ func IsFieldUnique(group string,  field string, value string) bool {
 
 
 func GroupExists(name string) (bool, error) {
 func GroupExists(name string) (bool, error) {
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -78,7 +78,7 @@ func GroupExists(name string) (bool, error) {
 func UpdateGroupNodeAddresses(groupName string) error {
 func UpdateGroupNodeAddresses(groupName string) error {
 
 
         //Connection mongoDB with mongoconn class
         //Connection mongoDB with mongoconn class
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -158,7 +158,7 @@ func IsGroupDisplayNameUnique(name string) bool {
 func ListGroups() []models.Group{
 func ListGroups() []models.Group{
         var groups []models.Group
         var groups []models.Group
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -222,7 +222,7 @@ func GetParentGroup(groupname string) (models.Group, error) {
 
 
         var group models.Group
         var group models.Group
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -275,7 +275,7 @@ func GetNodeObj(id primitive.ObjectID) models.Node {
 
 
         var node models.Node
         var node models.Node
 
 
-	collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+	collection := mongoconn.Client.Database("netmaker").Collection("nodes")
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
         filter := bson.M{"_id": id}
         filter := bson.M{"_id": id}
@@ -329,7 +329,7 @@ func GetNodeByMacAddress(group string, macaddress string) (models.Node, error) {
 
 
 	filter := bson.M{"macaddress": macaddress, "group": group}
 	filter := bson.M{"macaddress": macaddress, "group": group}
 
 
-	collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+	collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -420,7 +420,7 @@ func IsIPUnique(group string, ip string) bool {
 
 
 	isunique := true
 	isunique := true
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("nodes")
+        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
 	filter := bson.M{"address": ip, "group": group}
 	filter := bson.M{"address": ip, "group": group}
@@ -465,7 +465,7 @@ func DecrimentKey(groupName string, keyvalue string) {
                 }
                 }
         }
         }
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
@@ -490,7 +490,7 @@ func DeleteKey(group models.Group, i int) {
 	group.AccessKeys = append(group.AccessKeys[:i],
 	group.AccessKeys = append(group.AccessKeys[:i],
                                 group.AccessKeys[i+1:]...)
                                 group.AccessKeys[i+1:]...)
 
 
-        collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 

+ 620 - 0
group_test.go

@@ -0,0 +1,620 @@
+package main
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"testing"
+
+	"github.com/gravitl/netmaker/models"
+	"github.com/stretchr/testify/assert"
+	"go.mongodb.org/mongo-driver/mongo"
+)
+
+var Groups []models.Group
+
+func TestCreateGroup(t *testing.T) {
+	group := models.Group{}
+	group.NameID = "skynet"
+	group.AddressRange = "10.71.0.0/16"
+	t.Run("CreateGroup", func(t *testing.T) {
+		response, err := api(t, group, http.MethodPost, "http://localhost:8081/api/groups", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, group, http.MethodPost, "http://localhost:8081/api/groups", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("BadName", func(t *testing.T) {
+		//issue #42
+		t.Skip()
+	})
+	t.Run("BadAddress", func(t *testing.T) {
+		//issue #42
+		t.Skip()
+	})
+	t.Run("DuplicateGroup", func(t *testing.T) {
+		//issue #42
+		t.Skip()
+	})
+}
+
+func TestGetGroups(t *testing.T) {
+	t.Run("ValidToken", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		err = json.NewDecoder(response.Body).Decode(&Groups)
+		assert.Nil(t, err, err)
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+}
+
+func TestGetGroup(t *testing.T) {
+	t.Run("ValidToken", func(t *testing.T) {
+		var group models.Group
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		err = json.NewDecoder(response.Body).Decode(&group)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "skynet", group.DisplayName)
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("InvalidGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/badgroup", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+}
+
+func TestGetGroupNodeNumber(t *testing.T) {
+	t.Run("ValidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/numnodes", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message int
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		//assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+	})
+	t.Run("InvalidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/numnodes", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("BadGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/badgroup/numnodes", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+}
+
+func TestDeleteGroup(t *testing.T) {
+	t.Run("InvalidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("ValidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message mongo.DeleteResult
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		assert.Equal(t, int64(1), message.DeletedCount)
+
+	})
+	t.Run("BadGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/badgroup", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("NodesExist", func(t *testing.T) {
+		t.Skip()
+	})
+	//Create Group for follow-on tests
+	createGroup(t)
+}
+
+func TestCreateAccessKey(t *testing.T) {
+	key := models.AccessKey{}
+	key.Name = "skynet"
+	key.Uses = 10
+	t.Run("MultiUse", func(t *testing.T) {
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		message, err := ioutil.ReadAll(response.Body)
+		assert.Nil(t, err, err)
+		assert.NotNil(t, message, message)
+		returnedkey := getKey(t, key.Name)
+		assert.Equal(t, key.Name, returnedkey.Name)
+		assert.Equal(t, key.Uses, returnedkey.Uses)
+	})
+	deleteKey(t, "skynet", "skynet")
+	t.Run("ZeroUse", func(t *testing.T) {
+		//t.Skip()
+		key.Uses = 0
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		message, err := ioutil.ReadAll(response.Body)
+		assert.Nil(t, err, err)
+		assert.NotNil(t, message, message)
+		returnedkey := getKey(t, key.Name)
+		assert.Equal(t, key.Name, returnedkey.Name)
+		assert.Equal(t, 1, returnedkey.Uses)
+	})
+	t.Run("DuplicateAccessKey", func(t *testing.T) {
+		//t.Skip()
+		//this will fail
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+		deleteKey(t, key.Name, "skynet")
+	})
+
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("BadGroup", func(t *testing.T) {
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/badgroup/keys", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+}
+
+func TestDeleteKey(t *testing.T) {
+	t.Run("KeyValid", func(t *testing.T) {
+		//fails -- deletecount not returned
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet/keys/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message mongo.DeleteResult
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		assert.Equal(t, int64(1), message.DeletedCount)
+	})
+	t.Run("InValidKey", func(t *testing.T) {
+		//fails -- status message  not returned
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet/keys/badkey", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This key does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("KeyInValidGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/badgroup/keys/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("InvalidCredentials", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet/keys/skynet", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+}
+
+func TestGetKeys(t *testing.T) {
+	createKey(t)
+	t.Run("Valid", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		var keys []models.AccessKey
+		err = json.NewDecoder(response.Body).Decode(&keys)
+		assert.Nil(t, err, err)
+	})
+	//deletekeys
+	t.Run("InvalidGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/badgroup/keys", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("InvalidCredentials", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/keys", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+}
+
+func TestUpdateGroup(t *testing.T) {
+	var returnedGroup models.Group
+	t.Run("UpdateNameID", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.NameID, returnedGroup.NameID)
+	})
+	t.Run("NameIDInvalidCredentials", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "badkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+	})
+	t.Run("InvalidGroup", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/badgroup", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusNotFound, message.Code)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("UpdateNameIDTooLong", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat-skynet"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateAddress", func(t *testing.T) {
+		type Group struct {
+			AddressRange string
+		}
+		var group Group
+		group.AddressRange = "10.0.0.1/24"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.AddressRange, returnedGroup.AddressRange)
+	})
+	t.Run("UpdateAddressInvalid", func(t *testing.T) {
+		type Group struct {
+			AddressRange string
+		}
+		var group Group
+		group.AddressRange = "10.0.0.1/36"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateDisplayName", func(t *testing.T) {
+		type Group struct {
+			DisplayName string
+		}
+		var group Group
+		group.DisplayName = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DisplayName, returnedGroup.DisplayName)
+
+	})
+	t.Run("UpdateDisplayNameInvalidName", func(t *testing.T) {
+		type Group struct {
+			DisplayName string
+		}
+		var group Group
+		//create name that is longer than 100 chars
+		name := ""
+		for i := 0; i < 101; i++ {
+			name = name + "a"
+		}
+		group.DisplayName = name
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DisplayName' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateInterface", func(t *testing.T) {
+		type Group struct {
+			DefaultInterface string
+		}
+		var group Group
+		group.DefaultInterface = "netmaker"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultInterface, returnedGroup.DefaultInterface)
+
+	})
+	t.Run("UpdateListenPort", func(t *testing.T) {
+		type Group struct {
+			DefaultListenPort int32
+		}
+		var group Group
+		group.DefaultListenPort = 6000
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultListenPort, returnedGroup.DefaultListenPort)
+	})
+	t.Run("UpdateListenPortInvalidPort", func(t *testing.T) {
+		type Group struct {
+			DefaultListenPort int32
+		}
+		var group Group
+		group.DefaultListenPort = 1023
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DefaultListenPort' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdatePostUP", func(t *testing.T) {
+		type Group struct {
+			DefaultPostUp string
+		}
+		var group Group
+		group.DefaultPostUp = "sudo wg add-conf wc-netmaker /etc/wireguard/peers/conf"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultPostUp, returnedGroup.DefaultPostUp)
+	})
+	t.Run("UpdatePreUP", func(t *testing.T) {
+		type Group struct {
+			DefaultPreUp string
+		}
+		var group Group
+		group.DefaultPreUp = "test string"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultPreUp, returnedGroup.DefaultPreUp)
+	})
+	t.Run("UpdateKeepAlive", func(t *testing.T) {
+		type Group struct {
+			DefaultKeepalive int32
+		}
+		var group Group
+		group.DefaultKeepalive = 60
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultKeepalive, returnedGroup.DefaultKeepalive)
+	})
+	t.Run("UpdateKeepAliveTooBig", func(t *testing.T) {
+		type Group struct {
+			DefaultKeepAlive int32
+		}
+		var group Group
+		group.DefaultKeepAlive = 1001
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DefaultKeepAlive' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateSaveConfig", func(t *testing.T) {
+		//causes panic
+		t.Skip()
+		type Group struct {
+			DefaultSaveConfig *bool
+		}
+		var group Group
+		value := false
+		group.DefaultSaveConfig = &value
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, *group.DefaultSaveConfig, *returnedGroup.DefaultSaveConfig)
+	})
+	t.Run("UpdateManualSignUP", func(t *testing.T) {
+		t.Skip()
+		type Group struct {
+			AllowManualSignUp *bool
+		}
+		var group Group
+		value := true
+		group.AllowManualSignUp = &value
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, *group.AllowManualSignUp, *returnedGroup.AllowManualSignUp)
+	})
+	t.Run("DefaultCheckInterval", func(t *testing.T) {
+		type Group struct {
+			DefaultCheckInInterval int32
+		}
+		var group Group
+		group.DefaultCheckInInterval = 6000
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultCheckInInterval, returnedGroup.DefaultCheckInInterval)
+	})
+	t.Run("DefaultCheckIntervalTooBig", func(t *testing.T) {
+		type Group struct {
+			DefaultCheckInInterval int32
+		}
+		var group Group
+		group.DefaultCheckInInterval = 100001
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DefaultCheckInInterval' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("MultipleFields", func(t *testing.T) {
+		type Group struct {
+			DisplayName       string
+			DefaultListenPort int32
+		}
+		var group Group
+		group.DefaultListenPort = 7777
+		group.DisplayName = "multi"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DisplayName, returnedGroup.DisplayName)
+		assert.Equal(t, group.DefaultListenPort, returnedGroup.DefaultListenPort)
+	})
+}

+ 3 - 5
models/group.go

@@ -41,10 +41,10 @@ func(group *Group) SetDefaults(){
         group.DisplayName = group.NameID
         group.DisplayName = group.NameID
     }
     }
     if group.DefaultInterface == "" {
     if group.DefaultInterface == "" {
-	group.DefaultInterface = "wc-" + group.NameID
+	group.DefaultInterface = "nm-" + group.NameID
     }
     }
     if group.DefaultListenPort == 0 {
     if group.DefaultListenPort == 0 {
-        group.DefaultListenPort = 5555
+        group.DefaultListenPort = 51821
     }
     }
     if group.DefaultPreUp == "" {
     if group.DefaultPreUp == "" {
 
 
@@ -57,12 +57,10 @@ func(group *Group) SetDefaults(){
         group.DefaultKeepalive = 20
         group.DefaultKeepalive = 20
     }
     }
     if group.DefaultPostUp == "" {
     if group.DefaultPostUp == "" {
-            postup := "sudo wg addconf " + group.DefaultInterface + " /etc/wireguard/peers.conf"
-        group.DefaultPostUp = postup
     }
     }
     //Check-In Interval for Nodes, In Seconds
     //Check-In Interval for Nodes, In Seconds
     if group.DefaultCheckInInterval == 0 {
     if group.DefaultCheckInInterval == 0 {
-        group.DefaultCheckInInterval = 120
+        group.DefaultCheckInInterval = 30
     }
     }
     if group.AllowManualSignUp == nil {
     if group.AllowManualSignUp == nil {
 	signup := false
 	signup := false

+ 1 - 1
models/node.go

@@ -49,7 +49,7 @@ func(node *Node) GetGroup() (Group, error){
         var group Group
         var group Group
 
 
         collection := mongoconn.GroupDB
         collection := mongoconn.GroupDB
-        //collection := mongoconn.Client.Database("wirecat").Collection("groups")
+        //collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 

+ 2 - 2
mongoconn/mongoconn.go

@@ -93,8 +93,8 @@ func ConnectDatabase() {
         log.Fatal(err)
         log.Fatal(err)
     }
     }
 
 
-    NodeDB = Client.Database("wirecat").Collection("nodes")
-    GroupDB = Client.Database("wirecat").Collection("groups")
+    NodeDB = Client.Database("netmaker").Collection("nodes")
+    GroupDB = Client.Database("netmaker").Collection("groups")
 
 
     log.Println("Database Connected.")
     log.Println("Database Connected.")
 }
 }

+ 2 - 2
netclient/main.go

@@ -15,8 +15,8 @@ import (
 
 
 const (
 const (
 	// name of the service
 	// name of the service
-	name        = "wcdaemon"
-	description = "Wirecat Daemon Service"
+	name        = "netclient"
+	description = "Netmaker Daemon Service"
 )
 )
 
 
 var password string
 var password string

+ 197 - 0
test/api_test.go

@@ -0,0 +1,197 @@
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"sync"
+	"testing"
+	"time"
+
+	controller "github.com/gravitl/netmaker/controllers"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mongoconn"
+	"github.com/stretchr/testify/assert"
+)
+
+type databaseError struct {
+	Inner  *int
+	Errors int
+}
+
+//should be use models.SuccessResponse and models.SuccessfulUserLoginResponse
+//rather than creating new type but having trouble decoding that way
+type Auth struct {
+	Username  string
+	AuthToken string
+}
+type Success struct {
+	Code     int
+	Message  string
+	Response Auth
+}
+
+type AuthorizeTestCase struct {
+	testname      string
+	name          string
+	password      string
+	code          int
+	tokenExpected bool
+	errMessage    string
+}
+
+func TestMain(m *testing.M) {
+	mongoconn.ConnectDatabase()
+	var waitgroup sync.WaitGroup
+	waitgroup.Add(1)
+	go controller.HandleRESTRequests(&waitgroup)
+	//wait for http server to start
+	time.Sleep(time.Second * 1)
+	os.Exit(m.Run())
+}
+
+func adminExists(t *testing.T) bool {
+	response, err := http.Get("http://localhost:8081/users/hasadmin")
+	assert.Nil(t, err, err)
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+	defer response.Body.Close()
+	var body bool
+	json.NewDecoder(response.Body).Decode(&body)
+	return body
+}
+
+func api(t *testing.T, data interface{}, method, url, authorization string) (*http.Response, error) {
+	var request *http.Request
+	var err error
+	if data != "" {
+		payload, err := json.Marshal(data)
+		assert.Nil(t, err, err)
+		request, err = http.NewRequest(method, url, bytes.NewBuffer(payload))
+		assert.Nil(t, err, err)
+		request.Header.Set("Content-Type", "application/json")
+	} else {
+		request, err = http.NewRequest(method, url, nil)
+		assert.Nil(t, err, err)
+	}
+	if authorization != "" {
+		request.Header.Set("Authorization", "Bearer "+authorization)
+	}
+	client := http.Client{}
+	return client.Do(request)
+}
+
+func addAdmin(t *testing.T) {
+	var admin models.User
+	admin.UserName = "admin"
+	admin.Password = "password"
+	response, err := api(t, admin, http.MethodPost, "http://localhost:8081/users/createadmin", "secretkey")
+	assert.Nil(t, err, err)
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+}
+
+func authenticate(t *testing.T) (string, error) {
+	var admin models.User
+	admin.UserName = "admin"
+	admin.Password = "password"
+	response, err := api(t, admin, http.MethodPost, "http://localhost:8081/users/authenticate", "secretkey")
+	assert.Nil(t, err, err)
+
+	var body Success
+	err = json.NewDecoder(response.Body).Decode(&body)
+	assert.Nil(t, err, err)
+	assert.NotEmpty(t, body.Response.AuthToken, "token not returned")
+	assert.Equal(t, "W1R3: Device admin Authorized", body.Message)
+
+	return body.Response.AuthToken, nil
+}
+
+func deleteAdmin(t *testing.T) {
+	if !adminExists(t) {
+		return
+	}
+	token, err := authenticate(t)
+	assert.Nil(t, err, err)
+	_, err = api(t, "", http.MethodDelete, "http://localhost:8081/users/admin", token)
+	assert.Nil(t, err, err)
+}
+
+func createGroup(t *testing.T) {
+	group := models.Group{}
+	group.NameID = "skynet"
+	group.AddressRange = "10.71.0.0/16"
+	response, err := api(t, group, http.MethodPost, "http://localhost:8081/api/groups", "secretkey")
+	assert.Nil(t, err, err)
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+}
+
+func createKey(t *testing.T) {
+	key := models.AccessKey{}
+	key.Name = "skynet"
+	key.Uses = 10
+	response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+	assert.Nil(t, err, err)
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+	defer response.Body.Close()
+	message, err := ioutil.ReadAll(response.Body)
+	assert.Nil(t, err, err)
+	assert.NotNil(t, message, message)
+}
+
+func getKey(t *testing.T, name string) models.AccessKey {
+	response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+	assert.Nil(t, err, err)
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+	defer response.Body.Close()
+	var keys []models.AccessKey
+	err = json.NewDecoder(response.Body).Decode(&keys)
+	assert.Nil(t, err, err)
+	for _, key := range keys {
+		if key.Name == name {
+			return key
+		}
+	}
+	return models.AccessKey{}
+}
+
+func deleteKey(t *testing.T, key, group string) {
+	response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/"+group+"/keys/"+key, "secretkey")
+	assert.Nil(t, err, err)
+	//api does not return Deleted Count at this time
+	//defer response.Body.Close()
+	//var message mongo.DeleteResult
+	//err = json.NewDecoder(response.Body).Decode(&message)
+	//assert.Nil(t, err, err)
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+	//assert.Equal(t, int64(1), message.DeletedCount)
+}
+
+func groupExists(t *testing.T) bool {
+	response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups", "secretkey")
+	assert.Nil(t, err, err)
+	defer response.Body.Close()
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+	err = json.NewDecoder(response.Body).Decode(&Groups)
+	assert.Nil(t, err, err)
+	if Groups == nil {
+		return false
+	} else {
+		return true
+	}
+}
+
+func deleteGroups(t *testing.T) {
+
+	response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups", "secretkey")
+	assert.Nil(t, err, err)
+	defer response.Body.Close()
+	assert.Equal(t, http.StatusOK, response.StatusCode)
+	err = json.NewDecoder(response.Body).Decode(&Groups)
+	assert.Nil(t, err, err)
+	for _, group := range Groups {
+		name := group.DisplayName
+		_, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/"+name, "secretkey")
+		assert.Nil(t, err, err)
+	}
+}

+ 14 - 0
test/config/environments/dev.yaml

@@ -0,0 +1,14 @@
+server:
+  host: "localhost"
+  apiport: "8081"
+  grpcport: "50051"
+  masterkey: "secretkey"
+  allowedorigin: "*"
+  restbackend: true            
+  agentbackend: true
+mongoconn:
+  user: "mongoadmin"
+  pass: "mongopass"
+  host: "localhost"
+  port: "27017"
+  opts: '/?authSource=admin'

+ 621 - 0
test/group_test.go

@@ -0,0 +1,621 @@
+package main
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"testing"
+
+	"github.com/gravitl/netmaker/models"
+	"github.com/stretchr/testify/assert"
+	"go.mongodb.org/mongo-driver/mongo"
+)
+
+var Groups []models.Group
+
+func TestCreateGroup(t *testing.T) {
+	group := models.Group{}
+	group.NameID = "skynet"
+	group.AddressRange = "10.71.0.0/16"
+	deleteGroups(t)
+	t.Run("CreateGroup", func(t *testing.T) {
+		response, err := api(t, group, http.MethodPost, "http://localhost:8081/api/groups", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, group, http.MethodPost, "http://localhost:8081/api/groups", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("BadName", func(t *testing.T) {
+		//issue #42
+		t.Skip()
+	})
+	t.Run("BadAddress", func(t *testing.T) {
+		//issue #42
+		t.Skip()
+	})
+	t.Run("DuplicateGroup", func(t *testing.T) {
+		//issue #42
+		t.Skip()
+	})
+}
+
+func TestGetGroups(t *testing.T) {
+	t.Run("ValidToken", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		err = json.NewDecoder(response.Body).Decode(&Groups)
+		assert.Nil(t, err, err)
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+}
+
+func TestGetGroup(t *testing.T) {
+	t.Run("ValidToken", func(t *testing.T) {
+		var group models.Group
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		err = json.NewDecoder(response.Body).Decode(&group)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "skynet", group.DisplayName)
+	})
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("InvalidGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/badgroup", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+}
+
+func TestGetGroupNodeNumber(t *testing.T) {
+	t.Run("ValidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/numnodes", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message int
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		//assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+	})
+	t.Run("InvalidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/numnodes", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("BadGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/badgroup/numnodes", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+}
+
+func TestDeleteGroup(t *testing.T) {
+	t.Run("InvalidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet", "badkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("ValidKey", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message mongo.DeleteResult
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		assert.Equal(t, int64(1), message.DeletedCount)
+
+	})
+	t.Run("BadGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/badgroup", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("NodesExist", func(t *testing.T) {
+		t.Skip()
+	})
+	//Create Group for follow-on tests
+	createGroup(t)
+}
+
+func TestCreateAccessKey(t *testing.T) {
+	key := models.AccessKey{}
+	key.Name = "skynet"
+	key.Uses = 10
+	t.Run("MultiUse", func(t *testing.T) {
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		message, err := ioutil.ReadAll(response.Body)
+		assert.Nil(t, err, err)
+		assert.NotNil(t, message, message)
+		returnedkey := getKey(t, key.Name)
+		assert.Equal(t, key.Name, returnedkey.Name)
+		assert.Equal(t, key.Uses, returnedkey.Uses)
+	})
+	deleteKey(t, "skynet", "skynet")
+	t.Run("ZeroUse", func(t *testing.T) {
+		//t.Skip()
+		key.Uses = 0
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		message, err := ioutil.ReadAll(response.Body)
+		assert.Nil(t, err, err)
+		assert.NotNil(t, message, message)
+		returnedkey := getKey(t, key.Name)
+		assert.Equal(t, key.Name, returnedkey.Name)
+		assert.Equal(t, 1, returnedkey.Uses)
+	})
+	t.Run("DuplicateAccessKey", func(t *testing.T) {
+		//t.Skip()
+		//this will fail
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+		deleteKey(t, key.Name, "skynet")
+	})
+
+	t.Run("InvalidToken", func(t *testing.T) {
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/skynet/keys", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+	t.Run("BadGroup", func(t *testing.T) {
+		response, err := api(t, key, http.MethodPost, "http://localhost:8081/api/groups/badgroup/keys", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+}
+
+func TestDeleteKey(t *testing.T) {
+	t.Run("KeyValid", func(t *testing.T) {
+		//fails -- deletecount not returned
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet/keys/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message mongo.DeleteResult
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		assert.Equal(t, int64(1), message.DeletedCount)
+	})
+	t.Run("InValidKey", func(t *testing.T) {
+		//fails -- status message  not returned
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet/keys/badkey", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This key does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("KeyInValidGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/badgroup/keys/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("InvalidCredentials", func(t *testing.T) {
+		response, err := api(t, "", http.MethodDelete, "http://localhost:8081/api/groups/skynet/keys/skynet", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+}
+
+func TestGetKeys(t *testing.T) {
+	createKey(t)
+	t.Run("Valid", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/keys", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		var keys []models.AccessKey
+		err = json.NewDecoder(response.Body).Decode(&keys)
+		assert.Nil(t, err, err)
+	})
+	//deletekeys
+	t.Run("InvalidGroup", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/badgroup/keys", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("InvalidCredentials", func(t *testing.T) {
+		response, err := api(t, "", http.MethodGet, "http://localhost:8081/api/groups/skynet/keys", "badkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+	})
+}
+
+func TestUpdateGroup(t *testing.T) {
+	var returnedGroup models.Group
+	t.Run("UpdateNameID", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.NameID, returnedGroup.NameID)
+	})
+	t.Run("NameIDInvalidCredentials", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "badkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnauthorized, message.Code)
+		assert.Equal(t, "W1R3: You are unauthorized to access this endpoint.", message.Message)
+		assert.Equal(t, http.StatusUnauthorized, response.StatusCode)
+	})
+	t.Run("InvalidGroup", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/badgroup", "secretkey")
+		assert.Nil(t, err, err)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusNotFound, message.Code)
+		assert.Equal(t, "W1R3: This group does not exist.", message.Message)
+		assert.Equal(t, http.StatusNotFound, response.StatusCode)
+	})
+	t.Run("UpdateNameIDTooLong", func(t *testing.T) {
+		type Group struct {
+			NameID string
+		}
+		var group Group
+		group.NameID = "wirecat-skynet"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateAddress", func(t *testing.T) {
+		type Group struct {
+			AddressRange string
+		}
+		var group Group
+		group.AddressRange = "10.0.0.1/24"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.AddressRange, returnedGroup.AddressRange)
+	})
+	t.Run("UpdateAddressInvalid", func(t *testing.T) {
+		type Group struct {
+			AddressRange string
+		}
+		var group Group
+		group.AddressRange = "10.0.0.1/36"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateDisplayName", func(t *testing.T) {
+		type Group struct {
+			DisplayName string
+		}
+		var group Group
+		group.DisplayName = "wirecat"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DisplayName, returnedGroup.DisplayName)
+
+	})
+	t.Run("UpdateDisplayNameInvalidName", func(t *testing.T) {
+		type Group struct {
+			DisplayName string
+		}
+		var group Group
+		//create name that is longer than 100 chars
+		name := ""
+		for i := 0; i < 101; i++ {
+			name = name + "a"
+		}
+		group.DisplayName = name
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DisplayName' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateInterface", func(t *testing.T) {
+		type Group struct {
+			DefaultInterface string
+		}
+		var group Group
+		group.DefaultInterface = "netmaker"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultInterface, returnedGroup.DefaultInterface)
+
+	})
+	t.Run("UpdateListenPort", func(t *testing.T) {
+		type Group struct {
+			DefaultListenPort int32
+		}
+		var group Group
+		group.DefaultListenPort = 6000
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultListenPort, returnedGroup.DefaultListenPort)
+	})
+	t.Run("UpdateListenPortInvalidPort", func(t *testing.T) {
+		type Group struct {
+			DefaultListenPort int32
+		}
+		var group Group
+		group.DefaultListenPort = 1023
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DefaultListenPort' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdatePostUP", func(t *testing.T) {
+		type Group struct {
+			DefaultPostUp string
+		}
+		var group Group
+		group.DefaultPostUp = "sudo wg add-conf wc-netmaker /etc/wireguard/peers/conf"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultPostUp, returnedGroup.DefaultPostUp)
+	})
+	t.Run("UpdatePreUP", func(t *testing.T) {
+		type Group struct {
+			DefaultPreUp string
+		}
+		var group Group
+		group.DefaultPreUp = "test string"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultPreUp, returnedGroup.DefaultPreUp)
+	})
+	t.Run("UpdateKeepAlive", func(t *testing.T) {
+		type Group struct {
+			DefaultKeepalive int32
+		}
+		var group Group
+		group.DefaultKeepalive = 60
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultKeepalive, returnedGroup.DefaultKeepalive)
+	})
+	t.Run("UpdateKeepAliveTooBig", func(t *testing.T) {
+		type Group struct {
+			DefaultKeepAlive int32
+		}
+		var group Group
+		group.DefaultKeepAlive = 1001
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DefaultKeepAlive' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("UpdateSaveConfig", func(t *testing.T) {
+		//causes panic
+		t.Skip()
+		type Group struct {
+			DefaultSaveConfig *bool
+		}
+		var group Group
+		value := false
+		group.DefaultSaveConfig = &value
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, *group.DefaultSaveConfig, *returnedGroup.DefaultSaveConfig)
+	})
+	t.Run("UpdateManualSignUP", func(t *testing.T) {
+		t.Skip()
+		type Group struct {
+			AllowManualSignUp *bool
+		}
+		var group Group
+		value := true
+		group.AllowManualSignUp = &value
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, *group.AllowManualSignUp, *returnedGroup.AllowManualSignUp)
+	})
+	t.Run("DefaultCheckInterval", func(t *testing.T) {
+		type Group struct {
+			DefaultCheckInInterval int32
+		}
+		var group Group
+		group.DefaultCheckInInterval = 6000
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DefaultCheckInInterval, returnedGroup.DefaultCheckInInterval)
+	})
+	t.Run("DefaultCheckIntervalTooBig", func(t *testing.T) {
+		type Group struct {
+			DefaultCheckInInterval int32
+		}
+		var group Group
+		group.DefaultCheckInInterval = 100001
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusUnprocessableEntity, message.Code)
+		assert.Equal(t, "W1R3: Field validation for 'DefaultCheckInInterval' failed.", message.Message)
+		assert.Equal(t, http.StatusUnprocessableEntity, response.StatusCode)
+	})
+	t.Run("MultipleFields", func(t *testing.T) {
+		type Group struct {
+			DisplayName       string
+			DefaultListenPort int32
+		}
+		var group Group
+		group.DefaultListenPort = 7777
+		group.DisplayName = "multi"
+		response, err := api(t, group, http.MethodPut, "http://localhost:8081/api/groups/skynet", "secretkey")
+		assert.Nil(t, err, err)
+		assert.Equal(t, http.StatusOK, response.StatusCode)
+		defer response.Body.Close()
+		err = json.NewDecoder(response.Body).Decode(&returnedGroup)
+		assert.Nil(t, err, err)
+		assert.Equal(t, group.DisplayName, returnedGroup.DisplayName)
+		assert.Equal(t, group.DefaultListenPort, returnedGroup.DefaultListenPort)
+	})
+}

+ 0 - 107
user_test.go → test/user_test.go

@@ -1,56 +1,14 @@
 package main
 package main
 
 
 import (
 import (
-	"bytes"
 	"encoding/json"
 	"encoding/json"
 	"net/http"
 	"net/http"
-	"os"
-	"sync"
 	"testing"
 	"testing"
-	"time"
 
 
-	controller "github.com/gravitl/netmaker/controllers"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
-	"github.com/gravitl/netmaker/mongoconn"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
 )
 )
 
 
-type databaseError struct {
-	Inner  *int
-	Errors int
-}
-
-//should be use models.SuccessResponse and models.SuccessfulUserLoginResponse
-//rather than creating new type but having trouble decoding that way
-type Auth struct {
-	Username  string
-	AuthToken string
-}
-type Success struct {
-	Code     int
-	Message  string
-	Response Auth
-}
-
-type AuthorizeTestCase struct {
-	testname      string
-	name          string
-	password      string
-	code          int
-	tokenExpected bool
-	errMessage    string
-}
-
-func TestMain(m *testing.M) {
-	mongoconn.ConnectDatabase()
-	var waitgroup sync.WaitGroup
-	waitgroup.Add(1)
-	go controller.HandleRESTRequests(&waitgroup)
-	//wait for http server to start
-	time.Sleep(time.Second * 1)
-	os.Exit(m.Run())
-}
-
 func TestAdminCreation(t *testing.T) {
 func TestAdminCreation(t *testing.T) {
 	var admin models.UserAuthParams
 	var admin models.UserAuthParams
 	var user models.User
 	var user models.User
@@ -260,68 +218,3 @@ func TestAuthenticateUser(t *testing.T) {
 		})
 		})
 	}
 	}
 }
 }
-
-func adminExists(t *testing.T) bool {
-	response, err := http.Get("http://localhost:8081/users/hasadmin")
-	assert.Nil(t, err, err)
-	assert.Equal(t, http.StatusOK, response.StatusCode)
-	defer response.Body.Close()
-	var body bool
-	json.NewDecoder(response.Body).Decode(&body)
-	return body
-}
-
-func api(t *testing.T, data interface{}, method, url, authorization string) (*http.Response, error) {
-	var request *http.Request
-	var err error
-	if data != "" {
-		payload, err := json.Marshal(data)
-		assert.Nil(t, err, err)
-		request, err = http.NewRequest(method, url, bytes.NewBuffer(payload))
-		assert.Nil(t, err, err)
-		request.Header.Set("Content-Type", "application/json")
-	} else {
-		request, err = http.NewRequest(method, url, nil)
-		assert.Nil(t, err, err)
-	}
-	if authorization != "" {
-		request.Header.Set("Authorization", "Bearer "+authorization)
-	}
-	client := http.Client{}
-	return client.Do(request)
-}
-
-func addAdmin(t *testing.T) {
-	var admin models.User
-	admin.UserName = "admin"
-	admin.Password = "password"
-	response, err := api(t, admin, http.MethodPost, "http://localhost:8081/users/createadmin", "secretkey")
-	assert.Nil(t, err, err)
-	assert.Equal(t, http.StatusOK, response.StatusCode)
-}
-
-func authenticate(t *testing.T) (string, error) {
-	var admin models.User
-	admin.UserName = "admin"
-	admin.Password = "password"
-	response, err := api(t, admin, http.MethodPost, "http://localhost:8081/users/authenticate", "secretkey")
-	assert.Nil(t, err, err)
-
-	var body Success
-	err = json.NewDecoder(response.Body).Decode(&body)
-	assert.Nil(t, err, err)
-	assert.NotEmpty(t, body.Response.AuthToken, "token not returned")
-	assert.Equal(t, "W1R3: Device admin Authorized", body.Message)
-
-	return body.Response.AuthToken, nil
-}
-
-func deleteAdmin(t *testing.T) {
-	if !adminExists(t) {
-		return
-	}
-	token, err := authenticate(t)
-	assert.Nil(t, err, err)
-	_, err = api(t, "", http.MethodDelete, "http://localhost:8081/users/admin", token)
-	assert.Nil(t, err, err)
-}