satellite/console: Add reCAPTCHA verification step to registration
The user must complete a reCAPTCHA in order to register. ReCAPTCHA verification failure results in rejection of the registration attempt. Change-Id: I34ba7db414d756fd1aaebdc3d19cccbfc7fc1ea3
This commit is contained in:
parent
ec9ad5bd7d
commit
a5f6bb9cc0
@ -25,6 +25,8 @@ type Flags struct {
|
||||
StorageNodeCount int
|
||||
Identities int
|
||||
|
||||
NoGateways bool
|
||||
|
||||
IsDev bool
|
||||
FailFast bool
|
||||
|
||||
@ -64,6 +66,8 @@ func main() {
|
||||
rootCmd.PersistentFlags().IntVarP(&flags.StorageNodeCount, "storage-nodes", "", 10, "number of storage nodes to start")
|
||||
rootCmd.PersistentFlags().IntVarP(&flags.Identities, "identities", "", 10, "number of identities to create")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(&flags.NoGateways, "no-gateways", "", false, "whether to disable gateway creation for each satellite")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(&printCommands, "print-commands", "x", false, "print commands as they are run")
|
||||
rootCmd.PersistentFlags().BoolVarP(&flags.IsDev, "dev", "", true, "use configuration values tuned for development")
|
||||
rootCmd.PersistentFlags().BoolVarP(&flags.FailFast, "failfast", "", true, "stop all processes when one of the processes fails")
|
||||
|
@ -457,6 +457,9 @@ func newNetwork(flags *Flags) (*Processes, error) {
|
||||
|
||||
// Create gateways for each satellite
|
||||
for i, satellite := range satellites {
|
||||
if flags.NoGateways {
|
||||
break
|
||||
}
|
||||
satellite := satellite
|
||||
process := processes.New(Info{
|
||||
Name: fmt.Sprintf("gateway/%d", i),
|
||||
|
@ -70,7 +70,7 @@ func (rl *IPRateLimiter) cleanupLimiters() {
|
||||
// Limit applies a per IP rate limiting as an HTTP Handler.
|
||||
func (rl *IPRateLimiter) Limit(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ip, err := getRequestIP(r)
|
||||
ip, err := GetRequestIP(r)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
@ -84,8 +84,8 @@ func (rl *IPRateLimiter) Limit(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// getRequestIP gets the original IP address of the request by handling the request headers.
|
||||
func getRequestIP(r *http.Request) (ip string, err error) {
|
||||
// GetRequestIP gets the original IP address of the request by handling the request headers.
|
||||
func GetRequestIP(r *http.Request) (ip string, err error) {
|
||||
realIP := r.Header.Get("X-REAL-IP")
|
||||
if realIP != "" {
|
||||
return realIP, nil
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
"storj.io/common/uuid"
|
||||
"storj.io/storj/private/post"
|
||||
"storj.io/storj/private/web"
|
||||
"storj.io/storj/satellite/analytics"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/consoleweb/consoleql"
|
||||
@ -112,19 +113,20 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
var registerData struct {
|
||||
FullName string `json:"fullName"`
|
||||
ShortName string `json:"shortName"`
|
||||
Email string `json:"email"`
|
||||
Partner string `json:"partner"`
|
||||
PartnerID string `json:"partnerId"`
|
||||
Password string `json:"password"`
|
||||
SecretInput string `json:"secret"`
|
||||
ReferrerUserID string `json:"referrerUserId"`
|
||||
IsProfessional bool `json:"isProfessional"`
|
||||
Position string `json:"position"`
|
||||
CompanyName string `json:"companyName"`
|
||||
EmployeeCount string `json:"employeeCount"`
|
||||
HaveSalesContact bool `json:"haveSalesContact"`
|
||||
FullName string `json:"fullName"`
|
||||
ShortName string `json:"shortName"`
|
||||
Email string `json:"email"`
|
||||
Partner string `json:"partner"`
|
||||
PartnerID string `json:"partnerId"`
|
||||
Password string `json:"password"`
|
||||
SecretInput string `json:"secret"`
|
||||
ReferrerUserID string `json:"referrerUserId"`
|
||||
IsProfessional bool `json:"isProfessional"`
|
||||
Position string `json:"position"`
|
||||
CompanyName string `json:"companyName"`
|
||||
EmployeeCount string `json:"employeeCount"`
|
||||
HaveSalesContact bool `json:"haveSalesContact"`
|
||||
RecaptchaResponse string `json:"recaptchaResponse"`
|
||||
}
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(®isterData)
|
||||
@ -148,18 +150,26 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
ip, err := web.GetRequestIP(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := a.service.CreateUser(ctx,
|
||||
console.CreateUser{
|
||||
FullName: registerData.FullName,
|
||||
ShortName: registerData.ShortName,
|
||||
Email: registerData.Email,
|
||||
PartnerID: registerData.PartnerID,
|
||||
Password: registerData.Password,
|
||||
IsProfessional: registerData.IsProfessional,
|
||||
Position: registerData.Position,
|
||||
CompanyName: registerData.CompanyName,
|
||||
EmployeeCount: registerData.EmployeeCount,
|
||||
HaveSalesContact: registerData.HaveSalesContact,
|
||||
FullName: registerData.FullName,
|
||||
ShortName: registerData.ShortName,
|
||||
Email: registerData.Email,
|
||||
PartnerID: registerData.PartnerID,
|
||||
Password: registerData.Password,
|
||||
IsProfessional: registerData.IsProfessional,
|
||||
Position: registerData.Position,
|
||||
CompanyName: registerData.CompanyName,
|
||||
EmployeeCount: registerData.EmployeeCount,
|
||||
HaveSalesContact: registerData.HaveSalesContact,
|
||||
RecaptchaResponse: registerData.RecaptchaResponse,
|
||||
IP: ip,
|
||||
},
|
||||
secret,
|
||||
)
|
||||
|
@ -358,6 +358,8 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
|
||||
StorageTBPrice string
|
||||
EgressTBPrice string
|
||||
ObjectPrice string
|
||||
RecaptchaEnabled bool
|
||||
RecaptchaSiteKey string
|
||||
}
|
||||
|
||||
data.ExternalAddress = server.config.ExternalAddress
|
||||
@ -380,6 +382,8 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data.StorageTBPrice = server.pricing.StorageTBPrice
|
||||
data.EgressTBPrice = server.pricing.EgressTBPrice
|
||||
data.ObjectPrice = server.pricing.ObjectPrice
|
||||
data.RecaptchaEnabled = server.config.Recaptcha.Enabled
|
||||
data.RecaptchaSiteKey = server.config.Recaptcha.SiteKey
|
||||
|
||||
if server.templates.index == nil {
|
||||
server.log.Error("index template is not set")
|
||||
|
80
satellite/console/recaptcha.go
Normal file
80
satellite/console/recaptcha.go
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
)
|
||||
|
||||
const recaptchaAPIURL = "https://www.google.com/recaptcha/api/siteverify"
|
||||
|
||||
// RecaptchaHandler is responsible for contacting the reCAPTCHA API
|
||||
// and returning whether the user response characterized by the given
|
||||
// response token and IP is valid.
|
||||
type RecaptchaHandler interface {
|
||||
Verify(ctx context.Context, responseToken string, userIP string) (bool, error)
|
||||
}
|
||||
|
||||
// googleRecaptcha is a reCAPTCHA handler that contacts Google's reCAPTCHA API.
|
||||
type googleRecaptcha struct {
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
// NewDefaultRecaptcha returns a reCAPTCHA handler that contacts Google's reCAPTCHA API.
|
||||
func NewDefaultRecaptcha(secretKey string) RecaptchaHandler {
|
||||
return googleRecaptcha{SecretKey: secretKey}
|
||||
}
|
||||
|
||||
// Verify contacts the reCAPTCHA API and returns whether the given response token is valid.
|
||||
// The documentation can be found here: https://developers.google.com/recaptcha/docs/verify
|
||||
func (r googleRecaptcha) Verify(ctx context.Context, responseToken string, userIP string) (valid bool, err error) {
|
||||
if responseToken == "" {
|
||||
return false, errs.New("the response token is empty")
|
||||
}
|
||||
if userIP == "" {
|
||||
return false, errs.New("the user's IP address is empty")
|
||||
}
|
||||
|
||||
reqBody := url.Values{
|
||||
"secret": {r.SecretKey},
|
||||
"response": {responseToken},
|
||||
"remoteip": {userIP},
|
||||
}.Encode()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, recaptchaAPIURL, strings.NewReader(reqBody))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err = errs.Combine(err, resp.Body.Close())
|
||||
}()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return false, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
var data struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
err = json.NewDecoder(resp.Body).Decode(&data)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return data.Success, nil
|
||||
}
|
69
satellite/console/recaptcha_test.go
Normal file
69
satellite/console/recaptcha_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package console_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/storj/private/testplanet"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/console"
|
||||
)
|
||||
|
||||
const validResponseToken = "myResponseToken"
|
||||
|
||||
type mockRecaptcha struct{}
|
||||
|
||||
func (r mockRecaptcha) Verify(ctx context.Context, responseToken string, userIP string) (bool, error) {
|
||||
return responseToken == validResponseToken, nil
|
||||
}
|
||||
|
||||
// TestRecaptcha ensures the reCAPTCHA service is working properly.
|
||||
func TestRecaptcha(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1,
|
||||
Reconfigure: testplanet.Reconfigure{
|
||||
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||
config.Console.Recaptcha.Enabled = true
|
||||
config.Console.Recaptcha.SecretKey = "mySecretKey"
|
||||
config.Console.Recaptcha.SiteKey = "mySiteKey"
|
||||
},
|
||||
},
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
service := planet.Satellites[0].API.Console.Service
|
||||
require.NotNil(t, service)
|
||||
service.TestSwapRecaptchaHandler(mockRecaptcha{})
|
||||
|
||||
regToken1, err := service.CreateRegToken(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
user, err := service.CreateUser(ctx, console.CreateUser{
|
||||
FullName: "User",
|
||||
Email: "u@mail.test",
|
||||
Password: "password",
|
||||
RecaptchaResponse: validResponseToken,
|
||||
}, regToken1.Secret)
|
||||
|
||||
require.NotNil(t, user)
|
||||
require.NoError(t, err)
|
||||
|
||||
regToken2, err := service.CreateRegToken(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
user, err = service.CreateUser(ctx, console.CreateUser{
|
||||
FullName: "User2",
|
||||
Email: "u2@mail.test",
|
||||
Password: "password",
|
||||
RecaptchaResponse: "wrong",
|
||||
}, regToken2.Secret)
|
||||
|
||||
require.Nil(t, user)
|
||||
require.True(t, console.ErrValidation.Has(err))
|
||||
})
|
||||
}
|
@ -96,6 +96,7 @@ type Service struct {
|
||||
buckets Buckets
|
||||
partners *rewards.PartnersService
|
||||
accounts payments.Accounts
|
||||
recaptchaHandler RecaptchaHandler
|
||||
analytics *analytics.Service
|
||||
|
||||
config Config
|
||||
@ -121,6 +122,14 @@ type Config struct {
|
||||
OpenRegistrationEnabled bool `help:"enable open registration" default:"false" testDefault:"true"`
|
||||
DefaultProjectLimit int `help:"default project limits for users" default:"3" testDefault:"5"`
|
||||
UsageLimits UsageLimitsConfig
|
||||
Recaptcha RecaptchaConfig
|
||||
}
|
||||
|
||||
// RecaptchaConfig contains configurations for the reCAPTCHA system.
|
||||
type RecaptchaConfig struct {
|
||||
Enabled bool `help:"whether or not reCAPTCHA is enabled for user registration" default:"false"`
|
||||
SiteKey string `help:"reCAPTCHA site key"`
|
||||
SecretKey string `help:"reCAPTCHA secret key"`
|
||||
}
|
||||
|
||||
// PaymentsService separates all payment related functionality.
|
||||
@ -153,6 +162,7 @@ func NewService(log *zap.Logger, signer Signer, store DB, projectAccounting acco
|
||||
buckets: buckets,
|
||||
partners: partners,
|
||||
accounts: accounts,
|
||||
recaptchaHandler: NewDefaultRecaptcha(config.Recaptcha.SecretKey),
|
||||
analytics: analytics,
|
||||
config: config,
|
||||
minCoinPayment: minCoinPayment,
|
||||
@ -545,6 +555,18 @@ func (s *Service) checkRegistrationSecret(ctx context.Context, tokenSecret Regis
|
||||
// CreateUser gets password hash value and creates new inactive User.
|
||||
func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret RegistrationSecret) (u *User, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
if s.config.Recaptcha.Enabled {
|
||||
valid, err := s.recaptchaHandler.Verify(ctx, user.RecaptchaResponse, user.IP)
|
||||
if err != nil {
|
||||
s.log.Error("reCAPTCHA authorization failed", zap.Error(err))
|
||||
return nil, ErrValidation.Wrap(err)
|
||||
}
|
||||
if !valid {
|
||||
return nil, ErrValidation.New("reCAPTCHA validation unsuccessful")
|
||||
}
|
||||
}
|
||||
|
||||
if err := user.IsValid(); err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
@ -627,6 +649,12 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// TestSwapRecaptchaHandler replaces the existing handler for reCAPTCHAs with
|
||||
// the one specified for use in testing.
|
||||
func (s *Service) TestSwapRecaptchaHandler(h RecaptchaHandler) {
|
||||
s.recaptchaHandler = h
|
||||
}
|
||||
|
||||
// GenerateActivationToken - is a method for generating activation token.
|
||||
func (s *Service) GenerateActivationToken(ctx context.Context, id uuid.UUID, email string) (token string, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
@ -51,17 +51,19 @@ func (user *UserInfo) IsValid() error {
|
||||
|
||||
// CreateUser struct holds info for User creation.
|
||||
type CreateUser struct {
|
||||
FullName string `json:"fullName"`
|
||||
ShortName string `json:"shortName"`
|
||||
Email string `json:"email"`
|
||||
PartnerID string `json:"partnerId"`
|
||||
Password string `json:"password"`
|
||||
IsProfessional bool `json:"isProfessional"`
|
||||
Position string `json:"position"`
|
||||
CompanyName string `json:"companyName"`
|
||||
WorkingOn string `json:"workingOn"`
|
||||
EmployeeCount string `json:"employeeCount"`
|
||||
HaveSalesContact bool `json:"haveSalesContact"`
|
||||
FullName string `json:"fullName"`
|
||||
ShortName string `json:"shortName"`
|
||||
Email string `json:"email"`
|
||||
PartnerID string `json:"partnerId"`
|
||||
Password string `json:"password"`
|
||||
IsProfessional bool `json:"isProfessional"`
|
||||
Position string `json:"position"`
|
||||
CompanyName string `json:"companyName"`
|
||||
WorkingOn string `json:"workingOn"`
|
||||
EmployeeCount string `json:"employeeCount"`
|
||||
HaveSalesContact bool `json:"haveSalesContact"`
|
||||
RecaptchaResponse string `json:"recaptchaResponse"`
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
|
||||
// IsValid checks CreateUser validity and returns error describing whats wrong.
|
||||
|
9
scripts/testdata/satellite-config.yaml.lock
vendored
9
scripts/testdata/satellite-config.yaml.lock
vendored
@ -148,6 +148,15 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0
|
||||
# number of IPs whose rate limits we store
|
||||
# console.rate-limit.num-limits: 1000
|
||||
|
||||
# whether or not reCAPTCHA is enabled for user registration
|
||||
# console.recaptcha.enabled: false
|
||||
|
||||
# reCAPTCHA secret key
|
||||
# console.recaptcha.secret-key: ""
|
||||
|
||||
# reCAPTCHA site key
|
||||
# console.recaptcha.site-key: ""
|
||||
|
||||
# used to display at web satellite console
|
||||
# console.satellite-name: Storj
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
<meta name="storage-tb-price" content="{{ .StorageTBPrice }}">
|
||||
<meta name="egress-tb-price" content="{{ .EgressTBPrice }}">
|
||||
<meta name="object-price" content="{{ .ObjectPrice }}">
|
||||
<meta name="recaptcha-enabled" content="{{ .RecaptchaEnabled }}">
|
||||
<meta name="recaptcha-site-key" content="{{ .RecaptchaSiteKey }}">
|
||||
<title>{{ .SatelliteName }}</title>
|
||||
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACDVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////8nbP8obf8pbf8qbv8rb/8sb/8tcP8ucf8vcf8vcv8xc/8zdP81df81dv82dv83d/84eP85eP86ef87ev89e/8+fP8/fP9Aff9Bfv9Cfv9Df/9EgP9FgP9Ggf9Hgv9Jg/9LhP9Mhf9Nhv9Oh/9Ph/9RiP9Rif9Sif9Ui/9Vi/9WjP9Xjf9Yjf9aj/9dkf9ekf9ilP9jlf9llv9nl/9omP9rmv9sm/9tnP9vnf9wnv9yn/91of92ov93o/94o/98pv9/qP+Bqf+Cqv+Eq/+FrP+Hrf+Irv+Jr/+Kr/+Msf+Nsv+Stf+Ttf+Ttv+Utv+Vt/+WuP+XuP+Zuf+Zuv+hv/+kwf+lwv+mwv+nw/+oxP+pxP+pxf+qxf+rxv+yy/+0zP+1zf+3zv+4z/+60P+70f+90v+/0/+/1P/B1f/D1v/E1//F1//F2P/G2P/H2f/I2v/J2v/K2//L3P/P3v/Q3//R4P/S4P/V4v/V4//W4//X5P/Y5P/b5v/b5//c5//d6P/e6f/f6f/g6v/h6//j7P/k7f/l7f/m7v/q8f/r8f/u8//w9f/x9f/x9v/z9//0+P/2+f/3+f/3+v/4+v/5+//6/P/8/f/9/v/+/v////9uCbVDAAAAFXRSTlMABAU4Ozw9PpSWl5ilp6ip4+Tl/P6nIcp/AAAAAWJLR0SuuWuTpwAAAh5JREFUOMtjYGBgYOcXEl6HAYSF+FgZQICJex1OwMkEVIAi3+Xh1ozM5wKaj8xfpBwcITsbWYSNgR+JtzpJYvU6jbAVSEK8DEIITpOZqnxItISWfgVCTJAB7v4ZXpKRC9uMNCqXJci6TID7hQFMrV2zJE7abTKQFesDJGb7SYTOX7sGLAVWUKCgrGZcDeaDFaxb12alqC6XDlMwTyKnRLJ1HbKCddNEc0skJkAVdEssXatRiKqgVmLlatUqqILVpuaOEnLJy4GsIhONuHlAOldVwtJWcwnMDb2i4dPKdHVKV3uqRCdYqU9psVDOmh0vUQN35FTRhevWLU+V0FeZBdTtpSQRvgAoKtuMqmBdpKxvKYjXJ+o+cx0WBRPFO6ABHuesMheLghIdePiutc7AoqBLchZchVMSFgUr9HTS8sEgL1C0E1XBRNGUeeV6OlFONjbqSjY2Nv7mKjnzMyXqYQrW2OsYS8smLkOE5OpsFSkdQ6PlUAU9EgtXq6MFdZ3EkpVKNVAFc8TKW6QbURVMFK1slOyGuSFdUkLOoQtZwSRXaRmpKLgj1y1eMjdIImguTMHCCAnvGcuXQhIMPMl1O8hnrOy31GtfnaNi3oRIcohEu7ZY20DZK0DGTCV7NVKi5UVK40vDJVatU/dfgCTEw8AsgsSdLx+TKjUdOeMAsycnMr/BzrIcmc8ByrycuDMvByM4f7PyCmLL/gK8LEBJALYsGEdXEyupAAAAAElFTkSuQmCC" type="image/x-icon">
|
||||
<link rel="dns-prefetch" href="https://js.stripe.com">
|
||||
|
602
web/satellite/package-lock.json
generated
602
web/satellite/package-lock.json
generated
@ -2226,18 +2226,190 @@
|
||||
"yorkie": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
||||
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
||||
"dev": true
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
|
||||
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.1.0",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin-v5": {
|
||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz",
|
||||
"integrity": "sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^9.0.0",
|
||||
"memfs": "^3.1.2",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "2.7.0",
|
||||
"semver": "^7.3.2",
|
||||
"tapable": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
|
||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.4",
|
||||
"ajv": "^6.12.2",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.20.1",
|
||||
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
|
||||
@ -2258,6 +2430,20 @@
|
||||
"tslib": "^1.8.0",
|
||||
"tsutils": "^2.29.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2401,6 +2587,16 @@
|
||||
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"cacache": {
|
||||
"version": "13.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz",
|
||||
@ -2427,6 +2623,53 @@
|
||||
"unique-filename": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@ -2443,6 +2686,16 @@
|
||||
"minipass": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"terser-webpack-plugin": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz",
|
||||
@ -2459,6 +2712,18 @@
|
||||
"terser": "^4.6.12",
|
||||
"webpack-sources": "^1.4.3"
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.2.0.tgz",
|
||||
"integrity": "sha512-TitGhqSQ61RJljMmhIGvfWzJ2zk9m1Qug049Ugml6QP3t0e95o0XJjk29roNEiPKJQBEi8Ord5hFuSuELzSp8Q==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4121,6 +4386,29 @@
|
||||
"webpack-chain": "^6.4.0",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-merge": "^4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.2.0.tgz",
|
||||
"integrity": "sha512-TitGhqSQ61RJljMmhIGvfWzJ2zk9m1Qug049Ugml6QP3t0e95o0XJjk29roNEiPKJQBEi8Ord5hFuSuELzSp8Q==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/cli-shared-utils": {
|
||||
@ -4147,6 +4435,15 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"aws-sdk": {
|
||||
"version": "2.908.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.908.0.tgz",
|
||||
@ -4163,11 +4460,43 @@
|
||||
"xml2js": "0.4.19"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"optional": true
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.12.1.tgz",
|
||||
"integrity": "sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"ssri": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
|
||||
@ -4175,6 +4504,15 @@
|
||||
"requires": {
|
||||
"minipass": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -7273,192 +7611,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin-v5": {
|
||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz",
|
||||
"integrity": "sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^9.0.0",
|
||||
"memfs": "^3.1.2",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "2.7.0",
|
||||
"semver": "^7.3.2",
|
||||
"tapable": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
|
||||
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.1.0",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
|
||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.4",
|
||||
"ajv": "^6.12.2",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
@ -17154,79 +17306,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.2.0.tgz",
|
||||
"integrity": "sha512-TitGhqSQ61RJljMmhIGvfWzJ2zk9m1Qug049Ugml6QP3t0e95o0XJjk29roNEiPKJQBEi8Ord5hFuSuELzSp8Q==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-parser": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-parser/-/vue-parser-1.1.6.tgz",
|
||||
@ -17260,6 +17339,11 @@
|
||||
"resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.0.0.tgz",
|
||||
"integrity": "sha512-oegTNPItuHOkW0AP1MnbdNwkmyhfsUIIXvIRHpgC18tVoEo21/i6kItyeekjMs8JgZJeuHzsaTc/DZaJFH4IWQ=="
|
||||
},
|
||||
"vue-recaptcha": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-recaptcha/-/vue-recaptcha-1.3.0.tgz",
|
||||
"integrity": "sha512-9Qf1niyHq4QbEUhsvdUkS8BoOyhYwpp8v+imUSj67ffDo9RQ6h8Ekq8EGnw/GKViXCwWalp7EEY/n/fOtU0FyA=="
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.3.tgz",
|
||||
|
@ -11,15 +11,15 @@
|
||||
"dev": "vue-cli-service build --mode development"
|
||||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "2.853.0",
|
||||
"browser": "git+https://github.com/storj/browser#4e5770dfa9883176bbab793138911d92305243ed",
|
||||
"apollo-cache-inmemory": "1.6.6",
|
||||
"apollo-client": "2.6.10",
|
||||
"apollo-link": "1.2.14",
|
||||
"apollo-link-context": "1.0.20",
|
||||
"apollo-link-error": "1.1.13",
|
||||
"apollo-link-http": "1.5.17",
|
||||
"aws-sdk": "2.853.0",
|
||||
"bip39": "3.0.3",
|
||||
"browser": "git+https://github.com/storj/browser#4e5770dfa9883176bbab793138911d92305243ed",
|
||||
"graphql": "15.3.0",
|
||||
"graphql-tag": "2.11.0",
|
||||
"load-script": "1.0.0",
|
||||
@ -29,6 +29,7 @@
|
||||
"vue-class-component": "7.2.5",
|
||||
"vue-clipboard2": "0.3.1",
|
||||
"vue-property-decorator": "9.0.0",
|
||||
"vue-recaptcha": "1.3.0",
|
||||
"vue-router": "3.4.3",
|
||||
"vue2-datepicker": "3.7.0",
|
||||
"vuex": "3.5.1"
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { ErrorBadRequest } from '@/api/errors/ErrorBadRequest';
|
||||
import { ErrorEmailUsed } from '@/api/errors/ErrorEmailUsed';
|
||||
import { ErrorTooManyRequests } from '@/api/errors/ErrorTooManyRequests';
|
||||
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
|
||||
@ -206,7 +207,7 @@ export class AuthHttpApi {
|
||||
* @returns id of created user
|
||||
* @throws Error
|
||||
*/
|
||||
public async register(user: {fullName: string; shortName: string; email: string; partner: string; partnerId: string; password: string; isProfessional: boolean; position: string; companyName: string; employeeCount: string; haveSalesContact: boolean }, secret: string): Promise<string> {
|
||||
public async register(user: {fullName: string; shortName: string; email: string; partner: string; partnerId: string; password: string; isProfessional: boolean; position: string; companyName: string; employeeCount: string; haveSalesContact: boolean }, secret: string, recaptchaResponse: string): Promise<string> {
|
||||
const path = `${this.ROOT_PATH}/register`;
|
||||
const body = {
|
||||
secret: secret,
|
||||
@ -221,10 +222,13 @@ export class AuthHttpApi {
|
||||
companyName: user.companyName,
|
||||
employeeCount: user.employeeCount,
|
||||
haveSalesContact: user.haveSalesContact,
|
||||
recaptchaResponse: recaptchaResponse,
|
||||
};
|
||||
const response = await this.http.post(path, JSON.stringify(body));
|
||||
if (!response.ok) {
|
||||
switch (response.status) {
|
||||
case 400:
|
||||
throw new ErrorBadRequest('Validation of reCAPTCHA was unsuccessful');
|
||||
case 401:
|
||||
throw new ErrorUnauthorized('We are unable to create your account. This is an invite-only alpha, please join our waitlist to receive an invitation');
|
||||
case 409:
|
||||
|
11
web/satellite/src/api/errors/ErrorBadRequest.ts
Normal file
11
web/satellite/src/api/errors/ErrorBadRequest.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
/**
|
||||
* ErrorBadRequest is a custom error type for performing invalid operations.
|
||||
*/
|
||||
export class ErrorBadRequest extends Error {
|
||||
public constructor(message: string = 'bad request') {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import VueRecaptcha from 'vue-recaptcha';
|
||||
|
||||
import AddCouponCodeInput from '@/components/common/AddCouponCodeInput.vue';
|
||||
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
|
||||
@ -17,15 +18,18 @@ import BottomArrowIcon from '@/../static/images/common/lightBottomArrow.svg';
|
||||
import SelectedCheckIcon from '@/../static/images/common/selectedCheck.svg';
|
||||
import LogoIcon from '@/../static/images/dcs-logo.svg';
|
||||
import InfoIcon from '@/../static/images/info.svg';
|
||||
import ErrorIcon from '@/../static/images/register/ErrorInfo.svg';
|
||||
import RegisterGlobe from '@/../static/images/register/RegisterGlobe.svg';
|
||||
import RegisterGlobeSmall from '@/../static/images/register/RegisterGlobeSmall.svg';
|
||||
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { ErrorBadRequest } from '@/api/errors/ErrorBadRequest';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { PartneredSatellite } from '@/types/common';
|
||||
import { User } from '@/types/users';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { Validator } from '@/utils/validation';
|
||||
|
||||
@Component({
|
||||
@ -34,6 +38,7 @@ import { Validator } from '@/utils/validation';
|
||||
RegistrationSuccess,
|
||||
AuthIcon,
|
||||
BottomArrowIcon,
|
||||
ErrorIcon,
|
||||
SelectedCheckIcon,
|
||||
LogoIcon,
|
||||
InfoIcon,
|
||||
@ -42,6 +47,7 @@ import { Validator } from '@/utils/validation';
|
||||
SelectInput,
|
||||
RegisterGlobe,
|
||||
RegisterGlobeSmall,
|
||||
VueRecaptcha,
|
||||
},
|
||||
})
|
||||
export default class RegisterArea extends Vue {
|
||||
@ -71,8 +77,14 @@ export default class RegisterArea extends Vue {
|
||||
private isProfessional: boolean = false;
|
||||
private haveSalesContact: boolean = false;
|
||||
|
||||
private recaptchaError: boolean = false;
|
||||
private recaptchaResponseToken: string = '';
|
||||
|
||||
private readonly auth: AuthHttpApi = new AuthHttpApi();
|
||||
|
||||
private readonly recaptchaEnabled: boolean = MetaUtils.getMetaContent('recaptcha-enabled') === 'true';
|
||||
private readonly recaptchaSiteKey: string = MetaUtils.getMetaContent('recaptcha-site-key');
|
||||
|
||||
public isPasswordStrengthShown: boolean = false;
|
||||
|
||||
// tardigrade logic
|
||||
@ -269,6 +281,21 @@ export default class RegisterArea extends Vue {
|
||||
this.isProfessional = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles reCAPTCHA verification response.
|
||||
*/
|
||||
public onRecaptchaVerified(response: string): void {
|
||||
this.recaptchaResponseToken = response;
|
||||
this.recaptchaError = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles reCAPTCHA error and expiry.
|
||||
*/
|
||||
public onRecaptchaError(): void {
|
||||
this.recaptchaResponseToken = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates input values to satisfy expected rules.
|
||||
*/
|
||||
@ -325,6 +352,11 @@ export default class RegisterArea extends Vue {
|
||||
isNoErrors = false;
|
||||
}
|
||||
|
||||
if (this.recaptchaEnabled && !this.recaptchaResponseToken) {
|
||||
this.recaptchaError = true;
|
||||
isNoErrors = false;
|
||||
}
|
||||
|
||||
return isNoErrors;
|
||||
}
|
||||
|
||||
@ -336,11 +368,14 @@ export default class RegisterArea extends Vue {
|
||||
this.user.haveSalesContact = this.haveSalesContact;
|
||||
|
||||
try {
|
||||
this.userId = await this.auth.register(this.user, this.secret);
|
||||
this.userId = await this.auth.register(this.user, this.secret, this.recaptchaResponseToken);
|
||||
LocalData.setUserId(this.userId);
|
||||
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_REGISTRATION);
|
||||
} catch (error) {
|
||||
if (error instanceof ErrorBadRequest) {
|
||||
(this.$refs.recaptcha as VueRecaptcha).reset();
|
||||
}
|
||||
await this.$notify.error(error.message);
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
@ -176,6 +176,20 @@
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div class="register-area__input-area__container__recaptcha-wrapper" v-if="recaptchaEnabled">
|
||||
<div class="register-area__input-area__container__recaptcha-wrapper__label-container" v-if="recaptchaError">
|
||||
<ErrorIcon/>
|
||||
<p class="register-area__input-area__container__recaptcha-wrapper__label-container__error">reCAPTCHA is required</p>
|
||||
</div>
|
||||
<vue-recaptcha
|
||||
:sitekey="recaptchaSiteKey"
|
||||
loadRecaptchaScript="true"
|
||||
@verify="onRecaptchaVerified"
|
||||
@expired="onRecaptchaError"
|
||||
@error="onRecaptchaError"
|
||||
ref="recaptcha">
|
||||
</vue-recaptcha>
|
||||
</div>
|
||||
<p class="register-area__input-area__container__button" @click.prevent="onCreateClick">Sign Up</p>
|
||||
</div>
|
||||
|
||||
|
@ -42,7 +42,7 @@ h1 {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
min-height: 655px;
|
||||
min-height: 733px;
|
||||
width: 75%;
|
||||
margin-top: 50px;
|
||||
padding: 70px 90px 40px 90px;
|
||||
@ -267,6 +267,24 @@ h1 {
|
||||
background-color: #0059d0;
|
||||
}
|
||||
}
|
||||
|
||||
&__recaptcha-wrapper {
|
||||
margin-top: 30px;
|
||||
|
||||
&__label-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 8px;
|
||||
flex-direction: row;
|
||||
|
||||
&__error {
|
||||
font-size: 16px;
|
||||
margin-left: 10px;
|
||||
color: #ff5560;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__container.professional-container {
|
||||
|
Loading…
Reference in New Issue
Block a user