diff --git a/server/models.go b/server/models.go index 1e70ca1..5540364 100644 --- a/server/models.go +++ b/server/models.go @@ -56,6 +56,15 @@ type ServerSpecs struct { GPU string `form:"GPU" binding:"required" bson:GPU` } +// BarrierIP Barrier connection information +type BarrierIP struct { + ID string `bson: ID` + BarrierIP string `form:"BarrierIP" binding:"required" bson:hostname` + MachineName string `form:"MachineName" binding:"required" bson:hostname` + UserID string `json:"UserID"` + User Users `gorm:"foreignKey:UserID;references:UserID" json:"ServerInformation"` +} + // CreateTables CreateDB Add tables to the database func CreateTables(db *gorm.DB) (*gorm.DB, error) { // Creates table to store login sessions @@ -66,6 +75,8 @@ func CreateTables(db *gorm.DB) (*gorm.DB, error) { db.AutoMigrate(GameSession{}) // Creates table of type ServerSpecs db.AutoMigrate(ServerSpecs{}) + // Creates table of type BarrierIP + db.AutoMigrate(BarrierIP{}) // returns variable DB of type *gorm.DB and error // which is nil at the current moment return db, nil @@ -348,3 +359,60 @@ func GetUserInformation(db *gorm.DB, SessionID string) (*Users, error) { return nil, errors.New("Session not found. ") } + +// AddBarrierIP Adds barrierIP information to barrier table +func AddBarrierIP(db *gorm.DB, SessionID string, barrierIP string, MachineName string) (*BarrierIP, error) { + // Get User Information + user, err := GetUserInformation(db, SessionID) + if err != nil { + return nil, err + } + + // Check if the barrier IP exists + exists, err := CheckIfBarrierAddressExists(db, barrierIP) + if err != nil { + return nil, err + } + + if exists == false { + var NewBarrierIP BarrierIP + NewBarrierIP.BarrierIP = barrierIP + NewBarrierIP.UserID = user.UserID + NewBarrierIP.MachineName = MachineName + + // creates barrier table with info + db.Create(NewBarrierIP) + + return &NewBarrierIP, nil + } + + return nil, errors.New("BarrierIP already exists. ") +} + +// CheckIfBarrierAddressExists Check if the barrier ip +// address with port exists +func CheckIfBarrierAddressExists(db *gorm.DB, barrierIP string) (bool, error) { + BarrierRows, err := db.Model(&BarrierIP{}).Where("barrier_ip = ? ", barrierIP).Rows() + if err != nil { + return false, err + } + defer BarrierRows.Close() + + // Checks if there is more than one entry and returns + // true if that entry exists. + if BarrierRows.Next() { + return true, nil + } + + return false, nil +} + +// RemoveBarrierIP Remove barrier row based on the IP address provided +func RemoveBarrierIP(db *gorm.DB, barrierIP string) error { + // Delete session from the database + err := db.Where("barrier_ip = ?", barrierIP).Delete(BarrierIP{}) + if err != nil { + return err.Error + } + return nil +} diff --git a/server/server.go b/server/server.go index 726a0cb..0412b4a 100644 --- a/server/server.go +++ b/server/server.go @@ -1,223 +1,261 @@ package server import ( - "crypto/tls" - "fmt" - "github.com/gin-gonic/gin" - "gorm.io/gorm" - "net/http" - "strconv" - "time" + "crypto/tls" + "fmt" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "net/http" + "strconv" + "time" ) // Server Starts the server for the client side func Server(port string) error { - r := gin.Default() + r := gin.Default() - r.Static("/assets", "./templates/assets") + r.Static("/assets", "./templates/assets") - r.LoadHTMLGlob("./templates/*.html") - // htmlRender.TemplatesDir = "templates/" // default - // htmlRender.Ext = ".html" // default + r.LoadHTMLGlob("./templates/*.html") + // htmlRender.TemplatesDir = "templates/" // default + // htmlRender.Ext = ".html" // default - // Tell gin to use our html render + // Tell gin to use our html render - // Initialise connection to Sqlite DB - connect, err := Connect() - if err != nil { - return err - } + // Initialise connection to Sqlite DB + connect, err := Connect() + if err != nil { + return err + } - // Gets default information about the game sessions - r.GET("/", func(c *gin.Context) { - // Get client session ID - session, err := c.Cookie("SessionID") - if err != nil { - c.Redirect(http.StatusFound, "/login") - } + // Gets default information about the game sessions + r.GET("/", func(c *gin.Context) { + // Get client session ID + session, err := c.Cookie("SessionID") + if err != nil { + c.Redirect(http.StatusFound, "/login") + } - // User information based on session ID - User, err := GetUserInformation(connect, session) - if err != nil { - c.Redirect(http.StatusFound, "/login") - } + // User information based on session ID + User, err := GetUserInformation(connect, session) + if err != nil { + c.Redirect(http.StatusFound, "/login") + } - // Get information of all game sessions available - GameSessions, err := DisplayGameSessions(connect) - if err != nil { - c.String(http.StatusOK, fmt.Sprint(err)) - } - c.HTML(http.StatusOK, "index.html", gin.H{ - "title": "Xplane11-WebRTC", - "GameSessions": GameSessions, - "User": User, - }) - }) + // Get information of all game sessions available + GameSessions, err := DisplayGameSessions(connect) + if err != nil { + c.String(http.StatusOK, fmt.Sprint(err)) + } + c.HTML(http.StatusOK, "index.html", gin.H{ + "title": "Xplane11-WebRTC", + "GameSessions": GameSessions, + "User": User, + }) + }) - // Opens the forgot password page - r.GET("/forgotpassword", func(c *gin.Context) { - c.HTML(http.StatusOK, "forgotpassword.html", gin.H{ - "title": "Xplane11-WebRTC", - }) - }) + // Opens the forgot password page + r.GET("/forgotpassword", func(c *gin.Context) { + c.HTML(http.StatusOK, "forgotpassword.html", gin.H{ + "title": "Xplane11-WebRTC", + }) + }) - // Opens the login page - r.GET("/login", func(c *gin.Context) { - c.HTML(http.StatusOK, "login.html", gin.H{ - "title": "Xplane11-WebRTC", - }) - }) + // Opens the login page + r.GET("/login", func(c *gin.Context) { + c.HTML(http.StatusOK, "login.html", gin.H{ + "title": "Xplane11-WebRTC", + }) + }) - // Validate login information - r.POST("/login", func(c *gin.Context) { - // you can bind multipart form with explicit binding declaration: - // c.ShouldBindWith(&form, binding.Form) - // or you can simply use autobinding with ShouldBind method: - // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding - var users Users - // in this case proper binding will be automatically selected - if err := c.ShouldBind(&users); err != nil { - c.String(http.StatusBadRequest, "bad request") - } + // Validate login information + r.POST("/login", func(c *gin.Context) { + // you can bind multipart form with explicit binding declaration: + // c.ShouldBindWith(&form, binding.Form) + // or you can simply use autobinding with ShouldBind method: + // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding + var users Users + // in this case proper binding will be automatically selected + if err := c.ShouldBind(&users); err != nil { + c.String(http.StatusBadRequest, "bad request") + } - result, err := AuthLogin(connect, &users) - if err != nil { - c.String(http.StatusOK, fmt.Sprint(err)) - } else { - if result == "success" { - // Create Login session - session, err := CreateLoginSession(connect, &users) - if err != nil { - c.String(http.StatusExpectationFailed, "error") - } - // TODO redirect to homepage - // Set client Cookie as Session ID - // To be changed when we use HTTPS - c.SetCookie("SessionID", session.SessionKey, 3600, "/", "*", false, true) - // redirects to the home page - //c.Redirect(http.StatusFound, "/") + result, err := AuthLogin(connect, &users) + if err != nil { + c.String(http.StatusOK, fmt.Sprint(err)) + } else { + if result == "success" { + // Create Login session + session, err := CreateLoginSession(connect, &users) + if err != nil { + c.String(http.StatusExpectationFailed, "error") + } + // TODO redirect to homepage + // Set client Cookie as Session ID + // To be changed when we use HTTPS + c.SetCookie("SessionID", session.SessionKey, 3600, "/", "*", false, true) + // redirects to the home page + //c.Redirect(http.StatusFound, "/") - // Sends message success. which then redirects back to the home page - c.String(http.StatusOK, "Success!") - } else { - c.String(http.StatusOK, "Something is wrong with from our side. Email us: me@akilan.io to find out more. ") - } - } - }) + // Sends message success. which then redirects back to the home page + c.String(http.StatusOK, "Success!") + } else { + c.String(http.StatusOK, "Something is wrong with from our side. Email us: me@akilan.io to find out more. ") + } + } + }) - // Route for logout - r.GET("/logout", func(c *gin.Context) { - // Get client session ID - session, err := c.Cookie("SessionID") - if err != nil { - c.Redirect(http.StatusFound, "/login") - } + // Route for logout + r.GET("/logout", func(c *gin.Context) { + // Get client session ID + session, err := c.Cookie("SessionID") + if err != nil { + c.Redirect(http.StatusFound, "/login") + } - // Remove Session ID from the database - RemoveLoginSession(connect, session) + // Remove Session ID from the database + RemoveLoginSession(connect, session) - // redirect to the login page - c.Redirect(http.StatusFound, "/login") - }) + // redirect to the login page + c.Redirect(http.StatusFound, "/login") + }) - // Opens the registration page - r.GET("/register", func(c *gin.Context) { - c.HTML(http.StatusOK, "registration.html", gin.H{ - "title": "Xplane11-WebRTC", - }) - }) + // Opens the registration page + r.GET("/register", func(c *gin.Context) { + c.HTML(http.StatusOK, "registration.html", gin.H{ + "title": "Xplane11-WebRTC", + }) + }) - // Register user information required - r.POST("/register", func(c *gin.Context) { - // you can bind multipart form with explicit binding declaration: - // c.ShouldBindWith(&form, binding.Form) - // or you can simply use autobinding with ShouldBind method: - // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding - var users Users - // in this case proper binding will be automatically selected - if err := c.ShouldBind(&users); err != nil { - c.String(http.StatusBadRequest, "bad request") - } + // Register user information required + r.POST("/register", func(c *gin.Context) { + // you can bind multipart form with explicit binding declaration: + // c.ShouldBindWith(&form, binding.Form) + // or you can simply use autobinding with ShouldBind method: + // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding + var users Users + // in this case proper binding will be automatically selected + if err := c.ShouldBind(&users); err != nil { + c.String(http.StatusBadRequest, "bad request") + } - err = RegisterUser(connect, &users) - if err != nil { - c.String(http.StatusOK, fmt.Sprint(err)) - } else { - c.String(http.StatusOK, "Success! Head back to the login page") - } - }) + err = RegisterUser(connect, &users) + if err != nil { + c.String(http.StatusOK, fmt.Sprint(err)) + } else { + c.String(http.StatusOK, "Success! Head back to the login page") + } + }) - // Add new server information - r.POST("/AddGameSession", func(c *gin.Context) { + // Add new server information + r.POST("/AddGameSession", func(c *gin.Context) { - // TODO: Binding - // you can bind multipart form with explicit binding declaration: - // c.ShouldBindWith(&form, binding.Form) - // or you can simply use autobinding with ShouldBind method: - // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding - var gameSession GameSession + // TODO: Binding + // you can bind multipart form with explicit binding declaration: + // c.ShouldBindWith(&form, binding.Form) + // or you can simply use autobinding with ShouldBind method: + // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding + var gameSession GameSession - gameSession.Rate, _ = strconv.ParseFloat(c.PostForm("Rate"), 8) - gameSession.Server.GPU = c.PostForm("GPU") - gameSession.Link = c.PostForm("Link") - gameSession.Server.CPU = c.PostForm("CPU") - gameSession.Server.GPU = c.PostForm("GPU") - gameSession.Server.Platform = c.PostForm("Platform") - gameSession.Server.Hostname = c.PostForm("HostName") - gameSession.Server.RAM = c.PostForm("RAM") - gameSession.Server.Disk = c.PostForm("Disk") + gameSession.Rate, _ = strconv.ParseFloat(c.PostForm("Rate"), 8) + gameSession.Server.GPU = c.PostForm("GPU") + gameSession.Link = c.PostForm("Link") + gameSession.Server.CPU = c.PostForm("CPU") + gameSession.Server.GPU = c.PostForm("GPU") + gameSession.Server.Platform = c.PostForm("Platform") + gameSession.Server.Hostname = c.PostForm("HostName") + gameSession.Server.RAM = c.PostForm("RAM") + gameSession.Server.Disk = c.PostForm("Disk") - // in this case proper binding will be automatically selected - //if err := c.ShouldBind(&gameSession); err != nil { - // c.String(http.StatusBadRequest, "bad request") - //} + // in this case proper binding will be automatically selected + //if err := c.ShouldBind(&gameSession); err != nil { + // c.String(http.StatusBadRequest, "bad request") + //} - err = AddServerSpecs(connect, &gameSession) - if err != nil { - c.String(http.StatusOK, fmt.Sprint(err)) - } else { - c.String(http.StatusOK, "Success") - } - }) + err = AddServerSpecs(connect, &gameSession) + if err != nil { + c.String(http.StatusOK, fmt.Sprint(err)) + } else { + c.String(http.StatusOK, "Success") + } + }) - go CheckIfGameSessionIsActiveOrRemove(connect) + // route to add barrier IP information + r.POST("/AddBarrierIP", func(c *gin.Context) { + // Get client session ID + session, err := c.Cookie("SessionID") + if err != nil { + c.Redirect(http.StatusFound, "/login") + } - // Run gin server on the specified port - err = r.Run(":" + port) - if err != nil { - return err - } + barrierIP := c.PostForm("BarrierIP") + MachineName := c.PostForm("MachineName") - return nil + BarrierIP, err := AddBarrierIP(connect, session, barrierIP, MachineName) + if err != nil { + c.String(http.StatusOK, fmt.Sprint(err)) + } + + c.JSON(http.StatusOK, BarrierIP) + }) + + // Removes barrier ip information from the table + // based on the barrier ip address provided. + r.POST("RemoveBarrierIP", func(c *gin.Context) { + // Get client session ID + _, err = c.Cookie("SessionID") + if err != nil { + c.Redirect(http.StatusFound, "/login") + } + + barrierIP := c.PostForm("BarrierIP") + // Remove Barrier IP + err = RemoveBarrierIP(connect, barrierIP) + if err != nil { + c.String(http.StatusOK, fmt.Sprint(err)) + } + + c.String(http.StatusOK, "BarrierIP removed successfully") + }) + + go CheckIfGameSessionIsActiveOrRemove(connect) + + // Run gin server on the specified port + err = r.Run(":" + port) + if err != nil { + return err + } + + return nil } func CheckIfGameSessionIsActiveOrRemove(gorm *gorm.DB) { - for { - time.Sleep(10 * time.Second) - Gamesessions, err := DisplayGameSessions(gorm) - if err != nil { - return - } + for { + time.Sleep(10 * time.Second) + Gamesessions, err := DisplayGameSessions(gorm) + if err != nil { + return + } - if len(Gamesessions) != 0 { - fmt.Println(Gamesessions[0].Link) - } + if len(Gamesessions) != 0 { + fmt.Println(Gamesessions[0].Link) + } - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - for i, _ := range Gamesessions { - req, err := http.NewRequest("GET", Gamesessions[i].Link, nil) - // Sending request to the backend server - client := &http.Client{} - _, err = client.Do(req) - if err != nil { - // remove from database game session - _, err = RemoveTableGameSessionID(gorm, Gamesessions[i].GameSessionID) - if err != nil { - fmt.Println(err) - return - } - } - } - } + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + for i, _ := range Gamesessions { + req, err := http.NewRequest("GET", Gamesessions[i].Link, nil) + // Sending request to the backend server + client := &http.Client{} + _, err = client.Do(req) + if err != nil { + // remove from database game session + _, err = RemoveTableGameSessionID(gorm, Gamesessions[i].GameSessionID) + if err != nil { + fmt.Println(err) + return + } + } + } + } } diff --git a/templates/index.html b/templates/index.html index baa473b..160c770 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5,7 +5,7 @@ - Admin - Free Bulma template + Xplane WebRTC @@ -15,71 +15,140 @@ - - - -
-
+ + +
-
-
-
-

- Hello, {{ .User.Name }} -

-

- I hope you are having a great day! -

- +
+
+
+
+

+ Hello, {{ .User.Name }} +

+

+ I hope you are having a great day! +

+ +
-
-
-
-
- {{ range .GameSessions }} -
-
-

{{ .Server.GPU }}

-

RAM: {{ .Server.RAM }} MB

-

Rate: {{ .Rate }}$/hr

-

CPU: {{ .Server.CPU }}

-

Disk: {{ .Server.Disk }} MB

-

Platform: {{ .Server.Platform }}

-
- Play -
+
+
+
+
- {{ end }} -
- +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+

+ Barrier Session information +

+ + + + + +
+
+
+ + + + + + + + +
Barrier IP address and HostNameRemove
+
+
+ +
+
+
+ {{ range .GameSessions }} +
+
+

{{ .Server.GPU }}

+

+ RAM: {{ .Server.RAM }} MB

+

Rate: {{ .Rate }}$/hr +

+

CPU: {{ .Server.CPU }} +

+

Disk: {{ .Server.Disk }} + MB

+

Platform: {{ + .Server.Platform }}

+
+ Play +
+
+ {{ end }} +
+ +
- - + \ No newline at end of file