Files
nCovTrack-Backend/service/user/user.go
2022-02-27 16:36:33 +08:00

141 lines
4.5 KiB
Go

package user
import (
"encoding/json"
"fmt"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
"nCovTrack-Backend/global"
"nCovTrack-Backend/models"
"nCovTrack-Backend/utils"
"strings"
"time"
)
const (
EMAIL_CODE_REDIS_KEY = "verify_code_"
)
// Login if login success, will return token
func Login(user map[string]interface{}) (token string) {
account := user["account"].(string)
var queryMap []map[string]interface{}
if strings.Contains(account, "@") {
queryMap = append(queryMap, map[string]interface{}{"email": account})
} else {
queryMap = append(queryMap, map[string]interface{}{"phone": account})
}
userInfo := models.Get[models.BackUser](queryMap)
if userInfo == nil {
return ""
}
if !utils.PasswordCompare(user["password"].(string), userInfo["password"].(string)) {
return ""
}
claims := jwt.MapClaims{
"id": userInfo["id"],
"username": userInfo["username"],
"role": userInfo["role"],
"email": userInfo["email"],
}
return utils.GenerateToken(claims)
}
// Register user register, user can use account after approved
func Register(user map[string]interface{}) {
user["password"] = utils.PasswordEncrypt(user["password"].(string))
userStr, _ := json.Marshal(user)
// insert into redis, wait for approve
cmd := global.Redis.HMSet(global.REGISTER_REDIS_KEY, map[string]interface{}{user["email"].(string): userStr})
if cmd.Err() != nil {
panic(cmd.Err())
}
}
// ListRegister list the registers in the redis to be approved
func ListRegister() *[]map[string]interface{} {
applyStrMap := global.Redis.HGetAll(global.REGISTER_REDIS_KEY).Val()
var applies []map[string]interface{}
for _, v := range applyStrMap {
var apply map[string]interface{}
_ = json.Unmarshal([]byte(v), &apply)
applies = append(applies, apply)
}
if applies == nil {
applies = []map[string]interface{}{}
}
return &applies
}
// ApproveRegister approve a register
func ApproveRegister(email string, pass bool) bool {
if !pass {
rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val()
return rowsAffected != 0
}
// if pass, will get the register info from redis, and the insert into mysql, this mean user is register success
applyStr := global.Redis.HGet(global.REGISTER_REDIS_KEY, email).Val()
rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val()
if rowsAffected == 0 {
return false
}
var apply map[string]interface{}
_ = json.Unmarshal([]byte(applyStr), &apply)
if !NoDuplicatePhoneOrEmail(apply["phone"].(string), apply["email"].(string)) {
return false
}
colMap := models.MapJ2c[models.BackUser](apply, true)
ok, rowsAffected := models.Upsert[models.BackUser](colMap)
return ok && rowsAffected != 0
}
// ChangePassword user change password, or user forgot password
func ChangePassword(changePwd map[string]interface{}) bool {
match := VerifyEmailCode(changePwd["email"].(string), changePwd["code"].(string))["match"].(bool)
if !match {
return false
}
newPassword := utils.PasswordEncrypt(changePwd["newPassword"].(string))
colMap := map[string]interface{}{
"id": 1,
"password": newPassword,
}
models.BeforeSave(colMap, -1)
delete(colMap, "id")
rowAffected := global.Db.Model(models.BackUser{}).Where("email = ?", changePwd["email"]).Updates(colMap).RowsAffected
if rowAffected == 0 {
return false
}
now := time.Now().Unix()
global.Redis.HSet(global.CHANGEPWD_REDIS_KEY, changePwd["email"].(string), now)
return true
}
// NoDuplicatePhoneOrEmail detect the phone or email is registered or not
func NoDuplicatePhoneOrEmail(phone string, email string) bool {
var queryMap []map[string]interface{}
if phone != "" {
queryMap = append(queryMap, map[string]interface{}{"phone": phone})
}
if email != "" {
queryMap = append(queryMap, map[string]interface{}{"email": email})
}
return len(queryMap) != 0 && models.Count[models.BackUser](queryMap) == 0
}
// SendEmailCode used to send email verify code
func SendEmailCode(email string) bool {
code := uuid.New().String()[0:6]
text := fmt.Sprintf("Your Verify Code is :%s, Will Expire After 10 Minutes", code)
subject := "nCovTrack Verify"
// only set expired, not limit the frequency of use
global.Redis.Set(EMAIL_CODE_REDIS_KEY+email, code, 10*time.Minute)
return utils.SendEmail(subject, text, email)
}
// VerifyEmailCode use to verify user's verify code is correct or not
func VerifyEmailCode(email string, code string) map[string]interface{} {
verifyCode := global.Redis.Get(EMAIL_CODE_REDIS_KEY + email).Val()
return map[string]interface{}{"match": verifyCode == code}
}