2.8 KiB · text 5af55d9
defmodule GitGud.Organizations.Organization do
use Ecto.Schema
import Ecto.Changeset
alias GitGud.Organizations.Membership
alias GitGud.Organizations.Team
@handle_format ~r/\A[a-z0-9][a-z0-9-]{0,59}\z/
@valid_visibilities ~w(public internal private)
schema "organizations" do
field :handle, :string
field :name, :string
field :description, :string
field :visibility, :string, default: "public"
# See `GitGud.Repositories.Repository.runner_reg_token_hash`.
field :runner_reg_token_hash, :binary
field :display_name, :string
field :bio, :string
field :url, :string
field :location, :string
field :company, :string
field :public_email, :string
field :timezone, :string
field :socials, :map, default: %{"items" => []}
has_many :memberships, Membership
has_many :teams, Team
timestamps(type: :utc_datetime)
end
def changeset(org, attrs) do
org
|> cast(attrs, [:handle, :name, :description, :visibility])
|> validate_required([:handle])
|> update_change(:handle, &String.downcase/1)
|> validate_format(:handle, @handle_format,
message: "lowercase letters, digits, dashes; must start alphanumeric"
)
|> validate_length(:name, max: 120)
|> validate_length(:description, max: 500)
|> validate_inclusion(:visibility, @valid_visibilities)
|> unique_constraint(:handle)
end
@doc "Settings-side changeset — visibility-only, leaves handle alone."
def visibility_changeset(org, attrs) do
org
|> cast(attrs, [:visibility])
|> validate_required([:visibility])
|> validate_inclusion(:visibility, @valid_visibilities)
end
@doc "Ordered visibility hierarchy. Higher index = less public."
@spec visibility_rank(String.t()) :: 0..2
def visibility_rank("public"), do: 0
def visibility_rank("internal"), do: 1
def visibility_rank("private"), do: 2
def visibility_rank(_), do: 2
def valid_visibilities, do: @valid_visibilities
@doc "Profile-only changeset; same shape as `User.profile_changeset/2`."
def profile_changeset(org, attrs) do
org
|> cast(attrs, [
:display_name,
:description,
:bio,
:url,
:location,
:company,
:public_email,
:timezone,
:socials
])
|> validate_length(:display_name, max: 120)
|> validate_length(:description, max: 500)
|> validate_length(:bio, max: 1_000)
|> validate_length(:url, max: 200)
|> validate_length(:location, max: 120)
|> validate_length(:company, max: 120)
|> validate_length(:public_email, max: 160)
|> validate_length(:timezone, max: 60)
end
def display(%__MODULE__{display_name: d}) when is_binary(d) and d != "", do: d
def display(%__MODULE__{name: n}) when is_binary(n) and n != "", do: n
def display(%__MODULE__{handle: h}) when is_binary(h), do: h
def display(_), do: "(unknown)"
end