defmodule GitGud.Repositories.Repository do
use Ecto.Schema
import Ecto.Changeset
alias GitGud.Accounts.User
alias GitGud.Organizations.Organization
@valid_visibilities ~w(public internal private)
@valid_interaction_policies ~w(public followers approved)
@name_format ~r/\A[a-zA-Z0-9][a-zA-Z0-9._-]{0,99}\z/
schema "repositories" do
field :name, :string
field :description, :string
field :default_branch, :string, default: "main"
field :visibility, :string, default: "private"
field :interaction_policy, :string, default: "public"
field :disk_path, :string
field :pushed_at, :utc_datetime
field :size_kb, :integer, default: 0
field :archived, :boolean, default: false
# SHA-256 of the current runner registration token, if any.
# Regenerating the token replaces the hash, invalidating the old
# token immediately.
field :runner_reg_token_hash, :binary
belongs_to :owner, User
belongs_to :organization, Organization
belongs_to :parent_repository, __MODULE__
timestamps(type: :utc_datetime)
end
def fork?(%__MODULE__{parent_repository_id: id}), do: not is_nil(id)
@doc """
Changeset for creating a repo. `disk_path` is set programmatically by
the context, never via user input — same security pattern as `user_id`.
"""
def create_changeset(repo, attrs) do
repo
|> cast(attrs, [:name, :description, :default_branch, :visibility])
|> validate_required([:name])
|> validate_format(:name, @name_format,
message:
"must start with alphanumeric and contain only letters, numbers, dots, dashes, underscores"
)
|> validate_inclusion(:visibility, @valid_visibilities)
|> validate_length(:default_branch, max: 100)
|> validate_length(:description, max: 1000)
|> unique_constraint(:name, name: :repositories_user_owner_id_name_index)
|> unique_constraint(:name, name: :repositories_org_id_name_index)
end
def update_changeset(repo, attrs) do
repo
|> cast(attrs, [
:description,
:default_branch,
:visibility,
:archived,
:interaction_policy
])
|> validate_inclusion(:visibility, @valid_visibilities)
|> validate_inclusion(:interaction_policy, @valid_interaction_policies)
|> validate_length(:default_branch, max: 100)
|> validate_length(:description, max: 1000)
end
def valid_interaction_policies, do: @valid_interaction_policies
end
2.4 KiB · text
5af55d9