mirror of
https://github.com/harness/drone.git
synced 2025-05-06 16:42:31 +08:00
feat: [AH-396]: webhook support (#2778)
* feat: [AH-396]: resolve PR comments * feat: [AH-396]: adjust sql * feat: [AH-396]: implement registry webhooks
This commit is contained in:
parent
49e52935c4
commit
a655c2f8e9
@ -0,0 +1,4 @@
|
|||||||
|
DROP INDEX registry_webhooks_registry_id_identifier;
|
||||||
|
DROP INDEX registry_webhooks_space_id_identifier;
|
||||||
|
DROP TABLE registry_webhook_executions;
|
||||||
|
DROP TABLE registry_webhooks;
|
@ -0,0 +1,61 @@
|
|||||||
|
CREATE TABLE registry_webhooks
|
||||||
|
(
|
||||||
|
registry_webhook_id SERIAL PRIMARY KEY,
|
||||||
|
registry_webhook_version INTEGER NOT NULL DEFAULT 0,
|
||||||
|
registry_webhook_created_by INTEGER NOT NULL,
|
||||||
|
registry_webhook_created BIGINT NOT NULL,
|
||||||
|
registry_webhook_updated BIGINT NOT NULL,
|
||||||
|
registry_webhook_space_id INTEGER,
|
||||||
|
registry_webhook_registry_id INTEGER,
|
||||||
|
registry_webhook_name TEXT NOT NULL,
|
||||||
|
registry_webhook_description TEXT NOT NULL,
|
||||||
|
registry_webhook_url TEXT NOT NULL,
|
||||||
|
registry_webhook_secret_identifier TEXT,
|
||||||
|
registry_webhook_secret_space_id INTEGER,
|
||||||
|
registry_webhook_enabled BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_insecure BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_triggers TEXT NOT NULL,
|
||||||
|
registry_webhook_latest_execution_result TEXT,
|
||||||
|
registry_webhook_scope INTEGER DEFAULT 0,
|
||||||
|
registry_webhook_internal BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_identifier TEXT NOT NULL,
|
||||||
|
registry_webhook_extra_headers TEXT,
|
||||||
|
CONSTRAINT fk_registry_webhook_created_by FOREIGN KEY (registry_webhook_created_by)
|
||||||
|
REFERENCES principals (principal_id) MATCH SIMPLE
|
||||||
|
ON UPDATE NO ACTION
|
||||||
|
ON DELETE NO ACTION,
|
||||||
|
CONSTRAINT fk_registry_webhook_registry_id FOREIGN KEY (registry_webhook_registry_id)
|
||||||
|
REFERENCES registries (registry_id) MATCH SIMPLE
|
||||||
|
ON UPDATE NO ACTION
|
||||||
|
ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX registry_webhooks_registry_id_identifier
|
||||||
|
ON registry_webhooks(registry_webhook_registry_id, registry_webhook_identifier)
|
||||||
|
WHERE registry_webhook_space_id IS NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX registry_webhooks_space_id_identifier
|
||||||
|
ON registry_webhooks(registry_webhook_space_id, registry_webhook_identifier)
|
||||||
|
WHERE registry_webhook_registry_id IS NULL;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE registry_webhook_executions
|
||||||
|
(
|
||||||
|
registry_webhook_execution_id SERIAL PRIMARY KEY,
|
||||||
|
registry_webhook_execution_retrigger_of INTEGER,
|
||||||
|
registry_webhook_execution_retriggerable BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_execution_webhook_id INTEGER NOT NULL,
|
||||||
|
registry_webhook_execution_trigger_type TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_trigger_id TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_result TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_created BIGINT NOT NULL,
|
||||||
|
registry_webhook_execution_duration BIGINT NOT NULL,
|
||||||
|
registry_webhook_execution_error TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_request_url TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_request_headers TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_request_body TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_response_status_code INTEGER NOT NULL,
|
||||||
|
registry_webhook_execution_response_status TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_response_headers TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_response_body TEXT NOT NULL
|
||||||
|
);
|
@ -0,0 +1,4 @@
|
|||||||
|
DROP INDEX registry_webhooks_registry_id_identifier;
|
||||||
|
DROP INDEX registry_webhooks_space_id_identifier;
|
||||||
|
DROP TABLE registry_webhook_executions;
|
||||||
|
DROP TABLE registry_webhooks;
|
@ -0,0 +1,60 @@
|
|||||||
|
CREATE TABLE registry_webhooks
|
||||||
|
(
|
||||||
|
registry_webhook_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
registry_webhook_version INTEGER NOT NULL DEFAULT 0,
|
||||||
|
registry_webhook_created_by INTEGER NOT NULL,
|
||||||
|
registry_webhook_created BIGINT NOT NULL,
|
||||||
|
registry_webhook_updated BIGINT NOT NULL,
|
||||||
|
registry_webhook_space_id INTEGER,
|
||||||
|
registry_webhook_registry_id INTEGER,
|
||||||
|
registry_webhook_name TEXT NOT NULL,
|
||||||
|
registry_webhook_description TEXT NOT NULL,
|
||||||
|
registry_webhook_url TEXT NOT NULL,
|
||||||
|
registry_webhook_secret_identifier TEXT,
|
||||||
|
registry_webhook_secret_space_id INTEGER,
|
||||||
|
registry_webhook_enabled BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_insecure BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_triggers TEXT NOT NULL,
|
||||||
|
registry_webhook_latest_execution_result TEXT,
|
||||||
|
registry_webhook_scope INTEGER DEFAULT 0,
|
||||||
|
registry_webhook_internal BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_identifier TEXT NOT NULL,
|
||||||
|
registry_webhook_extra_headers TEXT,
|
||||||
|
CONSTRAINT fk_registry_webhook_created_by FOREIGN KEY (registry_webhook_created_by)
|
||||||
|
REFERENCES principals (principal_id) MATCH SIMPLE
|
||||||
|
ON UPDATE NO ACTION
|
||||||
|
ON DELETE NO ACTION,
|
||||||
|
CONSTRAINT fk_registry_webhook_registry_id FOREIGN KEY (registry_webhook_registry_id)
|
||||||
|
REFERENCES registries (registry_id) MATCH SIMPLE
|
||||||
|
ON UPDATE NO ACTION
|
||||||
|
ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX registry_webhooks_registry_id_identifier
|
||||||
|
ON registry_webhooks(registry_webhook_registry_id, registry_webhook_identifier)
|
||||||
|
WHERE registry_webhook_space_id IS NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX registry_webhooks_space_id_identifier
|
||||||
|
ON registry_webhooks(registry_webhook_space_id, registry_webhook_identifier)
|
||||||
|
WHERE registry_webhook_registry_id IS NULL;
|
||||||
|
|
||||||
|
CREATE TABLE registry_webhook_executions
|
||||||
|
(
|
||||||
|
registry_webhook_execution_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
registry_webhook_execution_retrigger_of INTEGER,
|
||||||
|
registry_webhook_execution_retriggerable BOOLEAN NOT NULL,
|
||||||
|
registry_webhook_execution_webhook_id INTEGER NOT NULL,
|
||||||
|
registry_webhook_execution_trigger_type TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_trigger_id TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_result TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_created BIGINT NOT NULL,
|
||||||
|
registry_webhook_execution_duration BIGINT NOT NULL,
|
||||||
|
registry_webhook_execution_error TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_request_url TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_request_headers TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_request_body TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_response_status_code INTEGER NOT NULL,
|
||||||
|
registry_webhook_execution_response_status TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_response_headers TEXT NOT NULL,
|
||||||
|
registry_webhook_execution_response_body TEXT NOT NULL
|
||||||
|
);
|
@ -481,7 +481,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
handler := api2.NewHandlerProvider(dockerController, spaceStore, tokenStore, controller, authenticator, provider, authorizer, config)
|
handler := api2.NewHandlerProvider(dockerController, spaceStore, tokenStore, controller, authenticator, provider, authorizer, config)
|
||||||
registryOCIHandler := router.OCIHandlerProvider(handler)
|
registryOCIHandler := router.OCIHandlerProvider(handler)
|
||||||
cleanupPolicyRepository := database2.ProvideCleanupPolicyDao(db, transactor)
|
cleanupPolicyRepository := database2.ProvideCleanupPolicyDao(db, transactor)
|
||||||
apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceStore, transactor, authenticator, provider, authorizer, auditService, spacePathStore, artifactRepository)
|
webhooksRepository := database2.ProvideWebhookDao(db)
|
||||||
|
apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceStore, transactor, authenticator, provider, authorizer, auditService, spacePathStore, artifactRepository, webhooksRepository)
|
||||||
nodesRepository := database2.ProvideNodeDao(db)
|
nodesRepository := database2.ProvideNodeDao(db)
|
||||||
mavenDBStore := maven.DBStoreProvider(registryRepository, imageRepository, artifactRepository, spaceStore, bandwidthStatRepository, downloadStatRepository, nodesRepository, upstreamProxyConfigRepository)
|
mavenDBStore := maven.DBStoreProvider(registryRepository, imageRepository, artifactRepository, spaceStore, bandwidthStatRepository, downloadStatRepository, nodesRepository, upstreamProxyConfigRepository)
|
||||||
filemanagerApp := filemanager.NewApp(ctx, config, storageService)
|
filemanagerApp := filemanager.NewApp(ctx, config, storageService)
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/harness/gitness/registry/app/pkg/commons"
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
"github.com/harness/gitness/registry/app/storage"
|
"github.com/harness/gitness/registry/app/storage"
|
||||||
"github.com/harness/gitness/registry/types"
|
"github.com/harness/gitness/registry/types"
|
||||||
|
registryenum "github.com/harness/gitness/registry/types/enum"
|
||||||
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@ -47,6 +48,8 @@ type RegistryRequestBaseInfo struct {
|
|||||||
|
|
||||||
ParentRef string
|
ParentRef string
|
||||||
parentID int64
|
parentID int64
|
||||||
|
|
||||||
|
RegistryType api.RegistryType
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegistryRequestInfo struct {
|
type RegistryRequestInfo struct {
|
||||||
@ -129,6 +132,7 @@ func (c *APIController) GetRegistryRequestBaseInfo(
|
|||||||
baseInfo.RegistryRef = regRef
|
baseInfo.RegistryRef = regRef
|
||||||
baseInfo.RegistryIdentifier = regIdentifier
|
baseInfo.RegistryIdentifier = regIdentifier
|
||||||
baseInfo.RegistryID = reg.ID
|
baseInfo.RegistryID = reg.ID
|
||||||
|
baseInfo.RegistryType = reg.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
return baseInfo, nil
|
return baseInfo, nil
|
||||||
@ -404,3 +408,105 @@ func CreateUpstreamProxyResponseJSONResponse(upstreamproxy *types.UpstreamProxy)
|
|||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *APIController) mapToWebhookResponseEntity(
|
||||||
|
ctx context.Context,
|
||||||
|
createdWebhook types.Webhook,
|
||||||
|
) (*api.Webhook, error) {
|
||||||
|
createdAt := GetTimeInMs(createdWebhook.CreatedAt)
|
||||||
|
modifiedAt := GetTimeInMs(createdWebhook.UpdatedAt)
|
||||||
|
webhookResponseEntity := &api.Webhook{
|
||||||
|
Identifier: createdWebhook.Identifier,
|
||||||
|
Name: createdWebhook.Name,
|
||||||
|
Description: &createdWebhook.Description,
|
||||||
|
Url: createdWebhook.URL,
|
||||||
|
Version: &createdWebhook.Version,
|
||||||
|
Enabled: createdWebhook.Enabled,
|
||||||
|
Internal: &createdWebhook.Internal,
|
||||||
|
Insecure: createdWebhook.Insecure,
|
||||||
|
Triggers: &createdWebhook.Triggers,
|
||||||
|
CreatedBy: &createdWebhook.CreatedBy,
|
||||||
|
CreatedAt: &createdAt,
|
||||||
|
ModifiedAt: &modifiedAt,
|
||||||
|
LatestExecutionResult: createdWebhook.LatestExecutionResult,
|
||||||
|
}
|
||||||
|
if createdWebhook.ExtraHeaders != nil {
|
||||||
|
webhookResponseEntity.ExtraHeaders = &createdWebhook.ExtraHeaders
|
||||||
|
}
|
||||||
|
secretSpacePath := ""
|
||||||
|
if createdWebhook.SecretSpaceID > 0 {
|
||||||
|
primary, err := c.spacePathStore.FindPrimaryBySpaceID(ctx, int64(createdWebhook.SecretSpaceID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get secret space path: %w", err)
|
||||||
|
}
|
||||||
|
secretSpacePath = primary.Value
|
||||||
|
}
|
||||||
|
if createdWebhook.SecretIdentifier != "" {
|
||||||
|
webhookResponseEntity.SecretIdentifier = &createdWebhook.SecretIdentifier
|
||||||
|
}
|
||||||
|
if secretSpacePath != "" {
|
||||||
|
webhookResponseEntity.SecretSpacePath = &secretSpacePath
|
||||||
|
}
|
||||||
|
if createdWebhook.SecretSpaceID > 0 {
|
||||||
|
webhookResponseEntity.SecretSpaceId = &createdWebhook.SecretSpaceID
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhookResponseEntity, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIController) mapToWebhook(
|
||||||
|
ctx context.Context,
|
||||||
|
webhookRequest api.WebhookRequest,
|
||||||
|
regInfo *RegistryRequestBaseInfo,
|
||||||
|
) (*types.Webhook, error) {
|
||||||
|
webhook := &types.Webhook{
|
||||||
|
Name: webhookRequest.Identifier,
|
||||||
|
ParentType: registryenum.WebhookParentRegistry,
|
||||||
|
ParentID: regInfo.RegistryID,
|
||||||
|
Scope: webhookScopeRegistry,
|
||||||
|
Identifier: webhookRequest.Identifier,
|
||||||
|
URL: webhookRequest.Url,
|
||||||
|
Enabled: webhookRequest.Enabled,
|
||||||
|
Insecure: webhookRequest.Insecure,
|
||||||
|
Triggers: deduplicateTriggers(*webhookRequest.Triggers),
|
||||||
|
}
|
||||||
|
if webhookRequest.Description != nil {
|
||||||
|
webhook.Description = *webhookRequest.Description
|
||||||
|
}
|
||||||
|
if webhookRequest.SecretIdentifier != nil {
|
||||||
|
webhook.SecretIdentifier = *webhookRequest.SecretIdentifier
|
||||||
|
}
|
||||||
|
if webhookRequest.ExtraHeaders != nil {
|
||||||
|
webhook.ExtraHeaders = *webhookRequest.ExtraHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
if webhookRequest.SecretSpacePath != nil && len(*webhookRequest.SecretSpacePath) > 0 {
|
||||||
|
secretSpaceID, err := c.getSecretSpaceID(ctx, webhookRequest.SecretSpacePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhook.SecretSpaceID = secretSpaceID
|
||||||
|
} else if webhookRequest.SecretSpaceId != nil {
|
||||||
|
webhook.SecretSpaceID = *webhookRequest.SecretSpaceId
|
||||||
|
}
|
||||||
|
return webhook, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// deduplicateTriggers de-duplicates the triggers provided by the user.
|
||||||
|
func deduplicateTriggers(in []api.Trigger) []api.Trigger {
|
||||||
|
if len(in) == 0 {
|
||||||
|
return []api.Trigger{}
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerSet := make(map[api.Trigger]bool, len(in))
|
||||||
|
out := make([]api.Trigger, 0, len(in))
|
||||||
|
for _, trigger := range in {
|
||||||
|
if triggerSet[trigger] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
triggerSet[trigger] = true
|
||||||
|
out = append(out, trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
@ -40,6 +40,7 @@ type APIController struct {
|
|||||||
AuditService audit.Service
|
AuditService audit.Service
|
||||||
spacePathStore corestore.SpacePathStore
|
spacePathStore corestore.SpacePathStore
|
||||||
ArtifactStore store.ArtifactRepository
|
ArtifactStore store.ArtifactRepository
|
||||||
|
WebhooksRepository store.WebhooksRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIController(
|
func NewAPIController(
|
||||||
@ -57,6 +58,7 @@ func NewAPIController(
|
|||||||
auditService audit.Service,
|
auditService audit.Service,
|
||||||
spacePathStore corestore.SpacePathStore,
|
spacePathStore corestore.SpacePathStore,
|
||||||
artifactStore store.ArtifactRepository,
|
artifactStore store.ArtifactRepository,
|
||||||
|
webhooksRepository store.WebhooksRepository,
|
||||||
) *APIController {
|
) *APIController {
|
||||||
return &APIController{
|
return &APIController{
|
||||||
RegistryRepository: repositoryStore,
|
RegistryRepository: repositoryStore,
|
||||||
@ -73,5 +75,6 @@ func NewAPIController(
|
|||||||
AuditService: auditService,
|
AuditService: auditService,
|
||||||
spacePathStore: spacePathStore,
|
spacePathStore: spacePathStore,
|
||||||
ArtifactStore: artifactStore,
|
ArtifactStore: artifactStore,
|
||||||
|
WebhooksRepository: webhooksRepository,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ func (c *APIController) CreateUpstreamProxyEntity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.SecretSpacePath != nil && len(*res.SecretSpacePath) > 0 {
|
if res.SecretSpacePath != nil && len(*res.SecretSpacePath) > 0 {
|
||||||
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretID(ctx, res.SecretSpacePath)
|
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretSpaceID(ctx, res.SecretSpacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -350,7 +350,7 @@ func (c *APIController) CreateUpstreamProxyEntity(
|
|||||||
return nil, nil, fmt.Errorf("failed to create upstream proxy: access_key_secret_identifier missing")
|
return nil, nil, fmt.Errorf("failed to create upstream proxy: access_key_secret_identifier missing")
|
||||||
default:
|
default:
|
||||||
if res.AccessKeySecretSpacePath != nil && len(*res.AccessKeySecretSpacePath) > 0 {
|
if res.AccessKeySecretSpacePath != nil && len(*res.AccessKeySecretSpacePath) > 0 {
|
||||||
upstreamProxyConfigEntity.UserNameSecretSpaceID, err = c.getSecretID(ctx, res.AccessKeySecretSpacePath)
|
upstreamProxyConfigEntity.UserNameSecretSpaceID, err = c.getSecretSpaceID(ctx, res.AccessKeySecretSpacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ func (c *APIController) CreateUpstreamProxyEntity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.SecretKeySpacePath != nil && len(*res.SecretKeySpacePath) > 0 {
|
if res.SecretKeySpacePath != nil && len(*res.SecretKeySpacePath) > 0 {
|
||||||
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretID(ctx, res.SecretKeySpacePath)
|
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretSpaceID(ctx, res.SecretKeySpacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -373,9 +373,9 @@ func (c *APIController) CreateUpstreamProxyEntity(
|
|||||||
return repoEntity, upstreamProxyConfigEntity, nil
|
return repoEntity, upstreamProxyConfigEntity, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *APIController) getSecretID(ctx context.Context, secretSpacePath *string) (int, error) {
|
func (c *APIController) getSecretSpaceID(ctx context.Context, secretSpacePath *string) (int, error) {
|
||||||
if secretSpacePath == nil {
|
if secretSpacePath == nil {
|
||||||
return -1, fmt.Errorf("failed to create upstream proxy: secret space missing")
|
return -1, fmt.Errorf("secret space path is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := c.spacePathStore.FindByPath(ctx, *secretSpacePath)
|
path, err := c.spacePathStore.FindByPath(ctx, *secretSpacePath)
|
||||||
|
124
registry/app/api/controller/metadata/create_webhook.go
Normal file
124
registry/app/api/controller/metadata/create_webhook.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
apiauth "github.com/harness/gitness/app/api/auth"
|
||||||
|
"github.com/harness/gitness/app/api/request"
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const webhookScopeRegistry = int64(0)
|
||||||
|
|
||||||
|
func (c *APIController) CreateWebhook(
|
||||||
|
ctx context.Context,
|
||||||
|
r api.CreateWebhookRequestObject,
|
||||||
|
) (api.CreateWebhookResponseObject, error) {
|
||||||
|
webhookRequest := api.WebhookRequest(*r.Body)
|
||||||
|
regInfo, err := c.GetRegistryRequestBaseInfo(ctx, "", string(r.RegistryRef))
|
||||||
|
if err != nil {
|
||||||
|
return createWebhookBadRequestErrorResponse(err)
|
||||||
|
}
|
||||||
|
if regInfo.RegistryType != api.RegistryTypeVIRTUAL {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to store webhook: %s with error: %v", webhookRequest.Identifier, err)
|
||||||
|
return createWebhookBadRequestErrorResponse(
|
||||||
|
fmt.Errorf("not allowed to create webhook for %s registry", regInfo.RegistryType),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
space, err := c.SpaceStore.FindByRef(ctx, regInfo.ParentRef)
|
||||||
|
if err != nil {
|
||||||
|
return createWebhookBadRequestErrorResponse(err)
|
||||||
|
}
|
||||||
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
|
permissionChecks := GetPermissionChecks(space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit)
|
||||||
|
if err = apiauth.CheckRegistry(
|
||||||
|
ctx,
|
||||||
|
c.Authorizer,
|
||||||
|
session,
|
||||||
|
permissionChecks...,
|
||||||
|
); err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("permission check failed while creating webhook for registry: %s, error: %v",
|
||||||
|
regInfo.RegistryIdentifier, err)
|
||||||
|
return api.CreateWebhook403JSONResponse{
|
||||||
|
UnauthorizedJSONResponse: api.UnauthorizedJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusForbidden, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook, err := c.mapToWebhook(ctx, webhookRequest, regInfo)
|
||||||
|
webhook.Internal = false
|
||||||
|
webhook.CreatedBy = session.Principal.ID
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to store webhook: %s with error: %v", webhookRequest.Identifier, err)
|
||||||
|
return createWebhookBadRequestErrorResponse(fmt.Errorf("failed to store webhook %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.WebhooksRepository.Create(ctx, webhook)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to store webhook: %s with error: %v", webhookRequest.Identifier, err)
|
||||||
|
if isDuplicateKeyError(err) {
|
||||||
|
return createWebhookBadRequestErrorResponse(fmt.Errorf(
|
||||||
|
"failed to store webhook, Webhook with identifier %s already exists", webhookRequest.Identifier,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return createWebhookBadRequestErrorResponse(fmt.Errorf("failed to store webhook: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
createdWebhook, err := c.WebhooksRepository.GetByRegistryAndIdentifier(
|
||||||
|
ctx, regInfo.RegistryID, webhookRequest.Identifier,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to stored webhook: %s with error: %v",
|
||||||
|
webhookRequest.Identifier, err)
|
||||||
|
return createWebhookInternalErrorResponse(fmt.Errorf("failed to stored webhook: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookResponseEntity, err := c.mapToWebhookResponseEntity(ctx, *createdWebhook)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to stored webhook: %s with error: %v",
|
||||||
|
webhookRequest.Identifier, err)
|
||||||
|
return createWebhookInternalErrorResponse(fmt.Errorf("failed to stored webhook: %w", err))
|
||||||
|
}
|
||||||
|
return api.CreateWebhook201JSONResponse{
|
||||||
|
WebhookResponseJSONResponse: api.WebhookResponseJSONResponse{
|
||||||
|
Data: *webhookResponseEntity,
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createWebhookBadRequestErrorResponse(err error) (api.CreateWebhookResponseObject, error) {
|
||||||
|
return api.CreateWebhook400JSONResponse{
|
||||||
|
BadRequestJSONResponse: api.BadRequestJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusBadRequest, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createWebhookInternalErrorResponse(err error) (api.CreateWebhookResponseObject, error) {
|
||||||
|
return api.CreateWebhook500JSONResponse{
|
||||||
|
InternalServerErrorJSONResponse: api.InternalServerErrorJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusInternalServerError, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
72
registry/app/api/controller/metadata/delete_webhook.go
Normal file
72
registry/app/api/controller/metadata/delete_webhook.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
apiauth "github.com/harness/gitness/app/api/auth"
|
||||||
|
"github.com/harness/gitness/app/api/request"
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) DeleteWebhook(
|
||||||
|
ctx context.Context,
|
||||||
|
r api.DeleteWebhookRequestObject,
|
||||||
|
) (api.DeleteWebhookResponseObject, error) {
|
||||||
|
regInfo, err := c.GetRegistryRequestBaseInfo(ctx, "", string(r.RegistryRef))
|
||||||
|
if err != nil {
|
||||||
|
return deleteWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
space, err := c.SpaceStore.FindByRef(ctx, regInfo.ParentRef)
|
||||||
|
if err != nil {
|
||||||
|
return deleteWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
|
permissionChecks := GetPermissionChecks(space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit)
|
||||||
|
if err = apiauth.CheckRegistry(
|
||||||
|
ctx,
|
||||||
|
c.Authorizer,
|
||||||
|
session,
|
||||||
|
permissionChecks...,
|
||||||
|
); err != nil {
|
||||||
|
return api.DeleteWebhook403JSONResponse{
|
||||||
|
UnauthorizedJSONResponse: api.UnauthorizedJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusForbidden, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookIdentifier := string(r.WebhookIdentifier)
|
||||||
|
err = c.WebhooksRepository.DeleteByRegistryAndIdentifier(ctx, regInfo.RegistryID, webhookIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
return deleteWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
return api.DeleteWebhook200JSONResponse{
|
||||||
|
SuccessJSONResponse: api.SuccessJSONResponse(*GetSuccessResponse()),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteWebhookInternalErrorResponse(err error) (api.DeleteWebhookResponseObject, error) {
|
||||||
|
return api.DeleteWebhook500JSONResponse{
|
||||||
|
InternalServerErrorJSONResponse: api.InternalServerErrorJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusInternalServerError, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
89
registry/app/api/controller/metadata/get_webhook_details.go
Normal file
89
registry/app/api/controller/metadata/get_webhook_details.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
apiauth "github.com/harness/gitness/app/api/auth"
|
||||||
|
"github.com/harness/gitness/app/api/request"
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) GetWebhook(
|
||||||
|
ctx context.Context,
|
||||||
|
r api.GetWebhookRequestObject,
|
||||||
|
) (api.GetWebhookResponseObject, error) {
|
||||||
|
regInfo, err := c.GetRegistryRequestBaseInfo(ctx, "", string(r.RegistryRef))
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to get registry details: %v", err)
|
||||||
|
return getWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
space, err := c.SpaceStore.FindByRef(ctx, regInfo.ParentRef)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to find space: %v", err)
|
||||||
|
return getWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
|
permissionChecks := GetPermissionChecks(space, regInfo.RegistryIdentifier, enum.PermissionRegistryView)
|
||||||
|
if err = apiauth.CheckRegistry(
|
||||||
|
ctx,
|
||||||
|
c.Authorizer,
|
||||||
|
session,
|
||||||
|
permissionChecks...,
|
||||||
|
); err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("permission check failed while getting webhook for registry: %s, error: %v",
|
||||||
|
regInfo.RegistryIdentifier, err)
|
||||||
|
return api.GetWebhook403JSONResponse{
|
||||||
|
UnauthorizedJSONResponse: api.UnauthorizedJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusForbidden, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookIdentifier := string(r.WebhookIdentifier)
|
||||||
|
webhook, err := c.WebhooksRepository.GetByRegistryAndIdentifier(ctx, regInfo.RegistryID, webhookIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to get webhook: %s with error: %v", webhookIdentifier, err)
|
||||||
|
return getWebhookInternalErrorResponse(fmt.Errorf("failed to get webhook"))
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookResponseEntity, err := c.mapToWebhookResponseEntity(ctx, *webhook)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to get webhook: %s with error: %v", webhookIdentifier, err)
|
||||||
|
return getWebhookInternalErrorResponse(fmt.Errorf("failed to get webhook"))
|
||||||
|
}
|
||||||
|
return api.GetWebhook200JSONResponse{
|
||||||
|
WebhookResponseJSONResponse: api.WebhookResponseJSONResponse{
|
||||||
|
Data: *webhookResponseEntity,
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getWebhookInternalErrorResponse(err error) (api.GetWebhookResponseObject, error) {
|
||||||
|
return api.GetWebhook500JSONResponse{
|
||||||
|
InternalServerErrorJSONResponse: api.InternalServerErrorJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusInternalServerError, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) GetWebhookExecution(
|
||||||
|
_ context.Context,
|
||||||
|
_ api.GetWebhookExecutionRequestObject,
|
||||||
|
) (api.GetWebhookExecutionResponseObject, error) {
|
||||||
|
return api.GetWebhookExecution200JSONResponse{
|
||||||
|
WebhookExecutionResponseJSONResponse: api.WebhookExecutionResponseJSONResponse{
|
||||||
|
Data: api.WebhookExecution{},
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) ListWebhookExecutions(
|
||||||
|
_ context.Context,
|
||||||
|
_ api.ListWebhookExecutionsRequestObject,
|
||||||
|
) (api.ListWebhookExecutionsResponseObject, error) {
|
||||||
|
return api.ListWebhookExecutions200JSONResponse{
|
||||||
|
ListWebhooksExecutionResponseJSONResponse: api.ListWebhooksExecutionResponseJSONResponse{
|
||||||
|
Data: api.ListWebhooksExecutions{},
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
140
registry/app/api/controller/metadata/list_webhooks.go
Normal file
140
registry/app/api/controller/metadata/list_webhooks.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
apiauth "github.com/harness/gitness/app/api/auth"
|
||||||
|
"github.com/harness/gitness/app/api/request"
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/registry/types"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) ListWebhooks(
|
||||||
|
ctx context.Context,
|
||||||
|
r api.ListWebhooksRequestObject,
|
||||||
|
) (api.ListWebhooksResponseObject, error) {
|
||||||
|
regInfo, err := c.GetRegistryRequestBaseInfo(ctx, "", string(r.RegistryRef))
|
||||||
|
if err != nil {
|
||||||
|
return listWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
space, err := c.SpaceStore.FindByRef(ctx, regInfo.ParentRef)
|
||||||
|
if err != nil {
|
||||||
|
return listWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
|
permissionChecks := GetPermissionChecks(space, regInfo.RegistryIdentifier, enum.PermissionRegistryView)
|
||||||
|
if err = apiauth.CheckRegistry(
|
||||||
|
ctx,
|
||||||
|
c.Authorizer,
|
||||||
|
session,
|
||||||
|
permissionChecks...,
|
||||||
|
); err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("permission check failed while listing webhook for registry: %s, error: %v",
|
||||||
|
regInfo.RegistryIdentifier, err)
|
||||||
|
return api.ListWebhooks403JSONResponse{
|
||||||
|
UnauthorizedJSONResponse: api.UnauthorizedJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusForbidden, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := GetOffset(r.Params.Size, r.Params.Page)
|
||||||
|
limit := GetPageLimit(r.Params.Size)
|
||||||
|
pageNumber := GetPageNumber(r.Params.Page)
|
||||||
|
|
||||||
|
searchTerm := ""
|
||||||
|
if r.Params.SearchTerm != nil {
|
||||||
|
searchTerm = string(*r.Params.SearchTerm)
|
||||||
|
}
|
||||||
|
sortByField := ""
|
||||||
|
sortByOrder := ""
|
||||||
|
if r.Params.SortOrder != nil {
|
||||||
|
sortByOrder = string(*r.Params.SortOrder)
|
||||||
|
}
|
||||||
|
if r.Params.SortField != nil {
|
||||||
|
sortByField = string(*r.Params.SortField)
|
||||||
|
}
|
||||||
|
|
||||||
|
webhooks, err := c.WebhooksRepository.ListByRegistry(
|
||||||
|
ctx,
|
||||||
|
sortByField,
|
||||||
|
sortByOrder,
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
|
searchTerm,
|
||||||
|
regInfo.RegistryID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to list webhooks for registry: %s with error: %v", regInfo.RegistryRef, err)
|
||||||
|
return listWebhookInternalErrorResponse(fmt.Errorf("failed list to webhooks"))
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := c.WebhooksRepository.CountAllByRegistry(ctx, regInfo.RegistryID, searchTerm)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to list webhooks for registry: %s with error: %v", regInfo.RegistryRef, err)
|
||||||
|
return listWebhookInternalErrorResponse(fmt.Errorf("failed list to webhooks"))
|
||||||
|
}
|
||||||
|
webhooksResponse, err := c.mapToListWebhookResponseEntity(ctx, webhooks)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to list webhooks for registry: %s with error: %v", regInfo.RegistryRef, err)
|
||||||
|
return listWebhookInternalErrorResponse(fmt.Errorf("failed to list webhooks"))
|
||||||
|
}
|
||||||
|
pageCount := GetPageCount(count, limit)
|
||||||
|
|
||||||
|
return api.ListWebhooks200JSONResponse{
|
||||||
|
ListWebhooksResponseJSONResponse: api.ListWebhooksResponseJSONResponse{
|
||||||
|
Data: api.ListWebhooks{
|
||||||
|
PageIndex: &pageNumber,
|
||||||
|
PageCount: &pageCount,
|
||||||
|
PageSize: &limit,
|
||||||
|
ItemCount: &count,
|
||||||
|
Webhooks: webhooksResponse,
|
||||||
|
},
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func listWebhookInternalErrorResponse(err error) (api.ListWebhooksResponseObject, error) {
|
||||||
|
return api.ListWebhooks500JSONResponse{
|
||||||
|
InternalServerErrorJSONResponse: api.InternalServerErrorJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusInternalServerError, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIController) mapToListWebhookResponseEntity(
|
||||||
|
ctx context.Context,
|
||||||
|
webhooks *[]types.Webhook,
|
||||||
|
) ([]api.Webhook, error) {
|
||||||
|
webhooksEntities := make([]api.Webhook, 0, len(*webhooks))
|
||||||
|
for _, d := range *webhooks {
|
||||||
|
webhook, err := c.mapToWebhookResponseEntity(ctx, d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhooksEntities = append(webhooksEntities, *webhook)
|
||||||
|
}
|
||||||
|
return webhooksEntities, nil
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) ReTriggerWebhookExecution(
|
||||||
|
_ context.Context,
|
||||||
|
_ api.ReTriggerWebhookExecutionRequestObject,
|
||||||
|
) (api.ReTriggerWebhookExecutionResponseObject, error) {
|
||||||
|
return api.ReTriggerWebhookExecution200JSONResponse{
|
||||||
|
WebhookExecutionResponseJSONResponse: api.WebhookExecutionResponseJSONResponse{
|
||||||
|
Data: api.WebhookExecution{},
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
@ -392,7 +392,7 @@ func (c *APIController) UpdateUpstreamProxyEntity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.SecretSpacePath != nil && len(*res.SecretSpacePath) > 0 {
|
if res.SecretSpacePath != nil && len(*res.SecretSpacePath) > 0 {
|
||||||
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretID(ctx, res.SecretSpacePath)
|
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretSpaceID(ctx, res.SecretSpacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -412,7 +412,7 @@ func (c *APIController) UpdateUpstreamProxyEntity(
|
|||||||
return nil, nil, fmt.Errorf("failed to create upstream proxy: access_key_secret_identifier missing")
|
return nil, nil, fmt.Errorf("failed to create upstream proxy: access_key_secret_identifier missing")
|
||||||
default:
|
default:
|
||||||
if res.AccessKeySecretSpacePath != nil && len(*res.AccessKeySecretSpacePath) > 0 {
|
if res.AccessKeySecretSpacePath != nil && len(*res.AccessKeySecretSpacePath) > 0 {
|
||||||
upstreamProxyConfigEntity.UserNameSecretSpaceID, err = c.getSecretID(ctx, res.AccessKeySecretSpacePath)
|
upstreamProxyConfigEntity.UserNameSecretSpaceID, err = c.getSecretSpaceID(ctx, res.AccessKeySecretSpacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ func (c *APIController) UpdateUpstreamProxyEntity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.SecretKeySpacePath != nil && len(*res.SecretKeySpacePath) > 0 {
|
if res.SecretKeySpacePath != nil && len(*res.SecretKeySpacePath) > 0 {
|
||||||
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretID(ctx, res.SecretKeySpacePath)
|
upstreamProxyConfigEntity.SecretSpaceID, err = c.getSecretSpaceID(ctx, res.SecretKeySpacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
112
registry/app/api/controller/metadata/update_webhook.go
Normal file
112
registry/app/api/controller/metadata/update_webhook.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// 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 metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
apiauth "github.com/harness/gitness/app/api/auth"
|
||||||
|
"github.com/harness/gitness/app/api/request"
|
||||||
|
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *APIController) UpdateWebhook(
|
||||||
|
ctx context.Context,
|
||||||
|
r api.UpdateWebhookRequestObject,
|
||||||
|
) (api.UpdateWebhookResponseObject, error) {
|
||||||
|
webhookRequest := api.WebhookRequest(*r.Body)
|
||||||
|
regInfo, err := c.GetRegistryRequestBaseInfo(ctx, "", string(r.RegistryRef))
|
||||||
|
if err != nil {
|
||||||
|
return updateWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
space, err := c.SpaceStore.FindByRef(ctx, regInfo.ParentRef)
|
||||||
|
if err != nil {
|
||||||
|
return updateWebhookInternalErrorResponse(err)
|
||||||
|
}
|
||||||
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
|
permissionChecks := GetPermissionChecks(space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit)
|
||||||
|
if err = apiauth.CheckRegistry(
|
||||||
|
ctx,
|
||||||
|
c.Authorizer,
|
||||||
|
session,
|
||||||
|
permissionChecks...,
|
||||||
|
); err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("permission check failed while updating webhook for registry: %s, error: %v",
|
||||||
|
regInfo.RegistryIdentifier, err)
|
||||||
|
return api.UpdateWebhook403JSONResponse{
|
||||||
|
UnauthorizedJSONResponse: api.UnauthorizedJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusForbidden, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook, err := c.mapToWebhook(ctx, webhookRequest, regInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to update webhook: %s with error: %v", webhookRequest.Identifier, err)
|
||||||
|
return updateWebhookBadRequestErrorResponse(fmt.Errorf("failed to update webhook"))
|
||||||
|
}
|
||||||
|
webhook.Identifier = string(r.WebhookIdentifier)
|
||||||
|
|
||||||
|
err = c.WebhooksRepository.Update(ctx, webhook)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to update webhook: %s for registry: %s with error: %v",
|
||||||
|
webhookRequest.Identifier, regInfo.RegistryRef, err)
|
||||||
|
return updateWebhookBadRequestErrorResponse(fmt.Errorf("failed to update webhook"))
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedWebhook, err := c.WebhooksRepository.GetByRegistryAndIdentifier(
|
||||||
|
ctx, regInfo.RegistryID, webhookRequest.Identifier,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to get updated webhook: %s with error: %v",
|
||||||
|
webhookRequest.Identifier, err)
|
||||||
|
return updateWebhookInternalErrorResponse(fmt.Errorf("failed to get updated webhook"))
|
||||||
|
}
|
||||||
|
|
||||||
|
webhookResponseEntity, err := c.mapToWebhookResponseEntity(ctx, *updatedWebhook)
|
||||||
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Msgf("failed to get updated webhook: %s with error: %v",
|
||||||
|
webhookRequest.Identifier, err)
|
||||||
|
return updateWebhookInternalErrorResponse(fmt.Errorf("failed to get updated webhook"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.UpdateWebhook201JSONResponse{
|
||||||
|
WebhookResponseJSONResponse: api.WebhookResponseJSONResponse{
|
||||||
|
Data: *webhookResponseEntity,
|
||||||
|
Status: api.StatusSUCCESS,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateWebhookInternalErrorResponse(err error) (api.UpdateWebhookResponseObject, error) {
|
||||||
|
return api.UpdateWebhook500JSONResponse{
|
||||||
|
InternalServerErrorJSONResponse: api.InternalServerErrorJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusInternalServerError, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateWebhookBadRequestErrorResponse(err error) (api.UpdateWebhookResponseObject, error) {
|
||||||
|
return api.UpdateWebhook400JSONResponse{
|
||||||
|
BadRequestJSONResponse: api.BadRequestJSONResponse(
|
||||||
|
*GetErrorResponse(http.StatusBadRequest, err.Error()),
|
||||||
|
),
|
||||||
|
}, err
|
||||||
|
}
|
@ -15,6 +15,8 @@ tags:
|
|||||||
description: APIs to get details of docker artifacts
|
description: APIs to get details of docker artifacts
|
||||||
- name: Helm Artifacts
|
- name: Helm Artifacts
|
||||||
description: APIs to get details of helm artifacts
|
description: APIs to get details of helm artifacts
|
||||||
|
- name: Webhooks
|
||||||
|
description: APIs to create, update, list webhooks
|
||||||
|
|
||||||
|
|
||||||
servers:
|
servers:
|
||||||
@ -665,6 +667,184 @@ paths:
|
|||||||
$ref: "#/components/responses/NotFound"
|
$ref: "#/components/responses/NotFound"
|
||||||
500:
|
500:
|
||||||
$ref: "#/components/responses/InternalServerError"
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
/registry/{registry_ref}/webhooks:
|
||||||
|
post:
|
||||||
|
summary: CreateWebhook
|
||||||
|
description: Returns Webhook Details
|
||||||
|
operationId: CreateWebhook
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
requestBody:
|
||||||
|
$ref: "#/components/requestBodies/WebhookRequest"
|
||||||
|
responses:
|
||||||
|
201:
|
||||||
|
$ref: "#/components/responses/WebhookResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
get:
|
||||||
|
summary: ListWebhooks
|
||||||
|
description: Returns List of Webhook Details
|
||||||
|
operationId: ListWebhooks
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/pageNumber"
|
||||||
|
- $ref: "#/components/parameters/pageSize"
|
||||||
|
- $ref: "#/components/parameters/sortOrder"
|
||||||
|
- $ref: "#/components/parameters/sortField"
|
||||||
|
- $ref: "#/components/parameters/searchTerm"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/ListWebhooksResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
/registry/{registry_ref}/webhooks/{webhook_identifier}:
|
||||||
|
put:
|
||||||
|
summary: UpdateWebhook
|
||||||
|
description: Returns Webhook Details
|
||||||
|
operationId: UpdateWebhook
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookIdentifierPathParam"
|
||||||
|
requestBody:
|
||||||
|
$ref: "#/components/requestBodies/WebhookRequest"
|
||||||
|
responses:
|
||||||
|
201:
|
||||||
|
$ref: "#/components/responses/WebhookResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
get:
|
||||||
|
summary: GetWebhook
|
||||||
|
description: Returns Webhook Details
|
||||||
|
operationId: GetWebhook
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookIdentifierPathParam"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/WebhookResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
delete:
|
||||||
|
summary: DeleteWebhook
|
||||||
|
description: Delete a Webhook
|
||||||
|
operationId: DeleteWebhook
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookIdentifierPathParam"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/Success"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
404:
|
||||||
|
$ref: "#/components/responses/NotFound"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
/registry/{registry_ref}/webhooks/{webhook_identifier}/executions:
|
||||||
|
get:
|
||||||
|
summary: ListWebhookExecutions
|
||||||
|
description: Returns Webhook Execution Details List
|
||||||
|
operationId: ListWebhookExecutions
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookIdentifierPathParam"
|
||||||
|
- $ref: "#/components/parameters/pageNumber"
|
||||||
|
- $ref: "#/components/parameters/pageSize"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/ListWebhooksExecutionResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
/registry/{registry_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}:
|
||||||
|
get:
|
||||||
|
summary: GetWebhookExecution
|
||||||
|
description: Returns Webhook Execution Details
|
||||||
|
operationId: GetWebhookExecution
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookIdentifierPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookExecutionIdPathParam"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/WebhookExecutionResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
|
/registry/{registry_ref}/webhooks/{webhook_identifier}/executions/{webhook_execution_id}/retrigger:
|
||||||
|
get:
|
||||||
|
summary: ReTriggerWebhookExecution
|
||||||
|
description: Retrigger Webhook Execution
|
||||||
|
operationId: ReTriggerWebhookExecution
|
||||||
|
tags:
|
||||||
|
- Webhooks
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/registryRefPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookIdentifierPathParam"
|
||||||
|
- $ref: "#/components/parameters/webhookExecutionIdPathParam"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/WebhookExecutionResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/BadRequest"
|
||||||
|
401:
|
||||||
|
$ref: "#/components/responses/Unauthenticated"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
500:
|
||||||
|
$ref: "#/components/responses/InternalServerError"
|
||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
RegistryRequest:
|
RegistryRequest:
|
||||||
@ -679,6 +859,12 @@ components:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/ArtifactLabelRequest"
|
$ref: "#/components/schemas/ArtifactLabelRequest"
|
||||||
|
WebhookRequest:
|
||||||
|
description: request for create and update webhook
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/WebhookRequest"
|
||||||
responses:
|
responses:
|
||||||
ArtifactStatsResponse:
|
ArtifactStatsResponse:
|
||||||
description: response to get artifact stats response
|
description: response to get artifact stats response
|
||||||
@ -736,6 +922,48 @@ components:
|
|||||||
required:
|
required:
|
||||||
- status
|
- status
|
||||||
- data
|
- data
|
||||||
|
WebhookResponse:
|
||||||
|
description: response for create, get and update webhook
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: "#/components/schemas/Status"
|
||||||
|
data:
|
||||||
|
$ref: "#/components/schemas/Webhook"
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- data
|
||||||
|
ListWebhooksExecutionResponse:
|
||||||
|
description: list webhooks executions response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: "#/components/schemas/Status"
|
||||||
|
data:
|
||||||
|
$ref: "#/components/schemas/ListWebhooksExecutions"
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- data
|
||||||
|
WebhookExecutionResponse:
|
||||||
|
description: webhook execution response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: "#/components/schemas/Status"
|
||||||
|
data:
|
||||||
|
$ref: "#/components/schemas/WebhookExecution"
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- data
|
||||||
DockerArtifactDetailResponse:
|
DockerArtifactDetailResponse:
|
||||||
description: response to get docker artifact detail
|
description: response to get docker artifact detail
|
||||||
content:
|
content:
|
||||||
@ -927,6 +1155,20 @@ components:
|
|||||||
required:
|
required:
|
||||||
- status
|
- status
|
||||||
- data
|
- data
|
||||||
|
ListWebhooksResponse:
|
||||||
|
description: response for list webhooks
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: "#/components/schemas/Status"
|
||||||
|
data:
|
||||||
|
$ref: "#/components/schemas/ListWebhooks"
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- data
|
||||||
ListArtifactResponse:
|
ListArtifactResponse:
|
||||||
description: response for list artifact
|
description: response for list artifact
|
||||||
content:
|
content:
|
||||||
@ -1057,6 +1299,66 @@ components:
|
|||||||
$ref: "#/components/schemas/RegistryMetadata"
|
$ref: "#/components/schemas/RegistryMetadata"
|
||||||
required:
|
required:
|
||||||
- registries
|
- registries
|
||||||
|
ListWebhooks:
|
||||||
|
type: object
|
||||||
|
description: A list of Harness Registries webhooks
|
||||||
|
properties:
|
||||||
|
pageCount:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: The total number of pages
|
||||||
|
example: 100
|
||||||
|
itemCount:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: The total number of items
|
||||||
|
example: 1
|
||||||
|
pageSize:
|
||||||
|
type: integer
|
||||||
|
description: The number of items per page
|
||||||
|
example: 1
|
||||||
|
pageIndex:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: The current page
|
||||||
|
example: 0
|
||||||
|
webhooks:
|
||||||
|
type: array
|
||||||
|
description: A list of Registries webhooks
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Webhook"
|
||||||
|
required:
|
||||||
|
- webhooks
|
||||||
|
ListWebhooksExecutions:
|
||||||
|
type: object
|
||||||
|
description: A list of Harness Registries webhooks executions
|
||||||
|
properties:
|
||||||
|
pageCount:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: The total number of pages
|
||||||
|
example: 100
|
||||||
|
itemCount:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: The total number of items
|
||||||
|
example: 1
|
||||||
|
pageSize:
|
||||||
|
type: integer
|
||||||
|
description: The number of items per page
|
||||||
|
example: 1
|
||||||
|
pageIndex:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: The current page
|
||||||
|
example: 0
|
||||||
|
executions:
|
||||||
|
type: array
|
||||||
|
description: A list of Registries webhooks executions
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/WebhookExecution"
|
||||||
|
required:
|
||||||
|
- executions
|
||||||
ListArtifact:
|
ListArtifact:
|
||||||
type: object
|
type: object
|
||||||
description: A list of Artifacts
|
description: A list of Artifacts
|
||||||
@ -1445,6 +1747,109 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
pullCommand:
|
pullCommand:
|
||||||
type: string
|
type: string
|
||||||
|
Webhook:
|
||||||
|
type: object
|
||||||
|
description: Harness Regstries Webhook
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
identifier:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
createdAt:
|
||||||
|
type: string
|
||||||
|
createdBy:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
modifiedAt:
|
||||||
|
type: string
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
internal:
|
||||||
|
type: boolean
|
||||||
|
secretIdentifier:
|
||||||
|
type: string
|
||||||
|
secretSpacePath:
|
||||||
|
type: string
|
||||||
|
secretSpaceId:
|
||||||
|
type: integer
|
||||||
|
insecure:
|
||||||
|
type: boolean
|
||||||
|
triggers:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Trigger"
|
||||||
|
latestExecutionResult:
|
||||||
|
$ref: "#/components/schemas/WebhookExecResult"
|
||||||
|
extraHeaders:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ExtraHeader"
|
||||||
|
required:
|
||||||
|
- identifier
|
||||||
|
- url
|
||||||
|
- name
|
||||||
|
- enabled
|
||||||
|
- insecure
|
||||||
|
WebhookExecution:
|
||||||
|
type: object
|
||||||
|
description: Harness Regstries Webhook Execution
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
retriggerOf:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
retriggerable:
|
||||||
|
type: boolean
|
||||||
|
created:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
webhookId:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
triggerType:
|
||||||
|
$ref: "#/components/schemas/Trigger"
|
||||||
|
result:
|
||||||
|
$ref: "#/components/schemas/WebhookExecResult"
|
||||||
|
duration:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
request:
|
||||||
|
$ref: "#/components/schemas/WebhookExecRequest"
|
||||||
|
response:
|
||||||
|
$ref: "#/components/schemas/WebhookExecResponse"
|
||||||
|
WebhookExecRequest:
|
||||||
|
type: object
|
||||||
|
description: Harness Regstries HTTP Webhook Request
|
||||||
|
properties:
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
headers:
|
||||||
|
type: string
|
||||||
|
body:
|
||||||
|
type: string
|
||||||
|
WebhookExecResponse:
|
||||||
|
type: object
|
||||||
|
description: Harness Regstries HTTP Webhook Response
|
||||||
|
properties:
|
||||||
|
statusCode:
|
||||||
|
type: integer
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
headers:
|
||||||
|
type: string
|
||||||
|
body:
|
||||||
|
type: string
|
||||||
DockerArtifactDetail:
|
DockerArtifactDetail:
|
||||||
type: object
|
type: object
|
||||||
description: Docker Artifact Detail
|
description: Docker Artifact Detail
|
||||||
@ -1710,6 +2115,28 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
|
Trigger:
|
||||||
|
type: string
|
||||||
|
description: refers to trigger
|
||||||
|
enum:
|
||||||
|
- ARTIFACT_CREATION
|
||||||
|
- ARTIFACT_MODIFICATION
|
||||||
|
- ARTIFACT_DELETION
|
||||||
|
ExtraHeader:
|
||||||
|
type: object
|
||||||
|
description: Webhook Extra Header
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
type: string
|
||||||
|
WebhookExecResult:
|
||||||
|
type: string
|
||||||
|
description: refers to webhook execution
|
||||||
|
enum:
|
||||||
|
- SUCCESS
|
||||||
|
- RETRIABLE_ERROR
|
||||||
|
- FATAL_ERROR
|
||||||
RegistryType:
|
RegistryType:
|
||||||
type: string
|
type: string
|
||||||
description: refers to type of registry i.e virtual or upstream
|
description: refers to type of registry i.e virtual or upstream
|
||||||
@ -1803,6 +2230,41 @@ components:
|
|||||||
- identifier
|
- identifier
|
||||||
- type
|
- type
|
||||||
- packageType
|
- packageType
|
||||||
|
WebhookRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
identifier:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
insecure:
|
||||||
|
type: boolean
|
||||||
|
secretIdentifier:
|
||||||
|
type: string
|
||||||
|
secretSpacePath:
|
||||||
|
type: string
|
||||||
|
secretSpaceId:
|
||||||
|
type: integer
|
||||||
|
triggers:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Trigger"
|
||||||
|
extraHeaders:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ExtraHeader"
|
||||||
|
required:
|
||||||
|
- insecure
|
||||||
|
- enabled
|
||||||
|
- identifier
|
||||||
|
- url
|
||||||
|
- name
|
||||||
ArtifactLabelRequest:
|
ArtifactLabelRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -1910,6 +2372,20 @@ components:
|
|||||||
description: Unique registry path.
|
description: Unique registry path.
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
webhookIdentifierPathParam:
|
||||||
|
name: webhook_identifier
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: Unique webhook identifier.
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
webhookExecutionIdPathParam:
|
||||||
|
name: webhook_execution_id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: Unique webhook execution identifier.
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
artifactParam:
|
artifactParam:
|
||||||
name: artifact
|
name: artifact
|
||||||
in: query
|
in: query
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,13 @@ const (
|
|||||||
StatusSUCCESS Status = "SUCCESS"
|
StatusSUCCESS Status = "SUCCESS"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Defines values for Trigger.
|
||||||
|
const (
|
||||||
|
TriggerARTIFACTCREATION Trigger = "ARTIFACT_CREATION"
|
||||||
|
TriggerARTIFACTDELETION Trigger = "ARTIFACT_DELETION"
|
||||||
|
TriggerARTIFACTMODIFICATION Trigger = "ARTIFACT_MODIFICATION"
|
||||||
|
)
|
||||||
|
|
||||||
// Defines values for UpstreamConfigSource.
|
// Defines values for UpstreamConfigSource.
|
||||||
const (
|
const (
|
||||||
UpstreamConfigSourceAwsEcr UpstreamConfigSource = "AwsEcr"
|
UpstreamConfigSourceAwsEcr UpstreamConfigSource = "AwsEcr"
|
||||||
@ -53,6 +60,13 @@ const (
|
|||||||
UpstreamConfigSourceMavenCentral UpstreamConfigSource = "MavenCentral"
|
UpstreamConfigSourceMavenCentral UpstreamConfigSource = "MavenCentral"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Defines values for WebhookExecResult.
|
||||||
|
const (
|
||||||
|
WebhookExecResultFATALERROR WebhookExecResult = "FATAL_ERROR"
|
||||||
|
WebhookExecResultRETRIABLEERROR WebhookExecResult = "RETRIABLE_ERROR"
|
||||||
|
WebhookExecResultSUCCESS WebhookExecResult = "SUCCESS"
|
||||||
|
)
|
||||||
|
|
||||||
// Defines values for RegistryTypeParam.
|
// Defines values for RegistryTypeParam.
|
||||||
const (
|
const (
|
||||||
UPSTREAM RegistryTypeParam = "UPSTREAM"
|
UPSTREAM RegistryTypeParam = "UPSTREAM"
|
||||||
@ -272,6 +286,12 @@ type Error struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtraHeader Webhook Extra Header
|
||||||
|
type ExtraHeader struct {
|
||||||
|
Key *string `json:"key,omitempty"`
|
||||||
|
Value *string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// FileDetail File Detail
|
// FileDetail File Detail
|
||||||
type FileDetail struct {
|
type FileDetail struct {
|
||||||
Checksums []string `json:"checksums"`
|
Checksums []string `json:"checksums"`
|
||||||
@ -401,6 +421,42 @@ type ListRegistryArtifact struct {
|
|||||||
PageSize *int `json:"pageSize,omitempty"`
|
PageSize *int `json:"pageSize,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListWebhooks A list of Harness Registries webhooks
|
||||||
|
type ListWebhooks struct {
|
||||||
|
// ItemCount The total number of items
|
||||||
|
ItemCount *int64 `json:"itemCount,omitempty"`
|
||||||
|
|
||||||
|
// PageCount The total number of pages
|
||||||
|
PageCount *int64 `json:"pageCount,omitempty"`
|
||||||
|
|
||||||
|
// PageIndex The current page
|
||||||
|
PageIndex *int64 `json:"pageIndex,omitempty"`
|
||||||
|
|
||||||
|
// PageSize The number of items per page
|
||||||
|
PageSize *int `json:"pageSize,omitempty"`
|
||||||
|
|
||||||
|
// Webhooks A list of Registries webhooks
|
||||||
|
Webhooks []Webhook `json:"webhooks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooksExecutions A list of Harness Registries webhooks executions
|
||||||
|
type ListWebhooksExecutions struct {
|
||||||
|
// Executions A list of Registries webhooks executions
|
||||||
|
Executions []WebhookExecution `json:"executions"`
|
||||||
|
|
||||||
|
// ItemCount The total number of items
|
||||||
|
ItemCount *int64 `json:"itemCount,omitempty"`
|
||||||
|
|
||||||
|
// PageCount The total number of pages
|
||||||
|
PageCount *int64 `json:"pageCount,omitempty"`
|
||||||
|
|
||||||
|
// PageIndex The current page
|
||||||
|
PageIndex *int64 `json:"pageIndex,omitempty"`
|
||||||
|
|
||||||
|
// PageSize The number of items per page
|
||||||
|
PageSize *int `json:"pageSize,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// MavenArtifactDetailConfig Config for generic artifact details
|
// MavenArtifactDetailConfig Config for generic artifact details
|
||||||
type MavenArtifactDetailConfig struct {
|
type MavenArtifactDetailConfig struct {
|
||||||
ArtifactId *string `json:"artifactId,omitempty"`
|
ArtifactId *string `json:"artifactId,omitempty"`
|
||||||
@ -492,6 +548,9 @@ type RegistryType string
|
|||||||
// Status Indicates if the request was successful or not
|
// Status Indicates if the request was successful or not
|
||||||
type Status string
|
type Status string
|
||||||
|
|
||||||
|
// Trigger refers to trigger
|
||||||
|
type Trigger string
|
||||||
|
|
||||||
// UpstreamConfig Configuration for Harness Artifact UpstreamProxies
|
// UpstreamConfig Configuration for Harness Artifact UpstreamProxies
|
||||||
type UpstreamConfig struct {
|
type UpstreamConfig struct {
|
||||||
Auth *UpstreamConfig_Auth `json:"auth,omitempty"`
|
Auth *UpstreamConfig_Auth `json:"auth,omitempty"`
|
||||||
@ -523,6 +582,85 @@ type VirtualConfig struct {
|
|||||||
UpstreamProxies *[]string `json:"upstreamProxies,omitempty"`
|
UpstreamProxies *[]string `json:"upstreamProxies,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Webhook Harness Regstries Webhook
|
||||||
|
type Webhook struct {
|
||||||
|
CreatedAt *string `json:"createdAt,omitempty"`
|
||||||
|
CreatedBy *int64 `json:"createdBy,omitempty"`
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
ExtraHeaders *[]ExtraHeader `json:"extraHeaders,omitempty"`
|
||||||
|
Identifier string `json:"identifier"`
|
||||||
|
Insecure bool `json:"insecure"`
|
||||||
|
Internal *bool `json:"internal,omitempty"`
|
||||||
|
|
||||||
|
// LatestExecutionResult refers to webhook execution
|
||||||
|
LatestExecutionResult *WebhookExecResult `json:"latestExecutionResult,omitempty"`
|
||||||
|
ModifiedAt *string `json:"modifiedAt,omitempty"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
SecretIdentifier *string `json:"secretIdentifier,omitempty"`
|
||||||
|
SecretSpaceId *int `json:"secretSpaceId,omitempty"`
|
||||||
|
SecretSpacePath *string `json:"secretSpacePath,omitempty"`
|
||||||
|
Triggers *[]Trigger `json:"triggers,omitempty"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Version *int64 `json:"version,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookExecRequest Harness Regstries HTTP Webhook Request
|
||||||
|
type WebhookExecRequest struct {
|
||||||
|
Body *string `json:"body,omitempty"`
|
||||||
|
Headers *string `json:"headers,omitempty"`
|
||||||
|
Url *string `json:"url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookExecResponse Harness Regstries HTTP Webhook Response
|
||||||
|
type WebhookExecResponse struct {
|
||||||
|
Body *string `json:"body,omitempty"`
|
||||||
|
Headers *string `json:"headers,omitempty"`
|
||||||
|
Status *string `json:"status,omitempty"`
|
||||||
|
StatusCode *int `json:"statusCode,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookExecResult refers to webhook execution
|
||||||
|
type WebhookExecResult string
|
||||||
|
|
||||||
|
// WebhookExecution Harness Regstries Webhook Execution
|
||||||
|
type WebhookExecution struct {
|
||||||
|
Created *int64 `json:"created,omitempty"`
|
||||||
|
Duration *int64 `json:"duration,omitempty"`
|
||||||
|
Error *string `json:"error,omitempty"`
|
||||||
|
Id *int64 `json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Request Harness Regstries HTTP Webhook Request
|
||||||
|
Request *WebhookExecRequest `json:"request,omitempty"`
|
||||||
|
|
||||||
|
// Response Harness Regstries HTTP Webhook Response
|
||||||
|
Response *WebhookExecResponse `json:"response,omitempty"`
|
||||||
|
|
||||||
|
// Result refers to webhook execution
|
||||||
|
Result *WebhookExecResult `json:"result,omitempty"`
|
||||||
|
RetriggerOf *int64 `json:"retriggerOf,omitempty"`
|
||||||
|
Retriggerable *bool `json:"retriggerable,omitempty"`
|
||||||
|
|
||||||
|
// TriggerType refers to trigger
|
||||||
|
TriggerType *Trigger `json:"triggerType,omitempty"`
|
||||||
|
WebhookId *int64 `json:"webhookId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookRequest defines model for WebhookRequest.
|
||||||
|
type WebhookRequest struct {
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
ExtraHeaders *[]ExtraHeader `json:"extraHeaders,omitempty"`
|
||||||
|
Identifier string `json:"identifier"`
|
||||||
|
Insecure bool `json:"insecure"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
SecretIdentifier *string `json:"secretIdentifier,omitempty"`
|
||||||
|
SecretSpaceId *int `json:"secretSpaceId,omitempty"`
|
||||||
|
SecretSpacePath *string `json:"secretSpacePath,omitempty"`
|
||||||
|
Triggers *[]Trigger `json:"triggers,omitempty"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
// LabelsParam defines model for LabelsParam.
|
// LabelsParam defines model for LabelsParam.
|
||||||
type LabelsParam []string
|
type LabelsParam []string
|
||||||
|
|
||||||
@ -589,6 +727,12 @@ type VersionParam string
|
|||||||
// VersionPathParam defines model for versionPathParam.
|
// VersionPathParam defines model for versionPathParam.
|
||||||
type VersionPathParam string
|
type VersionPathParam string
|
||||||
|
|
||||||
|
// WebhookExecutionIdPathParam defines model for webhookExecutionIdPathParam.
|
||||||
|
type WebhookExecutionIdPathParam string
|
||||||
|
|
||||||
|
// WebhookIdentifierPathParam defines model for webhookIdentifierPathParam.
|
||||||
|
type WebhookIdentifierPathParam string
|
||||||
|
|
||||||
// ArtifactDetailResponse defines model for ArtifactDetailResponse.
|
// ArtifactDetailResponse defines model for ArtifactDetailResponse.
|
||||||
type ArtifactDetailResponse struct {
|
type ArtifactDetailResponse struct {
|
||||||
// Data Artifact Detail
|
// Data Artifact Detail
|
||||||
@ -769,6 +913,24 @@ type ListRegistryResponse struct {
|
|||||||
Status Status `json:"status"`
|
Status Status `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListWebhooksExecutionResponse defines model for ListWebhooksExecutionResponse.
|
||||||
|
type ListWebhooksExecutionResponse struct {
|
||||||
|
// Data A list of Harness Registries webhooks executions
|
||||||
|
Data ListWebhooksExecutions `json:"data"`
|
||||||
|
|
||||||
|
// Status Indicates if the request was successful or not
|
||||||
|
Status Status `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhooksResponse defines model for ListWebhooksResponse.
|
||||||
|
type ListWebhooksResponse struct {
|
||||||
|
// Data A list of Harness Registries webhooks
|
||||||
|
Data ListWebhooks `json:"data"`
|
||||||
|
|
||||||
|
// Status Indicates if the request was successful or not
|
||||||
|
Status Status `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
// NotFound defines model for NotFound.
|
// NotFound defines model for NotFound.
|
||||||
type NotFound Error
|
type NotFound Error
|
||||||
|
|
||||||
@ -793,6 +955,24 @@ type Unauthenticated Error
|
|||||||
// Unauthorized defines model for Unauthorized.
|
// Unauthorized defines model for Unauthorized.
|
||||||
type Unauthorized Error
|
type Unauthorized Error
|
||||||
|
|
||||||
|
// WebhookExecutionResponse defines model for WebhookExecutionResponse.
|
||||||
|
type WebhookExecutionResponse struct {
|
||||||
|
// Data Harness Regstries Webhook Execution
|
||||||
|
Data WebhookExecution `json:"data"`
|
||||||
|
|
||||||
|
// Status Indicates if the request was successful or not
|
||||||
|
Status Status `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookResponse defines model for WebhookResponse.
|
||||||
|
type WebhookResponse struct {
|
||||||
|
// Data Harness Regstries Webhook
|
||||||
|
Data Webhook `json:"data"`
|
||||||
|
|
||||||
|
// Status Indicates if the request was successful or not
|
||||||
|
Status Status `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
// CreateRegistryParams defines parameters for CreateRegistry.
|
// CreateRegistryParams defines parameters for CreateRegistry.
|
||||||
type CreateRegistryParams struct {
|
type CreateRegistryParams struct {
|
||||||
// SpaceRef Unique space path
|
// SpaceRef Unique space path
|
||||||
@ -901,6 +1081,33 @@ type GetClientSetupDetailsParams struct {
|
|||||||
Version *VersionParam `form:"version,omitempty" json:"version,omitempty"`
|
Version *VersionParam `form:"version,omitempty" json:"version,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListWebhooksParams defines parameters for ListWebhooks.
|
||||||
|
type ListWebhooksParams struct {
|
||||||
|
// Page Current page number
|
||||||
|
Page *PageNumber `form:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Size Number of items per page
|
||||||
|
Size *PageSize `form:"size,omitempty" json:"size,omitempty"`
|
||||||
|
|
||||||
|
// SortOrder sortOrder
|
||||||
|
SortOrder *SortOrder `form:"sort_order,omitempty" json:"sort_order,omitempty"`
|
||||||
|
|
||||||
|
// SortField sortField
|
||||||
|
SortField *SortField `form:"sort_field,omitempty" json:"sort_field,omitempty"`
|
||||||
|
|
||||||
|
// SearchTerm search Term.
|
||||||
|
SearchTerm *SearchTerm `form:"search_term,omitempty" json:"search_term,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListWebhookExecutionsParams defines parameters for ListWebhookExecutions.
|
||||||
|
type ListWebhookExecutionsParams struct {
|
||||||
|
// Page Current page number
|
||||||
|
Page *PageNumber `form:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Size Number of items per page
|
||||||
|
Size *PageSize `form:"size,omitempty" json:"size,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetArtifactStatsForSpaceParams defines parameters for GetArtifactStatsForSpace.
|
// GetArtifactStatsForSpaceParams defines parameters for GetArtifactStatsForSpace.
|
||||||
type GetArtifactStatsForSpaceParams struct {
|
type GetArtifactStatsForSpaceParams struct {
|
||||||
// From Date. Format - MM/DD/YYYY
|
// From Date. Format - MM/DD/YYYY
|
||||||
@ -976,6 +1183,12 @@ type ModifyRegistryJSONRequestBody RegistryRequest
|
|||||||
// UpdateArtifactLabelsJSONRequestBody defines body for UpdateArtifactLabels for application/json ContentType.
|
// UpdateArtifactLabelsJSONRequestBody defines body for UpdateArtifactLabels for application/json ContentType.
|
||||||
type UpdateArtifactLabelsJSONRequestBody ArtifactLabelRequest
|
type UpdateArtifactLabelsJSONRequestBody ArtifactLabelRequest
|
||||||
|
|
||||||
|
// CreateWebhookJSONRequestBody defines body for CreateWebhook for application/json ContentType.
|
||||||
|
type CreateWebhookJSONRequestBody WebhookRequest
|
||||||
|
|
||||||
|
// UpdateWebhookJSONRequestBody defines body for UpdateWebhook for application/json ContentType.
|
||||||
|
type UpdateWebhookJSONRequestBody WebhookRequest
|
||||||
|
|
||||||
// AsDockerArtifactDetailConfig returns the union data inside the ArtifactDetail as a DockerArtifactDetailConfig
|
// AsDockerArtifactDetailConfig returns the union data inside the ArtifactDetail as a DockerArtifactDetailConfig
|
||||||
func (t ArtifactDetail) AsDockerArtifactDetailConfig() (DockerArtifactDetailConfig, error) {
|
func (t ArtifactDetail) AsDockerArtifactDetailConfig() (DockerArtifactDetailConfig, error) {
|
||||||
var body DockerArtifactDetailConfig
|
var body DockerArtifactDetailConfig
|
||||||
|
@ -67,6 +67,7 @@ func NewAPIHandler(
|
|||||||
auditService audit.Service,
|
auditService audit.Service,
|
||||||
spacePathStore corestore.SpacePathStore,
|
spacePathStore corestore.SpacePathStore,
|
||||||
artifactStore store.ArtifactRepository,
|
artifactStore store.ArtifactRepository,
|
||||||
|
webhooksRepository store.WebhooksRepository,
|
||||||
) APIHandler {
|
) APIHandler {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Use(audit.Middleware())
|
r.Use(audit.Middleware())
|
||||||
@ -87,6 +88,7 @@ func NewAPIHandler(
|
|||||||
auditService,
|
auditService,
|
||||||
spacePathStore,
|
spacePathStore,
|
||||||
artifactStore,
|
artifactStore,
|
||||||
|
webhooksRepository,
|
||||||
)
|
)
|
||||||
handler := artifact.NewStrictHandler(apiController, []artifact.StrictMiddlewareFunc{})
|
handler := artifact.NewStrictHandler(apiController, []artifact.StrictMiddlewareFunc{})
|
||||||
muxHandler := artifact.HandlerFromMuxWithBaseURL(handler, r, baseURL)
|
muxHandler := artifact.HandlerFromMuxWithBaseURL(handler, r, baseURL)
|
||||||
|
@ -57,6 +57,7 @@ func APIHandlerProvider(
|
|||||||
auditService audit.Service,
|
auditService audit.Service,
|
||||||
spacePathStore corestore.SpacePathStore,
|
spacePathStore corestore.SpacePathStore,
|
||||||
artifactStore store.ArtifactRepository,
|
artifactStore store.ArtifactRepository,
|
||||||
|
webhooksRepository store.WebhooksRepository,
|
||||||
) harness.APIHandler {
|
) harness.APIHandler {
|
||||||
return harness.NewAPIHandler(
|
return harness.NewAPIHandler(
|
||||||
repoDao,
|
repoDao,
|
||||||
@ -75,6 +76,7 @@ func APIHandlerProvider(
|
|||||||
auditService,
|
auditService,
|
||||||
spacePathStore,
|
spacePathStore,
|
||||||
artifactStore,
|
artifactStore,
|
||||||
|
webhooksRepository,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,3 +516,25 @@ type GenericBlobRepository interface {
|
|||||||
Create(ctx context.Context, gb *types.GenericBlob) error
|
Create(ctx context.Context, gb *types.GenericBlob) error
|
||||||
DeleteByID(ctx context.Context, id string) error
|
DeleteByID(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WebhooksRepository interface {
|
||||||
|
Create(ctx context.Context, webhook *types.Webhook) error
|
||||||
|
GetByRegistryAndIdentifier(ctx context.Context, registryID int64, webhookIdentifier string) (*types.Webhook, error)
|
||||||
|
ListByRegistry(
|
||||||
|
ctx context.Context,
|
||||||
|
sortByField string,
|
||||||
|
sortByOrder string,
|
||||||
|
limit int,
|
||||||
|
offset int,
|
||||||
|
search string,
|
||||||
|
registryID int64,
|
||||||
|
) (*[]types.Webhook, error)
|
||||||
|
CountAllByRegistry(
|
||||||
|
ctx context.Context,
|
||||||
|
registryID int64,
|
||||||
|
search string,
|
||||||
|
) (int64, error)
|
||||||
|
|
||||||
|
Update(ctx context.Context, webhook *types.Webhook) error
|
||||||
|
DeleteByRegistryAndIdentifier(ctx context.Context, registryID int64, webhookIdentifier string) error
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
"github.com/harness/gitness/registry/app/store"
|
"github.com/harness/gitness/registry/app/store"
|
||||||
"github.com/harness/gitness/registry/app/store/database/util"
|
"github.com/harness/gitness/registry/app/store/database/util"
|
||||||
"github.com/harness/gitness/registry/types"
|
"github.com/harness/gitness/registry/types"
|
||||||
gitness_store "github.com/harness/gitness/store"
|
gitnessstore "github.com/harness/gitness/store"
|
||||||
databaseg "github.com/harness/gitness/store/database"
|
databaseg "github.com/harness/gitness/store/database"
|
||||||
"github.com/harness/gitness/store/database/dbtx"
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
@ -236,7 +236,6 @@ func (r registryDao) GetAll(
|
|||||||
repoType string,
|
repoType string,
|
||||||
recursive bool,
|
recursive bool,
|
||||||
) (repos *[]store.RegistryMetadata, err error) {
|
) (repos *[]store.RegistryMetadata, err error) {
|
||||||
// Select only required fields
|
|
||||||
selectFields := `
|
selectFields := `
|
||||||
r.registry_id AS registry_id,
|
r.registry_id AS registry_id,
|
||||||
r.registry_name AS reg_identifier,
|
r.registry_name AS reg_identifier,
|
||||||
@ -620,7 +619,7 @@ func (r registryDao) Update(ctx context.Context, registry *types.Registry) (err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return gitness_store.ErrVersionConflict
|
return gitnessstore.ErrVersionConflict
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
453
registry/app/store/database/webhook.go
Normal file
453
registry/app/store/database/webhook.go
Normal file
@ -0,0 +1,453 @@
|
|||||||
|
// 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 database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/registry/app/pkg/commons"
|
||||||
|
"github.com/harness/gitness/registry/app/store"
|
||||||
|
"github.com/harness/gitness/registry/app/store/database/util"
|
||||||
|
"github.com/harness/gitness/registry/types"
|
||||||
|
"github.com/harness/gitness/registry/types/enum"
|
||||||
|
gitnessstore "github.com/harness/gitness/store"
|
||||||
|
"github.com/harness/gitness/store/database"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
|
|
||||||
|
"github.com/guregu/null"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const triggersSeparator = ","
|
||||||
|
|
||||||
|
var registryWebhooksFields = []string{
|
||||||
|
"registry_webhook_id",
|
||||||
|
"registry_webhook_version",
|
||||||
|
"registry_webhook_registry_id",
|
||||||
|
"registry_webhook_space_id",
|
||||||
|
"registry_webhook_created_by",
|
||||||
|
"registry_webhook_created",
|
||||||
|
"registry_webhook_updated",
|
||||||
|
"registry_webhook_scope",
|
||||||
|
"registry_webhook_identifier",
|
||||||
|
"registry_webhook_name",
|
||||||
|
"registry_webhook_description",
|
||||||
|
"registry_webhook_url",
|
||||||
|
"registry_webhook_secret_identifier",
|
||||||
|
"registry_webhook_secret_space_id",
|
||||||
|
"registry_webhook_enabled",
|
||||||
|
"registry_webhook_internal",
|
||||||
|
"registry_webhook_insecure",
|
||||||
|
"registry_webhook_triggers",
|
||||||
|
"registry_webhook_extra_headers",
|
||||||
|
"registry_webhook_latest_execution_result",
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWebhookDao(db *sqlx.DB) store.WebhooksRepository {
|
||||||
|
return &WebhookDao{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type webhookDB struct {
|
||||||
|
ID int64 `db:"registry_webhook_id"`
|
||||||
|
Version int64 `db:"registry_webhook_version"`
|
||||||
|
RegistryID null.Int `db:"registry_webhook_registry_id"`
|
||||||
|
SpaceID null.Int `db:"registry_webhook_space_id"`
|
||||||
|
CreatedBy int64 `db:"registry_webhook_created_by"`
|
||||||
|
Created int64 `db:"registry_webhook_created"`
|
||||||
|
Updated int64 `db:"registry_webhook_updated"`
|
||||||
|
Scope int64 `db:"registry_webhook_scope"`
|
||||||
|
Internal bool `db:"registry_webhook_internal"`
|
||||||
|
Identifier string `db:"registry_webhook_identifier"`
|
||||||
|
Name string `db:"registry_webhook_name"`
|
||||||
|
Description string `db:"registry_webhook_description"`
|
||||||
|
URL string `db:"registry_webhook_url"`
|
||||||
|
SecretIdentifier sql.NullString `db:"registry_webhook_secret_identifier"`
|
||||||
|
SecretSpaceID sql.NullInt32 `db:"registry_webhook_secret_space_id"`
|
||||||
|
Enabled bool `db:"registry_webhook_enabled"`
|
||||||
|
Insecure bool `db:"registry_webhook_insecure"`
|
||||||
|
Triggers string `db:"registry_webhook_triggers"`
|
||||||
|
ExtraHeaders null.String `db:"registry_webhook_extra_headers"`
|
||||||
|
LatestExecutionResult null.String `db:"registry_webhook_latest_execution_result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebhookDao struct {
|
||||||
|
db *sqlx.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebhookDao) Create(ctx context.Context, webhook *types.Webhook) error {
|
||||||
|
const sqlQuery = `
|
||||||
|
INSERT INTO registry_webhooks (
|
||||||
|
registry_webhook_registry_id
|
||||||
|
,registry_webhook_space_id
|
||||||
|
,registry_webhook_created_by
|
||||||
|
,registry_webhook_created
|
||||||
|
,registry_webhook_updated
|
||||||
|
,registry_webhook_identifier
|
||||||
|
,registry_webhook_name
|
||||||
|
,registry_webhook_description
|
||||||
|
,registry_webhook_url
|
||||||
|
,registry_webhook_secret_identifier
|
||||||
|
,registry_webhook_secret_space_id
|
||||||
|
,registry_webhook_enabled
|
||||||
|
,registry_webhook_internal
|
||||||
|
,registry_webhook_insecure
|
||||||
|
,registry_webhook_triggers
|
||||||
|
,registry_webhook_latest_execution_result
|
||||||
|
,registry_webhook_extra_headers
|
||||||
|
,registry_webhook_scope
|
||||||
|
) values (
|
||||||
|
:registry_webhook_registry_id
|
||||||
|
,:registry_webhook_space_id
|
||||||
|
,:registry_webhook_created_by
|
||||||
|
,:registry_webhook_created
|
||||||
|
,:registry_webhook_updated
|
||||||
|
,:registry_webhook_identifier
|
||||||
|
,:registry_webhook_name
|
||||||
|
,:registry_webhook_description
|
||||||
|
,:registry_webhook_url
|
||||||
|
,:registry_webhook_secret_identifier
|
||||||
|
,:registry_webhook_secret_space_id
|
||||||
|
,:registry_webhook_enabled
|
||||||
|
,:registry_webhook_internal
|
||||||
|
,:registry_webhook_insecure
|
||||||
|
,:registry_webhook_triggers
|
||||||
|
,:registry_webhook_latest_execution_result
|
||||||
|
,:registry_webhook_extra_headers
|
||||||
|
,:registry_webhook_scope
|
||||||
|
) RETURNING registry_webhook_id`
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, w.db)
|
||||||
|
|
||||||
|
dbwebhook, err := mapToWebhookDB(webhook)
|
||||||
|
dbwebhook.Created = webhook.CreatedAt.UnixMilli()
|
||||||
|
dbwebhook.Updated = webhook.UpdatedAt.UnixMilli()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to map registry webhook to internal db type: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
query, arg, err := db.BindNamed(sqlQuery, dbwebhook)
|
||||||
|
if err != nil {
|
||||||
|
return database.ProcessSQLErrorf(ctx, err, "Failed to registry bind webhook object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.QueryRowContext(ctx, query, arg...).Scan(&webhook.ID); err != nil {
|
||||||
|
return database.ProcessSQLErrorf(ctx, err, "Insert query failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebhookDao) GetByRegistryAndIdentifier(
|
||||||
|
ctx context.Context,
|
||||||
|
registryID int64,
|
||||||
|
webhookIdentifier string,
|
||||||
|
) (*types.Webhook, error) {
|
||||||
|
query := database.Builder.Select(registryWebhooksFields...).
|
||||||
|
From("registry_webhooks").
|
||||||
|
Where("registry_webhook_registry_id = ? AND registry_webhook_identifier = ?", registryID, webhookIdentifier)
|
||||||
|
|
||||||
|
sqlQuery, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, w.db)
|
||||||
|
|
||||||
|
dst := new(webhookDB)
|
||||||
|
if err = db.GetContext(ctx, dst, sqlQuery, args...); err != nil {
|
||||||
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to get webhook detail")
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapToWebhook(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebhookDao) ListByRegistry(
|
||||||
|
ctx context.Context,
|
||||||
|
sortByField string,
|
||||||
|
sortByOrder string,
|
||||||
|
limit int,
|
||||||
|
offset int,
|
||||||
|
search string,
|
||||||
|
registryID int64,
|
||||||
|
) (*[]types.Webhook, error) {
|
||||||
|
query := database.Builder.Select(registryWebhooksFields...).
|
||||||
|
From("registry_webhooks").
|
||||||
|
Where("registry_webhook_registry_id = ?", registryID)
|
||||||
|
|
||||||
|
if search != "" {
|
||||||
|
query = query.Where("registry_webhook_name LIKE ?", "%"+search+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
validSortFields := map[string]string{
|
||||||
|
"name": "registry_webhook_name",
|
||||||
|
}
|
||||||
|
validSortByField := validSortFields[sortByField]
|
||||||
|
if validSortByField != "" {
|
||||||
|
query = query.OrderBy(fmt.Sprintf("%s %s", validSortByField, sortByOrder))
|
||||||
|
}
|
||||||
|
query = query.Limit(uint64(limit)).Offset(uint64(offset))
|
||||||
|
|
||||||
|
sqlQuery, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, w.db)
|
||||||
|
|
||||||
|
var dst []*webhookDB
|
||||||
|
if err = db.SelectContext(ctx, &dst, sqlQuery, args...); err != nil {
|
||||||
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to list webhooks details")
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapToWebhooksList(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebhookDao) CountAllByRegistry(
|
||||||
|
ctx context.Context,
|
||||||
|
registryID int64,
|
||||||
|
search string,
|
||||||
|
) (int64, error) {
|
||||||
|
stmt := database.Builder.Select("COUNT(*)").
|
||||||
|
From("registry_webhooks").
|
||||||
|
Where("registry_webhook_registry_id = ?", registryID)
|
||||||
|
|
||||||
|
if !commons.IsEmpty(search) {
|
||||||
|
stmt = stmt.Where("registry_webhook_name LIKE ?", "%"+search+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlQuery, args, err := stmt.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return -1, errors.Wrap(err, "Failed to convert query to sql")
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, w.db)
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
err = db.QueryRowContext(ctx, sqlQuery, args...).Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, database.ProcessSQLErrorf(ctx, err, "Failed executing count query")
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebhookDao) Update(ctx context.Context, webhook *types.Webhook) error {
|
||||||
|
var sqlQuery = " UPDATE registry_webhooks SET " +
|
||||||
|
util.GetSetDBKeys(webhookDB{},
|
||||||
|
"registry_webhook_identifier",
|
||||||
|
"registry_webhook_registry_id",
|
||||||
|
"registry_webhook_created",
|
||||||
|
"registry_webhook_created_by",
|
||||||
|
"registry_webhook_version",
|
||||||
|
"registry_webhook_internal") +
|
||||||
|
", registry_webhook_version = registry_webhook_version + 1" +
|
||||||
|
" WHERE registry_webhook_identifier = :registry_webhook_identifier" +
|
||||||
|
" AND registry_webhook_registry_id = :registry_webhook_registry_id"
|
||||||
|
|
||||||
|
dbWebhook, err := mapToWebhookDB(webhook)
|
||||||
|
dbWebhook.Updated = webhook.UpdatedAt.UnixMilli()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dbWebhook.Updated = time.Now().UnixMilli()
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, w.db)
|
||||||
|
|
||||||
|
query, arg, err := db.BindNamed(sqlQuery, dbWebhook)
|
||||||
|
if err != nil {
|
||||||
|
return database.ProcessSQLErrorf(ctx, err, "Failed to bind registry webhook object")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := db.ExecContext(ctx, query, arg...)
|
||||||
|
if err != nil {
|
||||||
|
return database.ProcessSQLErrorf(ctx, err, "Failed to update registry webhook")
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return database.ProcessSQLErrorf(ctx, err, "Failed to get number of updated rows")
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return gitnessstore.ErrVersionConflict
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebhookDao) DeleteByRegistryAndIdentifier(
|
||||||
|
ctx context.Context,
|
||||||
|
registryID int64,
|
||||||
|
webhookIdentifier string,
|
||||||
|
) error {
|
||||||
|
sqlQuery := database.Builder.Delete("registry_webhooks").
|
||||||
|
Where("registry_webhook_identifier = ? AND registry_webhook_registry_id = ?", webhookIdentifier, registryID)
|
||||||
|
|
||||||
|
query, args, err := sqlQuery.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to convert purge registry_webhooks query to sql: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, w.db)
|
||||||
|
|
||||||
|
_, err = db.ExecContext(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return database.ProcessSQLErrorf(ctx, err, "the delete registry_webhooks query failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapToWebhookDB(webhook *types.Webhook) (*webhookDB, error) {
|
||||||
|
if webhook.CreatedAt.IsZero() {
|
||||||
|
webhook.CreatedAt = time.Now()
|
||||||
|
}
|
||||||
|
webhook.UpdatedAt = time.Now()
|
||||||
|
dBwebhook := &webhookDB{
|
||||||
|
ID: webhook.ID,
|
||||||
|
Version: webhook.Version,
|
||||||
|
CreatedBy: webhook.CreatedBy,
|
||||||
|
Identifier: webhook.Identifier,
|
||||||
|
Scope: webhook.Scope,
|
||||||
|
Name: webhook.Name,
|
||||||
|
Description: webhook.Description,
|
||||||
|
URL: webhook.URL,
|
||||||
|
SecretIdentifier: util.GetEmptySQLString(webhook.SecretIdentifier),
|
||||||
|
SecretSpaceID: util.GetEmptySQLInt32(webhook.SecretSpaceID),
|
||||||
|
Enabled: webhook.Enabled,
|
||||||
|
Insecure: webhook.Insecure,
|
||||||
|
Internal: webhook.Internal,
|
||||||
|
Triggers: triggersToString(webhook.Triggers),
|
||||||
|
ExtraHeaders: null.StringFrom(structListToString(webhook.ExtraHeaders)),
|
||||||
|
LatestExecutionResult: null.StringFromPtr((*string)(webhook.LatestExecutionResult)),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch webhook.ParentType {
|
||||||
|
case enum.WebhookParentRegistry:
|
||||||
|
dBwebhook.RegistryID = null.IntFrom(webhook.ParentID)
|
||||||
|
case enum.WebhookParentSpace:
|
||||||
|
dBwebhook.SpaceID = null.IntFrom(webhook.ParentID)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("webhook parent type %q is not supported", webhook.ParentType)
|
||||||
|
}
|
||||||
|
return dBwebhook, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapToWebhook(webhookDB *webhookDB) (*types.Webhook, error) {
|
||||||
|
webhook := &types.Webhook{
|
||||||
|
ID: webhookDB.ID,
|
||||||
|
Version: webhookDB.Version,
|
||||||
|
CreatedBy: webhookDB.CreatedBy,
|
||||||
|
CreatedAt: time.UnixMilli(webhookDB.Created),
|
||||||
|
UpdatedAt: time.UnixMilli(webhookDB.Updated),
|
||||||
|
Scope: webhookDB.Scope,
|
||||||
|
Identifier: webhookDB.Identifier,
|
||||||
|
Name: webhookDB.Name,
|
||||||
|
Description: webhookDB.Description,
|
||||||
|
URL: webhookDB.URL,
|
||||||
|
Enabled: webhookDB.Enabled,
|
||||||
|
Internal: webhookDB.Internal,
|
||||||
|
Insecure: webhookDB.Insecure,
|
||||||
|
Triggers: triggersFromString(webhookDB.Triggers),
|
||||||
|
ExtraHeaders: stringToStructList(webhookDB.ExtraHeaders.String),
|
||||||
|
LatestExecutionResult: (*artifact.WebhookExecResult)(webhookDB.LatestExecutionResult.Ptr()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if webhookDB.SecretIdentifier.Valid {
|
||||||
|
webhook.SecretIdentifier = webhookDB.SecretIdentifier.String
|
||||||
|
}
|
||||||
|
if webhookDB.SecretSpaceID.Valid {
|
||||||
|
webhook.SecretSpaceID = int(webhookDB.SecretSpaceID.Int32)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case webhookDB.RegistryID.Valid && webhookDB.SpaceID.Valid:
|
||||||
|
return nil, fmt.Errorf("both registryID and spaceID are set for hook %d", webhookDB.ID)
|
||||||
|
case webhookDB.RegistryID.Valid:
|
||||||
|
webhook.ParentType = enum.WebhookParentRegistry
|
||||||
|
webhook.ParentID = webhookDB.RegistryID.Int64
|
||||||
|
case webhookDB.SpaceID.Valid:
|
||||||
|
webhook.ParentType = enum.WebhookParentSpace
|
||||||
|
webhook.ParentID = webhookDB.SpaceID.Int64
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("neither registryID nor spaceID are set for hook %d", webhookDB.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhook, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func triggersToString(triggers []artifact.Trigger) string {
|
||||||
|
rawTriggers := make([]string, len(triggers))
|
||||||
|
for i := range triggers {
|
||||||
|
rawTriggers[i] = string(triggers[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(rawTriggers, triggersSeparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func triggersFromString(triggersString string) []artifact.Trigger {
|
||||||
|
if triggersString == "" {
|
||||||
|
return []artifact.Trigger{}
|
||||||
|
}
|
||||||
|
|
||||||
|
rawTriggers := strings.Split(triggersString, triggersSeparator)
|
||||||
|
triggers := make([]artifact.Trigger, len(rawTriggers))
|
||||||
|
for i, rawTrigger := range rawTriggers {
|
||||||
|
triggers[i] = artifact.Trigger(rawTrigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
return triggers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a list of ExtraHeaders structs to a JSON string.
|
||||||
|
func structListToString(headers []artifact.ExtraHeader) string {
|
||||||
|
jsonData, err := json.Marshal(headers)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(jsonData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a JSON string back to a list of ExtraHeaders structs.
|
||||||
|
func stringToStructList(jsonStr string) []artifact.ExtraHeader {
|
||||||
|
var headers []artifact.ExtraHeader
|
||||||
|
err := json.Unmarshal([]byte(jsonStr), &headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapToWebhooksList(
|
||||||
|
dst []*webhookDB,
|
||||||
|
) (*[]types.Webhook, error) {
|
||||||
|
webhooks := make([]types.Webhook, 0, len(dst))
|
||||||
|
for _, d := range dst {
|
||||||
|
webhook, err := mapToWebhook(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
webhooks = append(webhooks, *webhook)
|
||||||
|
}
|
||||||
|
return &webhooks, nil
|
||||||
|
}
|
@ -71,6 +71,10 @@ func ProvideManifestDao(sqlDB *sqlx.DB, mtRepository store.MediaTypesRepository)
|
|||||||
return NewManifestDao(sqlDB, mtRepository)
|
return NewManifestDao(sqlDB, mtRepository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ProvideWebhookDao(sqlDB *sqlx.DB) store.WebhooksRepository {
|
||||||
|
return NewWebhookDao(sqlDB)
|
||||||
|
}
|
||||||
|
|
||||||
func ProvideManifestRefDao(db *sqlx.DB) store.ManifestReferenceRepository {
|
func ProvideManifestRefDao(db *sqlx.DB) store.ManifestReferenceRepository {
|
||||||
return NewManifestReferenceDao(db)
|
return NewManifestReferenceDao(db)
|
||||||
}
|
}
|
||||||
@ -113,4 +117,5 @@ var WireSet = wire.NewSet(
|
|||||||
ProvideBandwidthStatDao,
|
ProvideBandwidthStatDao,
|
||||||
ProvideNodeDao,
|
ProvideNodeDao,
|
||||||
ProvideGenericBlobDao,
|
ProvideGenericBlobDao,
|
||||||
|
ProvideWebhookDao,
|
||||||
)
|
)
|
||||||
|
33
registry/types/enum/common.go
Normal file
33
registry/types/enum/common.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// 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 enum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/exp/constraints"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
func toInterfaceSlice[T interface{}](vals []T) []interface{} {
|
||||||
|
res := make([]interface{}, len(vals))
|
||||||
|
for i := range vals {
|
||||||
|
res[i] = vals[i]
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortEnum[T constraints.Ordered](slice []T) []T {
|
||||||
|
slices.Sort(slice)
|
||||||
|
return slice
|
||||||
|
}
|
33
registry/types/enum/webhook.go
Normal file
33
registry/types/enum/webhook.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// 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 enum
|
||||||
|
|
||||||
|
// RegistryWebhookParent defines different types of parents of a webhook.
|
||||||
|
type RegistryWebhookParent string
|
||||||
|
|
||||||
|
func (RegistryWebhookParent) Enum() []interface{} { return toInterfaceSlice(webhookParents) }
|
||||||
|
|
||||||
|
const (
|
||||||
|
// WebhookParentRegistry describes a registry as webhook owner.
|
||||||
|
WebhookParentRegistry RegistryWebhookParent = "registry"
|
||||||
|
|
||||||
|
// WebhookParentSpace describes a space as webhook owner.
|
||||||
|
WebhookParentSpace RegistryWebhookParent = "space"
|
||||||
|
)
|
||||||
|
|
||||||
|
var webhookParents = sortEnum([]RegistryWebhookParent{
|
||||||
|
WebhookParentRegistry,
|
||||||
|
WebhookParentSpace,
|
||||||
|
})
|
46
registry/types/webhook.go
Normal file
46
registry/types/webhook.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// 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 types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
|
||||||
|
"github.com/harness/gitness/registry/types/enum"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Webhook DTO object.
|
||||||
|
type Webhook struct {
|
||||||
|
ID int64
|
||||||
|
Version int64
|
||||||
|
ParentType enum.RegistryWebhookParent
|
||||||
|
ParentID int64
|
||||||
|
CreatedBy int64
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
Scope int64
|
||||||
|
Identifier string
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
URL string
|
||||||
|
SecretIdentifier string
|
||||||
|
SecretSpaceID int
|
||||||
|
Enabled bool
|
||||||
|
Insecure bool
|
||||||
|
Internal bool
|
||||||
|
ExtraHeaders []artifact.ExtraHeader
|
||||||
|
Triggers []artifact.Trigger
|
||||||
|
LatestExecutionResult *artifact.WebhookExecResult
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user