Skip to content

Commit

Permalink
Merge pull request #18 from Nullify-Platform/add-Type-to-distinguish-…
Browse files Browse the repository at this point in the history
…gitlab-DiffNote-and-DiscussionNote

Add type to distinguish gitlab diff note and discussion note
  • Loading branch information
jonathanlam authored Jan 20, 2025
2 parents 4d07e59 + 7ab63f4 commit 3221bfa
Show file tree
Hide file tree
Showing 8 changed files with 565 additions and 15 deletions.
46 changes: 43 additions & 3 deletions azuredevops/azuredevops.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import (

// parse errors
var (
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
ErrParsingPayload = errors.New("error parsing payload")
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
ErrParsingPayload = errors.New("error parsing payload")
ErrBasicAuthVerificationFailed = errors.New("basic auth verification failed")
)

// Event defines an Azure DevOps server hook event type
Expand All @@ -30,13 +31,38 @@ const (
GitPullRequestCommentEventType Event = "ms.vss-code.git-pullrequest-comment-event"
)

// Option is a configuration option for the webhook
type Option func(*Webhook) error

// Options is a namespace var for configuration options
var Options = WebhookOptions{}

// WebhookOptions is a namespace for configuration option methods
type WebhookOptions struct{}

// BasicAuth verifies payload using basic auth
func (WebhookOptions) BasicAuth(username, password string) Option {
return func(hook *Webhook) error {
hook.username = username
hook.password = password
return nil
}
}

// Webhook instance contains all methods needed to process events
type Webhook struct {
username string
password string
}

// New creates and returns a WebHook instance
func New() (*Webhook, error) {
func New(options ...Option) (*Webhook, error) {
hook := new(Webhook)
for _, opt := range options {
if err := opt(hook); err != nil {
return nil, errors.New("Error applying Option")
}
}
return hook, nil
}

Expand All @@ -47,6 +73,10 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error)
_ = r.Body.Close()
}()

if !hook.verifyBasicAuth(r) {
return nil, ErrBasicAuthVerificationFailed
}

if r.Method != http.MethodPost {
return nil, ErrInvalidHTTPMethod
}
Expand Down Expand Up @@ -83,3 +113,13 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error)
return nil, fmt.Errorf("unknown event %s", pl.EventType)
}
}

func (hook Webhook) verifyBasicAuth(r *http.Request) bool {
// skip validation if username or password was not provided
if hook.username == "" && hook.password == "" {
return true
}
username, password, ok := r.BasicAuth()

return ok && username == hook.username && password == hook.password
}
66 changes: 66 additions & 0 deletions azuredevops/azuredevops_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package azuredevops

import (
"bytes"
"fmt"
"github.com/stretchr/testify/assert"
"log"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -117,3 +120,66 @@ func TestWebhooks(t *testing.T) {
})
}
}

func TestParseBasicAuth(t *testing.T) {
const validUser = "validUser"
const validPass = "pass123"
tests := []struct {
name string
webhookUser string
webhookPass string
reqUser string
reqPass string
expectedErr error
}{
{
name: "valid basic auth",
webhookUser: validUser,
webhookPass: validPass,
reqUser: validUser,
reqPass: validPass,
expectedErr: fmt.Errorf("unknown event "), // no event passed, so this is expected
},
{
name: "no basic auth provided",
expectedErr: fmt.Errorf("unknown event "), // no event passed, so this is expected
},
{
name: "invalid basic auth",
webhookUser: validUser,
webhookPass: validPass,
reqUser: "fakeUser",
reqPass: "fakePass",
expectedErr: ErrBasicAuthVerificationFailed,
},
}

for _, tt := range tests {
h := Webhook{
username: tt.webhookUser,
password: tt.webhookPass,
}
body := []byte(`{}`)
r, err := http.NewRequest(http.MethodPost, "", bytes.NewBuffer(body))
assert.NoError(t, err)
r.SetBasicAuth(tt.reqUser, tt.reqPass)

p, err := h.Parse(r)

assert.Equal(t, err, tt.expectedErr)
assert.Nil(t, p)
}
}

func TestBasicAuth(t *testing.T) {
const user = "user"
const pass = "pass123"

opt := Options.BasicAuth(user, pass)
h := &Webhook{}
err := opt(h)

assert.NoError(t, err)
assert.Equal(t, h.username, user)
assert.Equal(t, h.password, pass)
}
5 changes: 5 additions & 0 deletions github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const (
WorkflowJobEvent Event = "workflow_job"
WorkflowRunEvent Event = "workflow_run"
GitHubAppAuthorizationEvent Event = "github_app_authorization"
CodeScanningAlertEvent Event = "code_scanning_alert"
)

// EventSubtype defines a GitHub Hook Event subtype
Expand Down Expand Up @@ -353,6 +354,10 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error)
var pl GitHubAppAuthorizationPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case CodeScanningAlertEvent:
var pl CodeScanningAlertPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
default:
return nil, fmt.Errorf("unknown event %s", gitHubEvent)
}
Expand Down
9 changes: 9 additions & 0 deletions github/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,15 @@ func TestWebhooks(t *testing.T) {
"X-Github-Event": []string{"github_app_authorization"},
},
},
{
name: "CodeScanningAlertEvent",
event: CodeScanningAlertEvent,
typ: CodeScanningAlertPayload{},
filename: "../testdata/github/code_scanning_alert.json",
headers: http.Header{
"X-Github-Event": []string{"code_scanning_alert"},
},
},
}

for _, tt := range tests {
Expand Down
Loading

0 comments on commit 3221bfa

Please sign in to comment.