Puberty commit

This commit is contained in:
2017-10-29 23:06:41 +01:00
commit 34034b5223
63 changed files with 16011 additions and 0 deletions
+50
View File
@@ -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
}
+60
View File
@@ -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)
}
+52
View File
@@ -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()
}