1
0
Fork 0

Add data-model for more types and prevent double-registration

master
Dario Ernst 8 years ago
parent a22cfe992f
commit 4c3a8d5ad7

@ -3,10 +3,10 @@ package main
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"log"
"encoding/json" "encoding/json"
// "errors" "crypto/rand"
// "os" "reflect"
"log"
// muxer and form parser // muxer and form parser
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -25,17 +25,50 @@ import (
// database backend // database backend
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite" _ "github.com/jinzhu/gorm/dialects/sqlite"
// password hashing
"golang.org/x/crypto/scrypt"
) )
type User struct { type User struct {
gorm.Model gorm.Model
Name string `valid:"alphanum,required"`
Pass string `valid:"runelength(8|999),required"` Name string `valid:"alphanum,required"`
Email string `valid:"email,required"` Pass string `valid:"runelength(8|999),required"`
Salt string `valid:"optional"`
Email string `valid:"email,required"`
Lists []List
}
type List struct {
gorm.Model
UserID uint
Name string `valid:"alphanum,required"`
Icon string `valid:"alphanum,optional"`
Items []Item
}
type Item struct {
gorm.Model
ListID uint
Name string `valid:"alphanum,required"`
Amount float64 `valid:"optional"`
Bought bool `valid:"required"`
Unit Unit
UnitID uint
}
type Unit struct {
gorm.Model
Name string `valid:"alphanum,required"`
} }
var db *gorm.DB var db *gorm.DB
func getToken(w http.ResponseWriter, r *http.Request) error { func getToken(w http.ResponseWriter, r *http.Request) error {
var userInput User var userInput User
var userRecord User var userRecord User
@ -44,28 +77,30 @@ func getToken(w http.ResponseWriter, r *http.Request) error {
decoder := schema.NewDecoder() decoder := schema.NewDecoder()
err = r.ParseForm() err = r.ParseForm()
if err != nil { if err != nil {
return ehttp.NewErrorf(http.StatusInternalServerError, "could not parse form") return ehttp.NewErrorf(http.StatusInternalServerError, "could not parse form", err)
} }
err = decoder.Decode(&userInput, r.PostForm) err = decoder.Decode(&userInput, r.PostForm)
if err != nil { if err != nil {
return ehttp.NewErrorf(http.StatusInternalServerError, "could not decode user from form") return ehttp.NewErrorf(http.StatusInternalServerError, "could not decode user from form", err)
} }
log.Println("getToken got name:", userInput.Name, "pass:", userInput.Pass)
db.First(&userRecord) db.First(&userRecord)
if db.Error != nil { if db.Error != nil {
log.Println("db finding user had error",err) return ehttp.NewErrorf(http.StatusInternalServerError, "database lookup error", err)
return ehttp.NewErrorf(http.StatusInternalServerError, "database lookup error")
} }
if userRecord.Name == userInput.Name && userRecord.Pass == userInput.Pass { hash, err := scrypt.Key([]byte(userInput.Pass), []byte(userRecord.Salt), 16384, 8, 1, 32)
if err != nil {
return ehttp.NewErrorf(http.StatusInternalServerError, "cannot hash pass", err)
}
if userRecord.Name == userInput.Name && reflect.DeepEqual(hash, []byte(userRecord.Pass)) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"name":userRecord.Name, "name":userRecord.Name,
}) })
tokenString, err := token.SignedString([]byte("TODO")) tokenString, err := token.SignedString([]byte("TODO"))
if err != nil { if err != nil {
return ehttp.NewErrorf(http.StatusForbidden, "could not construct token") return ehttp.NewErrorf(http.StatusForbidden, "could not construct token", err)
} }
log.Println("authenticated user", userRecord.Name, "with token", tokenString) log.Println("authenticated user", userRecord.Name, "with token", tokenString)
@ -74,7 +109,6 @@ func getToken(w http.ResponseWriter, r *http.Request) error {
return nil return nil
} }
log.Println("getToken user not found")
return ehttp.NewErrorf(http.StatusForbidden, "Could not find user/pass") return ehttp.NewErrorf(http.StatusForbidden, "Could not find user/pass")
} }
@ -82,38 +116,49 @@ func register(w http.ResponseWriter, r *http.Request) error {
decoder := schema.NewDecoder() decoder := schema.NewDecoder()
err := r.ParseForm() err := r.ParseForm()
if err != nil { if err != nil {
log.Println("could not parse form because", err) return ehttp.NewErrorf(http.StatusInternalServerError, "could not parse form", err)
return ehttp.NewErrorf(http.StatusInternalServerError, "could not parse form")
} }
var input User var input User
err = decoder.Decode(&input, r.PostForm) err = decoder.Decode(&input, r.PostForm)
if err != nil { if err != nil {
log.Println("could not decode user because", err) return ehttp.NewErrorf(http.StatusInternalServerError, "could not decode user", err)
return ehttp.NewErrorf(http.StatusInternalServerError, "could not decode user")
} }
res, err := govalidator.ValidateStruct(input) res, err := govalidator.ValidateStruct(input)
if err != nil || res != true { if err != nil || res != true {
log.Println("user",input,"was invalid because", err) return ehttp.NewErrorf(http.StatusBadRequest, "could not validate your data", err)
return ehttp.NewErrorf(http.StatusBadRequest, "could not validate your data")
} }
countName := 0; countEmail := 0
db.Model(&User{Name:input.Name}).Count(&countName)
db.Model(&User{Email:input.Email}).Count(&countEmail)
if countName != 0 || countEmail != 0{
return ehttp.NewErrorf(http.StatusConflict, "username already exists")
}
salt := make([]byte, 64)
_, err = rand.Read(salt)
if err != nil {
return ehttp.NewErrorf(http.StatusInternalServerError, "could not generate salt", err)
}
input.Salt = string(salt)
log.Println("registered user", input) hash, err := scrypt.Key([]byte(input.Pass), salt, 16384, 8, 1, 32)
if err != nil {
return ehttp.NewErrorf(http.StatusInternalServerError, "could not hash pass", err)
}
input.Pass = string(hash)
ret := db.NewRecord(input) ret := db.NewRecord(input)
if ret != true { if ret != true {
log.Println("cannot register user",input,"cannot create record") return ehttp.NewErrorf(http.StatusInternalServerError, "could not create user", err)
return ehttp.NewErrorf(http.StatusInternalServerError, "could not create user")
} }
db.Create(&input) db.Create(&input)
log.Println("registered user", input) log.Println("registered user", input.Name)
return nil return nil
} }
func main() { func main() {
var err error var err error
@ -124,8 +169,15 @@ func main() {
} }
db.LogMode(false) db.LogMode(false)
// Create or update schemas … // Create or update schemas …
db.AutoMigrate(&User{}) db.AutoMigrate(&User{})
db.AutoMigrate(&List{})
db.AutoMigrate(&Item{})
db.AutoMigrate(&Unit{})
db.Model(&User{}).Related(&List{})
db.Model(&List{}).Related(&Item{})
db.Model(&Item{}).Related(&Unit{})
defer db.Close() defer db.Close()
// define URL handlers // define URL handlers
@ -136,3 +188,4 @@ func main() {
http.Handle("/", r) http.Handle("/", r)
http.ListenAndServe(":8000", nil) http.ListenAndServe(":8000", nil)
} }

Loading…
Cancel
Save