1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-01-10 04:17:59 +02:00
authboss/context.go
Aaron L 37ace55579 Clean up context and client state
- Remove extraneous http.ResponseWriter from all read-only queries
  against the request context (for the ClientState)
- Instead of using a context.Context on the ClientStateResponseWriter
  just store variables for the things we'd like to store, it should be
  less expensive and it's much easier to work with and more clear.
- Save the loaded client state into both the ResponseWriter itself and
  the Request context, the ResponseWriter will store them simply to send
  them into the WriteState() method later on, the Request will store
  them to be able to query data.
2018-03-07 16:21:37 -08:00

163 lines
4.0 KiB
Go

package authboss
import (
"context"
"net/http"
)
type contextKey string
// CTX Keys for authboss
const (
CTXKeyPID contextKey = "pid"
CTXKeyUser contextKey = "user"
CTXKeySessionState contextKey = "session"
CTXKeyCookieState contextKey = "cookie"
// CTXKeyData is a context key for the accumulating
// map[string]interface{} (authboss.HTMLData) to pass to the
// renderer
CTXKeyData contextKey = "data"
// CTXKeyValues is to pass the data submitted from API request or form
// along in the context in case modules need it. The only module that needs
// user information currently is remember so only auth/oauth2 are currently
// going to use this.
CTXKeyValues contextKey = "values"
)
func (c contextKey) String() string {
return "authboss ctx key " + string(c)
}
// CurrentUserID retrieves the current user from the session.
func (a *Authboss) CurrentUserID(r *http.Request) (string, error) {
if pid := r.Context().Value(CTXKeyPID); pid != nil {
return pid.(string), nil
}
pid, _ := GetSession(r, SessionKey)
return pid, nil
}
// CurrentUserIDP retrieves the current user but panics if it's not available for
// any reason.
func (a *Authboss) CurrentUserIDP(r *http.Request) string {
i, err := a.CurrentUserID(r)
if err != nil {
panic(err)
} else if len(i) == 0 {
panic(ErrUserNotFound)
}
return i
}
// CurrentUser retrieves the current user from the session and the database.
// Before the user is loaded from the database the context key is checked.
// If the session doesn't have the user ID ErrUserNotFound will be returned.
func (a *Authboss) CurrentUser(r *http.Request) (User, error) {
if user := r.Context().Value(CTXKeyUser); user != nil {
return user.(User), nil
}
pid, err := a.CurrentUserID(r)
if err != nil {
return nil, err
} else if len(pid) == 0 {
return nil, ErrUserNotFound
}
return a.currentUser(r.Context(), pid)
}
// CurrentUserP retrieves the current user but panics if it's not available for
// any reason.
func (a *Authboss) CurrentUserP(r *http.Request) User {
i, err := a.CurrentUser(r)
if err != nil {
panic(err)
} else if i == nil {
panic(ErrUserNotFound)
}
return i
}
func (a *Authboss) currentUser(ctx context.Context, pid string) (User, error) {
return a.Storage.Server.Load(ctx, pid)
}
// LoadCurrentUserID takes a pointer to a pointer to the request in order to
// change the current method's request pointer itself to the new request that
// contains the new context that has the pid in it.
func (a *Authboss) LoadCurrentUserID(r **http.Request) (string, error) {
pid, err := a.CurrentUserID(*r)
if err != nil {
return "", err
}
if len(pid) == 0 {
return "", nil
}
ctx := context.WithValue((**r).Context(), CTXKeyPID, pid)
*r = (**r).WithContext(ctx)
return pid, nil
}
// LoadCurrentUserIDP loads the current user id and panics if it's not found
func (a *Authboss) LoadCurrentUserIDP(r **http.Request) string {
pid, err := a.LoadCurrentUserID(r)
if err != nil {
panic(err)
} else if len(pid) == 0 {
panic(ErrUserNotFound)
}
return pid
}
// LoadCurrentUser takes a pointer to a pointer to the request in order to
// change the current method's request pointer itself to the new request that
// contains the new context that has the user in it. Calls LoadCurrentUserID
// so the primary id is also put in the context.
func (a *Authboss) LoadCurrentUser(r **http.Request) (User, error) {
if user := (*r).Context().Value(CTXKeyUser); user != nil {
return user.(User), nil
}
pid, err := a.LoadCurrentUserID(r)
if err != nil {
return nil, err
}
if len(pid) == 0 {
return nil, nil
}
ctx := (**r).Context()
user, err := a.currentUser(ctx, pid)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, CTXKeyUser, user)
*r = (**r).WithContext(ctx)
return user, nil
}
// LoadCurrentUserP does the same as LoadCurrentUser but panics if
// the current user is not found.
func (a *Authboss) LoadCurrentUserP(r **http.Request) User {
user, err := a.LoadCurrentUser(r)
if err != nil {
panic(err)
} else if user == nil {
panic(ErrUserNotFound)
}
return user
}