From 7f311218803fdeadb3db425f3b1153855a394c56 Mon Sep 17 00:00:00 2001 From: Vincent Date: Thu, 2 May 2019 13:04:21 +0200 Subject: [PATCH] Simplify PageController --- config/config.exs | 2 +- .../controllers/activity_pub_controller.ex | 68 ---------------- .../controllers/fallback_controller.ex | 2 +- .../controllers/page_controller.ex | 72 +++++------------ .../views/activity_pub/object_view.ex | 39 --------- lib/mobilizon_web/views/error_view.ex | 4 + lib/mobilizon_web/views/page_view.ex | 79 +++++++++++++++++++ .../activity_pub_controller_test.exs | 7 +- 8 files changed, 109 insertions(+), 164 deletions(-) diff --git a/config/config.exs b/config/config.exs index 1f26daec3..c83cac04c 100644 --- a/config/config.exs +++ b/config/config.exs @@ -64,7 +64,7 @@ config :geolix, config :arc, storage: Arc.Storage.Local -config :phoenix, :format_encoders, json: Jason +config :phoenix, :format_encoders, json: Jason, "activity-json": Jason config :mobilizon, Mobilizon.Service.Geospatial.Nominatim, endpoint: diff --git a/lib/mobilizon_web/controllers/activity_pub_controller.ex b/lib/mobilizon_web/controllers/activity_pub_controller.ex index 4ffae9395..e0898745a 100644 --- a/lib/mobilizon_web/controllers/activity_pub_controller.ex +++ b/lib/mobilizon_web/controllers/activity_pub_controller.ex @@ -16,74 +16,6 @@ defmodule MobilizonWeb.ActivityPubController do action_fallback(:errors) - @doc """ - Renders an Actor ActivityPub's representation - """ - @spec actor(Plug.Conn.t(), String.t()) :: Plug.Conn.t() - def actor(conn, %{"name" => name}) do - with {status, %Actor{} = actor} when status in [:ok, :commit] <- - Actors.get_cached_local_actor_by_name(name) do - conn - |> put_resp_header("content-type", "application/activity+json") - |> json(ActorView.render("actor.json", %{actor: actor})) - else - {:ignore, _} -> - {:error, :not_found} - end - end - - @doc """ - Renders an Event ActivityPub's representation - """ - @spec event(Plug.Conn.t(), map()) :: Plug.Conn.t() - def event(conn, %{"uuid" => uuid}) do - with {status, %Event{} = event} when status in [:ok, :commit] <- - Events.get_cached_event_full_by_uuid(uuid), - true <- event.visibility in [:public, :unlisted] do - conn - |> put_resp_header("content-type", "application/activity+json") - |> json( - ObjectView.render( - "event.json", - %{ - event: - event - |> Utils.make_event_data() - } - ) - ) - else - {:ignore, _} -> - {:error, :not_found} - end - end - - @doc """ - Renders a Comment ActivityPub's representation - """ - @spec comment(Plug.Conn.t(), map()) :: Plug.Conn.t() - def comment(conn, %{"uuid" => uuid}) do - with {status, %Comment{} = comment} when status in [:ok, :commit] <- - Events.get_cached_comment_full_by_uuid(uuid), - true <- comment.visibility in [:public, :unlisted] do - conn - |> put_resp_header("content-type", "application/activity+json") - |> json( - ObjectView.render( - "comment.json", - %{ - comment: - comment - |> Utils.make_comment_data() - } - ) - ) - else - _ -> - {:error, :not_found} - end - end - def following(conn, %{"name" => name, "page" => page}) do with {page, ""} = Integer.parse(page), %Actor{} = actor <- Actors.get_local_actor_by_name_with_everything(name) do diff --git a/lib/mobilizon_web/controllers/fallback_controller.ex b/lib/mobilizon_web/controllers/fallback_controller.ex index ec74eadba..aea620e1b 100644 --- a/lib/mobilizon_web/controllers/fallback_controller.ex +++ b/lib/mobilizon_web/controllers/fallback_controller.ex @@ -10,6 +10,6 @@ defmodule MobilizonWeb.FallbackController do conn |> put_status(:not_found) |> put_view(MobilizonWeb.ErrorView) - |> render("404.html") + |> render(:"404") end end diff --git a/lib/mobilizon_web/controllers/page_controller.ex b/lib/mobilizon_web/controllers/page_controller.ex index 5bb761542..9c479edff 100644 --- a/lib/mobilizon_web/controllers/page_controller.ex +++ b/lib/mobilizon_web/controllers/page_controller.ex @@ -10,69 +10,35 @@ defmodule MobilizonWeb.PageController do action_fallback(MobilizonWeb.FallbackController) - def index(conn, _params) do - render(conn, "app.html") - end + def index(conn, _params), do: render(conn, :index) def actor(conn, %{"name" => name}) do - case get_format(conn) do - "html" -> - with {status, %Actor{} = actor} when status in [:ok, :commit] <- - Actors.get_cached_local_actor_by_name(name) do - render_with_meta(conn, actor) - else - _ -> {:error, :not_found} - end - - # "activity-json" matches "application/activity+json" inside our config - "activity-json" -> - MobilizonWeb.ActivityPubController.call(conn, :actor) - - _ -> - {:error, :not_found} - end + {status, actor} = Actors.get_cached_local_actor_by_name(name) + render_or_error(conn, &ok_status?/2, status, :actor, actor) end def event(conn, %{"uuid" => uuid}) do - case get_format(conn) do - "html" -> - with {status, %Event{} = event} when status in [:ok, :commit] <- - Events.get_cached_event_full_by_uuid(uuid), - true <- event.visibility in [:public, :unlisted] do - render_with_meta(conn, event) - else - _ -> {:error, :not_found} - end - - "activity-json" -> - MobilizonWeb.ActivityPubController.call(conn, :event) - - _ -> - {:error, :not_found} - end + {status, event} = Events.get_cached_event_full_by_uuid(uuid) + render_or_error(conn, &ok_status_and_is_visible?/2, status, :event, event) end def comment(conn, %{"uuid" => uuid}) do - case get_format(conn) do - "html" -> - with {status, %Comment{} = comment} when status in [:ok, :commit] <- - Events.get_cached_comment_full_by_uuid(uuid), - true <- comment.visibility in [:public, :unlisted] do - render_with_meta(conn, comment) - else - _ -> {:error, :not_found} - end + {status, comment} = Events.get_cached_comment_full_by_uuid(uuid) + render_or_error(conn, &ok_status_and_is_visible?/2, status, :comment, comment) + end - "activity-json" -> - MobilizonWeb.ActivityPubController.call(conn, :comment) - - _ -> - {:error, :not_found} + defp render_or_error(conn, check_fn, status, object_type, object) do + if check_fn.(status, object) do + render(conn, object_type, object: object) + else + {:error, :not_found} end end - # Inject OpenGraph information - defp render_with_meta(conn, object) do - render(conn, "app.html", object: object) - end + defp is_visible?(%{visibility: v}), do: v in [:public, :unlisted] + + defp ok_status?(status), do: status in [:ok, :commit] + defp ok_status?(status, _), do: ok_status?(status) + + defp ok_status_and_is_visible?(status, o), do: ok_status?(status) and is_visible?(o) end diff --git a/lib/mobilizon_web/views/activity_pub/object_view.ex b/lib/mobilizon_web/views/activity_pub/object_view.ex index 9e7de95b8..9a1da8fca 100644 --- a/lib/mobilizon_web/views/activity_pub/object_view.ex +++ b/lib/mobilizon_web/views/activity_pub/object_view.ex @@ -3,45 +3,6 @@ defmodule MobilizonWeb.ActivityPub.ObjectView do alias Mobilizon.Service.ActivityPub.Utils alias Mobilizon.Activity - def render("event.json", %{event: event}) do - {:ok, html, []} = Earmark.as_html(event["summary"]) - - event = %{ - "type" => "Event", - "attributedTo" => event["actor"], - "id" => event["id"], - "name" => event["title"], - "category" => event["category"], - "content" => html, - "source" => %{ - "content" => event["summary"], - "mediaType" => "text/markdown" - }, - "mediaType" => "text/html", - "published" => event["publish_at"], - "updated" => event["updated_at"] - } - - Map.merge(event, Utils.make_json_ld_header()) - end - - def render("comment.json", %{comment: comment}) do - comment = %{ - "actor" => comment["actor"], - "uuid" => comment["uuid"], - # The activity should have attributedTo, not the comment itself - # "attributedTo" => comment.attributed_to, - "type" => "Note", - "id" => comment["id"], - "content" => comment["content"], - "mediaType" => "text/html" - # "published" => Timex.format!(comment.inserted_at, "{ISO:Extended}"), - # "updated" => Timex.format!(comment.updated_at, "{ISO:Extended}") - } - - Map.merge(comment, Utils.make_json_ld_header()) - end - def render("activity.json", %{activity: %Activity{local: local, data: data} = activity}) do %{ "id" => data["id"], diff --git a/lib/mobilizon_web/views/error_view.ex b/lib/mobilizon_web/views/error_view.ex index c4d6b3ce4..3a252a8bf 100644 --- a/lib/mobilizon_web/views/error_view.ex +++ b/lib/mobilizon_web/views/error_view.ex @@ -8,6 +8,10 @@ defmodule MobilizonWeb.ErrorView do "Page not found" end + def render("404.json", _assigns) do + %{msg: "Resource not found"} + end + def render("invalid_request.json", _assigns) do %{errors: "Invalid request"} end diff --git a/lib/mobilizon_web/views/page_view.ex b/lib/mobilizon_web/views/page_view.ex index ea88b06af..0166680fd 100644 --- a/lib/mobilizon_web/views/page_view.ex +++ b/lib/mobilizon_web/views/page_view.ex @@ -3,4 +3,83 @@ defmodule MobilizonWeb.PageView do View for our webapp """ use MobilizonWeb, :view + alias Mobilizon.Actors.Actor + alias Mobilizon.Service.ActivityPub.Utils + + def render("actor.activity-json", %{conn: %{assigns: %{object: actor}}}) do + public_key = Mobilizon.Service.ActivityPub.Utils.pem_to_public_key_pem(actor.keys) + + %{ + "id" => Actor.build_url(actor.preferred_username, :page), + "type" => "Person", + "following" => Actor.build_url(actor.preferred_username, :following), + "followers" => Actor.build_url(actor.preferred_username, :followers), + "inbox" => Actor.build_url(actor.preferred_username, :inbox), + "outbox" => Actor.build_url(actor.preferred_username, :outbox), + "preferredUsername" => actor.preferred_username, + "name" => actor.name, + "summary" => actor.summary, + "url" => actor.url, + "manuallyApprovesFollowers" => actor.manually_approves_followers, + "publicKey" => %{ + "id" => "#{actor.url}#main-key", + "owner" => actor.url, + "publicKeyPem" => public_key + }, + # TODO : Make have actors have an uuid + # "uuid" => actor.uuid + "endpoints" => %{ + "sharedInbox" => actor.shared_inbox_url + } + # "icon" => %{ + # "type" => "Image", + # "url" => User.avatar_url(actor) + # }, + # "image" => %{ + # "type" => "Image", + # "url" => User.banner_url(actor) + # } + } + |> Map.merge(Utils.make_json_ld_header()) + end + + def render("event.activity-json", %{conn: %{assigns: %{object: event}}}) do + event = Utils.make_event_data(event) + {:ok, html, []} = Earmark.as_html(event["summary"]) + + %{ + "type" => "Event", + "attributedTo" => event["actor"], + "id" => event["id"], + "name" => event["title"], + "category" => event["category"], + "content" => html, + "source" => %{ + "content" => event["summary"], + "mediaType" => "text/markdown" + }, + "mediaType" => "text/html", + "published" => event["publish_at"], + "updated" => event["updated_at"] + } + |> Map.merge(Utils.make_json_ld_header()) + end + + def render("comment.activity-json", %{conn: %{assigns: %{object: comment}}}) do + comment = Utils.make_comment_data(comment) + + %{ + "actor" => comment["actor"], + "uuid" => comment["uuid"], + # The activity should have attributedTo, not the comment itself + # "attributedTo" => comment.attributed_to, + "type" => "Note", + "id" => comment["id"], + "content" => comment["content"], + "mediaType" => "text/html" + # "published" => Timex.format!(comment.inserted_at, "{ISO:Extended}"), + # "updated" => Timex.format!(comment.updated_at, "{ISO:Extended}") + } + |> Map.merge(Utils.make_json_ld_header()) + end end diff --git a/test/mobilizon_web/controllers/activity_pub_controller_test.exs b/test/mobilizon_web/controllers/activity_pub_controller_test.exs index b5217964c..3b0eef813 100644 --- a/test/mobilizon_web/controllers/activity_pub_controller_test.exs +++ b/test/mobilizon_web/controllers/activity_pub_controller_test.exs @@ -7,6 +7,7 @@ defmodule MobilizonWeb.ActivityPubControllerTest do use MobilizonWeb.ConnCase import Mobilizon.Factory alias MobilizonWeb.ActivityPub.{ActorView, ObjectView} + alias MobilizonWeb.PageView alias Mobilizon.Actors alias Mobilizon.Actors.Actor alias Mobilizon.Service.ActivityPub @@ -43,7 +44,7 @@ defmodule MobilizonWeb.ActivityPubControllerTest do |> get(Routes.page_url(Endpoint, :event, event.uuid)) assert json_response(conn, 200) == - ObjectView.render("event.json", %{event: event |> Utils.make_event_data()}) + PageView.render("event.activity-json", %{conn: %{assigns: %{object: event}}}) end test "it returns 404 for non-public events", %{conn: conn} do @@ -51,6 +52,7 @@ defmodule MobilizonWeb.ActivityPubControllerTest do conn = conn + |> put_req_header("accept", "application/activity+json") |> get(Routes.page_url(Endpoint, :event, event.uuid)) assert json_response(conn, 404) @@ -63,10 +65,11 @@ defmodule MobilizonWeb.ActivityPubControllerTest do conn = conn + |> put_req_header("accept", "application/activity+json") |> get(Routes.page_url(Endpoint, :comment, comment.uuid)) assert json_response(conn, 200) == - ObjectView.render("comment.json", %{comment: comment |> Utils.make_comment_data()}) + PageView.render("comment.activity-json", %{conn: %{assigns: %{object: comment}}}) end test "it returns 404 for non-public comments", %{conn: conn} do