package sess import ( "encoding/json" "errors" "fmt" "git.clearsky.net.au/cody/gex.git/sess/jwt" "git.clearsky.net.au/cody/gex.git/srv" "git.clearsky.net.au/cody/gex.git/utils" "time" ) type Sess struct { req *srv.Req res *srv.Res Expires time.Time Data map[string]any } // config defaults var TOKENNAME string = "SessToken" var TIMEOUT time.Duration = 1 * time.Hour var SECRET string = "secret" func (sess *Sess) Construct(req *srv.Req, res *srv.Res) { sess.req = req sess.res = res sess.setDefaults() // check cookie is valid and not expired cookie, err := req.Cookie(TOKENNAME) if err != nil { //utils.Err(err) return } // decode jwt to json bytes jsonByt, err := jwt.Decode(cookie, SECRET) if err != nil { utils.Err(err) return } // decode json bytes to session err = json.Unmarshal(jsonByt, &sess) if err != nil { utils.Err(err) return } // if session token has expired, return default session if time.Now().After(sess.Expires) { if time.Now().After(sess.Expires.Add(TIMEOUT)) { sess.Expires = time.Now().Add(20 * time.Minute) return } fmt.Println("session expired") sess.setDefaults() } } func (sess *Sess) setDefaults() { sess.Data = make(map[string]any) sess.Expires = time.Now().Add(20 * time.Minute) } func (sess *Sess) Token() (string, error) { jsonStr, err := json.Marshal(sess) if err != nil { return "", err } // encode the json to jwt and set the cookie token, err := jwt.Encode(jsonStr, SECRET) if err != nil { return "", err } return token, nil } // Saves token to cookie func (sess *Sess) Save() { // get the session token token, err := sess.Token() if err != nil { sess.res.Send(err.Error()) return } // set the token cookie sess.res.Cookie(TOKENNAME, token) } func GetCtxSess(req *srv.Req) (*Sess, error) { if req.Ctx["Sess"] == nil { err := errors.New("no session context, did you add the session middleware?") utils.Err(err) return nil, err } sess, ok := req.Ctx["Sess"].(*Sess) if !ok { err := errors.New("session from context is not of type *Sess") utils.Err(err) return nil, err } return sess, nil }