diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-11-06 04:10:55 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-11-08 05:04:02 +0900 |
| commit | e0cc2915f22fe74d5be9e8f51d6b73437192e0ba (patch) | |
| tree | e2e27e3cba8b5e7205732eef7b6df9789e83396f /backend/auth/session.go | |
| parent | ba1e0c904f810193f25d4f88cc2bb168f1d625fe (diff) | |
| download | feedaka-e0cc2915f22fe74d5be9e8f51d6b73437192e0ba.tar.gz feedaka-e0cc2915f22fe74d5be9e8f51d6b73437192e0ba.tar.zst feedaka-e0cc2915f22fe74d5be9e8f51d6b73437192e0ba.zip | |
feat: Support multi-user
Diffstat (limited to 'backend/auth/session.go')
| -rw-r--r-- | backend/auth/session.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/backend/auth/session.go b/backend/auth/session.go new file mode 100644 index 0000000..f480bff --- /dev/null +++ b/backend/auth/session.go @@ -0,0 +1,94 @@ +package auth + +import ( + "errors" + "net/http" + "os" + + "github.com/gorilla/sessions" + "github.com/labstack/echo-contrib/session" + "github.com/labstack/echo/v4" +) + +const ( + sessionName = "feedaka_session" + sessionUserIDKey = "user_id" + // Session duration: 7 days + sessionMaxAge = 7 * 24 * 60 * 60 +) + +var ( + ErrNoSession = errors.New("no session found") + ErrNoUserIDInSession = errors.New("no user_id in session") + ErrNoSessionSecretEnvVar = errors.New("FEEDAKA_SESSION_SECRET environment variable is not set") +) + +type SessionConfig struct { + store *sessions.CookieStore +} + +func NewSessionConfig() (*SessionConfig, error) { + secret := os.Getenv("FEEDAKA_SESSION_SECRET") + if secret == "" { + return nil, ErrNoSessionSecretEnvVar + } + useNonSecureCookie := os.Getenv("FEEDAKA_DEV_NON_SECURE_COOKIE") == "1" + + store := sessions.NewCookieStore([]byte(secret)) + store.Options = &sessions.Options{ + Path: "/", + MaxAge: sessionMaxAge, + HttpOnly: true, + Secure: !useNonSecureCookie, + SameSite: http.SameSiteDefaultMode, + } + + return &SessionConfig{ + store: store, + }, nil +} + +func (c *SessionConfig) GetStore() *sessions.CookieStore { + return c.store +} + +func (c *SessionConfig) SetUserID(ctx echo.Context, userID int64) error { + sess, err := session.Get(sessionName, ctx) + if err != nil { + return err + } + + sess.Values[sessionUserIDKey] = userID + return sess.Save(ctx.Request(), ctx.Response()) +} + +func (c *SessionConfig) GetUserID(ctx echo.Context) (int64, error) { + sess, err := session.Get(sessionName, ctx) + if err != nil { + return 0, ErrNoSession + } + + userIDVal, ok := sess.Values[sessionUserIDKey] + if !ok { + return 0, ErrNoUserIDInSession + } + + userID, ok := userIDVal.(int64) + if !ok { + return 0, ErrNoUserIDInSession + } + + return userID, nil +} + +func (c *SessionConfig) DestroySession(ctx echo.Context) error { + sess, err := session.Get(sessionName, ctx) + if err != nil { + // If there's no session, nothing to destroy + return nil + } + + // Set MaxAge to -1 to delete the session + sess.Options.MaxAge = -1 + return sess.Save(ctx.Request(), ctx.Response()) +} |
