github.com/volatiletech/authboss@v2.4.1+incompatible/context.go (about)

     1  package authboss
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  )
     7  
     8  type contextKey string
     9  
    10  // CTX Keys for authboss
    11  const (
    12  	CTXKeyPID  contextKey = "pid"
    13  	CTXKeyUser contextKey = "user"
    14  
    15  	CTXKeySessionState contextKey = "session"
    16  	CTXKeyCookieState  contextKey = "cookie"
    17  
    18  	// CTXKeyData is a context key for the accumulating
    19  	// map[string]interface{} (authboss.HTMLData) to pass to the
    20  	// renderer
    21  	CTXKeyData contextKey = "data"
    22  
    23  	// CTXKeyValues is to pass the data submitted from API request or form
    24  	// along in the context in case modules need it. The only module that needs
    25  	// user information currently is remember so only auth/oauth2 are currently
    26  	// going to use this.
    27  	CTXKeyValues contextKey = "values"
    28  )
    29  
    30  func (c contextKey) String() string {
    31  	return "authboss ctx key " + string(c)
    32  }
    33  
    34  // CurrentUserID retrieves the current user from the session.
    35  // TODO(aarondl): This method never returns an error, one day we'll change
    36  // the function signature.
    37  func (a *Authboss) CurrentUserID(r *http.Request) (string, error) {
    38  	if pid := r.Context().Value(CTXKeyPID); pid != nil {
    39  		return pid.(string), nil
    40  	}
    41  
    42  	pid, _ := GetSession(r, SessionKey)
    43  	return pid, nil
    44  }
    45  
    46  // CurrentUserIDP retrieves the current user but panics if it's not available for
    47  // any reason.
    48  func (a *Authboss) CurrentUserIDP(r *http.Request) string {
    49  	i, err := a.CurrentUserID(r)
    50  	if err != nil {
    51  		panic(err)
    52  	} else if len(i) == 0 {
    53  		panic(ErrUserNotFound)
    54  	}
    55  
    56  	return i
    57  }
    58  
    59  // CurrentUser retrieves the current user from the session and the database.
    60  // Before the user is loaded from the database the context key is checked.
    61  // If the session doesn't have the user ID ErrUserNotFound will be returned.
    62  func (a *Authboss) CurrentUser(r *http.Request) (User, error) {
    63  	if user := r.Context().Value(CTXKeyUser); user != nil {
    64  		return user.(User), nil
    65  	}
    66  
    67  	pid, err := a.CurrentUserID(r)
    68  	if err != nil {
    69  		return nil, err
    70  	} else if len(pid) == 0 {
    71  		return nil, ErrUserNotFound
    72  	}
    73  
    74  	return a.currentUser(r.Context(), pid)
    75  }
    76  
    77  // CurrentUserP retrieves the current user but panics if it's not available for
    78  // any reason.
    79  func (a *Authboss) CurrentUserP(r *http.Request) User {
    80  	i, err := a.CurrentUser(r)
    81  	if err != nil {
    82  		panic(err)
    83  	} else if i == nil {
    84  		panic(ErrUserNotFound)
    85  	}
    86  	return i
    87  }
    88  
    89  func (a *Authboss) currentUser(ctx context.Context, pid string) (User, error) {
    90  	return a.Storage.Server.Load(ctx, pid)
    91  }
    92  
    93  // LoadCurrentUserID takes a pointer to a pointer to the request in order to
    94  // change the current method's request pointer itself to the new request that
    95  // contains the new context that has the pid in it.
    96  func (a *Authboss) LoadCurrentUserID(r **http.Request) (string, error) {
    97  	pid, err := a.CurrentUserID(*r)
    98  	if err != nil {
    99  		return "", err
   100  	}
   101  
   102  	if len(pid) == 0 {
   103  		return "", nil
   104  	}
   105  
   106  	ctx := context.WithValue((**r).Context(), CTXKeyPID, pid)
   107  	*r = (**r).WithContext(ctx)
   108  
   109  	return pid, nil
   110  }
   111  
   112  // LoadCurrentUserIDP loads the current user id and panics if it's not found
   113  func (a *Authboss) LoadCurrentUserIDP(r **http.Request) string {
   114  	pid, err := a.LoadCurrentUserID(r)
   115  	if err != nil {
   116  		panic(err)
   117  	} else if len(pid) == 0 {
   118  		panic(ErrUserNotFound)
   119  	}
   120  
   121  	return pid
   122  }
   123  
   124  // LoadCurrentUser takes a pointer to a pointer to the request in order to
   125  // change the current method's request pointer itself to the new request that
   126  // contains the new context that has the user in it. Calls LoadCurrentUserID
   127  // so the primary id is also put in the context.
   128  func (a *Authboss) LoadCurrentUser(r **http.Request) (User, error) {
   129  	if user := (*r).Context().Value(CTXKeyUser); user != nil {
   130  		return user.(User), nil
   131  	}
   132  
   133  	pid, err := a.LoadCurrentUserID(r)
   134  	if err != nil {
   135  		return nil, err
   136  	} else if len(pid) == 0 {
   137  		return nil, ErrUserNotFound
   138  	}
   139  
   140  	ctx := (**r).Context()
   141  	user, err := a.currentUser(ctx, pid)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  
   146  	ctx = context.WithValue(ctx, CTXKeyUser, user)
   147  	*r = (**r).WithContext(ctx)
   148  	return user, nil
   149  }
   150  
   151  // LoadCurrentUserP does the same as LoadCurrentUser but panics if
   152  // the current user is not found.
   153  func (a *Authboss) LoadCurrentUserP(r **http.Request) User {
   154  	user, err := a.LoadCurrentUser(r)
   155  	if err != nil {
   156  		panic(err)
   157  	} else if user == nil {
   158  		panic(ErrUserNotFound)
   159  	}
   160  
   161  	return user
   162  }