auth/internal/token/repository/bolt/bolt_token.go

86 lines
1.8 KiB
Go

package bolt
import (
"context"
"time"
"github.com/pkg/errors"
bolt "go.etcd.io/bbolt"
"golang.org/x/xerrors"
"source.toby3d.me/website/oauth/internal/domain"
"source.toby3d.me/website/oauth/internal/token"
)
type boltTokenRepository struct {
db *bolt.DB
}
var ErrNotExist error = errors.New("token not exist")
var DefaultBucket []byte = []byte("tokens")
func NewBoltTokenRepository(db *bolt.DB) token.Repository {
return &boltTokenRepository{
db: db,
}
}
func (repo *boltTokenRepository) Create(ctx context.Context, accessToken *domain.Token) error {
find, err := repo.Get(ctx, accessToken.AccessToken)
if err != nil {
return errors.Wrap(err, "cannot check token in database")
}
if find != nil {
return token.ErrExist
}
if err = repo.db.Update(func(tx *bolt.Tx) error {
bkt, err := tx.CreateBucketIfNotExists(DefaultBucket)
if err != nil {
return errors.Wrap(err, "cannot create bucket")
}
return bkt.Put([]byte(accessToken.AccessToken), []byte(accessToken.Expiry.Format(time.RFC3339)))
}); err != nil {
return errors.Wrap(err, "failed to batch token in database")
}
return nil
}
func (repo *boltTokenRepository) Get(ctx context.Context, accessToken string) (*domain.Token, error) {
result := &domain.Token{
AccessToken: accessToken,
TokenType: "Bearer",
Expiry: time.Time{},
}
if err := repo.db.View(func(tx *bolt.Tx) (err error) {
bkt := tx.Bucket(DefaultBucket)
if bkt == nil {
return ErrNotExist
}
expiry := bkt.Get([]byte(accessToken))
if expiry == nil {
return ErrNotExist
}
if result.Expiry, err = time.Parse(time.RFC3339, string(expiry)); err != nil {
return err
}
return nil
}); err != nil {
if xerrors.Is(err, ErrNotExist) {
return nil, nil
}
return nil, errors.Wrap(err, "failed to view token in database")
}
return result, nil
}