web/satellite: registration/welcome message fixed, usage-report url fixed, storj-sim fixed (#3622)

This commit is contained in:
Nikolai Siedov 2019-11-22 19:03:15 +02:00 committed by GitHub
parent 37c379f7da
commit ded7f6e2eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 88 additions and 845 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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,

View File

@ -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)
})
})
}

View File

@ -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
},
},
},
})
}

View File

@ -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)
})
})
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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))
}

View File

@ -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<void> {
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<User> {
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);
}
}

View File

@ -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;
}

View File

@ -7,9 +7,8 @@
<RegistrationSuccessIcon/>
</div>
<div class="register-success-popup__form-container">
<h2 class="register-success-popup__form-container__title">Verify Your Email</h2>
<p class="register-success-popup__form-container__text">You have almost finished registering your account on the Tardigrade Satellite. Only one step left. Please check your inbox for a verification email.</p>
<h3 class="register-success-popup__form-container__verification-cooldown">Didnt receive a verification email?<b class="register-success-popup__form-container__verification-cooldown__bold-text"> {{timeToEnableResendEmailButton}}</b></h3>
<h2 class="register-success-popup__form-container__title">Check your inbox for your verification email</h2>
<p class="register-success-popup__form-container__text">Didnt receive a verification email?<b class="register-success-popup__form-container__verification-cooldown__bold-text"> {{timeToEnableResendEmailButton}}</b></p>
<div class="register-success-popup__form-container__button-container">
<VButton
label="Resend Email"

View File

@ -178,7 +178,7 @@ export default class UsageReport extends Vue {
const url = new URL(location.origin);
url.pathname = 'usage-report/';
url.pathname = 'usage-report';
url.searchParams.append('projectID', projectID);
url.searchParams.append('since', toUnixTimestamp(startDate).toString());
url.searchParams.append('before', toUnixTimestamp(endDate).toString());

View File

@ -493,7 +493,7 @@
<div style="Margin-left: 20px;Margin-right: 20px;Margin-top: 12px;Margin-bottom: 12px;">
<div style="mso-line-height-rule: exactly;mso-text-raise: 4px;">
<p class="size-20" style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 17px;line-height: 26px;" lang="x-size-20"><span class="font-montserrat">Thank you for creating a Satellite account.</span></p><p class="size-20" style="Margin-top: 5px;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 17px;line-height: 26px;" lang="x-size-20"><span class="font-montserrat">&#8232;Now you need to verify your account &#8232;</span></p>
<p class="size-18" style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 17px;line-height: 25px;" lang="x-size-18"><span class="font-montserrat">Thank you for creating a Satellite account.</span></p><p class="size-18" style="Margin-top: 5px;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 17px;line-height: 26px;" lang="x-size-18"><span class="font-montserrat">&#8232;Now you need to verify your account. &#8232;</span></p>
</div>
</div>
@ -511,9 +511,8 @@
<div style="Margin-left: 20px;Margin-right: 20px;Margin-top: 12px;Margin-bottom: 12px;">
<div style="mso-line-height-rule: exactly;mso-text-raise: 4px;">
<p class="size-16" style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 16px;line-height: 24px;" lang="x-size-16"><span class="font-montserrat">After verification you will have access to create new Projects<br />
and setup your API keys within a team and project</span></p>
</div>
<p class="size-18" style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 17px;line-height: 25px;" lang="x-size-18"><span class="font-montserrat">After verification you will have access to create new Projects<br /> and setup your API keys within a team and project.</span></p>
</div>
</div>
</div>

View File

@ -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);