| package notification |
|
|
| import ( |
| "errors" |
| "fmt" |
|
|
| "github.com/openmeterio/openmeter/pkg/models" |
| "github.com/openmeterio/openmeter/pkg/pagination" |
| "github.com/openmeterio/openmeter/pkg/sortx" |
| ) |
|
|
| var ( |
| _ models.Validator = (*Rule)(nil) |
| _ models.CustomValidator[Rule] = (*Rule)(nil) |
| ) |
|
|
| type Rule struct { |
| models.NamespacedID |
| models.ManagedModel |
| models.Annotations |
| models.Metadata |
|
|
| |
| Type EventType `json:"type"` |
| |
| Name string `json:"name"` |
| |
| Disabled bool `json:"disabled"` |
| |
| Config RuleConfig `json:"config"` |
| |
| Channels []Channel `json:"channels"` |
| } |
|
|
| func (r Rule) ValidateWith(validators ...models.ValidatorFunc[Rule]) error { |
| return models.Validate(r, validators...) |
| } |
|
|
| func (r Rule) Validate() error { |
| var errs []error |
|
|
| if err := r.NamespacedID.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| if r.Name == "" { |
| errs = append(errs, errors.New("name is required")) |
| } |
|
|
| if err := r.Type.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| if err := r.Config.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| var ( |
| _ models.Validator = (*RuleConfigMeta)(nil) |
| _ models.CustomValidator[RuleConfigMeta] = (*RuleConfigMeta)(nil) |
| ) |
|
|
| type RuleConfigMeta struct { |
| Type EventType `json:"type"` |
| } |
|
|
| func (m RuleConfigMeta) ValidateWith(validators ...models.ValidatorFunc[RuleConfigMeta]) error { |
| return models.Validate(m, validators...) |
| } |
|
|
| func (m RuleConfigMeta) Validate() error { |
| return m.Type.Validate() |
| } |
|
|
| var ( |
| _ models.Validator = (*RuleConfig)(nil) |
| _ models.CustomValidator[RuleConfig] = (*RuleConfig)(nil) |
| ) |
|
|
| |
| type RuleConfig struct { |
| RuleConfigMeta |
|
|
| |
| BalanceThreshold *BalanceThresholdRuleConfig `json:"balanceThreshold,omitempty"` |
| EntitlementReset *EntitlementResetRuleConfig `json:"entitlementReset,omitempty"` |
|
|
| |
| Invoice *InvoiceRuleConfig `json:"invoice,omitempty"` |
| } |
|
|
| func (c RuleConfig) ValidateWith(validators ...models.ValidatorFunc[RuleConfig]) error { |
| return models.Validate(c, validators...) |
| } |
|
|
| |
| func (c RuleConfig) Validate() error { |
| switch c.Type { |
| case EventTypeBalanceThreshold: |
| if c.BalanceThreshold == nil { |
| return models.NewGenericValidationError(errors.New("missing balance threshold rule config")) |
| } |
|
|
| return c.BalanceThreshold.Validate() |
| case EventTypeEntitlementReset: |
| if c.EntitlementReset == nil { |
| return models.NewGenericValidationError(errors.New("missing entitlement reset rule config")) |
| } |
|
|
| return c.EntitlementReset.Validate() |
| case EventTypeInvoiceCreated, EventTypeInvoiceUpdated: |
| if c.Invoice == nil { |
| return models.NewGenericValidationError(errors.New("missing invoice rule config")) |
| } |
|
|
| return c.Invoice.Validate() |
| default: |
| return models.NewGenericValidationError(fmt.Errorf("unknown rule type: %s", c.Type)) |
| } |
| } |
|
|
| var ( |
| _ models.Validator = (*ListRulesInput)(nil) |
| _ models.CustomValidator[ListRulesInput] = (*ListRulesInput)(nil) |
| ) |
|
|
| type ListRulesInput struct { |
| pagination.Page |
|
|
| Namespaces []string |
| Rules []string |
| IncludeDisabled bool |
| Types []EventType |
| Channels []string |
|
|
| OrderBy OrderBy |
| Order sortx.Order |
| } |
|
|
| func (i ListRulesInput) ValidateWith(validators ...models.ValidatorFunc[ListRulesInput]) error { |
| return models.Validate(i, validators...) |
| } |
|
|
| func (i ListRulesInput) Validate() error { |
| return nil |
| } |
|
|
| type ListRulesResult = pagination.Result[Rule] |
|
|
| var ( |
| _ models.Validator = (*CreateRuleInput)(nil) |
| _ models.CustomValidator[CreateRuleInput] = (*CreateRuleInput)(nil) |
| ) |
|
|
| type CreateRuleInput struct { |
| models.NamespacedModel |
|
|
| |
| Type EventType |
| |
| Name string |
| |
| Disabled bool |
| |
| Config RuleConfig |
| |
| Channels []string |
| |
| Metadata models.Metadata |
| |
| Annotations models.Annotations |
| } |
|
|
| func (i CreateRuleInput) ValidateWith(validators ...models.ValidatorFunc[CreateRuleInput]) error { |
| return models.Validate(i, validators...) |
| } |
|
|
| const MaxChannelsPerRule = 5 |
|
|
| func (i CreateRuleInput) Validate() error { |
| var errs []error |
|
|
| if i.Namespace == "" { |
| errs = append(errs, errors.New("namespace is required")) |
| } |
|
|
| if err := i.Type.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| if i.Name == "" { |
| errs = append(errs, errors.New("rule name is required")) |
| } |
|
|
| if err := i.Config.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| if len(i.Channels) == 0 { |
| errs = append(errs, errors.New("at least one channel is required")) |
| } |
|
|
| if len(i.Channels) > MaxChannelsPerRule { |
| errs = append(errs, fmt.Errorf("too many channels: %d > %d", len(i.Channels), MaxChannelsPerRule)) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| var ( |
| _ models.Validator = (*UpdateRuleInput)(nil) |
| _ models.CustomValidator[UpdateRuleInput] = (*UpdateRuleInput)(nil) |
| ) |
|
|
| type UpdateRuleInput struct { |
| models.NamespacedID |
|
|
| |
| Type EventType |
| |
| Name string |
| |
| Disabled bool |
| |
| Config RuleConfig |
| |
| Channels []string |
| |
| Metadata models.Metadata |
| |
| Annotations models.Annotations |
| } |
|
|
| func (i UpdateRuleInput) ValidateWith(validators ...models.ValidatorFunc[UpdateRuleInput]) error { |
| return models.Validate(i, validators...) |
| } |
|
|
| func (i UpdateRuleInput) Validate() error { |
| var errs []error |
|
|
| if i.Namespace == "" { |
| errs = append(errs, errors.New("namespace is required")) |
| } |
|
|
| if i.ID == "" { |
| errs = append(errs, errors.New("id is required")) |
| } |
|
|
| if err := i.Type.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| if i.Name == "" { |
| errs = append(errs, errors.New("rule name is required")) |
| } |
|
|
| if err := i.Config.Validate(); err != nil { |
| errs = append(errs, err) |
| } |
|
|
| if len(i.Channels) == 0 { |
| errs = append(errs, errors.New("at least one channel is required")) |
| } |
|
|
| if len(i.Channels) > MaxChannelsPerRule { |
| errs = append(errs, fmt.Errorf("too many channels: %d > %d", len(i.Channels), MaxChannelsPerRule)) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| var ( |
| _ models.Validator = (*GetRuleInput)(nil) |
| _ models.CustomValidator[GetRuleInput] = (*GetRuleInput)(nil) |
| ) |
|
|
| type GetRuleInput models.NamespacedID |
|
|
| func (i GetRuleInput) ValidateWith(validators ...models.ValidatorFunc[GetRuleInput]) error { |
| return models.Validate(i, validators...) |
| } |
|
|
| func (i GetRuleInput) Validate() error { |
| var errs []error |
|
|
| if i.Namespace == "" { |
| errs = append(errs, errors.New("namespace is required")) |
| } |
|
|
| if i.ID == "" { |
| errs = append(errs, errors.New("id is required")) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| var ( |
| _ models.Validator = (*DeleteRuleInput)(nil) |
| _ models.CustomValidator[DeleteRuleInput] = (*DeleteRuleInput)(nil) |
| ) |
|
|
| type DeleteRuleInput = GetRuleInput |
|
|