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`
}
// 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
}

View File

@@ -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
}
}
}
}
}

View File

@@ -5,7 +5,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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 href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet">
<!-- Bulma Version 0.9.0-->
@@ -15,71 +15,140 @@
<body>
<!-- START NAV -->
<nav class="navbar is-white">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item brand-text" href="/">
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
<!-- START NAV -->
<nav class="navbar is-white">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item brand-text" href="/">
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>
</div>
</div>
</div>
</div>
</nav>
<!-- END NAV -->
<div class="container">
<div class="">
</nav>
<!-- END NAV -->
<div class="container">
<div class="">
<section class="hero is-info welcome is-small">
<div class="hero-body">
<div class="container">
<h1 class="title">
Hello, {{ .User.Name }}
</h1>
<h2 class="subtitle">
I hope you are having a great day!
</h2>
</article>
<div class="">
<section class="hero is-info welcome is-small">
<div class="hero-body">
<div class="container">
<h1 class="title">
Hello, {{ .User.Name }}
</h1>
<h2 class="subtitle">
I hope you are having a great day!
</h2>
</article>
</div>
</div>
</div>
</section>
<section class="info-tiles">
<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>
</section>
<section class="info-tiles">
<div class="column is-6 row 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>
</div>
{{ end }}
</div>
</section>
<div class="column is-6 row is-multiline">
<div class="field is-horizontal">
<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>
<script async type="text/javascript" src="assets/js/bulma.js"></script>
<script async type="text/javascript" src="assets/js/bulma.js"></script>
</body>
</html>