259 lines
7.1 KiB
Go
259 lines
7.1 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
//"bytes"
|
|
"net/http"
|
|
"github.com/dgrijalva/jwt-go"
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"gitlab.computing.dcu.ie/murphg62/2023-ca400-murphg62-byrnm257/src/backend/pkg/database"
|
|
"gitlab.computing.dcu.ie/murphg62/2023-ca400-murphg62-byrnm257/src/backend/pkg/docker"
|
|
_ "golang.org/x/mod/module"
|
|
)
|
|
|
|
const (
|
|
host = "localhost"
|
|
port = 5432
|
|
user = "postgres"
|
|
password = "Gcvy4266"
|
|
dbname = "Panoptes"
|
|
)
|
|
|
|
var db, err = database.ConnectDB(host, port, user, password, dbname)
|
|
var jwtSecret = []byte("fAHr+Hlho9qhCePEuMxLVG2i/1tiEqtocAWkcYRJx0s=")
|
|
|
|
type Schema struct {
|
|
Name string `json:"Name"`
|
|
Type int `json:"Type"`
|
|
}
|
|
|
|
|
|
type Module struct {
|
|
Name string `json:"Name"`
|
|
Container string `json:"Container"`
|
|
}
|
|
|
|
type User struct {
|
|
Username string `json:"Username"`
|
|
Password string `json:"Password"`
|
|
}
|
|
|
|
|
|
func homePage(c echo.Context) error {
|
|
return c.String(http.StatusOK, "Welcome to the home page!")
|
|
}
|
|
|
|
func getSchema(c echo.Context) error {
|
|
key := c.Param("container")
|
|
|
|
|
|
requestURL := fmt.Sprintf("http://%s/schema", key)
|
|
resp, err := http.Get(requestURL)
|
|
if err != nil {
|
|
log.Fatalf("Request to container failed: %v", err)
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Fatalf("Failed to print Body: %v", err)
|
|
}
|
|
|
|
return c.JSONBlob(resp.StatusCode, body)
|
|
}
|
|
|
|
func getComponent(c echo.Context) error {
|
|
container := c.Param("container")
|
|
component := c.Param("component")
|
|
|
|
requestURL := fmt.Sprintf("http://%s:8080/component/%s", container, component)
|
|
resp, err := http.Get(requestURL)
|
|
if err != nil {
|
|
log.Fatalf("Request to container failed: %v", err)
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Fatalf("Failed to print Body: %v", err)
|
|
}
|
|
|
|
return c.JSONBlob(http.StatusOK, body)
|
|
}
|
|
|
|
func postComponent(c echo.Context) error {
|
|
container := c.Param("container")
|
|
component := c.Param("component")
|
|
|
|
requestURL := fmt.Sprintf("http://%s:8080/component/%s", container, component)
|
|
resp, err := http.Post(requestURL, "application/json", c.Request().Body)
|
|
if err != nil {
|
|
log.Fatalf("Request to container failed: %v", err)
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Fatalf("Failed to print Body: %v", err)
|
|
}
|
|
|
|
return c.JSONBlob(http.StatusOK, body)
|
|
}
|
|
|
|
func GetModules(db *sql.DB) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
modules := make([]Module, 0)
|
|
rows, err := db.Query("SELECT name, container_name FROM Module")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var module Module
|
|
if err := rows.Scan(&module.Name, &module.Container); err != nil {
|
|
return err
|
|
}
|
|
modules = append(modules, module)
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, modules)
|
|
}
|
|
}
|
|
|
|
func RegisterUser(db *sql.DB) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
user := new(User)
|
|
if err := c.Bind(user); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Check if user already exists
|
|
var count int
|
|
if err := db.QueryRow("SELECT COUNT(*) FROM users WHERE name = $1", user.Username).Scan(&count); err != nil {
|
|
return err
|
|
}
|
|
if count > 0 {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Username already in use"})
|
|
}
|
|
|
|
// Hash password
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Insert new user into database
|
|
_, err = db.Exec("INSERT INTO users(name, password) VALUES ($1, $2)", user.Username, string(hashedPassword))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, map[string]string{"message": "User created"})
|
|
}
|
|
}
|
|
|
|
|
|
func LoginUser(db *sql.DB, jwtSecret []byte) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
login := new(User)
|
|
if err := c.Bind(login); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Check if user exists
|
|
var user User
|
|
if err := db.QueryRow("SELECT name, password FROM users WHERE name = $1", login.Username).Scan(&user.Username, &user.Password); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid username or password"})
|
|
}
|
|
return err
|
|
}
|
|
|
|
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password)); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid username or password"})
|
|
}
|
|
|
|
// Generate JWT token
|
|
token := jwt.New(jwt.SigningMethodHS256)
|
|
claims := token.Claims.(jwt.MapClaims)
|
|
claims["name"] = user.Username
|
|
tokenString, err := token.SignedString(jwtSecret)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, map[string]string{"token": tokenString})
|
|
}
|
|
}
|
|
|
|
func LogoutUser() echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
// Clear JWT token cookie
|
|
cookie := &http.Cookie{
|
|
Name: "jwt",
|
|
Value: "",
|
|
HttpOnly: true,
|
|
Path: "/",
|
|
}
|
|
http.SetCookie(c.Response().Writer, cookie)
|
|
|
|
return c.NoContent(http.StatusOK)
|
|
}
|
|
}
|
|
|
|
func CreateModule(c echo.Context) error {
|
|
var module docker.Module
|
|
if err := c.Bind(&module); err != nil {
|
|
panic(err)
|
|
}
|
|
s, _ := json.MarshalIndent(module, "", " ")
|
|
fmt.Println(string(s))
|
|
mod_id := docker.CreateModule(module)
|
|
stmt, err := db.Prepare(`INSERT INTO Module (name, container_name) VALUES ($1, $2);`)
|
|
if err != nil {
|
|
fmt.Println("lmao")
|
|
panic(err)
|
|
}
|
|
_, err = stmt.Exec(module.Name, mod_id)
|
|
return c.NoContent(http.StatusOK)
|
|
}
|
|
|
|
|
|
func main() {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
db.Exec(`CREATE TABLE IF NOT EXISTS Module (
|
|
name VARCHAR(64),
|
|
container_name VARCHAR(64));
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(64) UNIQUE NOT NULL,
|
|
password VARCHAR(255) NOT NULL
|
|
)
|
|
`)
|
|
e := echo.New()
|
|
e.GET("/", homePage)
|
|
e.GET("/:container/schema", getSchema)
|
|
e.GET("/component/:container/:component", getComponent)
|
|
e.POST("/component/:container/:component", postComponent)
|
|
e.GET("/modules", GetModules(db))
|
|
e.POST("/user/register", RegisterUser(db))
|
|
e.POST("/user/login", LoginUser(db, jwtSecret))
|
|
e.POST("/user/logout", LogoutUser())
|
|
e.POST("/create_module", CreateModule)
|
|
e.Logger.Fatal(e.Start(":10000"))
|
|
defer db.Close()
|
|
}
|