package main import ( "database/sql" _"encoding/json" "fmt" "io/ioutil" "log" "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" _ "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(http.StatusOK, body) } func getStats(c echo.Context) error { key := c.Param("container") requestURL := fmt.Sprintf("http://%s:8080", 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(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 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("/:container/stats", getStats) e.GET("/modules", GetModules(db)) e.POST("/user/register", RegisterUser(db)) e.POST("/user/login", LoginUser(db, jwtSecret)) e.POST("/user/logout", LogoutUser()) e.Logger.Fatal(e.Start(":10000")) defer db.Close() }