/session.go

http://github.com/TheOnly92/bloody.go · Go · 134 lines · 119 code · 14 blank · 1 comment · 21 complexity · d1ed48cbd03800f477dcec1cb5756922 MD5 · raw file

  1. package session
  2. import (
  3. "crypto/sha1"
  4. "http"
  5. "time"
  6. "hash"
  7. "web"
  8. "launchpad.net/mgo"
  9. "launchpad.net/gobson/bson"
  10. "encoding/hex"
  11. "json"
  12. "strconv"
  13. )
  14. type Session struct {
  15. id string
  16. old_id string
  17. Data map[string]interface{}
  18. handler *MHandler
  19. }
  20. func Start(ctx *web.Context, handler *MHandler) *Session {
  21. session := new(Session)
  22. session.handler = handler
  23. session.handler.Clean()
  24. old := false
  25. if ctx.Cookies != nil {
  26. if id, exists := ctx.Cookies["bloody_sess"]; exists {
  27. session.id = id
  28. old = true
  29. }
  30. }
  31. if !old {
  32. // Starts new session
  33. session.generateId()
  34. session.handler.Store(session.GetID(), nil)
  35. }
  36. rt := session.handler.Retrieve(session.GetID())
  37. json.Unmarshal(rt.SessionData, &session.Data)
  38. if session.Data == nil {
  39. t := make(map[string]interface{})
  40. session.Data = t
  41. }
  42. ctx.SetCookie("bloody_sess", session.GetID(), time.LocalTime().Seconds() + 3600)
  43. return session
  44. }
  45. func (session *Session) Save() {
  46. session.handler.Store(session.id, session.Data)
  47. }
  48. func (session *Session) generateId() string {
  49. var header = make(http.Header)
  50. remoteAddr := header.Get("REMOTE_ADDR")
  51. t := time.LocalTime()
  52. var h hash.Hash = sha1.New()
  53. h.Write([]byte(remoteAddr+strconv.Itoa64(t.Seconds())))
  54. session.id = hex.EncodeToString(h.Sum())
  55. return session.id
  56. }
  57. func (session *Session) GetID() string {
  58. return session.id
  59. }
  60. func (session *Session) SetID(id string) {
  61. session.id = id
  62. }
  63. type MHandler struct {
  64. session *mgo.Session
  65. }
  66. type sessionRow struct {
  67. SessionID string
  68. ExpirationTS int64
  69. SessionData []byte
  70. }
  71. func (handler *MHandler) Store(id string, data map[string]interface{}) {
  72. c := handler.session.DB("bloody").C("sessions")
  73. t := time.LocalTime()
  74. b, _ := json.Marshal(data)
  75. var sav sessionRow
  76. sav.SessionID = id
  77. sav.ExpirationTS = t.Seconds()+1440
  78. sav.SessionData = b
  79. err := c.Update(bson.M{"sessionid": id}, sav)
  80. if err != nil {
  81. if err == mgo.NotFound {
  82. err = c.Insert(&sessionRow{id, t.Seconds()+1440, b})
  83. if err != nil {
  84. panic(err)
  85. }
  86. } else {
  87. panic(err)
  88. }
  89. }
  90. }
  91. func (handler *MHandler) Clean() {
  92. c := handler.session.DB("bloody").C("sessions")
  93. t := time.LocalTime()
  94. err := c.RemoveAll(bson.M{"expirationts": bson.M{"$lt":t.Seconds()}})
  95. if err != nil {
  96. panic(err)
  97. }
  98. }
  99. func (handler *MHandler) Remove(id string) {
  100. c := handler.session.DB("bloody").C("sessions")
  101. err := c.Remove(bson.M{"sessionid": id})
  102. if err != nil {
  103. panic(err)
  104. }
  105. }
  106. func (handler *MHandler) Retrieve(id string) *sessionRow {
  107. var rt sessionRow
  108. c := handler.session.DB("bloody").C("sessions")
  109. err := c.Find(bson.M{"sessionid": id}).One(&rt)
  110. if err != nil {
  111. if err == mgo.NotFound {
  112. return &sessionRow{id,0,nil}
  113. }
  114. panic(err)
  115. }
  116. return &rt
  117. }
  118. func (handler *MHandler) SetSession(mSession *mgo.Session) {
  119. handler.session = mSession
  120. }