Validators: Add a type for the datetime used in AP.
authorlain <lain@soykaf.club>
Thu, 5 Dec 2019 11:33:06 +0000 (12:33 +0100)
committerlain <lain@soykaf.club>
Thu, 5 Dec 2019 11:33:06 +0000 (12:33 +0100)
lib/pleroma/web/activity_pub/object_validators/note_validator.ex
lib/pleroma/web/activity_pub/object_validators/types/date_time.ex [new file with mode: 0644]
test/web/activity_pub/object_validators/types/date_time_test.exs [new file with mode: 0644]

index c660f30f0e3d9c1b8ff4cc3e0fbbc1e6f31033ba..eea15ce1cf8750fbafaa5fbdbc19380cc69550e6 100644 (file)
@@ -25,8 +25,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
     field(:actor, Types.ObjectID)
     field(:attributedTo, Types.ObjectID)
     field(:summary, :string)
-    # TODO: Write type
-    field(:published, :string)
+    field(:published, Types.DateTime)
     # TODO: Write type
     field(:emoji, :map, default: %{})
     field(:sensitive, :boolean, default: false)
diff --git a/lib/pleroma/web/activity_pub/object_validators/types/date_time.ex b/lib/pleroma/web/activity_pub/object_validators/types/date_time.ex
new file mode 100644 (file)
index 0000000..4f412fc
--- /dev/null
@@ -0,0 +1,34 @@
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime do
+  @moduledoc """
+  The AP standard defines the date fields in AP as xsd:DateTime. Elixir's
+  DateTime can't parse this, but it can parse the related iso8601. This
+  module punches the date until it looks like iso8601 and normalizes to
+  it.
+
+  DateTimes without a timezone offset are treated as UTC.
+
+  Reference: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published
+  """
+  use Ecto.Type
+
+  def type, do: :string
+
+  def cast(datetime) when is_binary(datetime) do
+    with {:ok, datetime, _} <- DateTime.from_iso8601(datetime) do
+      {:ok, DateTime.to_iso8601(datetime)}
+    else
+      {:error, :missing_offset} -> cast("#{datetime}Z")
+      _e -> :error
+    end
+  end
+
+  def cast(_), do: :error
+
+  def dump(data) do
+    {:ok, data}
+  end
+
+  def load(data) do
+    {:ok, data}
+  end
+end
diff --git a/test/web/activity_pub/object_validators/types/date_time_test.exs b/test/web/activity_pub/object_validators/types/date_time_test.exs
new file mode 100644 (file)
index 0000000..3e17a94
--- /dev/null
@@ -0,0 +1,32 @@
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTimeTest do
+  alias Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime
+  use Pleroma.DataCase
+
+  test "it validates an xsd:Datetime" do
+    valid_strings = [
+      "2004-04-12T13:20:00",
+      "2004-04-12T13:20:15.5",
+      "2004-04-12T13:20:00-05:00",
+      "2004-04-12T13:20:00Z"
+    ]
+
+    invalid_strings = [
+      "2004-04-12T13:00",
+      "2004-04-1213:20:00",
+      "99-04-12T13:00",
+      "2004-04-12"
+    ]
+
+    assert {:ok, "2004-04-01T12:00:00Z"} == DateTime.cast("2004-04-01T12:00:00Z")
+
+    Enum.each(valid_strings, fn date_time ->
+      result = DateTime.cast(date_time)
+      assert {:ok, _} = result
+    end)
+
+    Enum.each(invalid_strings, fn date_time ->
+      result = DateTime.cast(date_time)
+      assert :error == result
+    end)
+  end
+end