Skip to content

Commit

Permalink
Control faucetPackage generation by OAuth Account (#12)
Browse files Browse the repository at this point in the history
Control faucetPackage generation by OAuth Account
  • Loading branch information
nigeon authored Dec 11, 2023
1 parent 506abdd commit f8ee436
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 42 deletions.
39 changes: 32 additions & 7 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.checkIsFundedAddress(addr, "open"); funded {
if funded, t := f.storage.checkIsFundedUserID(addr.Bytes(), "open"); 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, "open")
if err != nil {
return err
}
if err := f.storage.addFundedAddress(addr, "open"); err != nil {
if err := f.storage.addFundedUserID(addr.Bytes(), "open"); 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.checkIsFundedAddress(addr, "oauth"); funded {
if funded, t := f.storage.checkIsFundedUserID(addr.Bytes(), "oauth"); funded {
errReason := fmt.Sprintf("address %s already funded, wait until %s", addr.Hex(), t)
return ctx.Send(new(HandlerResponse).SetError(errReason).MustMarshall(), CodeErrFlood)
}
Expand All @@ -139,16 +139,41 @@ func (f *faucet) authOAuthHandler(msg *apirest.APIdata, ctx *httprouter.HTTPCont
return ctx.Send(new(HandlerResponse).SetError(ReasonErrOauthProviderNotFound).MustMarshall(), CodeErrOauthProviderNotFound)
}

_, err = provider.GetOAuthToken(newRequest.Code, newRequest.RedirectURL)
token, err := provider.GetOAuthToken(newRequest.Code, newRequest.RedirectURL)
if err != nil {
return ctx.Send(new(HandlerResponse).SetError(ReasonErrOauthProviderError).MustMarshall(), CodeErrOauthProviderError)
}

profileRaw, err := provider.GetOAuthProfile(token)
if err != nil {
log.Warnw("error obtaining the profile", "err", err)
return ctx.Send(new(HandlerResponse).SetError(ReasonErrOauthProviderError).MustMarshall(), CodeErrOauthProviderError)
}

var profile map[string]interface{}
if err := json.Unmarshal(profileRaw, &profile); err != nil {
log.Warnw("error marshalling the profile", "err", err)
return ctx.Send(new(HandlerResponse).SetError(ReasonErrOauthProviderError).MustMarshall(), CodeErrOauthProviderError)
}

// 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 {
errReason := fmt.Sprintf("user %s already funded, wait until %s", fundedProfileField, t)
return ctx.Send(new(HandlerResponse).SetError(errReason).MustMarshall(), CodeErrFlood)
}

data, err := f.prepareFaucetPackage(addr, "oauth")
if err != nil {
return err
}
if err := f.storage.addFundedAddress(addr, "oauth"); err != nil {

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

Expand Down Expand Up @@ -209,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.checkIsFundedAddress(addr, "aragon"); funded {
if funded, t := f.storage.checkIsFundedUserID(addr.Bytes(), "aragon"); 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 @@ -237,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.addFundedAddress(addr, "aragon"); err != nil {
if err := f.storage.addFundedUserID(addr.Bytes(), "aragon"); err != nil {
return ctx.Send(new(HandlerResponse).SetError(err.Error()).MustMarshall(), CodeErrInternalError)
}

Expand Down
5 changes: 4 additions & 1 deletion oauthhandler/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ providers:
client_id: FACEBOOK_CLIENT_ID
client_secret: FACEBOOK_CLIENT_SECRET
scope: email
username_field: email
github:
name: Github
auth_url: https://github.com/login/oauth/authorize
Expand All @@ -15,6 +16,7 @@ providers:
client_id: GITHUB_CLIENT_ID
client_secret: GITHUB_CLIENT_SECRET
scope: user:email
username_field: login
twitter:
name: Twitter
auth_url: https://api.twitter.com/oauth/authenticate
Expand Down Expand Up @@ -46,4 +48,5 @@ providers:
profile_url: https://www.googleapis.com/oauth2/v1/userinfo
client_id: GOOGLE_CLIENT_ID
client_secret: GOOGLE_CLIENT_SECRET
scope: email
scope: email
username_field: id
48 changes: 26 additions & 22 deletions oauthhandler/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,26 @@ type Config struct {

// ProviderConfig represents the configuration for an OAuth provider.
type ProviderConfig struct {
Name string `yaml:"name"`
AuthURL string `yaml:"auth_url"`
TokenURL string `yaml:"token_url"`
ProfileURL string `yaml:"profile_url"`
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
Scope string `yaml:"scope"`
Name string `yaml:"name"`
AuthURL string `yaml:"auth_url"`
TokenURL string `yaml:"token_url"`
ProfileURL string `yaml:"profile_url"`
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
Scope string `yaml:"scope"`
UsernameField string `yaml:"username_field"`
}

// Provider is the OAuth provider.
type Provider struct {
Name string
AuthURL string
TokenURL string
ProfileURL string
ClientID string
ClientSecret string
Scope string
Name string
AuthURL string
TokenURL string
ProfileURL string
ClientID string
ClientSecret string
Scope string
UsernameField string
}

// OAuthToken is the OAuth token.
Expand All @@ -50,15 +52,16 @@ type OAuthToken struct {
}

// NewProvider creates a new OAuth provider.
func NewProvider(name, authURL, tokenURL, profileURL, clientID, clientSecret, scope string) *Provider {
func NewProvider(name, authURL, tokenURL, profileURL, clientID, clientSecret, scope string, usernameField string) *Provider {
return &Provider{
Name: name,
AuthURL: authURL,
TokenURL: tokenURL,
ProfileURL: profileURL,
ClientID: clientID,
ClientSecret: clientSecret,
Scope: scope,
Name: name,
AuthURL: authURL,
TokenURL: tokenURL,
ProfileURL: profileURL,
ClientID: clientID,
ClientSecret: clientSecret,
Scope: scope,
UsernameField: usernameField,
}
}

Expand Down Expand Up @@ -92,6 +95,7 @@ func InitProviders() (map[string]*Provider, error) {
viper.GetString(conf.ClientID),
viper.GetString(conf.ClientSecret),
conf.Scope,
conf.UsernameField,
)
providers[name] = provider
}
Expand Down
18 changes: 6 additions & 12 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,12 @@ import (
"path/filepath"
"time"

"github.com/ethereum/go-ethereum/common"
"go.vocdoni.io/dvote/db"
"go.vocdoni.io/dvote/db/metadb"
"go.vocdoni.io/dvote/db/prefixeddb"
"go.vocdoni.io/dvote/log"
)

const (
fundedAddressPrefix = "a_"
)

type storage struct {
kv db.Database
waitPeriodSeconds uint64
Expand All @@ -40,12 +35,12 @@ func newStorage(dbType string, dataDir string, waitPeriod time.Duration, dbPrefi
return st, nil
}

// addFundedAddress adds the given address to the funded addresses list, with the current time
// addFundedUserID adds the given userID to the funded list, with the current time
// as the wait period end time.
func (st *storage) addFundedAddress(addr common.Address, authType string) error {
func (st *storage) addFundedUserID(userID []byte, authType string) error {
tx := st.kv.WriteTx()
defer tx.Discard()
key := append([]byte(fundedAddressPrefix), append(addr.Bytes(), []byte(authType)...)...)
key := append(userID, []byte(authType)...)
wp := uint64(time.Now().Unix()) + st.waitPeriodSeconds
wpBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(wpBytes, wp)
Expand All @@ -55,11 +50,10 @@ func (st *storage) addFundedAddress(addr common.Address, authType string) error
return tx.Commit()
}

// checkIsFundedAddress checks if the given address is funded and returns true if it is, within
// checkIsFundedUserID checks if the given text is funded and returns true if it is, within
// the wait period time window. Otherwise, it returns false.
// The second return value is the wait period end time, if the address is funded.
func (st *storage) checkIsFundedAddress(addr common.Address, authType string) (bool, time.Time) {
key := append([]byte(fundedAddressPrefix), append(addr.Bytes(), []byte(authType)...)...)
func (st *storage) checkIsFundedUserID(userID []byte, authType string) (bool, time.Time) {
key := append(userID, []byte(authType)...)
wpBytes, err := st.kv.Get(key)
if err != nil {
return false, time.Time{}
Expand Down

0 comments on commit f8ee436

Please sign in to comment.