feat: refactor status check to create abstraction (#902)

This commit is contained in:
Abhinav Singh 2023-12-15 07:13:13 +00:00 committed by Harness
parent 528ed2252a
commit 05af8b777b
5 changed files with 95 additions and 33 deletions

View File

@ -41,7 +41,9 @@ var regexpCheckUID = "^[0-9a-zA-Z-_.$]{1,127}$"
var matcherCheckUID = regexp.MustCompile(regexpCheckUID)
// Validate validates and sanitizes the ReportInput data.
func (in *ReportInput) Validate() error {
func (in *ReportInput) Validate(
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, session *auth.Session) error, session *auth.Session,
) error {
if in.CheckUID == "" {
return usererror.BadRequest("Status check UID is missing")
}
@ -55,44 +57,20 @@ func (in *ReportInput) Validate() error {
return usererror.BadRequest("Invalid value provided for status check status")
}
payloadKind, ok := in.Payload.Kind.Sanitize()
validatorFn, ok := sanitizers[in.Payload.Kind]
if !ok {
return usererror.BadRequest("Invalid value provided for the payload type")
return usererror.BadRequest("Invalid value provided for the payload kind")
}
in.Payload.Kind = payloadKind
switch in.Payload.Kind {
case enum.CheckPayloadKindEmpty:
// the default payload kind (empty) does not support the payload data: clear it here
in.Payload.Version = ""
in.Payload.Data = []byte("{}")
if in.Link == "" { // the link is mandatory as there is nothing in the payload
return usererror.BadRequest("Link is missing")
}
case enum.CheckPayloadKindRaw, enum.CheckPayloadKindMarkdown:
// the text payload kinds (raw and markdown) do not support the version
if in.Payload.Version != "" {
return usererror.BadRequestf("Payload version must be empty for the payload kind '%s'",
in.Payload.Kind)
}
payloadDataJSON, err := sanitizeJSONPayload(in.Payload.Data, &types.CheckPayloadText{})
if err != nil {
return err
}
in.Payload.Data = payloadDataJSON
case enum.CheckPayloadKindPipeline:
return usererror.BadRequest("Kind cannot be pipeline for external checks")
// Validate and sanitize the input data based on version; Require a link... and similar operations.
if err := validatorFn(in, session); err != nil {
return err
}
return nil
}
func sanitizeJSONPayload(source json.RawMessage, data any) (json.RawMessage, error) {
func SanitizeJSONPayload(source json.RawMessage, data any) (json.RawMessage, error) {
if len(source) == 0 {
return json.Marshal(data) // marshal the empty object
}
@ -136,7 +114,7 @@ func (c *Controller) Report(
return nil, fmt.Errorf("failed to acquire access access to repo: %w", err)
}
if errValidate := in.Validate(); errValidate != nil {
if errValidate := in.Validate(c.sanitizers, session); errValidate != nil {
return nil, errValidate
}

View File

@ -35,6 +35,7 @@ type Controller struct {
repoStore store.RepoStore
checkStore store.CheckStore
git git.Interface
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error
}
func NewController(
@ -43,6 +44,7 @@ func NewController(
repoStore store.RepoStore,
checkStore store.CheckStore,
git git.Interface,
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error,
) *Controller {
return &Controller{
tx: tx,
@ -50,6 +52,7 @@ func NewController(
repoStore: repoStore,
checkStore: checkStore,
git: git,
sanitizers: sanitizers,
}
}

View File

@ -0,0 +1,75 @@
// 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 check
import (
"github.com/harness/gitness/app/api/usererror"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
func ProvideCheckSanitizers() map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error {
registeredCheckSanitizers := make(map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error)
registeredCheckSanitizers[enum.CheckPayloadKindEmpty] = createEmptyPayloadSanitizer()
registeredCheckSanitizers[enum.CheckPayloadKindRaw] = createRawPayloadSanitizer()
// Markdown and Raw are the same.
registeredCheckSanitizers[enum.CheckPayloadKindMarkdown] = registeredCheckSanitizers[enum.CheckPayloadKindRaw]
registeredCheckSanitizers[enum.CheckPayloadKindPipeline] = createPipelinePayloadSanitizer()
return registeredCheckSanitizers
}
func createEmptyPayloadSanitizer() func(in *ReportInput, s *auth.Session) error {
return func(in *ReportInput, s *auth.Session) error {
// the default payload kind (empty) does not support the payload data: clear it here
in.Payload.Version = ""
in.Payload.Data = []byte("{}")
if in.Link == "" { // the link is mandatory as there is nothing in the payload
return usererror.BadRequest("Link is missing")
}
return nil
}
}
func createRawPayloadSanitizer() func(in *ReportInput, s *auth.Session) error {
return func(in *ReportInput, s *auth.Session) error {
// the text payload kinds (raw and markdown) do not support the version
if in.Payload.Version != "" {
return usererror.BadRequestf("Payload version must be empty for the payload kind '%s'",
in.Payload.Kind)
}
payloadDataJSON, err := SanitizeJSONPayload(in.Payload.Data, &types.CheckPayloadText{})
if err != nil {
return err
}
in.Payload.Data = payloadDataJSON
return nil
}
}
func createPipelinePayloadSanitizer() func(in *ReportInput, s *auth.Session) error {
return func(in *ReportInput, s *auth.Session) error {
return usererror.BadRequest("Kind cannot be pipeline for external checks")
}
}

View File

@ -15,16 +15,19 @@
package check
import (
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/git"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types/enum"
"github.com/google/wire"
)
// WireSet provides a wire set for this package.
var WireSet = wire.NewSet(
ProvideCheckSanitizers,
ProvideController,
)
@ -34,6 +37,7 @@ func ProvideController(
repoStore store.RepoStore,
checkStore store.CheckStore,
rpcClient git.Interface,
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error,
) *Controller {
return NewController(
tx,
@ -41,5 +45,6 @@ func ProvideController(
repoStore,
checkStore,
rpcClient,
sanitizers,
)
}

View File

@ -252,7 +252,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, gitInterface, pullReqStore, provider, protectionManager)
serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore)
principalController := principal.ProvideController(principalStore)
checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface)
v := check2.ProvideCheckSanitizers()
checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v)
systemController := system.NewController(principalStore, config)
blobConfig, err := server.ProvideBlobStoreConfig(config)
if err != nil {