1.8 KiB · text History 6280797
defmodule GitGud.Repo.Migrations.CreateModerationBans do
use Ecto.Migration
# Stopping a local user from acting in one repo, or across every repo
# an org owns.
#
# Nothing here suspends an account instance-wide — that stays an
# instance-admin power. This is scoped so a repo or org admin can
# protect their own ground without reaching further than it.
def change do
create table(:moderation_bans) do
add :organization_id, references(:organizations, on_delete: :delete_all)
add :repository_id, references(:repositories, on_delete: :delete_all)
add :banned_user_id, references(:users, on_delete: :delete_all), null: false
add :banned_by_id, references(:users, on_delete: :nilify_all)
add :reason, :string
# Null means it lasts until someone lifts it.
add :expires_at, :utc_datetime
add :lifted_at, :utc_datetime
add :lifted_by_id, references(:users, on_delete: :nilify_all)
timestamps(type: :utc_datetime)
end
# Exactly one scope, never both and never neither.
create constraint(:moderation_bans, :moderation_bans_one_scope,
check: "(organization_id IS NULL) <> (repository_id IS NULL)"
)
# One live ban per person per scope; lifted ones are kept as record.
create unique_index(:moderation_bans, [:organization_id, :banned_user_id],
where: "lifted_at IS NULL AND organization_id IS NOT NULL",
name: :moderation_bans_active_org_index
)
create unique_index(:moderation_bans, [:repository_id, :banned_user_id],
where: "lifted_at IS NULL AND repository_id IS NOT NULL",
name: :moderation_bans_active_repo_index
)
# "Is this person banned here?" — checked on every write.
create index(:moderation_bans, [:banned_user_id, :lifted_at])
end
end