diff --git a/logic/utils/handler.go b/logic/utils/handler.go index decdef4..45028e1 100644 --- a/logic/utils/handler.go +++ b/logic/utils/handler.go @@ -385,6 +385,10 @@ func (c Context) SendJSONStatus(w http.ResponseWriter, status int, dat any) *Err return nil } +func (c Context) JsonBadRequest(w http.ResponseWriter, dat any) *Error { + return c.SendJSONStatus(w, http.StatusBadRequest, dat) +} + func (c Context) Error400(err error, message string, w http.ResponseWriter, path string, base string, data AnyMap) *Error { c.SetReportCaller(true) c.Logger.Error(message) diff --git a/users.go b/users.go index 9405b95..b0150e1 100644 --- a/users.go +++ b/users.go @@ -10,6 +10,7 @@ import ( "golang.org/x/crypto/bcrypt" + dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" ) @@ -41,7 +42,6 @@ func genToken() string { } func generateToken(db *sql.DB, email string, password string) (string, bool) { - row, err := db.Query("select id, salt, password from users where email = $1;", email) if err != nil || !row.Next() { return "", false @@ -60,7 +60,7 @@ func generateToken(db *sql.DB, email string, password string) (string, bool) { panic("TODO handle better! Somethign is wrong with salt being stored in the database") } - if bcrypt.CompareHashAndPassword([]byte(db_password), append([]byte(password), bytes_salt...)) != nil { + if err = bcrypt.CompareHashAndPassword([]byte(db_password), append([]byte(password), bytes_salt...)); err != nil { return "", false } @@ -79,38 +79,45 @@ func usersEndpints(db *sql.DB, handle *Handle) { handle.Post("/login", func(w http.ResponseWriter, r *http.Request, c *Context) *Error { if c.Mode == JSON { - type UserLogin struct { - Email string `json:email` - Password string `json:password` - } + type UserLogin struct { + Email string `json:"email"` + Password string `json:"password"` + } - var dat UserLogin + var dat UserLogin if err := c.ToJSON(r, &dat); err != nil { return err } + // TODO Give this to the generateToken function + token, login := generateToken(db, dat.Email, dat.Password) + if !login { + return c.SendJSONStatus(w, http.StatusUnauthorized, "Email or password are incorrect") + } - /*if (dat["email"] == nil || dat["password"] == nil) { - // TODO improve this - c.Logger.Warn("Email or password are empty") - return c.Error500(nil) - }*/ + user, err := dbtypes.UserFromToken(c.Db, token) + if err != nil { + return c.Error500(err) + } - // TODO Give this to the generateToken function - expiration := time.Now().Add(24 * time.Hour) - token, login := generateToken(db, dat.Email, dat.Password) - if !login { - return c.SendJSONStatus(w, http.StatusUnauthorized, "Email or password are incorrect") - } + type UserReturn struct { + Token string `json:"token"` + Id string `json:"id"` + UserType int `json:"user_type"` + Username string `json:"username"` + Email string `json:"email"` + } + userReturn := UserReturn{ + Token: token, + Id: user.Id, + UserType: user.UserType, + Username: user.Username, + Email: user.Email, + } - cookie := &http.Cookie{Name: "auth", Value: token, HttpOnly: false, Expires: expiration} - http.SetCookie(w, cookie) - - w.Header().Set("Location", "/") - w.WriteHeader(http.StatusSeeOther) - return nil + return c.SendJSON(w, userReturn) } r.ParseForm() @@ -149,7 +156,87 @@ func usersEndpints(db *sql.DB, handle *Handle) { handle.GetHTML("/register", AnswerTemplate("register.html", nil, 0)) handle.Post("/register", func(w http.ResponseWriter, r *http.Request, c *Context) *Error { if c.Mode == JSON { - return &Error{Code: http.StatusNotFound} + type UserLogin struct { + Username string `json:"username"` + Email string `json:"email"` + Password string `json:"password"` + } + + var dat UserLogin + + if err := c.ToJSON(r, &dat); err != nil { + 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"); + } + + 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); + } + 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 len([]byte(dat.Password)) > 68 { + return c.JsonBadRequest(w, "Password is to long!") + } + + salt := generateSalt() + hash_password, err := hashPassword(dat.Password, salt) + if err != nil { + 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) + } + + // 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") + } + + user, err := dbtypes.UserFromToken(c.Db, token) + if err != nil { + return c.Error500(err) + } + + type UserReturn struct { + Token string `json:"token"` + Id string `json:"id"` + UserType int `json:"user_type"` + Username string `json:"username"` + Email string `json:"email"` + } + + userReturn := UserReturn{ + Token: token, + Id: user.Id, + UserType: user.UserType, + Username: user.Username, + Email: user.Email, + } + + return c.SendJSON(w, userReturn) } r.ParseForm() @@ -264,8 +351,6 @@ func usersEndpints(db *sql.DB, handle *Handle) { })) } - c.Logger.Warn("test", "email", r.Form.Get("email")) - _, err := c.Db.Exec("update users set email=$1 where id=$2", r.Form.Get("email"), c.User.Id) if err != nil { return c.Error500(err) diff --git a/webpage/src/routes/login/+page.svelte b/webpage/src/routes/login/+page.svelte index 41240a4..242e0ea 100644 --- a/webpage/src/routes/login/+page.svelte +++ b/webpage/src/routes/login/+page.svelte @@ -22,6 +22,7 @@ userStore.user = req; goto("/"); } catch (e) { + loginData.password = ""; if (e instanceof Response) { errorMessage = await e.json(); } else { @@ -29,7 +30,6 @@ } } } - diff --git a/webpage/src/routes/register/+page.svelte b/webpage/src/routes/register/+page.svelte new file mode 100644 index 0000000..c720189 --- /dev/null +++ b/webpage/src/routes/register/+page.svelte @@ -0,0 +1,104 @@ + + + + + Register + + + +
+
+

+ Register +

+
+
+ + + +
+
+ + + +
+
+ + + +
+ {#if errorMessage} +
+ {errorMessage} +
+ {/if} + +
+ + Login + +
+
+
+ +