Skip to content

Commit

Permalink
move storage to a separate package
Browse files Browse the repository at this point in the history
Signed-off-by: p4u <[email protected]>
  • Loading branch information
p4u committed Jun 3, 2024
1 parent b1e022b commit 08d5712
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 19 deletions.
3 changes: 2 additions & 1 deletion faucet.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/vocdoni/vocfaucet/storage"
"go.vocdoni.io/dvote/api"
vfaucet "go.vocdoni.io/dvote/api/faucet"
"go.vocdoni.io/dvote/crypto/ethereum"
Expand All @@ -16,7 +17,7 @@ type faucet struct {
signer *ethereum.SignKeys
authTypes map[string]uint64
waitPeriod time.Duration
storage *storage
storage *storage.Storage
}

// prepareFaucetPackage prepares a faucet package, including the signature, for the given address.
Expand Down
16 changes: 8 additions & 8 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ func (f *faucet) authOpenHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext
if err != nil {
return err
}
if funded, t := f.storage.checkIsFundedUserID(addr.Bytes(), AuthTypeOpen); funded {
if funded, t := f.storage.CheckFundedUserWithWaitTime(addr.Bytes(), AuthTypeOpen); funded {
errReason := fmt.Sprintf("address %s already funded, wait until %s", addr.Hex(), t)
return ctx.Send(new(HandlerResponse).SetError(errReason).MustMarshall(), CodeErrFlood)
}
data, err := f.prepareFaucetPackage(addr, AuthTypeOpen)
if err != nil {
return err
}
if err := f.storage.addFundedUserID(addr.Bytes(), AuthTypeOpen); err != nil {
if err := f.storage.AddFundedUserWithWaitTime(addr.Bytes(), AuthTypeOpen); err != nil {
return err
}
return ctx.Send(new(HandlerResponse).Set(data).MustMarshall(), apirest.HTTPstatusOK)
Expand Down Expand Up @@ -123,7 +123,7 @@ func (f *faucet) authOAuthHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCont
if err != nil {
return err
}
if funded, t := f.storage.checkIsFundedUserID(addr.Bytes(), AuthTypeOauth); funded {
if funded, t := f.storage.CheckFundedUserWithWaitTime(addr.Bytes(), AuthTypeOauth); funded {
errReason := fmt.Sprintf("address %s already funded, wait until %s", addr.Hex(), t)
return ctx.Send(new(HandlerResponse).SetError(errReason).MustMarshall(), CodeErrFlood)
}
Expand Down Expand Up @@ -159,7 +159,7 @@ func (f *faucet) authOAuthHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCont
// Check if the oauth profile is already funded
fundedProfileField := profile[provider.UsernameField].(string)
fundedAuthType := "oauth_" + newRequest.Provider
if funded, t := f.storage.checkIsFundedUserID([]byte(fundedProfileField), fundedAuthType); funded {
if funded, t := f.storage.CheckFundedUserWithWaitTime([]byte(fundedProfileField), fundedAuthType); funded {
errReason := fmt.Sprintf("user %s already funded, wait until %s", fundedProfileField, t)
return ctx.Send(new(HandlerResponse).SetError(errReason).MustMarshall(), CodeErrFlood)
}
Expand All @@ -170,10 +170,10 @@ func (f *faucet) authOAuthHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCont
}

// Add address and profile to the funded list
if err := f.storage.addFundedUserID(addr.Bytes(), AuthTypeOauth); err != nil {
if err := f.storage.AddFundedUserWithWaitTime(addr.Bytes(), AuthTypeOauth); err != nil {
return err
}
if err := f.storage.addFundedUserID([]byte(fundedProfileField), fundedAuthType); err != nil {
if err := f.storage.AddFundedUserWithWaitTime([]byte(fundedProfileField), fundedAuthType); err != nil {
return err
}

Expand Down Expand Up @@ -234,7 +234,7 @@ func (f *faucet) authAragonDaoHandler(msg *apirest.APIdata, ctx *httprouter.HTTP
}

// Check if the address is already funded
if funded, t := f.storage.checkIsFundedUserID(addr.Bytes(), AuthTypeAragonDao); funded {
if funded, t := f.storage.CheckFundedUserWithWaitTime(addr.Bytes(), AuthTypeAragonDao); funded {
errReason := fmt.Sprintf("address %s already funded, wait until %s", addr.Hex(), t)
return ctx.Send(new(HandlerResponse).SetError(errReason).MustMarshall(), CodeErrFlood)
}
Expand Down Expand Up @@ -262,7 +262,7 @@ func (f *faucet) authAragonDaoHandler(msg *apirest.APIdata, ctx *httprouter.HTTP
return ctx.Send(new(HandlerResponse).SetError(err.Error()).MustMarshall(), CodeErrInternalError)
}

if err := f.storage.addFundedUserID(addr.Bytes(), AuthTypeAragonDao); err != nil {
if err := f.storage.AddFundedUserWithWaitTime(addr.Bytes(), AuthTypeAragonDao); err != nil {
return ctx.Send(new(HandlerResponse).SetError(err.Error()).MustMarshall(), CodeErrInternalError)
}

Expand Down
3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

flag "github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/vocdoni/vocfaucet/storage"
"go.vocdoni.io/dvote/crypto/ethereum"
"go.vocdoni.io/dvote/db"
"go.vocdoni.io/dvote/httprouter"
Expand Down Expand Up @@ -170,7 +171,7 @@ func main() {
}

// init storage
storage, err := newStorage(dbType, dataDir, waitPeriod, signer.Address().Bytes()[:8])
storage, err := storage.New(dbType, dataDir, waitPeriod, signer.Address().Bytes()[:8])
if err != nil {
log.Fatal(err)
}
Expand Down
39 changes: 39 additions & 0 deletions storage/sotrage_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package storage

import (
"testing"
"time"
)

func TestAddFundedUserWithWaitTime(t *testing.T) {
// Create a new storage instance
st, err := New("pebble", t.TempDir(), time.Second*2, []byte("prefix"))
if err != nil {
t.Fatalf("failed to create storage instance: %v", err)
}
defer st.Close()

// Define test data
userID := []byte("user123")
authType := "email"

// Add funded user with wait time
err = st.AddFundedUserWithWaitTime(userID, authType)
if err != nil {
t.Fatalf("failed to add funded user: %v", err)
}

// Retrieve wait period end time
funded, _ := st.CheckFundedUserWithWaitTime(userID, authType)
if !funded {
t.Fatalf("expected user to be funded, but it is not")
}

// Verify wait period end time
time.Sleep(time.Second * 3)
funded, _ = st.CheckFundedUserWithWaitTime(userID, authType)
if funded {
t.Fatalf("expected user to be not funded, but it is not")
}

}
41 changes: 32 additions & 9 deletions storage.go → storage/storage.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package storage

import (
"encoding/binary"
Expand All @@ -13,17 +13,20 @@ import (
"go.vocdoni.io/dvote/log"
)

type storage struct {
// Storage is a key-value storage for the faucet.
type Storage struct {
kv db.Database
waitPeriodSeconds uint64
}

func newStorage(dbType string, dataDir string, waitPeriod time.Duration, dbPrefix []byte) (*storage, error) {
// New creates a new storage instance.
func New(dbType string, dataDir string, waitPeriod time.Duration, dbPrefix []byte) (*Storage, error) {
if dbType != db.TypePebble && dbType != db.TypeLevelDB && dbType != db.TypeMongo {
return nil, fmt.Errorf("invalid dbType: %q. Available types: %q %q %q", dbType, db.TypePebble, db.TypeLevelDB, db.TypeMongo)
return nil, fmt.Errorf("invalid dbType: %q. Available types: %q %q %q",
dbType, db.TypePebble, db.TypeLevelDB, db.TypeMongo)
}
log.Infow("create db storage", "type", dbType, "dir", dataDir, "prefix", hex.EncodeToString(dbPrefix))
st := &storage{}
st := &Storage{}
var err error
mdb, err := metadb.New(dbType, filepath.Join(filepath.Clean(dataDir), "db"))
if err != nil {
Expand All @@ -35,9 +38,29 @@ func newStorage(dbType string, dataDir string, waitPeriod time.Duration, dbPrefi
return st, nil
}

// addFundedUserID adds the given userID to the funded list, with the current time
// Set sets the given key to the given value.
func (st *Storage) Set(key, value []byte) error {
tx := st.kv.WriteTx()
defer tx.Discard()
if err := tx.Set(key, value); err != nil {
return fmt.Errorf("failed to set key %s: %w", key, err)
}
return tx.Commit()
}

// Get gets the value for the given key.
func (st *Storage) Get(key []byte) ([]byte, error) {
return st.kv.Get(key)
}

// Close closes the storage.
func (st *Storage) Close() error {
return st.kv.Close()
}

// AddFundedUserWithWaitTime adds the given userID to the funded list, with the current time
// as the wait period end time.
func (st *storage) addFundedUserID(userID []byte, authType string) error {
func (st *Storage) AddFundedUserWithWaitTime(userID []byte, authType string) error {
tx := st.kv.WriteTx()
defer tx.Discard()
key := append(userID, []byte(authType)...)
Expand All @@ -50,9 +73,9 @@ func (st *storage) addFundedUserID(userID []byte, authType string) error {
return tx.Commit()
}

// checkIsFundedUserID checks if the given text is funded and returns true if it is, within
// CheckFundedUserWithWaitTime checks if the given text is funded and returns true if it is, within
// the wait period time window. Otherwise, it returns false.
func (st *storage) checkIsFundedUserID(userID []byte, authType string) (bool, time.Time) {
func (st *Storage) CheckFundedUserWithWaitTime(userID []byte, authType string) (bool, time.Time) {
key := append(userID, []byte(authType)...)
wpBytes, err := st.kv.Get(key)
if err != nil {
Expand Down

0 comments on commit 08d5712

Please sign in to comment.