package main import ( "database/sql" "encoding/json" "fmt" "io/ioutil" "os" //"bytes" "net/http" "github.com/dgrijalva/jwt-go" "golang.org/x/crypto/bcrypt" "github.com/labstack/echo/v4" "github.com/google/uuid" "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 ( port = 5432 ) var db, err = database.ConnectDB(os.Getenv("db"), port, os.Getenv("db_user"), os.Getenv("db_pass"), os.Getenv("db_name")) 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:8080/schema", key) resp, err := http.Get(requestURL) if err != nil { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(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 { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(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 { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(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 { fmt.Println("test") 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 getFromModule(c echo.Context) error { url := c.Param("url") requestURL := fmt.Sprintf("http://%s", url) fmt.Println(requestURL) resp, err := http.Get(requestURL) if err != nil { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } return c.JSONBlob(http.StatusOK, body) } func postFromModule(c echo.Context) error { url := c.Param("url") requestURL := fmt.Sprintf("http://%s", url) resp, err := http.Post(requestURL, "application/json", c.Request().Body) if err != nil { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } return c.JSONBlob(http.StatusOK, body) } 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) } module.ID = uuid.New().String() s, _ := json.MarshalIndent(module, "", " ") fmt.Println(string(s)) mod_id := docker.CreateModule(module) fmt.Println(mod_id) stmt, err := db.Prepare(`INSERT INTO Module (name, container_name) VALUES ($1, $2);`) if err != nil { 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.GET("/get/:url", getFromModule) e.POST("/post/:url", postFromModule) e.Logger.Fatal(e.Start(":10000")) defer db.Close() }