added base UI changes

This commit is contained in:
2023-03-02 23:30:58 +00:00
parent 66d53490c7
commit df911ee456
3 changed files with 415 additions and 240 deletions

View File

@@ -56,6 +56,15 @@ type ServerSpecs struct {
GPU string `form:"GPU" binding:"required" bson:GPU` 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 // CreateTables CreateDB Add tables to the database
func CreateTables(db *gorm.DB) (*gorm.DB, error) { func CreateTables(db *gorm.DB) (*gorm.DB, error) {
// Creates table to store login sessions // Creates table to store login sessions
@@ -66,6 +75,8 @@ func CreateTables(db *gorm.DB) (*gorm.DB, error) {
db.AutoMigrate(GameSession{}) db.AutoMigrate(GameSession{})
// Creates table of type ServerSpecs // Creates table of type ServerSpecs
db.AutoMigrate(ServerSpecs{}) db.AutoMigrate(ServerSpecs{})
// Creates table of type BarrierIP
db.AutoMigrate(BarrierIP{})
// returns variable DB of type *gorm.DB and error // returns variable DB of type *gorm.DB and error
// which is nil at the current moment // which is nil at the current moment
return db, nil return db, nil
@@ -348,3 +359,60 @@ func GetUserInformation(db *gorm.DB, SessionID string) (*Users, error) {
return nil, errors.New("Session not found. ") 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
}

View File

@@ -1,223 +1,261 @@
package server package server
import ( import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gorm.io/gorm" "gorm.io/gorm"
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
) )
// Server Starts the server for the client side // Server Starts the server for the client side
func Server(port string) error { 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") r.LoadHTMLGlob("./templates/*.html")
// htmlRender.TemplatesDir = "templates/" // default // htmlRender.TemplatesDir = "templates/" // default
// htmlRender.Ext = ".html" // default // htmlRender.Ext = ".html" // default
// Tell gin to use our html render // Tell gin to use our html render
// Initialise connection to Sqlite DB // Initialise connection to Sqlite DB
connect, err := Connect() connect, err := Connect()
if err != nil { if err != nil {
return err return err
} }
// Gets default information about the game sessions // Gets default information about the game sessions
r.GET("/", func(c *gin.Context) { r.GET("/", func(c *gin.Context) {
// Get client session ID // Get client session ID
session, err := c.Cookie("SessionID") session, err := c.Cookie("SessionID")
if err != nil { if err != nil {
c.Redirect(http.StatusFound, "/login") c.Redirect(http.StatusFound, "/login")
} }
// User information based on session ID // User information based on session ID
User, err := GetUserInformation(connect, session) User, err := GetUserInformation(connect, session)
if err != nil { if err != nil {
c.Redirect(http.StatusFound, "/login") c.Redirect(http.StatusFound, "/login")
} }
// Get information of all game sessions available // Get information of all game sessions available
GameSessions, err := DisplayGameSessions(connect) GameSessions, err := DisplayGameSessions(connect)
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} }
c.HTML(http.StatusOK, "index.html", gin.H{ c.HTML(http.StatusOK, "index.html", gin.H{
"title": "Xplane11-WebRTC", "title": "Xplane11-WebRTC",
"GameSessions": GameSessions, "GameSessions": GameSessions,
"User": User, "User": User,
}) })
}) })
// Opens the forgot password page // Opens the forgot password page
r.GET("/forgotpassword", func(c *gin.Context) { r.GET("/forgotpassword", func(c *gin.Context) {
c.HTML(http.StatusOK, "forgotpassword.html", gin.H{ c.HTML(http.StatusOK, "forgotpassword.html", gin.H{
"title": "Xplane11-WebRTC", "title": "Xplane11-WebRTC",
}) })
}) })
// Opens the login page // Opens the login page
r.GET("/login", func(c *gin.Context) { r.GET("/login", func(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", gin.H{ c.HTML(http.StatusOK, "login.html", gin.H{
"title": "Xplane11-WebRTC", "title": "Xplane11-WebRTC",
}) })
}) })
// Validate login information // Validate login information
r.POST("/login", func(c *gin.Context) { r.POST("/login", func(c *gin.Context) {
// you can bind multipart form with explicit binding declaration: // you can bind multipart form with explicit binding declaration:
// c.ShouldBindWith(&form, binding.Form) // c.ShouldBindWith(&form, binding.Form)
// or you can simply use autobinding with ShouldBind method: // or you can simply use autobinding with ShouldBind method:
// source: https://github.com/gin-gonic/gin#multiparturlencoded-binding // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding
var users Users var users Users
// in this case proper binding will be automatically selected // in this case proper binding will be automatically selected
if err := c.ShouldBind(&users); err != nil { if err := c.ShouldBind(&users); err != nil {
c.String(http.StatusBadRequest, "bad request") c.String(http.StatusBadRequest, "bad request")
} }
result, err := AuthLogin(connect, &users) result, err := AuthLogin(connect, &users)
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} else { } else {
if result == "success" { if result == "success" {
// Create Login session // Create Login session
session, err := CreateLoginSession(connect, &users) session, err := CreateLoginSession(connect, &users)
if err != nil { if err != nil {
c.String(http.StatusExpectationFailed, "error") c.String(http.StatusExpectationFailed, "error")
} }
// TODO redirect to homepage // TODO redirect to homepage
// Set client Cookie as Session ID // Set client Cookie as Session ID
// To be changed when we use HTTPS // To be changed when we use HTTPS
c.SetCookie("SessionID", session.SessionKey, 3600, "/", "*", false, true) c.SetCookie("SessionID", session.SessionKey, 3600, "/", "*", false, true)
// redirects to the home page // redirects to the home page
//c.Redirect(http.StatusFound, "/") //c.Redirect(http.StatusFound, "/")
// Sends message success. which then redirects back to the home page // Sends message success. which then redirects back to the home page
c.String(http.StatusOK, "Success!") c.String(http.StatusOK, "Success!")
} else { } else {
c.String(http.StatusOK, "Something is wrong with from our side. Email us: me@akilan.io to find out more. ") c.String(http.StatusOK, "Something is wrong with from our side. Email us: me@akilan.io to find out more. ")
} }
} }
}) })
// Route for logout // Route for logout
r.GET("/logout", func(c *gin.Context) { r.GET("/logout", func(c *gin.Context) {
// Get client session ID // Get client session ID
session, err := c.Cookie("SessionID") session, err := c.Cookie("SessionID")
if err != nil { if err != nil {
c.Redirect(http.StatusFound, "/login") c.Redirect(http.StatusFound, "/login")
} }
// Remove Session ID from the database // Remove Session ID from the database
RemoveLoginSession(connect, session) RemoveLoginSession(connect, session)
// redirect to the login page // redirect to the login page
c.Redirect(http.StatusFound, "/login") c.Redirect(http.StatusFound, "/login")
}) })
// Opens the registration page // Opens the registration page
r.GET("/register", func(c *gin.Context) { r.GET("/register", func(c *gin.Context) {
c.HTML(http.StatusOK, "registration.html", gin.H{ c.HTML(http.StatusOK, "registration.html", gin.H{
"title": "Xplane11-WebRTC", "title": "Xplane11-WebRTC",
}) })
}) })
// Register user information required // Register user information required
r.POST("/register", func(c *gin.Context) { r.POST("/register", func(c *gin.Context) {
// you can bind multipart form with explicit binding declaration: // you can bind multipart form with explicit binding declaration:
// c.ShouldBindWith(&form, binding.Form) // c.ShouldBindWith(&form, binding.Form)
// or you can simply use autobinding with ShouldBind method: // or you can simply use autobinding with ShouldBind method:
// source: https://github.com/gin-gonic/gin#multiparturlencoded-binding // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding
var users Users var users Users
// in this case proper binding will be automatically selected // in this case proper binding will be automatically selected
if err := c.ShouldBind(&users); err != nil { if err := c.ShouldBind(&users); err != nil {
c.String(http.StatusBadRequest, "bad request") c.String(http.StatusBadRequest, "bad request")
} }
err = RegisterUser(connect, &users) err = RegisterUser(connect, &users)
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} else { } else {
c.String(http.StatusOK, "Success! Head back to the login page") c.String(http.StatusOK, "Success! Head back to the login page")
} }
}) })
// Add new server information // Add new server information
r.POST("/AddGameSession", func(c *gin.Context) { r.POST("/AddGameSession", func(c *gin.Context) {
// TODO: Binding // TODO: Binding
// you can bind multipart form with explicit binding declaration: // you can bind multipart form with explicit binding declaration:
// c.ShouldBindWith(&form, binding.Form) // c.ShouldBindWith(&form, binding.Form)
// or you can simply use autobinding with ShouldBind method: // or you can simply use autobinding with ShouldBind method:
// source: https://github.com/gin-gonic/gin#multiparturlencoded-binding // source: https://github.com/gin-gonic/gin#multiparturlencoded-binding
var gameSession GameSession var gameSession GameSession
gameSession.Rate, _ = strconv.ParseFloat(c.PostForm("Rate"), 8) gameSession.Rate, _ = strconv.ParseFloat(c.PostForm("Rate"), 8)
gameSession.Server.GPU = c.PostForm("GPU") gameSession.Server.GPU = c.PostForm("GPU")
gameSession.Link = c.PostForm("Link") gameSession.Link = c.PostForm("Link")
gameSession.Server.CPU = c.PostForm("CPU") gameSession.Server.CPU = c.PostForm("CPU")
gameSession.Server.GPU = c.PostForm("GPU") gameSession.Server.GPU = c.PostForm("GPU")
gameSession.Server.Platform = c.PostForm("Platform") gameSession.Server.Platform = c.PostForm("Platform")
gameSession.Server.Hostname = c.PostForm("HostName") gameSession.Server.Hostname = c.PostForm("HostName")
gameSession.Server.RAM = c.PostForm("RAM") gameSession.Server.RAM = c.PostForm("RAM")
gameSession.Server.Disk = c.PostForm("Disk") gameSession.Server.Disk = c.PostForm("Disk")
// in this case proper binding will be automatically selected // in this case proper binding will be automatically selected
//if err := c.ShouldBind(&gameSession); err != nil { //if err := c.ShouldBind(&gameSession); err != nil {
// c.String(http.StatusBadRequest, "bad request") // c.String(http.StatusBadRequest, "bad request")
//} //}
err = AddServerSpecs(connect, &gameSession) err = AddServerSpecs(connect, &gameSession)
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} else { } else {
c.String(http.StatusOK, "Success") 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 barrierIP := c.PostForm("BarrierIP")
err = r.Run(":" + port) MachineName := c.PostForm("MachineName")
if err != nil {
return err
}
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) { func CheckIfGameSessionIsActiveOrRemove(gorm *gorm.DB) {
for { for {
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
Gamesessions, err := DisplayGameSessions(gorm) Gamesessions, err := DisplayGameSessions(gorm)
if err != nil { if err != nil {
return return
} }
if len(Gamesessions) != 0 { if len(Gamesessions) != 0 {
fmt.Println(Gamesessions[0].Link) fmt.Println(Gamesessions[0].Link)
} }
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
for i, _ := range Gamesessions { for i, _ := range Gamesessions {
req, err := http.NewRequest("GET", Gamesessions[i].Link, nil) req, err := http.NewRequest("GET", Gamesessions[i].Link, nil)
// Sending request to the backend server // Sending request to the backend server
client := &http.Client{} client := &http.Client{}
_, err = client.Do(req) _, err = client.Do(req)
if err != nil { if err != nil {
// remove from database game session // remove from database game session
_, err = RemoveTableGameSessionID(gorm, Gamesessions[i].GameSessionID) _, err = RemoveTableGameSessionID(gorm, Gamesessions[i].GameSessionID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
} }
} }
} }
} }

View File

@@ -5,7 +5,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Admin - Free Bulma template</title> <title>Xplane WebRTC</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet">
<!-- Bulma Version 0.9.0--> <!-- Bulma Version 0.9.0-->
@@ -15,71 +15,140 @@
<body> <body>
<!-- START NAV --> <!-- START NAV -->
<nav class="navbar is-white"> <nav class="navbar is-white">
<div class="container"> <div class="container">
<div class="navbar-brand"> <div class="navbar-brand">
<a class="navbar-item brand-text" href="/"> <a class="navbar-item brand-text" href="/">
XPlane11-WebRTC XPlane11-WebRTC
</a>
<div class="navbar-burger burger" data-target="navMenu">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div id="navMenu" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/">
Home
</a>
<a class="navbar-item" href="/logout">
Logout
</a> </a>
<div class="navbar-burger burger" data-target="navMenu">
<span></span>
<span></span>
<span></span>
</div>
</div> </div>
<div id="navMenu" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/">
Home
</a>
<a class="navbar-item" href="/logout">
Logout
</a>
</div>
</div>
</div> </div>
</div> </nav>
</nav> <!-- END NAV -->
<!-- END NAV --> <div class="container">
<div class="container">
<div class="">
<div class=""> <div class="">
<section class="hero is-info welcome is-small"> <div class="">
<div class="hero-body"> <section class="hero is-info welcome is-small">
<div class="container"> <div class="hero-body">
<h1 class="title"> <div class="container">
Hello, {{ .User.Name }} <h1 class="title">
</h1> Hello, {{ .User.Name }}
<h2 class="subtitle"> </h1>
I hope you are having a great day! <h2 class="subtitle">
</h2> I hope you are having a great day!
</article> </h2>
</article>
</div>
</div> </div>
</div> </section>
</section> <section class="info-tiles">
<section class="info-tiles"> <div class="column is-6 row is-multiline">
<div class="tile is-ancestor has-text-centered row columns is-multiline"> <iframe src="https://www.youtube.com/embed/WVDSVhMW7o4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen style="width: 100%; height: 100%"></iframe>
{{ range .GameSessions }}
<div class="column is-4 tile is-parent">
<article class="tile is-child box">
<p class="title">{{ .Server.GPU }}</p>
<p style="color: #8F99A3; margin-top:-1.25rem; font-weight: 300; font-size: 1.25rem">RAM: {{ .Server.RAM }} MB</p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">Rate: {{ .Rate }}$/hr </p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">CPU: {{ .Server.CPU }} </p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">Disk: {{ .Server.Disk }} MB</p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">Platform: {{ .Server.Platform }}</p>
<br>
<a href="{{ .Link }}" class="button is-block is-success is-fullwidth is-medium">Play</a>
</article>
</div> </div>
{{ end }} <div class="column is-6 row is-multiline">
</div> <div class="field is-horizontal">
</section> <div class="field-label is-medium">
<label class="label">Barrier IP Address</label>
</div>
<div class="field-body">
<div class="field">
<div class="control">
<input class="input is-medium" type="text" placeholder="Barrier IP address">
</div>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label is-medium">
<label class="label">Machine Name</label>
</div>
<div class="field-body">
<div class="field">
<div class="control">
<input class="input is-medium" type="text" placeholder="Machine name">
</div>
</div>
</div>
</div>
<center><button class="button is-black" style="font-weight:700">Add Barrier Information</button>
</center>
</div>
<div class="column is-6 row is-multiline">
<div class="card events-card">
<header class="card-header">
<p class="card-header-title">
Barrier Session information
</p>
<a href="#" class="card-header-icon" aria-label="more options">
<span class="icon">
<i class="fa fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div class="card-table">
<div class="content">
<table class="table is-fullwidth is-striped">
<tbody>
<tr>
<td width="5%"></td>
<td>Barrier IP address and HostName</td>
<td class="level-right"><a class="button is-small bg-danger"
href="#">Remove</a></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- <footer class="card-footer">
<a href="#" class="card-footer-item">Add Barrier session</a>
</footer> -->
</div>
</div>
<div class="tile is-ancestor has-text-centered row columns is-multiline">
{{ range .GameSessions }}
<div class="column is-4 tile is-parent">
<article class="tile is-child box">
<p class="title">{{ .Server.GPU }}</p>
<p style="color: #8F99A3; margin-top:-1.25rem; font-weight: 300; font-size: 1.25rem">
RAM: {{ .Server.RAM }} MB</p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">Rate: {{ .Rate }}$/hr
</p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">CPU: {{ .Server.CPU }}
</p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">Disk: {{ .Server.Disk }}
MB</p>
<p style="color: #8F99A3; font-weight: 300; font-size: 1.25rem">Platform: {{
.Server.Platform }}</p>
<br>
<a href="{{ .Link }}" class="button is-block is-success is-fullwidth is-medium">Play</a>
</article>
</div>
{{ end }}
</div>
</section>
</div>
</div> </div>
</div> </div>
</div> <script async type="text/javascript" src="assets/js/bulma.js"></script>
<script async type="text/javascript" src="assets/js/bulma.js"></script>
</body> </body>
</html> </html>