79 lines
3.0 KiB
Go
79 lines
3.0 KiB
Go
package gitlab
|
|
|
|
import (
|
|
"context"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func TestReviewWatchMutationGuardHidesCrossWorkspaceWatch(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
store := newTestStore(t)
|
|
watch := &ReviewWatch{
|
|
WorkspaceID: "workspace-a", WorkflowID: "wf", WorkflowStepID: "step",
|
|
AgentProfileID: "agent", ExecutorProfileID: "executor", Enabled: true,
|
|
}
|
|
if err := store.CreateReviewWatch(context.Background(), watch); err != nil {
|
|
t.Fatalf("create watch: %v", err)
|
|
}
|
|
svc := NewService("", nil, "none", nil, newTestLogger(t))
|
|
svc.SetStore(store)
|
|
controller := NewController(svc, newTestLogger(t))
|
|
recorder := httptest.NewRecorder()
|
|
ctx, _ := gin.CreateTestContext(recorder)
|
|
ctx.Request = httptest.NewRequest("PATCH", "/api/v1/gitlab/watches/review/"+watch.ID+"?workspace_id=workspace-b", nil)
|
|
ctx.Params = gin.Params{{Key: "id", Value: watch.ID}}
|
|
|
|
if controller.requireReviewWatchInWorkspace(ctx, watch.ID) {
|
|
t.Fatal("cross-workspace watch unexpectedly authorized")
|
|
}
|
|
if recorder.Code != 404 {
|
|
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestWatchDeleteGuardsAllowOwnedTombstoneRetries(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
store := newTestStore(t)
|
|
review := &ReviewWatch{WorkspaceID: "workspace-a", WorkflowID: "wf", WorkflowStepID: "step", AgentProfileID: "agent", ExecutorProfileID: "executor", Enabled: true}
|
|
issue := &IssueWatch{WorkspaceID: "workspace-a", WorkflowID: "wf", WorkflowStepID: "step", AgentProfileID: "agent", ExecutorProfileID: "executor", Enabled: true}
|
|
if err := store.CreateReviewWatch(t.Context(), review); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := store.CreateIssueWatch(t.Context(), issue); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := store.BeginReviewWatchDelete(t.Context(), review.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := store.BeginIssueWatchDelete(t.Context(), issue.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
service := NewService("", nil, AuthMethodNone, nil, newTestLogger(t))
|
|
service.SetStore(store)
|
|
controller := NewController(service, newTestLogger(t))
|
|
|
|
for _, test := range []struct {
|
|
name string
|
|
id string
|
|
guard func(*gin.Context, string) bool
|
|
}{{"review", review.ID, controller.requireReviewWatchDeleteInWorkspace}, {"issue", issue.ID, controller.requireIssueWatchDeleteInWorkspace}} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
recorder := httptest.NewRecorder()
|
|
ctx, _ := gin.CreateTestContext(recorder)
|
|
ctx.Request = httptest.NewRequest("DELETE", "/?workspace_id=workspace-a", nil)
|
|
if !test.guard(ctx, test.id) {
|
|
t.Fatalf("owned tombstone retry rejected: status=%d body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
foreignRecorder := httptest.NewRecorder()
|
|
foreign, _ := gin.CreateTestContext(foreignRecorder)
|
|
foreign.Request = httptest.NewRequest("DELETE", "/?workspace_id=workspace-b", nil)
|
|
if test.guard(foreign, test.id) || foreignRecorder.Code != 404 {
|
|
t.Fatalf("foreign tombstone disclosed: status=%d body=%s", foreignRecorder.Code, foreignRecorder.Body.String())
|
|
}
|
|
})
|
|
}
|
|
}
|