mirror of https://github.com/harness/drone.git
feat: [CODE-2292]: Add API for space level webhook creation (#2730)
* Merge remote-tracking branch 'origin/main' into dd/webhooks-space * Move webphookpreprocessor to webhook controller * Merge remote-tracking branch 'origin/main' into dd/webhooks-space * Merge branch 'main' into dd/webhooks-space * Add webhookpreprocessor service * Add WebhookParentInfo type and refactor webhook svc and store to use it * Introduce webhookpreprocessor service * Add space webhooks * Refactor handlers to use custom fn params * Move everything webhook service related to webhook service * Remove webhook parent info type * Add webhook execution count * Add space webhookspull/3576/head
parent
fd848b1e15
commit
b002a60b02
|
@ -19,54 +19,47 @@ import (
|
|||
"fmt"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/auth/authz"
|
||||
"github.com/harness/gitness/app/services/webhook"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/encrypt"
|
||||
"github.com/harness/gitness/errors"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
allowLoopback bool
|
||||
allowPrivateNetwork bool
|
||||
|
||||
authorizer authz.Authorizer
|
||||
webhookStore store.WebhookStore
|
||||
webhookExecutionStore store.WebhookExecutionStore
|
||||
repoStore store.RepoStore
|
||||
webhookService *webhook.Service
|
||||
encrypter encrypt.Encrypter
|
||||
authorizer authz.Authorizer
|
||||
spaceStore store.SpaceStore
|
||||
repoStore store.RepoStore
|
||||
webhookService *webhook.Service
|
||||
encrypter encrypt.Encrypter
|
||||
preprocessor Preprocessor
|
||||
}
|
||||
|
||||
func NewController(
|
||||
allowLoopback bool,
|
||||
allowPrivateNetwork bool,
|
||||
authorizer authz.Authorizer,
|
||||
webhookStore store.WebhookStore,
|
||||
webhookExecutionStore store.WebhookExecutionStore,
|
||||
spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore,
|
||||
webhookService *webhook.Service,
|
||||
encrypter encrypt.Encrypter,
|
||||
preprocessor Preprocessor,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
allowLoopback: allowLoopback,
|
||||
allowPrivateNetwork: allowPrivateNetwork,
|
||||
authorizer: authorizer,
|
||||
webhookStore: webhookStore,
|
||||
webhookExecutionStore: webhookExecutionStore,
|
||||
repoStore: repoStore,
|
||||
webhookService: webhookService,
|
||||
encrypter: encrypter,
|
||||
authorizer: authorizer,
|
||||
spaceStore: spaceStore,
|
||||
repoStore: repoStore,
|
||||
webhookService: webhookService,
|
||||
encrypter: encrypter,
|
||||
preprocessor: preprocessor,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getRepoCheckAccess(ctx context.Context,
|
||||
session *auth.Session, repoRef string, reqPermission enum.Permission) (*types.Repository, error) {
|
||||
if repoRef == "" {
|
||||
return nil, usererror.BadRequest("A valid repository reference must be provided.")
|
||||
return nil, errors.InvalidArgument("A valid repository reference must be provided.")
|
||||
}
|
||||
|
||||
repo, err := c.repoStore.FindByRef(ctx, repoRef)
|
||||
|
@ -80,3 +73,24 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context,
|
|||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getSpaceCheckAccess(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
permission enum.Permission,
|
||||
) (*types.Space, error) {
|
||||
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parent space not found: %w", err)
|
||||
}
|
||||
|
||||
scope := &types.Scope{SpacePath: space.Path}
|
||||
resource := &types.Resource{Type: enum.ResourceTypeRepo}
|
||||
err = apiauth.Check(ctx, c.authorizer, session, scope, resource, permission)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("auth check failed: %w", err)
|
||||
}
|
||||
|
||||
return space, nil
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// Find finds a webhook from the provided repository.
|
||||
func (c *Controller) Find(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
) (*types.Webhook, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.getWebhookVerifyOwnership(ctx, repo.ID, webhookIdentifier)
|
||||
}
|
||||
|
||||
func (c *Controller) getWebhookVerifyOwnership(
|
||||
ctx context.Context,
|
||||
repoID int64,
|
||||
webhookIdentifier string,
|
||||
) (*types.Webhook, error) {
|
||||
// TODO: Remove once webhook identifier migration completed
|
||||
webhookID, err := strconv.ParseInt(webhookIdentifier, 10, 64)
|
||||
if (err == nil && webhookID <= 0) || len(strings.TrimSpace(webhookIdentifier)) == 0 {
|
||||
return nil, usererror.BadRequest("A valid webhook identifier must be provided.")
|
||||
}
|
||||
|
||||
var webhook *types.Webhook
|
||||
if err == nil {
|
||||
webhook, err = c.webhookStore.Find(ctx, webhookID)
|
||||
} else {
|
||||
webhook, err = c.webhookStore.FindByIdentifier(ctx, enum.WebhookParentRepo, repoID, webhookIdentifier)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find webhook with identifier %q: %w", webhookIdentifier, err)
|
||||
}
|
||||
|
||||
// ensure the webhook actually belongs to the repo
|
||||
if webhook.ParentType != enum.WebhookParentRepo || webhook.ParentID != repoID {
|
||||
return nil, fmt.Errorf("webhook doesn't belong to requested repo. Returning error %w", usererror.ErrNotFound)
|
||||
}
|
||||
|
||||
return webhook, nil
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// FindExecution finds a webhook execution.
|
||||
func (c *Controller) FindExecution(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get the webhook and ensure it belongs to us
|
||||
webhook, err := c.getWebhookVerifyOwnership(ctx, repo.ID, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// get the webhook execution and ensure it belongs to us
|
||||
webhookExecution, err := c.getWebhookExecutionVerifyOwnership(ctx, webhook.ID, webhookExecutionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return webhookExecution, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getWebhookExecutionVerifyOwnership(ctx context.Context, webhookID int64,
|
||||
webhookExecutionID int64) (*types.WebhookExecution, error) {
|
||||
if webhookExecutionID <= 0 {
|
||||
return nil, usererror.BadRequest("A valid webhook execution ID must be provided.")
|
||||
}
|
||||
|
||||
webhookExecution, err := c.webhookExecutionStore.Find(ctx, webhookExecutionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find webhook execution with id %d: %w", webhookExecutionID, err)
|
||||
}
|
||||
|
||||
// ensure the webhook execution actually belongs to the webhook
|
||||
if webhookID != webhookExecution.WebhookID {
|
||||
return nil, fmt.Errorf("webhook execution doesn't belong to requested webhook. Returning error %w",
|
||||
usererror.ErrNotFound)
|
||||
}
|
||||
|
||||
return webhookExecution, nil
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type Preprocessor interface {
|
||||
PreprocessCreateInput(enum.PrincipalType, *types.WebhookCreateInput) (bool, error)
|
||||
PreprocessUpdateInput(enum.PrincipalType, *types.WebhookUpdateInput) (bool, error)
|
||||
PreprocessFilter(enum.PrincipalType, *types.WebhookFilter)
|
||||
IsInternalCall(enum.PrincipalType) bool
|
||||
}
|
||||
|
||||
type NoopPreprocessor struct {
|
||||
}
|
||||
|
||||
// PreprocessCreateInput always return false for internal.
|
||||
func (p NoopPreprocessor) PreprocessCreateInput(
|
||||
enum.PrincipalType,
|
||||
*types.WebhookCreateInput,
|
||||
) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PreprocessUpdateInput always return false for internal.
|
||||
func (p NoopPreprocessor) PreprocessUpdateInput(
|
||||
enum.PrincipalType,
|
||||
*types.WebhookUpdateInput,
|
||||
) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (p NoopPreprocessor) PreprocessFilter(_ enum.PrincipalType, filter *types.WebhookFilter) {
|
||||
if filter.Order == enum.OrderDefault {
|
||||
filter.Order = enum.OrderAsc
|
||||
}
|
||||
|
||||
// always skip internal for requests from handler
|
||||
filter.SkipInternal = true
|
||||
}
|
||||
|
||||
func (p NoopPreprocessor) IsInternalCall(enum.PrincipalType) bool {
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// CreateRepo creates a new repo webhook.
|
||||
func (c *Controller) CreateRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
in *types.WebhookCreateInput,
|
||||
) (*types.Webhook, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
internal, err := c.preprocessor.PreprocessCreateInput(session.Principal.Type, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to preprocess create input: %w", err)
|
||||
}
|
||||
|
||||
hook, err := c.webhookService.Create(
|
||||
ctx, session.Principal.ID, repo.ID, enum.WebhookParentRepo, internal, in,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed create webhook: %w", err)
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
|
@ -16,32 +16,26 @@ package webhook
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// Delete deletes an existing webhook.
|
||||
func (c *Controller) Delete(
|
||||
// DeleteRepo deletes an existing webhook.
|
||||
func (c *Controller) DeleteRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
allowDeletingInternal bool,
|
||||
) error {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
// get the webhook and ensure it belongs to us
|
||||
webhook, err := c.getWebhookVerifyOwnership(ctx, repo.ID, webhookIdentifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if webhook.Internal && !allowDeletingInternal {
|
||||
return ErrInternalWebhookOperationNotAllowed
|
||||
}
|
||||
// delete webhook
|
||||
return c.webhookStore.Delete(ctx, webhook.ID)
|
||||
return c.webhookService.Delete(
|
||||
ctx, repo.ID, enum.WebhookParentRepo, webhookIdentifier,
|
||||
c.preprocessor.IsInternalCall(session.Principal.Type),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// FindRepo finds a webhook from the provided repository.
|
||||
func (c *Controller) FindRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
) (*types.Webhook, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.Find(ctx, repo.ID, enum.WebhookParentRepo, webhookIdentifier)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// FindExecutionRepo finds a webhook execution.
|
||||
func (c *Controller) FindExecutionRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.FindExecution(
|
||||
ctx, repo.ID, enum.WebhookParentRepo, webhookIdentifier, webhookExecutionID)
|
||||
}
|
|
@ -23,27 +23,20 @@ import (
|
|||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// List returns the webhooks from the provided repository.
|
||||
func (c *Controller) List(
|
||||
// ListRepo returns the webhooks from the provided repository.
|
||||
func (c *Controller) ListRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
inherited bool,
|
||||
filter *types.WebhookFilter,
|
||||
) ([]*types.Webhook, int64, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, 0, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
count, err := c.webhookStore.Count(ctx, enum.WebhookParentRepo, repo.ID, filter)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count webhooks for repo with id %d: %w", repo.ID, err)
|
||||
}
|
||||
c.preprocessor.PreprocessFilter(session.Principal.Type, filter)
|
||||
|
||||
webhooks, err := c.webhookStore.List(ctx, enum.WebhookParentRepo, repo.ID, filter)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to list webhooks for repo with id %d: %w", repo.ID, err)
|
||||
}
|
||||
|
||||
return webhooks, count, nil
|
||||
return c.webhookService.List(ctx, repo.ID, enum.WebhookParentRepo, inherited, filter)
|
||||
}
|
|
@ -23,30 +23,19 @@ import (
|
|||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// ListExecutions returns the executions of the webhook.
|
||||
func (c *Controller) ListExecutions(
|
||||
// ListExecutionsRepo returns the executions of the webhook.
|
||||
func (c *Controller) ListExecutionsRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
filter *types.WebhookExecutionFilter,
|
||||
) ([]*types.WebhookExecution, error) {
|
||||
) ([]*types.WebhookExecution, int64, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
// get the webhook and ensure it belongs to us
|
||||
webhook, err := c.getWebhookVerifyOwnership(ctx, repo.ID, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get webhook executions
|
||||
webhookExecutions, err := c.webhookExecutionStore.ListForWebhook(ctx, webhook.ID, filter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list webhook executions for webhook %d: %w", webhook.ID, err)
|
||||
}
|
||||
|
||||
return webhookExecutions, nil
|
||||
return c.webhookService.ListExecutions(
|
||||
ctx, repo.ID, enum.WebhookParentRepo, webhookIdentifier, filter)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// RetriggerExecutionRepo retriggers an existing webhook execution.
|
||||
func (c *Controller) RetriggerExecutionRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.RetriggerExecution(
|
||||
ctx, repo.ID, enum.WebhookParentRepo, webhookIdentifier, webhookExecutionID)
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// UpdateRepo updates an existing webhook.
|
||||
func (c *Controller) UpdateRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
in *types.WebhookUpdateInput,
|
||||
) (*types.Webhook, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
allowModifyingInternal, err := c.preprocessor.PreprocessUpdateInput(session.Principal.Type, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to preprocess update input: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.Update(
|
||||
ctx, repo.ID, enum.WebhookParentRepo, webhookIdentifier, allowModifyingInternal, in,
|
||||
)
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// RetriggerExecution retriggers an existing webhook execution.
|
||||
func (c *Controller) RetriggerExecution(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to the repo: %w", err)
|
||||
}
|
||||
|
||||
// get the webhook and ensure it belongs to us
|
||||
webhook, err := c.getWebhookVerifyOwnership(ctx, repo.ID, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get the webhookexecution and ensure it belongs to us
|
||||
webhookExecution, err := c.getWebhookExecutionVerifyOwnership(ctx, webhook.ID, webhookExecutionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// retrigger the execution ...
|
||||
executionResult, err := c.webhookService.RetriggerWebhookExecution(ctx, webhookExecution.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrigger webhook execution: %w", err)
|
||||
}
|
||||
|
||||
// log execution error so we have the necessary debug information if needed
|
||||
if executionResult.Err != nil {
|
||||
log.Ctx(ctx).Warn().Err(executionResult.Err).Msgf(
|
||||
"retrigger of webhhook %d execution %d (new id: %d) had an error",
|
||||
webhook.ID, webhookExecution.ID, executionResult.Execution.ID)
|
||||
}
|
||||
|
||||
return executionResult.Execution, nil
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// CreateSpace creates a new webhook.
|
||||
func (c *Controller) CreateSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
in *types.WebhookCreateInput,
|
||||
) (*types.Webhook, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
internal, err := c.preprocessor.PreprocessCreateInput(session.Principal.Type, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to preprocess create input: %w", err)
|
||||
}
|
||||
|
||||
hook, err := c.webhookService.Create(
|
||||
ctx, session.Principal.ID, space.ID, enum.WebhookParentSpace, internal, in,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create webhook: %w", err)
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// DeleteSpace deletes an existing webhook.
|
||||
func (c *Controller) DeleteSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
webhookIdentifier string,
|
||||
) error {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceEdit)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.Delete(
|
||||
ctx, space.ID, enum.WebhookParentSpace, webhookIdentifier,
|
||||
c.preprocessor.IsInternalCall(session.Principal.Type),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// FindSpace finds a webhook from the provided repository.
|
||||
func (c *Controller) FindSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
webhookIdentifier string,
|
||||
) (*types.Webhook, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceView)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.Find(ctx, space.ID, enum.WebhookParentSpace, webhookIdentifier)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// FindExecutionSpace finds a webhook execution.
|
||||
func (c *Controller) FindExecutionSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceView)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.FindExecution(
|
||||
ctx, space.ID, enum.WebhookParentSpace, webhookIdentifier, webhookExecutionID)
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// ListSpace returns the webhooks from the provided space.
|
||||
func (c *Controller) ListSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
inherited bool,
|
||||
filter *types.WebhookFilter,
|
||||
) ([]*types.Webhook, int64, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceView)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
c.preprocessor.PreprocessFilter(session.Principal.Type, filter)
|
||||
|
||||
return c.webhookService.List(ctx, space.ID, enum.WebhookParentSpace, inherited, filter)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// ListExecutionsSpace returns the executions of the webhook.
|
||||
func (c *Controller) ListExecutionsSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
webhookIdentifier string,
|
||||
filter *types.WebhookExecutionFilter,
|
||||
) ([]*types.WebhookExecution, int64, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceView)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.ListExecutions(
|
||||
ctx, space.ID, enum.WebhookParentSpace, webhookIdentifier, filter)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// RetriggerExecutionSpace retriggers an existing webhook execution.
|
||||
func (c *Controller) RetriggerExecutionSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceView)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.RetriggerExecution(
|
||||
ctx, space.ID, enum.WebhookParentSpace, webhookIdentifier, webhookExecutionID)
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// UpdateSpace updates an existing webhook.
|
||||
func (c *Controller) UpdateSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
webhookIdentifier string,
|
||||
in *types.WebhookUpdateInput,
|
||||
) (*types.Webhook, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
allowModifyingInternal, err := c.preprocessor.PreprocessUpdateInput(session.Principal.Type, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to preprocess update input: %w", err)
|
||||
}
|
||||
|
||||
return c.webhookService.Update(
|
||||
ctx, space.ID, enum.WebhookParentSpace, webhookIdentifier, allowModifyingInternal, in,
|
||||
)
|
||||
}
|
|
@ -28,12 +28,15 @@ var WireSet = wire.NewSet(
|
|||
ProvideController,
|
||||
)
|
||||
|
||||
func ProvideController(config webhook.Config, authorizer authz.Authorizer,
|
||||
webhookStore store.WebhookStore, webhookExecutionStore store.WebhookExecutionStore,
|
||||
repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter,
|
||||
func ProvideController(authorizer authz.Authorizer,
|
||||
spaceStore store.SpaceStore, repoStore store.RepoStore,
|
||||
webhookService *webhook.Service, encrypter encrypt.Encrypter,
|
||||
preprocessor Preprocessor,
|
||||
) *Controller {
|
||||
return NewController(
|
||||
config.AllowLoopback, config.AllowPrivateNetwork, authorizer,
|
||||
webhookStore, webhookExecutionStore,
|
||||
repoStore, webhookService, encrypter)
|
||||
authorizer, spaceStore, repoStore, webhookService, encrypter, preprocessor)
|
||||
}
|
||||
|
||||
func ProvidePreprocessor() Preprocessor {
|
||||
return NoopPreprocessor{}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,11 @@ import (
|
|||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
// HandleCreate returns a http.HandlerFunc that creates a new webhook.
|
||||
func HandleCreate(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleCreateRepo returns a http.HandlerFunc that creates a new webhook.
|
||||
func HandleCreateRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -35,14 +36,14 @@ func HandleCreate(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
in := new(webhook.CreateInput)
|
||||
in := new(types.WebhookCreateInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
hook, err := webhookCtrl.Create(ctx, session, repoRef, in, false)
|
||||
hook, err := webhookCtrl.CreateRepo(ctx, session, repoRef, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleDelete returns a http.HandlerFunc that deletes a webhook.
|
||||
func HandleDelete(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleDeleteRepo returns a http.HandlerFunc that deletes a webhook.
|
||||
func HandleDeleteRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -40,7 +40,7 @@ func HandleDelete(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
err = webhookCtrl.Delete(ctx, session, repoRef, webhookIdentifier, false)
|
||||
err = webhookCtrl.DeleteRepo(ctx, session, repoRef, webhookIdentifier)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleFind returns a http.HandlerFunc that finds a webhook.
|
||||
func HandleFind(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleFindRepo returns a http.HandlerFunc that finds a webhook.
|
||||
func HandleFindRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -40,7 +40,7 @@ func HandleFind(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
webhook, err := webhookCtrl.Find(ctx, session, repoRef, webhookIdentifier)
|
||||
webhook, err := webhookCtrl.FindRepo(ctx, session, repoRef, webhookIdentifier)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleFindExecution returns a http.HandlerFunc that finds a webhook execution.
|
||||
func HandleFindExecution(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleFindExecutionRepo returns a http.HandlerFunc that finds a webhook execution.
|
||||
func HandleFindExecutionRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -46,7 +46,7 @@ func HandleFindExecution(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
execution, err := webhookCtrl.FindExecution(ctx, session, repoRef, webhookIdentifier, webhookExecutionID)
|
||||
execution, err := webhookCtrl.FindExecutionRepo(ctx, session, repoRef, webhookIdentifier, webhookExecutionID)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -20,11 +20,10 @@ import (
|
|||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// HandleList returns a http.HandlerFunc that lists webhooks.
|
||||
func HandleList(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleListRepo returns a http.HandlerFunc that lists webhooks.
|
||||
func HandleListRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -35,15 +34,14 @@ func HandleList(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
filter := request.ParseWebhookFilter(r)
|
||||
if filter.Order == enum.OrderDefault {
|
||||
filter.Order = enum.OrderAsc
|
||||
inherited, err := request.ParseInheritedFromQuery(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
}
|
||||
|
||||
// always skip internal for requests from handler
|
||||
filter.SkipInternal = true
|
||||
filter := request.ParseWebhookFilter(r)
|
||||
|
||||
webhooks, totalCount, err := webhookCtrl.List(ctx, session, repoRef, filter)
|
||||
webhooks, totalCount, err := webhookCtrl.ListRepo(ctx, session, repoRef, inherited, filter)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleListExecutions returns a http.HandlerFunc that lists webhook executions.
|
||||
func HandleListExecutions(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleListExecutionsRepo returns a http.HandlerFunc that lists webhook executions.
|
||||
func HandleListExecutionsRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -42,15 +42,13 @@ func HandleListExecutions(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
|
||||
filter := request.ParseWebhookExecutionFilter(r)
|
||||
|
||||
executions, err := webhookCtrl.ListExecutions(ctx, session, repoRef, webhookIdentifier, filter)
|
||||
executions, total, err := webhookCtrl.ListExecutionsRepo(ctx, session, repoRef, webhookIdentifier, filter)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: get last page indicator explicitly - current check is wrong in case len % pageSize == 0
|
||||
isLastPage := len(executions) < filter.Size
|
||||
render.PaginationNoTotal(r, w, filter.Page, filter.Size, isLastPage)
|
||||
render.Pagination(r, w, filter.Page, filter.Size, int(total))
|
||||
render.JSON(w, http.StatusOK, executions)
|
||||
}
|
||||
}
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleRetriggerExecution returns a http.HandlerFunc that retriggers a webhook executions.
|
||||
func HandleRetriggerExecution(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleRetriggerExecutionRepo returns a http.HandlerFunc that retriggers a webhook executions.
|
||||
func HandleRetriggerExecutionRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -46,7 +46,7 @@ func HandleRetriggerExecution(webhookCtrl *webhook.Controller) http.HandlerFunc
|
|||
return
|
||||
}
|
||||
|
||||
execution, err := webhookCtrl.RetriggerExecution(ctx, session, repoRef, webhookIdentifier, webhookExecutionID)
|
||||
execution, err := webhookCtrl.RetriggerExecutionRepo(ctx, session, repoRef, webhookIdentifier, webhookExecutionID)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -21,10 +21,11 @@ import (
|
|||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
// HandleUpdate returns a http.HandlerFunc that updates an existing webhook.
|
||||
func HandleUpdate(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
// HandleUpdateRepo returns a http.HandlerFunc that updates an existing webhook.
|
||||
func HandleUpdateRepo(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
@ -41,14 +42,14 @@ func HandleUpdate(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
in := new(webhook.UpdateInput)
|
||||
in := new(types.WebhookUpdateInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
hook, err := webhookCtrl.Update(ctx, session, repoRef, webhookIdentifier, in, false)
|
||||
hook, err := webhookCtrl.UpdateRepo(ctx, session, repoRef, webhookIdentifier, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
// HandleCreateSpace returns a http.HandlerFunc that creates a new webhook.
|
||||
func HandleCreateSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(types.WebhookCreateInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
hook, err := webhookCtrl.CreateSpace(ctx, session, spaceRef, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusCreated, hook)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleDeleteSpace returns a http.HandlerFunc that deletes a webhook.
|
||||
func HandleDeleteSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookIdentifier, err := request.GetWebhookIdentifierFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = webhookCtrl.DeleteSpace(ctx, session, spaceRef, webhookIdentifier)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.DeleteSuccessful(w)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleFindSpace returns a http.HandlerFunc that finds a webhook.
|
||||
func HandleFindSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookIdentifier, err := request.GetWebhookIdentifierFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhook, err := webhookCtrl.FindSpace(ctx, session, spaceRef, webhookIdentifier)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, webhook)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleFindExecutionSpace returns a http.HandlerFunc that finds a webhook execution.
|
||||
func HandleFindExecutionSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookIdentifier, err := request.GetWebhookIdentifierFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookExecutionID, err := request.GetWebhookExecutionIDFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
execution, err := webhookCtrl.FindExecutionSpace(ctx, session, spaceRef, webhookIdentifier, webhookExecutionID)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, execution)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleListSpace returns a http.HandlerFunc that lists webhooks.
|
||||
func HandleListSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
inherited, err := request.ParseInheritedFromQuery(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
}
|
||||
|
||||
filter := request.ParseWebhookFilter(r)
|
||||
|
||||
webhooks, totalCount, err := webhookCtrl.ListSpace(ctx, session, spaceRef, inherited, filter)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Pagination(r, w, filter.Page, filter.Size, int(totalCount))
|
||||
render.JSON(w, http.StatusOK, webhooks)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleListExecutionsSpace returns a http.HandlerFunc that lists webhook executions.
|
||||
func HandleListExecutionsSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookIdentifier, err := request.GetWebhookIdentifierFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
filter := request.ParseWebhookExecutionFilter(r)
|
||||
|
||||
executions, total, err := webhookCtrl.ListExecutionsSpace(ctx, session, spaceRef, webhookIdentifier, filter)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Pagination(r, w, filter.Page, filter.Size, int(total))
|
||||
render.JSON(w, http.StatusOK, executions)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleRetriggerExecutionSpace returns a http.HandlerFunc that retriggers a webhook executions.
|
||||
func HandleRetriggerExecutionSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookIdentifier, err := request.GetWebhookIdentifierFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookExecutionID, err := request.GetWebhookExecutionIDFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
execution, err := webhookCtrl.RetriggerExecutionSpace(ctx, session, spaceRef, webhookIdentifier, webhookExecutionID)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, execution)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
// HandleUpdateSpace returns a http.HandlerFunc that updates an existing webhook.
|
||||
func HandleUpdateSpace(webhookCtrl *webhook.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
webhookIdentifier, err := request.GetWebhookIdentifierFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(types.WebhookUpdateInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
hook, err := webhookCtrl.UpdateSpace(ctx, session, spaceRef, webhookIdentifier, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, hook)
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ package openapi
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/types"
|
||||
|
@ -33,44 +32,84 @@ type webhookType struct {
|
|||
HasSecret bool `json:"has_secret"`
|
||||
}
|
||||
|
||||
type createWebhookRequest struct {
|
||||
repoRequest
|
||||
webhook.CreateInput
|
||||
type createSpaceWebhookRequest struct {
|
||||
spaceRequest
|
||||
types.WebhookCreateInput
|
||||
}
|
||||
|
||||
type listWebhooksRequest struct {
|
||||
type createRepoWebhookRequest struct {
|
||||
repoRequest
|
||||
types.WebhookCreateInput
|
||||
}
|
||||
|
||||
type listSpaceWebhooksRequest struct {
|
||||
spaceRequest
|
||||
}
|
||||
|
||||
type listRepoWebhooksRequest struct {
|
||||
repoRequest
|
||||
}
|
||||
|
||||
type webhookRequest struct {
|
||||
type spaceWebhookRequest struct {
|
||||
spaceRequest
|
||||
ID int64 `path:"webhook_identifier"`
|
||||
}
|
||||
|
||||
type repoWebhookRequest struct {
|
||||
repoRequest
|
||||
ID int64 `path:"webhook_identifier"`
|
||||
}
|
||||
|
||||
type getWebhookRequest struct {
|
||||
webhookRequest
|
||||
type getSpaceWebhookRequest struct {
|
||||
spaceWebhookRequest
|
||||
}
|
||||
|
||||
type deleteWebhookRequest struct {
|
||||
webhookRequest
|
||||
type getRepoWebhookRequest struct {
|
||||
repoWebhookRequest
|
||||
}
|
||||
|
||||
type updateWebhookRequest struct {
|
||||
webhookRequest
|
||||
webhook.UpdateInput
|
||||
type deleteSpaceWebhookRequest struct {
|
||||
spaceWebhookRequest
|
||||
}
|
||||
|
||||
type listWebhookExecutionsRequest struct {
|
||||
webhookRequest
|
||||
type deleteRepoWebhookRequest struct {
|
||||
repoWebhookRequest
|
||||
}
|
||||
|
||||
type webhookExecutionRequest struct {
|
||||
webhookRequest
|
||||
type updateSpaceWebhookRequest struct {
|
||||
spaceWebhookRequest
|
||||
types.WebhookUpdateInput
|
||||
}
|
||||
|
||||
type updateRepoWebhookRequest struct {
|
||||
repoWebhookRequest
|
||||
types.WebhookUpdateInput
|
||||
}
|
||||
|
||||
type listSpaceWebhookExecutionsRequest struct {
|
||||
spaceWebhookRequest
|
||||
}
|
||||
|
||||
type listRepoWebhookExecutionsRequest struct {
|
||||
repoWebhookRequest
|
||||
}
|
||||
|
||||
type spaceWebhookExecutionRequest struct {
|
||||
spaceWebhookRequest
|
||||
ID int64 `path:"webhook_execution_id"`
|
||||
}
|
||||
|
||||
type getWebhookExecutionRequest struct {
|
||||
webhookExecutionRequest
|
||||
type repoWebhookExecutionRequest struct {
|
||||
repoWebhookRequest
|
||||
ID int64 `path:"webhook_execution_id"`
|
||||
}
|
||||
|
||||
type getSpaceWebhookExecutionRequest struct {
|
||||
spaceWebhookExecutionRequest
|
||||
}
|
||||
|
||||
type getRepoWebhookExecutionRequest struct {
|
||||
repoWebhookExecutionRequest
|
||||
}
|
||||
|
||||
var queryParameterSortWebhook = openapi3.ParameterOrRef{
|
||||
|
@ -113,99 +152,210 @@ var queryParameterQueryWebhook = openapi3.ParameterOrRef{
|
|||
|
||||
//nolint:funlen
|
||||
func webhookOperations(reflector *openapi3.Reflector) {
|
||||
createWebhook := openapi3.Operation{}
|
||||
createWebhook.WithTags("webhook")
|
||||
createWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "createWebhook"})
|
||||
_ = reflector.SetRequest(&createWebhook, new(createWebhookRequest), http.MethodPost)
|
||||
_ = reflector.SetJSONResponse(&createWebhook, new(webhookType), http.StatusCreated)
|
||||
_ = reflector.SetJSONResponse(&createWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&createWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&createWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&createWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPost, "/repos/{repo_ref}/webhooks", createWebhook)
|
||||
// space
|
||||
|
||||
listWebhooks := openapi3.Operation{}
|
||||
listWebhooks.WithTags("webhook")
|
||||
listWebhooks.WithMapOfAnything(map[string]interface{}{"operationId": "listWebhooks"})
|
||||
listWebhooks.WithParameters(queryParameterQueryWebhook, queryParameterSortWebhook, queryParameterOrder,
|
||||
createSpaceWebhook := openapi3.Operation{}
|
||||
createSpaceWebhook.WithTags("webhook")
|
||||
createSpaceWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "createSpaceWebhook"})
|
||||
_ = reflector.SetRequest(&createSpaceWebhook, new(createSpaceWebhookRequest), http.MethodPost)
|
||||
_ = reflector.SetJSONResponse(&createSpaceWebhook, new(webhookType), http.StatusCreated)
|
||||
_ = reflector.SetJSONResponse(&createSpaceWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&createSpaceWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&createSpaceWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&createSpaceWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPost, "/spaces/{space_ref}/webhooks", createSpaceWebhook)
|
||||
|
||||
listSpaceWebhooks := openapi3.Operation{}
|
||||
listSpaceWebhooks.WithTags("webhook")
|
||||
listSpaceWebhooks.WithMapOfAnything(map[string]interface{}{"operationId": "listSpaceWebhooks"})
|
||||
listSpaceWebhooks.WithParameters(queryParameterQueryWebhook, queryParameterSortWebhook, queryParameterOrder,
|
||||
QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&listWebhooks, new(listWebhooksRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&listWebhooks, new([]webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&listWebhooks, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&listWebhooks, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&listWebhooks, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listWebhooks, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/webhooks", listWebhooks)
|
||||
_ = reflector.SetRequest(&listSpaceWebhooks, new(listSpaceWebhooksRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhooks, new([]webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhooks, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhooks, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhooks, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhooks, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/spaces/{space_ref}/webhooks", listSpaceWebhooks)
|
||||
|
||||
getWebhook := openapi3.Operation{}
|
||||
getWebhook.WithTags("webhook")
|
||||
getWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "getWebhook"})
|
||||
_ = reflector.SetRequest(&getWebhook, new(getWebhookRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&getWebhook, new(webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&getWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&getWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&getWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&getWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/webhooks/{webhook_identifier}", getWebhook)
|
||||
getSpaceWebhook := openapi3.Operation{}
|
||||
getSpaceWebhook.WithTags("webhook")
|
||||
getSpaceWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "getSpaceWebhook"})
|
||||
_ = reflector.SetRequest(&getSpaceWebhook, new(getSpaceWebhookRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhook, new(webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/spaces/{space_ref}/webhooks/{webhook_identifier}", getSpaceWebhook)
|
||||
|
||||
updateWebhook := openapi3.Operation{}
|
||||
updateWebhook.WithTags("webhook")
|
||||
updateWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "updateWebhook"})
|
||||
_ = reflector.SetRequest(&updateWebhook, new(updateWebhookRequest), http.MethodPatch)
|
||||
_ = reflector.SetJSONResponse(&updateWebhook, new(webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&updateWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&updateWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&updateWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&updateWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPatch, "/repos/{repo_ref}/webhooks/{webhook_identifier}", updateWebhook)
|
||||
updateSpaceWebhook := openapi3.Operation{}
|
||||
updateSpaceWebhook.WithTags("webhook")
|
||||
updateSpaceWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "updateWebhook"})
|
||||
_ = reflector.SetRequest(&updateSpaceWebhook, new(updateSpaceWebhookRequest), http.MethodPatch)
|
||||
_ = reflector.SetJSONResponse(&updateSpaceWebhook, new(webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&updateSpaceWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&updateSpaceWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&updateSpaceWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&updateSpaceWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(
|
||||
http.MethodPatch, "/spaces/{space_ref}/webhooks/{webhook_identifier}", updateSpaceWebhook,
|
||||
)
|
||||
|
||||
deleteWebhook := openapi3.Operation{}
|
||||
deleteWebhook.WithTags("webhook")
|
||||
deleteWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "deleteWebhook"})
|
||||
_ = reflector.SetRequest(&deleteWebhook, new(deleteWebhookRequest), http.MethodDelete)
|
||||
_ = reflector.SetJSONResponse(&deleteWebhook, nil, http.StatusNoContent)
|
||||
_ = reflector.SetJSONResponse(&deleteWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&deleteWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&deleteWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&deleteWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodDelete, "/repos/{repo_ref}/webhooks/{webhook_identifier}", deleteWebhook)
|
||||
deleteSpaceWebhook := openapi3.Operation{}
|
||||
deleteSpaceWebhook.WithTags("webhook")
|
||||
deleteSpaceWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "deleteWebhook"})
|
||||
_ = reflector.SetRequest(&deleteSpaceWebhook, new(deleteSpaceWebhookRequest), http.MethodDelete)
|
||||
_ = reflector.SetJSONResponse(&deleteSpaceWebhook, nil, http.StatusNoContent)
|
||||
_ = reflector.SetJSONResponse(&deleteSpaceWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&deleteSpaceWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&deleteSpaceWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&deleteSpaceWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(
|
||||
http.MethodDelete, "/spaces/{space_ref}/webhooks/{webhook_identifier}", deleteSpaceWebhook,
|
||||
)
|
||||
|
||||
listWebhookExecutions := openapi3.Operation{}
|
||||
listWebhookExecutions.WithTags("webhook")
|
||||
listWebhookExecutions.WithMapOfAnything(map[string]interface{}{"operationId": "listWebhookExecutions"})
|
||||
listWebhookExecutions.WithParameters(QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&listWebhookExecutions, new(listWebhookExecutionsRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&listWebhookExecutions, new([]types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&listWebhookExecutions, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&listWebhookExecutions, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&listWebhookExecutions, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listWebhookExecutions, new(usererror.Error), http.StatusForbidden)
|
||||
listSpaceWebhookExecutions := openapi3.Operation{}
|
||||
listSpaceWebhookExecutions.WithTags("webhook")
|
||||
listSpaceWebhookExecutions.WithMapOfAnything(map[string]interface{}{"operationId": "listSpaceWebhookExecutions"})
|
||||
listSpaceWebhookExecutions.WithParameters(QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&listSpaceWebhookExecutions, new(listSpaceWebhookExecutionsRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhookExecutions, new([]types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhookExecutions, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhookExecutions, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhookExecutions, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listSpaceWebhookExecutions, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet,
|
||||
"/repos/{repo_ref}/webhooks/{webhook_identifier}/executions", listWebhookExecutions)
|
||||
"/spaces/{space_ref}/webhooks/{webhook_identifier}/executions", listSpaceWebhookExecutions)
|
||||
|
||||
getWebhookExecution := openapi3.Operation{}
|
||||
getWebhookExecution.WithTags("webhook")
|
||||
getWebhookExecution.WithMapOfAnything(map[string]interface{}{"operationId": "getWebhookExecution"})
|
||||
getWebhookExecution.WithParameters(QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&getWebhookExecution, new(getWebhookExecutionRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&getWebhookExecution, new(types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&getWebhookExecution, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&getWebhookExecution, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&getWebhookExecution, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&getWebhookExecution, new(usererror.Error), http.StatusForbidden)
|
||||
getSpaceWebhookExecution := openapi3.Operation{}
|
||||
getSpaceWebhookExecution.WithTags("webhook")
|
||||
getSpaceWebhookExecution.WithMapOfAnything(map[string]interface{}{"operationId": "getSpaceWebhookExecution"})
|
||||
getSpaceWebhookExecution.WithParameters(QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&getSpaceWebhookExecution, new(getSpaceWebhookExecutionRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhookExecution, new(types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhookExecution, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhookExecution, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhookExecution, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&getSpaceWebhookExecution, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet,
|
||||
"/repos/{repo_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}", getWebhookExecution)
|
||||
"/spaces/{space_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}",
|
||||
getSpaceWebhookExecution,
|
||||
)
|
||||
|
||||
retriggerWebhookExecution := openapi3.Operation{}
|
||||
retriggerWebhookExecution.WithTags("webhook")
|
||||
retriggerWebhookExecution.WithMapOfAnything(map[string]interface{}{"operationId": "retriggerWebhookExecution"})
|
||||
_ = reflector.SetRequest(&retriggerWebhookExecution, new(webhookExecutionRequest), http.MethodPost)
|
||||
_ = reflector.SetJSONResponse(&retriggerWebhookExecution, new(types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&retriggerWebhookExecution, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&retriggerWebhookExecution, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&retriggerWebhookExecution, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&retriggerWebhookExecution, new(usererror.Error), http.StatusForbidden)
|
||||
retriggerSpaceWebhookExecution := openapi3.Operation{}
|
||||
retriggerSpaceWebhookExecution.WithTags("webhook")
|
||||
retriggerSpaceWebhookExecution.WithMapOfAnything(
|
||||
map[string]interface{}{"operationId": "retriggerSpaceWebhookExecution"},
|
||||
)
|
||||
_ = reflector.SetRequest(&retriggerSpaceWebhookExecution, new(spaceWebhookExecutionRequest), http.MethodPost)
|
||||
_ = reflector.SetJSONResponse(&retriggerSpaceWebhookExecution, new(types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&retriggerSpaceWebhookExecution, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&retriggerSpaceWebhookExecution, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&retriggerSpaceWebhookExecution, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&retriggerSpaceWebhookExecution, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPost,
|
||||
"/spaces/{space_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}/retrigger",
|
||||
retriggerSpaceWebhookExecution,
|
||||
)
|
||||
|
||||
// repo
|
||||
|
||||
createRepoWebhook := openapi3.Operation{}
|
||||
createRepoWebhook.WithTags("webhook")
|
||||
createRepoWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "createRepoWebhook"})
|
||||
_ = reflector.SetRequest(&createRepoWebhook, new(createRepoWebhookRequest), http.MethodPost)
|
||||
_ = reflector.SetJSONResponse(&createRepoWebhook, new(webhookType), http.StatusCreated)
|
||||
_ = reflector.SetJSONResponse(&createRepoWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&createRepoWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&createRepoWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&createRepoWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPost, "/repos/{repo_ref}/webhooks", createRepoWebhook)
|
||||
|
||||
listRepoWebhooks := openapi3.Operation{}
|
||||
listRepoWebhooks.WithTags("webhook")
|
||||
listRepoWebhooks.WithMapOfAnything(map[string]interface{}{"operationId": "listRepoWebhooks"})
|
||||
listRepoWebhooks.WithParameters(queryParameterQueryWebhook, queryParameterSortWebhook, queryParameterOrder,
|
||||
QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&listRepoWebhooks, new(listRepoWebhooksRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhooks, new([]webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhooks, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhooks, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhooks, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhooks, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/webhooks", listRepoWebhooks)
|
||||
|
||||
getRepoWebhook := openapi3.Operation{}
|
||||
getRepoWebhook.WithTags("webhook")
|
||||
getRepoWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "getRepoWebhook"})
|
||||
_ = reflector.SetRequest(&getRepoWebhook, new(getRepoWebhookRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhook, new(webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/webhooks/{webhook_identifier}", getRepoWebhook)
|
||||
|
||||
updateRepoWebhook := openapi3.Operation{}
|
||||
updateRepoWebhook.WithTags("webhook")
|
||||
updateRepoWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "updateRepoWebhook"})
|
||||
_ = reflector.SetRequest(&updateRepoWebhook, new(updateRepoWebhookRequest), http.MethodPatch)
|
||||
_ = reflector.SetJSONResponse(&updateRepoWebhook, new(webhookType), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&updateRepoWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&updateRepoWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&updateRepoWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&updateRepoWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPatch, "/repos/{repo_ref}/webhooks/{webhook_identifier}", updateRepoWebhook)
|
||||
|
||||
deleteRepoWebhook := openapi3.Operation{}
|
||||
deleteRepoWebhook.WithTags("webhook")
|
||||
deleteRepoWebhook.WithMapOfAnything(map[string]interface{}{"operationId": "deleteRepoWebhook"})
|
||||
_ = reflector.SetRequest(&deleteRepoWebhook, new(deleteRepoWebhookRequest), http.MethodDelete)
|
||||
_ = reflector.SetJSONResponse(&deleteRepoWebhook, nil, http.StatusNoContent)
|
||||
_ = reflector.SetJSONResponse(&deleteRepoWebhook, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&deleteRepoWebhook, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&deleteRepoWebhook, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&deleteRepoWebhook, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(
|
||||
http.MethodDelete, "/repos/{repo_ref}/webhooks/{webhook_identifier}", deleteRepoWebhook,
|
||||
)
|
||||
|
||||
listRepoWebhookExecutions := openapi3.Operation{}
|
||||
listRepoWebhookExecutions.WithTags("webhook")
|
||||
listRepoWebhookExecutions.WithMapOfAnything(map[string]interface{}{"operationId": "listRepoWebhookExecutions"})
|
||||
listRepoWebhookExecutions.WithParameters(QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&listRepoWebhookExecutions, new(listRepoWebhookExecutionsRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhookExecutions, new([]types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhookExecutions, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhookExecutions, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhookExecutions, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listRepoWebhookExecutions, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet,
|
||||
"/repos/{repo_ref}/webhooks/{webhook_identifier}/executions", listRepoWebhookExecutions)
|
||||
|
||||
getRepoWebhookExecution := openapi3.Operation{}
|
||||
getRepoWebhookExecution.WithTags("webhook")
|
||||
getRepoWebhookExecution.WithMapOfAnything(map[string]interface{}{"operationId": "getRepoWebhookExecution"})
|
||||
getRepoWebhookExecution.WithParameters(QueryParameterPage, QueryParameterLimit)
|
||||
_ = reflector.SetRequest(&getRepoWebhookExecution, new(getRepoWebhookExecutionRequest), http.MethodGet)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhookExecution, new(types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhookExecution, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhookExecution, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhookExecution, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&getRepoWebhookExecution, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet,
|
||||
"/repos/{repo_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}", getRepoWebhookExecution)
|
||||
|
||||
retriggerRepoWebhookExecution := openapi3.Operation{}
|
||||
retriggerRepoWebhookExecution.WithTags("webhook")
|
||||
retriggerRepoWebhookExecution.WithMapOfAnything(map[string]interface{}{"operationId": "retriggerRepoWebhookExecution"})
|
||||
_ = reflector.SetRequest(&retriggerRepoWebhookExecution, new(repoWebhookExecutionRequest), http.MethodPost)
|
||||
_ = reflector.SetJSONResponse(&retriggerRepoWebhookExecution, new(types.WebhookExecution), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&retriggerRepoWebhookExecution, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&retriggerRepoWebhookExecution, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&retriggerRepoWebhookExecution, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&retriggerRepoWebhookExecution, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPost,
|
||||
"/repos/{repo_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}/retrigger",
|
||||
retriggerWebhookExecution)
|
||||
retriggerRepoWebhookExecution)
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ var codes = map[errors.Status]int{
|
|||
errors.StatusNotImplemented: http.StatusNotImplemented,
|
||||
errors.StatusPreconditionFailed: http.StatusPreconditionFailed,
|
||||
errors.StatusUnauthorized: http.StatusUnauthorized,
|
||||
errors.StatusForbidden: http.StatusForbidden,
|
||||
errors.StatusInternal: http.StatusInternalServerError,
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ func setupRoutesV1WithAuth(r chi.Router,
|
|||
capabilitiesCtrl *capabilities.Controller,
|
||||
) {
|
||||
setupAccountWithAuth(r, userCtrl, config)
|
||||
setupSpaces(r, appCtx, spaceCtrl, userGroupCtrl)
|
||||
setupSpaces(r, appCtx, spaceCtrl, userGroupCtrl, webhookCtrl)
|
||||
setupRepos(r, repoCtrl, repoSettingsCtrl, pipelineCtrl, executionCtrl, triggerCtrl,
|
||||
logCtrl, pullreqCtrl, webhookCtrl, checkCtrl, uploadCtrl)
|
||||
setupConnectors(r, connectorCtrl)
|
||||
|
@ -247,6 +247,7 @@ func setupSpaces(
|
|||
appCtx context.Context,
|
||||
spaceCtrl *space.Controller,
|
||||
userGroupCtrl *usergroup.Controller,
|
||||
webhookCtrl *webhook.Controller,
|
||||
|
||||
) {
|
||||
r.Route("/spaces", func(r chi.Router) {
|
||||
|
@ -290,6 +291,7 @@ func setupSpaces(
|
|||
})
|
||||
|
||||
SetupSpaceLabels(r, spaceCtrl)
|
||||
SetupWebhookSpace(r, webhookCtrl)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -316,6 +318,28 @@ func SetupSpaceLabels(r chi.Router, spaceCtrl *space.Controller) {
|
|||
})
|
||||
}
|
||||
|
||||
func SetupWebhookSpace(r chi.Router, webhookCtrl *webhook.Controller) {
|
||||
r.Route("/webhooks", func(r chi.Router) {
|
||||
r.Post("/", handlerwebhook.HandleCreateSpace(webhookCtrl))
|
||||
r.Get("/", handlerwebhook.HandleListSpace(webhookCtrl))
|
||||
|
||||
r.Route(fmt.Sprintf("/{%s}", request.PathParamWebhookIdentifier), func(r chi.Router) {
|
||||
r.Get("/", handlerwebhook.HandleFindSpace(webhookCtrl))
|
||||
r.Patch("/", handlerwebhook.HandleUpdateSpace(webhookCtrl))
|
||||
r.Delete("/", handlerwebhook.HandleDeleteSpace(webhookCtrl))
|
||||
|
||||
r.Route("/executions", func(r chi.Router) {
|
||||
r.Get("/", handlerwebhook.HandleListExecutionsSpace(webhookCtrl))
|
||||
|
||||
r.Route(fmt.Sprintf("/{%s}", request.PathParamWebhookExecutionID), func(r chi.Router) {
|
||||
r.Get("/", handlerwebhook.HandleFindExecutionSpace(webhookCtrl))
|
||||
r.Post("/retrigger", handlerwebhook.HandleRetriggerExecutionSpace(webhookCtrl))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func setupRepos(r chi.Router,
|
||||
repoCtrl *repo.Controller,
|
||||
repoSettingsCtrl *reposettings.Controller,
|
||||
|
@ -427,7 +451,7 @@ func setupRepos(r chi.Router,
|
|||
|
||||
SetupPullReq(r, pullreqCtrl)
|
||||
|
||||
SetupWebhook(r, webhookCtrl)
|
||||
SetupWebhookRepo(r, webhookCtrl)
|
||||
|
||||
setupPipelines(r, repoCtrl, pipelineCtrl, executionCtrl, triggerCtrl, logCtrl)
|
||||
|
||||
|
@ -681,22 +705,22 @@ func setupPullReqLabels(r chi.Router, pullreqCtrl *pullreq.Controller) {
|
|||
})
|
||||
}
|
||||
|
||||
func SetupWebhook(r chi.Router, webhookCtrl *webhook.Controller) {
|
||||
func SetupWebhookRepo(r chi.Router, webhookCtrl *webhook.Controller) {
|
||||
r.Route("/webhooks", func(r chi.Router) {
|
||||
r.Post("/", handlerwebhook.HandleCreate(webhookCtrl))
|
||||
r.Get("/", handlerwebhook.HandleList(webhookCtrl))
|
||||
r.Post("/", handlerwebhook.HandleCreateRepo(webhookCtrl))
|
||||
r.Get("/", handlerwebhook.HandleListRepo(webhookCtrl))
|
||||
|
||||
r.Route(fmt.Sprintf("/{%s}", request.PathParamWebhookIdentifier), func(r chi.Router) {
|
||||
r.Get("/", handlerwebhook.HandleFind(webhookCtrl))
|
||||
r.Patch("/", handlerwebhook.HandleUpdate(webhookCtrl))
|
||||
r.Delete("/", handlerwebhook.HandleDelete(webhookCtrl))
|
||||
r.Get("/", handlerwebhook.HandleFindRepo(webhookCtrl))
|
||||
r.Patch("/", handlerwebhook.HandleUpdateRepo(webhookCtrl))
|
||||
r.Delete("/", handlerwebhook.HandleDeleteRepo(webhookCtrl))
|
||||
|
||||
r.Route("/executions", func(r chi.Router) {
|
||||
r.Get("/", handlerwebhook.HandleListExecutions(webhookCtrl))
|
||||
r.Get("/", handlerwebhook.HandleListExecutionsRepo(webhookCtrl))
|
||||
|
||||
r.Route(fmt.Sprintf("/{%s}", request.PathParamWebhookExecutionID), func(r chi.Router) {
|
||||
r.Get("/", handlerwebhook.HandleFindExecution(webhookCtrl))
|
||||
r.Post("/retrigger", handlerwebhook.HandleRetriggerExecution(webhookCtrl))
|
||||
r.Get("/", handlerwebhook.HandleFindExecutionRepo(webhookCtrl))
|
||||
r.Post("/retrigger", handlerwebhook.HandleRetriggerExecutionRepo(webhookCtrl))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
webhookpkg "github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/services/webhook"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
|
@ -62,7 +61,7 @@ func (migrate Webhook) Import(
|
|||
|
||||
// sanitize and convert webhooks
|
||||
for i, whook := range extWebhooks {
|
||||
triggers := webhookpkg.ConvertTriggers(whook.Events)
|
||||
triggers := webhook.ConvertTriggers(whook.Events)
|
||||
err := sanitizeWebhook(whook, triggers, migrate.allowLoopback, migrate.allowPrivateNetwork)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to sanitize external webhook input: %w", err)
|
||||
|
@ -84,7 +83,7 @@ func (migrate Webhook) Import(
|
|||
URL: whook.Target,
|
||||
Enabled: whook.Active,
|
||||
Insecure: whook.SkipVerify,
|
||||
Triggers: webhookpkg.DeduplicateTriggers(triggers),
|
||||
Triggers: webhook.DeduplicateTriggers(triggers),
|
||||
LatestExecutionResult: nil,
|
||||
}
|
||||
|
||||
|
@ -117,11 +116,11 @@ func sanitizeWebhook(
|
|||
return err
|
||||
}
|
||||
|
||||
if err := webhookpkg.CheckURL(in.Target, allowLoopback, allowPrivateNetwork, false); err != nil {
|
||||
if err := webhook.CheckURL(in.Target, allowLoopback, allowPrivateNetwork, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := webhookpkg.CheckTriggers(triggers); err != nil { //nolint:revive
|
||||
if err := webhook.CheckTriggers(triggers); err != nil { //nolint:revive
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/errors"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ const (
|
|||
webhookMaxSecretLength = 4096
|
||||
)
|
||||
|
||||
var ErrInternalWebhookOperationNotAllowed = usererror.Forbidden("changes to internal webhooks are not allowed")
|
||||
var ErrInternalWebhookOperationNotAllowed = errors.Forbidden("changes to internal webhooks are not allowed")
|
||||
|
||||
// CheckURL validates the url of a webhook.
|
||||
func CheckURL(rawURL string, allowLoopback bool, allowPrivateNetwork bool, internal bool) error {
|
||||
|
@ -58,9 +58,9 @@ func CheckURL(rawURL string, allowLoopback bool, allowPrivateNetwork bool, inter
|
|||
// basic validation for loopback / private network addresses (only sanitary to give user an early error)
|
||||
// IMPORTANT: during webook execution loopback / private network addresses are blocked (handles DNS resolution)
|
||||
|
||||
if host == "localhost" {
|
||||
return check.NewValidationError("localhost is not allowed.")
|
||||
}
|
||||
// if host == "localhost" {
|
||||
// return check.NewValidationError("localhost is not allowed.")
|
||||
// }
|
||||
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
if !allowLoopback && ip.IsLoopback() {
|
||||
|
@ -80,7 +80,7 @@ func CheckURL(rawURL string, allowLoopback bool, allowPrivateNetwork bool, inter
|
|||
}
|
||||
|
||||
// checkSecret validates the secret of a webhook.
|
||||
func checkSecret(secret string) error {
|
||||
func CheckSecret(secret string) error {
|
||||
if len(secret) > webhookMaxSecretLength {
|
||||
return check.NewValidationErrorf("The secret of a webhook can be at most %d characters long.",
|
||||
webhookMaxSecretLength)
|
|
@ -16,13 +16,11 @@ package webhook
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/store/database/migrate"
|
||||
"github.com/harness/gitness/errors"
|
||||
"github.com/harness/gitness/store"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
@ -31,102 +29,7 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type CreateInput struct {
|
||||
// TODO [CODE-1363]: remove after identifier migration.
|
||||
UID string `json:"uid" deprecated:"true"`
|
||||
Identifier string `json:"identifier"`
|
||||
// TODO [CODE-1364]: Remove once UID/Identifier migration is completed.
|
||||
DisplayName string `json:"display_name"`
|
||||
Description string `json:"description"`
|
||||
URL string `json:"url"`
|
||||
Secret string `json:"secret"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Insecure bool `json:"insecure"`
|
||||
Triggers []enum.WebhookTrigger `json:"triggers"`
|
||||
}
|
||||
|
||||
// Create creates a new webhook.
|
||||
//
|
||||
//nolint:gocognit
|
||||
func (c *Controller) Create(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
in *CreateInput,
|
||||
internal bool,
|
||||
) (*types.Webhook, error) {
|
||||
// validate input
|
||||
err := sanitizeCreateInput(in, c.allowLoopback, c.allowPrivateNetwork, internal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encryptedSecret, err := c.encrypter.Encrypt(in.Secret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encrypt webhook secret: %w", err)
|
||||
}
|
||||
|
||||
// create new webhook object
|
||||
hook := &types.Webhook{
|
||||
ID: 0, // the ID will be populated in the data layer
|
||||
Version: 0, // the Version will be populated in the data layer
|
||||
CreatedBy: session.Principal.ID,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
ParentID: repo.ID,
|
||||
ParentType: enum.WebhookParentRepo,
|
||||
Internal: internal,
|
||||
|
||||
// user input
|
||||
Identifier: in.Identifier,
|
||||
DisplayName: in.DisplayName,
|
||||
Description: in.Description,
|
||||
URL: in.URL,
|
||||
Secret: string(encryptedSecret),
|
||||
Enabled: in.Enabled,
|
||||
Insecure: in.Insecure,
|
||||
Triggers: DeduplicateTriggers(in.Triggers),
|
||||
LatestExecutionResult: nil,
|
||||
}
|
||||
|
||||
err = c.webhookStore.Create(ctx, hook)
|
||||
|
||||
// internal hooks are hidden from non-internal read requests - properly communicate their existence on duplicate.
|
||||
// This is best effort, any error we just ignore and fallback to original duplicate error.
|
||||
if errors.Is(err, store.ErrDuplicate) && !internal {
|
||||
existingHook, derr := c.webhookStore.FindByIdentifier(ctx, enum.WebhookParentRepo, repo.ID, hook.Identifier)
|
||||
if derr != nil {
|
||||
log.Ctx(ctx).Warn().Err(derr).Msgf(
|
||||
"failed to retrieve webhook for repo %d with identifier %q on duplicate error",
|
||||
repo.ID,
|
||||
hook.Identifier,
|
||||
)
|
||||
}
|
||||
if derr == nil && existingHook.Internal {
|
||||
return nil, usererror.Conflict("The provided identifier is reserved for internal purposes.")
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to store webhook: %w", err)
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
func sanitizeCreateInput(
|
||||
in *CreateInput,
|
||||
allowLoopback bool,
|
||||
allowPrivateNetwork bool,
|
||||
internal bool,
|
||||
) error {
|
||||
func (s *Service) sanitizeCreateInput(in *types.WebhookCreateInput, internal bool) error {
|
||||
// TODO [CODE-1363]: remove after identifier migration.
|
||||
if in.Identifier == "" {
|
||||
in.Identifier = in.UID
|
||||
|
@ -154,10 +57,10 @@ func sanitizeCreateInput(
|
|||
if err := check.Description(in.Description); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := CheckURL(in.URL, allowLoopback, allowPrivateNetwork, internal); err != nil {
|
||||
if err := CheckURL(in.URL, s.config.AllowLoopback, s.config.AllowPrivateNetwork, internal); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkSecret(in.Secret); err != nil {
|
||||
if err := CheckSecret(in.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := CheckTriggers(in.Triggers); err != nil { //nolint:revive
|
||||
|
@ -166,3 +69,72 @@ func sanitizeCreateInput(
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Create(
|
||||
ctx context.Context,
|
||||
principalID int64,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
internal bool,
|
||||
in *types.WebhookCreateInput,
|
||||
) (*types.Webhook, error) {
|
||||
err := s.sanitizeCreateInput(in, internal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encryptedSecret, err := s.encrypter.Encrypt(in.Secret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encrypt webhook secret: %w", err)
|
||||
}
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
// create new webhook object
|
||||
hook := &types.Webhook{
|
||||
ID: 0, // the ID will be populated in the data layer
|
||||
Version: 0, // the Version will be populated in the data layer
|
||||
CreatedBy: principalID,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
ParentID: parentID,
|
||||
ParentType: parentType,
|
||||
Internal: internal,
|
||||
|
||||
// user input
|
||||
Identifier: in.Identifier,
|
||||
DisplayName: in.DisplayName,
|
||||
Description: in.Description,
|
||||
URL: in.URL,
|
||||
Secret: string(encryptedSecret),
|
||||
Enabled: in.Enabled,
|
||||
Insecure: in.Insecure,
|
||||
Triggers: DeduplicateTriggers(in.Triggers),
|
||||
LatestExecutionResult: nil,
|
||||
}
|
||||
|
||||
err = s.webhookStore.Create(ctx, hook)
|
||||
|
||||
// internal hooks are hidden from non-internal read requests - properly communicate their existence on duplicate.
|
||||
// This is best effort, any error we just ignore and fallback to original duplicate error.
|
||||
if errors.Is(err, store.ErrDuplicate) && !internal {
|
||||
existingHook, derr := s.webhookStore.FindByIdentifier(
|
||||
ctx, enum.WebhookParentRepo, parentID, hook.Identifier)
|
||||
if derr != nil {
|
||||
log.Ctx(ctx).Warn().Err(derr).Msgf(
|
||||
"failed to retrieve webhook for repo %d with identifier %q on duplicate error",
|
||||
parentID,
|
||||
hook.Identifier,
|
||||
)
|
||||
}
|
||||
if derr == nil && existingHook.Internal {
|
||||
return nil, errors.Conflict("The provided identifier is reserved for internal purposes.")
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to store webhook: %w", err)
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// Delete deletes an existing webhook.
|
||||
func (s *Service) Delete(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
allowDeletingInternal bool,
|
||||
) error {
|
||||
hook, err := s.GetWebhookVerifyOwnership(ctx, parentID, parentType, webhookIdentifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hook.Internal && !allowDeletingInternal {
|
||||
return ErrInternalWebhookOperationNotAllowed
|
||||
}
|
||||
|
||||
return s.webhookStore.Delete(ctx, hook.ID)
|
||||
}
|
|
@ -36,9 +36,14 @@ func generateTriggerIDFromEventID(eventID string) string {
|
|||
// using the eventID to generate a deterministic triggerID and using the output of bodyFn as payload.
|
||||
// The method tries to find the repository and principal and provides both to the bodyFn to generate the body.
|
||||
// NOTE: technically we could avoid this call if we send the data via the event (though then events will get big).
|
||||
func (s *Service) triggerForEventWithRepo(ctx context.Context,
|
||||
triggerType enum.WebhookTrigger, eventID string, principalID int64, repoID int64,
|
||||
createBodyFn func(*types.Principal, *types.Repository) (any, error)) error {
|
||||
func (s *Service) triggerForEventWithRepo(
|
||||
ctx context.Context,
|
||||
triggerType enum.WebhookTrigger,
|
||||
eventID string,
|
||||
principalID int64,
|
||||
repoID int64,
|
||||
createBodyFn func(*types.Principal, *types.Repository) (any, error),
|
||||
) error {
|
||||
principal, err := s.findPrincipalForEvent(ctx, principalID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -55,7 +60,12 @@ func (s *Service) triggerForEventWithRepo(ctx context.Context,
|
|||
return fmt.Errorf("body creation function failed: %w", err)
|
||||
}
|
||||
|
||||
return s.triggerForEvent(ctx, eventID, enum.WebhookParentRepo, repo.ID, triggerType, body)
|
||||
parents, err := s.getParentInfoRepo(ctx, repo.ID, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get webhook parent info for parents: %w", err)
|
||||
}
|
||||
|
||||
return s.triggerForEvent(ctx, eventID, parents, triggerType, body)
|
||||
}
|
||||
|
||||
// triggerForEventWithPullReq triggers all webhooks for the given repo and triggerType
|
||||
|
@ -96,7 +106,12 @@ func (s *Service) triggerForEventWithPullReq(ctx context.Context,
|
|||
return fmt.Errorf("body creation function failed: %w", err)
|
||||
}
|
||||
|
||||
return s.triggerForEvent(ctx, eventID, enum.WebhookParentRepo, targetRepo.ID, triggerType, body)
|
||||
parents, err := s.getParentInfoRepo(ctx, targetRepo.ID, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get webhook parent info: %w", err)
|
||||
}
|
||||
|
||||
return s.triggerForEvent(ctx, eventID, parents, triggerType, body)
|
||||
}
|
||||
|
||||
// findRepositoryForEvent finds the repository for the provided repoID.
|
||||
|
@ -149,16 +164,23 @@ func (s *Service) findPrincipalForEvent(ctx context.Context, principalID int64)
|
|||
|
||||
// triggerForEvent triggers all webhooks for the given parentType/ID and triggerType
|
||||
// using the eventID to generate a deterministic triggerID and sending the provided body as payload.
|
||||
func (s *Service) triggerForEvent(ctx context.Context, eventID string,
|
||||
parentType enum.WebhookParent, parentID int64, triggerType enum.WebhookTrigger, body any) error {
|
||||
func (s *Service) triggerForEvent(
|
||||
ctx context.Context,
|
||||
eventID string,
|
||||
parents []types.WebhookParentInfo,
|
||||
triggerType enum.WebhookTrigger,
|
||||
body any,
|
||||
) error {
|
||||
triggerID := generateTriggerIDFromEventID(eventID)
|
||||
|
||||
results, err := s.triggerWebhooksFor(ctx, parentType, parentID, triggerID, triggerType, body)
|
||||
results, err := s.triggerWebhooksFor(ctx, parents, triggerID, triggerType, body)
|
||||
|
||||
// return all errors and force the event to be reprocessed (it's not webhook execution specific!)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to trigger %s (id: '%s') for webhooks of %s %d: %w",
|
||||
triggerType, triggerID, parentType, parentID, err)
|
||||
return fmt.Errorf(
|
||||
"failed to trigger %s (id: '%s') for webhooks %#v: %w",
|
||||
triggerType, triggerID, parents, err,
|
||||
)
|
||||
}
|
||||
|
||||
// go through all events and figure out if we need to retry the event.
|
||||
|
@ -172,8 +194,9 @@ func (s *Service) triggerForEvent(ctx context.Context, eventID string,
|
|||
|
||||
// combine errors of non-successful executions
|
||||
if result.Execution.Result != enum.WebhookExecutionResultSuccess {
|
||||
errs = multierr.Append(errs, fmt.Errorf("execution %d of webhook %d resulted in %s: %w",
|
||||
result.Execution.ID, result.Webhook.ID, result.Execution.Result, result.Err))
|
||||
errs = multierr.Append(errs,
|
||||
fmt.Errorf("execution %d of webhook %d resulted in %s: %w",
|
||||
result.Execution.ID, result.Webhook.ID, result.Execution.Result, result.Err))
|
||||
}
|
||||
|
||||
if result.Execution.Result == enum.WebhookExecutionResultRetriableError {
|
||||
|
@ -183,12 +206,12 @@ func (s *Service) triggerForEvent(ctx context.Context, eventID string,
|
|||
|
||||
// in case there was at least one error, log error details in single log to reduce log flooding
|
||||
if errs != nil {
|
||||
log.Ctx(ctx).Warn().Err(errs).Msgf("webhook execution for %s %d had errors", parentType, parentID)
|
||||
log.Ctx(ctx).Warn().Err(errs).Msgf("webhook execution for %#v had errors", parents)
|
||||
}
|
||||
|
||||
// in case at least one webhook has to be retried, return an error to the event framework to have it reprocessed
|
||||
if retryRequired {
|
||||
return fmt.Errorf("at least one webhook execution resulted in a retry for %s %d", parentType, parentID)
|
||||
return fmt.Errorf("at least one webhook execution resulted in a retry for %#v", parents)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// FindExecution finds a webhook execution.
|
||||
func (s *Service) FindExecution(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
webhook, err := s.GetWebhookVerifyOwnership(ctx, parentID, parentType, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
webhookExecution, err := s.GetWebhookExecutionVerifyOwnership(ctx, webhook.ID, webhookExecutionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return webhookExecution, nil
|
||||
}
|
||||
|
||||
// ListExecutions returns the executions of the webhook.
|
||||
func (s *Service) ListExecutions(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
filter *types.WebhookExecutionFilter,
|
||||
) ([]*types.WebhookExecution, int64, error) {
|
||||
webhook, err := s.GetWebhookVerifyOwnership(ctx, parentID, parentType, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to verify ownership for webhook %d: %w", webhook.ID, err)
|
||||
}
|
||||
|
||||
total, err := s.webhookExecutionStore.CountForWebhook(ctx, webhook.ID)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count webhook executions for webhook %d: %w", webhook.ID, err)
|
||||
}
|
||||
|
||||
webhookExecutions, err := s.webhookExecutionStore.ListForWebhook(ctx, webhook.ID, filter)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to list webhook executions for webhook %d: %w", webhook.ID, err)
|
||||
}
|
||||
|
||||
return webhookExecutions, total, nil
|
||||
}
|
||||
|
||||
// RetriggerExecution retriggers an existing webhook execution.
|
||||
func (s *Service) RetriggerExecution(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
webhook, err := s.GetWebhookVerifyOwnership(
|
||||
ctx, parentID, parentType, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
webhookExecution, err := s.GetWebhookExecutionVerifyOwnership(
|
||||
ctx, webhook.ID, webhookExecutionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
executionResult, err := s.RetriggerWebhookExecution(ctx, webhookExecution.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrigger webhook execution: %w", err)
|
||||
}
|
||||
|
||||
if executionResult.Err != nil {
|
||||
log.Ctx(ctx).Warn().Err(executionResult.Err).Msgf(
|
||||
"retrigger of webhhook %d execution %d (new id: %d) had an error",
|
||||
webhook.ID, webhookExecution.ID, executionResult.Execution.ID)
|
||||
}
|
||||
|
||||
return executionResult.Execution, nil
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// Listreturns the webhooks from the provided scope.
|
||||
func (s *Service) List(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
inherited bool,
|
||||
filter *types.WebhookFilter,
|
||||
) ([]*types.Webhook, int64, error) {
|
||||
var parents []types.WebhookParentInfo
|
||||
var err error
|
||||
|
||||
switch parentType {
|
||||
case enum.WebhookParentRepo:
|
||||
parents, err = s.getParentInfoRepo(ctx, parentID, inherited)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
case enum.WebhookParentSpace:
|
||||
parents, err = s.getParentInfoSpace(ctx, parentID, inherited)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("webhook type %s is not supported", parentType)
|
||||
}
|
||||
|
||||
count, err := s.webhookStore.Count(ctx, parents, filter)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count webhooks for scope with id %d: %w", parentID, err)
|
||||
}
|
||||
|
||||
webhooks, err := s.webhookStore.List(ctx, parents, filter)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to list webhooks for scope with id %d: %w", parentID, err)
|
||||
}
|
||||
|
||||
return webhooks, count, nil
|
||||
}
|
||||
|
||||
func (s *Service) getParentInfoRepo(
|
||||
ctx context.Context,
|
||||
repoID int64,
|
||||
inherited bool,
|
||||
) ([]types.WebhookParentInfo, error) {
|
||||
var parents []types.WebhookParentInfo
|
||||
|
||||
parents = append(parents, types.WebhookParentInfo{
|
||||
ID: repoID,
|
||||
Type: enum.WebhookParentRepo,
|
||||
})
|
||||
|
||||
if inherited {
|
||||
repo, err := s.repoStore.Find(ctx, repoID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get repo: %w", err)
|
||||
}
|
||||
|
||||
ids, err := s.spaceStore.GetAncestorIDs(ctx, repo.ParentID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get parent space ids: %w", err)
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
parents = append(parents, types.WebhookParentInfo{
|
||||
Type: enum.WebhookParentSpace,
|
||||
ID: id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return parents, nil
|
||||
}
|
||||
|
||||
func (s *Service) getParentInfoSpace(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
inherited bool,
|
||||
) ([]types.WebhookParentInfo, error) {
|
||||
var parents []types.WebhookParentInfo
|
||||
|
||||
if inherited {
|
||||
ids, err := s.spaceStore.GetAncestorIDs(ctx, spaceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get parent space ids: %w", err)
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
parents = append(parents, types.WebhookParentInfo{
|
||||
Type: enum.WebhookParentSpace,
|
||||
ID: id,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
parents = append(parents, types.WebhookParentInfo{
|
||||
Type: enum.WebhookParentSpace,
|
||||
ID: spaceID,
|
||||
})
|
||||
}
|
||||
|
||||
return parents, nil
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/harness/gitness/errors"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
func (s *Service) Find(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
) (*types.Webhook, error) {
|
||||
hook, err := s.GetWebhookVerifyOwnership(ctx, parentID, parentType, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, errors.NotFound("failed to find webhook %s: %q", webhookIdentifier, err)
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
// GetWebhookVerifyOwnership gets the webhook and
|
||||
// ensures it belongs to the scope with the specified id and type.
|
||||
func (s *Service) GetWebhookVerifyOwnership(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
) (*types.Webhook, error) {
|
||||
// TODO: Remove once webhook identifier migration completed
|
||||
webhookID, err := strconv.ParseInt(webhookIdentifier, 10, 64)
|
||||
if (err == nil && webhookID <= 0) || len(strings.TrimSpace(webhookIdentifier)) == 0 {
|
||||
return nil, errors.InvalidArgument("A valid webhook identifier must be provided.")
|
||||
}
|
||||
|
||||
var webhook *types.Webhook
|
||||
if err == nil {
|
||||
webhook, err = s.webhookStore.Find(ctx, webhookID)
|
||||
} else {
|
||||
webhook, err = s.webhookStore.FindByIdentifier(
|
||||
ctx, parentType, parentID, webhookIdentifier)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find webhook with identifier %q: %w", webhookIdentifier, err)
|
||||
}
|
||||
|
||||
// ensure the webhook actually belongs to the repo
|
||||
if webhook.ParentType != parentType || webhook.ParentID != parentID {
|
||||
return nil, errors.NotFound("webhook doesn't belong to requested %s.", parentType)
|
||||
}
|
||||
|
||||
return webhook, nil
|
||||
}
|
||||
|
||||
// GetWebhookExecutionVerifyOwnership gets the webhook execution and
|
||||
// ensures it belongs to the webhook with the specified id.
|
||||
func (s *Service) GetWebhookExecutionVerifyOwnership(
|
||||
ctx context.Context,
|
||||
webhookID int64,
|
||||
webhookExecutionID int64,
|
||||
) (*types.WebhookExecution, error) {
|
||||
if webhookExecutionID <= 0 {
|
||||
return nil, errors.InvalidArgument("A valid webhook execution ID must be provided.")
|
||||
}
|
||||
|
||||
webhookExecution, err := s.webhookExecutionStore.Find(ctx, webhookExecutionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find webhook execution with id %d: %w", webhookExecutionID, err)
|
||||
}
|
||||
|
||||
// ensure the webhook execution actually belongs to the webhook
|
||||
if webhookID != webhookExecution.WebhookID {
|
||||
return nil, errors.NotFound("webhook execution doesn't belong to requested webhook")
|
||||
}
|
||||
|
||||
return webhookExecution, nil
|
||||
}
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/harness/gitness/encrypt"
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/stream"
|
||||
)
|
||||
|
||||
|
@ -79,9 +80,12 @@ func (c *Config) Prepare() error {
|
|||
|
||||
// Service is responsible for processing webhook events.
|
||||
type Service struct {
|
||||
tx dbtx.Transactor
|
||||
|
||||
webhookStore store.WebhookStore
|
||||
webhookExecutionStore store.WebhookExecutionStore
|
||||
urlProvider url.Provider
|
||||
spaceStore store.SpaceStore
|
||||
repoStore store.RepoStore
|
||||
pullreqStore store.PullReqStore
|
||||
principalStore store.PrincipalStore
|
||||
|
@ -101,10 +105,12 @@ type Service struct {
|
|||
func NewService(
|
||||
ctx context.Context,
|
||||
config Config,
|
||||
tx dbtx.Transactor,
|
||||
gitReaderFactory *events.ReaderFactory[*gitevents.Reader],
|
||||
prReaderFactory *events.ReaderFactory[*pullreqevents.Reader],
|
||||
webhookStore store.WebhookStore,
|
||||
webhookExecutionStore store.WebhookExecutionStore,
|
||||
spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore,
|
||||
pullreqStore store.PullReqStore,
|
||||
activityStore store.PullReqActivityStore,
|
||||
|
@ -117,8 +123,10 @@ func NewService(
|
|||
return nil, fmt.Errorf("provided webhook service config is invalid: %w", err)
|
||||
}
|
||||
service := &Service{
|
||||
tx: tx,
|
||||
webhookStore: webhookStore,
|
||||
webhookExecutionStore: webhookExecutionStore,
|
||||
spaceStore: spaceStore,
|
||||
repoStore: repoStore,
|
||||
pullreqStore: pullreqStore,
|
||||
activityStore: activityStore,
|
||||
|
|
|
@ -66,14 +66,16 @@ func (r *TriggerResult) Skipped() bool {
|
|||
return r.Execution == nil
|
||||
}
|
||||
|
||||
func (s *Service) triggerWebhooksFor(ctx context.Context, parentType enum.WebhookParent, parentID int64,
|
||||
triggerID string, triggerType enum.WebhookTrigger, body any) ([]TriggerResult, error) {
|
||||
// get all webhooks for the given parent
|
||||
// NOTE: there never should be even close to 1000 webhooks for a repo (that should be blocked in the future).
|
||||
// We just use 1000 as a safe number to get all hooks
|
||||
webhooks, err := s.webhookStore.List(ctx, parentType, parentID, &types.WebhookFilter{Size: 1000, Order: enum.OrderAsc})
|
||||
func (s *Service) triggerWebhooksFor(
|
||||
ctx context.Context,
|
||||
parents []types.WebhookParentInfo,
|
||||
triggerID string,
|
||||
triggerType enum.WebhookTrigger,
|
||||
body any,
|
||||
) ([]TriggerResult, error) {
|
||||
webhooks, err := s.webhookStore.List(ctx, parents, &types.WebhookFilter{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list webhooks for %s %d: %w", parentType, parentID, err)
|
||||
return nil, fmt.Errorf("failed to list webhooks for: %w", err)
|
||||
}
|
||||
|
||||
return s.triggerWebhooks(ctx, webhooks, triggerID, triggerType, body)
|
||||
|
|
|
@ -18,92 +18,12 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type UpdateInput struct {
|
||||
// TODO [CODE-1363]: remove after identifier migration.
|
||||
UID *string `json:"uid" deprecated:"true"`
|
||||
Identifier *string `json:"identifier"`
|
||||
// TODO [CODE-1364]: Remove once UID/Identifier migration is completed.
|
||||
DisplayName *string `json:"display_name"`
|
||||
Description *string `json:"description"`
|
||||
URL *string `json:"url"`
|
||||
Secret *string `json:"secret"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Insecure *bool `json:"insecure"`
|
||||
Triggers []enum.WebhookTrigger `json:"triggers"`
|
||||
}
|
||||
|
||||
// Update updates an existing webhook.
|
||||
func (c *Controller) Update(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
webhookIdentifier string,
|
||||
in *UpdateInput,
|
||||
allowModifyingInternal bool,
|
||||
) (*types.Webhook, error) {
|
||||
if err := sanitizeUpdateInput(in, c.allowLoopback, c.allowPrivateNetwork); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get the hook and ensure it belongs to us
|
||||
hook, err := c.getWebhookVerifyOwnership(ctx, repo.ID, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !allowModifyingInternal && hook.Internal {
|
||||
return nil, ErrInternalWebhookOperationNotAllowed
|
||||
}
|
||||
|
||||
// update webhook struct (only for values that are provided)
|
||||
if in.Identifier != nil {
|
||||
hook.Identifier = *in.Identifier
|
||||
}
|
||||
if in.DisplayName != nil {
|
||||
hook.DisplayName = *in.DisplayName
|
||||
}
|
||||
if in.Description != nil {
|
||||
hook.Description = *in.Description
|
||||
}
|
||||
if in.URL != nil {
|
||||
hook.URL = *in.URL
|
||||
}
|
||||
if in.Secret != nil {
|
||||
encryptedSecret, err := c.encrypter.Encrypt(*in.Secret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encrypt webhook secret: %w", err)
|
||||
}
|
||||
hook.Secret = string(encryptedSecret)
|
||||
}
|
||||
if in.Enabled != nil {
|
||||
hook.Enabled = *in.Enabled
|
||||
}
|
||||
if in.Insecure != nil {
|
||||
hook.Insecure = *in.Insecure
|
||||
}
|
||||
if in.Triggers != nil {
|
||||
hook.Triggers = DeduplicateTriggers(in.Triggers)
|
||||
}
|
||||
|
||||
if err = c.webhookStore.Update(ctx, hook); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
func sanitizeUpdateInput(in *UpdateInput, allowLoopback bool, allowPrivateNetwork bool) error {
|
||||
func (s *Service) sanitizeUpdateInput(in *types.WebhookUpdateInput) error {
|
||||
// TODO [CODE-1363]: remove after identifier migration.
|
||||
if in.Identifier == nil {
|
||||
in.Identifier = in.UID
|
||||
|
@ -126,12 +46,12 @@ func sanitizeUpdateInput(in *UpdateInput, allowLoopback bool, allowPrivateNetwor
|
|||
}
|
||||
if in.URL != nil {
|
||||
// internal is set to false as internal webhooks cannot be updated
|
||||
if err := CheckURL(*in.URL, allowLoopback, allowPrivateNetwork, false); err != nil {
|
||||
if err := CheckURL(*in.URL, s.config.AllowLoopback, s.config.AllowPrivateNetwork, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if in.Secret != nil {
|
||||
if err := checkSecret(*in.Secret); err != nil {
|
||||
if err := CheckSecret(*in.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -143,3 +63,61 @@ func sanitizeUpdateInput(in *UpdateInput, allowLoopback bool, allowPrivateNetwor
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(
|
||||
ctx context.Context,
|
||||
parentID int64,
|
||||
parentType enum.WebhookParent,
|
||||
webhookIdentifier string,
|
||||
allowModifyingInternal bool,
|
||||
in *types.WebhookUpdateInput,
|
||||
) (*types.Webhook, error) {
|
||||
hook, err := s.GetWebhookVerifyOwnership(ctx, parentID, parentType, webhookIdentifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to verify webhook ownership: %w", err)
|
||||
}
|
||||
|
||||
if err := s.sanitizeUpdateInput(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !allowModifyingInternal && hook.Internal {
|
||||
return nil, ErrInternalWebhookOperationNotAllowed
|
||||
}
|
||||
|
||||
// update webhook struct (only for values that are provided)
|
||||
if in.Identifier != nil {
|
||||
hook.Identifier = *in.Identifier
|
||||
}
|
||||
if in.DisplayName != nil {
|
||||
hook.DisplayName = *in.DisplayName
|
||||
}
|
||||
if in.Description != nil {
|
||||
hook.Description = *in.Description
|
||||
}
|
||||
if in.URL != nil {
|
||||
hook.URL = *in.URL
|
||||
}
|
||||
if in.Secret != nil {
|
||||
encryptedSecret, err := s.encrypter.Encrypt(*in.Secret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encrypt webhook secret: %w", err)
|
||||
}
|
||||
hook.Secret = string(encryptedSecret)
|
||||
}
|
||||
if in.Enabled != nil {
|
||||
hook.Enabled = *in.Enabled
|
||||
}
|
||||
if in.Insecure != nil {
|
||||
hook.Insecure = *in.Insecure
|
||||
}
|
||||
if in.Triggers != nil {
|
||||
hook.Triggers = DeduplicateTriggers(in.Triggers)
|
||||
}
|
||||
|
||||
if err := s.webhookStore.Update(ctx, hook); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/harness/gitness/encrypt"
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
@ -33,12 +34,15 @@ var WireSet = wire.NewSet(
|
|||
ProvideService,
|
||||
)
|
||||
|
||||
func ProvideService(ctx context.Context,
|
||||
func ProvideService(
|
||||
ctx context.Context,
|
||||
config Config,
|
||||
tx dbtx.Transactor,
|
||||
gitReaderFactory *events.ReaderFactory[*gitevents.Reader],
|
||||
prReaderFactory *events.ReaderFactory[*pullreqevents.Reader],
|
||||
webhookStore store.WebhookStore,
|
||||
webhookExecutionStore store.WebhookExecutionStore,
|
||||
spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore,
|
||||
pullreqStore store.PullReqStore,
|
||||
activityStore store.PullReqActivityStore,
|
||||
|
@ -47,7 +51,7 @@ func ProvideService(ctx context.Context,
|
|||
git git.Interface,
|
||||
encrypter encrypt.Encrypter,
|
||||
) (*Service, error) {
|
||||
return NewService(ctx, config, gitReaderFactory, prReaderFactory,
|
||||
webhookStore, webhookExecutionStore, repoStore, pullreqStore, activityStore,
|
||||
return NewService(ctx, config, tx, gitReaderFactory, prReaderFactory,
|
||||
webhookStore, webhookExecutionStore, spaceStore, repoStore, pullreqStore, activityStore,
|
||||
urlProvider, principalStore, git, encrypter)
|
||||
}
|
||||
|
|
|
@ -579,13 +579,15 @@ type (
|
|||
|
||||
// Count counts the webhooks for a given parent type and id.
|
||||
Count(
|
||||
ctx context.Context, parentType enum.WebhookParent, parentID int64,
|
||||
ctx context.Context,
|
||||
parents []types.WebhookParentInfo,
|
||||
opts *types.WebhookFilter,
|
||||
) (int64, error)
|
||||
|
||||
// List lists the webhooks for a given parent type and id.
|
||||
List(
|
||||
ctx context.Context, parentType enum.WebhookParent, parentID int64,
|
||||
ctx context.Context,
|
||||
parents []types.WebhookParentInfo,
|
||||
opts *types.WebhookFilter,
|
||||
) ([]*types.Webhook, error)
|
||||
}
|
||||
|
@ -607,6 +609,8 @@ type (
|
|||
opts *types.WebhookExecutionFilter,
|
||||
) ([]*types.WebhookExecution, error)
|
||||
|
||||
CountForWebhook(ctx context.Context, webhookID int64) (int64, error)
|
||||
|
||||
// ListForTrigger lists the webhook executions for a given trigger id.
|
||||
ListForTrigger(ctx context.Context, triggerID string) ([]*types.WebhookExecution, error)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/guregu/null"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -342,24 +343,21 @@ func (s *WebhookStore) DeleteByIdentifier(
|
|||
}
|
||||
|
||||
// Count counts the webhooks for a given parent type and id.
|
||||
func (s *WebhookStore) Count(ctx context.Context, parentType enum.WebhookParent, parentID int64,
|
||||
opts *types.WebhookFilter) (int64, error) {
|
||||
func (s *WebhookStore) Count(
|
||||
ctx context.Context,
|
||||
parents []types.WebhookParentInfo,
|
||||
opts *types.WebhookFilter,
|
||||
) (int64, error) {
|
||||
stmt := database.Builder.
|
||||
Select("count(*)").
|
||||
From("webhooks")
|
||||
|
||||
switch parentType {
|
||||
case enum.WebhookParentRepo:
|
||||
stmt = stmt.Where("webhook_repo_id = ?", parentID)
|
||||
case enum.WebhookParentSpace:
|
||||
stmt = stmt.Where("webhook_space_id = ?", parentID)
|
||||
default:
|
||||
return 0, fmt.Errorf("webhook parent type '%s' is not supported", parentType)
|
||||
err := selectParents(parents, &stmt)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to select parents: %w", err)
|
||||
}
|
||||
|
||||
if opts.Query != "" {
|
||||
stmt = stmt.Where("LOWER(webhook_uid) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(opts.Query)))
|
||||
}
|
||||
stmt = applyWebhookFilter(opts, stmt)
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
|
@ -377,29 +375,21 @@ func (s *WebhookStore) Count(ctx context.Context, parentType enum.WebhookParent,
|
|||
return count, nil
|
||||
}
|
||||
|
||||
// List lists the webhooks for a given parent type and id.
|
||||
func (s *WebhookStore) List(ctx context.Context, parentType enum.WebhookParent, parentID int64,
|
||||
opts *types.WebhookFilter) ([]*types.Webhook, error) {
|
||||
func (s *WebhookStore) List(
|
||||
ctx context.Context,
|
||||
parents []types.WebhookParentInfo,
|
||||
opts *types.WebhookFilter,
|
||||
) ([]*types.Webhook, error) {
|
||||
stmt := database.Builder.
|
||||
Select(webhookColumns).
|
||||
From("webhooks")
|
||||
|
||||
switch parentType {
|
||||
case enum.WebhookParentRepo:
|
||||
stmt = stmt.Where("webhook_repo_id = ?", parentID)
|
||||
case enum.WebhookParentSpace:
|
||||
stmt = stmt.Where("webhook_space_id = ?", parentID)
|
||||
default:
|
||||
return nil, fmt.Errorf("webhook parent type '%s' is not supported", parentType)
|
||||
err := selectParents(parents, &stmt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to select parents: %w", err)
|
||||
}
|
||||
|
||||
if opts.Query != "" {
|
||||
stmt = stmt.Where("LOWER(webhook_uid) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(opts.Query)))
|
||||
}
|
||||
|
||||
if opts.SkipInternal {
|
||||
stmt = stmt.Where("webhook_internal != ?", true)
|
||||
}
|
||||
stmt = applyWebhookFilter(opts, stmt)
|
||||
|
||||
stmt = stmt.Limit(database.Limit(opts.Size))
|
||||
stmt = stmt.Offset(database.Offset(opts.Page, opts.Size))
|
||||
|
@ -507,7 +497,7 @@ func mapToInternalWebhook(hook *types.Webhook) (*webhook, error) {
|
|||
case enum.WebhookParentSpace:
|
||||
res.SpaceID = null.IntFrom(hook.ParentID)
|
||||
default:
|
||||
return nil, fmt.Errorf("webhook parent type '%s' is not supported", hook.ParentType)
|
||||
return nil, fmt.Errorf("webhook parent type %q is not supported", hook.ParentType)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
@ -553,3 +543,43 @@ func triggersToString(triggers []enum.WebhookTrigger) string {
|
|||
|
||||
return strings.Join(rawTriggers, triggersSeparator)
|
||||
}
|
||||
|
||||
func applyWebhookFilter(
|
||||
opts *types.WebhookFilter,
|
||||
stmt squirrel.SelectBuilder,
|
||||
) squirrel.SelectBuilder {
|
||||
if opts.Query != "" {
|
||||
stmt = stmt.Where("LOWER(webhook_uid) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(opts.Query)))
|
||||
}
|
||||
|
||||
if opts.SkipInternal {
|
||||
stmt = stmt.Where("webhook_internal != ?", true)
|
||||
}
|
||||
|
||||
return stmt
|
||||
}
|
||||
|
||||
func selectParents(
|
||||
parents []types.WebhookParentInfo,
|
||||
stmt *squirrel.SelectBuilder,
|
||||
) error {
|
||||
var parentSelector squirrel.Or
|
||||
for _, parent := range parents {
|
||||
switch parent.Type {
|
||||
case enum.WebhookParentRepo:
|
||||
parentSelector = append(parentSelector, squirrel.Eq{
|
||||
"webhook_repo_id": parent.ID,
|
||||
})
|
||||
case enum.WebhookParentSpace:
|
||||
parentSelector = append(parentSelector, squirrel.Eq{
|
||||
"webhook_space_id": parent.ID,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("webhook parent type '%s' is not supported", parent.Type)
|
||||
}
|
||||
}
|
||||
|
||||
*stmt = stmt.Where(parentSelector)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -213,6 +213,31 @@ func (s *WebhookExecutionStore) ListForWebhook(ctx context.Context, webhookID in
|
|||
return mapToWebhookExecutions(dst), nil
|
||||
}
|
||||
|
||||
// CountForWebhook counts the total number of webhook executions for a given webhook ID.
|
||||
func (s *WebhookExecutionStore) CountForWebhook(
|
||||
ctx context.Context,
|
||||
webhookID int64,
|
||||
) (int64, error) {
|
||||
stmt := database.Builder.
|
||||
Select("COUNT(*)").
|
||||
From("webhook_executions").
|
||||
Where("webhook_execution_webhook_id = ?", webhookID)
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||
}
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
var count int64
|
||||
if err = db.GetContext(ctx, &count, sql, args...); err != nil {
|
||||
return 0, database.ProcessSQLErrorf(ctx, err, "Count query failed")
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// ListForTrigger lists the webhook executions for a given trigger id.
|
||||
func (s *WebhookExecutionStore) ListForTrigger(ctx context.Context,
|
||||
triggerID string) ([]*types.WebhookExecution, error) {
|
||||
|
|
|
@ -164,6 +164,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
|||
reposettings.WireSet,
|
||||
pullreq.WireSet,
|
||||
controllerwebhook.WireSet,
|
||||
controllerwebhook.ProvidePreprocessor,
|
||||
svclabel.WireSet,
|
||||
serviceaccount.WireSet,
|
||||
user.WireSet,
|
||||
|
|
|
@ -365,11 +365,12 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||
webhookConfig := server.ProvideWebhookConfig(config)
|
||||
webhookStore := database.ProvideWebhookStore(db)
|
||||
webhookExecutionStore := database.ProvideWebhookExecutionStore(db)
|
||||
webhookService, err := webhook.ProvideService(ctx, webhookConfig, readerFactory, eventsReaderFactory, webhookStore, webhookExecutionStore, repoStore, pullReqStore, pullReqActivityStore, provider, principalStore, gitInterface, encrypter)
|
||||
webhookService, err := webhook.ProvideService(ctx, webhookConfig, transactor, readerFactory, eventsReaderFactory, webhookStore, webhookExecutionStore, spaceStore, repoStore, pullReqStore, pullReqActivityStore, provider, principalStore, gitInterface, encrypter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter)
|
||||
preprocessor := webhook2.ProvidePreprocessor()
|
||||
webhookController := webhook2.ProvideController(authorizer, spaceStore, repoStore, webhookService, encrypter, preprocessor)
|
||||
reporter5, err := events7.ProvideReporter(eventsSystem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -28,6 +28,7 @@ const (
|
|||
StatusNotFound Status = "not_found"
|
||||
StatusNotImplemented Status = "not_implemented"
|
||||
StatusUnauthorized Status = "unauthorized"
|
||||
StatusForbidden Status = "forbidden"
|
||||
StatusFailed Status = "failed"
|
||||
StatusPreconditionFailed Status = "precondition_failed"
|
||||
StatusAborted Status = "aborted"
|
||||
|
@ -156,6 +157,16 @@ func PreconditionFailed(format string, args ...interface{}) *Error {
|
|||
return Format(StatusPreconditionFailed, format, args...)
|
||||
}
|
||||
|
||||
// Unauthorized is a helper function to return an unauthorized error.
|
||||
func Unauthorized(format string, args ...interface{}) *Error {
|
||||
return Format(StatusUnauthorized, format, args...)
|
||||
}
|
||||
|
||||
// Forbidden is a helper function to return a forbidden error.
|
||||
func Forbidden(format string, args ...interface{}) *Error {
|
||||
return Format(StatusForbidden, format, args...)
|
||||
}
|
||||
|
||||
// Failed is a helper function to return failed error status.
|
||||
func Failed(format string, args ...interface{}) *Error {
|
||||
return Format(StatusFailed, format, args...)
|
||||
|
|
|
@ -66,6 +66,34 @@ func (w *Webhook) MarshalJSON() ([]byte, error) {
|
|||
})
|
||||
}
|
||||
|
||||
type WebhookCreateInput struct {
|
||||
// TODO [CODE-1363]: remove after identifier migration.
|
||||
UID string `json:"uid" deprecated:"true"`
|
||||
Identifier string `json:"identifier"`
|
||||
// TODO [CODE-1364]: Remove once UID/Identifier migration is completed.
|
||||
DisplayName string `json:"display_name"`
|
||||
Description string `json:"description"`
|
||||
URL string `json:"url"`
|
||||
Secret string `json:"secret"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Insecure bool `json:"insecure"`
|
||||
Triggers []enum.WebhookTrigger `json:"triggers"`
|
||||
}
|
||||
|
||||
type WebhookUpdateInput struct {
|
||||
// TODO [CODE-1363]: remove after identifier migration.
|
||||
UID *string `json:"uid" deprecated:"true"`
|
||||
Identifier *string `json:"identifier"`
|
||||
// TODO [CODE-1364]: Remove once UID/Identifier migration is completed.
|
||||
DisplayName *string `json:"display_name"`
|
||||
Description *string `json:"description"`
|
||||
URL *string `json:"url"`
|
||||
Secret *string `json:"secret"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Insecure *bool `json:"insecure"`
|
||||
Triggers []enum.WebhookTrigger `json:"triggers"`
|
||||
}
|
||||
|
||||
// WebhookExecution represents a single execution of a webhook.
|
||||
type WebhookExecution struct {
|
||||
ID int64 `json:"id"`
|
||||
|
@ -112,3 +140,8 @@ type WebhookExecutionFilter struct {
|
|||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type WebhookParentInfo struct {
|
||||
Type enum.WebhookParent
|
||||
ID int64
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue