balls/lib/balls_pds/ecto/schema/object.ex

89 lines
2.3 KiB
Elixir
Raw Normal View History

2024-12-02 11:03:06 +00:00
defmodule BallsPDS.Ecto.Schema.Object do
use Ecto.Schema
import Ecto.Changeset
import Ecto.Query
alias BallsPDS.Ecto.Schema.ObjectReadAgent
alias BallsPDS.Repo
alias BallsPDS.Util.ACL
schema "objects" do
field(:path, :string)
field(:content_type, :string)
field(:activitypub_type, :string)
field(:storage_key, :string)
field(:public, :boolean, default: false)
field(:total_items, :integer)
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [
:path,
:content_type,
:activitypub_type,
:storage_key,
:public,
:total_items
])
|> validate_required([
:path,
:public
])
|> validate_format(:path, ~r/^[^<>:"\\|\?\*\0]+$/, message: "Invalid characters")
|> validate_format(:path, ~r/^\/$|^\/.*[^\/]$/,
message: "Must have leading slash but no trailing slash"
)
|> validate_format(:path, ~r/(?<!\/)\/{1}(?!\/)/, message: "Multiple sequential slashes")
|> validate_format(
:content_type,
~r/^(application|audio|font|image|message|model|multipart|text|video)\/[\w\-\+\.]+(?:;\s*charset=[\w\-]+)?$/i,
allow_nil: true
)
|> validate_format(:activitypub_type, ~r/[A-Z][a-zA-Z0-9]*/, allow_nil: true)
|> validate_format(:storage_key, ~r/^[0-9a-f]{64}$/,
allow_nil: true,
message: "Invalid 256-bit hexadecimal string"
)
|> validate_inclusion(:public, [true, false])
|> validate_number(:total_items, greater_than: -1, allow_nil: true)
|> unique_constraint(:path)
end
def get_by_path(path) when is_binary(path) do
query =
from(o in __MODULE__,
where: o.path == ^path
)
Repo.one(query)
end
def get_ap_id(object_id) do
from(o in __MODULE__,
where: o.id == ^object_id,
select: o.path
)
|> Repo.one()
|> case do
nil -> nil
path -> ACL.make_object_url(path)
end
end
def get_all_by_paths(paths) when is_list(paths) do
from(o in __MODULE__,
where: o.path in ^paths
)
|> Repo.all()
end
def is_authorized_read?(%__MODULE__{public: true}, _), do: true
def is_authorized_read?(%__MODULE__{}, nil), do: false
def is_authorized_read?(%__MODULE__{} = object, acl) when is_binary(acl),
do: ObjectReadAgent.is_authorized_read?(object, acl)
end