go-gallery/routers/account/account.go

169 lines
3.1 KiB
Go

package account
import (
"crypto/rand"
"crypto/sha512"
"encoding/hex"
"encoding/json"
"reflect"
"strings"
"git.trj.tw/golang/go-gallery/modules/memstore"
"git.trj.tw/golang/go-gallery/models"
"git.trj.tw/golang/go-gallery/modules/context"
"git.trj.tw/golang/go-gallery/modules/utils"
"golang.org/x/crypto/pbkdf2"
)
var passIterator = 2048
var passLen = 64
var passSaltLen = 16
var passHash = sha512.New
// UserLogin route
func UserLogin(c *context.Context) {
loginArg := struct {
Account string `form:"account" json:"account" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
}{
Account: "",
Password: "",
}
err := c.BindData(&loginArg)
if err != nil {
c.DataFormat(nil)
return
}
acc, err := models.GetAccount(loginArg.Account)
if err != nil {
c.ServerError(nil)
return
}
if acc == nil {
c.NotFound("User not found")
return
}
strs := strings.Split(acc.Password, ".")
if len(strs) != 2 {
c.ServerError("store pass format error")
return
}
b, err := hex.DecodeString(strs[0])
if err != nil {
c.ServerError(nil)
return
}
hashPass, err := hex.DecodeString(strs[1])
if err != nil {
c.ServerError(nil)
return
}
enc := pbkdf2.Key([]byte(loginArg.Password), b, passIterator, passLen, passHash)
if enc == nil || !reflect.DeepEqual(enc, hashPass) {
c.DataFormat("password error")
return
}
res := utils.ToMap(acc)
m := make(map[string]interface{})
m["user"] = res
jsonStr, err := json.Marshal(m)
if err != nil {
c.ServerError(nil)
return
}
tByte := make([]byte, 20)
_, err = rand.Read(tByte)
if err != nil {
c.ServerError(nil)
return
}
err = memstore.RedisSet("golang", hex.EncodeToString(tByte), string(jsonStr), 3600)
if err != nil {
c.ServerError(nil)
}
m["token"] = hex.EncodeToString(tByte)
c.Success(m)
}
// UserLogout route
func UserLogout(c *context.Context) {
token := c.GetHeader("X-Auth-Token")
if len(token) == 0 {
c.DataFormat("token not found")
return
}
err := memstore.RedisDel("golang", token)
if err != nil {
c.ServerError("remvoe session fail")
return
}
c.Success(nil)
}
// UserSignup route
func UserSignup(c *context.Context) {
singupObj := struct {
Account string `json:"account" binding:"required"`
Password string `json:"password" binding:"required"`
Nick string `json:"nick"`
Email string `json:"email" binding:"required"`
}{}
err := c.BindData(&singupObj)
if err != nil {
c.DataFormat(nil)
return
}
salt := make([]byte, passSaltLen)
_, err = rand.Read(salt)
if err != nil {
c.ServerError(nil)
return
}
passBuf := pbkdf2.Key([]byte(singupObj.Password), salt, passIterator, passLen, passHash)
passStr := hex.EncodeToString(salt) + "." + hex.EncodeToString(passBuf)
dat, err := models.GetAccount(singupObj.Account)
if err != nil {
c.ServerError(nil)
return
}
if dat != nil {
c.DataFormat("account exists")
return
}
dat = nil
acc := &models.Account{}
acc.Account = singupObj.Account
acc.Nick = singupObj.Nick
acc.Password = passStr
acc.Email = singupObj.Email
err = acc.Create()
if err != nil {
c.ServerError(nil)
return
}
c.Success(nil)
}