From ce866725ffe09795ed5414afe67dd860e82551ff Mon Sep 17 00:00:00 2001 From: Andre Henriques Date: Sat, 24 Feb 2024 15:28:23 +0000 Subject: [PATCH] chore: more work on the app --- logic/db_types/user.go | 7 + logic/utils/handler.go | 39 +++-- users.go | 169 ++++++++++++++++++--- webpage/src/lib/FileUpload.svelte | 43 ++++++ webpage/src/lib/MessageSimple.svelte | 52 +++++++ webpage/src/routes/models/+page.svelte | 59 +++++++ webpage/src/routes/models/add/+page.svelte | 80 ++++++++++ webpage/src/routes/user/info/+page.svelte | 129 ++++++++++++++++ webpage/src/styles/app.css | 4 + webpage/static/imgs/upload-icon.png | Bin 0 -> 5572 bytes 10 files changed, 544 insertions(+), 38 deletions(-) create mode 100644 webpage/src/lib/FileUpload.svelte create mode 100644 webpage/src/lib/MessageSimple.svelte create mode 100644 webpage/src/routes/models/+page.svelte create mode 100644 webpage/src/routes/models/add/+page.svelte create mode 100644 webpage/src/routes/user/info/+page.svelte create mode 100644 webpage/static/imgs/upload-icon.png diff --git a/logic/db_types/user.go b/logic/db_types/user.go index 89a4785..f29e62a 100644 --- a/logic/db_types/user.go +++ b/logic/db_types/user.go @@ -5,6 +5,13 @@ import ( "errors" ) +type UserType int + +const ( + User_Normal UserType = iota + 1 + User_Admin +) + type User struct { Id string Username string diff --git a/logic/utils/handler.go b/logic/utils/handler.go index 45028e1..586e05b 100644 --- a/logic/utils/handler.go +++ b/logic/utils/handler.go @@ -471,11 +471,19 @@ func (x Handle) createContext(handler *Handle, mode AnswerType, r *http.Request) Prefix: r.URL.Path, }) - for _, r := range r.Cookies() { - if r.Name == "auth" { - token = &r.Value - } - } + if mode != JSON { + for _, r := range r.Cookies() { + if r.Name == "auth" { + token = &r.Value + } + } + } else { + t := r.Header.Get("token") + if t != "" { + token = &t + } + } + // TODO check that the token is still valid @@ -512,14 +520,19 @@ func Redirect(path string, mode AnswerType, w http.ResponseWriter, r *http.Reque } func Logoff(mode AnswerType, w http.ResponseWriter, r *http.Request) { - // Delete cookie - cookie := &http.Cookie{ - Name: "auth", - Value: "", - Expires: time.Unix(0, 0), - } - http.SetCookie(w, cookie) - Redirect("/login", mode, w, r) + if (mode == JSON) { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("\"Not Authorized\"")) + } else { + // Delete cookie + cookie := &http.Cookie{ + Name: "auth", + Value: "", + Expires: time.Unix(0, 0), + } + http.SetCookie(w, cookie) + Redirect("/login", mode, w, r) + } } func notAuth(mode AnswerType, w http.ResponseWriter, r *http.Request) { diff --git a/users.go b/users.go index b0150e1..5c31f71 100644 --- a/users.go +++ b/users.go @@ -11,6 +11,7 @@ import ( "golang.org/x/crypto/bcrypt" dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" + "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" ) @@ -168,52 +169,52 @@ func usersEndpints(db *sql.DB, handle *Handle) { return err } - if len(dat.Username) == 0 || len(dat.Password) == 0 || len(dat.Email) == 0 { - return c.SendJSONStatus(w, http.StatusBadRequest, "Please provide a valid json"); - } + if len(dat.Username) == 0 || len(dat.Password) == 0 || len(dat.Email) == 0 { + return c.SendJSONStatus(w, http.StatusBadRequest, "Please provide a valid json") + } rows, err := db.Query("select username, email from users where username=$1 or email=$2;", dat.Username, dat.Email) - if err != nil { - return c.Error500(err); - } + if err != nil { + return c.Error500(err) + } defer rows.Close() if rows.Next() { var db_username string var db_email string err = rows.Scan(&db_username, &db_email) - if err != nil { - return c.Error500(err) - } - if (db_email == dat.Email) { - return c.SendJSONStatus(w, http.StatusBadRequest, "Email already in use!") - } - if (db_username == dat.Username) { - return c.SendJSONStatus(w, http.StatusBadRequest, "Username already in use!") - } - panic("Unrechable") + if err != nil { + return c.Error500(err) + } + if db_email == dat.Email { + return c.SendJSONStatus(w, http.StatusBadRequest, "Email already in use!") + } + if db_username == dat.Username { + return c.SendJSONStatus(w, http.StatusBadRequest, "Username already in use!") + } + panic("Unrechable") } if len([]byte(dat.Password)) > 68 { - return c.JsonBadRequest(w, "Password is to long!") + return c.JsonBadRequest(w, "Password is to long!") } salt := generateSalt() hash_password, err := hashPassword(dat.Password, salt) if err != nil { - return c.Error500(err) + return c.Error500(err) } _, err = db.Exec("insert into users (username, email, salt, password) values ($1, $2, $3, $4);", dat.Username, dat.Email, salt, hash_password) - if err != nil { - return c.Error500(err) - } + if err != nil { + return c.Error500(err) + } // TODO Give this to the generateToken function token, login := generateToken(db, dat.Email, dat.Password) - if !login { - return c.SendJSONStatus(w, 500, "Could not login after creatting account please try again later") - } + if !login { + return c.SendJSONStatus(w, 500, "Could not login after creatting account please try again later") + } user, err := dbtypes.UserFromToken(c.Db, token) if err != nil { @@ -335,6 +336,87 @@ func usersEndpints(db *sql.DB, handle *Handle) { return nil }) + // Handles updating users + handle.Post("/user/info", func(w http.ResponseWriter, r *http.Request, c *Context) *Error { + if !CheckAuthLevel(int(dbtypes.User_Normal), w, r, c) { + return nil + } + if c.Mode != JSON { + return c.Error500(nil) + } + + type UserData struct { + Id string `json:"id"` + Email string `json:"email"` + } + + var dat UserData + + if err := c.ToJSON(r, &dat); err != nil { + return err + } + + if dat.Id != c.User.Id && c.User.UserType != int(dbtypes.User_Admin) { + return c.SendJSONStatus(w, 401, "You need to be an admin to update another users account") + } + + if dat.Id != c.User.Id { + var data struct { + Id string + } + + err := utils.GetDBOnce(c, &data, "users where id=$1", dat.Id) + if err == NotFoundError { + return c.JsonBadRequest(w, "User does not exist") + } else if err != nil { + return c.Error500(err) + } + } + + var data struct { + Id string + } + + err := utils.GetDBOnce(c, &data, "users where email=$1", dat.Email) + if err != nil && err != NotFoundError { + return c.Error500(err) + } + + if err != NotFoundError { + if data.Id == dat.Id { + return c.JsonBadRequest(w, "Email is the name as the previous one!") + } else { + return c.JsonBadRequest(w, "Email already in use") + } + } + + _, err = c.Db.Exec("update users set email=$2 where id=$1", dat.Id, dat.Email) + if err != nil { + return c.Error500(err) + } + + var user struct { + Id string + Username string + Email string + User_Type int + } + + err = utils.GetDBOnce(c, &user, "users where id=$1", dat.Id) + if err != nil { + return c.Error500(err) + } + + toReturnUser := dbtypes.User{ + Id: user.Id, + Username: user.Username, + Email: user.Email, + UserType: user.User_Type, + } + + return c.SendJSON(w, toReturnUser) + }) + handle.Post("/user/info/email", func(w http.ResponseWriter, r *http.Request, c *Context) *Error { if !CheckAuthLevel(1, w, r, c) { return nil @@ -367,7 +449,44 @@ func usersEndpints(db *sql.DB, handle *Handle) { return nil } if c.Mode == JSON { - return c.Error500(nil) + + var dat struct { + Old_Password string `json:"old_password"` + Password string `json:"password"` + Password2 string `json:"password2"` + } + + if err := c.ToJSON(r, &dat); err != nil { + return err + } + + if dat.Password == "" { + return c.JsonBadRequest(w, "Password can not be empty") + } + + if dat.Password != dat.Password2 { + return c.JsonBadRequest(w, "New passwords did not match") + } + + c.Logger.Warn("test", "dat", dat) + + _, login := generateToken(db, c.User.Email, dat.Old_Password) + if !login { + return c.JsonBadRequest(w, "Password is incorrect"); + } + + salt := generateSalt() + hash_password, err := hashPassword(dat.Password, salt) + if err != nil { + return c.Error500(err) + } + + _, err = db.Exec("update users set salt=$1, password=$2 where id=$3", salt, hash_password, c.User.Id) + if err != nil { + return c.Error500(err) + } + + return c.SendJSON(w, c.User.Id) } r.ParseForm() diff --git a/webpage/src/lib/FileUpload.svelte b/webpage/src/lib/FileUpload.svelte new file mode 100644 index 0000000..c3e1090 --- /dev/null +++ b/webpage/src/lib/FileUpload.svelte @@ -0,0 +1,43 @@ + + +
+ + +
diff --git a/webpage/src/lib/MessageSimple.svelte b/webpage/src/lib/MessageSimple.svelte new file mode 100644 index 0000000..86d1d2e --- /dev/null +++ b/webpage/src/lib/MessageSimple.svelte @@ -0,0 +1,52 @@ + + + + +{#if message} +
+ {message} +
+{/if} diff --git a/webpage/src/routes/models/+page.svelte b/webpage/src/routes/models/+page.svelte new file mode 100644 index 0000000..f19c30d --- /dev/null +++ b/webpage/src/routes/models/+page.svelte @@ -0,0 +1,59 @@ + + + + + Models + + + +
+ {#if list.length > 0} +
+

My Models

+
+ + New + +
+ + + + + + + + + {#each list as item} + + + + + {/each} + +
+ Name + + +
+ {item.name} + + + Edit + +
+ {:else} +

+ You don't have any models +

+ + {/if} +
diff --git a/webpage/src/routes/models/add/+page.svelte b/webpage/src/routes/models/add/+page.svelte new file mode 100644 index 0000000..c8cf3d8 --- /dev/null +++ b/webpage/src/routes/models/add/+page.svelte @@ -0,0 +1,80 @@ + + + + Create new Model + + +
+

+ Create new Model +

+
+
+ + + +
+
+ +
+ Please provide a base image.
+ This image is a sample of the images that you are going to classfiy. +
+ + + + Upload image + +
+ + Image selected + +
+
+
+ + {#await buttonClicked} +
+ File Uploading +
+ {:then} + + {/await} + +
+ + diff --git a/webpage/src/routes/user/info/+page.svelte b/webpage/src/routes/user/info/+page.svelte new file mode 100644 index 0000000..67cb796 --- /dev/null +++ b/webpage/src/routes/user/info/+page.svelte @@ -0,0 +1,129 @@ + + + + User Info + + +
+
+

User Infomation

+
+
+ + +
+ + + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ + +
+
+ + diff --git a/webpage/src/styles/app.css b/webpage/src/styles/app.css index 50800a7..4fd3e93 100644 --- a/webpage/src/styles/app.css +++ b/webpage/src/styles/app.css @@ -37,6 +37,10 @@ button { } } +a.button { + text-decoration: none; +} + .flex { display: flex; } diff --git a/webpage/static/imgs/upload-icon.png b/webpage/static/imgs/upload-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..88e26b837c9c8e182c59ddb3c30585d04160b128 GIT binary patch literal 5572 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