mirror of https://github.com/sunface/rust-course
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
5.6 KiB
245 lines
5.6 KiB
package user
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/asaskevich/govalidator"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/imdotdev/im.dev/server/internal/email"
|
|
"github.com/imdotdev/im.dev/server/pkg/common"
|
|
"github.com/imdotdev/im.dev/server/pkg/config"
|
|
"github.com/imdotdev/im.dev/server/pkg/db"
|
|
"github.com/imdotdev/im.dev/server/pkg/log"
|
|
"github.com/imdotdev/im.dev/server/pkg/models"
|
|
"github.com/matcornic/hermes/v2"
|
|
)
|
|
|
|
var logger = log.RootLogger.New("logger", "user")
|
|
|
|
type Session struct {
|
|
Token string `json:"token"`
|
|
User *models.User `json:"user"`
|
|
CreateTime time.Time `json:"createTime"`
|
|
}
|
|
|
|
func Login(c *gin.Context) {
|
|
user := &models.User{}
|
|
c.Bind(&user)
|
|
err := user.Query("", "", user.Email)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
c.JSON(http.StatusNotFound, common.RespError("邮箱不存在"))
|
|
return
|
|
}
|
|
logger.Error("login error", "error", err)
|
|
c.JSON(http.StatusInternalServerError, common.RespInternalError())
|
|
return
|
|
}
|
|
|
|
// delete old session
|
|
token := getToken(c)
|
|
deleteSession(token)
|
|
|
|
token = strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
session := &Session{
|
|
Token: token,
|
|
User: user,
|
|
CreateTime: time.Now(),
|
|
}
|
|
|
|
err = storeSession(session)
|
|
if err != nil {
|
|
c.JSON(500, common.RespInternalError())
|
|
return
|
|
}
|
|
|
|
_, err = db.Conn.Exec(`UPDATE user SET last_seen_at=? WHERE id=?`, time.Now(), user.ID)
|
|
if err != nil {
|
|
logger.Warn("set last login date error", "error", err)
|
|
}
|
|
|
|
c.JSON(http.StatusOK, common.RespSuccess(session))
|
|
}
|
|
|
|
func LoginEmail(c *gin.Context) {
|
|
user := &models.User{}
|
|
c.Bind(&user)
|
|
|
|
if !govalidator.IsEmail(user.Email) {
|
|
c.JSON(http.StatusBadRequest, common.RespError("邮件格式不合法"))
|
|
return
|
|
}
|
|
|
|
fmt.Println(user.Email)
|
|
|
|
e := hermes.Email{
|
|
Body: hermes.Body{
|
|
Title: "Hello there",
|
|
Name: "",
|
|
Intros: []string{
|
|
fmt.Sprintf("Welcome to %s! We're very excited to have you on board.", config.Data.Common.AppName),
|
|
},
|
|
Actions: []hermes.Action{
|
|
{
|
|
Instructions: "To get started, please click here:",
|
|
Button: hermes.Button{
|
|
Color: "#22BC66", // Optional action button color
|
|
Text: "Confirm your account",
|
|
Link: config.Data.UI.Domain,
|
|
},
|
|
},
|
|
},
|
|
Outros: []string{
|
|
"Need help, or have questions? Just reply to this email, we'd love to help.",
|
|
},
|
|
},
|
|
}
|
|
|
|
emailBody, err := email.H.GenerateHTML(e)
|
|
|
|
emailMsg := &email.EmailMessage{
|
|
To: []string{user.Email},
|
|
From: fmt.Sprintf("%s <%s>", config.Dynamic.SMTP.FromName, config.Dynamic.SMTP.FromAddress),
|
|
Subject: fmt.Sprintf("Sign in to %s", config.Data.Common.AppName),
|
|
Body: emailBody,
|
|
}
|
|
|
|
err = email.Send(emailMsg)
|
|
if err != nil {
|
|
logger.Warn("send login email error", "error", err)
|
|
c.JSON(http.StatusBadRequest, common.RespError(err.Error()))
|
|
return
|
|
}
|
|
// err := user.Query("", "", user.Email)
|
|
// if err != nil {
|
|
// if err == sql.ErrNoRows {
|
|
// c.JSON(http.StatusNotFound, common.RespError("邮箱不存在"))
|
|
// return
|
|
// }
|
|
// logger.Error("login error", "error", err)
|
|
// c.JSON(http.StatusInternalServerError, common.RespInternalError())
|
|
// return
|
|
// }
|
|
|
|
// // delete old session
|
|
// token := getToken(c)
|
|
// deleteSession(token)
|
|
|
|
// token = strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
// session := &Session{
|
|
// Token: token,
|
|
// User: user,
|
|
// CreateTime: time.Now(),
|
|
// }
|
|
|
|
// err = storeSession(session)
|
|
// if err != nil {
|
|
// c.JSON(500, common.RespInternalError())
|
|
// return
|
|
// }
|
|
|
|
// _, err = db.Conn.Exec(`UPDATE user SET last_seen_at=? WHERE id=?`, time.Now(), user.ID)
|
|
// if err != nil {
|
|
// logger.Warn("set last login date error", "error", err)
|
|
// }
|
|
|
|
c.JSON(http.StatusOK, common.RespSuccess(nil))
|
|
}
|
|
|
|
// Logout ...
|
|
func Logout(c *gin.Context) {
|
|
token := getToken(c)
|
|
// 删除用户的session
|
|
deleteSession(token)
|
|
|
|
c.JSON(http.StatusOK, common.RespSuccess(nil))
|
|
}
|
|
|
|
func getToken(c *gin.Context) string {
|
|
return c.Request.Header.Get("X-Token")
|
|
}
|
|
|
|
func deleteSession(sid string) {
|
|
q := `DELETE FROM sessions WHERE sid=?`
|
|
_, err := db.Conn.Exec(q, sid)
|
|
if err != nil {
|
|
logger.Warn("delete session error", "error", err)
|
|
}
|
|
}
|
|
|
|
func storeSession(s *Session) error {
|
|
q := `insert into sessions (user_id,sid) VALUES (?,?)`
|
|
_, err := db.Conn.Exec(q, s.User.ID, s.Token)
|
|
if err != nil {
|
|
logger.Warn("store session error", "error", err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func CurrentUser(c *gin.Context) *models.User {
|
|
token := getToken(c)
|
|
createTime, _ := strconv.ParseInt(token, 10, 64)
|
|
if createTime != 0 {
|
|
// check whether token is expired
|
|
if (time.Now().Unix() - createTime/1e9) > config.Data.User.SessionExpire {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
sess := loadSession(token)
|
|
if sess == nil {
|
|
// 用户未登陆或者session失效
|
|
return nil
|
|
}
|
|
|
|
return sess.User
|
|
}
|
|
|
|
func GetSession(c *gin.Context) *Session {
|
|
token := getToken(c)
|
|
createTime, _ := strconv.ParseInt(token, 10, 64)
|
|
if createTime != 0 {
|
|
// check whether token is expired
|
|
if (time.Now().Unix() - createTime/1e9) > config.Data.User.SessionExpire {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
sess := loadSession(token)
|
|
if sess == nil {
|
|
// 用户未登陆或者session失效
|
|
return nil
|
|
}
|
|
|
|
return sess
|
|
}
|
|
|
|
func loadSession(sid string) *Session {
|
|
var userid string
|
|
q := `SELECT user_id FROM sessions WHERE sid=?`
|
|
err := db.Conn.QueryRow(q, sid).Scan(&userid)
|
|
if err != nil {
|
|
if err != sql.ErrNoRows {
|
|
logger.Warn("query session error", "error", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
user := &models.User{}
|
|
err = user.Query(userid, "", "")
|
|
if err != nil {
|
|
logger.Warn("query user error", "error", err)
|
|
return nil
|
|
}
|
|
|
|
return &Session{
|
|
Token: sid,
|
|
User: user,
|
|
}
|
|
}
|