From ded7f6e2eb9d9a0d4eae749ff7f29b1a783aebf3 Mon Sep 17 00:00:00 2001 From: Nikolai Siedov <46809683+Qweder93@users.noreply.github.com> Date: Fri, 22 Nov 2019 19:03:15 +0200 Subject: [PATCH] web/satellite: registration/welcome message fixed, usage-report url fixed, storj-sim fixed (#3622) --- cmd/storj-sim/console.go | 100 +++++--- cmd/storj-sim/network.go | 13 +- .../console/consoleweb/consoleql/mutation.go | 152 ------------- .../consoleweb/consoleql/mutation_test.go | 214 ------------------ .../console/consoleweb/consoleql/query.go | 159 ------------- .../consoleweb/consoleql/query_test.go | 131 ----------- .../console/consoleweb/consoleql/user.go | 37 --- .../console/consoleweb/consoleql/utils.go | 27 --- satellite/console/consoleweb/server.go | 2 +- web/satellite/src/api/users.ts | 68 ------ .../common/RegistrationSuccessPopup.vue | 2 +- .../common/registrationSuccessPopup.html | 5 +- .../src/components/project/UsageReport.vue | 2 +- web/satellite/static/emails/Welcome.html | 7 +- web/satellite/tests/unit/store/users.spec.ts | 14 +- 15 files changed, 88 insertions(+), 845 deletions(-) delete mode 100644 satellite/console/consoleweb/consoleql/utils.go delete mode 100644 web/satellite/src/api/users.ts diff --git a/cmd/storj-sim/console.go b/cmd/storj-sim/console.go index aa7e85fbf..6747a3398 100644 --- a/cmd/storj-sim/console.go +++ b/cmd/storj-sim/console.go @@ -80,7 +80,7 @@ func generateActivationKey(userID uuid.UUID, email string, createdAt time.Time) return token.String(), nil } -func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activationAddress, address string) error { +func addExampleProjectWithKey(key *string, endpoints map[string]string) error { client := http.Client{} var createTokenResponse struct { @@ -90,7 +90,7 @@ func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activ { request, err := http.NewRequest( http.MethodGet, - createRegistrationTokenAddress, + endpoints["regtoken"], nil) if err != nil { return err @@ -130,34 +130,52 @@ func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activ } } { - createUserQuery := fmt.Sprintf( - "mutation {createUser(input:{email:\"%s\",password:\"%s\",fullName:\"%s\", shortName:\"\", partnerId: \"\"}, secret:\"%s\" ){id,email,createdAt}}", - "alice@mail.test", - "123a123", - "Alice", - createTokenResponse.Secret) + var registerData struct { + FullName string `json:"fullName"` + ShortName string `json:"shortName"` + Email string `json:"email"` + Password string `json:"password"` + SecretInput string `json:"secret"` + } + + registerData.FullName = "Alice" + registerData.Email = "alice@mail.test" + registerData.Password = "123a123" + registerData.ShortName = "al" + registerData.SecretInput = createTokenResponse.Secret + + res, _ := json.Marshal(registerData) request, err := http.NewRequest( http.MethodPost, - address, - bytes.NewReader([]byte(createUserQuery))) + endpoints["register"], + bytes.NewReader(res)) + if err != nil { + return err + } + request.Header.Add("Content-Type", "application/json") + + response, err := client.Do(request) if err != nil { return err } - request.Header.Add("Content-Type", "application/graphql") + defer func() { err = errs.Combine(err, response.Body.Close()) }() - err = graphqlDo(&client, request, &user) + if response.StatusCode != http.StatusOK { + return err + } + + err = json.NewDecoder(response.Body).Decode(&user.CreateUser.ID) if err != nil { return err } + + user.CreateUser.Email = registerData.Email + user.CreateUser.CreatedAt = time.Now() } - var token struct { - Token struct { - Token string - } - } + var token string { userID, err := uuid.Parse(user.CreateUser.ID) if err != nil { @@ -171,7 +189,7 @@ func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activ request, err := http.NewRequest( http.MethodGet, - activationAddress+activationToken, + endpoints["activation"]+activationToken, nil) if err != nil { return err @@ -182,28 +200,40 @@ func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activ return err } - err = resp.Body.Close() - if err != nil { - return err + defer func() { err = errs.Combine(err, resp.Body.Close()) }() + + var authToken struct { + Email string `json:"email"` + Password string `json:"password"` } - tokenQuery := fmt.Sprintf( - "query {token(email:\"%s\",password:\"%s\"){token}}", - "alice@mail.test", - "123a123") + authToken.Email = "alice@mail.test" + authToken.Password = "123a123" + + res, _ := json.Marshal(authToken) request, err = http.NewRequest( http.MethodPost, - address, - bytes.NewReader([]byte(tokenQuery))) - + endpoints["token"], + bytes.NewReader(res)) if err != nil { return err } - request.Header.Add("Content-Type", "application/graphql") + request.Header.Add("Content-Type", "application/json") - err = graphqlDo(&client, request, &token) + response, err := client.Do(request) + if err != nil { + return err + } + + defer func() { err = errs.Combine(err, response.Body.Close()) }() + + if response.StatusCode != http.StatusOK { + return err + } + + err = json.NewDecoder(response.Body).Decode(&token) if err != nil { return err } @@ -222,15 +252,14 @@ func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activ request, err := http.NewRequest( http.MethodPost, - address, + endpoints["graphql"], bytes.NewReader([]byte(createProjectQuery))) - if err != nil { return err } request.Header.Add("Content-Type", "application/graphql") - request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token.Token.Token)) + request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) if err := graphqlDo(&client, request, &createProject); err != nil { return err @@ -251,15 +280,14 @@ func addExampleProjectWithKey(key *string, createRegistrationTokenAddress, activ request, err := http.NewRequest( http.MethodPost, - address, + endpoints["graphql"], bytes.NewReader([]byte(createAPIKeyQuery))) - if err != nil { return err } request.Header.Add("Content-Type", "application/graphql") - request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token.Token.Token)) + request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) if err := graphqlDo(&client, request, &createAPIKey); err != nil { return err diff --git a/cmd/storj-sim/network.go b/cmd/storj-sim/network.go index abb081848..af37f5b6e 100644 --- a/cmd/storj-sim/network.go +++ b/cmd/storj-sim/network.go @@ -456,15 +456,20 @@ func newNetwork(flags *Flags) (*Processes, error) { } host := "http://" + consoleAddress - createRegistrationTokenAddress := host + "/registrationToken/?projectsLimit=1" - consoleActivationAddress := host + "/activation/?token=" - consoleAPIAddress := host + "/api/v0/graphql" + + endpoints := map[string]string{ + "regtoken": host + "/registrationToken/?projectsLimit=1", + "register": host + "/api/v0/auth/register", + "activation": host + "/activation/?token=", + "token": host + "/api/v0/auth/token", + "graphql": host + "/api/v0/graphql", + } // wait for console server to start time.Sleep(3 * time.Second) var apiKey string - if err := addExampleProjectWithKey(&apiKey, createRegistrationTokenAddress, consoleActivationAddress, consoleAPIAddress); err != nil { + if err := addExampleProjectWithKey(&apiKey, endpoints); err != nil { return err } diff --git a/satellite/console/consoleweb/consoleql/mutation.go b/satellite/console/consoleweb/consoleql/mutation.go index 9169c92a9..b927b2156 100644 --- a/satellite/console/consoleweb/consoleql/mutation.go +++ b/satellite/console/consoleweb/consoleql/mutation.go @@ -17,14 +17,6 @@ const ( // Mutation is graphql request that modifies data Mutation = "mutation" - // CreateUserMutation is a user creation mutation name - CreateUserMutation = "createUser" - // UpdateAccountMutation is a mutation name for account updating - UpdateAccountMutation = "updateAccount" - // DeleteAccountMutation is a mutation name for account deletion - DeleteAccountMutation = "deleteAccount" - // ChangePasswordMutation is a mutation name for password changing - ChangePasswordMutation = "changePassword" // CreateProjectMutation is a mutation name for project creation CreateProjectMutation = "createProject" // DeleteProjectMutation is a mutation name for project deletion @@ -66,150 +58,6 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse return graphql.NewObject(graphql.ObjectConfig{ Name: Mutation, Fields: graphql.Fields{ - CreateUserMutation: &graphql.Field{ - Type: types.user, - Args: graphql.FieldConfigArgument{ - InputArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.userInput), - }, - Secret: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - ReferrerUserID: &graphql.ArgumentConfig{ - Type: graphql.String, - }, - }, - // creates user and company from input params and returns userID if succeed - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - input, _ := p.Args[InputArg].(map[string]interface{}) - secretInput, _ := p.Args[Secret].(string) - refUserID, _ := p.Args[ReferrerUserID].(string) - - createUser := fromMapCreateUser(input) - - secret, err := console.RegistrationSecretFromBase64(secretInput) - if err != nil { - log.Error("register: failed to create account", - zap.Error(err)) - log.Debug("register: ", zap.String("rawSecret", secretInput)) - - return nil, err - } - - user, err := service.CreateUser(p.Context, createUser, secret, refUserID) - if err != nil { - log.Error("register: failed to create account", - zap.Error(err)) - log.Debug("register: ", zap.String("rawSecret", secretInput)) - - return nil, HandleError(err) - } - - token, err := service.GenerateActivationToken(p.Context, user.ID, user.Email) - if err != nil { - log.Error("register: failed to generate activation token", - zap.Stringer("id", user.ID), - zap.String("email", user.Email), - zap.Error(err)) - - return user, HandleError(err) - } - - rootObject := p.Info.RootValue.(map[string]interface{}) - origin := rootObject["origin"].(string) - link := origin + rootObject[ActivationPath].(string) + token - userName := user.ShortName - if user.ShortName == "" { - userName = user.FullName - } - - mailService.SendRenderedAsync( - p.Context, - []post.Address{{Address: user.Email, Name: userName}}, - &AccountActivationEmail{ - Origin: origin, - ActivationLink: link, - }, - ) - - return user, nil - }, - }, - UpdateAccountMutation: &graphql.Field{ - Type: types.user, - Args: graphql.FieldConfigArgument{ - InputArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.userInput), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - input, _ := p.Args[InputArg].(map[string]interface{}) - - auth, err := console.GetAuth(p.Context) - if err != nil { - return nil, HandleError(err) - } - - info := fillUserInfo(&auth.User, input) - - err = service.UpdateAccount(p.Context, info.FullName, info.ShortName) - if err != nil { - return nil, HandleError(err) - } - - return auth.User, nil - }, - }, - ChangePasswordMutation: &graphql.Field{ - Type: types.user, - Args: graphql.FieldConfigArgument{ - FieldPassword: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - FieldNewPassword: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - pass, _ := p.Args[FieldPassword].(string) - newPass, _ := p.Args[FieldNewPassword].(string) - - auth, err := console.GetAuth(p.Context) - if err != nil { - return nil, HandleError(err) - } - - err = service.ChangePassword(p.Context, pass, newPass) - if err != nil { - return nil, HandleError(err) - } - - return auth.User, nil - }, - }, - DeleteAccountMutation: &graphql.Field{ - Type: types.user, - Args: graphql.FieldConfigArgument{ - FieldPassword: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - password, _ := p.Args[FieldPassword].(string) - - auth, err := console.GetAuth(p.Context) - if err != nil { - return nil, HandleError(err) - } - - err = service.DeleteAccount(p.Context, password) - if err != nil { - return nil, HandleError(err) - } - - return auth.User, nil - }, - }, // creates project from input params CreateProjectMutation: &graphql.Field{ Type: types.project, diff --git a/satellite/console/consoleweb/consoleql/mutation_test.go b/satellite/console/consoleweb/consoleql/mutation_test.go index 8bd874533..b5acf2648 100644 --- a/satellite/console/consoleweb/consoleql/mutation_test.go +++ b/satellite/console/consoleweb/consoleql/mutation_test.go @@ -4,7 +4,6 @@ package consoleql_test import ( - "bytes" "context" "fmt" "testing" @@ -134,105 +133,6 @@ func TestGrapqhlMutation(t *testing.T) { authCtx := console.WithAuth(ctx, sauth) - t.Run("Create user mutation with partner id", func(t *testing.T) { - newUser := console.CreateUser{ - FullName: "Green Mickey", - ShortName: "Green", - Email: "u1@mail.test", - PartnerID: "120bf202-8252-437e-ac12-0e364bee852e", - Password: "123a123", - } - - require.NoError(t, err) - - query := fmt.Sprintf( - "mutation {createUser(input:{email:\"%s\",password:\"%s\", fullName:\"%s\", shortName:\"%s\", partnerId:\"%s\"}, secret: \"\", referrerUserId: \"\"){id,shortName,fullName,email,partnerId,createdAt}}", - newUser.Email, - newUser.Password, - newUser.FullName, - newUser.ShortName, - newUser.PartnerID, - ) - - result := graphql.Do(graphql.Params{ - Schema: schema, - Context: ctx, - RequestString: query, - RootObject: rootObject, - }) - - for _, err := range result.Errors { - if rewards.ErrPartnerNotExist.Has(err) { - assert.Error(t, err) - } - assert.NoError(t, err) - } - require.False(t, result.HasErrors()) - - data := result.Data.(map[string]interface{}) - usrData := data[consoleql.CreateUserMutation].(map[string]interface{}) - idStr := usrData["id"].(string) - - uID, err := uuid.Parse(idStr) - assert.NoError(t, err) - - user, err := service.GetUser(authCtx, *uID) - assert.NoError(t, err) - - assert.Equal(t, newUser.FullName, user.FullName) - assert.Equal(t, newUser.ShortName, user.ShortName) - assert.Equal(t, newUser.PartnerID, user.PartnerID.String()) - }) - - t.Run("Create user mutation without partner id", func(t *testing.T) { - newUser := console.CreateUser{ - FullName: "Red Mickey", - ShortName: "Red", - Email: "u2@mail.test", - PartnerID: "", - Password: "123a123", - } - - require.NoError(t, err) - - query := fmt.Sprintf( - "mutation {createUser(input:{email:\"%s\",password:\"%s\", fullName:\"%s\", shortName:\"%s\", partnerId:\"\"}, secret: \"%s\", referrerUserId: \"\"){id,shortName,fullName,email,partnerId,createdAt}}", - newUser.Email, - newUser.Password, - newUser.FullName, - newUser.ShortName, - regToken.Secret, - ) - - result := graphql.Do(graphql.Params{ - Schema: schema, - Context: ctx, - RequestString: query, - RootObject: rootObject, - }) - - for _, err := range result.Errors { - if rewards.ErrPartnerNotExist.Has(err) { - assert.Error(t, err) - } - assert.NoError(t, err) - } - require.False(t, result.HasErrors()) - - data := result.Data.(map[string]interface{}) - usrData := data[consoleql.CreateUserMutation].(map[string]interface{}) - idStr := usrData["id"].(string) - - uID, err := uuid.Parse(idStr) - assert.NoError(t, err) - - user, err := service.GetUser(authCtx, *uID) - assert.NoError(t, err) - - assert.Equal(t, newUser.FullName, user.FullName) - assert.Equal(t, newUser.ShortName, user.ShortName) - }) - testQuery := func(t *testing.T, query string) interface{} { result := graphql.Do(graphql.Params{ Schema: schema, @@ -249,103 +149,6 @@ func TestGrapqhlMutation(t *testing.T) { return result.Data } - t.Run("Update account mutation fullName only", func(t *testing.T) { - fullName := "George" - query := fmt.Sprintf( - "mutation {updateAccount(input:{fullName:\"%s\"}){id,email,fullName,shortName,createdAt}}", - fullName, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.UpdateAccountMutation].(map[string]interface{}) - - assert.Equal(t, rootUser.ID.String(), user[consoleql.FieldID]) - assert.Equal(t, rootUser.Email, user[consoleql.FieldEmail]) - assert.Equal(t, fullName, user[consoleql.FieldFullName]) - assert.Equal(t, rootUser.ShortName, user[consoleql.FieldShortName]) - }) - - t.Run("Update account mutation shortName only", func(t *testing.T) { - shortName := "Yellow" - query := fmt.Sprintf( - "mutation {updateAccount(input:{shortName:\"%s\"}){id,email,fullName,shortName,createdAt}}", - shortName, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.UpdateAccountMutation].(map[string]interface{}) - - assert.Equal(t, rootUser.ID.String(), user[consoleql.FieldID]) - assert.Equal(t, rootUser.Email, user[consoleql.FieldEmail]) - assert.Equal(t, rootUser.FullName, user[consoleql.FieldFullName]) - assert.Equal(t, shortName, user[consoleql.FieldShortName]) - }) - - t.Run("Update account mutation all info", func(t *testing.T) { - fullName := "Fill Goal" - shortName := "Goal" - - query := fmt.Sprintf( - "mutation {updateAccount(input:{,fullName:\"%s\",shortName:\"%s\"}){id,fullName,shortName,createdAt}}", - fullName, - shortName, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.UpdateAccountMutation].(map[string]interface{}) - - assert.Equal(t, rootUser.ID.String(), user[consoleql.FieldID]) - assert.Equal(t, fullName, user[consoleql.FieldFullName]) - assert.Equal(t, shortName, user[consoleql.FieldShortName]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(user[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, rootUser.CreatedAt.Equal(createdAt)) - }) - - t.Run("Change password mutation", func(t *testing.T) { - newPassword := "145a145a" - - query := fmt.Sprintf( - "mutation {changePassword(password:\"%s\",newPassword:\"%s\"){id,email,fullName,shortName,createdAt}}", - createUser.Password, - newPassword, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.ChangePasswordMutation].(map[string]interface{}) - - assert.Equal(t, rootUser.ID.String(), user[consoleql.FieldID]) - assert.Equal(t, rootUser.Email, user[consoleql.FieldEmail]) - assert.Equal(t, rootUser.FullName, user[consoleql.FieldFullName]) - assert.Equal(t, rootUser.ShortName, user[consoleql.FieldShortName]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(user[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, rootUser.CreatedAt.Equal(createdAt)) - - oldHash := rootUser.PasswordHash - - rootUser, err = service.GetUser(authCtx, rootUser.ID) - require.NoError(t, err) - - assert.False(t, bytes.Equal(oldHash, rootUser.PasswordHash)) - - createUser.Password = newPassword - }) - token, err = service.Token(ctx, rootUser.Email, createUser.Password) require.NoError(t, err) @@ -562,22 +365,5 @@ func TestGrapqhlMutation(t *testing.T) { _, err := service.GetProject(authCtx, project.ID) assert.Error(t, err) }) - - t.Run("Delete account mutation", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {deleteAccount(password:\"%s\"){id}}", - createUser.Password, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.DeleteAccountMutation].(map[string]interface{}) - - assert.Equal(t, rootUser.ID.String(), user[consoleql.FieldID]) - - _, err := service.GetUser(authCtx, rootUser.ID) - assert.Error(t, err) - }) }) } diff --git a/satellite/console/consoleweb/consoleql/query.go b/satellite/console/consoleweb/consoleql/query.go index 066482778..6888ec050 100644 --- a/satellite/console/consoleweb/consoleql/query.go +++ b/satellite/console/consoleweb/consoleql/query.go @@ -4,12 +4,9 @@ package consoleql import ( - "errors" - "github.com/graphql-go/graphql" "github.com/skyrings/skyring-common/tools/uuid" - "storj.io/storj/private/post" "storj.io/storj/satellite/console" "storj.io/storj/satellite/mailservice" "storj.io/storj/satellite/rewards" @@ -18,8 +15,6 @@ import ( const ( // Query is immutable graphql request Query = "query" - // UserQuery is a query name for user - UserQuery = "user" // ProjectQuery is a query name for project ProjectQuery = "project" // MyProjectsQuery is a query name for projects related to account @@ -28,12 +23,6 @@ const ( ActiveRewardQuery = "activeReward" // CreditUsageQuery is a query name for credit usage related to an user CreditUsageQuery = "creditUsage" - // TokenQuery is a query name for token - TokenQuery = "token" - // ForgotPasswordQuery is a query name for password recovery request - ForgotPasswordQuery = "forgotPassword" - // ResendAccountActivationEmailQuery is a query name for password recovery request - ResendAccountActivationEmailQuery = "resendAccountActivationEmail" ) // rootQuery creates query for graphql populated by AccountsClient @@ -41,31 +30,6 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types return graphql.NewObject(graphql.ObjectConfig{ Name: Query, Fields: graphql.Fields{ - UserQuery: &graphql.Field{ - Type: types.user, - Args: graphql.FieldConfigArgument{ - FieldID: &graphql.ArgumentConfig{ - Type: graphql.String, - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - id, err := uuidIDAuthFallback(p, FieldID) - if err != nil { - return nil, HandleError(err) - } - _, err = console.GetAuth(p.Context) - if err != nil { - return nil, HandleError(err) - } - - user, err := service.GetUser(p.Context, *id) - if err != nil { - return nil, HandleError(err) - } - - return user, nil - }, - }, ProjectQuery: &graphql.Field{ Type: types.project, Args: graphql.FieldConfigArgument{ @@ -129,129 +93,6 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types return usage, nil }, }, - TokenQuery: &graphql.Field{ - Type: types.token, - Args: graphql.FieldConfigArgument{ - FieldEmail: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - FieldPassword: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - email, _ := p.Args[FieldEmail].(string) - pass, _ := p.Args[FieldPassword].(string) - - token, err := service.Token(p.Context, email, pass) - if err != nil { - return nil, HandleError(err) - } - - return tokenWrapper{Token: token}, nil - }, - }, - ForgotPasswordQuery: &graphql.Field{ - Type: graphql.Boolean, - Args: graphql.FieldConfigArgument{ - FieldEmail: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - email, _ := p.Args[FieldEmail].(string) - - user, err := service.GetUserByEmail(p.Context, email) - if err != nil { - return true, nil - } - - recoveryToken, err := service.GeneratePasswordRecoveryToken(p.Context, user.ID) - if err != nil { - return false, errors.New("failed to generate password recovery token") - } - - rootObject := p.Info.RootValue.(map[string]interface{}) - origin := rootObject["origin"].(string) - passwordRecoveryLink := origin + rootObject[PasswordRecoveryPath].(string) + recoveryToken - cancelPasswordRecoveryLink := origin + rootObject[CancelPasswordRecoveryPath].(string) + recoveryToken - userName := user.ShortName - if user.ShortName == "" { - userName = user.FullName - } - - contactInfoURL := rootObject[ContactInfoURL].(string) - letUsKnowURL := rootObject[LetUsKnowURL].(string) - termsAndConditionsURL := rootObject[TermsAndConditionsURL].(string) - - mailService.SendRenderedAsync( - p.Context, - []post.Address{{Address: user.Email, Name: userName}}, - &ForgotPasswordEmail{ - Origin: origin, - ResetLink: passwordRecoveryLink, - CancelPasswordRecoveryLink: cancelPasswordRecoveryLink, - UserName: userName, - LetUsKnowURL: letUsKnowURL, - TermsAndConditionsURL: termsAndConditionsURL, - ContactInfoURL: contactInfoURL, - }, - ) - - return true, nil - }, - }, - ResendAccountActivationEmailQuery: &graphql.Field{ - Type: graphql.Boolean, - Args: graphql.FieldConfigArgument{ - FieldID: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - id, _ := p.Args[FieldID].(string) - - userID, err := uuid.Parse(id) - if err != nil { - return false, err - } - - user, err := service.GetUser(p.Context, *userID) - if err != nil { - return false, HandleError(err) - } - - token, err := service.GenerateActivationToken(p.Context, user.ID, user.Email) - if err != nil { - return false, HandleError(err) - } - - rootObject := p.Info.RootValue.(map[string]interface{}) - origin := rootObject["origin"].(string) - link := origin + rootObject[ActivationPath].(string) + token - userName := user.ShortName - if user.ShortName == "" { - userName = user.FullName - } - - contactInfoURL := rootObject[ContactInfoURL].(string) - termsAndConditionsURL := rootObject[TermsAndConditionsURL].(string) - - // TODO: think of a better solution - mailService.SendRenderedAsync( - p.Context, - []post.Address{{Address: user.Email, Name: userName}}, - &AccountActivationEmail{ - Origin: origin, - ActivationLink: link, - TermsAndConditionsURL: termsAndConditionsURL, - ContactInfoURL: contactInfoURL, - }, - ) - - return true, nil - }, - }, }, }) } diff --git a/satellite/console/consoleweb/consoleql/query_test.go b/satellite/console/consoleweb/consoleql/query_test.go index 1113adbbe..8711c3142 100644 --- a/satellite/console/consoleweb/consoleql/query_test.go +++ b/satellite/console/consoleweb/consoleql/query_test.go @@ -128,46 +128,6 @@ func TestGraphqlQuery(t *testing.T) { return result.Data } - t.Run("User query", func(t *testing.T) { - testUser := func(t *testing.T, actual map[string]interface{}, expected *console.User) { - assert.Equal(t, expected.ID.String(), actual[consoleql.FieldID]) - assert.Equal(t, expected.Email, actual[consoleql.FieldEmail]) - assert.Equal(t, expected.FullName, actual[consoleql.FieldFullName]) - assert.Equal(t, expected.ShortName, actual[consoleql.FieldShortName]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(actual[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, expected.CreatedAt.Equal(createdAt)) - } - - t.Run("With ID", func(t *testing.T) { - query := fmt.Sprintf( - "query {user(id:\"%s\"){id,email,fullName,shortName,createdAt}}", - rootUser.ID.String(), - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.UserQuery].(map[string]interface{}) - - testUser(t, user, rootUser) - }) - - t.Run("With AuthFallback", func(t *testing.T) { - query := "query {user{id,email,fullName,shortName,createdAt}}" - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - user := data[consoleql.UserQuery].(map[string]interface{}) - - testUser(t, user, rootUser) - }) - }) - createdProject, err := service.CreateProject(authCtx, console.ProjectInfo{ Name: "TestProject", }) @@ -408,96 +368,5 @@ func TestGraphqlQuery(t *testing.T) { assert.True(t, foundProj1) assert.True(t, foundProj2) }) - - t.Run("Token query", func(t *testing.T) { - query := fmt.Sprintf( - "query {token(email: \"%s\", password: \"%s\"){token,user{id,email,fullName,shortName,createdAt}}}", - createUser.Email, - createUser.Password, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - queryToken := data[consoleql.TokenQuery].(map[string]interface{}) - - token := queryToken[consoleql.TokenType].(string) - user := queryToken[consoleql.UserType].(map[string]interface{}) - - tauth, err := service.Authorize(auth.WithAPIKey(ctx, []byte(token))) - require.NoError(t, err) - - assert.Equal(t, rootUser.ID, tauth.User.ID) - assert.Equal(t, rootUser.ID.String(), user[consoleql.FieldID]) - assert.Equal(t, rootUser.Email, user[consoleql.FieldEmail]) - assert.Equal(t, rootUser.FullName, user[consoleql.FieldFullName]) - assert.Equal(t, rootUser.ShortName, user[consoleql.FieldShortName]) - - createdAt := time.Time{} - err = createdAt.UnmarshalText([]byte(user[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, rootUser.CreatedAt.Equal(createdAt)) - }) - - t.Run("PasswordReset query", func(t *testing.T) { - regToken, err := service.CreateRegToken(ctx, 2) - require.NoError(t, err) - user, err := service.CreateUser(authCtx, console.CreateUser{ - FullName: "Example User", - ShortName: "Example", - Email: "user@mail.test", - Password: "123a123", - }, regToken.Secret, refUserID) - - require.NoError(t, err) - - t.Run("Activation", func(t *testing.T) { - activationToken, err := service.GenerateActivationToken( - ctx, - user.ID, - "user@mail.test", - ) - require.NoError(t, err) - - err = service.ActivateAccount(ctx, activationToken) - require.NoError(t, err) - user.Email = "user@mail.test" - - }) - - rootObject[consoleql.PasswordRecoveryPath] = "?token=" - rootObject[consoleql.CancelPasswordRecoveryPath] = "?token=" - query := fmt.Sprintf("query {forgotPassword(email: \"%s\")}", user.Email) - - result := testQuery(t, query) - assert.NotNil(t, result) - data := result.(map[string]interface{}) - - ok := data[consoleql.ForgotPasswordQuery].(bool) - assert.True(t, ok) - }) - - t.Run("Resend activation email query", func(t *testing.T) { - regToken, err := service.CreateRegToken(ctx, 2) - require.NoError(t, err) - user, err := service.CreateUser(authCtx, console.CreateUser{ - FullName: "Example User", - ShortName: "Example", - Email: "user1@mail.test", - Password: "123a123", - }, regToken.Secret, refUserID) - - require.NoError(t, err) - - query := fmt.Sprintf("query {resendAccountActivationEmail(id: \"%s\")}", user.ID) - - result := testQuery(t, query) - assert.NotNil(t, result) - data := result.(map[string]interface{}) - - ok := data[consoleql.ResendAccountActivationEmailQuery].(bool) - assert.True(t, ok) - }) }) } diff --git a/satellite/console/consoleweb/consoleql/user.go b/satellite/console/consoleweb/consoleql/user.go index 6398c4502..c1b3348c6 100644 --- a/satellite/console/consoleweb/consoleql/user.go +++ b/satellite/console/consoleweb/consoleql/user.go @@ -5,8 +5,6 @@ package consoleql import ( "github.com/graphql-go/graphql" - - "storj.io/storj/satellite/console" ) const ( @@ -86,38 +84,3 @@ func graphqlUserInput() *graphql.InputObject { }, }) } - -func fromMapCreateUser(args map[string]interface{}) (user console.CreateUser) { - user.Email, _ = args[FieldEmail].(string) - user.FullName, _ = args[FieldFullName].(string) - user.ShortName, _ = args[FieldShortName].(string) - user.Password, _ = args[FieldPassword].(string) - user.PartnerID, _ = args[FieldPartnerID].(string) - return -} - -// fillUserInfo fills satellite.UserInfo from satellite.User and input args -func fillUserInfo(user *console.User, args map[string]interface{}) console.UserInfo { - info := console.UserInfo{ - FullName: user.FullName, - ShortName: user.ShortName, - } - - for fieldName, fieldValue := range args { - value, ok := fieldValue.(string) - if !ok { - continue - } - - switch fieldName { - case FieldFullName: - info.FullName = value - user.FullName = value - case FieldShortName: - info.ShortName = value - user.ShortName = value - } - } - - return info -} diff --git a/satellite/console/consoleweb/consoleql/utils.go b/satellite/console/consoleweb/consoleql/utils.go deleted file mode 100644 index 64746035d..000000000 --- a/satellite/console/consoleweb/consoleql/utils.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" - "github.com/skyrings/skyring-common/tools/uuid" - - "storj.io/storj/satellite/console" -) - -// uuidIDAuthFallback returns auth user id if no id argument provided -func uuidIDAuthFallback(p graphql.ResolveParams, field string) (*uuid.UUID, error) { - // if client passed id - parse it and return - if idStr, ok := p.Args[field].(string); ok { - return uuid.Parse(idStr) - } - - // else get id of authorized user - auth, err := console.GetAuth(p.Context) - if err != nil { - return nil, err - } - - return &auth.User.ID, nil -} diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index 9cf62c297..c4ea48e9d 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -154,7 +154,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, mail router.HandleFunc("/activation/", server.accountActivationHandler) router.HandleFunc("/password-recovery/", server.passwordRecoveryHandler) router.HandleFunc("/cancel-password-recovery/", server.cancelPasswordRecoveryHandler) - router.HandleFunc("/usage-report/", server.bucketUsageReportHandler) + router.HandleFunc("/usage-report", server.bucketUsageReportHandler) router.PathPrefix("/static/").Handler(server.gzipMiddleware(http.StripPrefix("/static", fs))) router.PathPrefix("/").Handler(http.HandlerFunc(server.appHandler)) } diff --git a/web/satellite/src/api/users.ts b/web/satellite/src/api/users.ts deleted file mode 100644 index d7925ebd3..000000000 --- a/web/satellite/src/api/users.ts +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -import { BaseGql } from '@/api/baseGql'; -import { UpdatedUser, User, UsersApi } from '@/types/users'; - -/** - * UsersApiGql is a graphql implementation of Users API. - * Exposes all user-related functionality - */ -export class UsersApiGql extends BaseGql implements UsersApi { - - /** - * Updates users full name and short name - * - * @param user - contains information that should be updated - * @throws Error - */ - public async update(user: UpdatedUser): Promise { - const query: string = - `mutation ($fullName: String!, $shortName: String!) { - updateAccount ( - input: { - fullName: $fullName, - shortName: $shortName - } - ) { - email, - fullName, - shortName - } - }`; - - const variables: any = { - fullName: user.fullName, - shortName: user.shortName, - }; - - await this.mutate(query, variables); - } - - /** - * Fetch user - * - * @returns User - * @throws Error - */ - public async get(): Promise { - const query = - ` query { - user { - id, - fullName, - shortName, - email, - partnerId, - } - }`; - - const response = await this.query(query); - - return this.fromJson(response.data.user); - } - - private fromJson(user): User { - return new User(user.id, user.fullName, user.shortName, user.email, user.partnerId); - } -} diff --git a/web/satellite/src/components/common/RegistrationSuccessPopup.vue b/web/satellite/src/components/common/RegistrationSuccessPopup.vue index 1323d8683..647f440fd 100644 --- a/web/satellite/src/components/common/RegistrationSuccessPopup.vue +++ b/web/satellite/src/components/common/RegistrationSuccessPopup.vue @@ -125,7 +125,7 @@ export default class RegistrationSuccessPopup extends Vue { font-size: 32px; line-height: 39px; color: #384b65; - margin: 0; + margin: 0 0 25px 0; user-select: none; } diff --git a/web/satellite/src/components/common/registrationSuccessPopup.html b/web/satellite/src/components/common/registrationSuccessPopup.html index 305be2c03..8ecdcad52 100644 --- a/web/satellite/src/components/common/registrationSuccessPopup.html +++ b/web/satellite/src/components/common/registrationSuccessPopup.html @@ -7,9 +7,8 @@
-

Verify Your Email

-

You have almost finished registering your account on the Tardigrade Satellite. Only one step left. Please check your inbox for a verification email.

-

Didn’t receive a verification email? {{timeToEnableResendEmailButton}}

+

Check your inbox for your verification email

+

Didn’t receive a verification email? {{timeToEnableResendEmailButton}}

-

Thank you for creating a Satellite account.


Now you need to verify your account 


+

Thank you for creating a Satellite account.


Now you need to verify your account. 


@@ -511,9 +511,8 @@
-

After verification you will have access to create new Projects
-and setup your API keys within a team and project

-
+

After verification you will have access to create new Projects
and setup your API keys within a team and project.

+
diff --git a/web/satellite/tests/unit/store/users.spec.ts b/web/satellite/tests/unit/store/users.spec.ts index 5bbf10c5e..98d6a01ab 100644 --- a/web/satellite/tests/unit/store/users.spec.ts +++ b/web/satellite/tests/unit/store/users.spec.ts @@ -3,14 +3,14 @@ import Vuex from 'vuex'; -import { UsersApiGql } from '@/api/users'; +import { AuthHttpApi } from '@/api/auth'; import { makeUsersModule, USER_ACTIONS, USER_MUTATIONS } from '@/store/modules/users'; import { UpdatedUser, User } from '@/types/users'; import { createLocalVue } from '@vue/test-utils'; const Vue = createLocalVue(); -const usersApi = new UsersApiGql(); -const usersModule = makeUsersModule(usersApi); +const authApi = new AuthHttpApi(); +const usersModule = makeUsersModule(authApi); const { UPDATE, GET, CLEAR } = USER_ACTIONS; Vue.use(Vuex); @@ -56,7 +56,7 @@ describe('actions', () => { jest.resetAllMocks(); }); it('success update account', async () => { - jest.spyOn(usersApi, 'update').mockReturnValue( + jest.spyOn(authApi, 'update').mockReturnValue( Promise.resolve(), ); @@ -69,7 +69,7 @@ describe('actions', () => { }); it('update throws an error when api call fails', async () => { - jest.spyOn(usersApi, 'update').mockImplementation(() => { throw new Error(); }); + jest.spyOn(authApi, 'update').mockImplementation(() => { throw new Error(); }); const newUser = new UpdatedUser('', ''); const oldUser = store.getters.user; @@ -95,7 +95,7 @@ describe('actions', () => { it('success get user', async () => { const user = new User('2', 'newFullName', 'newShortName', 'example2@email.com'); - jest.spyOn(usersApi, 'get').mockReturnValue( + jest.spyOn(authApi, 'get').mockReturnValue( Promise.resolve(user), ); @@ -109,7 +109,7 @@ describe('actions', () => { it('get throws an error when api call fails', async () => { const user = store.getters.user; - jest.spyOn(usersApi, 'get').mockImplementation(() => { throw new Error(); }); + jest.spyOn(authApi, 'get').mockImplementation(() => { throw new Error(); }); try { await store.dispatch(GET);