better path validation
This commit is contained in:
parent
2e04ebf470
commit
8ccd8e6586
|
@ -31,26 +31,42 @@ defmodule BallsPDS.Ecto.Schema.Object do
|
||||||
:path,
|
:path,
|
||||||
:public
|
:public
|
||||||
])
|
])
|
||||||
|> validate_format(:path, ~r/^[^<>:"\\|\?\*\0]+$/, message: "Invalid characters")
|
|> validate_path(:path)
|
||||||
|> validate_format(:path, ~r/^\/$|^\/.*[^\/]$/,
|
|
||||||
message: "Must have leading slash but no trailing slash"
|
|
||||||
)
|
|
||||||
|> validate_format(:path, ~r/(?<!\/)\/{1}(?!\/)/, message: "Multiple sequential slashes")
|
|
||||||
|> validate_format(
|
|> validate_format(
|
||||||
:content_type,
|
:content_type,
|
||||||
~r/^(application|audio|font|image|message|model|multipart|text|video)\/[\w\-\+\.]+(?:;\s*charset=[\w\-]+)?$/i,
|
~r/^(application|audio|font|image|message|model|multipart|text|video)\/[\w\-\+\.]+(?:;\s*charset=[\w\-]+)?$/i,
|
||||||
allow_nil: true
|
allow_nil: true
|
||||||
)
|
)
|
||||||
|> validate_format(:activitypub_type, ~r/[A-Z][a-zA-Z0-9]*/, 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}$/,
|
|> validate_format(:storage_key, ~r/^[0-9a-f]+$/,
|
||||||
allow_nil: true,
|
allow_nil: true,
|
||||||
message: "Invalid 256-bit hexadecimal string"
|
message: "Invalid hexadecimal string"
|
||||||
)
|
)
|
||||||
|> validate_inclusion(:public, [true, false])
|
|> validate_inclusion(:public, [true, false])
|
||||||
|> validate_number(:total_items, greater_than: -1, allow_nil: true)
|
|> validate_number(:total_items, greater_than: -1, allow_nil: true)
|
||||||
|> unique_constraint(:path)
|
|> unique_constraint(:path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp validate_path(changeset, field) do
|
||||||
|
validate_change(changeset, field, fn _, path ->
|
||||||
|
case BallsPDS.Util.Util.is_valid_path?(path) do
|
||||||
|
:ok -> []
|
||||||
|
|
||||||
|
{:error, :invalid_char} ->
|
||||||
|
[{field, "Invalid characters"}]
|
||||||
|
|
||||||
|
{:error, :trailing_or_no_starting_slash} ->
|
||||||
|
[{field, "Trailing slash, or no starting slash"}]
|
||||||
|
|
||||||
|
{:error, :sequential_slashes} ->
|
||||||
|
[{field, "Sequential slashes"}]
|
||||||
|
|
||||||
|
{:error, :relative_path} ->
|
||||||
|
[{field, "Relative path"}]
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
def get_by_path(path) when is_binary(path) do
|
def get_by_path(path) when is_binary(path) do
|
||||||
query =
|
query =
|
||||||
from(o in __MODULE__,
|
from(o in __MODULE__,
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
defmodule BallsPDS.Util.Util do
|
||||||
|
@valid_path_chars_regex ~r/^[^<>:"\\|\?\*\0\s]+$/
|
||||||
|
@starting_trailing_slashes_regex ~r/^\/$|^\/.*[^\/]$/
|
||||||
|
@sequential_slashes_regex ~r/(?<!\/)\/{1}(?!\/)/
|
||||||
|
@relative_path_regex ~r{^(?!.*(/\./|/\.\./)).*$}
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
A valid path inside the PDS.
|
||||||
|
"""
|
||||||
|
def is_valid_path?(path) when is_binary(path) do
|
||||||
|
with {:invalid_char, false} <- {:invalid_char, Regex.match?(@valid_path_chars_regex, path)},
|
||||||
|
{:trailing_or_no_starting_slash, false} <-
|
||||||
|
{:trailing_or_no_starting_slash, Regex.match?(@starting_trailing_slashes_regex, path)},
|
||||||
|
{:sequential_slashes, false} <-
|
||||||
|
{:sequential_slashes, Regex.match?(@sequential_slashes_regex, path)},
|
||||||
|
{:relative_path, false} <- {:relative_path, Regex.match?(@relative_path_regex, path)} do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{error, _} -> {:error, error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Every AP ID in an AP object should validate against this function.
|
||||||
|
"""
|
||||||
|
def is_valid_personal_ap_id(id) when is_binary(id) do
|
||||||
|
owner = Application.get_env(:balls_pds, :owner_ap_id)
|
||||||
|
service = Application.get_env(:balls_pds, :did_service)
|
||||||
|
prefix = "#{owner}?service=#{URI.encode(service)}&relativeRef="
|
||||||
|
|
||||||
|
with {:prefix, ^prefix <> relative_ref} <- {:prefix, id},
|
||||||
|
{:decode, relative_ref} <- {:decode, URI.decode(relative_ref)},
|
||||||
|
{:valid, :ok} <- {:valid, is_valid_path?(relative_ref)} do
|
||||||
|
true
|
||||||
|
else
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue