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

     1  package authboss
     2  
     3  // A concious decision was made to put all storer
     4  // and user types into this file despite them truly
     5  // belonging to outside modules. The reason for this
     6  // is because documentation-wise, it was previously
     7  // difficult to find what you had to implement or even
     8  // what you could implement.
     9  
    10  import (
    11  	"context"
    12  
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  var (
    17  	// ErrUserFound should be returned from Create (see ConfirmUser)
    18  	// when the primaryID of the record is found.
    19  	ErrUserFound = errors.New("user found")
    20  	// ErrUserNotFound should be returned from Get when the record is not found.
    21  	ErrUserNotFound = errors.New("user not found")
    22  	// ErrTokenNotFound should be returned from UseToken when the
    23  	// record is not found.
    24  	ErrTokenNotFound = errors.New("token not found")
    25  )
    26  
    27  // ServerStorer represents the data store that's capable of loading users
    28  // and giving them a context with which to store themselves.
    29  type ServerStorer interface {
    30  	// Load will look up the user based on the passed the PrimaryID
    31  	Load(ctx context.Context, key string) (User, error)
    32  
    33  	// Save persists the user in the database, this should never
    34  	// create a user and instead return ErrUserNotFound if the user
    35  	// does not exist.
    36  	Save(ctx context.Context, user User) error
    37  }
    38  
    39  // CreatingServerStorer is used for creating new users
    40  // like when Registration or OAuth2 is being done.
    41  type CreatingServerStorer interface {
    42  	ServerStorer
    43  
    44  	// New creates a blank user, it is not yet persisted in the database
    45  	// but is just for storing data
    46  	New(ctx context.Context) User
    47  	// Create the user in storage, it should not overwrite a user
    48  	// and should return ErrUserFound if it currently exists.
    49  	Create(ctx context.Context, user User) error
    50  }
    51  
    52  // OAuth2ServerStorer has the ability to create users from data from the provider.
    53  type OAuth2ServerStorer interface {
    54  	ServerStorer
    55  
    56  	// NewFromOAuth2 should return an OAuth2User from a set
    57  	// of details returned from OAuth2Provider.FindUserDetails
    58  	// A more in-depth explanation is that once we've got an access token
    59  	// for the service in question (say a service that rhymes with book)
    60  	// the FindUserDetails function does an http request to a known endpoint
    61  	// that provides details about the user, those details are captured in a
    62  	// generic way as map[string]string and passed into this function to be
    63  	// turned into a real user.
    64  	//
    65  	// It's possible that the user exists in the database already, and so
    66  	// an attempt should be made to look that user up using the details.
    67  	// Any details that have changed should be updated. Do not save the user
    68  	// since that will be done later by OAuth2ServerStorer.SaveOAuth2()
    69  	NewFromOAuth2(ctx context.Context, provider string, details map[string]string) (OAuth2User, error)
    70  
    71  	// SaveOAuth2 has different semantics from the typical ServerStorer.Save,
    72  	// in this case we want to insert a user if they do not exist.
    73  	// The difference must be made clear because in the non-oauth2 case,
    74  	// we know exactly when we want to Create vs Update. However since we're
    75  	// simply trying to persist a user that may have been in our database,
    76  	// but if not should already be (since you can think of the operation as
    77  	// a caching of what's on the oauth2 provider's servers).
    78  	SaveOAuth2(ctx context.Context, user OAuth2User) error
    79  }
    80  
    81  // ConfirmingServerStorer can find a user by a confirm token
    82  type ConfirmingServerStorer interface {
    83  	ServerStorer
    84  
    85  	// LoadByConfirmSelector finds a user by his confirm selector field
    86  	// and should return ErrUserNotFound if that user cannot be found.
    87  	LoadByConfirmSelector(ctx context.Context, selector string) (ConfirmableUser, error)
    88  }
    89  
    90  // RecoveringServerStorer allows users to be recovered by a token
    91  type RecoveringServerStorer interface {
    92  	ServerStorer
    93  
    94  	// LoadByRecoverSelector finds a user by his recover selector field
    95  	// and should return ErrUserNotFound if that user cannot be found.
    96  	LoadByRecoverSelector(ctx context.Context, selector string) (RecoverableUser, error)
    97  }
    98  
    99  // RememberingServerStorer allows users to be remembered across sessions
   100  type RememberingServerStorer interface {
   101  	ServerStorer
   102  
   103  	// AddRememberToken to a user
   104  	AddRememberToken(ctx context.Context, pid, token string) error
   105  	// DelRememberTokens removes all tokens for the given pid
   106  	DelRememberTokens(ctx context.Context, pid string) error
   107  	// UseRememberToken finds the pid-token pair and deletes it.
   108  	// If the token could not be found return ErrTokenNotFound
   109  	UseRememberToken(ctx context.Context, pid, token string) error
   110  }
   111  
   112  // EnsureCanCreate makes sure the server storer supports create operations
   113  func EnsureCanCreate(storer ServerStorer) CreatingServerStorer {
   114  	s, ok := storer.(CreatingServerStorer)
   115  	if !ok {
   116  		panic("could not upgrade ServerStorer to CreatingServerStorer, check your struct")
   117  	}
   118  
   119  	return s
   120  }
   121  
   122  // EnsureCanConfirm makes sure the server storer supports
   123  // confirm-lookup operations
   124  func EnsureCanConfirm(storer ServerStorer) ConfirmingServerStorer {
   125  	s, ok := storer.(ConfirmingServerStorer)
   126  	if !ok {
   127  		panic("could not upgrade ServerStorer to ConfirmingServerStorer, check your struct")
   128  	}
   129  
   130  	return s
   131  }
   132  
   133  // EnsureCanRecover makes sure the server storer supports
   134  // confirm-lookup operations
   135  func EnsureCanRecover(storer ServerStorer) RecoveringServerStorer {
   136  	s, ok := storer.(RecoveringServerStorer)
   137  	if !ok {
   138  		panic("could not upgrade ServerStorer to RecoveringServerStorer, check your struct")
   139  	}
   140  
   141  	return s
   142  }
   143  
   144  // EnsureCanRemember makes sure the server storer supports remember operations
   145  func EnsureCanRemember(storer ServerStorer) RememberingServerStorer {
   146  	s, ok := storer.(RememberingServerStorer)
   147  	if !ok {
   148  		panic("could not upgrade ServerStorer to RememberingServerStorer, check your struct")
   149  	}
   150  
   151  	return s
   152  }
   153  
   154  // EnsureCanOAuth2 makes sure the server storer supports
   155  // oauth2 creation and lookup
   156  func EnsureCanOAuth2(storer ServerStorer) OAuth2ServerStorer {
   157  	s, ok := storer.(OAuth2ServerStorer)
   158  	if !ok {
   159  		panic("could not upgrade ServerStorer to OAuth2ServerStorer, check your struct")
   160  	}
   161  
   162  	return s
   163  }