satellite: enable open registration (and add flag that disables it) SM-441
Change-Id: I47bfedb312089f6d2bfbab013bd74ad4b8aa5f5e
This commit is contained in:
parent
803e2930f4
commit
051569c69f
@ -410,9 +410,11 @@ func (planet *Planet) newSatellites(count int) ([]*SatelliteSystem, error) {
|
||||
Console: consoleweb.Config{
|
||||
Address: "127.0.0.1:0",
|
||||
StaticDir: filepath.Join(developmentRoot, "web/satellite"),
|
||||
PasswordCost: console.TestPasswordCost,
|
||||
AuthToken: "very-secret-token",
|
||||
AuthTokenSecret: "my-suppa-secret-key",
|
||||
Config: console.Config{
|
||||
PasswordCost: console.TestPasswordCost,
|
||||
},
|
||||
},
|
||||
Marketing: marketingweb.Config{
|
||||
Address: "127.0.0.1:0",
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"net/mail"
|
||||
"net/smtp"
|
||||
|
||||
"github.com/spacemonkeygo/monkit/v3"
|
||||
monkit "github.com/spacemonkeygo/monkit/v3"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@ -575,7 +575,7 @@ func NewAPI(log *zap.Logger, full *identity.FullIdentity, db DB,
|
||||
peer.DB.Rewards(),
|
||||
peer.Marketing.PartnersService,
|
||||
peer.Payments.Accounts,
|
||||
consoleConfig.PasswordCost,
|
||||
consoleConfig.Config,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errs.Combine(err, peer.Close())
|
||||
|
@ -85,7 +85,7 @@ func TestGrapqhlMutation(t *testing.T) {
|
||||
db.Rewards(),
|
||||
partnersService,
|
||||
payments.Accounts(),
|
||||
console.TestPasswordCost,
|
||||
console.Config{PasswordCost: console.TestPasswordCost},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -70,7 +70,7 @@ func TestGraphqlQuery(t *testing.T) {
|
||||
db.Rewards(),
|
||||
partnersService,
|
||||
payments.Accounts(),
|
||||
console.TestPasswordCost,
|
||||
console.Config{PasswordCost: console.TestPasswordCost},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"github.com/graphql-go/graphql"
|
||||
"github.com/graphql-go/graphql/gqlerrors"
|
||||
"github.com/skyrings/skyring-common/tools/uuid"
|
||||
"github.com/spacemonkeygo/monkit/v3"
|
||||
monkit "github.com/spacemonkeygo/monkit/v3"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@ -61,8 +61,6 @@ type Config struct {
|
||||
AuthToken string `help:"auth token needed for access to registration token creation endpoint" default:""`
|
||||
AuthTokenSecret string `help:"secret used to sign auth tokens" releaseDefault:"" devDefault:"my-suppa-secret-key"`
|
||||
|
||||
PasswordCost int `internal:"true" help:"password hashing cost (0=automatic)" default:"0"`
|
||||
|
||||
ContactInfoURL string `help:"url link to contacts page" default:"https://forum.storj.io"`
|
||||
FrameAncestors string `help:"allow domains to embed the satellite in a frame, space separated" default:"tardigrade.io"`
|
||||
LetUsKnowURL string `help:"url link to let us know page" default:"https://storjlabs.atlassian.net/servicedesk/customer/portals"`
|
||||
@ -71,6 +69,8 @@ type Config struct {
|
||||
SatelliteOperator string `help:"name of organization which set up satellite" default:"Storj Labs" `
|
||||
TermsAndConditionsURL string `help:"url link to terms and conditions page" default:"https://storj.io/storage-sla/"`
|
||||
SegmentIOPublicKey string `help:"used to initialize segment.io at web satellite console" default:""`
|
||||
|
||||
console.Config
|
||||
}
|
||||
|
||||
// Server represents console web server
|
||||
|
@ -4,6 +4,7 @@
|
||||
package console
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
@ -60,6 +61,14 @@ func (secret RegistrationSecret) String() string {
|
||||
return base64.URLEncoding.EncodeToString(secret[:])
|
||||
}
|
||||
|
||||
// IsZero returns if the RegistrationSecret is not set
|
||||
func (secret RegistrationSecret) IsZero() bool {
|
||||
var zero RegistrationSecret
|
||||
// this doesn't need to be constant-time, because we're explicitly testing
|
||||
// against a hardcoded, well-known value
|
||||
return bytes.Equal(secret[:], zero[:])
|
||||
}
|
||||
|
||||
// RegistrationSecretFromBase64 creates new registration secret from base64 string
|
||||
func RegistrationSecretFromBase64(s string) (RegistrationSecret, error) {
|
||||
var secret RegistrationSecret
|
||||
|
@ -86,7 +86,13 @@ type Service struct {
|
||||
partners *rewards.PartnersService
|
||||
accounts payments.Accounts
|
||||
|
||||
passwordCost int
|
||||
config Config
|
||||
}
|
||||
|
||||
// Config keeps track of core console service configuration parameters
|
||||
type Config struct {
|
||||
PasswordCost int `help:"password hashing cost (0=automatic)" internal:"true" default:"0"`
|
||||
OpenRegistrationEnabled bool `help:"enable open registration" default:"false"`
|
||||
}
|
||||
|
||||
// PaymentsService separates all payment related functionality
|
||||
@ -95,7 +101,7 @@ type PaymentsService struct {
|
||||
}
|
||||
|
||||
// NewService returns new instance of Service.
|
||||
func NewService(log *zap.Logger, signer Signer, store DB, projectAccounting accounting.ProjectAccounting, projectUsage *accounting.Service, rewards rewards.DB, partners *rewards.PartnersService, accounts payments.Accounts, passwordCost int) (*Service, error) {
|
||||
func NewService(log *zap.Logger, signer Signer, store DB, projectAccounting accounting.ProjectAccounting, projectUsage *accounting.Service, rewards rewards.DB, partners *rewards.PartnersService, accounts payments.Accounts, config Config) (*Service, error) {
|
||||
if signer == nil {
|
||||
return nil, errs.New("signer can't be nil")
|
||||
}
|
||||
@ -105,8 +111,8 @@ func NewService(log *zap.Logger, signer Signer, store DB, projectAccounting acco
|
||||
if log == nil {
|
||||
return nil, errs.New("log can't be nil")
|
||||
}
|
||||
if passwordCost == 0 {
|
||||
passwordCost = bcrypt.DefaultCost
|
||||
if config.PasswordCost == 0 {
|
||||
config.PasswordCost = bcrypt.DefaultCost
|
||||
}
|
||||
|
||||
return &Service{
|
||||
@ -118,7 +124,7 @@ func NewService(log *zap.Logger, signer Signer, store DB, projectAccounting acco
|
||||
rewards: rewards,
|
||||
partners: partners,
|
||||
accounts: accounts,
|
||||
passwordCost: passwordCost,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -366,6 +372,28 @@ func (paymentService PaymentsService) AddPromotionalCoupon(ctx context.Context,
|
||||
return paymentService.service.accounts.Coupons().AddPromotionalCoupon(ctx, userID, duration, amount, limit)
|
||||
}
|
||||
|
||||
// checkRegistrationSecret returns a RegistrationToken if applicable (nil if not), and an error
|
||||
// if and only if the registration shouldn't proceed.
|
||||
func (s *Service) checkRegistrationSecret(ctx context.Context, tokenSecret RegistrationSecret) (*RegistrationToken, error) {
|
||||
if s.config.OpenRegistrationEnabled && tokenSecret.IsZero() {
|
||||
// in this case we're going to let the registration happen without a token
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// in all other cases, require a registration token
|
||||
registrationToken, err := s.store.RegistrationTokens().GetBySecret(ctx, tokenSecret)
|
||||
if err != nil {
|
||||
return nil, ErrUnauthorized.Wrap(err)
|
||||
}
|
||||
// if a registration token is already associated with an user ID, that means the token is already used
|
||||
// we should terminate the account creation process and return an error
|
||||
if registrationToken.OwnerID != nil {
|
||||
return nil, errs.New(usedRegTokenErrMsg)
|
||||
}
|
||||
|
||||
return registrationToken, nil
|
||||
}
|
||||
|
||||
// CreateUser gets password hash value and creates new inactive User
|
||||
func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret RegistrationSecret, refUserID string) (u *User, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
@ -393,23 +421,20 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
// TODO: remove after vanguard release
|
||||
registrationToken, err := s.store.RegistrationTokens().GetBySecret(ctx, tokenSecret)
|
||||
registrationToken, err := s.checkRegistrationSecret(ctx, tokenSecret)
|
||||
if err != nil {
|
||||
return nil, ErrUnauthorized.Wrap(err)
|
||||
}
|
||||
// if a registration token is already associated with an user ID, that means the token is already used
|
||||
// we should terminate the account creation process and return an error
|
||||
if registrationToken.OwnerID != nil {
|
||||
return nil, errs.New(usedRegTokenErrMsg)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, err = s.store.Users().GetByEmail(ctx, user.Email)
|
||||
if err == nil {
|
||||
return nil, errs.New(emailUsedErrMsg)
|
||||
}
|
||||
if err != sql.ErrNoRows {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), s.passwordCost)
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), s.config.PasswordCost)
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
@ -444,9 +469,11 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
err = tx.RegistrationTokens().UpdateOwner(ctx, registrationToken.Secret, u.ID)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
if registrationToken != nil {
|
||||
err = tx.RegistrationTokens().UpdateOwner(ctx, registrationToken.Secret, u.ID)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
if currentReward != nil {
|
||||
@ -583,7 +610,7 @@ func (s *Service) ResetPassword(ctx context.Context, resetPasswordToken, passwor
|
||||
return errs.New(passwordRecoveryTokenIsExpiredErrMsg)
|
||||
}
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), s.passwordCost)
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), s.config.PasswordCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -719,7 +746,7 @@ func (s *Service) ChangePassword(ctx context.Context, pass, newPass string) (err
|
||||
return err
|
||||
}
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(newPass), s.passwordCost)
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(newPass), s.config.PasswordCost)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
3
scripts/testdata/satellite-config.yaml.lock
vendored
3
scripts/testdata/satellite-config.yaml.lock
vendored
@ -58,6 +58,9 @@
|
||||
# url link to let us know page
|
||||
# console.let-us-know-url: https://storjlabs.atlassian.net/servicedesk/customer/portals
|
||||
|
||||
# enable open registration
|
||||
# console.open-registration-enabled: false
|
||||
|
||||
# used to display at web satellite console
|
||||
# console.satellite-name: Storj
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user