storj/storagenode/apikey/apikeys.go

82 lines
1.8 KiB
Go
Raw Normal View History

// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package apikey
import (
"bytes"
"context"
"crypto/rand"
"encoding/base64"
"time"
"github.com/zeebo/errs"
)
// ErrNoSecret represents errors from the apikey database.
var ErrNoSecret = errs.Class("no apikey error")
// DB is interface for working with apikey tokens.
//
// architecture: Database
type DB interface {
// Store stores apikey token into db.
Store(ctx context.Context, secret APIKey) error
// Check checks if unique apikey exists in db by token.
Check(ctx context.Context, token Secret) error
// Revoke removes token from db.
Revoke(ctx context.Context, token Secret) error
}
// Secret stores token of storagenode APIkey.
type Secret [32]byte
// APIKey describing apikey model in the database.
type APIKey struct {
// Secret is PK of the table and keeps unique value sno apikey token
Secret Secret
CreatedAt time.Time `json:"createdAt"`
}
// NewSecretToken creates new apikey token.
func NewSecretToken() (Secret, error) {
var b [32]byte
_, err := rand.Read(b[:])
if err != nil {
return b, errs.New("error creating apikey token")
}
return b, nil
}
// String implements Stringer.
func (secret Secret) String() string {
return base64.URLEncoding.EncodeToString(secret[:])
}
// IsZero returns if the apikey token is not set.
func (secret Secret) IsZero() bool {
var zero Secret
// this doesn't need to be constant-time, because we're explicitly testing
// against a hardcoded, well-known value
return bytes.Equal(secret[:], zero[:])
}
// TokenSecretFromBase64 creates new apikey token from base64 string.
func TokenSecretFromBase64(s string) (Secret, error) {
var token Secret
b, err := base64.URLEncoding.DecodeString(s)
if err != nil {
return token, err
}
copy(token[:], b)
return token, nil
}