Skip to content

Commit

Permalink
feat(server): implement regenerate integration token functionality (#…
Browse files Browse the repository at this point in the history
…1156)

* feat: implement regererate integration token

* add unit test

* add e2e test
  • Loading branch information
nourbalaha authored and yk-eukarya committed Oct 1, 2024
1 parent e04c336 commit b634cf8
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 0 deletions.
112 changes: 112 additions & 0 deletions server/e2e/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package e2e

import (
"net/http"
"testing"

"github.com/gavv/httpexpect/v2"
"github.com/reearth/reearth-cms/server/internal/app"
)

func createIntegration(e *httpexpect.Expect, name, desc, logoUrl, iType string) (string, *httpexpect.Value) {
requestBody := GraphQLRequest{
Query: `
mutation CreateIntegration(
$name: String!
$description: String
$logoUrl: URL!
$type: IntegrationType!
) {
createIntegration(
input: { name: $name, description: $description, logoUrl: $logoUrl, type: $type }
) {
integration {
id
name
description
logoUrl
iType
config {
token
}
}
}
}
`,
Variables: map[string]any{
"name": name,
"description": desc,
"logoUrl": logoUrl,
"type": iType,
},
}

res := e.POST("/api/graphql").
WithHeader("Origin", "https://example.com").
WithHeader("X-Reearth-Debug-User", uId1.String()).
WithHeader("Content-Type", "application/json").
WithJSON(requestBody).
Expect().
Status(http.StatusOK).
JSON()

return res.Path("$.data.createIntegration.integration.id").Raw().(string), res
}

func regenerateToken(e *httpexpect.Expect, iId string) (string, *httpexpect.Value) {
requestBody := GraphQLRequest{
Query: `
mutation regenerateToken($integrationId: ID!) {
regenerateToken(input: { integrationId: $integrationId }) {
integration {
id
name
description
logoUrl
iType
config {
token
}
}
}
}
`,
Variables: map[string]any{
"integrationId": iId,
},
}

res := e.POST("/api/graphql").
WithHeader("Origin", "https://example.com").
WithHeader("X-Reearth-Debug-User", uId1.String()).
WithHeader("Content-Type", "application/json").
WithJSON(requestBody).
Expect().
Status(http.StatusOK).
JSON()

return res.Path("$.data.regenerateToken.integration.config.token").Raw().(string), res
}

func TestRegenerateToken(t *testing.T) {
e, _ := StartGQLServer(t, &app.Config{}, true, baseSeederUser)

iId, integration := createIntegration(e, "test", "test", "https://example.com/logo.png", "Public")
oldToken := integration.Object().
Value("data").Object().
Value("createIntegration").Object().
Value("integration").Object().
Value("config").Object().
Value("token")

_, updatedIntegration := regenerateToken(e, iId)
newToken := updatedIntegration.Object().
Value("data").Object().
Value("regenerateToken").Object().
Value("integration").Object().
Value("config").Object().
Value("token")

// Check if the token is regenerated
newToken.NotEqual(oldToken)
}
127 changes: 127 additions & 0 deletions server/internal/adapter/gql/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions server/internal/adapter/gql/gqlmodel/models_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions server/internal/adapter/gql/resolver_mutation_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,23 @@ func (r *mutationResolver) DeleteIntegration(ctx context.Context, input gqlmodel
}, nil
}

func (r *mutationResolver) RegenerateToken(ctx context.Context, input gqlmodel.RegenerateTokenInput) (*gqlmodel.IntegrationPayload, error) {
iId, err := gqlmodel.ToID[id.Integration](input.IntegrationID)
if err != nil {
return nil, err
}

op := getOperator(ctx)
res, err := usecases(ctx).Integration.RegenerateToken(ctx, iId, op)
if err != nil {
return nil, err
}

return &gqlmodel.IntegrationPayload{
Integration: gqlmodel.ToIntegration(res, op.AcOperator.User),
}, nil
}

func (r *mutationResolver) CreateWebhook(ctx context.Context, input gqlmodel.CreateWebhookInput) (*gqlmodel.WebhookPayload, error) {
iId, err := gqlmodel.ToID[id.Integration](input.IntegrationID)
if err != nil {
Expand Down
26 changes: 26 additions & 0 deletions server/internal/usecase/interactor/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,32 @@ func (i Integration) Delete(ctx context.Context, integrationId id.IntegrationID,
})
}

func (i Integration) RegenerateToken(ctx context.Context, iId id.IntegrationID, operator *usecase.Operator) (*integration.Integration, error) {
if operator.AcOperator.User == nil {
return nil, interfaces.ErrInvalidOperator
}
return Run1(ctx, operator, i.repos, Usecase().Transaction(),
func(ctx context.Context) (*integration.Integration, error) {
in, err := i.repos.Integration.FindByID(ctx, iId)
if err != nil {
return nil, err
}

if in.Developer() != *operator.AcOperator.User {
return nil, interfaces.ErrOperationDenied
}

in.RandomToken()
in.SetUpdatedAt(time.Now())

if err := i.repos.Integration.Save(ctx, in); err != nil {
return nil, err
}

return in, nil
})
}

func (i Integration) CreateWebhook(ctx context.Context, iId id.IntegrationID, param interfaces.CreateWebhookParam, operator *usecase.Operator) (*integration.Webhook, error) {
if operator.AcOperator.User == nil {
return nil, interfaces.ErrInvalidOperator
Expand Down
Loading

0 comments on commit b634cf8

Please sign in to comment.