2021-02-25 18:24:24 +00:00
|
|
|
package nosql
|
|
|
|
|
|
|
|
import (
|
2021-02-28 01:05:37 +00:00
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2021-02-25 18:24:24 +00:00
|
|
|
nosqlDB "github.com/smallstep/nosql"
|
|
|
|
)
|
|
|
|
|
2021-02-28 01:05:37 +00:00
|
|
|
var (
|
|
|
|
accountTable = []byte("acme_accounts")
|
|
|
|
accountByKeyIDTable = []byte("acme_keyID_accountID_index")
|
|
|
|
authzTable = []byte("acme_authzs")
|
|
|
|
challengeTable = []byte("acme_challenges")
|
|
|
|
nonceTable = []byte("nonces")
|
|
|
|
orderTable = []byte("acme_orders")
|
|
|
|
ordersByAccountIDTable = []byte("acme_account_orders_index")
|
|
|
|
certTable = []byte("acme_certs")
|
|
|
|
)
|
|
|
|
|
2021-02-25 18:24:24 +00:00
|
|
|
// DB is a struct that implements the AcmeDB interface.
|
|
|
|
type DB struct {
|
|
|
|
db nosqlDB.DB
|
|
|
|
}
|
2021-02-28 01:05:37 +00:00
|
|
|
|
|
|
|
// save writes the new data to the database, overwriting the old data if it
|
|
|
|
// existed.
|
|
|
|
func (db *DB) save(ctx context.Context, id string, nu interface{}, old interface{}, typ string, table []byte) error {
|
|
|
|
newB, err := json.Marshal(nu)
|
|
|
|
if err != nil {
|
|
|
|
return ServerInternalErr(errors.Wrapf(err,
|
|
|
|
"error marshaling new acme %s", typ))
|
|
|
|
}
|
|
|
|
var oldB []byte
|
|
|
|
if old == nil {
|
|
|
|
oldB = nil
|
|
|
|
} else {
|
|
|
|
oldB, err = json.Marshal(old)
|
|
|
|
if err != nil {
|
|
|
|
return ServerInternalErr(errors.Wrapf(err,
|
|
|
|
"error marshaling old acme %s", typ))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, swapped, err := db.CmpAndSwap(table, []byte(id), oldB, newB)
|
|
|
|
switch {
|
|
|
|
case err != nil:
|
|
|
|
return ServerInternalErr(errors.Wrapf(err, "error saving acme %s", typ))
|
|
|
|
case !swapped:
|
|
|
|
return ServerInternalErr(errors.Errorf("error saving acme %s; "+
|
|
|
|
"changed since last read", typ))
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|