feat: moved files into a better position for organization closes #8
This commit is contained in:
parent
b8278bacf6
commit
1986be1a84
2
go.mod
2
go.mod
@ -1,4 +1,4 @@
|
|||||||
module andr3h3nriqu3s.com/m
|
module git.andr3h3nriqu3s.com/andr3/fyp
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
39
logic/db_types/user.go
Normal file
39
logic/db_types/user.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package dbtypes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Id string
|
||||||
|
Username string
|
||||||
|
Email string
|
||||||
|
UserType int
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrUserNotFound = errors.New("User Not found")
|
||||||
|
|
||||||
|
func UserFromToken(db *sql.DB, token string) (*User, error) {
|
||||||
|
row, err := db.Query("select users.id, users.username, users.email, users.user_type from users inner join tokens on tokens.user_id = users.id where tokens.token = $1;", token)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var id string
|
||||||
|
var username string
|
||||||
|
var email string
|
||||||
|
var user_type int
|
||||||
|
|
||||||
|
if !row.Next() {
|
||||||
|
return nil, ErrUserNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
err = row.Scan(&id, &username, &email, &user_type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &User{id, username, email, user_type}, nil
|
||||||
|
}
|
183
logic/models/add.go
Normal file
183
logic/models/add.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
_ "image/png"
|
||||||
|
"image/color"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadBaseImage(handle *Handle, id string) {
|
||||||
|
// TODO handle more types than png
|
||||||
|
infile, err := os.Open(path.Join("savedData", id, "baseimage.png"))
|
||||||
|
if err != nil {
|
||||||
|
// TODO better logging
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Printf("Failed to read image for model with id %s\n", id)
|
||||||
|
modelUpdateStatus(handle, id, -1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer infile.Close()
|
||||||
|
|
||||||
|
src, format, err := image.Decode(infile)
|
||||||
|
if err != nil {
|
||||||
|
// TODO better logging
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Printf("Failed to load image for model with id %s\n", id)
|
||||||
|
modelUpdateStatus(handle, id, -1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if format != "png" {
|
||||||
|
// TODO better logging
|
||||||
|
fmt.Printf("Found unkown format '%s'\n", format)
|
||||||
|
panic("Handle diferent files than .png")
|
||||||
|
}
|
||||||
|
|
||||||
|
var model_color string
|
||||||
|
|
||||||
|
bounds := src.Bounds()
|
||||||
|
width, height := bounds.Max.X, bounds.Max.Y
|
||||||
|
|
||||||
|
switch src.ColorModel() {
|
||||||
|
case color.Gray16Model:
|
||||||
|
fallthrough
|
||||||
|
case color.GrayModel:
|
||||||
|
model_color = "greyscale"
|
||||||
|
default:
|
||||||
|
fmt.Println("Do not know how to handle this color model")
|
||||||
|
|
||||||
|
if src.ColorModel() == color.RGBA64Model {
|
||||||
|
fmt.Println("Color is rgb")
|
||||||
|
} else if src.ColorModel() == color.NRGBAModel {
|
||||||
|
fmt.Println("Color is nrgb")
|
||||||
|
} else if src.ColorModel() == color.YCbCrModel {
|
||||||
|
fmt.Println("Color is ycbcr")
|
||||||
|
} else if src.ColorModel() == color.AlphaModel {
|
||||||
|
fmt.Println("Color is alpha")
|
||||||
|
} else if src.ColorModel() == color.CMYKModel {
|
||||||
|
fmt.Println("Color is cmyk")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Other so assuming color")
|
||||||
|
}
|
||||||
|
|
||||||
|
modelUpdateStatus(handle, id, -1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this also updates the status to 2
|
||||||
|
_, err = handle.Db.Exec("update models set width=$1, height=$2, color_mode=$3, status=$4 where id=$5", width, height, model_color, CONFIRM_PRE_TRAINING, id)
|
||||||
|
if err != nil {
|
||||||
|
// TODO better logging
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Printf("Could not update model\n")
|
||||||
|
modelUpdateStatus(handle, id, -1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleAdd(handle *Handle) {
|
||||||
|
handle.GetHTML("/models/add", AnswerTemplate("models/add.html", nil, 1))
|
||||||
|
// TODO json
|
||||||
|
handle.Post("/models/add", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
|
if c.Mode == JSON {
|
||||||
|
panic("TODO JSON")
|
||||||
|
}
|
||||||
|
if !CheckAuthLevel(1, w, r, c) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
read_form, err := r.MultipartReader()
|
||||||
|
if err != nil {
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "models/add.html", c.AddMap(nil))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
var file []byte
|
||||||
|
|
||||||
|
for {
|
||||||
|
part, err_part := read_form.NextPart()
|
||||||
|
if err_part == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err_part != nil {
|
||||||
|
return &Error{Code: http.StatusBadRequest}
|
||||||
|
}
|
||||||
|
if part.FormName() == "name" {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.ReadFrom(part)
|
||||||
|
name = buf.String()
|
||||||
|
}
|
||||||
|
if part.FormName() == "file" {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.ReadFrom(part)
|
||||||
|
file = buf.Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "" || len(file) == 0 {
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "models/add.html", c.AddMap(nil))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
row, err := handle.Db.Query("select id from models where name=$1 and user_id=$2;", name, c.User.Id)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if row.Next() {
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "models/add.html", c.AddMap(AnyMap{
|
||||||
|
"NameFoundError": true,
|
||||||
|
"Name": name,
|
||||||
|
}))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = handle.Db.Exec("insert into models (user_id, name) values ($1, $2)", c.User.Id, name)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
row, err = handle.Db.Query("select id from models where name=$1 and user_id=$2;", name, c.User.Id)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !row.Next() {
|
||||||
|
return &Error{Code: http.StatusInternalServerError}
|
||||||
|
}
|
||||||
|
|
||||||
|
var id string
|
||||||
|
err = row.Scan(&id)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO mk this path configurable
|
||||||
|
dir_path := path.Join("savedData", id)
|
||||||
|
|
||||||
|
err = os.Mkdir(dir_path, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
f, err := os.Create(path.Join(dir_path, "baseimage.png"))
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
f.Write(file)
|
||||||
|
|
||||||
|
fmt.Printf("Created model with id %s! Started to proccess image!\n", id)
|
||||||
|
go loadBaseImage(handle, id)
|
||||||
|
|
||||||
|
Redirect("/models/edit?id="+id, c.Mode, w, r)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
107
logic/models/delete.go
Normal file
107
logic/models/delete.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deleteModel(handle *Handle, id string, w http.ResponseWriter, c *Context, model BaseModel) {
|
||||||
|
fmt.Printf("Removing model with id: %s\n", id)
|
||||||
|
_, err := handle.Db.Exec("delete from models where id=$1;", id)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
panic("TODO handle better deleteModel failed delete database query")
|
||||||
|
}
|
||||||
|
|
||||||
|
model_path := path.Join("./savedData", id)
|
||||||
|
fmt.Printf("Removing folder of model with id: %s at %s\n", id, model_path)
|
||||||
|
err = os.RemoveAll(model_path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
panic("TODO handle better deleteModel failed to delete folder")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Mode == HTML {
|
||||||
|
// TODO move this to a constant so i don't forget
|
||||||
|
w.WriteHeader(309)
|
||||||
|
c.Mode = HTMLFULL
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "/models/delete.html", c.AddMap(AnyMap{
|
||||||
|
"Model": model,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleDelete(handle *Handle) {
|
||||||
|
handle.Delete("/models/delete", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
|
if c.Mode == JSON {
|
||||||
|
panic("TODO handle json on models/delete")
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := MyParseForm(r)
|
||||||
|
if err != nil {
|
||||||
|
return ErrorCode(err, 400, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !CheckId(f, "id") {
|
||||||
|
return ErrorCode(nil, http.StatusNotFound, AnyMap{
|
||||||
|
"NotFoundMessage": "Model not found",
|
||||||
|
"GoBackLink": "/models",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
id := f.Get("id")
|
||||||
|
|
||||||
|
// TODO handle admin users
|
||||||
|
rows, err := handle.Db.Query("select name, status from models where id=$1 and user_id=$2;", id, c.User.Id)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rows.Next() {
|
||||||
|
return ErrorCode(nil, http.StatusNotFound, AnyMap{
|
||||||
|
"NotFoundMessage": "Model not found",
|
||||||
|
"GoBackLink": "/models",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var model BaseModel = BaseModel{}
|
||||||
|
model.Id = id
|
||||||
|
|
||||||
|
err = rows.Scan(&model.Name, &model.Status)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch model.Status {
|
||||||
|
case FAILED_PREPARING:
|
||||||
|
deleteModel(handle, id, w, c, model)
|
||||||
|
return nil
|
||||||
|
case CONFIRM_PRE_TRAINING:
|
||||||
|
|
||||||
|
if CheckEmpty(f, "name") {
|
||||||
|
// TODO improve result
|
||||||
|
return ErrorCode(nil, http.StatusBadRequest, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
name := f.Get("name")
|
||||||
|
if name != model.Name {
|
||||||
|
LoadError(w, "/models/edit.html", "delete-model-card", c.AddMap(AnyMap{
|
||||||
|
"NameDoesNotMatch": true,
|
||||||
|
"Model": model,
|
||||||
|
}))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteModel(handle, id, w, c, model)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
panic("Do not know how to handle model in status:" + strconv.Itoa(model.Status))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
80
logic/models/edit.go
Normal file
80
logic/models/edit.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleEdit(handle *Handle) {
|
||||||
|
handle.GetHTML("/models/edit", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
|
if !CheckAuthLevel(1, w, r, c) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := GetIdFromUrl(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
return ErrorCode(nil, http.StatusNotFound, AnyMap{
|
||||||
|
"NotFoundMessage": "Model not found",
|
||||||
|
"GoBackLink": "/models",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO handle admin users
|
||||||
|
rows, err := handle.Db.Query("select name, status, width, height, color_mode from models where id=$1 and user_id=$2;", id, c.User.Id)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rows.Next() {
|
||||||
|
return ErrorCode(nil, http.StatusNotFound, AnyMap{
|
||||||
|
"NotFoundMessage": "Model not found",
|
||||||
|
"GoBackLink": "/models",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type rowmodel struct {
|
||||||
|
Name string
|
||||||
|
Status int
|
||||||
|
Id string
|
||||||
|
Width *int
|
||||||
|
Height *int
|
||||||
|
Color_mode *string
|
||||||
|
}
|
||||||
|
|
||||||
|
var model rowmodel = rowmodel{}
|
||||||
|
model.Id = id
|
||||||
|
|
||||||
|
err = rows.Scan(&model.Name, &model.Status, &model.Width, &model.Height, &model.Color_mode)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle errors
|
||||||
|
// All errors will be negative
|
||||||
|
if model.Status < 0 {
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "/models/edit.html", c.AddMap(AnyMap{
|
||||||
|
"Model": model,
|
||||||
|
}))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch model.Status {
|
||||||
|
case PREPARING:
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "/models/edit.html", c.AddMap(AnyMap{
|
||||||
|
"Model": model,
|
||||||
|
}))
|
||||||
|
case CONFIRM_PRE_TRAINING:
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "/models/edit.html", c.AddMap(AnyMap{
|
||||||
|
"Model": model,
|
||||||
|
}))
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Printf("Unkown Status: %d\n", model.Status)
|
||||||
|
return Error500(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
12
logic/models/index.go
Normal file
12
logic/models/index.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HandleModels (handle *Handle) {
|
||||||
|
handleAdd(handle)
|
||||||
|
handleEdit(handle)
|
||||||
|
handleDelete(handle)
|
||||||
|
handleList(handle)
|
||||||
|
}
|
47
logic/models/list.go
Normal file
47
logic/models/list.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func handleList(handle *Handle) {
|
||||||
|
// TODO json
|
||||||
|
handle.GetHTML("/models", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
|
if c.Mode == JSON {
|
||||||
|
panic("TODO JSON")
|
||||||
|
}
|
||||||
|
if !CheckAuthLevel(1, w, r, c) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := handle.Db.Query("select id, name from models where user_id=$1;", c.User.Id)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type row struct {
|
||||||
|
Name string
|
||||||
|
Id string
|
||||||
|
}
|
||||||
|
|
||||||
|
got := []row{}
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var r row
|
||||||
|
err = rows.Scan(&r.Id, &r.Name)
|
||||||
|
if err != nil {
|
||||||
|
return Error500(err)
|
||||||
|
}
|
||||||
|
got = append(got, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadBasedOnAnswer(c.Mode, w, "/models/list.html", c.AddMap(AnyMap{
|
||||||
|
"List": got,
|
||||||
|
}))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
14
logic/models/types.go
Normal file
14
logic/models/types.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type BaseModel struct {
|
||||||
|
Name string
|
||||||
|
Status int
|
||||||
|
Id string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
FAILED_PREPARING = -1
|
||||||
|
|
||||||
|
PREPARING = iota
|
||||||
|
CONFIRM_PRE_TRAINING
|
||||||
|
)
|
16
logic/models/utils.go
Normal file
16
logic/models/utils.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func modelUpdateStatus(handle *Handle, id string, status int) {
|
||||||
|
_, err := handle.Db.Exec("update models set status = $1 where id = $2", status, id)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Failed to update model status")
|
||||||
|
fmt.Println(err)
|
||||||
|
panic("TODO handle better")
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@ -12,6 +12,8 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func baseLoadTemplate(base string, path string) (*template.Template, any) {
|
func baseLoadTemplate(base string, path string) (*template.Template, any) {
|
||||||
@ -127,8 +129,8 @@ func LoadError(writer http.ResponseWriter, path string, base string, data AnyMap
|
|||||||
type AnyMap = map[string]interface{}
|
type AnyMap = map[string]interface{}
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
code int
|
Code int
|
||||||
msg *string
|
Msg *string
|
||||||
data AnyMap
|
data AnyMap
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +182,7 @@ type Handler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Handle struct {
|
type Handle struct {
|
||||||
db *sql.DB
|
Db *sql.DB
|
||||||
gets []HandleFunc
|
gets []HandleFunc
|
||||||
posts []HandleFunc
|
posts []HandleFunc
|
||||||
deletes []HandleFunc
|
deletes []HandleFunc
|
||||||
@ -189,7 +191,7 @@ type Handle struct {
|
|||||||
func decodeBody(r *http.Request) (string, *Error) {
|
func decodeBody(r *http.Request) (string, *Error) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return "", &Error{code: http.StatusBadRequest}
|
return "", &Error{Code: http.StatusBadRequest}
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(body[:]), nil
|
return string(body[:]), nil
|
||||||
@ -198,18 +200,18 @@ func decodeBody(r *http.Request) (string, *Error) {
|
|||||||
func handleError(err *Error, w http.ResponseWriter, context *Context) {
|
func handleError(err *Error, w http.ResponseWriter, context *Context) {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data := context.addMap(err.data)
|
data := context.AddMap(err.data)
|
||||||
w.WriteHeader(err.code)
|
w.WriteHeader(err.Code)
|
||||||
if err.code == http.StatusNotFound {
|
if err.Code == http.StatusNotFound {
|
||||||
LoadBasedOnAnswer(context.Mode, w, "404.html", data)
|
LoadBasedOnAnswer(context.Mode, w, "404.html", data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err.code == http.StatusBadRequest {
|
if err.Code == http.StatusBadRequest {
|
||||||
LoadBasedOnAnswer(context.Mode, w, "400.html", data)
|
LoadBasedOnAnswer(context.Mode, w, "400.html", data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err.msg != nil {
|
if err.Msg != nil {
|
||||||
w.Write([]byte(*err.msg))
|
w.Write([]byte(*err.Msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,7 +262,7 @@ func (x *Handle) handleGets(w http.ResponseWriter, r *http.Request, context *Con
|
|||||||
if context.Mode != HTMLFULL {
|
if context.Mode != HTMLFULL {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
}
|
}
|
||||||
LoadBasedOnAnswer(context.Mode, w, "404.html", context.addMap(nil))
|
LoadBasedOnAnswer(context.Mode, w, "404.html", context.AddMap(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Handle) handlePosts(w http.ResponseWriter, r *http.Request, context *Context) {
|
func (x *Handle) handlePosts(w http.ResponseWriter, r *http.Request, context *Context) {
|
||||||
@ -273,7 +275,7 @@ func (x *Handle) handlePosts(w http.ResponseWriter, r *http.Request, context *Co
|
|||||||
if context.Mode != HTMLFULL {
|
if context.Mode != HTMLFULL {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
}
|
}
|
||||||
LoadBasedOnAnswer(context.Mode, w, "404.html", context.addMap(nil))
|
LoadBasedOnAnswer(context.Mode, w, "404.html", context.AddMap(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Handle) handleDeletes(w http.ResponseWriter, r *http.Request, context *Context) {
|
func (x *Handle) handleDeletes(w http.ResponseWriter, r *http.Request, context *Context) {
|
||||||
@ -286,16 +288,16 @@ func (x *Handle) handleDeletes(w http.ResponseWriter, r *http.Request, context *
|
|||||||
if context.Mode != HTMLFULL {
|
if context.Mode != HTMLFULL {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
}
|
}
|
||||||
LoadBasedOnAnswer(context.Mode, w, "404.html", context.addMap(nil))
|
LoadBasedOnAnswer(context.Mode, w, "404.html", context.AddMap(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkAuthLevel(authLevel int, w http.ResponseWriter, r *http.Request, c *Context) bool {
|
func CheckAuthLevel(authLevel int, w http.ResponseWriter, r *http.Request, c *Context) bool {
|
||||||
if authLevel > 0 {
|
if authLevel > 0 {
|
||||||
if c.requireAuth(w, r) {
|
if c.requireAuth(w, r) {
|
||||||
logoff(c.Mode, w, r)
|
Logoff(c.Mode, w, r)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if c.User.user_type < authLevel {
|
if c.User.UserType < authLevel {
|
||||||
notAuth(c.Mode, w, r)
|
notAuth(c.Mode, w, r)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -305,21 +307,21 @@ func checkAuthLevel(authLevel int, w http.ResponseWriter, r *http.Request, c *Co
|
|||||||
|
|
||||||
func AnswerTemplate(path string, data AnyMap, authLevel int) func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
func AnswerTemplate(path string, data AnyMap, authLevel int) func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
return func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
return func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
if !checkAuthLevel(authLevel, w, r, c) {
|
if !CheckAuthLevel(authLevel, w, r, c) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
LoadBasedOnAnswer(c.Mode, w, path, c.addMap(data))
|
LoadBasedOnAnswer(c.Mode, w, path, c.AddMap(data))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Token *string
|
Token *string
|
||||||
User *User
|
User *dbtypes.User
|
||||||
Mode AnswerType
|
Mode AnswerType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) addMap(m AnyMap) AnyMap {
|
func (c Context) AddMap(m AnyMap) AnyMap {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"Context": c,
|
"Context": c,
|
||||||
@ -356,7 +358,7 @@ func (x Handle) createContext(mode AnswerType, r *http.Request) (*Context, error
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := userFromToken(x.db, *token)
|
user, err := dbtypes.UserFromToken(x.Db, *token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(err, LogoffError)
|
return nil, errors.Join(err, LogoffError)
|
||||||
}
|
}
|
||||||
@ -365,7 +367,7 @@ func (x Handle) createContext(mode AnswerType, r *http.Request) (*Context, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO check if I can use http.Redirect
|
// TODO check if I can use http.Redirect
|
||||||
func redirect(path string, mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
func Redirect(path string, mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Location", path)
|
w.Header().Set("Location", path)
|
||||||
if mode == JSON {
|
if mode == JSON {
|
||||||
w.WriteHeader(http.StatusSeeOther)
|
w.WriteHeader(http.StatusSeeOther)
|
||||||
@ -380,7 +382,7 @@ func redirect(path string, mode AnswerType, w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func logoff(mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
func Logoff(mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
||||||
// Delete cookie
|
// Delete cookie
|
||||||
cookie := &http.Cookie{
|
cookie := &http.Cookie{
|
||||||
Name: "auth",
|
Name: "auth",
|
||||||
@ -388,7 +390,7 @@ func logoff(mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
|||||||
Expires: time.Unix(0, 0),
|
Expires: time.Unix(0, 0),
|
||||||
}
|
}
|
||||||
http.SetCookie(w, cookie)
|
http.SetCookie(w, cookie)
|
||||||
redirect("/login", mode, w, r)
|
Redirect("/login", mode, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func notAuth(mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
func notAuth(mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
||||||
@ -405,7 +407,7 @@ func notAuth(mode AnswerType, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x Handle) staticFiles(pathTest string, fileType string, contentType string) {
|
func (x Handle) StaticFiles(pathTest string, fileType string, contentType string) {
|
||||||
http.HandleFunc(pathTest, func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc(pathTest, func(w http.ResponseWriter, r *http.Request) {
|
||||||
path := r.URL.Path[len(pathTest):]
|
path := r.URL.Path[len(pathTest):]
|
||||||
|
|
||||||
@ -428,7 +430,7 @@ func (x Handle) staticFiles(pathTest string, fileType string, contentType string
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorCode(err error, code int, data AnyMap) *Error {
|
func ErrorCode(err error, code int, data AnyMap) *Error {
|
||||||
// TODO Improve Logging
|
// TODO Improve Logging
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Something went wrong returning with: %d\n.Err:\n", code)
|
fmt.Printf("Something went wrong returning with: %d\n.Err:\n", code)
|
||||||
@ -437,11 +439,11 @@ func errorCode(err error, code int, data AnyMap) *Error {
|
|||||||
return &Error{code, nil, data}
|
return &Error{code, nil, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
func error500(err error) *Error {
|
func Error500(err error) *Error {
|
||||||
return errorCode(err, http.StatusInternalServerError, nil)
|
return ErrorCode(err, http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x Handle) readFiles(pathTest string, baseFilePath string, fileType string, contentType string) {
|
func (x Handle) ReadFiles(pathTest string, baseFilePath string, fileType string, contentType string) {
|
||||||
http.HandleFunc(pathTest, func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc(pathTest, func(w http.ResponseWriter, r *http.Request) {
|
||||||
user_path := r.URL.Path[len(pathTest):]
|
user_path := r.URL.Path[len(pathTest):]
|
||||||
|
|
||||||
@ -487,7 +489,7 @@ func NewHandler(db *sql.DB) *Handle {
|
|||||||
//Login state
|
//Login state
|
||||||
context, err := x.createContext(ans, r)
|
context, err := x.createContext(ans, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logoff(ans, w, r)
|
Logoff(ans, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -10,20 +10,20 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkEmpty(f url.Values, path string) bool {
|
func CheckEmpty(f url.Values, path string) bool {
|
||||||
return !f.Has(path) || f.Get(path) == ""
|
return !f.Has(path) || f.Get(path) == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkId(f url.Values, path string) bool {
|
func CheckId(f url.Values, path string) bool {
|
||||||
return !checkEmpty(f, path) && isValidUUID(f.Get(path))
|
return !CheckEmpty(f, path) && IsValidUUID(f.Get(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func isValidUUID(u string) bool {
|
func IsValidUUID(u string) bool {
|
||||||
_, err := uuid.Parse(u)
|
_, err := uuid.Parse(u)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIdFromUrl(r *http.Request, target string) (string, error) {
|
func GetIdFromUrl(r *http.Request, target string) (string, error) {
|
||||||
if !r.URL.Query().Has(target) {
|
if !r.URL.Query().Has(target) {
|
||||||
return "", errors.New("Query does not have " + target)
|
return "", errors.New("Query does not have " + target)
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ func getIdFromUrl(r *http.Request, target string) (string, error) {
|
|||||||
return "", errors.New("Query is empty for " + target)
|
return "", errors.New("Query is empty for " + target)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isValidUUID(id) {
|
if !IsValidUUID(id) {
|
||||||
return "", errors.New("Value of query is not a valid uuid for " + target)
|
return "", errors.New("Value of query is not a valid uuid for " + target)
|
||||||
}
|
}
|
||||||
|
|
13
main.go
13
main.go
@ -5,6 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -33,15 +36,15 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
// TODO Handle this in other way
|
// TODO Handle this in other way
|
||||||
handle.staticFiles("/styles/", ".css", "text/css");
|
handle.StaticFiles("/styles/", ".css", "text/css");
|
||||||
handle.staticFiles("/js/", ".js", "text/javascript");
|
handle.StaticFiles("/js/", ".js", "text/javascript");
|
||||||
handle.readFiles("/imgs/", "views", ".png", "image/png;");
|
handle.ReadFiles("/imgs/", "views", ".png", "image/png;");
|
||||||
handle.readFiles("/savedData/", ".", ".png", "image/png;");
|
handle.ReadFiles("/savedData/", ".", ".png", "image/png;");
|
||||||
|
|
||||||
handle.GetHTML("/", AnswerTemplate("index.html", nil, 0))
|
handle.GetHTML("/", AnswerTemplate("index.html", nil, 0))
|
||||||
|
|
||||||
usersEndpints(db, handle)
|
usersEndpints(db, handle)
|
||||||
handleModelsEndpoints(handle)
|
HandleModels(handle)
|
||||||
|
|
||||||
handle.Startup()
|
handle.Startup()
|
||||||
}
|
}
|
||||||
|
405
models.go
405
models.go
@ -1,405 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
_ "image/png"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
FAILED_PREPARING = -1
|
|
||||||
|
|
||||||
PREPARING = iota
|
|
||||||
CONFIRM_PRE_TRAINING
|
|
||||||
)
|
|
||||||
|
|
||||||
type BaseModel struct {
|
|
||||||
Name string
|
|
||||||
Status int
|
|
||||||
Id string
|
|
||||||
}
|
|
||||||
|
|
||||||
func modelUpdateStatus(handle *Handle, id string, status int) {
|
|
||||||
_, err := handle.db.Exec("update models set status = $1 where id = $2", status, id)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Failed to update model status")
|
|
||||||
fmt.Println(err)
|
|
||||||
panic("TODO handle better")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadBaseImage(handle *Handle, id string) {
|
|
||||||
// TODO handle more types than png
|
|
||||||
infile, err := os.Open(path.Join("savedData", id, "baseimage.png"))
|
|
||||||
if err != nil {
|
|
||||||
// TODO better logging
|
|
||||||
fmt.Println(err)
|
|
||||||
fmt.Printf("Failed to read image for model with id %s\n", id)
|
|
||||||
modelUpdateStatus(handle, id, -1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer infile.Close()
|
|
||||||
|
|
||||||
src, format, err := image.Decode(infile)
|
|
||||||
if err != nil {
|
|
||||||
// TODO better logging
|
|
||||||
fmt.Println(err)
|
|
||||||
fmt.Printf("Failed to load image for model with id %s\n", id)
|
|
||||||
modelUpdateStatus(handle, id, -1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if format != "png" {
|
|
||||||
// TODO better logging
|
|
||||||
fmt.Printf("Found unkown format '%s'\n", format)
|
|
||||||
panic("Handle diferent files than .png")
|
|
||||||
}
|
|
||||||
|
|
||||||
var model_color string
|
|
||||||
|
|
||||||
bounds := src.Bounds()
|
|
||||||
width, height := bounds.Max.X, bounds.Max.Y
|
|
||||||
|
|
||||||
switch src.ColorModel() {
|
|
||||||
case color.Gray16Model:
|
|
||||||
fallthrough
|
|
||||||
case color.GrayModel:
|
|
||||||
model_color = "greyscale"
|
|
||||||
default:
|
|
||||||
fmt.Println("Do not know how to handle this color model")
|
|
||||||
|
|
||||||
if src.ColorModel() == color.RGBA64Model {
|
|
||||||
fmt.Println("Color is rgb")
|
|
||||||
} else if src.ColorModel() == color.NRGBAModel {
|
|
||||||
fmt.Println("Color is nrgb")
|
|
||||||
} else if src.ColorModel() == color.YCbCrModel {
|
|
||||||
fmt.Println("Color is ycbcr")
|
|
||||||
} else if src.ColorModel() == color.AlphaModel {
|
|
||||||
fmt.Println("Color is alpha")
|
|
||||||
} else if src.ColorModel() == color.CMYKModel {
|
|
||||||
fmt.Println("Color is cmyk")
|
|
||||||
} else {
|
|
||||||
fmt.Println("Other so assuming color")
|
|
||||||
}
|
|
||||||
|
|
||||||
modelUpdateStatus(handle, id, -1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: this also updates the status to 2
|
|
||||||
_, err = handle.db.Exec("update models set width=$1, height=$2, color_mode=$3, status=$4 where id=$5", width, height, model_color, CONFIRM_PRE_TRAINING, id)
|
|
||||||
if err != nil {
|
|
||||||
// TODO better logging
|
|
||||||
fmt.Println(err)
|
|
||||||
fmt.Printf("Could not update model\n")
|
|
||||||
modelUpdateStatus(handle, id, -1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteModel(handle *Handle, id string, w http.ResponseWriter, c *Context, model BaseModel) {
|
|
||||||
fmt.Printf("Removing model with id: %s\n", id)
|
|
||||||
_, err := handle.db.Exec("delete from models where id=$1;", id)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
panic("TODO handle better deleteModel failed delete database query")
|
|
||||||
}
|
|
||||||
|
|
||||||
model_path := path.Join("./savedData", id)
|
|
||||||
fmt.Printf("Removing folder of model with id: %s at %s\n", id, model_path)
|
|
||||||
err = os.RemoveAll(model_path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
panic("TODO handle better deleteModel failed to delete folder")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Mode == HTML {
|
|
||||||
// TODO move this to a constant so i don't forget
|
|
||||||
w.WriteHeader(309)
|
|
||||||
c.Mode = HTMLFULL
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "/models/delete.html", c.addMap(AnyMap{
|
|
||||||
"Model": model,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleModelsEndpoints(handle *Handle) {
|
|
||||||
|
|
||||||
// TODO json
|
|
||||||
handle.GetHTML("/models", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
|
||||||
if c.Mode == JSON {
|
|
||||||
panic("TODO JSON")
|
|
||||||
}
|
|
||||||
if !checkAuthLevel(1, w, r, c) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
rows, err := handle.db.Query("select id, name from models where user_id=$1;", c.User.id)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type row struct {
|
|
||||||
Name string
|
|
||||||
Id string
|
|
||||||
}
|
|
||||||
|
|
||||||
got := []row{}
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var r row
|
|
||||||
err = rows.Scan(&r.Id, &r.Name)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
got = append(got, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "/models/list.html", c.addMap(AnyMap{
|
|
||||||
"List": got,
|
|
||||||
}))
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
handle.GetHTML("/models/add", AnswerTemplate("models/add.html", nil, 1))
|
|
||||||
// TODO json
|
|
||||||
handle.Post("/models/add", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
|
||||||
if c.Mode == JSON {
|
|
||||||
panic("TODO JSON")
|
|
||||||
}
|
|
||||||
if !checkAuthLevel(1, w, r, c) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
read_form, err := r.MultipartReader()
|
|
||||||
if err != nil {
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "models/add.html", c.addMap(nil))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var name string
|
|
||||||
var file []byte
|
|
||||||
|
|
||||||
for {
|
|
||||||
part, err_part := read_form.NextPart()
|
|
||||||
if err_part == io.EOF {
|
|
||||||
break
|
|
||||||
} else if err_part != nil {
|
|
||||||
return &Error{code: http.StatusBadRequest}
|
|
||||||
}
|
|
||||||
if part.FormName() == "name" {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
buf.ReadFrom(part)
|
|
||||||
name = buf.String()
|
|
||||||
}
|
|
||||||
if part.FormName() == "file" {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
buf.ReadFrom(part)
|
|
||||||
file = buf.Bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "" || len(file) == 0 {
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "models/add.html", c.addMap(nil))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
row, err := handle.db.Query("select id from models where name=$1 and user_id=$2;", name, c.User.id)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if row.Next() {
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "models/add.html", c.addMap(AnyMap{
|
|
||||||
"NameFoundError": true,
|
|
||||||
"Name": name,
|
|
||||||
}))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = handle.db.Exec("insert into models (user_id, name) values ($1, $2)", c.User.id, name)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
row, err = handle.db.Query("select id from models where name=$1 and user_id=$2;", name, c.User.id)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !row.Next() {
|
|
||||||
return &Error{code: http.StatusInternalServerError}
|
|
||||||
}
|
|
||||||
|
|
||||||
var id string
|
|
||||||
err = row.Scan(&id)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO mk this path configurable
|
|
||||||
dir_path := path.Join("savedData", id)
|
|
||||||
|
|
||||||
err = os.Mkdir(dir_path, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
f, err := os.Create(path.Join(dir_path, "baseimage.png"))
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
f.Write(file)
|
|
||||||
|
|
||||||
fmt.Printf("Created model with id %s! Started to proccess image!\n", id)
|
|
||||||
go loadBaseImage(handle, id)
|
|
||||||
|
|
||||||
redirect("/models/edit?id="+id, c.Mode, w, r)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
handle.GetHTML("/models/edit", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
|
||||||
if !checkAuthLevel(1, w, r, c) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := getIdFromUrl(r, "id")
|
|
||||||
if err != nil {
|
|
||||||
return errorCode(nil, http.StatusNotFound, AnyMap{
|
|
||||||
"NotFoundMessage": "Model not found",
|
|
||||||
"GoBackLink": "/models",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO handle admin users
|
|
||||||
rows, err := handle.db.Query("select name, status, width, height, color_mode from models where id=$1 and user_id=$2;", id, c.User.id)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rows.Next() {
|
|
||||||
return errorCode(nil, http.StatusNotFound, AnyMap{
|
|
||||||
"NotFoundMessage": "Model not found",
|
|
||||||
"GoBackLink": "/models",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type rowmodel struct {
|
|
||||||
Name string
|
|
||||||
Status int
|
|
||||||
Id string
|
|
||||||
Width *int
|
|
||||||
Height *int
|
|
||||||
Color_mode *string
|
|
||||||
}
|
|
||||||
|
|
||||||
var model rowmodel = rowmodel{}
|
|
||||||
model.Id = id
|
|
||||||
|
|
||||||
err = rows.Scan(&model.Name, &model.Status, &model.Width, &model.Height, &model.Color_mode)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle errors
|
|
||||||
// All errors will be negative
|
|
||||||
if model.Status < 0 {
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "/models/edit.html", c.addMap(AnyMap{
|
|
||||||
"Model": model,
|
|
||||||
}))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch model.Status {
|
|
||||||
case PREPARING:
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "/models/edit.html", c.addMap(AnyMap{
|
|
||||||
"Model": model,
|
|
||||||
}))
|
|
||||||
case CONFIRM_PRE_TRAINING:
|
|
||||||
LoadBasedOnAnswer(c.Mode, w, "/models/edit.html", c.addMap(AnyMap{
|
|
||||||
"Model": model,
|
|
||||||
}))
|
|
||||||
|
|
||||||
default:
|
|
||||||
fmt.Printf("Unkown Status: %d\n", model.Status)
|
|
||||||
return error500(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
handle.Delete("/models/delete", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
|
||||||
if c.Mode == JSON {
|
|
||||||
panic("TODO handle json on models/delete")
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := MyParseForm(r)
|
|
||||||
if err != nil {
|
|
||||||
return errorCode(err, 400, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !checkId(f, "id") {
|
|
||||||
return errorCode(nil, http.StatusNotFound, AnyMap{
|
|
||||||
"NotFoundMessage": "Model not found",
|
|
||||||
"GoBackLink": "/models",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
id := f.Get("id")
|
|
||||||
|
|
||||||
// TODO handle admin users
|
|
||||||
rows, err := handle.db.Query("select name, status from models where id=$1 and user_id=$2;", id, c.User.id)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rows.Next() {
|
|
||||||
return errorCode(nil, http.StatusNotFound, AnyMap{
|
|
||||||
"NotFoundMessage": "Model not found",
|
|
||||||
"GoBackLink": "/models",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var model BaseModel = BaseModel{}
|
|
||||||
model.Id = id
|
|
||||||
|
|
||||||
err = rows.Scan(&model.Name, &model.Status)
|
|
||||||
if err != nil {
|
|
||||||
return error500(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch model.Status {
|
|
||||||
case FAILED_PREPARING:
|
|
||||||
deleteModel(handle, id, w, c, model)
|
|
||||||
return nil
|
|
||||||
case CONFIRM_PRE_TRAINING:
|
|
||||||
|
|
||||||
if checkEmpty(f, "name") {
|
|
||||||
// TODO improve result
|
|
||||||
return errorCode(nil, http.StatusBadRequest, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
name := f.Get("name")
|
|
||||||
if name != model.Name {
|
|
||||||
LoadError(w, "/models/edit.html", "delete-model-card", c.addMap(AnyMap{
|
|
||||||
"NameDoesNotMatch": true,
|
|
||||||
"Model": model,
|
|
||||||
}))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteModel(handle, id, w, c, model)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
panic("Do not know how to handle model in status:" + strconv.Itoa(model.Status))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
-- drop table if exists model_defenitions
|
-- drop table if exists model_defenitions;
|
||||||
-- drop table if exists models;
|
-- drop table if exists models;
|
||||||
create table if not exists models (
|
create table if not exists models (
|
||||||
id uuid primary key default gen_random_uuid(),
|
id uuid primary key default gen_random_uuid(),
|
||||||
@ -14,7 +14,9 @@ create table if not exists models (
|
|||||||
color_mode varchar (20)
|
color_mode varchar (20)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- create table model_defenitions (
|
-- drop table if exists model_classes;
|
||||||
-- id uuid primary key default gen_random_uuid(),
|
create table if not exists model_classes (
|
||||||
-- model_id uuid references models (id) not null,
|
id uuid primary key default gen_random_uuid(),
|
||||||
-- )
|
model_id uuid references models (id) not null,
|
||||||
|
name varchar (70) not null
|
||||||
|
);
|
||||||
|
60
users.go
60
users.go
@ -4,48 +4,16 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
|
||||||
id string
|
|
||||||
username string
|
|
||||||
email string
|
|
||||||
user_type int
|
|
||||||
}
|
|
||||||
|
|
||||||
var ErrUserNotFound = errors.New("User Not found")
|
|
||||||
|
|
||||||
func userFromToken(db *sql.DB, token string) (*User, error) {
|
|
||||||
row, err := db.Query("select users.id, users.username, users.email, users.user_type from users inner join tokens on tokens.user_id = users.id where tokens.token = $1;", token)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var id string
|
|
||||||
var username string
|
|
||||||
var email string
|
|
||||||
var user_type int
|
|
||||||
|
|
||||||
if !row.Next() {
|
|
||||||
return nil, ErrUserNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
err = row.Scan(&id, &username, &email, &user_type)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &User{id, username, email, user_type}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateSalt() string {
|
func generateSalt() string {
|
||||||
salt := make([]byte, 4)
|
salt := make([]byte, 4)
|
||||||
_, err := io.ReadFull(rand.Reader, salt)
|
_, err := io.ReadFull(rand.Reader, salt)
|
||||||
@ -112,14 +80,14 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
handle.Post("/login", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
handle.Post("/login", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
if c.Mode == JSON {
|
if c.Mode == JSON {
|
||||||
fmt.Println("Handle JSON")
|
fmt.Println("Handle JSON")
|
||||||
return &Error{code: 404}
|
return &Error{Code: 404}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
f := r.Form
|
f := r.Form
|
||||||
|
|
||||||
if checkEmpty(f, "email") || checkEmpty(f, "password") {
|
if CheckEmpty(f, "email") || CheckEmpty(f, "password") {
|
||||||
LoadBasedOnAnswer(c.Mode, w, "login.html", c.addMap(AnyMap{
|
LoadBasedOnAnswer(c.Mode, w, "login.html", c.AddMap(AnyMap{
|
||||||
"Submited": true,
|
"Submited": true,
|
||||||
}))
|
}))
|
||||||
return nil
|
return nil
|
||||||
@ -132,7 +100,7 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
expiration := time.Now().Add(24 * time.Hour)
|
expiration := time.Now().Add(24 * time.Hour)
|
||||||
token, login := generateToken(db, email, password)
|
token, login := generateToken(db, email, password)
|
||||||
if !login {
|
if !login {
|
||||||
LoadBasedOnAnswer(c.Mode, w, "login.html", c.addMap(AnyMap{
|
LoadBasedOnAnswer(c.Mode, w, "login.html", c.AddMap(AnyMap{
|
||||||
"Submited": true,
|
"Submited": true,
|
||||||
"NoUserOrPassword": true,
|
"NoUserOrPassword": true,
|
||||||
"Email": email,
|
"Email": email,
|
||||||
@ -151,13 +119,13 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
handle.GetHTML("/register", AnswerTemplate("register.html", nil, 0))
|
handle.GetHTML("/register", AnswerTemplate("register.html", nil, 0))
|
||||||
handle.Post("/register", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
handle.Post("/register", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
|
||||||
if c.Mode == JSON {
|
if c.Mode == JSON {
|
||||||
return &Error{code: http.StatusNotFound}
|
return &Error{Code: http.StatusNotFound}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
f := r.Form
|
f := r.Form
|
||||||
|
|
||||||
if checkEmpty(f, "email") || checkEmpty(f, "password") || checkEmpty(f, "username") {
|
if CheckEmpty(f, "email") || CheckEmpty(f, "password") || CheckEmpty(f, "username") {
|
||||||
LoadBasedOnAnswer(c.Mode, w, "register.html", AnyMap{
|
LoadBasedOnAnswer(c.Mode, w, "register.html", AnyMap{
|
||||||
"Submited": true,
|
"Submited": true,
|
||||||
})
|
})
|
||||||
@ -205,7 +173,7 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
hash_password, err := hashPassword(password, salt)
|
hash_password, err := hashPassword(password, salt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Error{
|
return &Error{
|
||||||
code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +181,7 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Error{
|
return &Error{
|
||||||
code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +192,8 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
if !login {
|
if !login {
|
||||||
msg := "Login failed"
|
msg := "Login failed"
|
||||||
return &Error{
|
return &Error{
|
||||||
code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
msg: &msg,
|
Msg: &msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +208,7 @@ func usersEndpints(db *sql.DB, handle *Handle) {
|
|||||||
if c.Mode == JSON {
|
if c.Mode == JSON {
|
||||||
panic("TODO handle json")
|
panic("TODO handle json")
|
||||||
}
|
}
|
||||||
logoff(c.Mode, w, r)
|
Logoff(c.Mode, w, r)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,18 @@
|
|||||||
</form>
|
</form>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "data-model-card" }}
|
||||||
|
<form hx-delete="/models/train" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML" {{ if .Error }} class="submitted" {{end}} >
|
||||||
|
data menu
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "train-model-card" }}
|
||||||
|
<form hx-delete="/models/train" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML" {{ if .Error }} class="submitted" {{end}} >
|
||||||
|
tain menu
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ define "mainbody" }}
|
{{ define "mainbody" }}
|
||||||
<main>
|
<main>
|
||||||
{{ if (eq .Model.Status 1) }}
|
{{ if (eq .Model.Status 1) }}
|
||||||
@ -73,6 +85,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{{ else if (eq .Model.Status 2) }}
|
{{ else if (eq .Model.Status 2) }}
|
||||||
{{ template "base-model-card" . }}
|
{{ template "base-model-card" . }}
|
||||||
|
{{ template "data-model-card" . }}
|
||||||
|
{{ template "train-model-card" . }}
|
||||||
{{ template "delete-model-card" . }}
|
{{ template "delete-model-card" . }}
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<h1>
|
<h1>
|
||||||
|
Loading…
Reference in New Issue
Block a user