diff --git a/api/admin/triggers.go b/api/admin/triggers.go new file mode 100644 index 0000000..9f6162e --- /dev/null +++ b/api/admin/triggers.go @@ -0,0 +1,145 @@ +package admin + +// Enables you to manage webhook notification triggers for your Cloudinary product environment. +// +// https://cloudinary.com/documentation/notifications + +import ( + "context" + + "github.com/cloudinary/cloudinary-go/v2/api" +) + +const ( + triggersEndpoint api.EndPoint = "triggers" +) + +// Trigger represents a single webhook notification trigger. +type Trigger struct { + ID string `json:"id,omitempty"` + URI string `json:"uri,omitempty"` + EventType string `json:"event_type,omitempty"` + Additive bool `json:"additive"` + Filter map[string]any `json:"filter,omitempty"` + FilterLanguage string `json:"filter_language,omitempty"` + PayloadTemplate map[string]any `json:"payload_template,omitempty"` + AuthScheme string `json:"auth_scheme,omitempty"` + ProductEnvironmentID string `json:"product_environment_id,omitempty"` + URIType string `json:"uri_type,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// ListTriggersParams are the parameters for ListTriggers. +type ListTriggersParams struct{} + +// ListTriggersResult is the result of ListTriggers. +type ListTriggersResult struct { + Triggers []Trigger `json:"triggers"` + Error api.ErrorResp `json:"error,omitempty"` +} + +// ListTriggers lists all webhook notification triggers for the product environment. +func (a *API) ListTriggers(ctx context.Context, params ListTriggersParams) (*ListTriggersResult, error) { + res := &ListTriggersResult{} + _, err := a.get(ctx, triggersEndpoint, params, res) + return res, err +} + +// GetTriggerParams are the parameters for GetTrigger. +type GetTriggerParams struct { + TriggerID string `json:"-"` +} + +// GetTriggerResult is the result of GetTrigger. +type GetTriggerResult struct { + Trigger + Error api.ErrorResp `json:"error,omitempty"` +} + +// GetTrigger retrieves a single webhook notification trigger by its ID. +// Cloudinary does not expose a single-resource GET endpoint, so this is +// implemented as ListTriggers filtered to the matching ID. +func (a *API) GetTrigger(ctx context.Context, params GetTriggerParams) (*GetTriggerResult, error) { + list, err := a.ListTriggers(ctx, ListTriggersParams{}) + if err != nil { + return nil, err + } + if list.Error.Message != "" { + return &GetTriggerResult{Error: list.Error}, nil + } + for _, t := range list.Triggers { + if t.ID == params.TriggerID { + return &GetTriggerResult{Trigger: t}, nil + } + } + // Not found — return empty result with no error; caller checks ID == "". + return &GetTriggerResult{}, nil +} + +// CreateTriggerParams are the parameters for CreateTrigger. +type CreateTriggerParams struct { + URI string `json:"uri"` + EventType string `json:"event_type"` + Additive bool `json:"additive,omitempty"` + Filter map[string]any `json:"filter,omitempty"` + FilterLanguage string `json:"filter_language,omitempty"` + PayloadTemplate map[string]any `json:"payload_template,omitempty"` + AuthScheme string `json:"auth_scheme,omitempty"` +} + +// CreateTriggerResult is the result of CreateTrigger. +type CreateTriggerResult struct { + Trigger + Error api.ErrorResp `json:"error,omitempty"` +} + +// CreateTrigger creates a new webhook notification trigger. +func (a *API) CreateTrigger(ctx context.Context, params CreateTriggerParams) (*CreateTriggerResult, error) { + res := &CreateTriggerResult{} + _, err := a.post(ctx, triggersEndpoint, params, res) + return res, err +} + +// UpdateTriggerParams are the parameters for UpdateTrigger. +type UpdateTriggerParams struct { + TriggerID string `json:"-"` + URI string `json:"uri,omitempty"` + EventType string `json:"event_type,omitempty"` + Additive *bool `json:"additive,omitempty"` + Filter map[string]any `json:"filter,omitempty"` + FilterLanguage string `json:"filter_language,omitempty"` + PayloadTemplate map[string]any `json:"payload_template,omitempty"` + AuthScheme string `json:"auth_scheme,omitempty"` +} + +// UpdateTriggerResult is the result of UpdateTrigger. +type UpdateTriggerResult struct { + Trigger + Error api.ErrorResp `json:"error,omitempty"` +} + +// UpdateTrigger updates an existing webhook notification trigger. +func (a *API) UpdateTrigger(ctx context.Context, params UpdateTriggerParams) (*UpdateTriggerResult, error) { + res := &UpdateTriggerResult{} + _, err := a.put(ctx, api.BuildPath(triggersEndpoint, params.TriggerID), params, res) + return res, err +} + +// DeleteTriggerParams are the parameters for DeleteTrigger. +type DeleteTriggerParams struct { + TriggerID string `json:"-"` +} + +// DeleteTriggerResult is the result of DeleteTrigger. +type DeleteTriggerResult struct { + Message string `json:"message,omitempty"` + Error api.ErrorResp `json:"error,omitempty"` +} + +// DeleteTrigger deletes a webhook notification trigger by its ID. +func (a *API) DeleteTrigger(ctx context.Context, params DeleteTriggerParams) (*DeleteTriggerResult, error) { + res := &DeleteTriggerResult{} + _, err := a.delete(ctx, api.BuildPath(triggersEndpoint, params.TriggerID), params, res) + return res, err +} diff --git a/api/admin/triggers_test.go b/api/admin/triggers_test.go new file mode 100644 index 0000000..f22a89e --- /dev/null +++ b/api/admin/triggers_test.go @@ -0,0 +1,83 @@ +package admin_test + +import ( + "testing" + + "github.com/cloudinary/cloudinary-go/v2/api/admin" + "github.com/stretchr/testify/assert" +) + +const testTriggerURI = "https://example.com/000-go-trigger-test" + +var testTriggerID string + +func TestTriggers_CreateTrigger(t *testing.T) { + resp, err := adminAPI.CreateTrigger(ctx, admin.CreateTriggerParams{ + URI: testTriggerURI, + EventType: "upload", + }) + + if err != nil || resp.Error.Message != "" { + t.Error(resp, err) + return + } + + testTriggerID = resp.ID + assert.NotEmpty(t, testTriggerID) +} + +func TestTriggers_ListTriggers(t *testing.T) { + resp, err := adminAPI.ListTriggers(ctx, admin.ListTriggersParams{}) + + if err != nil || resp.Error.Message != "" { + t.Error(resp, err) + } +} + +func TestTriggers_GetTrigger(t *testing.T) { + if testTriggerID == "" { + t.Skip("create trigger test did not run or failed") + } + + resp, err := adminAPI.GetTrigger(ctx, admin.GetTriggerParams{ + TriggerID: testTriggerID, + }) + + if err != nil || resp.Error.Message != "" { + t.Error(resp, err) + return + } + + assert.Equal(t, testTriggerID, resp.ID) +} + +func TestTriggers_UpdateTrigger(t *testing.T) { + if testTriggerID == "" { + t.Skip("create trigger test did not run or failed") + } + + resp, err := adminAPI.UpdateTrigger(ctx, admin.UpdateTriggerParams{ + TriggerID: testTriggerID, + URI: testTriggerURI, + EventType: "upload", + AuthScheme: "default", + }) + + if err != nil || resp.Error.Message != "" { + t.Error(resp, err) + } +} + +func TestTriggers_DeleteTrigger(t *testing.T) { + if testTriggerID == "" { + t.Skip("create trigger test did not run or failed") + } + + resp, err := adminAPI.DeleteTrigger(ctx, admin.DeleteTriggerParams{ + TriggerID: testTriggerID, + }) + + if err != nil || resp.Error.Message != "" { + t.Error(resp, err) + } +}