Puberty commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/localhots/cmdui/backend/db"
|
||||
)
|
||||
|
||||
type ctxKey string
|
||||
|
||||
const (
|
||||
ctxSessionKey ctxKey = "session"
|
||||
ctxUserKey ctxKey = "user"
|
||||
)
|
||||
|
||||
func ContextWithSession(ctx context.Context, sess db.Session) context.Context {
|
||||
return context.WithValue(ctx, ctxSessionKey, sess)
|
||||
}
|
||||
|
||||
func SessionFromContext(ctx context.Context) (sess db.Session, ok bool) {
|
||||
v := ctx.Value(ctxSessionKey)
|
||||
if v == nil {
|
||||
return db.Session{}, false
|
||||
}
|
||||
|
||||
return v.(db.Session), true
|
||||
}
|
||||
|
||||
func Session(ctx context.Context) db.Session {
|
||||
sess, _ := SessionFromContext(ctx)
|
||||
return sess
|
||||
}
|
||||
|
||||
func ContextWithUser(ctx context.Context, u db.User) context.Context {
|
||||
return context.WithValue(ctx, ctxUserKey, u)
|
||||
}
|
||||
|
||||
func UserFromContext(ctx context.Context) (u db.User, ok bool) {
|
||||
v := ctx.Value(ctxUserKey)
|
||||
if v == nil {
|
||||
return db.User{}, false
|
||||
}
|
||||
|
||||
return v.(db.User), true
|
||||
}
|
||||
|
||||
func User(ctx context.Context) db.User {
|
||||
u, _ := UserFromContext(ctx)
|
||||
return u
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/juju/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
sessionCookieName = "cmdui_session_id"
|
||||
)
|
||||
|
||||
func AuthenticateRequest(w http.ResponseWriter, r *http.Request) (context.Context, error) {
|
||||
cook, err := r.Cookie(sessionCookieName)
|
||||
if err != nil {
|
||||
return r.Context(), errors.Annotate(err, "Failed to get cookie value")
|
||||
}
|
||||
sess, err := FindSession(cook.Value)
|
||||
if err != nil {
|
||||
return r.Context(), errors.Annotate(err, "Failed to authenticate request")
|
||||
}
|
||||
ctx := ContextWithSession(r.Context(), sess)
|
||||
if sess.ExpiresAt.Before(time.Now()) {
|
||||
ClearCookie(ctx, w)
|
||||
return ctx, errors.New("Session expired")
|
||||
}
|
||||
|
||||
u, err := sess.User()
|
||||
if err != nil {
|
||||
return ctx, errors.Annotatef(err, "Failed to find user %d", sess.UserID)
|
||||
}
|
||||
if u == nil {
|
||||
return ctx, errors.UserNotFoundf("User %s was not found", sess.UserID)
|
||||
}
|
||||
u.Authorized = true
|
||||
|
||||
ctx = ContextWithUser(ctx, *u)
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func AuthorizeResponse(ctx context.Context, w http.ResponseWriter) {
|
||||
if sess, ok := SessionFromContext(ctx); ok {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: sessionCookieName,
|
||||
Value: sess.ID,
|
||||
Path: "/",
|
||||
Expires: sess.ExpiresAt,
|
||||
HttpOnly: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ClearCookie(ctx context.Context, w http.ResponseWriter) {
|
||||
sess := Session(ctx)
|
||||
sess.ExpiresAt = time.Time{}
|
||||
ctx = ContextWithSession(ctx, sess)
|
||||
AuthorizeResponse(ctx, w)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/localhots/cmdui/backend/db"
|
||||
)
|
||||
|
||||
var (
|
||||
sessionCacheMux sync.Mutex
|
||||
sessionCache = map[string]db.Session{}
|
||||
errSessionNotFound = errors.New("Session not found")
|
||||
)
|
||||
|
||||
func FindSession(id string) (db.Session, error) {
|
||||
if id == "" {
|
||||
return db.Session{}, errSessionNotFound
|
||||
}
|
||||
|
||||
sessionCacheMux.Lock()
|
||||
sessc, ok := sessionCache[id]
|
||||
sessionCacheMux.Unlock()
|
||||
if ok {
|
||||
return sessc, nil
|
||||
}
|
||||
|
||||
sess, err := db.FindSession(id)
|
||||
if err != nil {
|
||||
return db.Session{}, errors.Annotate(err, "Session lookup failed")
|
||||
}
|
||||
if sess == nil {
|
||||
return db.Session{}, errSessionNotFound
|
||||
}
|
||||
|
||||
sessionCacheMux.Lock()
|
||||
sessionCache[sess.ID] = *sess
|
||||
sessionCacheMux.Unlock()
|
||||
|
||||
return *sess, nil
|
||||
}
|
||||
|
||||
func CacheSession(sess db.Session) {
|
||||
if sess.ID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
sessionCacheMux.Lock()
|
||||
sessionCache[sess.ID] = sess
|
||||
sessionCacheMux.Unlock()
|
||||
}
|
||||
Reference in New Issue
Block a user