2015-01-03 22:03:57 +02:00
|
|
|
package authboss
|
|
|
|
|
|
|
|
import (
|
2015-01-19 00:35:44 +02:00
|
|
|
"bytes"
|
2017-02-21 00:28:38 +02:00
|
|
|
"context"
|
2015-01-03 22:03:57 +02:00
|
|
|
"reflect"
|
|
|
|
"time"
|
2017-02-22 01:04:30 +02:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2015-01-03 22:03:57 +02:00
|
|
|
)
|
|
|
|
|
2015-02-10 10:43:45 +02:00
|
|
|
// Data store constants for attribute names.
|
|
|
|
const (
|
2015-02-16 23:27:29 +02:00
|
|
|
StoreEmail = "email"
|
|
|
|
StoreUsername = "username"
|
|
|
|
StorePassword = "password"
|
2015-02-10 10:43:45 +02:00
|
|
|
)
|
|
|
|
|
2015-03-13 04:20:36 +02:00
|
|
|
// Data store constants for OAuth2 attribute names.
|
|
|
|
const (
|
2015-03-14 01:23:43 +02:00
|
|
|
StoreOAuth2UID = "oauth2_uid"
|
|
|
|
StoreOAuth2Provider = "oauth2_provider"
|
|
|
|
StoreOAuth2Token = "oauth2_token"
|
|
|
|
StoreOAuth2Refresh = "oauth2_refresh"
|
|
|
|
StoreOAuth2Expiry = "oauth2_expiry"
|
2015-03-13 04:20:36 +02:00
|
|
|
)
|
|
|
|
|
2015-01-24 01:56:24 +02:00
|
|
|
var (
|
2015-02-02 00:17:18 +02:00
|
|
|
// ErrUserNotFound should be returned from Get when the record is not found.
|
2017-02-22 01:04:30 +02:00
|
|
|
ErrUserNotFound = errors.New("user not found")
|
2015-02-02 00:17:18 +02:00
|
|
|
// ErrTokenNotFound should be returned from UseToken when the record is not found.
|
2017-02-22 01:04:30 +02:00
|
|
|
ErrTokenNotFound = errors.New("token not found")
|
2017-02-21 00:28:38 +02:00
|
|
|
// ErrUserFound should be returned from Create when the primaryID of the record is found.
|
2017-02-22 01:04:30 +02:00
|
|
|
ErrUserFound = errors.New("user found")
|
2015-01-24 01:56:24 +02:00
|
|
|
)
|
2015-01-11 08:52:39 +02:00
|
|
|
|
2017-02-21 00:28:38 +02:00
|
|
|
// StoreLoader represents the data store that's capable of loading users
|
|
|
|
// and giving them a context with which to store themselves.
|
|
|
|
type StoreLoader interface {
|
|
|
|
// Load will be passed the PrimaryID and return pre-loaded storer (meaning
|
|
|
|
// Storer.Load will not be called)
|
|
|
|
Load(ctx context.Context, key string) (Storer, error)
|
|
|
|
}
|
2015-01-11 08:52:39 +02:00
|
|
|
|
2017-02-21 00:28:38 +02:00
|
|
|
// Storer represents a user that also knows how to put himself into the db.
|
|
|
|
// It has functions for each piece of data it requires.
|
|
|
|
// Note that you should only persist data once Save() has been called.
|
2015-01-11 08:52:39 +02:00
|
|
|
type Storer interface {
|
2017-02-21 00:28:38 +02:00
|
|
|
PutEmail(ctx context.Context, email string) error
|
|
|
|
PutUsername(ctx context.Context, username string) error
|
|
|
|
PutPassword(ctx context.Context, password string) error
|
|
|
|
|
|
|
|
GetEmail(ctx context.Context) (email string, err error)
|
|
|
|
GetUsername(ctx context.Context) (username string, err error)
|
|
|
|
GetPassword(ctx context.Context) (password string, err error)
|
|
|
|
|
2017-02-21 02:08:19 +02:00
|
|
|
// Save the state.
|
2017-02-21 00:28:38 +02:00
|
|
|
Save(ctx context.Context) error
|
|
|
|
|
|
|
|
// Load the state based on the properties that have been given (typically
|
|
|
|
// an e-mail/username).
|
|
|
|
Load(ctx context.Context) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type ArbitraryStorer interface {
|
|
|
|
Storer
|
|
|
|
|
|
|
|
// PutArbitrary allows arbitrary fields defined by the authboss library
|
|
|
|
// consumer to add fields to the user registration piece.
|
2017-02-21 01:56:26 +02:00
|
|
|
PutArbitrary(ctx context.Context, arbitrary map[string]string) error
|
2017-02-21 00:28:38 +02:00
|
|
|
// GetArbitrary is used only to display the arbitrary data back to the user
|
|
|
|
// when the form is reset.
|
|
|
|
GetArbitrary(ctx context.Context) (arbitrary map[string]string, err error)
|
2015-01-11 08:52:39 +02:00
|
|
|
}
|
|
|
|
|
2017-02-21 00:28:38 +02:00
|
|
|
// OAuth2Storer allows reading and writing values
|
2015-03-14 01:23:43 +02:00
|
|
|
type OAuth2Storer interface {
|
2017-02-21 00:28:38 +02:00
|
|
|
Storer
|
|
|
|
|
|
|
|
PutUID(ctx context.Context, uid string) error
|
|
|
|
PutProvider(ctx context.Context, provider string) error
|
|
|
|
PutToken(ctx context.Context, token string) error
|
|
|
|
PutRefreshToken(ctx context.Context, refreshToken string) error
|
|
|
|
PutExpiry(ctx context.Context, expiry time.Duration) error
|
|
|
|
|
|
|
|
GetUID(ctx context.Context) (uid string, err error)
|
|
|
|
GetProvider(ctx context.Context) (provider string, err error)
|
|
|
|
GetToken(ctx context.Context) (token string, err error)
|
|
|
|
GetRefreshToken(ctx context.Context) (refreshToken string, err error)
|
|
|
|
GetExpiry(ctx context.Context) (expiry time.Duration, err error)
|
2015-03-14 01:23:43 +02:00
|
|
|
}
|
|
|
|
|
2015-01-03 22:03:57 +02:00
|
|
|
// DataType represents the various types that clients must be able to store.
|
|
|
|
type DataType int
|
|
|
|
|
2015-03-16 23:42:45 +02:00
|
|
|
// DataType constants
|
2015-01-03 22:03:57 +02:00
|
|
|
const (
|
|
|
|
Integer DataType = iota
|
|
|
|
String
|
2015-02-07 14:27:12 +02:00
|
|
|
Bool
|
2015-01-03 22:03:57 +02:00
|
|
|
DateTime
|
|
|
|
)
|
|
|
|
|
2015-03-04 08:34:37 +02:00
|
|
|
var (
|
|
|
|
dateTimeType = reflect.TypeOf(time.Time{})
|
|
|
|
)
|
2015-01-07 21:39:12 +02:00
|
|
|
|
2015-08-02 18:31:21 +02:00
|
|
|
// String returns a string for the DataType representation.
|
2015-01-03 22:03:57 +02:00
|
|
|
func (d DataType) String() string {
|
|
|
|
switch d {
|
|
|
|
case Integer:
|
|
|
|
return "Integer"
|
|
|
|
case String:
|
|
|
|
return "String"
|
2015-02-07 14:27:12 +02:00
|
|
|
case Bool:
|
|
|
|
return "Bool"
|
2015-01-03 22:03:57 +02:00
|
|
|
case DateTime:
|
|
|
|
return "DateTime"
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2015-01-19 00:35:44 +02:00
|
|
|
func camelToUnder(in string) string {
|
|
|
|
out := bytes.Buffer{}
|
|
|
|
for i := 0; i < len(in); i++ {
|
|
|
|
chr := in[i]
|
|
|
|
if chr >= 'A' && chr <= 'Z' {
|
|
|
|
if i > 0 {
|
|
|
|
out.WriteByte('_')
|
|
|
|
}
|
|
|
|
out.WriteByte(chr + 'a' - 'A')
|
|
|
|
} else {
|
|
|
|
out.WriteByte(chr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func underToCamel(in string) string {
|
|
|
|
out := bytes.Buffer{}
|
|
|
|
for i := 0; i < len(in); i++ {
|
|
|
|
chr := in[i]
|
|
|
|
|
|
|
|
if first := i == 0; first || chr == '_' {
|
|
|
|
if !first {
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
out.WriteByte(in[i] - 'a' + 'A')
|
|
|
|
} else {
|
|
|
|
out.WriteByte(chr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out.String()
|
|
|
|
}
|