diff --git a/apps/console/src/__generated__/core/WebhooksSettingsPageQuery.graphql.ts b/apps/console/src/__generated__/core/WebhooksSettingsPageQuery.graphql.ts index 1dba7e35a..595b77357 100644 --- a/apps/console/src/__generated__/core/WebhooksSettingsPageQuery.graphql.ts +++ b/apps/console/src/__generated__/core/WebhooksSettingsPageQuery.graphql.ts @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type WebhookEventType = "MEETING_CREATED" | "MEETING_DELETED" | "MEETING_UPDATED" | "USER_CREATED" | "USER_DELETED" | "USER_UPDATED" | "VENDOR_CREATED" | "VENDOR_DELETED" | "VENDOR_UPDATED"; +export type WebhookEventType = "MEETING_CREATED" | "MEETING_DELETED" | "MEETING_UPDATED" | "OBLIGATION_CREATED" | "OBLIGATION_DELETED" | "OBLIGATION_UPDATED" | "USER_CREATED" | "USER_DELETED" | "USER_UPDATED" | "VENDOR_CREATED" | "VENDOR_DELETED" | "VENDOR_UPDATED"; export type WebhooksSettingsPageQuery$variables = { organizationId: string; }; diff --git a/apps/console/src/__generated__/core/WebhooksSettingsPage_createMutation.graphql.ts b/apps/console/src/__generated__/core/WebhooksSettingsPage_createMutation.graphql.ts index d2df166ae..eb9b8b07b 100644 --- a/apps/console/src/__generated__/core/WebhooksSettingsPage_createMutation.graphql.ts +++ b/apps/console/src/__generated__/core/WebhooksSettingsPage_createMutation.graphql.ts @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type WebhookEventType = "MEETING_CREATED" | "MEETING_DELETED" | "MEETING_UPDATED" | "USER_CREATED" | "USER_DELETED" | "USER_UPDATED" | "VENDOR_CREATED" | "VENDOR_DELETED" | "VENDOR_UPDATED"; +export type WebhookEventType = "MEETING_CREATED" | "MEETING_DELETED" | "MEETING_UPDATED" | "OBLIGATION_CREATED" | "OBLIGATION_DELETED" | "OBLIGATION_UPDATED" | "USER_CREATED" | "USER_DELETED" | "USER_UPDATED" | "VENDOR_CREATED" | "VENDOR_DELETED" | "VENDOR_UPDATED"; export type CreateWebhookSubscriptionInput = { endpointUrl: string; organizationId: string; diff --git a/apps/console/src/__generated__/core/WebhooksSettingsPage_updateMutation.graphql.ts b/apps/console/src/__generated__/core/WebhooksSettingsPage_updateMutation.graphql.ts index 24cb7d3e9..f8f5284f0 100644 --- a/apps/console/src/__generated__/core/WebhooksSettingsPage_updateMutation.graphql.ts +++ b/apps/console/src/__generated__/core/WebhooksSettingsPage_updateMutation.graphql.ts @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type WebhookEventType = "MEETING_CREATED" | "MEETING_DELETED" | "MEETING_UPDATED" | "USER_CREATED" | "USER_DELETED" | "USER_UPDATED" | "VENDOR_CREATED" | "VENDOR_DELETED" | "VENDOR_UPDATED"; +export type WebhookEventType = "MEETING_CREATED" | "MEETING_DELETED" | "MEETING_UPDATED" | "OBLIGATION_CREATED" | "OBLIGATION_DELETED" | "OBLIGATION_UPDATED" | "USER_CREATED" | "USER_DELETED" | "USER_UPDATED" | "VENDOR_CREATED" | "VENDOR_DELETED" | "VENDOR_UPDATED"; export type UpdateWebhookSubscriptionInput = { endpointUrl?: string | null | undefined; id: string; diff --git a/apps/console/src/pages/organizations/settings/WebhooksSettingsPage.tsx b/apps/console/src/pages/organizations/settings/WebhooksSettingsPage.tsx index cfa1c31f7..0d0ecbbf8 100644 --- a/apps/console/src/pages/organizations/settings/WebhooksSettingsPage.tsx +++ b/apps/console/src/pages/organizations/settings/WebhooksSettingsPage.tsx @@ -150,6 +150,9 @@ const EVENT_TYPES = [ { value: "USER_CREATED", label: "user:created" }, { value: "USER_UPDATED", label: "user:updated" }, { value: "USER_DELETED", label: "user:deleted" }, + { value: "OBLIGATION_CREATED", label: "obligation:created" }, + { value: "OBLIGATION_UPDATED", label: "obligation:updated" }, + { value: "OBLIGATION_DELETED", label: "obligation:deleted" }, ] as const; type WebhookEventType = (typeof EVENT_TYPES)[number]["value"]; diff --git a/package-lock.json b/package-lock.json index 342e12fd0..682276eef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14347,6 +14347,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } diff --git a/pkg/coredata/migrations/20260227T120000Z.sql b/pkg/coredata/migrations/20260227T120000Z.sql new file mode 100644 index 000000000..e2ef11bdc --- /dev/null +++ b/pkg/coredata/migrations/20260227T120000Z.sql @@ -0,0 +1,3 @@ +ALTER TYPE webhook_event_type ADD VALUE 'obligation:created'; +ALTER TYPE webhook_event_type ADD VALUE 'obligation:updated'; +ALTER TYPE webhook_event_type ADD VALUE 'obligation:deleted'; diff --git a/pkg/coredata/webhook_event_type.go b/pkg/coredata/webhook_event_type.go index c90029a54..2b398b772 100644 --- a/pkg/coredata/webhook_event_type.go +++ b/pkg/coredata/webhook_event_type.go @@ -23,15 +23,18 @@ import ( type WebhookEventType string const ( - WebhookEventTypeMeetingCreated WebhookEventType = "meeting:created" - WebhookEventTypeMeetingUpdated WebhookEventType = "meeting:updated" - WebhookEventTypeMeetingDeleted WebhookEventType = "meeting:deleted" - WebhookEventTypeVendorCreated WebhookEventType = "vendor:created" - WebhookEventTypeVendorUpdated WebhookEventType = "vendor:updated" - WebhookEventTypeVendorDeleted WebhookEventType = "vendor:deleted" - WebhookEventTypeUserCreated WebhookEventType = "user:created" - WebhookEventTypeUserUpdated WebhookEventType = "user:updated" - WebhookEventTypeUserDeleted WebhookEventType = "user:deleted" + WebhookEventTypeMeetingCreated WebhookEventType = "meeting:created" + WebhookEventTypeMeetingUpdated WebhookEventType = "meeting:updated" + WebhookEventTypeMeetingDeleted WebhookEventType = "meeting:deleted" + WebhookEventTypeVendorCreated WebhookEventType = "vendor:created" + WebhookEventTypeVendorUpdated WebhookEventType = "vendor:updated" + WebhookEventTypeVendorDeleted WebhookEventType = "vendor:deleted" + WebhookEventTypeUserCreated WebhookEventType = "user:created" + WebhookEventTypeUserUpdated WebhookEventType = "user:updated" + WebhookEventTypeUserDeleted WebhookEventType = "user:deleted" + WebhookEventTypeObligationCreated WebhookEventType = "obligation:created" + WebhookEventTypeObligationUpdated WebhookEventType = "obligation:updated" + WebhookEventTypeObligationDeleted WebhookEventType = "obligation:deleted" ) func (w WebhookEventType) String() string { @@ -42,7 +45,8 @@ func (w WebhookEventType) IsValid() bool { switch w { case WebhookEventTypeMeetingCreated, WebhookEventTypeMeetingUpdated, WebhookEventTypeMeetingDeleted, WebhookEventTypeVendorCreated, WebhookEventTypeVendorUpdated, WebhookEventTypeVendorDeleted, - WebhookEventTypeUserCreated, WebhookEventTypeUserUpdated, WebhookEventTypeUserDeleted: + WebhookEventTypeUserCreated, WebhookEventTypeUserUpdated, WebhookEventTypeUserDeleted, + WebhookEventTypeObligationCreated, WebhookEventTypeObligationUpdated, WebhookEventTypeObligationDeleted: return true } return false diff --git a/pkg/probo/obligation_service.go b/pkg/probo/obligation_service.go index 6d1ed5a79..853800c42 100644 --- a/pkg/probo/obligation_service.go +++ b/pkg/probo/obligation_service.go @@ -24,6 +24,8 @@ import ( "go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/page" "go.probo.inc/probo/pkg/validator" + "go.probo.inc/probo/pkg/webhook" + webhooktypes "go.probo.inc/probo/pkg/webhook/types" ) type ObligationService struct { @@ -160,6 +162,10 @@ func (s *ObligationService) Create( return fmt.Errorf("cannot insert obligation: %w", err) } + if err := webhook.InsertData(ctx, conn, s.svc.scope, req.OrganizationID, coredata.WebhookEventTypeObligationCreated, webhooktypes.NewObligation(obligation)); err != nil { + return fmt.Errorf("cannot insert webhook event: %w", err) + } + return nil }, ) @@ -238,6 +244,10 @@ func (s *ObligationService) Update( return fmt.Errorf("cannot update obligation: %w", err) } + if err := webhook.InsertData(ctx, conn, s.svc.scope, obligation.OrganizationID, coredata.WebhookEventTypeObligationUpdated, webhooktypes.NewObligation(obligation)); err != nil { + return fmt.Errorf("cannot insert webhook event: %w", err) + } + return nil }, ) @@ -261,6 +271,10 @@ func (s *ObligationService) Delete( return fmt.Errorf("cannot load obligation: %w", err) } + if err := webhook.InsertData(ctx, conn, s.svc.scope, obligation.OrganizationID, coredata.WebhookEventTypeObligationDeleted, webhooktypes.NewObligation(obligation)); err != nil { + return fmt.Errorf("cannot insert webhook event: %w", err) + } + if err := obligation.Delete(ctx, conn, s.svc.scope); err != nil { return fmt.Errorf("cannot delete obligation: %w", err) } diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index d421d00a8..426eb86a2 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -2288,6 +2288,12 @@ enum WebhookEventType @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeUserUpdated") USER_DELETED @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeUserDeleted") + OBLIGATION_CREATED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeObligationCreated") + OBLIGATION_UPDATED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeObligationUpdated") + OBLIGATION_DELETED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeObligationDeleted") } type WebhookSubscription implements Node { diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 2b52e4ac9..c4e8be097 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -12988,6 +12988,18 @@ enum WebhookEventType @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeVendorUpdated") VENDOR_DELETED @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeVendorDeleted") + USER_CREATED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeUserCreated") + USER_UPDATED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeUserUpdated") + USER_DELETED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeUserDeleted") + OBLIGATION_CREATED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeObligationCreated") + OBLIGATION_UPDATED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeObligationUpdated") + OBLIGATION_DELETED + @goEnum(value: "go.probo.inc/probo/pkg/coredata.WebhookEventTypeObligationDeleted") } type WebhookSubscription implements Node { @@ -101896,20 +101908,32 @@ func (ec *executionContext) marshalNWebhookEventType2goᚗproboᚗincᚋproboᚋ var ( unmarshalNWebhookEventType2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐWebhookEventType = map[string]coredata.WebhookEventType{ - "MEETING_CREATED": coredata.WebhookEventTypeMeetingCreated, - "MEETING_UPDATED": coredata.WebhookEventTypeMeetingUpdated, - "MEETING_DELETED": coredata.WebhookEventTypeMeetingDeleted, - "VENDOR_CREATED": coredata.WebhookEventTypeVendorCreated, - "VENDOR_UPDATED": coredata.WebhookEventTypeVendorUpdated, - "VENDOR_DELETED": coredata.WebhookEventTypeVendorDeleted, + "MEETING_CREATED": coredata.WebhookEventTypeMeetingCreated, + "MEETING_UPDATED": coredata.WebhookEventTypeMeetingUpdated, + "MEETING_DELETED": coredata.WebhookEventTypeMeetingDeleted, + "VENDOR_CREATED": coredata.WebhookEventTypeVendorCreated, + "VENDOR_UPDATED": coredata.WebhookEventTypeVendorUpdated, + "VENDOR_DELETED": coredata.WebhookEventTypeVendorDeleted, + "USER_CREATED": coredata.WebhookEventTypeUserCreated, + "USER_UPDATED": coredata.WebhookEventTypeUserUpdated, + "USER_DELETED": coredata.WebhookEventTypeUserDeleted, + "OBLIGATION_CREATED": coredata.WebhookEventTypeObligationCreated, + "OBLIGATION_UPDATED": coredata.WebhookEventTypeObligationUpdated, + "OBLIGATION_DELETED": coredata.WebhookEventTypeObligationDeleted, } marshalNWebhookEventType2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐWebhookEventType = map[coredata.WebhookEventType]string{ - coredata.WebhookEventTypeMeetingCreated: "MEETING_CREATED", - coredata.WebhookEventTypeMeetingUpdated: "MEETING_UPDATED", - coredata.WebhookEventTypeMeetingDeleted: "MEETING_DELETED", - coredata.WebhookEventTypeVendorCreated: "VENDOR_CREATED", - coredata.WebhookEventTypeVendorUpdated: "VENDOR_UPDATED", - coredata.WebhookEventTypeVendorDeleted: "VENDOR_DELETED", + coredata.WebhookEventTypeMeetingCreated: "MEETING_CREATED", + coredata.WebhookEventTypeMeetingUpdated: "MEETING_UPDATED", + coredata.WebhookEventTypeMeetingDeleted: "MEETING_DELETED", + coredata.WebhookEventTypeVendorCreated: "VENDOR_CREATED", + coredata.WebhookEventTypeVendorUpdated: "VENDOR_UPDATED", + coredata.WebhookEventTypeVendorDeleted: "VENDOR_DELETED", + coredata.WebhookEventTypeUserCreated: "USER_CREATED", + coredata.WebhookEventTypeUserUpdated: "USER_UPDATED", + coredata.WebhookEventTypeUserDeleted: "USER_DELETED", + coredata.WebhookEventTypeObligationCreated: "OBLIGATION_CREATED", + coredata.WebhookEventTypeObligationUpdated: "OBLIGATION_UPDATED", + coredata.WebhookEventTypeObligationDeleted: "OBLIGATION_DELETED", } ) diff --git a/pkg/webhook/types/obligation.go b/pkg/webhook/types/obligation.go new file mode 100644 index 000000000..4e8f22953 --- /dev/null +++ b/pkg/webhook/types/obligation.go @@ -0,0 +1,58 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package types + +import ( + "time" + + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/gid" +) + +type Obligation struct { + ID gid.GID `json:"id"` + OrganizationID gid.GID `json:"organizationId"` + Area *string `json:"area"` + Source *string `json:"source"` + Requirement *string `json:"requirement"` + ActionsToBeImplemented *string `json:"actionsToBeImplemented"` + Regulator *string `json:"regulator"` + OwnerID gid.GID `json:"ownerId"` + LastReviewDate *time.Time `json:"lastReviewDate"` + DueDate *time.Time `json:"dueDate"` + Status coredata.ObligationStatus `json:"status"` + Type coredata.ObligationType `json:"type"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +func NewObligation(o *coredata.Obligation) *Obligation { + return &Obligation{ + ID: o.ID, + OrganizationID: o.OrganizationID, + Area: o.Area, + Source: o.Source, + Requirement: o.Requirement, + ActionsToBeImplemented: o.ActionsToBeImplemented, + Regulator: o.Regulator, + OwnerID: o.OwnerID, + LastReviewDate: o.LastReviewDate, + DueDate: o.DueDate, + Status: o.Status, + Type: o.Type, + CreatedAt: o.CreatedAt, + UpdatedAt: o.UpdatedAt, + } +}