2017-02-24 02:13:25 +02:00
|
|
|
package authboss
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
type contextKey string
|
|
|
|
|
2018-02-15 00:18:03 +02:00
|
|
|
// CTX Keys for authboss
|
2017-02-24 02:13:25 +02:00
|
|
|
const (
|
2018-02-15 00:18:03 +02:00
|
|
|
CTXKeyPID contextKey = "pid"
|
|
|
|
CTXKeyUser contextKey = "user"
|
2017-02-25 02:45:47 +02:00
|
|
|
|
2018-02-15 00:18:03 +02:00
|
|
|
CTXKeySessionState contextKey = "session"
|
|
|
|
CTXKeyCookieState contextKey = "cookie"
|
2018-02-01 03:07:11 +02:00
|
|
|
|
|
|
|
// CTXKeyData is a context key for the accumulating
|
|
|
|
// map[string]interface{} (authboss.HTMLData) to pass to the
|
|
|
|
// renderer
|
|
|
|
CTXKeyData contextKey = "data"
|
2018-03-08 01:13:06 +02:00
|
|
|
|
2018-03-08 01:17:22 +02:00
|
|
|
// 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"
|
2017-02-24 02:13:25 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func (c contextKey) String() string {
|
|
|
|
return "authboss ctx key " + string(c)
|
|
|
|
}
|
|
|
|
|
|
|
|
// CurrentUserID retrieves the current user from the session.
|
|
|
|
func (a *Authboss) CurrentUserID(w http.ResponseWriter, r *http.Request) (string, error) {
|
2018-02-15 00:18:03 +02:00
|
|
|
if pid := r.Context().Value(CTXKeyPID); pid != nil {
|
2017-02-24 02:29:58 +02:00
|
|
|
return pid.(string), nil
|
|
|
|
}
|
|
|
|
|
2017-02-25 02:45:47 +02:00
|
|
|
pid, _ := GetSession(r, SessionKey)
|
2017-02-24 02:29:58 +02:00
|
|
|
return pid, nil
|
2017-02-24 02:13:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// CurrentUserIDP retrieves the current user but panics if it's not available for
|
|
|
|
// any reason.
|
|
|
|
func (a *Authboss) CurrentUserIDP(w http.ResponseWriter, r *http.Request) string {
|
|
|
|
i, err := a.CurrentUserID(w, 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.
|
2018-02-27 17:14:30 +02:00
|
|
|
// 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.
|
2018-02-01 03:07:11 +02:00
|
|
|
func (a *Authboss) CurrentUser(w http.ResponseWriter, r *http.Request) (User, error) {
|
2018-02-15 00:18:03 +02:00
|
|
|
if user := r.Context().Value(CTXKeyUser); user != nil {
|
2018-02-01 03:07:11 +02:00
|
|
|
return user.(User), nil
|
2017-02-24 02:29:58 +02:00
|
|
|
}
|
|
|
|
|
2017-02-24 02:13:25 +02:00
|
|
|
pid, err := a.CurrentUserID(w, r)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else if len(pid) == 0 {
|
2018-02-27 17:14:30 +02:00
|
|
|
return nil, ErrUserNotFound
|
2017-02-24 02:13:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return a.currentUser(r.Context(), pid)
|
|
|
|
}
|
|
|
|
|
|
|
|
// CurrentUserP retrieves the current user but panics if it's not available for
|
|
|
|
// any reason.
|
2018-02-01 03:07:11 +02:00
|
|
|
func (a *Authboss) CurrentUserP(w http.ResponseWriter, r *http.Request) User {
|
2017-02-24 02:13:25 +02:00
|
|
|
i, err := a.CurrentUser(w, r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2017-03-05 20:01:46 +02:00
|
|
|
} else if i == nil {
|
2018-01-30 02:24:42 +02:00
|
|
|
panic(ErrUserNotFound)
|
2017-02-24 02:13:25 +02:00
|
|
|
}
|
|
|
|
return i
|
|
|
|
}
|
|
|
|
|
2018-02-01 03:07:11 +02:00
|
|
|
func (a *Authboss) currentUser(ctx context.Context, pid string) (User, error) {
|
2018-03-08 01:13:06 +02:00
|
|
|
return a.Storage.Server.Load(ctx, pid)
|
2017-02-24 02:13:25 +02:00
|
|
|
}
|
|
|
|
|
2018-02-01 03:07:11 +02:00
|
|
|
// LoadCurrentUserID takes a pointer to a pointer to the request in order to
|
2017-02-24 02:13:25 +02:00
|
|
|
// 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(w http.ResponseWriter, r **http.Request) (string, error) {
|
2018-02-15 00:18:03 +02:00
|
|
|
if pid := (*r).Context().Value(CTXKeyPID); pid != nil {
|
2017-02-24 02:29:58 +02:00
|
|
|
return pid.(string), nil
|
|
|
|
}
|
|
|
|
|
2017-02-24 02:13:25 +02:00
|
|
|
pid, err := a.CurrentUserID(w, *r)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pid) == 0 {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
2018-02-15 00:18:03 +02:00
|
|
|
ctx := context.WithValue((**r).Context(), CTXKeyPID, pid)
|
2017-02-24 02:13:25 +02:00
|
|
|
*r = (**r).WithContext(ctx)
|
|
|
|
|
|
|
|
return pid, nil
|
|
|
|
}
|
|
|
|
|
2018-02-01 03:07:11 +02:00
|
|
|
// LoadCurrentUserIDP loads the current user id and panics if it's not found
|
2017-02-24 02:13:25 +02:00
|
|
|
func (a *Authboss) LoadCurrentUserIDP(w http.ResponseWriter, r **http.Request) string {
|
|
|
|
pid, err := a.LoadCurrentUserID(w, 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.
|
2018-02-01 03:07:11 +02:00
|
|
|
func (a *Authboss) LoadCurrentUser(w http.ResponseWriter, r **http.Request) (User, error) {
|
2018-02-15 00:18:03 +02:00
|
|
|
if user := (*r).Context().Value(CTXKeyUser); user != nil {
|
2018-02-01 03:07:11 +02:00
|
|
|
return user.(User), nil
|
2017-02-24 02:29:58 +02:00
|
|
|
}
|
|
|
|
|
2017-02-24 02:13:25 +02:00
|
|
|
pid, err := a.LoadCurrentUserID(w, 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
|
|
|
|
}
|
|
|
|
|
2018-02-15 00:18:03 +02:00
|
|
|
ctx = context.WithValue(ctx, CTXKeyUser, user)
|
2017-02-24 02:13:25 +02:00
|
|
|
*r = (**r).WithContext(ctx)
|
|
|
|
return user, nil
|
|
|
|
}
|
|
|
|
|
2018-02-01 03:07:11 +02:00
|
|
|
// LoadCurrentUserP does the same as LoadCurrentUser but panics if
|
|
|
|
// the current user is not found.
|
|
|
|
func (a *Authboss) LoadCurrentUserP(w http.ResponseWriter, r **http.Request) User {
|
2017-02-24 02:13:25 +02:00
|
|
|
user, err := a.LoadCurrentUser(w, r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
} else if user == nil {
|
|
|
|
panic(ErrUserNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return user
|
|
|
|
}
|