storage: add a password resource
This commit is contained in:
		| @@ -16,12 +16,12 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// stubbed out for testing | ||||
| 	now = time.Now | ||||
| ) | ||||
| 	// ErrNotFound is the error returned by storages if a resource cannot be found. | ||||
| 	ErrNotFound = errors.New("not found") | ||||
|  | ||||
| // ErrNotFound is the error returned by storages if a resource cannot be found. | ||||
| var ErrNotFound = errors.New("not found") | ||||
| 	// ErrAlreadyExists is the error returned by storages if a resource ID is taken during a create. | ||||
| 	ErrAlreadyExists = errors.New("ID already exists") | ||||
| ) | ||||
|  | ||||
| // Kubernetes only allows lower case letters for names. | ||||
| // | ||||
| @@ -51,6 +51,7 @@ type Storage interface { | ||||
| 	CreateClient(c Client) error | ||||
| 	CreateAuthCode(c AuthCode) error | ||||
| 	CreateRefresh(r RefreshToken) error | ||||
| 	CreatePassword(p Password) error | ||||
|  | ||||
| 	// TODO(ericchiang): return (T, bool, error) so we can indicate not found | ||||
| 	// requests that way instead of using ErrNotFound. | ||||
| @@ -59,6 +60,7 @@ type Storage interface { | ||||
| 	GetClient(id string) (Client, error) | ||||
| 	GetKeys() (Keys, error) | ||||
| 	GetRefresh(id string) (RefreshToken, error) | ||||
| 	GetPassword(email string) (Password, error) | ||||
|  | ||||
| 	ListClients() ([]Client, error) | ||||
| 	ListRefreshTokens() ([]RefreshToken, error) | ||||
| @@ -68,6 +70,7 @@ type Storage interface { | ||||
| 	DeleteAuthCode(code string) error | ||||
| 	DeleteClient(id string) error | ||||
| 	DeleteRefresh(id string) error | ||||
| 	DeletePassword(email string) error | ||||
|  | ||||
| 	// Update functions are assumed to be a performed within a single object transaction. | ||||
| 	// | ||||
| @@ -75,6 +78,7 @@ type Storage interface { | ||||
| 	UpdateClient(id string, updater func(old Client) (Client, error)) error | ||||
| 	UpdateKeys(updater func(old Keys) (Keys, error)) error | ||||
| 	UpdateAuthRequest(id string, updater func(a AuthRequest) (AuthRequest, error)) error | ||||
| 	UpdatePassword(email string, updater func(p Password) (Password, error)) error | ||||
|  | ||||
| 	// TODO(ericchiang): Add a GarbageCollect(now time.Time) method so conformance tests | ||||
| 	// can test implementations. | ||||
| @@ -217,6 +221,28 @@ type RefreshToken struct { | ||||
| 	Nonce string | ||||
| } | ||||
|  | ||||
| // Password is an email to password mapping managed by the storage. | ||||
| type Password struct { | ||||
| 	// Email and identifying name of the password. Emails are assumed to be valid and | ||||
| 	// determining that an end-user controls the address is left to an outside application. | ||||
| 	// | ||||
| 	// Emails are case insensitive and should be standardized by the storage. | ||||
| 	// | ||||
| 	// Storages that don't support an extended character set for IDs, such as '.' and '@' | ||||
| 	// (cough cough, kubernetes), must map this value appropriately. | ||||
| 	Email string `yaml:"email"` | ||||
|  | ||||
| 	// Bcrypt encoded hash of the password. This package recommends a cost value of at | ||||
| 	// least 14. | ||||
| 	Hash []byte `yaml:"hash"` | ||||
|  | ||||
| 	// Optional username to display. NOT used during login. | ||||
| 	Username string `yaml:"username"` | ||||
|  | ||||
| 	// Randomly generated user ID. This is NOT the primary ID of the Password object. | ||||
| 	UserID string `yaml:"userID"` | ||||
| } | ||||
|  | ||||
| // VerificationKey is a rotated signing key which can still be used to verify | ||||
| // signatures. | ||||
| type VerificationKey struct { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user