package session import ( "database/sql" "net/http" "strconv" "time" "github.com/gin-gonic/gin" "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" ) var logger = log.RootLogger.New("logger", "session") 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{} err := user.Query(0, config.Data.User.SuperAdminUsername, "") if err != nil { if err == sql.ErrNoRows { c.String(http.StatusNotFound, "") 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)) } // 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.Info("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 { deleteSession(token) return nil } } sess := loadSession(token) if sess == nil { // 用户未登陆或者session失效 return nil } return sess.User } func loadSession(sid string) *Session { var userid int64 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, } }