From 516241e406923dedcc66df06b7e7c1479dc98b91 Mon Sep 17 00:00:00 2001 From: Wilfred Asomani Date: Tue, 22 Aug 2023 10:51:59 +0000 Subject: [PATCH] cmd,satellite: remove Graphql code and dependencies This change removes unused GraphQL code. It also updates storj sim code to use the GraphQL replacement HTTP endpoints and removes the GraphQL dependency. Issue: https://github.com/storj/storj/issues/6142 Change-Id: Ie502553706c4b1282cd883a9275ea7332b8fc92d --- cmd/storj-sim/console.go | 98 ++- go.mod | 1 - go.sum | 2 - .../console/consoleweb/consoleql/apikey.go | 134 ---- .../console/consoleweb/consoleql/keys.go | 23 - .../console/consoleweb/consoleql/mutation.go | 372 ---------- .../consoleweb/consoleql/mutation_test.go | 511 -------------- .../console/consoleweb/consoleql/project.go | 529 --------------- .../consoleweb/consoleql/projectmember.go | 150 ---- .../console/consoleweb/consoleql/query.go | 82 --- .../consoleweb/consoleql/query_test.go | 501 -------------- .../console/consoleweb/consoleql/reward.go | 64 -- .../console/consoleweb/consoleql/schema.go | 27 - .../consoleweb/consoleql/testdata/Invite.html | 612 ----------------- .../consoleql/testdata/Welcome.html | 640 ------------------ .../consoleweb/consoleql/typecreator.go | 168 ----- .../console/consoleweb/consoleql/user.go | 78 --- .../console/consoleweb/endpoints_test.go | 521 +------------- satellite/console/consoleweb/server.go | 141 +--- satellite/console/consoleweb/utils.go | 41 -- scripts/testdata/satellite-config.yaml.lock | 2 +- testsuite/storjscan/go.mod | 1 - testsuite/storjscan/go.sum | 2 - testsuite/ui/go.mod | 1 - testsuite/ui/go.sum | 2 - 25 files changed, 50 insertions(+), 4653 deletions(-) delete mode 100644 satellite/console/consoleweb/consoleql/apikey.go delete mode 100644 satellite/console/consoleweb/consoleql/keys.go delete mode 100644 satellite/console/consoleweb/consoleql/mutation.go delete mode 100644 satellite/console/consoleweb/consoleql/mutation_test.go delete mode 100644 satellite/console/consoleweb/consoleql/project.go delete mode 100644 satellite/console/consoleweb/consoleql/projectmember.go delete mode 100644 satellite/console/consoleweb/consoleql/query.go delete mode 100644 satellite/console/consoleweb/consoleql/query_test.go delete mode 100644 satellite/console/consoleweb/consoleql/reward.go delete mode 100644 satellite/console/consoleweb/consoleql/schema.go delete mode 100644 satellite/console/consoleweb/consoleql/testdata/Invite.html delete mode 100644 satellite/console/consoleweb/consoleql/testdata/Welcome.html delete mode 100644 satellite/console/consoleweb/consoleql/typecreator.go delete mode 100644 satellite/console/consoleweb/consoleql/user.go diff --git a/cmd/storj-sim/console.go b/cmd/storj-sim/console.go index 3b310a9a5..ddc890abd 100644 --- a/cmd/storj-sim/console.go +++ b/cmd/storj-sim/console.go @@ -65,11 +65,15 @@ func (ce *consoleEndpoints) Token() string { return ce.appendPath("/api/v0/auth/token") } -func (ce *consoleEndpoints) GraphQL() string { - return ce.appendPath("/api/v0/graphql") +func (ce *consoleEndpoints) Projects() string { + return ce.appendPath("/api/v0/projects") } -func (ce *consoleEndpoints) graphqlDo(request *http.Request, jsonResponse interface{}) error { +func (ce *consoleEndpoints) APIKeys() string { + return ce.appendPath("/api/v0/api-keys") +} + +func (ce *consoleEndpoints) httpDo(request *http.Request, jsonResponse interface{}) error { resp, err := ce.client.Do(request) if err != nil { return err @@ -81,24 +85,24 @@ func (ce *consoleEndpoints) graphqlDo(request *http.Request, jsonResponse interf return err } - var response struct { - Data json.RawMessage - Errors []interface{} - } - - if err = json.NewDecoder(bytes.NewReader(b)).Decode(&response); err != nil { - return err - } - - if response.Errors != nil { - return errs.New("inner graphql error: %v", response.Errors) - } - if jsonResponse == nil { return errs.New("empty response: %q", b) } - return json.NewDecoder(bytes.NewReader(response.Data)).Decode(jsonResponse) + if resp.StatusCode >= 200 && resp.StatusCode < 300 { + return json.NewDecoder(bytes.NewReader(b)).Decode(jsonResponse) + } + + var errResponse struct { + Error string `json:"error"` + } + + err = json.NewDecoder(bytes.NewReader(b)).Decode(&errResponse) + if err != nil { + return err + } + + return errs.New("request failed with status %d: %s", resp.StatusCode, errResponse.Error) } func (ce *consoleEndpoints) createOrGetAPIKey(ctx context.Context) (string, error) { @@ -464,49 +468,41 @@ func (ce *consoleEndpoints) getProject(ctx context.Context, token string) (strin request, err := http.NewRequestWithContext( ctx, http.MethodGet, - ce.GraphQL(), + ce.Projects(), nil) if err != nil { return "", errs.Wrap(err) } - q := request.URL.Query() - q.Add("query", `query {myProjects{id}}`) - request.URL.RawQuery = q.Encode() - request.AddCookie(&http.Cookie{ Name: ce.cookieName, Value: token, }) - request.Header.Add("Content-Type", "application/graphql") + request.Header.Add("Content-Type", "application/json") - var getProjects struct { - MyProjects []struct { - ID string - } + var projects []struct { + ID string `json:"id"` } - if err := ce.graphqlDo(request, &getProjects); err != nil { + if err := ce.httpDo(request, &projects); err != nil { return "", errs.Wrap(err) } - if len(getProjects.MyProjects) == 0 { + if len(projects) == 0 { return "", errs.New("no projects") } - return getProjects.MyProjects[0].ID, nil + return projects[0].ID, nil } func (ce *consoleEndpoints) createProject(ctx context.Context, token string) (string, error) { rng := rand.NewSource(time.Now().UnixNano()) - createProjectQuery := fmt.Sprintf( - `mutation {createProject(input:{name:"TestProject-%d",description:""}){id}}`, - rng.Int63()) + body := fmt.Sprintf(`{"name":"TestProject-%d","description":""}`, rng.Int63()) request, err := http.NewRequestWithContext( ctx, http.MethodPost, - ce.GraphQL(), - bytes.NewReader([]byte(createProjectQuery))) + ce.Projects(), + bytes.NewReader([]byte(body))) if err != nil { return "", errs.Wrap(err) } @@ -516,31 +512,27 @@ func (ce *consoleEndpoints) createProject(ctx context.Context, token string) (st Value: token, }) - request.Header.Add("Content-Type", "application/graphql") + request.Header.Add("Content-Type", "application/json") - var createProject struct { - CreateProject struct { - ID string - } + var createdProject struct { + ID string `json:"id"` } - if err := ce.graphqlDo(request, &createProject); err != nil { + if err := ce.httpDo(request, &createdProject); err != nil { return "", errs.Wrap(err) } - return createProject.CreateProject.ID, nil + return createdProject.ID, nil } func (ce *consoleEndpoints) createAPIKey(ctx context.Context, token, projectID string) (string, error) { rng := rand.NewSource(time.Now().UnixNano()) - createAPIKeyQuery := fmt.Sprintf( - `mutation {createAPIKey(projectID:%q,name:"TestKey-%d"){key}}`, - projectID, rng.Int63()) + apiKeyName := fmt.Sprintf("TestKey-%d", rng.Int63()) request, err := http.NewRequestWithContext( ctx, http.MethodPost, - ce.GraphQL(), - bytes.NewReader([]byte(createAPIKeyQuery))) + ce.APIKeys()+"/create/"+projectID, + bytes.NewReader([]byte(apiKeyName))) if err != nil { return "", errs.Wrap(err) } @@ -550,18 +542,16 @@ func (ce *consoleEndpoints) createAPIKey(ctx context.Context, token, projectID s Value: token, }) - request.Header.Add("Content-Type", "application/graphql") + request.Header.Add("Content-Type", "application/json") - var createAPIKey struct { - CreateAPIKey struct { - Key string - } + var createdKey struct { + Key string `json:"key"` } - if err := ce.graphqlDo(request, &createAPIKey); err != nil { + if err := ce.httpDo(request, &createdKey); err != nil { return "", errs.Wrap(err) } - return createAPIKey.CreateAPIKey.Key, nil + return createdKey.Key, nil } func generateActivationKey(userID uuid.UUID, email string, createdAt time.Time) (string, error) { diff --git a/go.mod b/go.mod index b69551340..111f1d283 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/google/go-cmp v0.5.9 github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.2.0 - github.com/graphql-go/graphql v0.7.9 github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451 github.com/jackc/pgtype v1.14.0 github.com/jackc/pgx/v5 v5.3.1 diff --git a/go.sum b/go.sum index 43b14fe74..c6b02df3e 100644 --- a/go.sum +++ b/go.sum @@ -229,8 +229,6 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graphql-go/graphql v0.7.9 h1:5Va/Rt4l5g3YjwDnid3vFfn43faaQBq7rMcIZ0VnV34= -github.com/graphql-go/graphql v0.7.9/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= diff --git a/satellite/console/consoleweb/consoleql/apikey.go b/satellite/console/consoleweb/consoleql/apikey.go deleted file mode 100644 index 4ea4dc111..000000000 --- a/satellite/console/consoleweb/consoleql/apikey.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" - - "storj.io/storj/satellite/console" -) - -const ( - // APIKeyInfoType is graphql type name for api key. - APIKeyInfoType = "keyInfo" - // CreateAPIKeyType is graphql type name for createAPIKey struct - // which incapsulates the actual key and it's info. - CreateAPIKeyType = "graphqlCreateAPIKey" - // FieldKey is field name for the actual key in createAPIKey. - FieldKey = "key" -) - -// graphqlAPIKeyInfo creates satellite.APIKeyInfo graphql object. -func graphqlAPIKeyInfo() *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: APIKeyInfoType, - Fields: graphql.Fields{ - FieldID: &graphql.Field{ - Type: graphql.String, - }, - FieldProjectID: &graphql.Field{ - Type: graphql.String, - }, - FieldName: &graphql.Field{ - Type: graphql.String, - }, - FieldCreatedAt: &graphql.Field{ - Type: graphql.DateTime, - }, - }, - }) -} - -// graphqlCreateAPIKey creates createAPIKey graphql object. -func graphqlCreateAPIKey(types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: CreateAPIKeyType, - Fields: graphql.Fields{ - FieldKey: &graphql.Field{ - Type: graphql.String, - }, - APIKeyInfoType: &graphql.Field{ - Type: types.apiKeyInfo, - }, - }, - }) -} - -func graphqlAPIKeysCursor() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: APIKeysCursorInputType, - Fields: graphql.InputObjectConfigFieldMap{ - SearchArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - LimitArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - PageArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - OrderArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - OrderDirectionArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - }, - }) -} - -func graphqlAPIKeysPage(types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: APIKeysPageType, - Fields: graphql.Fields{ - FieldAPIKeys: &graphql.Field{ - Type: graphql.NewList(types.apiKeyInfo), - }, - SearchArg: &graphql.Field{ - Type: graphql.String, - }, - LimitArg: &graphql.Field{ - Type: graphql.Int, - }, - OrderArg: &graphql.Field{ - Type: graphql.Int, - }, - OrderDirectionArg: &graphql.Field{ - Type: graphql.Int, - }, - OffsetArg: &graphql.Field{ - Type: graphql.Int, - }, - FieldPageCount: &graphql.Field{ - Type: graphql.Int, - }, - FieldCurrentPage: &graphql.Field{ - Type: graphql.Int, - }, - FieldTotalCount: &graphql.Field{ - Type: graphql.Int, - }, - }, - }) -} - -// createAPIKey holds macaroon.APIKey and console.APIKeyInfo. -type createAPIKey struct { - Key string - KeyInfo *console.APIKeyInfo -} - -type apiKeysPage struct { - APIKeys []console.APIKeyInfo - - Search string - Limit uint - Order int - OrderDirection int - Offset uint64 - - PageCount uint - CurrentPage uint - TotalCount uint64 -} diff --git a/satellite/console/consoleweb/consoleql/keys.go b/satellite/console/consoleweb/consoleql/keys.go deleted file mode 100644 index 2cfb31b0b..000000000 --- a/satellite/console/consoleweb/consoleql/keys.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2022 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -const ( - // ActivationPath is key for path which handles account activation. - ActivationPath = "activationPath" - // PasswordRecoveryPath is key for path which handles password recovery. - PasswordRecoveryPath = "passwordRecoveryPath" - // CancelPasswordRecoveryPath is key for path which handles let us know sequence. - CancelPasswordRecoveryPath = "cancelPasswordRecoveryPath" - // SignInPath is key for sign in server route. - SignInPath = "signInPath" - // LetUsKnowURL is key to store let us know URL. - LetUsKnowURL = "letUsKnowURL" - // ContactInfoURL is a key to store contact info URL. - ContactInfoURL = "contactInfoURL" - // TermsAndConditionsURL is a key to store terms and conditions URL. - TermsAndConditionsURL = "termsAndConditionsURL" - // SatelliteRegion is a key to store the satellite's region/name. - SatelliteRegion = "satelliteRegion" -) diff --git a/satellite/console/consoleweb/consoleql/mutation.go b/satellite/console/consoleweb/consoleql/mutation.go deleted file mode 100644 index c954a5aee..000000000 --- a/satellite/console/consoleweb/consoleql/mutation.go +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" - "github.com/zeebo/errs" - "go.uber.org/zap" - - "storj.io/common/uuid" - "storj.io/storj/private/post" - "storj.io/storj/satellite/console" - "storj.io/storj/satellite/mailservice" -) - -const ( - // Mutation is graphql request that modifies data. - Mutation = "mutation" - - // CreateProjectMutation is a mutation name for project creation. - CreateProjectMutation = "createProject" - // DeleteProjectMutation is a mutation name for project deletion. - DeleteProjectMutation = "deleteProject" - // UpdateProjectMutation is a mutation name for project name and description updating. - UpdateProjectMutation = "updateProject" - - // AddProjectMembersMutation is a mutation name for adding new project members. - AddProjectMembersMutation = "addProjectMembers" - // DeleteProjectMembersMutation is a mutation name for deleting project members. - DeleteProjectMembersMutation = "deleteProjectMembers" - - // CreateAPIKeyMutation is a mutation name for api key creation. - CreateAPIKeyMutation = "createAPIKey" - // DeleteAPIKeysMutation is a mutation name for api key deleting. - DeleteAPIKeysMutation = "deleteAPIKeys" - - // AddPaymentMethodMutation is mutation name for adding new payment method. - AddPaymentMethodMutation = "addPaymentMethod" - // DeletePaymentMethodMutation is mutation name for deleting payment method. - DeletePaymentMethodMutation = "deletePaymentMethod" - // SetDefaultPaymentMethodMutation is mutation name setting payment method as default payment method. - SetDefaultPaymentMethodMutation = "setDefaultPaymentMethod" - - // InputArg is argument name for all input types. - InputArg = "input" - // ProjectFields is a field name for project specific fields. - ProjectFields = "projectFields" - // ProjectLimits is a field name for project specific limits. - ProjectLimits = "projectLimits" - // FieldProjectID is field name for projectID. - FieldProjectID = "projectID" - // FieldNewPassword is a field name for new password. - FieldNewPassword = "newPassword" - // Secret is a field name for registration token for user creation during Vanguard release. - Secret = "secret" - // ReferrerUserID is a field name for passing referrer's user id. - ReferrerUserID = "referrerUserId" -) - -// rootMutation creates mutation for graphql populated by AccountsClient. -func rootMutation(log *zap.Logger, service *console.Service, mailService *mailservice.Service, types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: Mutation, - Fields: graphql.Fields{ - // creates project from input params - CreateProjectMutation: &graphql.Field{ - Type: types.project, - Args: graphql.FieldConfigArgument{ - InputArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.projectInput), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - var projectInput = fromMapProjectInfo(p.Args[InputArg].(map[string]interface{})) - - project, err := service.CreateProject(p.Context, projectInput) - if err != nil { - return nil, err - } - - return project, nil - }, - }, - // deletes project by id, taken from input params - DeleteProjectMutation: &graphql.Field{ - Type: types.project, - Args: graphql.FieldConfigArgument{ - FieldID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldPublicID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return nil, console.ErrUnauthorized.New("not implemented") - }, - }, - // updates project name and description. - UpdateProjectMutation: &graphql.Field{ - Type: types.project, - Args: graphql.FieldConfigArgument{ - FieldID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldPublicID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - ProjectFields: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.projectInput), - }, - ProjectLimits: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.projectLimit), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - var projectInput, err = fromMapProjectInfoProjectLimits(p.Args[ProjectFields].(map[string]interface{}), p.Args[ProjectLimits].(map[string]interface{})) - if err != nil { - return nil, err - } - - projectID, err := getProjectID(p) - if err != nil { - return nil, err - } - - project, err := service.UpdateProject(p.Context, projectID, projectInput) - if err != nil { - return nil, err - } - - return project, nil - }, - }, - // add user as member of given project - AddProjectMembersMutation: &graphql.Field{ - Type: types.project, - Args: graphql.FieldConfigArgument{ - FieldProjectID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldPublicID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldEmail: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.NewList(graphql.String)), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - inviter, err := console.GetUser(p.Context) - if err != nil { - return nil, err - } - - emails, _ := p.Args[FieldEmail].([]interface{}) - - projectID, err := getProjectID(p) - if err != nil { - return nil, err - } - - var userEmails []string - for _, email := range emails { - userEmails = append(userEmails, email.(string)) - } - - project, err := service.GetProject(p.Context, projectID) - if err != nil { - return nil, err - } - - users, err := service.AddProjectMembers(p.Context, project.ID, userEmails) - if err != nil { - return nil, err - } - - rootObject := p.Info.RootValue.(map[string]interface{}) - origin := rootObject["origin"].(string) - signIn := origin + rootObject[SignInPath].(string) - - for _, user := range users { - userName := user.ShortName - if user.ShortName == "" { - userName = user.FullName - } - - satelliteRegion := rootObject[SatelliteRegion].(string) - - mailService.SendRenderedAsync( - p.Context, - []post.Address{{Address: user.Email, Name: userName}}, - &console.ExistingUserProjectInvitationEmail{ - InviterEmail: inviter.Email, - Region: satelliteRegion, - SignInLink: signIn, - }, - ) - } - - return project, nil - }, - }, - // delete user membership for given project - DeleteProjectMembersMutation: &graphql.Field{ - Type: types.project, - Args: graphql.FieldConfigArgument{ - FieldProjectID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldPublicID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldEmail: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.NewList(graphql.String)), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - emails, _ := p.Args[FieldEmail].([]interface{}) - - projectID, err := getProjectID(p) - if err != nil { - return nil, err - } - - var userEmails []string - for _, email := range emails { - userEmails = append(userEmails, email.(string)) - } - - project, err := service.GetProject(p.Context, projectID) - if err != nil { - return nil, err - } - - err = service.DeleteProjectMembersAndInvitations(p.Context, project.ID, userEmails) - if err != nil { - return nil, err - } - - return project, nil - }, - }, - // creates new api key - CreateAPIKeyMutation: &graphql.Field{ - Type: types.createAPIKey, - Args: graphql.FieldConfigArgument{ - FieldProjectID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldPublicID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldName: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - name, _ := p.Args[FieldName].(string) - - projectID, err := getProjectID(p) - if err != nil { - return nil, err - } - - info, key, err := service.CreateAPIKey(p.Context, projectID, name) - if err != nil { - return nil, err - } - - return createAPIKey{ - Key: key.Serialize(), - KeyInfo: info, - }, nil - }, - }, - // deletes api key - DeleteAPIKeysMutation: &graphql.Field{ - Type: graphql.NewList(types.apiKeyInfo), - Args: graphql.FieldConfigArgument{ - FieldID: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.NewList(graphql.String)), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - paramKeysID, _ := p.Args[FieldID].([]interface{}) - - var keyIds []uuid.UUID - var keys []console.APIKeyInfo - for _, id := range paramKeysID { - keyID, err := uuid.FromString(id.(string)) - if err != nil { - return nil, err - } - - key, err := service.GetAPIKeyInfo(p.Context, keyID) - if err != nil { - return nil, err - } - - keyIds = append(keyIds, keyID) - keys = append(keys, *key) - } - - err := service.DeleteAPIKeys(p.Context, keyIds) - if err != nil { - return nil, err - } - - return keys, nil - }, - }, - AddPaymentMethodMutation: &graphql.Field{ - Type: graphql.Boolean, - Args: graphql.FieldConfigArgument{}, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return nil, nil - }, - }, - DeletePaymentMethodMutation: &graphql.Field{ - Type: graphql.Boolean, - Args: graphql.FieldConfigArgument{}, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return nil, nil - }, - }, - SetDefaultPaymentMethodMutation: &graphql.Field{ - Type: graphql.Boolean, - Args: graphql.FieldConfigArgument{}, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return nil, nil - }, - }, - }, - }) -} - -func getProjectID(p graphql.ResolveParams) (projectID uuid.UUID, err error) { - inputID, _ := p.Args[FieldID].(string) - inputProjectID, _ := p.Args[FieldProjectID].(string) - inputPublicID, _ := p.Args[FieldPublicID].(string) - - if inputID != "" { - projectID, err = uuid.FromString(inputID) - if err != nil { - return uuid.UUID{}, err - } - } else if inputProjectID != "" { - projectID, err = uuid.FromString(inputProjectID) - if err != nil { - return uuid.UUID{}, err - } - } else if inputPublicID != "" { - projectID, err = uuid.FromString(inputPublicID) - if err != nil { - return uuid.UUID{}, err - } - } else { - return uuid.UUID{}, errs.New("Project ID was not provided.") - } - return projectID, nil -} diff --git a/satellite/console/consoleweb/consoleql/mutation_test.go b/satellite/console/consoleweb/consoleql/mutation_test.go deleted file mode 100644 index 7f433e708..000000000 --- a/satellite/console/consoleweb/consoleql/mutation_test.go +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql_test - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/graphql-go/graphql" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zaptest" - - "storj.io/common/testcontext" - "storj.io/common/uuid" - "storj.io/storj/private/post" - "storj.io/storj/private/testplanet" - "storj.io/storj/private/testredis" - "storj.io/storj/satellite/accounting" - "storj.io/storj/satellite/accounting/live" - "storj.io/storj/satellite/analytics" - "storj.io/storj/satellite/console" - "storj.io/storj/satellite/console/consoleauth" - "storj.io/storj/satellite/console/consoleweb/consoleql" - "storj.io/storj/satellite/console/restkeys" - "storj.io/storj/satellite/mailservice" - "storj.io/storj/satellite/payments" - "storj.io/storj/satellite/payments/paymentsconfig" - "storj.io/storj/satellite/payments/stripe" -) - -// discardSender discard sending of an actual email. -type discardSender struct{} - -// SendEmail immediately returns with nil error. -func (*discardSender) SendEmail(ctx context.Context, msg *post.Message) error { - return nil -} - -// FromAddress returns empty post.Address. -func (*discardSender) FromAddress() post.Address { - return post.Address{} -} - -func TestGraphqlMutation(t *testing.T) { - testplanet.Run(t, testplanet.Config{SatelliteCount: 1}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) { - sat := planet.Satellites[0] - db := sat.DB - log := zaptest.NewLogger(t) - - analyticsService := analytics.NewService(log, analytics.Config{}, "test-satellite") - - redis, err := testredis.Mini(ctx) - require.NoError(t, err) - defer ctx.Check(redis.Close) - - cache, err := live.OpenCache(ctx, log.Named("cache"), live.Config{StorageBackend: "redis://" + redis.Addr() + "?db=0"}) - require.NoError(t, err) - - projectLimitCache := accounting.NewProjectLimitCache(db.ProjectAccounting(), 0, 0, 0, accounting.ProjectLimitConfig{CacheCapacity: 100}) - - projectUsage := accounting.NewService(db.ProjectAccounting(), cache, projectLimitCache, *sat.Metabase.DB, 5*time.Minute, -10*time.Second) - - // TODO maybe switch this test to testplanet to avoid defining config and Stripe service - pc := paymentsconfig.Config{ - UsagePrice: paymentsconfig.ProjectUsagePrice{ - StorageTB: "10", - EgressTB: "45", - Segment: "0.0000022", - }, - } - - prices, err := pc.UsagePrice.ToModel() - require.NoError(t, err) - - priceOverrides, err := pc.UsagePriceOverrides.ToModels() - require.NoError(t, err) - - paymentsService, err := stripe.NewService( - log.Named("payments.stripe:service"), - stripe.NewStripeMock( - db.StripeCoinPayments().Customers(), - db.Console().Users(), - ), - pc.StripeCoinPayments, - db.StripeCoinPayments(), - db.Wallets(), - db.Billing(), - db.Console().Projects(), - db.Console().Users(), - db.ProjectAccounting(), - prices, - priceOverrides, - pc.PackagePlans.Packages, - pc.BonusRate, - nil, - ) - require.NoError(t, err) - - service, err := console.NewService( - log.Named("console"), - db.Console(), - restkeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.RESTKeys), - db.ProjectAccounting(), - projectUsage, - sat.API.Buckets.Service, - paymentsService.Accounts(), - // TODO: do we need a payment deposit wallet here? - nil, - db.Billing(), - analyticsService, - consoleauth.NewService(consoleauth.Config{ - TokenExpirationTime: 24 * time.Hour, - }, &consoleauth.Hmac{Secret: []byte("my-suppa-secret-key")}), - nil, - "", - "", - console.Config{ - PasswordCost: console.TestPasswordCost, - DefaultProjectLimit: 5, - Session: console.SessionConfig{ - Duration: time.Hour, - }, - }, - ) - require.NoError(t, err) - - mailService, err := mailservice.New(log, &discardSender{}, "testdata") - require.NoError(t, err) - defer ctx.Check(mailService.Close) - - rootObject := make(map[string]interface{}) - rootObject["origin"] = "http://doesntmatter.com/" - rootObject[consoleql.ActivationPath] = "?activationToken=" - rootObject[consoleql.SignInPath] = "login" - rootObject[consoleql.LetUsKnowURL] = "letUsKnowURL" - rootObject[consoleql.ContactInfoURL] = "contactInfoURL" - rootObject[consoleql.TermsAndConditionsURL] = "termsAndConditionsURL" - rootObject[consoleql.SatelliteRegion] = "EU1" - - schema, err := consoleql.CreateSchema(log, service, mailService) - require.NoError(t, err) - - createUser := console.CreateUser{ - FullName: "John Roll", - ShortName: "Roll", - Email: "test@mail.test", - UserAgent: []byte("120bf202-8252-437e-ac12-0e364bee852e"), - Password: "123a123", - SignupPromoCode: "promo1", - } - - regToken, err := service.CreateRegToken(ctx, 1) - require.NoError(t, err) - - rootUser, err := service.CreateUser(ctx, createUser, regToken.Secret) - require.NoError(t, err) - require.Equal(t, createUser.UserAgent, rootUser.UserAgent) - - couponType, err := paymentsService.Accounts().Setup(ctx, rootUser.ID, rootUser.Email, rootUser.SignupPromoCode) - - var signupCouponType payments.CouponType = payments.SignupCoupon - - require.NoError(t, err) - assert.Equal(t, signupCouponType, couponType) - - activationToken, err := service.GenerateActivationToken(ctx, rootUser.ID, rootUser.Email) - require.NoError(t, err) - - _, err = service.ActivateAccount(ctx, activationToken) - require.NoError(t, err) - - tokenInfo, err := service.Token(ctx, console.AuthUser{Email: createUser.Email, Password: createUser.Password}) - require.NoError(t, err) - - userCtx, err := service.TokenAuth(ctx, tokenInfo.Token, time.Now()) - require.NoError(t, err) - - testQuery := func(t *testing.T, query string) (interface{}, error) { - result := graphql.Do(graphql.Params{ - Schema: schema, - Context: userCtx, - RequestString: query, - RootObject: rootObject, - }) - - for _, err := range result.Errors { - if err.OriginalError() != nil { - return nil, err - } - } - require.False(t, result.HasErrors()) - - return result.Data, nil - } - - tokenInfo, err = service.Token(ctx, console.AuthUser{Email: rootUser.Email, Password: createUser.Password}) - require.NoError(t, err) - - userCtx, err = service.TokenAuth(ctx, tokenInfo.Token, time.Now()) - require.NoError(t, err) - - var projectIDField string - var projectPublicIDField string - t.Run("Create project mutation", func(t *testing.T) { - projectInfo := console.UpsertProjectInfo{ - Name: "Project name", - Description: "desc", - } - - query := fmt.Sprintf( - "mutation {createProject(input:{name:\"%s\",description:\"%s\"}){name,description,id,publicId,createdAt}}", - projectInfo.Name, - projectInfo.Description, - ) - - result, err := testQuery(t, query) - require.NoError(t, err) - - data := result.(map[string]interface{}) - project := data[consoleql.CreateProjectMutation].(map[string]interface{}) - - assert.Equal(t, projectInfo.Name, project[consoleql.FieldName]) - assert.Equal(t, projectInfo.Description, project[consoleql.FieldDescription]) - - projectIDField = project[consoleql.FieldID].(string) - projectPublicIDField = project[consoleql.FieldPublicID].(string) - - _, err = uuid.FromString(projectPublicIDField) - require.NoError(t, err) - }) - - projectID, err := uuid.FromString(projectIDField) - require.NoError(t, err) - - project, err := service.GetProject(userCtx, projectID) - require.NoError(t, err) - require.Equal(t, rootUser.UserAgent, project.UserAgent) - - regTokenUser1, err := service.CreateRegToken(ctx, 1) - require.NoError(t, err) - - user1, err := service.CreateUser(userCtx, console.CreateUser{ - FullName: "User1", - Email: "u1@mail.test", - Password: "123a123", - }, regTokenUser1.Secret) - require.NoError(t, err) - - t.Run("Activation", func(t *testing.T) { - activationToken1, err := service.GenerateActivationToken( - ctx, - user1.ID, - "u1@mail.test", - ) - require.NoError(t, err) - - _, err = service.ActivateAccount(ctx, activationToken1) - require.NoError(t, err) - - user1.Email = "u1@mail.test" - }) - - regTokenUser2, err := service.CreateRegToken(ctx, 1) - require.NoError(t, err) - - user2, err := service.CreateUser(userCtx, console.CreateUser{ - FullName: "User1", - Email: "u2@mail.test", - Password: "123a123", - }, regTokenUser2.Secret) - require.NoError(t, err) - - t.Run("Activation", func(t *testing.T) { - activationToken2, err := service.GenerateActivationToken( - ctx, - user2.ID, - "u2@mail.test", - ) - require.NoError(t, err) - - _, err = service.ActivateAccount(ctx, activationToken2) - require.NoError(t, err) - - user2.Email = "u2@mail.test" - }) - - regTokenUser3, err := service.CreateRegToken(ctx, 1) - require.NoError(t, err) - - user3, err := service.CreateUser(userCtx, console.CreateUser{ - FullName: "User3", - Email: "u3@mail.test", - Password: "123a123", - }, regTokenUser3.Secret) - require.NoError(t, err) - - t.Run("Activation", func(t *testing.T) { - activationToken3, err := service.GenerateActivationToken( - ctx, - user3.ID, - "u3@mail.test", - ) - require.NoError(t, err) - - _, err = service.ActivateAccount(ctx, activationToken3) - require.NoError(t, err) - - user3.Email = "u3@mail.test" - }) - - testAdd := func(query string, expectedMembers int) { - result, err := testQuery(t, query) - require.NoError(t, err) - - data := result.(map[string]interface{}) - proj := data[consoleql.AddProjectMembersMutation].(map[string]interface{}) - - members := proj[consoleql.FieldMembersAndInvitations].(map[string]interface{}) - projectMembers := members[consoleql.FieldProjectMembers].([]interface{}) - - assert.Equal(t, project.ID.String(), proj[consoleql.FieldID]) - assert.Equal(t, project.PublicID.String(), proj[consoleql.FieldPublicID]) - assert.Equal(t, project.Name, proj[consoleql.FieldName]) - assert.Equal(t, expectedMembers, len(projectMembers)) - } - - t.Run("Add project members mutation", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {addProjectMembers(projectID:\"%s\",email:[\"%s\",\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", - project.ID.String(), - user1.Email, - user2.Email, - ) - - testAdd(query, 3) - }) - - t.Run("Add project members mutation with publicId", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {addProjectMembers(publicId:\"%s\",email:[\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", - project.PublicID.String(), - user3.Email, - ) - - testAdd(query, 4) - }) - - t.Run("Fail add project members mutation without ID", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {addProjectMembers(email:[\"%s\",\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", - user1.Email, - user2.Email, - ) - - _, err = testQuery(t, query) - require.Error(t, err) - }) - - t.Run("Delete project members mutation", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {deleteProjectMembers(projectID:\"%s\",email:[\"%s\",\"%s\",\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{user{id}}}}}", - project.ID.String(), - user1.Email, - user2.Email, - user3.Email, - ) - - result, err := testQuery(t, query) - require.NoError(t, err) - - data := result.(map[string]interface{}) - proj := data[consoleql.DeleteProjectMembersMutation].(map[string]interface{}) - - members := proj[consoleql.FieldMembersAndInvitations].(map[string]interface{}) - projectMembers := members[consoleql.FieldProjectMembers].([]interface{}) - rootMember := projectMembers[0].(map[string]interface{})[consoleql.UserType].(map[string]interface{}) - - assert.Equal(t, project.ID.String(), proj[consoleql.FieldID]) - assert.Equal(t, project.PublicID.String(), proj[consoleql.FieldPublicID]) - assert.Equal(t, project.Name, proj[consoleql.FieldName]) - assert.Equal(t, 1, len(members)) - - assert.Equal(t, rootUser.ID.String(), rootMember[consoleql.FieldID]) - }) - - var keyID string - t.Run("Create api key mutation", func(t *testing.T) { - keyName := "key1" - query := fmt.Sprintf( - "mutation {createAPIKey(projectID:\"%s\",name:\"%s\"){key,keyInfo{id,name,projectID}}}", - project.ID.String(), - keyName, - ) - - result, err := testQuery(t, query) - require.NoError(t, err) - - data := result.(map[string]interface{}) - createAPIKey := data[consoleql.CreateAPIKeyMutation].(map[string]interface{}) - - key := createAPIKey[consoleql.FieldKey].(string) - keyInfo := createAPIKey[consoleql.APIKeyInfoType].(map[string]interface{}) - - assert.NotEqual(t, "", key) - - assert.Equal(t, keyName, keyInfo[consoleql.FieldName]) - assert.Equal(t, project.ID.String(), keyInfo[consoleql.FieldProjectID]) - - keyID = keyInfo[consoleql.FieldID].(string) - }) - - t.Run("Delete api key mutation", func(t *testing.T) { - id, err := uuid.FromString(keyID) - require.NoError(t, err) - - info, err := service.GetAPIKeyInfo(userCtx, id) - require.NoError(t, err) - - query := fmt.Sprintf( - "mutation {deleteAPIKeys(id:[\"%s\"]){name,projectID}}", - keyID, - ) - - result, err := testQuery(t, query) - require.NoError(t, err) - - data := result.(map[string]interface{}) - keyInfoList := data[consoleql.DeleteAPIKeysMutation].([]interface{}) - - for _, k := range keyInfoList { - keyInfo := k.(map[string]interface{}) - - assert.Equal(t, info.Name, keyInfo[consoleql.FieldName]) - assert.Equal(t, project.ID.String(), keyInfo[consoleql.FieldProjectID]) - } - }) - - const testName = "testName" - const testDescription = "test description" - const StorageLimit = "100" - const BandwidthLimit = "100" - - testUpdate := func(query string) { - result, err := testQuery(t, query) - require.NoError(t, err) - - data := result.(map[string]interface{}) - proj := data[consoleql.UpdateProjectMutation].(map[string]interface{}) - - assert.Equal(t, project.ID.String(), proj[consoleql.FieldID]) - assert.Equal(t, project.PublicID.String(), proj[consoleql.FieldPublicID]) - assert.Equal(t, testName, proj[consoleql.FieldName]) - assert.Equal(t, testDescription, proj[consoleql.FieldDescription]) - } - - t.Run("Update project mutation", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {updateProject(id:\"%s\",projectFields:{name:\"%s\",description:\"%s\"},projectLimits:{storageLimit:\"%s\",bandwidthLimit:\"%s\"}){id,publicId,name,description}}", - project.ID.String(), - testName, - testDescription, - StorageLimit, - BandwidthLimit, - ) - - testUpdate(query) - }) - - t.Run("Update project mutation with publicId", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {updateProject(publicId:\"%s\",projectFields:{name:\"%s\",description:\"%s\"},projectLimits:{storageLimit:\"%s\",bandwidthLimit:\"%s\"}){id,publicId,name,description}}", - project.PublicID.String(), - testName, - testDescription, - StorageLimit, - BandwidthLimit, - ) - - testUpdate(query) - }) - - t.Run("Fail update project mutation without ID", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {updateProject(projectFields:{name:\"%s\",description:\"%s\"},projectLimits:{storageLimit:\"%s\",bandwidthLimit:\"%s\"}){id,publicId,name,description}}", - testName, - testDescription, - StorageLimit, - BandwidthLimit, - ) - - _, err := testQuery(t, query) - require.Error(t, err) - }) - - t.Run("Delete project mutation", func(t *testing.T) { - query := fmt.Sprintf( - "mutation {deleteProject(id:\"%s\"){id,name}}", - projectID, - ) - - result, err := testQuery(t, query) - require.Error(t, err) - require.Nil(t, result) - require.Equal(t, console.ErrUnauthorized.New("not implemented").Error(), err.Error()) - }) - }) -} diff --git a/satellite/console/consoleweb/consoleql/project.go b/satellite/console/consoleweb/consoleql/project.go deleted file mode 100644 index 3776a7190..000000000 --- a/satellite/console/consoleweb/consoleql/project.go +++ /dev/null @@ -1,529 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "strconv" - "time" - - "github.com/graphql-go/graphql" - - "storj.io/common/memory" - "storj.io/storj/satellite/accounting" - "storj.io/storj/satellite/console" -) - -const ( - // ProjectType is a graphql type name for project. - ProjectType = "project" - // ProjectInputType is a graphql type name for project input. - ProjectInputType = "projectInput" - // ProjectLimitType is a graphql type name for project limit. - ProjectLimitType = "projectLimit" - // ProjectUsageType is a graphql type name for project usage. - ProjectUsageType = "projectUsage" - // ProjectsCursorInputType is a graphql input type name for projects cursor. - ProjectsCursorInputType = "projectsCursor" - // ProjectsPageType is a graphql type name for projects page. - ProjectsPageType = "projectsPage" - // BucketUsageCursorInputType is a graphql input - // type name for bucket usage cursor. - BucketUsageCursorInputType = "bucketUsageCursor" - // BucketUsageType is a graphql type name for bucket usage. - BucketUsageType = "bucketUsage" - // BucketUsagePageType is a graphql type name for bucket usage page. - BucketUsagePageType = "bucketUsagePage" - // ProjectMembersAndInvitationsPageType is a graphql type name for a page of project members and invitations. - ProjectMembersAndInvitationsPageType = "projectMembersAndInvitationsPage" - // ProjectMembersCursorInputType is a graphql type name for project members. - ProjectMembersCursorInputType = "projectMembersCursor" - // APIKeysPageType is a graphql type name for api keys page. - APIKeysPageType = "apiKeysPage" - // APIKeysCursorInputType is a graphql type name for api keys. - APIKeysCursorInputType = "apiKeysCursor" - // FieldPublicID is a field name for "publicId". - FieldPublicID = "publicId" - // FieldOwnerID is a field name for "ownerId". - FieldOwnerID = "ownerId" - // FieldName is a field name for "name". - FieldName = "name" - // FieldBucketName is a field name for "bucket name". - FieldBucketName = "bucketName" - // FieldDescription is a field name for description. - FieldDescription = "description" - // FieldMembersAndInvitations is field name for members and invitations. - FieldMembersAndInvitations = "membersAndInvitations" - // FieldAPIKeys is a field name for api keys. - FieldAPIKeys = "apiKeys" - // FieldUsage is a field name for usage rollup. - FieldUsage = "usage" - // FieldBucketUsages is a field name for bucket usages. - FieldBucketUsages = "bucketUsages" - // FieldStorageLimit is a field name for the storage limit. - FieldStorageLimit = "storageLimit" - // FieldBandwidthLimit is a field name for bandwidth limit. - FieldBandwidthLimit = "bandwidthLimit" - // FieldStorage is a field name for storage total. - FieldStorage = "storage" - // FieldEgress is a field name for egress total. - FieldEgress = "egress" - // FieldSegmentCount is a field name for segments count. - FieldSegmentCount = "segmentCount" - // FieldObjectCount is a field name for objects count. - FieldObjectCount = "objectCount" - // FieldPageCount is a field name for total page count. - FieldPageCount = "pageCount" - // FieldCurrentPage is a field name for current page number. - FieldCurrentPage = "currentPage" - // FieldTotalCount is a field name for bucket usage count total. - FieldTotalCount = "totalCount" - // FieldMemberCount is a field name for number of project members. - FieldMemberCount = "memberCount" - // FieldProjects is a field name for projects. - FieldProjects = "projects" - // FieldProjectMembers is a field name for project members. - FieldProjectMembers = "projectMembers" - // FieldProjectInvitations is a field name for project member invitations. - FieldProjectInvitations = "projectInvitations" - // CursorArg is an argument name for cursor. - CursorArg = "cursor" - // PageArg ia an argument name for page number. - PageArg = "page" - // LimitArg is argument name for limit. - LimitArg = "limit" - // OffsetArg is argument name for offset. - OffsetArg = "offset" - // SearchArg is argument name for search. - SearchArg = "search" - // OrderArg is argument name for order. - OrderArg = "order" - // OrderDirectionArg is argument name for order direction. - OrderDirectionArg = "orderDirection" - // SinceArg marks start of the period. - SinceArg = "since" - // BeforeArg marks end of the period. - BeforeArg = "before" -) - -// graphqlProject creates *graphql.Object type representation of satellite.ProjectInfo. -func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectType, - Fields: graphql.Fields{ - FieldID: &graphql.Field{ - Type: graphql.String, - }, - FieldPublicID: &graphql.Field{ - Type: graphql.String, - }, - FieldName: &graphql.Field{ - Type: graphql.String, - }, - FieldOwnerID: &graphql.Field{ - Type: graphql.String, - }, - FieldDescription: &graphql.Field{ - Type: graphql.String, - }, - FieldCreatedAt: &graphql.Field{ - Type: graphql.DateTime, - }, - FieldMemberCount: &graphql.Field{ - Type: graphql.Int, - }, - FieldMembersAndInvitations: &graphql.Field{ - Type: types.projectMembersAndInvitationsPage, - Args: graphql.FieldConfigArgument{ - CursorArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.projectMembersCursor), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - project, _ := p.Source.(*console.Project) - - _, err := console.GetUser(p.Context) - if err != nil { - return nil, err - } - - cursor := cursorArgsToProjectMembersCursor(p.Args[CursorArg].(map[string]interface{})) - page, err := service.GetProjectMembersAndInvitations(p.Context, project.ID, cursor) - if err != nil { - return nil, err - } - - var users []projectMember - for _, member := range page.ProjectMembers { - user, err := service.GetUser(p.Context, member.MemberID) - if err != nil { - return nil, err - } - - users = append(users, projectMember{ - User: user, - JoinedAt: member.CreatedAt, - }) - } - - var invites []projectInvitation - for _, invite := range page.ProjectInvitations { - invites = append(invites, projectInvitation{ - Email: invite.Email, - CreatedAt: invite.CreatedAt, - Expired: service.IsProjectInvitationExpired(&invite), - }) - } - - projectMembersPage := projectMembersPage{ - ProjectMembers: users, - ProjectInvitations: invites, - TotalCount: page.TotalCount, - Offset: page.Offset, - Limit: page.Limit, - Order: int(page.Order), - OrderDirection: int(page.OrderDirection), - Search: page.Search, - CurrentPage: page.CurrentPage, - PageCount: page.PageCount, - } - return projectMembersPage, nil - }, - }, - FieldAPIKeys: &graphql.Field{ - Type: types.apiKeyPage, - Args: graphql.FieldConfigArgument{ - CursorArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.apiKeysCursor), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - project, _ := p.Source.(*console.Project) - - cursor := cursorArgsToAPIKeysCursor(p.Args[CursorArg].(map[string]interface{})) - page, err := service.GetAPIKeys(p.Context, project.ID, cursor) - if err != nil { - return nil, err - } - - apiKeysPage := apiKeysPage{ - APIKeys: page.APIKeys, - TotalCount: page.TotalCount, - Offset: page.Offset, - Limit: page.Limit, - Order: int(page.Order), - OrderDirection: int(page.OrderDirection), - Search: page.Search, - CurrentPage: page.CurrentPage, - PageCount: page.PageCount, - } - - return apiKeysPage, err - }, - }, - FieldUsage: &graphql.Field{ - Type: types.projectUsage, - Args: graphql.FieldConfigArgument{ - SinceArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.DateTime), - }, - BeforeArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.DateTime), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - project, _ := p.Source.(*console.Project) - - since := p.Args[SinceArg].(time.Time) - before := p.Args[BeforeArg].(time.Time) - - usage, err := service.GetProjectUsage(p.Context, project.ID, since, before) - if err != nil { - return nil, err - } - - return usage, nil - }, - }, - FieldBucketUsages: &graphql.Field{ - Type: types.bucketUsagePage, - Args: graphql.FieldConfigArgument{ - BeforeArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(graphql.DateTime), - }, - CursorArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.bucketUsageCursor), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - project, _ := p.Source.(*console.Project) - - before := p.Args[BeforeArg].(time.Time) - cursor := fromMapBucketUsageCursor(p.Args[CursorArg].(map[string]interface{})) - - page, err := service.GetBucketTotals(p.Context, project.ID, cursor, before) - if err != nil { - return nil, err - } - - return page, nil - }, - }, - }, - }) -} - -// graphqlProjectInput creates graphql.InputObject type needed to create/update satellite.Project. -func graphqlProjectInput() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: ProjectInputType, - Fields: graphql.InputObjectConfigFieldMap{ - FieldName: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - FieldDescription: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - }, - }) -} - -// graphqlProjectLimit creates graphql.InputObject type needed to create/update satellite.Project. -func graphqlProjectLimit() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: ProjectLimitType, - Fields: graphql.InputObjectConfigFieldMap{ - FieldStorageLimit: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - FieldBandwidthLimit: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - }, - }) -} - -// graphqlBucketUsageCursor creates bucket usage cursor graphql input type. -func graphqlProjectsCursor() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: ProjectsCursorInputType, - Fields: graphql.InputObjectConfigFieldMap{ - LimitArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - PageArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - }, - }) -} - -// graphqlBucketUsageCursor creates bucket usage cursor graphql input type. -func graphqlBucketUsageCursor() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: BucketUsageCursorInputType, - Fields: graphql.InputObjectConfigFieldMap{ - SearchArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - LimitArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - PageArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - }, - }) -} - -// graphqlBucketUsage creates bucket usage grapqhl type. -func graphqlBucketUsage() *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: BucketUsageType, - Fields: graphql.Fields{ - FieldBucketName: &graphql.Field{ - Type: graphql.String, - }, - FieldStorage: &graphql.Field{ - Type: graphql.Float, - }, - FieldEgress: &graphql.Field{ - Type: graphql.Float, - }, - FieldObjectCount: &graphql.Field{ - Type: graphql.Float, - }, - FieldSegmentCount: &graphql.Field{ - Type: graphql.Float, - }, - SinceArg: &graphql.Field{ - Type: graphql.DateTime, - }, - BeforeArg: &graphql.Field{ - Type: graphql.DateTime, - }, - }, - }) -} - -// graphqlProjectsPage creates a projects page graphql object. -func graphqlProjectsPage(types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectsPageType, - Fields: graphql.Fields{ - FieldProjects: &graphql.Field{ - Type: graphql.NewList(types.project), - }, - LimitArg: &graphql.Field{ - Type: graphql.Int, - }, - OffsetArg: &graphql.Field{ - Type: graphql.Int, - }, - FieldPageCount: &graphql.Field{ - Type: graphql.Int, - }, - FieldCurrentPage: &graphql.Field{ - Type: graphql.Int, - }, - FieldTotalCount: &graphql.Field{ - Type: graphql.Int, - }, - }, - }) -} - -// graphqlBucketUsagePage creates bucket usage page graphql object. -func graphqlBucketUsagePage(types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: BucketUsagePageType, - Fields: graphql.Fields{ - FieldBucketUsages: &graphql.Field{ - Type: graphql.NewList(types.bucketUsage), - }, - SearchArg: &graphql.Field{ - Type: graphql.String, - }, - LimitArg: &graphql.Field{ - Type: graphql.Int, - }, - OffsetArg: &graphql.Field{ - Type: graphql.Int, - }, - FieldPageCount: &graphql.Field{ - Type: graphql.Int, - }, - FieldCurrentPage: &graphql.Field{ - Type: graphql.Int, - }, - FieldTotalCount: &graphql.Field{ - Type: graphql.Int, - }, - }, - }) -} - -// graphqlProjectUsage creates project usage graphql type. -func graphqlProjectUsage() *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectUsageType, - Fields: graphql.Fields{ - FieldStorage: &graphql.Field{ - Type: graphql.Float, - }, - FieldEgress: &graphql.Field{ - Type: graphql.Float, - }, - FieldObjectCount: &graphql.Field{ - Type: graphql.Float, - }, - FieldSegmentCount: &graphql.Field{ - Type: graphql.Float, - }, - SinceArg: &graphql.Field{ - Type: graphql.DateTime, - }, - BeforeArg: &graphql.Field{ - Type: graphql.DateTime, - }, - }, - }) -} - -// fromMapProjectInfo creates console.UpsertProjectInfo from input args. -func fromMapProjectInfo(args map[string]interface{}) (project console.UpsertProjectInfo) { - project.Name, _ = args[FieldName].(string) - project.Description, _ = args[FieldDescription].(string) - - return -} - -// fromMapProjectInfoProjectLimits creates console.UpsertProjectInfo from input args. -func fromMapProjectInfoProjectLimits(projectInfo, projectLimits map[string]interface{}) (project console.UpsertProjectInfo, err error) { - project.Name, _ = projectInfo[FieldName].(string) - project.Description, _ = projectInfo[FieldDescription].(string) - storageLimit, err := strconv.Atoi(projectLimits[FieldStorageLimit].(string)) - if err != nil { - return project, err - } - project.StorageLimit = memory.Size(storageLimit) - bandwidthLimit, err := strconv.Atoi(projectLimits[FieldBandwidthLimit].(string)) - if err != nil { - return project, err - } - project.BandwidthLimit = memory.Size(bandwidthLimit) - - return -} - -// fromMapProjectsCursor creates console.ProjectsCursor from input args. -func fromMapProjectsCursor(args map[string]interface{}) (cursor console.ProjectsCursor) { - cursor.Limit = args[LimitArg].(int) - cursor.Page = args[PageArg].(int) - return -} - -// fromMapBucketUsageCursor creates accounting.BucketUsageCursor from input args. -func fromMapBucketUsageCursor(args map[string]interface{}) (cursor accounting.BucketUsageCursor) { - limit, _ := args[LimitArg].(int) - page, _ := args[PageArg].(int) - - cursor.Limit = uint(limit) - cursor.Page = uint(page) - cursor.Search, _ = args[SearchArg].(string) - return -} - -func cursorArgsToProjectMembersCursor(args map[string]interface{}) console.ProjectMembersCursor { - limit, _ := args[LimitArg].(int) - page, _ := args[PageArg].(int) - order, _ := args[OrderArg].(int) - orderDirection, _ := args[OrderDirectionArg].(int) - - var cursor console.ProjectMembersCursor - - cursor.Limit = uint(limit) - cursor.Page = uint(page) - cursor.Order = console.ProjectMemberOrder(order) - cursor.OrderDirection = console.OrderDirection(orderDirection) - cursor.Search, _ = args[SearchArg].(string) - - return cursor -} - -func cursorArgsToAPIKeysCursor(args map[string]interface{}) console.APIKeyCursor { - limit, _ := args[LimitArg].(int) - page, _ := args[PageArg].(int) - order, _ := args[OrderArg].(int) - orderDirection, _ := args[OrderDirectionArg].(int) - - var cursor console.APIKeyCursor - - cursor.Limit = uint(limit) - cursor.Page = uint(page) - cursor.Order = console.APIKeyOrder(order) - cursor.OrderDirection = console.OrderDirection(orderDirection) - cursor.Search, _ = args[SearchArg].(string) - - return cursor -} diff --git a/satellite/console/consoleweb/consoleql/projectmember.go b/satellite/console/consoleweb/consoleql/projectmember.go deleted file mode 100644 index da9599faf..000000000 --- a/satellite/console/consoleweb/consoleql/projectmember.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "time" - - "github.com/graphql-go/graphql" - - "storj.io/storj/satellite/console" -) - -const ( - // ProjectMemberType is a graphql type name for project member. - ProjectMemberType = "projectMember" - // ProjectInvitationType is a graphql type name for project member invitation. - ProjectInvitationType = "projectInvitation" - // FieldJoinedAt is a field name for joined at timestamp. - FieldJoinedAt = "joinedAt" - // FieldExpired is a field name for expiration status. - FieldExpired = "expired" -) - -// graphqlProjectMember creates projectMember type. -func graphqlProjectMember(service *console.Service, types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectMemberType, - Fields: graphql.Fields{ - UserType: &graphql.Field{ - Type: types.user, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - member, _ := p.Source.(projectMember) - // company sub query expects pointer - return member.User, nil - }, - }, - FieldJoinedAt: &graphql.Field{ - Type: graphql.DateTime, - }, - }, - }) -} - -// graphqlProjectInvitation creates projectInvitation type. -func graphqlProjectInvitation() *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectInvitationType, - Fields: graphql.Fields{ - FieldEmail: &graphql.Field{ - Type: graphql.String, - }, - FieldCreatedAt: &graphql.Field{ - Type: graphql.DateTime, - }, - FieldExpired: &graphql.Field{ - Type: graphql.Boolean, - }, - }, - }) -} - -func graphqlProjectMembersCursor() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: ProjectMembersCursorInputType, - Fields: graphql.InputObjectConfigFieldMap{ - SearchArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.String), - }, - LimitArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - PageArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - OrderArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - OrderDirectionArg: &graphql.InputObjectFieldConfig{ - Type: graphql.NewNonNull(graphql.Int), - }, - }, - }) -} - -func graphqlProjectMembersAndInvitationsPage(types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectMembersAndInvitationsPageType, - Fields: graphql.Fields{ - FieldProjectMembers: &graphql.Field{ - Type: graphql.NewList(types.projectMember), - }, - FieldProjectInvitations: &graphql.Field{ - Type: graphql.NewList(types.projectInvitation), - }, - SearchArg: &graphql.Field{ - Type: graphql.String, - }, - LimitArg: &graphql.Field{ - Type: graphql.Int, - }, - OrderArg: &graphql.Field{ - Type: graphql.Int, - }, - OrderDirectionArg: &graphql.Field{ - Type: graphql.Int, - }, - OffsetArg: &graphql.Field{ - Type: graphql.Int, - }, - FieldPageCount: &graphql.Field{ - Type: graphql.Int, - }, - FieldCurrentPage: &graphql.Field{ - Type: graphql.Int, - }, - FieldTotalCount: &graphql.Field{ - Type: graphql.Int, - }, - }, - }) -} - -// projectMember encapsulates User and joinedAt. -type projectMember struct { - User *console.User - JoinedAt time.Time -} - -// projectInvitation encapsulates a console.ProjectInvitation and its expiration status. -type projectInvitation struct { - Email string - CreatedAt time.Time - Expired bool -} - -type projectMembersPage struct { - ProjectMembers []projectMember - ProjectInvitations []projectInvitation - - Search string - Limit uint - Order int - OrderDirection int - Offset uint64 - - PageCount uint - CurrentPage uint - TotalCount uint64 -} diff --git a/satellite/console/consoleweb/consoleql/query.go b/satellite/console/consoleweb/consoleql/query.go deleted file mode 100644 index 4020e4888..000000000 --- a/satellite/console/consoleweb/consoleql/query.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" - - "storj.io/storj/satellite/console" - "storj.io/storj/satellite/mailservice" -) - -const ( - // Query is immutable graphql request. - Query = "query" - // ProjectQuery is a query name for project. - ProjectQuery = "project" - // OwnedProjectsQuery is a query name for projects owned by an account. - OwnedProjectsQuery = "ownedProjects" - // MyProjectsQuery is a query name for projects related to account. - MyProjectsQuery = "myProjects" -) - -// rootQuery creates query for graphql populated by AccountsClient. -func rootQuery(service *console.Service, mailService *mailservice.Service, types *TypeCreator) *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: Query, - Fields: graphql.Fields{ - ProjectQuery: &graphql.Field{ - Type: types.project, - Args: graphql.FieldConfigArgument{ - FieldID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - FieldPublicID: &graphql.ArgumentConfig{ - Type: graphql.String, - DefaultValue: "", - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - - projectID, err := getProjectID(p) - if err != nil { - return nil, err - } - - project, err := service.GetProject(p.Context, projectID) - if err != nil { - return nil, err - } - - return project, nil - }, - }, - OwnedProjectsQuery: &graphql.Field{ - Type: types.projectsPage, - Args: graphql.FieldConfigArgument{ - CursorArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.projectsCursor), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - cursor := fromMapProjectsCursor(p.Args[CursorArg].(map[string]interface{})) - page, err := service.GetUsersOwnedProjectsPage(p.Context, cursor) - return page, err - }, - }, - MyProjectsQuery: &graphql.Field{ - Type: graphql.NewList(types.project), - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - projects, err := service.GetUsersProjects(p.Context) - if err != nil { - return nil, err - } - - return projects, nil - }, - }, - }, - }) -} diff --git a/satellite/console/consoleweb/consoleql/query_test.go b/satellite/console/consoleweb/consoleql/query_test.go deleted file mode 100644 index f158114ab..000000000 --- a/satellite/console/consoleweb/consoleql/query_test.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql_test - -import ( - "fmt" - "testing" - "time" - - "github.com/graphql-go/graphql" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zaptest" - - "storj.io/common/testcontext" - "storj.io/storj/private/testplanet" - "storj.io/storj/private/testredis" - "storj.io/storj/satellite/accounting" - "storj.io/storj/satellite/accounting/live" - "storj.io/storj/satellite/analytics" - "storj.io/storj/satellite/console" - "storj.io/storj/satellite/console/consoleauth" - "storj.io/storj/satellite/console/consoleweb/consoleql" - "storj.io/storj/satellite/console/restkeys" - "storj.io/storj/satellite/mailservice" - "storj.io/storj/satellite/payments" - "storj.io/storj/satellite/payments/paymentsconfig" - "storj.io/storj/satellite/payments/stripe" -) - -func TestGraphqlQuery(t *testing.T) { - testplanet.Run(t, testplanet.Config{SatelliteCount: 1}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) { - sat := planet.Satellites[0] - db := sat.DB - log := zaptest.NewLogger(t) - - analyticsService := analytics.NewService(log, analytics.Config{}, "test-satellite") - - redis, err := testredis.Mini(ctx) - require.NoError(t, err) - defer ctx.Check(redis.Close) - - cache, err := live.OpenCache(ctx, log.Named("cache"), live.Config{StorageBackend: "redis://" + redis.Addr() + "?db=0"}) - require.NoError(t, err) - - projectLimitCache := accounting.NewProjectLimitCache(db.ProjectAccounting(), 0, 0, 0, accounting.ProjectLimitConfig{CacheCapacity: 100}) - - projectUsage := accounting.NewService(db.ProjectAccounting(), cache, projectLimitCache, *sat.Metabase.DB, 5*time.Minute, -10*time.Second) - - // TODO maybe switch this test to testplanet to avoid defining config and Stripe service - pc := paymentsconfig.Config{ - UsagePrice: paymentsconfig.ProjectUsagePrice{ - StorageTB: "10", - EgressTB: "45", - Segment: "0.0000022", - }, - } - - prices, err := pc.UsagePrice.ToModel() - require.NoError(t, err) - - priceOverrides, err := pc.UsagePriceOverrides.ToModels() - require.NoError(t, err) - - paymentsService, err := stripe.NewService( - log.Named("payments.stripe:service"), - stripe.NewStripeMock( - db.StripeCoinPayments().Customers(), - db.Console().Users(), - ), - pc.StripeCoinPayments, - db.StripeCoinPayments(), - db.Wallets(), - db.Billing(), - db.Console().Projects(), - db.Console().Users(), - db.ProjectAccounting(), - prices, - priceOverrides, - pc.PackagePlans.Packages, - pc.BonusRate, - nil, - ) - require.NoError(t, err) - - service, err := console.NewService( - log.Named("console"), - db.Console(), - restkeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.RESTKeys), - db.ProjectAccounting(), - projectUsage, - sat.API.Buckets.Service, - paymentsService.Accounts(), - // TODO: do we need a payment deposit wallet here? - nil, - db.Billing(), - analyticsService, - consoleauth.NewService(consoleauth.Config{ - TokenExpirationTime: 24 * time.Hour, - }, &consoleauth.Hmac{Secret: []byte("my-suppa-secret-key")}), - nil, - "", - "", - console.Config{ - PasswordCost: console.TestPasswordCost, - DefaultProjectLimit: 5, - Session: console.SessionConfig{ - Duration: time.Hour, - }, - }, - ) - require.NoError(t, err) - - mailService, err := mailservice.New(log, &discardSender{}, "testdata") - require.NoError(t, err) - defer ctx.Check(mailService.Close) - - rootObject := make(map[string]interface{}) - rootObject["origin"] = "http://doesntmatter.com/" - rootObject[consoleql.ActivationPath] = "?activationToken=" - rootObject[consoleql.LetUsKnowURL] = "letUsKnowURL" - rootObject[consoleql.ContactInfoURL] = "contactInfoURL" - rootObject[consoleql.TermsAndConditionsURL] = "termsAndConditionsURL" - - creator := consoleql.TypeCreator{} - err = creator.Create(log, service, mailService) - require.NoError(t, err) - - schema, err := graphql.NewSchema(graphql.SchemaConfig{ - Query: creator.RootQuery(), - Mutation: creator.RootMutation(), - }) - require.NoError(t, err) - - createUser := console.CreateUser{ - FullName: "John", - ShortName: "", - Email: "mtest@mail.test", - Password: "123a123", - SignupPromoCode: "promo1", - } - - regToken, err := service.CreateRegToken(ctx, 2) - require.NoError(t, err) - - rootUser, err := service.CreateUser(ctx, createUser, regToken.Secret) - require.NoError(t, err) - - couponType, err := paymentsService.Accounts().Setup(ctx, rootUser.ID, rootUser.Email, rootUser.SignupPromoCode) - - var signupCouponType payments.CouponType = payments.SignupCoupon - - require.NoError(t, err) - assert.Equal(t, signupCouponType, couponType) - - t.Run("Activation", func(t *testing.T) { - activationToken, err := service.GenerateActivationToken( - ctx, - rootUser.ID, - "mtest@mail.test", - ) - require.NoError(t, err) - _, err = service.ActivateAccount(ctx, activationToken) - require.NoError(t, err) - rootUser.Email = "mtest@mail.test" - }) - - tokenInfo, err := service.Token(ctx, console.AuthUser{Email: createUser.Email, Password: createUser.Password}) - require.NoError(t, err) - - userCtx, err := service.TokenAuth(ctx, tokenInfo.Token, time.Now()) - require.NoError(t, err) - - testQuery := func(t *testing.T, query string) interface{} { - result := graphql.Do(graphql.Params{ - Schema: schema, - Context: userCtx, - RequestString: query, - RootObject: rootObject, - }) - - for _, err := range result.Errors { - assert.NoError(t, err) - } - require.False(t, result.HasErrors()) - - return result.Data - } - - createdProject, err := service.CreateProject(userCtx, console.UpsertProjectInfo{ - Name: "TestProject", - }) - require.NoError(t, err) - - // "query {project(id:\"%s\"){id,name,members(offset:0, limit:50){user{fullName,shortName,email}},apiKeys{name,id,createdAt,projectID}}}" - t.Run("Project query base info", func(t *testing.T) { - query := fmt.Sprintf( - "query {project(id:\"%s\"){id,name,publicId,description,createdAt}}", - createdProject.ID.String(), - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - project := data[consoleql.ProjectQuery].(map[string]interface{}) - - assert.Equal(t, createdProject.ID.String(), project[consoleql.FieldID]) - assert.Equal(t, createdProject.PublicID.String(), project[consoleql.FieldPublicID]) - assert.Equal(t, createdProject.Name, project[consoleql.FieldName]) - assert.Equal(t, createdProject.Description, project[consoleql.FieldDescription]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(project[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, createdProject.CreatedAt.Equal(createdAt)) - - // test getting by publicId - query = fmt.Sprintf( - "query {project(publicId:\"%s\"){id,name,publicId,description,createdAt}}", - createdProject.PublicID.String(), - ) - - result = testQuery(t, query) - - data = result.(map[string]interface{}) - project = data[consoleql.ProjectQuery].(map[string]interface{}) - - assert.Equal(t, createdProject.ID.String(), project[consoleql.FieldID]) - assert.Equal(t, createdProject.PublicID.String(), project[consoleql.FieldPublicID]) - }) - - regTokenUser1, err := service.CreateRegToken(ctx, 2) - require.NoError(t, err) - - user1, err := service.CreateUser(userCtx, console.CreateUser{ - FullName: "Mickey Last", - ShortName: "Last", - Password: "123a123", - Email: "muu1@mail.test", - }, regTokenUser1.Secret) - require.NoError(t, err) - - t.Run("Activation", func(t *testing.T) { - activationToken1, err := service.GenerateActivationToken( - ctx, - user1.ID, - "muu1@mail.test", - ) - require.NoError(t, err) - _, err = service.ActivateAccount(ctx, activationToken1) - require.NoError(t, err) - user1.Email = "muu1@mail.test" - }) - - regTokenUser2, err := service.CreateRegToken(ctx, 2) - require.NoError(t, err) - - user2, err := service.CreateUser(userCtx, console.CreateUser{ - FullName: "Dubas Name", - ShortName: "Name", - Email: "muu2@mail.test", - Password: "123a123", - }, regTokenUser2.Secret) - require.NoError(t, err) - - t.Run("Activation", func(t *testing.T) { - activationToken2, err := service.GenerateActivationToken( - ctx, - user2.ID, - "muu2@mail.test", - ) - require.NoError(t, err) - _, err = service.ActivateAccount(ctx, activationToken2) - require.NoError(t, err) - user2.Email = "muu2@mail.test" - }) - - users, err := service.AddProjectMembers(userCtx, createdProject.ID, []string{ - user1.Email, - user2.Email, - }) - require.NoError(t, err) - assert.Equal(t, 2, len(users)) - - t.Run("Project query team members", func(t *testing.T) { - query := fmt.Sprintf( - "query {project(id: \"%s\") {membersAndInvitations( cursor: { limit: %d, search: \"%s\", page: %d, order: %d, orderDirection: %d } ) { projectMembers{ user { id, fullName, shortName, email, createdAt }, joinedAt }, search, limit, order, offset, pageCount, currentPage, totalCount } } }", - createdProject.ID.String(), - 5, - "", - 1, - 1, - 2) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - project := data[consoleql.ProjectQuery].(map[string]interface{}) - members := project[consoleql.FieldMembersAndInvitations].(map[string]interface{}) - projectMembers := members[consoleql.FieldProjectMembers].([]interface{}) - - assert.Equal(t, 3, len(projectMembers)) - - testUser := func(t *testing.T, actual map[string]interface{}, expected *console.User) { - 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)) - } - - var foundRoot, foundU1, foundU2 bool - - for _, entry := range projectMembers { - member := entry.(map[string]interface{}) - user := member[consoleql.UserType].(map[string]interface{}) - - id := user[consoleql.FieldID].(string) - switch id { - case rootUser.ID.String(): - foundRoot = true - testUser(t, user, rootUser) - case user1.ID.String(): - foundU1 = true - testUser(t, user, user1) - case user2.ID.String(): - foundU2 = true - testUser(t, user, user2) - } - } - - assert.True(t, foundRoot) - assert.True(t, foundU1) - assert.True(t, foundU2) - }) - - keyInfo1, _, err := service.CreateAPIKey(userCtx, createdProject.ID, "key1") - require.NoError(t, err) - - keyInfo2, _, err := service.CreateAPIKey(userCtx, createdProject.ID, "key2") - require.NoError(t, err) - - t.Run("Project query api keys", func(t *testing.T) { - query := fmt.Sprintf( - "query {project(id: \"%s\") {apiKeys( cursor: { limit: %d, search: \"%s\", page: %d, order: %d, orderDirection: %d } ) { apiKeys { id, name, createdAt, projectID }, search, limit, order, offset, pageCount, currentPage, totalCount } } }", - createdProject.ID.String(), - 5, - "", - 1, - 1, - 2) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - project := data[consoleql.ProjectQuery].(map[string]interface{}) - keys := project[consoleql.FieldAPIKeys].(map[string]interface{}) - apiKeys := keys[consoleql.FieldAPIKeys].([]interface{}) - - assert.Equal(t, 2, len(apiKeys)) - - testAPIKey := func(t *testing.T, actual map[string]interface{}, expected *console.APIKeyInfo) { - assert.Equal(t, expected.Name, actual[consoleql.FieldName]) - assert.Equal(t, expected.ProjectID.String(), actual[consoleql.FieldProjectID]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(actual[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, expected.CreatedAt.Equal(createdAt)) - } - - var foundKey1, foundKey2 bool - - for _, entry := range apiKeys { - key := entry.(map[string]interface{}) - - id := key[consoleql.FieldID].(string) - switch id { - case keyInfo1.ID.String(): - foundKey1 = true - testAPIKey(t, key, keyInfo1) - case keyInfo2.ID.String(): - foundKey2 = true - testAPIKey(t, key, keyInfo2) - } - } - - assert.True(t, foundKey1) - assert.True(t, foundKey2) - }) - - project2, err := service.CreateProject(userCtx, console.UpsertProjectInfo{ - Name: "Project2", - Description: "Test desc", - }) - require.NoError(t, err) - - t.Run("MyProjects query", func(t *testing.T) { - query := "query {myProjects{id,publicId,name,description,createdAt}}" - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - projectsList := data[consoleql.MyProjectsQuery].([]interface{}) - - assert.Equal(t, 2, len(projectsList)) - - testProject := func(t *testing.T, actual map[string]interface{}, expected *console.Project) { - assert.Equal(t, expected.Name, actual[consoleql.FieldName]) - assert.Equal(t, expected.PublicID.String(), actual[consoleql.FieldPublicID]) - assert.Equal(t, expected.Description, actual[consoleql.FieldDescription]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(actual[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, expected.CreatedAt.Equal(createdAt)) - } - - var foundProj1, foundProj2 bool - - for _, entry := range projectsList { - project := entry.(map[string]interface{}) - - id := project[consoleql.FieldID].(string) - switch id { - case createdProject.ID.String(): - foundProj1 = true - testProject(t, project, createdProject) - case project2.ID.String(): - foundProj2 = true - testProject(t, project, project2) - } - } - - assert.True(t, foundProj1) - assert.True(t, foundProj2) - }) - t.Run("OwnedProjects query", func(t *testing.T) { - query := fmt.Sprintf( - "query {ownedProjects( cursor: { limit: %d, page: %d } ) {projects{id, publicId, name, ownerId, description, createdAt, memberCount}, limit, offset, pageCount, currentPage, totalCount } }", - 5, - 1, - ) - - result := testQuery(t, query) - - data := result.(map[string]interface{}) - projectsPage := data[consoleql.OwnedProjectsQuery].(map[string]interface{}) - - projectsList := projectsPage[consoleql.FieldProjects].([]interface{}) - assert.Len(t, projectsList, 2) - - assert.EqualValues(t, 1, projectsPage[consoleql.FieldCurrentPage]) - assert.EqualValues(t, 0, projectsPage[consoleql.OffsetArg]) - assert.EqualValues(t, 5, projectsPage[consoleql.LimitArg]) - assert.EqualValues(t, 1, projectsPage[consoleql.FieldPageCount]) - assert.EqualValues(t, 2, projectsPage[consoleql.FieldTotalCount]) - - testProject := func(t *testing.T, actual map[string]interface{}, expected *console.Project, expectedNumMembers int) { - assert.Equal(t, expected.Name, actual[consoleql.FieldName]) - assert.Equal(t, expected.PublicID.String(), actual[consoleql.FieldPublicID]) - assert.Equal(t, expected.Description, actual[consoleql.FieldDescription]) - - createdAt := time.Time{} - err := createdAt.UnmarshalText([]byte(actual[consoleql.FieldCreatedAt].(string))) - - assert.NoError(t, err) - assert.True(t, expected.CreatedAt.Equal(createdAt)) - - assert.EqualValues(t, expectedNumMembers, actual[consoleql.FieldMemberCount]) - } - - var foundProj1, foundProj2 bool - - for _, entry := range projectsList { - project := entry.(map[string]interface{}) - - id := project[consoleql.FieldID].(string) - switch id { - case createdProject.ID.String(): - foundProj1 = true - testProject(t, project, createdProject, 3) - case project2.ID.String(): - foundProj2 = true - testProject(t, project, project2, 1) - } - } - - assert.True(t, foundProj1) - assert.True(t, foundProj2) - }) - }) -} diff --git a/satellite/console/consoleweb/consoleql/reward.go b/satellite/console/consoleweb/consoleql/reward.go deleted file mode 100644 index cdf891701..000000000 --- a/satellite/console/consoleweb/consoleql/reward.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" -) - -const ( - // RewardType is a graphql type for reward. - RewardType = "reward" - // FieldAwardCreditInCent is a field name for award credit amount for referrers. - FieldAwardCreditInCent = "awardCreditInCent" - // FieldInviteeCreditInCents is a field name for credit amount rewarded to invitees. - FieldInviteeCreditInCents = "inviteeCreditInCents" - // FieldRedeemableCap is a field name for the total redeemable amount of the reward offer. - FieldRedeemableCap = "redeemableCap" - // FieldAwardCreditDurationDays is a field name for the valid time frame of current award credit. - FieldAwardCreditDurationDays = "awardCreditDurationDays" - // FieldInviteeCreditDurationDays is a field name for the valid time frame of current invitee credit. - FieldInviteeCreditDurationDays = "inviteeCreditDurationDays" - // FieldExpiresAt is a field name for the expiration time of a reward offer. - FieldExpiresAt = "expiresAt" - // FieldType is a field name for the type of reward offers. - FieldType = "type" - // FieldStatus is a field name for the status of reward offers. - FieldStatus = "status" -) - -func graphqlReward() *graphql.Object { - return graphql.NewObject(graphql.ObjectConfig{ - Name: RewardType, - Fields: graphql.Fields{ - FieldID: &graphql.Field{ - Type: graphql.Int, - }, - FieldAwardCreditInCent: &graphql.Field{ - Type: graphql.Int, - }, - FieldInviteeCreditInCents: &graphql.Field{ - Type: graphql.Int, - }, - FieldRedeemableCap: &graphql.Field{ - Type: graphql.Int, - }, - FieldAwardCreditDurationDays: &graphql.Field{ - Type: graphql.Int, - }, - FieldInviteeCreditDurationDays: &graphql.Field{ - Type: graphql.Int, - }, - FieldType: &graphql.Field{ - Type: graphql.Int, - }, - FieldStatus: &graphql.Field{ - Type: graphql.Int, - }, - FieldExpiresAt: &graphql.Field{ - Type: graphql.String, - }, - }, - }) -} diff --git a/satellite/console/consoleweb/consoleql/schema.go b/satellite/console/consoleweb/consoleql/schema.go deleted file mode 100644 index 553a64802..000000000 --- a/satellite/console/consoleweb/consoleql/schema.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2018 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" - "go.uber.org/zap" - - "storj.io/storj/satellite/console" - "storj.io/storj/satellite/mailservice" -) - -// CreateSchema creates a schema for satellites console graphql api. -func CreateSchema(log *zap.Logger, service *console.Service, mailService *mailservice.Service) (schema graphql.Schema, err error) { - creator := TypeCreator{} - - err = creator.Create(log, service, mailService) - if err != nil { - return - } - - return graphql.NewSchema(graphql.SchemaConfig{ - Query: creator.RootQuery(), - Mutation: creator.RootMutation(), - }) -} diff --git a/satellite/console/consoleweb/consoleql/testdata/Invite.html b/satellite/console/consoleweb/consoleql/testdata/Invite.html deleted file mode 100644 index 6e567cf4d..000000000 --- a/satellite/console/consoleweb/consoleql/testdata/Invite.html +++ /dev/null @@ -1,612 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/satellite/console/consoleweb/consoleql/testdata/Welcome.html b/satellite/console/consoleweb/consoleql/testdata/Welcome.html deleted file mode 100644 index 8607d5ad2..000000000 --- a/satellite/console/consoleweb/consoleql/testdata/Welcome.html +++ /dev/null @@ -1,640 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/satellite/console/consoleweb/consoleql/typecreator.go b/satellite/console/consoleweb/consoleql/typecreator.go deleted file mode 100644 index 9393a21fe..000000000 --- a/satellite/console/consoleweb/consoleql/typecreator.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" - "go.uber.org/zap" - - "storj.io/storj/satellite/console" - "storj.io/storj/satellite/mailservice" -) - -// TypeCreator handles graphql type creation and error checking. -type TypeCreator struct { - query *graphql.Object - mutation *graphql.Object - - user *graphql.Object - reward *graphql.Object - project *graphql.Object - projectUsage *graphql.Object - projectsPage *graphql.Object - bucketUsage *graphql.Object - bucketUsagePage *graphql.Object - projectMember *graphql.Object - projectInvitation *graphql.Object - projectMembersAndInvitationsPage *graphql.Object - apiKeyPage *graphql.Object - apiKeyInfo *graphql.Object - createAPIKey *graphql.Object - - userInput *graphql.InputObject - projectInput *graphql.InputObject - projectLimit *graphql.InputObject - projectsCursor *graphql.InputObject - bucketUsageCursor *graphql.InputObject - projectMembersCursor *graphql.InputObject - apiKeysCursor *graphql.InputObject -} - -// Create create types and check for error. -func (c *TypeCreator) Create(log *zap.Logger, service *console.Service, mailService *mailservice.Service) error { - // inputs - c.userInput = graphqlUserInput() - if err := c.userInput.Error(); err != nil { - return err - } - - c.projectInput = graphqlProjectInput() - if err := c.projectInput.Error(); err != nil { - return err - } - - c.projectLimit = graphqlProjectLimit() - if err := c.projectLimit.Error(); err != nil { - return err - } - - c.bucketUsageCursor = graphqlBucketUsageCursor() - if err := c.bucketUsageCursor.Error(); err != nil { - return err - } - - c.projectMembersCursor = graphqlProjectMembersCursor() - if err := c.projectMembersCursor.Error(); err != nil { - return err - } - - c.apiKeysCursor = graphqlAPIKeysCursor() - if err := c.apiKeysCursor.Error(); err != nil { - return err - } - - // entities - c.user = graphqlUser() - if err := c.user.Error(); err != nil { - return err - } - - c.reward = graphqlReward() - if err := c.reward.Error(); err != nil { - return err - } - - c.projectUsage = graphqlProjectUsage() - if err := c.projectUsage.Error(); err != nil { - return err - } - - c.bucketUsage = graphqlBucketUsage() - if err := c.bucketUsage.Error(); err != nil { - return err - } - - c.bucketUsagePage = graphqlBucketUsagePage(c) - if err := c.bucketUsagePage.Error(); err != nil { - return err - } - - c.apiKeyInfo = graphqlAPIKeyInfo() - if err := c.apiKeyInfo.Error(); err != nil { - return err - } - - c.createAPIKey = graphqlCreateAPIKey(c) - if err := c.createAPIKey.Error(); err != nil { - return err - } - - c.projectMember = graphqlProjectMember(service, c) - if err := c.projectMember.Error(); err != nil { - return err - } - - c.projectInvitation = graphqlProjectInvitation() - if err := c.projectInvitation.Error(); err != nil { - return err - } - - c.projectMembersAndInvitationsPage = graphqlProjectMembersAndInvitationsPage(c) - if err := c.projectMembersAndInvitationsPage.Error(); err != nil { - return err - } - - c.apiKeyPage = graphqlAPIKeysPage(c) - if err := c.apiKeyPage.Error(); err != nil { - return err - } - - c.project = graphqlProject(service, c) - if err := c.project.Error(); err != nil { - return err - } - - c.projectsCursor = graphqlProjectsCursor() - if err := c.projectsCursor.Error(); err != nil { - return err - } - - c.projectsPage = graphqlProjectsPage(c) - if err := c.projectsPage.Error(); err != nil { - return err - } - - // root objects - c.query = rootQuery(service, mailService, c) - if err := c.query.Error(); err != nil { - return err - } - - c.mutation = rootMutation(log, service, mailService, c) - if err := c.mutation.Error(); err != nil { - return err - } - - return nil -} - -// RootQuery returns instance of query *graphql.Object. -func (c *TypeCreator) RootQuery() *graphql.Object { - return c.query -} - -// RootMutation returns instance of mutation *graphql.Object. -func (c *TypeCreator) RootMutation() *graphql.Object { - return c.mutation -} diff --git a/satellite/console/consoleweb/consoleql/user.go b/satellite/console/consoleweb/consoleql/user.go deleted file mode 100644 index b810ecc14..000000000 --- a/satellite/console/consoleweb/consoleql/user.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package consoleql - -import ( - "github.com/graphql-go/graphql" -) - -const ( - // UserType is a graphql type for user. - UserType = "user" - // UserInputType is a graphql type for user input. - UserInputType = "userInput" - // FieldID is a field name for id. - FieldID = "id" - // FieldEmail is a field name for email. - FieldEmail = "email" - // FieldPassword is a field name for password. - FieldPassword = "password" - // FieldFullName is a field name for "first name". - FieldFullName = "fullName" - // FieldShortName is a field name for "last name". - FieldShortName = "shortName" - // FieldCreatedAt is a field name for created at timestamp. - FieldCreatedAt = "createdAt" -) - -// base graphql config for user. -func baseUserConfig() graphql.ObjectConfig { - return graphql.ObjectConfig{ - Name: UserType, - Fields: graphql.Fields{ - FieldID: &graphql.Field{ - Type: graphql.String, - }, - FieldEmail: &graphql.Field{ - Type: graphql.String, - }, - FieldFullName: &graphql.Field{ - Type: graphql.String, - }, - FieldShortName: &graphql.Field{ - Type: graphql.String, - }, - FieldCreatedAt: &graphql.Field{ - Type: graphql.DateTime, - }, - }, - } -} - -// graphqlUser creates *graphql.Object type representation of satellite.User. -func graphqlUser() *graphql.Object { - // TODO: simplify - return graphql.NewObject(baseUserConfig()) -} - -// graphqlUserInput creates graphql.InputObject type needed to register/update satellite.User. -func graphqlUserInput() *graphql.InputObject { - return graphql.NewInputObject(graphql.InputObjectConfig{ - Name: UserInputType, - Fields: graphql.InputObjectConfigFieldMap{ - FieldEmail: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - FieldFullName: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - FieldShortName: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - FieldPassword: &graphql.InputObjectFieldConfig{ - Type: graphql.String, - }, - }, - }) -} diff --git a/satellite/console/consoleweb/endpoints_test.go b/satellite/console/consoleweb/endpoints_test.go index 7fbc0bdf5..3e0c49b7f 100644 --- a/satellite/console/consoleweb/endpoints_test.go +++ b/satellite/console/consoleweb/endpoints_test.go @@ -334,43 +334,6 @@ func TestBuckets(t *testing.T) { } { // get bucket usages - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "before": "2021-05-12T18:32:30.533Z", - "limit": 7, - "search": "", - "page": 1, - }, - "query": ` - query ($projectId: String!, $before: DateTime!, $limit: Int!, $search: String!, $page: Int!) { - project(id: $projectId) { - bucketUsages(before: $before, cursor: {limit: $limit, search: $search, page: $page}) { - bucketUsages { - bucketName - storage - egress - objectCount - segmentCount - since - before - __typename - } - search - limit - offset - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "bucketUsagePage") - require.Equal(t, http.StatusOK, resp.StatusCode) - params := url.Values{ "projectID": {test.defaultProjectID()}, "before": {time.Now().Add(time.Second).Format(apigen.DateFormat)}, @@ -379,7 +342,7 @@ func TestBuckets(t *testing.T) { "page": {"1"}, } - resp, body = test.request(http.MethodGet, "/buckets/usage-totals?"+params.Encode(), nil) + resp, body := test.request(http.MethodGet, "/buckets/usage-totals?"+params.Encode(), nil) require.Equal(t, http.StatusOK, resp.StatusCode) var page accounting.BucketUsagePage require.NoError(t, json.Unmarshal([]byte(body), &page)) @@ -406,66 +369,6 @@ func TestAPIKeys(t *testing.T) { user := test.defaultUser() test.login(user.email, user.password) - { // Post_GenerateApiKey - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "name": user.email, - }, - "query": ` - mutation ($projectId: String!, $name: String!) { - createAPIKey(projectID: $projectId, name: $name) { - key - keyInfo { - id - name - createdAt - __typename - } - __typename - } - }`})) - require.Contains(t, body, "createAPIKey") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - - { // Get_APIKeyInfoByProjectId - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "orderDirection": 1, - "projectId": test.defaultProjectID(), - "limit": 6, - "search": ``, - "page": 1, - "order": 1, - }, - "query": ` - query ($projectId: String!, $limit: Int!, $search: String!, $page: Int!, $order: Int!, $orderDirection: Int!) { - project(id: $projectId) { - apiKeys(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { - apiKeys { - id - name - createdAt - __typename - } - search - limit - order - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "apiKeysPage") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - { // Get_ProjectAPIKeys var projects console.APIKeyPage path := "/api-keys/list-paged?projectID=" + test.defaultProjectID() + "&search=''&limit=6&page=1&order=1&orderDirection=1" @@ -517,27 +420,8 @@ func TestProjects(t *testing.T) { }, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) { test := newTest(t, ctx, planet) user := test.defaultUser() - user2 := test.registerUser("user@mail.test", "#$Rnkl12i3nkljfds") test.login(user.email, user.password) - { // Get_ProjectId - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "query": ` - { - myProjects { - name - id - description - createdAt - ownerId - __typename - } - }`})) - require.Contains(t, body, test.defaultProjectID()) - require.Equal(t, http.StatusOK, resp.StatusCode) - } - { // Get_Salt projectID := test.defaultProjectID() id, err := uuid.FromString(projectID) @@ -578,45 +462,6 @@ func TestProjects(t *testing.T) { require.NotEmpty(t, projects) } - { // Get_ProjectInfo - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "before": "2021-05-12T18:32:30.533Z", - "limit": 7, - "search": "", - "page": 1, - }, - "query": ` - query ($projectId: String!, $before: DateTime!, $limit: Int!, $search: String!, $page: Int!) { - project(id: $projectId) { - bucketUsages(before: $before, cursor: {limit: $limit, search: $search, page: $page}) { - bucketUsages { - bucketName - storage - egress - objectCount - segmentCount - since - before - __typename - } - search - limit - offset - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "bucketUsagePage") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - { // Get_ProjectUsageLimitById resp, body := test.request(http.MethodGet, `/projects/`+test.defaultProjectID()+`/usage-limits`, nil) require.Equal(t, http.StatusOK, resp.StatusCode) @@ -631,171 +476,8 @@ func TestProjects(t *testing.T) { require.NotEmpty(t, projects.Projects) } - { // Get_OwnedProjects - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "limit": 7, - "page": 1, - }, - "query": ` - query ($limit: Int!, $page: Int!) { - ownedProjects(cursor: {limit: $limit, page: $page}) { - projects { - id - name - ownerId - description - createdAt - memberCount - __typename - } - limit - offset - pageCount - currentPage - totalCount - __typename - } - }`})) - require.Contains(t, body, "projectsPage") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - - { // Get_ProjectMembersByProjectId - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - `orderDirection`: 1, - `projectId`: test.defaultProjectID(), - `limit`: 6, - `search`: ``, - `page`: 1, - `order`: 1, - }, - "query": ` - query ($projectId: String!, $limit: Int!, $search: String!, $page: Int!, $order: Int!, $orderDirection: Int!) { - project(id: $projectId) { - membersAndInvitations(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { - projectMembers { - user { - id - fullName - shortName - email - __typename - } - joinedAt - __typename - } - search - limit - order - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "projectMembersAndInvitationsPage") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - - { // Post_AddUserToProject - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "emails": []string{user2.email}, - }, - "query": ` - mutation ($projectId: String!, $emails: [String!]!) { - addProjectMembers(projectID: $projectId, email: $emails) { - id - __typename - } - }`})) - require.Contains(t, body, "addProjectMembers") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - - { // Post_RemoveUserFromProject - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "emails": []string{user2.email}, - }, - "query": ` - mutation ($projectId: String!, $emails: [String!]!) { - deleteProjectMembers(projectID: $projectId, email: $emails) { - id - __typename - } - }`})) - require.Contains(t, body, "deleteProjectMembers") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - - { // Post_AddMultipleUsersToProjectWhere1UserIsInvalid - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "emails": []string{user2.email, "invalid@mail.test"}, - }, - "query": ` - mutation ($projectId: String!, $emails: [String!]!) { - addProjectMembers(projectID: $projectId, email: $emails) { - id - __typename - } - }`})) - require.Contains(t, body, "addProjectMembers") - require.Equal(t, http.StatusOK, resp.StatusCode) - } - - { // Post_AddMultipleUsersToProjectWhereUserIsAlreadyAMember - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "emails": []string{user2.email, user.email}, - }, - "query": ` - mutation ($projectId: String!, $emails: [String!]!) { - addProjectMembers(projectID: $projectId, email: $emails) { - id - __typename - } - }`})) - require.Contains(t, body, "error") - // TODO: this should return a better error - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - } - { // Post_ProjectRenameInvalid - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - `projectId`: `e4a929a6-cc69-4920-ad06-c84f3c943928`, - `name`: `My Second Project`, - `description`: `___`, - }, - "query": ` - mutation ($projectId: String!, $name: String!, $description: String!) { - updateProject(id: $projectId, projectFields: {name: $name, description: $description}, projectLimits: {storageLimit: "1000", bandwidthLimit: "1000"}) { - name - __typename - } - }`})) - require.Contains(t, body, "error") - // TODO: this should return a better error - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - - resp, body = test.request(http.MethodPatch, fmt.Sprintf("/projects/%s", test.defaultProjectID()), + resp, body := test.request(http.MethodPatch, fmt.Sprintf("/projects/%s", test.defaultProjectID()), test.toJSON(map[string]interface{}{ "name": "My Second Project with a long name", })) @@ -804,24 +486,7 @@ func TestProjects(t *testing.T) { } { // Post_ProjectRename - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - `projectId`: test.defaultProjectID(), - `name`: `Test`, - `description`: `Misc`, - }, - "query": ` - mutation ($projectId: String!, $name: String!, $description: String!) { - updateProject(id: $projectId, projectFields: {name: $name, description: $description}, projectLimits: {storageLimit: "1000", bandwidthLimit: "1000"}) { - name - __typename - } - }`})) - require.Contains(t, body, "updateProject") - require.Equal(t, http.StatusOK, resp.StatusCode) - - resp, _ = test.request(http.MethodPatch, fmt.Sprintf("/projects/%s", test.defaultProjectID()), + resp, _ := test.request(http.MethodPatch, fmt.Sprintf("/projects/%s", test.defaultProjectID()), test.toJSON(map[string]interface{}{ "name": "new name", })) @@ -840,192 +505,12 @@ func TestWrongUser(t *testing.T) { user2 := test.registerUser("user@mail.test", "#$Rnkl12i3nkljfds") test.login(user2.email, user2.password) - { // Get_ProjectInfo - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "before": "2021-05-12T18:32:30.533Z", - "limit": 7, - "search": "", - "page": 1, - }, - "query": ` - query ($projectId: String!, $before: DateTime!, $limit: Int!, $search: String!, $page: Int!) { - project(id: $projectId) { - bucketUsages(before: $before, cursor: {limit: $limit, search: $search, page: $page}) { - bucketUsages { - bucketName - storage - egress - objectCount - segmentCount - since - before - __typename - } - search - limit - offset - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "not authorized") - // TODO: wrong error code - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - } - { // Get_ProjectUsageLimitById resp, body := test.request(http.MethodGet, `/projects/`+test.defaultProjectID()+`/usage-limits`, nil) require.Contains(t, body, "not authorized") // TODO: wrong error code require.Equal(t, http.StatusInternalServerError, resp.StatusCode) } - - { // Get_ProjectMembersByProjectId - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - `orderDirection`: 1, - `projectId`: test.defaultProjectID(), - `limit`: 6, - `search`: ``, - `page`: 1, - `order`: 1, - }, - "query": ` - query ($projectId: String!, $limit: Int!, $search: String!, $page: Int!, $order: Int!, $orderDirection: Int!) { - project(id: $projectId) { - membersAndInvitations(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { - projectMembers { - user { - id - fullName - shortName - email - __typename - } - joinedAt - __typename - } - search - limit - order - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "not authorized") - // TODO: wrong error code - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - } - - { // Post_AddUserToProject - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "emails": []string{user2.email}, - }, - "query": ` - mutation ($projectId: String!, $emails: [String!]!) { - addProjectMembers(projectID: $projectId, email: $emails) { - id - __typename - } - }`})) - require.Contains(t, body, "not authorized") - // TODO: wrong error code - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - } - - { // Post_RemoveUserFromProject - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "emails": []string{user2.email}, - }, - "query": ` - mutation ($projectId: String!, $emails: [String!]!) { - deleteProjectMembers(projectID: $projectId, email: $emails) { - id - __typename - } - }`})) - require.Contains(t, body, "not authorized") - // TODO: wrong error code - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - } - - { // Post_ProjectRename - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - `projectId`: test.defaultProjectID(), - `name`: `Test`, - `description`: `Misc`, - }, - "query": ` - mutation ($projectId: String!, $name: String!, $description: String!) { - updateProject(id: $projectId, projectFields: {name: $name, description: $description}, projectLimits: {storageLimit: "1000", bandwidthLimit: "1000"}) { - name - __typename - } - }`})) - require.Contains(t, body, "not authorized") - // TODO: wrong error code - require.Equal(t, http.StatusUnauthorized, resp.StatusCode) - } - - { // get bucket usages - resp, body := test.request(http.MethodPost, "/graphql", - test.toJSON(map[string]interface{}{ - "variables": map[string]interface{}{ - "projectId": test.defaultProjectID(), - "before": "2021-05-12T18:32:30.533Z", - "limit": 7, - "search": "", - "page": 1, - }, - "query": ` - query ($projectId: String!, $before: DateTime!, $limit: Int!, $search: String!, $page: Int!) { - project(id: $projectId) { - bucketUsages(before: $before, cursor: {limit: $limit, search: $search, page: $page}) { - bucketUsages { - bucketName - storage - egress - objectCount - segmentCount - since - before - __typename - } - search - limit - offset - pageCount - currentPage - totalCount - __typename - } - __typename - } - }`})) - require.Contains(t, body, "not authorized") - // TODO: wrong error code - require.Equal(t, http.StatusInternalServerError, resp.StatusCode) - } }) } diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index 0e6f1bdbb..22cad14ac 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -24,8 +24,6 @@ import ( "time" "github.com/gorilla/mux" - "github.com/graphql-go/graphql" - "github.com/graphql-go/graphql/gqlerrors" "github.com/spacemonkeygo/monkit/v3" "github.com/zeebo/errs" "go.uber.org/zap" @@ -41,7 +39,6 @@ import ( "storj.io/storj/satellite/analytics" "storj.io/storj/satellite/console" "storj.io/storj/satellite/console/consoleweb/consoleapi" - "storj.io/storj/satellite/console/consoleweb/consoleql" "storj.io/storj/satellite/console/consoleweb/consolewebauth" "storj.io/storj/satellite/mailservice" "storj.io/storj/satellite/oidc" @@ -51,8 +48,7 @@ import ( const ( contentType = "Content-Type" - applicationJSON = "application/json" - applicationGraphql = "application/graphql" + applicationJSON = "application/json" ) var ( @@ -64,7 +60,7 @@ var ( // Config contains configuration for console web server. type Config struct { - Address string `help:"server address of the graphql api gateway and frontend app" devDefault:"127.0.0.1:0" releaseDefault:":10100"` + Address string `help:"server address of the http api gateway and frontend app" devDefault:"127.0.0.1:0" releaseDefault:":10100"` FrontendAddress string `help:"server address of the front-end app" devDefault:"127.0.0.1:0" releaseDefault:":10200"` ExternalAddress string `help:"external endpoint of the satellite if hosted" default:""` FrontendEnable bool `help:"feature flag to toggle whether console back-end server should also serve front-end endpoints" default:"true"` @@ -151,8 +147,6 @@ type Server struct { packagePlans paymentsconfig.PackagePlans - schema graphql.Schema - errorTemplate *template.Template } @@ -268,8 +262,6 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc router.Handle("/api/v0/config", server.withCORS(http.HandlerFunc(server.frontendConfigHandler))) - router.Handle("/api/v0/graphql", server.withCORS(server.withAuth(http.HandlerFunc(server.graphqlHandler)))) - router.HandleFunc("/registrationToken/", server.createRegistrationTokenHandler) router.HandleFunc("/robots.txt", server.seoHandler) @@ -419,11 +411,6 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc func (server *Server) Run(ctx context.Context) (err error) { defer mon.Task()(&ctx)(&err) - server.schema, err = consoleql.CreateSchema(server.log, server.service, server.mailService) - if err != nil { - return Error.Wrap(err) - } - _, err = server.loadErrorTemplate() if err != nil { return Error.Wrap(err) @@ -934,130 +921,6 @@ func (server *Server) handleInvited(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, server.config.ExternalAddress+"signup?"+params.Encode(), http.StatusTemporaryRedirect) } -// graphqlHandler is graphql endpoint http handler function. -func (server *Server) graphqlHandler(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - defer mon.Task()(&ctx)(nil) - - handleError := func(code int, err error) { - w.WriteHeader(code) - - var jsonError struct { - Error string `json:"error"` - RequestID string `json:"requestID"` - } - - jsonError.Error = err.Error() - - if requestID := requestid.FromContext(ctx); requestID != "" { - jsonError.RequestID = requestID - } - - if err := json.NewEncoder(w).Encode(jsonError); err != nil { - server.log.Error("error graphql error", zap.Error(err)) - } - } - - w.Header().Set(contentType, applicationJSON) - - query, err := getQuery(w, r) - if err != nil { - handleError(http.StatusBadRequest, err) - return - } - - rootObject := make(map[string]interface{}) - - rootObject["origin"] = server.config.ExternalAddress - rootObject[consoleql.ActivationPath] = "activation?token=" - rootObject[consoleql.PasswordRecoveryPath] = "password-recovery?token=" - rootObject[consoleql.CancelPasswordRecoveryPath] = "cancel-password-recovery?token=" - rootObject[consoleql.SignInPath] = "login" - rootObject[consoleql.LetUsKnowURL] = server.config.LetUsKnowURL - rootObject[consoleql.ContactInfoURL] = server.config.ContactInfoURL - rootObject[consoleql.TermsAndConditionsURL] = server.config.TermsAndConditionsURL - rootObject[consoleql.SatelliteRegion] = server.config.SatelliteName - - result := graphql.Do(graphql.Params{ - Schema: server.schema, - Context: ctx, - RequestString: query.Query, - VariableValues: query.Variables, - OperationName: query.OperationName, - RootObject: rootObject, - }) - - getGqlError := func(err gqlerrors.FormattedError) error { - var gerr *gqlerrors.Error - if errors.As(err.OriginalError(), &gerr) { - return gerr.OriginalError - } - return nil - } - - parseConsoleError := func(err error) (int, error) { - switch { - case console.ErrUnauthorized.Has(err): - return http.StatusUnauthorized, err - case console.Error.Has(err): - return http.StatusInternalServerError, err - } - - return 0, nil - } - - handleErrors := func(code int, errors gqlerrors.FormattedErrors) { - w.WriteHeader(code) - - var jsonError struct { - Errors []string `json:"errors"` - RequestID string `json:"requestID"` - } - - for _, err := range errors { - jsonError.Errors = append(jsonError.Errors, err.Message) - } - - if requestID := requestid.FromContext(ctx); requestID != "" { - jsonError.RequestID = requestID - } - - if err := json.NewEncoder(w).Encode(jsonError); err != nil { - server.log.Error("error graphql error", zap.Error(err)) - } - } - - handleGraphqlErrors := func() { - for _, err := range result.Errors { - gqlErr := getGqlError(err) - if gqlErr == nil { - continue - } - - code, err := parseConsoleError(gqlErr) - if err != nil { - handleError(code, err) - return - } - } - - handleErrors(http.StatusOK, result.Errors) - } - - if result.HasErrors() { - handleGraphqlErrors() - return - } - - err = json.NewEncoder(w).Encode(result) - if err != nil { - server.log.Error("error encoding grapql result", zap.Error(err)) - return - } - - server.log.Debug(fmt.Sprintf("%s", result)) -} - // serveError serves a static error page. func (server *Server) serveError(w http.ResponseWriter, status int) { w.WriteHeader(status) diff --git a/satellite/console/consoleweb/utils.go b/satellite/console/consoleweb/utils.go index 9d9c3f9ec..8c45e3b9c 100644 --- a/satellite/console/consoleweb/utils.go +++ b/satellite/console/consoleweb/utils.go @@ -4,18 +4,13 @@ package consoleweb import ( - "encoding/json" "fmt" - "io" "mime" "net/http" "regexp" "strings" - "github.com/zeebo/errs" - "storj.io/common/memory" - "storj.io/storj/satellite/console/consoleweb/consoleql" ) // ContentLengthLimit describes 4KB limit. @@ -33,42 +28,6 @@ func init() { } } -// JSON request from graphql clients. -type graphqlJSON struct { - Query string - OperationName string - Variables map[string]interface{} -} - -// getQuery retrieves graphql query from request. -func getQuery(w http.ResponseWriter, req *http.Request) (query graphqlJSON, err error) { - switch req.Method { - case http.MethodGet: - query.Query = req.URL.Query().Get(consoleql.Query) - return query, nil - case http.MethodPost: - return queryPOST(w, req) - default: - return query, errs.New("wrong http request type") - } -} - -// queryPOST retrieves graphql query from POST request. -func queryPOST(w http.ResponseWriter, req *http.Request) (query graphqlJSON, err error) { - limitedReader := http.MaxBytesReader(w, req.Body, ContentLengthLimit.Int64()) - switch typ := req.Header.Get(contentType); typ { - case applicationGraphql: - body, err := io.ReadAll(limitedReader) - query.Query = string(body) - return query, errs.Combine(err, limitedReader.Close()) - case applicationJSON: - err := json.NewDecoder(limitedReader).Decode(&query) - return query, errs.Combine(err, limitedReader.Close()) - default: - return query, errs.New("can't parse request body of type %s", typ) - } -} - // getClientIPRegExp is used by the function getClientIP. var getClientIPRegExp = regexp.MustCompile(`(?i:(?:^|;)for=([^,; ]+))`) diff --git a/scripts/testdata/satellite-config.yaml.lock b/scripts/testdata/satellite-config.yaml.lock index 60c9e348b..30d8ae52f 100755 --- a/scripts/testdata/satellite-config.yaml.lock +++ b/scripts/testdata/satellite-config.yaml.lock @@ -172,7 +172,7 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0 # url link for account activation redirect # console.account-activation-redirect-url: "" -# server address of the graphql api gateway and frontend app +# server address of the http api gateway and frontend app # console.address: :10100 # indicates if all projects dashboard should be used diff --git a/testsuite/storjscan/go.mod b/testsuite/storjscan/go.mod index 87e441fed..8cd92fce5 100644 --- a/testsuite/storjscan/go.mod +++ b/testsuite/storjscan/go.mod @@ -56,7 +56,6 @@ require ( github.com/gorilla/schema v1.2.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect - github.com/graphql-go/graphql v0.7.9 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect diff --git a/testsuite/storjscan/go.sum b/testsuite/storjscan/go.sum index 73bb129e1..abdc2eb1b 100644 --- a/testsuite/storjscan/go.sum +++ b/testsuite/storjscan/go.sum @@ -320,8 +320,6 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/graphql-go/graphql v0.7.9 h1:5Va/Rt4l5g3YjwDnid3vFfn43faaQBq7rMcIZ0VnV34= -github.com/graphql-go/graphql v0.7.9/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= diff --git a/testsuite/ui/go.mod b/testsuite/ui/go.mod index 796550948..48bf8ce22 100644 --- a/testsuite/ui/go.mod +++ b/testsuite/ui/go.mod @@ -81,7 +81,6 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/graphql-go/graphql v0.7.9 // indirect github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect diff --git a/testsuite/ui/go.sum b/testsuite/ui/go.sum index b48d10fd9..fa6585233 100644 --- a/testsuite/ui/go.sum +++ b/testsuite/ui/go.sum @@ -570,8 +570,6 @@ github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlI github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graphql-go/graphql v0.7.9 h1:5Va/Rt4l5g3YjwDnid3vFfn43faaQBq7rMcIZ0VnV34= -github.com/graphql-go/graphql v0.7.9/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=