1.8 KiB · text 5af55d9
defmodule GitGud.Webhooks.Webhook do
use Ecto.Schema
import Ecto.Changeset
alias GitGud.Organizations.Organization
alias GitGud.Repositories.Repository
alias GitGud.Webhooks.WebhookDelivery
# Events that can be subscribed to. Empty list means "all".
@known_events ~w(push issue issue_comment pull_request pull_request_comment workflow_run)
schema "webhooks" do
field :url, :string
field :secret, :binary, redact: true
field :content_type, :string, default: "application/json"
field :events, {:array, :string}, default: []
field :enabled, :boolean, default: true
field :insecure_ssl, :boolean, default: false
# A hook is owned by exactly one of these (DB check constraint
# `webhooks_one_owner` enforces the XOR). Repo hooks fire for their
# repo; org hooks fire for every repo the org owns.
belongs_to :repository, Repository
belongs_to :organization, Organization
has_many :deliveries, WebhookDelivery
timestamps(type: :utc_datetime)
end
def changeset(hook, attrs) do
hook
|> cast(attrs, [:url, :content_type, :events, :enabled, :insecure_ssl])
|> maybe_put_secret()
|> validate_required([:url, :secret])
|> validate_format(:url, ~r{^https?://}, message: "must be http(s)")
|> validate_length(:url, max: 500)
|> validate_subset(:events, @known_events)
|> validate_inclusion(:content_type, ~w(application/json application/x-www-form-urlencoded))
end
defp maybe_put_secret(cs) do
case get_field(cs, :secret) do
nil -> put_change(cs, :secret, :crypto.strong_rand_bytes(32))
_ -> cs
end
end
def known_events, do: @known_events
@doc "True if this hook is subscribed to `event`."
def listens_to?(%__MODULE__{events: []}, _event), do: true
def listens_to?(%__MODULE__{events: events}, event), do: event in events
end