89 lines
2.3 KiB
Elixir
89 lines
2.3 KiB
Elixir
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
|