defmodule GitGud.Moderation.Ban do
use Ecto.Schema
import Ecto.Changeset
alias GitGud.Accounts.User
alias GitGud.Organizations.Organization
alias GitGud.Repositories.Repository
schema "moderation_bans" do
field :reason, :string
field :expires_at, :utc_datetime
field :lifted_at, :utc_datetime
belongs_to :organization, Organization
belongs_to :repository, Repository
belongs_to :banned_user, User
belongs_to :banned_by, User
belongs_to :lifted_by, User
timestamps(type: :utc_datetime)
end
def changeset(ban, attrs) do
ban
|> cast(attrs, [
:organization_id,
:repository_id,
:banned_user_id,
:banned_by_id,
:reason,
:expires_at
])
|> validate_required([:banned_user_id])
|> validate_one_scope()
|> validate_length(:reason, max: 500)
|> validate_future_expiry()
|> unique_constraint(:banned_user_id,
name: :moderation_bans_active_org_index,
message: "is already banned from this organization"
)
|> unique_constraint(:banned_user_id,
name: :moderation_bans_active_repo_index,
message: "is already banned from this repository"
)
|> check_constraint(:organization_id,
name: :moderation_bans_one_scope,
message: "must name exactly one of an organization or a repository"
)
end
defp validate_one_scope(changeset) do
org = get_field(changeset, :organization_id)
repo = get_field(changeset, :repository_id)
case {org, repo} do
{nil, nil} ->
add_error(changeset, :organization_id, "a ban needs a scope")
{o, r} when not is_nil(o) and not is_nil(r) ->
add_error(changeset, :organization_id, "a ban has one scope")
_ ->
changeset
end
end
# An expiry in the past would be a ban that never applies, which is
# more likely a mistake than an intention.
defp validate_future_expiry(changeset) do
case get_field(changeset, :expires_at) do
nil ->
changeset
at ->
if DateTime.compare(at, DateTime.utc_now()) == :gt,
do: changeset,
else: add_error(changeset, :expires_at, "must be in the future")
end
end
def lift_changeset(ban, %User{id: uid}) do
change(ban, lifted_at: DateTime.utc_now(:second), lifted_by_id: uid)
end
@doc "Whether this ban is in force right now."
def active?(%__MODULE__{lifted_at: lifted}) when not is_nil(lifted), do: false
def active?(%__MODULE__{expires_at: nil}), do: true
def active?(%__MODULE__{expires_at: at}),
do: DateTime.compare(at, DateTime.utc_now()) == :gt
end
neiam /gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Packages
⭐
Log in to mark this repository.
2.6 KiB · text
History
6280797