385 lines
9.3 KiB
Go
385 lines
9.3 KiB
Go
package flightlesssomething
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const BENCHMARKS_PER_PAGE = 10
|
|
|
|
func getBenchmarks(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
|
|
// Get "query" value
|
|
query := c.Query("query")
|
|
|
|
// Get "page" value
|
|
page := c.DefaultQuery("page", "1")
|
|
pageInt, _ := strconv.Atoi(page)
|
|
if pageInt < 1 {
|
|
pageInt = 1
|
|
}
|
|
|
|
// Get benchmarks according to query
|
|
var benchmarks []Benchmark
|
|
tx := db.
|
|
Preload("User").
|
|
Order("created_at DESC").
|
|
Offset((pageInt - 1) * BENCHMARKS_PER_PAGE).
|
|
Limit(BENCHMARKS_PER_PAGE)
|
|
if query != "" {
|
|
tx = tx.Where("title LIKE ?", "%"+query+"%").Or("description LIKE ?", "%"+query+"%")
|
|
}
|
|
result := tx.Find(&benchmarks)
|
|
if result.Error != nil {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Error occurred while fetching benchmarks",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Get total number of benchmarks matching the query
|
|
var benchmarksTotal int64
|
|
tx = db.Model(&Benchmark{})
|
|
if query != "" {
|
|
tx = tx.Where("title LIKE ?", "%"+query+"%").Or("description LIKE ?", "%"+query+"%")
|
|
}
|
|
result = tx.Count(&benchmarksTotal)
|
|
if result.Error != nil {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Error occurred while counting benchmarks",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Calculate pagination values
|
|
prevPage := pageInt - 1
|
|
nextPage := pageInt + 1
|
|
totalPages := (int(benchmarksTotal) + BENCHMARKS_PER_PAGE - 1) / BENCHMARKS_PER_PAGE
|
|
|
|
c.HTML(http.StatusOK, "benchmarks.tmpl", gin.H{
|
|
"activePage": "benchmarks",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"benchmarks": benchmarks,
|
|
"benchmarksTotal": benchmarksTotal,
|
|
|
|
// Query parameters
|
|
"query": query,
|
|
"page": pageInt,
|
|
|
|
// Pagination values
|
|
"prevPage": prevPage,
|
|
"nextPage": nextPage,
|
|
"totalPages": totalPages,
|
|
})
|
|
}
|
|
|
|
func getBenchmarkCreate(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
if session.Get("Username") == "" {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Please authenticate to create a benchmark",
|
|
})
|
|
}
|
|
|
|
c.HTML(http.StatusOK, "benchmark_create.tmpl", gin.H{
|
|
"activePage": "benchmark",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
})
|
|
}
|
|
|
|
func postBenchmarkCreate(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
if session.Get("Username") == "" {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Please authenticate to create a benchmark",
|
|
})
|
|
return
|
|
}
|
|
|
|
title := strings.TrimSpace(c.PostForm("title"))
|
|
if len(title) > 100 || title == "" {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Title must not be empty or exceed 100 characters",
|
|
})
|
|
return
|
|
}
|
|
|
|
description := strings.TrimSpace(c.PostForm("description"))
|
|
if len(description) > 500 {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Description must not exceed 500 characters",
|
|
})
|
|
return
|
|
}
|
|
|
|
form, err := c.MultipartForm()
|
|
if err != nil {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Error occurred while parsing form data",
|
|
})
|
|
return
|
|
}
|
|
files := form.File["files"]
|
|
if len(files) == 0 {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "No files uploaded",
|
|
})
|
|
return
|
|
}
|
|
if len(files) > 50 {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Too many files uploaded (max 50)",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Read CSV files
|
|
// Store to disk only when DB record is created successfully
|
|
csvFiles, csvSpecs, err := readCSVFiles(files)
|
|
if err != nil {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Error occurred while reading CSV files: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
benchmark := Benchmark{
|
|
UserID: session.Get("ID").(uint),
|
|
Title: title,
|
|
Description: description,
|
|
|
|
SpecDistro: csvSpecs.Distro,
|
|
SpecCPU: csvSpecs.CPU,
|
|
SpecGPU: csvSpecs.GPU,
|
|
SpecRAM: csvSpecs.RAM,
|
|
SpecKernel: csvSpecs.Kernel,
|
|
SpecScheduler: csvSpecs.Scheduler,
|
|
}
|
|
|
|
result := db.Create(&benchmark)
|
|
if result.Error != nil {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Error occurred while creating benchmark: " + result.Error.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Store CSV files to disk
|
|
err = storeBenchmarkData(csvFiles, benchmark.ID)
|
|
if err != nil {
|
|
db.Unscoped().Delete(&benchmark) // Hard delete from DB
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Error occurred while storing benchmark data: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Redirect to the newly created benchmark using GET request
|
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/benchmark/%d", benchmark.ID))
|
|
}
|
|
|
|
func deleteBenchmark(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
if session.Get("Username") == "" {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Please authenticate to create a benchmark",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Get benchmark ID from the path
|
|
id := c.Param("id")
|
|
|
|
// Check if user owns the benchmark
|
|
var benchmark Benchmark
|
|
result := db.First(&benchmark, id)
|
|
if result.Error != nil {
|
|
c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Internal server error occurred: " + result.Error.Error(),
|
|
})
|
|
return
|
|
}
|
|
if benchmark.UserID != session.Get("ID") {
|
|
c.HTML(http.StatusUnauthorized, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "You do not own this benchmark",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Delete benchmark from DB
|
|
result = db.Unscoped().Delete(&benchmark)
|
|
if result.Error != nil {
|
|
c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Internal server error occurred: " + result.Error.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Delete benchmark data from disk
|
|
err := deleteBenchmarkData(benchmark.ID)
|
|
if err != nil {
|
|
c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Internal server error occurred: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Redirect to the benchmarks page
|
|
c.Header("HX-Redirect", "/benchmarks")
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "Benchmark deleted successfully",
|
|
})
|
|
}
|
|
|
|
func getBenchmark(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
|
|
// Get benchmark ID from the path
|
|
id := c.Param("id")
|
|
|
|
// Get benchmark details
|
|
intID, err := strconv.Atoi(id)
|
|
if err != nil {
|
|
c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"errorMessage": "Internal server error occurred: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
var benchmark Benchmark
|
|
benchmark.ID = uint(intID)
|
|
|
|
var csvFiles []*CSVFile
|
|
var errCSV, errDB error
|
|
errHTTPStatus := http.StatusInternalServerError
|
|
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(2)
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
csvFiles, errCSV = retrieveBenchmarkData(benchmark.ID)
|
|
}()
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
result := db.Preload("User").First(&benchmark, id)
|
|
if result.Error != nil {
|
|
errDB = result.Error
|
|
return
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
errDB = fmt.Errorf("Benchmark not found")
|
|
errHTTPStatus = http.StatusNotFound
|
|
return
|
|
}
|
|
}()
|
|
|
|
wg.Wait()
|
|
|
|
err = errDB
|
|
if err == nil {
|
|
err = errCSV
|
|
}
|
|
if err != nil {
|
|
c.HTML(errHTTPStatus, "error.tmpl", gin.H{
|
|
"activePage": "error",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
"errorMessage": "Error occurred: " + errDB.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
c.HTML(http.StatusOK, "benchmark.tmpl", gin.H{
|
|
"activePage": "benchmark",
|
|
"username": session.Get("Username"),
|
|
"userID": session.Get("ID"),
|
|
|
|
"benchmark": benchmark,
|
|
"benchmarkData": csvFiles,
|
|
})
|
|
}
|