84 lines
1.8 KiB
Go
84 lines
1.8 KiB
Go
package source
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/oklog/ulid/v2"
|
|
"go.sour.is/pkg/ident"
|
|
"go.sour.is/pkg/lg"
|
|
"go.sour.is/pkg/locker"
|
|
)
|
|
|
|
const CookieName = "sour.is-ident"
|
|
|
|
type sessions map[ulid.ULID]ident.Ident
|
|
|
|
type session struct {
|
|
cookieName string
|
|
sessions *locker.Locked[sessions]
|
|
}
|
|
|
|
func NewSession(cookieName string) *session {
|
|
return &session{
|
|
cookieName: cookieName,
|
|
sessions: locker.New(make(sessions)),
|
|
}
|
|
}
|
|
|
|
func (s *session) ReadIdent(r *http.Request) (ident.Ident, error) {
|
|
ctx, span := lg.Span(r.Context())
|
|
defer span.End()
|
|
|
|
cookie, err := r.Cookie(s.cookieName)
|
|
span.RecordError(err)
|
|
if err != nil {
|
|
return nil, nil
|
|
}
|
|
|
|
sessionID, err := ulid.Parse(cookie.Value)
|
|
span.RecordError(err)
|
|
|
|
var id ident.Ident = ident.Anonymous
|
|
if err == nil {
|
|
err = s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
|
if session, ok := sessions[sessionID]; ok {
|
|
id = session
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
span.RecordError(err)
|
|
|
|
return id, err
|
|
}
|
|
|
|
func (s *session) CreateSession(ctx context.Context, w http.ResponseWriter, id ident.Ident) error {
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: s.cookieName,
|
|
Value: id.Session().SessionID.String(),
|
|
Expires: time.Time{},
|
|
Path: "/",
|
|
Secure: false,
|
|
HttpOnly: true,
|
|
})
|
|
|
|
return s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
|
sessions[id.Session().SessionID] = id
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *session) DestroySession(ctx context.Context, w http.ResponseWriter, id ident.Ident) error {
|
|
session := id.Session()
|
|
session.Active = false
|
|
|
|
http.SetCookie(w, &http.Cookie{Name: s.cookieName, MaxAge: -1})
|
|
|
|
return s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
|
delete(sessions, session.SessionID)
|
|
return nil
|
|
})
|
|
}
|