package middleware // //import ( // "amuz.es/src/mercury/bootstrap" // "amuz.es/src/mercury/common" // "amuz.es/src/mercury/endpoint/middleware2/internal" // rmisc "amuz.es/src/mercury/endpoint/misc" // "amuz.es/src/mercury/service" // "amuz.es/src/mercury/service/models" // "amuz.es/src/go/logging" // "amuz.es/src/go/misc" // "amuz.es/src/mercury/util/mycrypt" // "amuz.es/src/go/eighty" // "bytes" // "encoding/base64" // "encoding/binary" // "github.com/pkg/errors" // "github.com/valyala/fasthttp" // "go.uber.org/multierr" // "strings" // "time" //) // //func SessionFunc( // box mycrypt.SecretBox, // sessionCookieName string, // sessionExpire time.Duration, // sessionSecure bool, // parentLogger logging.Logger, // userService service.UserService, //) (rmisc.SessionMiddleware, error) { // logger := parentLogger.Named("session") // if box == nil { // return nil, errors.New("secret box needed") // } // sessionKeyReader := readSessionKeyValue(box, sessionCookieName) // sessionKeyWriter := writeSessionKeyValue(box, sessionCookieName, sessionExpire, sessionSecure) // sessionSyncGenerator := syncSessioner(logger, // sessionKeyWriter, // sessionService.Update, // sessionService.Delete, // ) // var sessionImplPool internal.SessionImplPool // return func(next fasthttp.RequestHandler) fasthttp.RequestHandler { // return func(ctx *fasthttp.RequestCtx) { // sessionData := sessionImplPool.Acquire() // defer sessionImplPool.Release(sessionData) // var ( // token misc.UUID // userId *int // user models.User // data map[string]any // err error // ) // sessionData.FBox = box // token, err = sessionKeyReader(&ctx.Request) // if err != nil { // logger.Debug("cannot extract token, error:", err) // } else if token.IsZero() { // logger.Debug("session is empty") // } else if userId, data, err = sessionService.Get(token); err != nil { // logger.Debug("cannot find session data from redis token:", token, " error : ", err) // } else { // sessionData.FToken = token // sessionData.FData = data // } // // if userId == nil { // logger.Debug("user id is nil token:", token.ToHexString()) // } else if user, err = userService.GetUser(ctx, *userId); err != nil { // logger.Debug("cannot query user, Id:", userId, " error : ", err) // } else if user == nil { // logger.Debug("user not found, Id:", userId) // } else if user.Status() != common.UserStatusEnabled { // logger.Debug("disabled user, Id:", userId, " status:", user.Status()) // } else { // logger.Info("user : ", user) // sessionData.FUser = user // } // sessionData.FSyncer = sessionSyncGenerator(&ctx.Request, &ctx.Response, token) // ctx.SetUserValue(rmisc.SessionContextKey, sessionData) // next(ctx) // } // }, nil //} // //func readSessionKeyValue(box mycrypt.SecretBox, cookieName string) func(r *fasthttp.Request) (misc.UUID, error) { // return func(r *fasthttp.Request) (token misc.UUID, err error) { // defer func() { // if panicErr := recover(); panicErr != nil { // err = multierr.Append(err, panicErr.(error)) // } // }() // sessionCookieValue := r.Header.Cookie(cookieName) // if len(sessionCookieValue) == 0 { // err = errors.New("session is Empty") // return // } // decryptor, err := box.NewDecryptReader(base64.NewDecoder(base64.StdEncoding, bytes.NewReader(sessionCookieValue))) // if err != nil { // return // } else if err = binary.Read(decryptor, binary.LittleEndian, &token); err != nil { // return // } // return // } //} // //func writeSessionKeyValue( // box mycrypt.SecretBox, cookieName string, // expireDuration time.Duration, secure bool) func(*fasthttp.Response, []byte, misc.UUID) error { // cookieWriter := eighty.SetCookieValueFasthttp(cookieName, expireDuration, secure) // return func(w *fasthttp.Response, hostname []byte, token misc.UUID) (err error) { // defer func() { // if panicErr := recover(); panicErr != nil { // err = multierr.Append(err, panicErr.(error)) // } // }() // if token.IsZero() { // cookieWriter(w, hostname, "") // return // } // // var b strings.Builder // encryptor, err := box.NewEncryptWriter(base64.NewEncoder(base64.StdEncoding, &b)) // if err != nil { // return // } else if err = binary.Write(encryptor, binary.LittleEndian, token[:]); err != nil { // return // } // _ = encryptor.Close() // // cookieWriter(w, hostname, b.String()) // return // } //} // //func syncSessioner( // logger logging.Logger, // sessionKeyWriter func(*fasthttp.Response, []byte, misc.UUID) error, // sessionDataUpdater func(misc.UUID, *int, map[string]any) error, // sessionDataDeleter func(misc.UUID) error, //) func(*fasthttp.Request, *fasthttp.Response, misc.UUID) func(newdata internal.SessionImpl) error { // return func(r *fasthttp.Request, w *fasthttp.Response, oldToken misc.UUID) func(newdata internal.SessionImpl) error { // return func(newdata internal.SessionImpl) (err error) { // newToken := newdata.FToken // tokenNotChanged := oldToken.Equal(newToken) // if tokenNotChanged { // // do nothing // } else if internalError := sessionKeyWriter(w, r.Host(), newToken); internalError != nil { // logger.Debug("cannot generate cookie, error:", internalError) // err = errors.Wrap(internalError, "cannot generate cookie") // return // } // // if newToken.IsZero() { // if !tokenNotChanged { // deleteErr := sessionDataDeleter(oldToken) // logger.Debug("cannot delete session, error:", deleteErr) // } // } else if user := newdata.FUser; user == nil { // err = sessionDataUpdater(newToken, nil, newdata.FData) // } else { // userId := user.Id() // err = sessionDataUpdater(newToken, &userId, newdata.FData) // } // if err != nil { // logger.Debug("cannot save session data, error:", err) // err = errors.Wrap(err, "cannot save session data") // } // return // } // } //} // //func NewSessionMiddleware( // box rmisc.RouterSecretBox, // sessionConfig bootstrap.SessionConfig, // parentLogger rmisc.RouterLogger, // sessionService service.SessionService, // userService service.UserService) (rmisc.SessionMiddleware, error) { // return SessionFunc( // box, // sessionConfig.CookieName(), // sessionConfig.ExpireTTL(), // sessionConfig.Secure(), // parentLogger, // sessionService, // userService, // ) //}