diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/activity.ex | 4 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 4 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 14 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub_controller.ex | 12 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/mrf/reject_non_public.ex | 29 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 3 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 28 | ||||
| -rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 46 | ||||
| -rw-r--r-- | lib/pleroma/web/ostatus/ostatus_controller.ex | 112 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/controllers/util_controller.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 23 | ||||
| -rw-r--r-- | lib/pleroma/web/web_finger/web_finger.ex | 82 | ||||
| -rw-r--r-- | lib/pleroma/web/xml/xml.ex | 4 | 
15 files changed, 269 insertions, 111 deletions
| diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index c7502981e..dd6805125 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -72,8 +72,10 @@ defmodule Pleroma.Activity do      )    end -  def get_create_activity_by_object_ap_id(ap_id) do +  def get_create_activity_by_object_ap_id(ap_id) when is_binary(ap_id) do      create_activity_by_object_id_query([ap_id])      |> Repo.one()    end + +  def get_create_activity_by_object_ap_id(_), do: nil  end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index aecf96c36..00cac153d 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -174,7 +174,7 @@ defmodule Pleroma.User do      should_direct_follow =        cond do          # if the account is locked, don't pre-create the relationship -        user_info["locked"] == true -> +        user_info[:locked] == true ->            false          # if the users are blocking each other, we shouldn't even be here, but check for it anyway @@ -193,7 +193,7 @@ defmodule Pleroma.User do      if should_direct_follow do        follow(follower, followed)      else -      follower +      {:ok, follower}      end    end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index a5e42d9d0..43e96fe37 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -564,6 +564,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      end    end +  @quarantined_instances Keyword.get(@instance, :quarantined_instances, []) + +  def should_federate?(inbox, public) do +    if public do +      true +    else +      inbox_info = URI.parse(inbox) +      inbox_info.host not in @quarantined_instances +    end +  end +    def publish(actor, activity) do      followers =        if actor.follower_address in activity.recipients do @@ -573,6 +584,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do          []        end +    public = is_public?(activity) +      remote_inboxes =        (Pleroma.Web.Salmon.remote_users(activity) ++ followers)        |> Enum.filter(fn user -> User.ap_enabled?(user) end) @@ -580,6 +593,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do          (data["endpoints"] && data["endpoints"]["sharedInbox"]) || data["inbox"]        end)        |> Enum.uniq() +      |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)      {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)      json = Jason.encode!(data) diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index a6a9b99ef..d337532d0 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -15,6 +15,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do        conn        |> put_resp_header("content-type", "application/activity+json")        |> json(UserView.render("user.json", %{user: user})) +    else +      nil -> {:error, :not_found}      end    end @@ -27,9 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do        |> json(ObjectView.render("object.json", %{object: object}))      else        {:public?, false} -> -        conn -        |> put_status(404) -        |> json("Not found") +        {:error, :not_found}      end    end @@ -107,6 +107,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do      json(conn, "ok")    end +  def errors(conn, {:error, :not_found}) do +    conn +    |> put_status(404) +    |> json("Not found") +  end +    def errors(conn, _e) do      conn      |> put_status(500) diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex new file mode 100644 index 000000000..879cbe6de --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex @@ -0,0 +1,29 @@ +defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do +  alias Pleroma.User +  @behaviour Pleroma.Web.ActivityPub.MRF + +  @impl true +  def filter(object) do +    if object["type"] == "Create" do +      user = User.get_cached_by_ap_id(object["actor"]) +      public = "https://www.w3.org/ns/activitystreams#Public" + +      # Determine visibility +      visibility = +        cond do +          public in object["to"] -> "public" +          public in object["cc"] -> "unlisted" +          user.follower_address in object["to"] -> "followers" +          true -> "direct" +        end + +      case visibility do +        "public" -> {:ok, object} +        "unlisted" -> {:ok, object} +        _ -> {:reject, nil} +      end +    else +      {:ok, object} +    end +  end +end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 3c9377be9..75ba36729 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -252,11 +252,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do        {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)        banner = new_user_data[:info]["banner"] +      locked = new_user_data[:info]["locked"]        update_data =          new_user_data          |> Map.take([:name, :bio, :avatar]) -        |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner})) +        |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner, "locked" => locked}))        actor        |> User.upgrade_changeset(update_data) diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 9c9951371..30089f553 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -9,11 +9,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do    def get_by_id_or_ap_id(id) do      activity = Repo.get(Activity, id) || Activity.get_create_activity_by_object_ap_id(id) -    if activity.data["type"] == "Create" do -      activity -    else -      Activity.get_create_activity_by_object_ap_id(activity.data["object"]) -    end +    activity && +      if activity.data["type"] == "Create" do +        activity +      else +        Activity.get_create_activity_by_object_ap_id(activity.data["object"]) +      end    end    def get_replied_to_activity(id) when not is_nil(id) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 12f9b5f7c..0f7d4bb6d 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -10,6 +10,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do    import Ecto.Query    require Logger +  action_fallback(:errors) +    def create_app(conn, params) do      with cs <- App.register_changeset(%App{}, params) |> IO.inspect(),           {:ok, app} <- Repo.insert(cs) |> IO.inspect() do @@ -134,6 +136,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do        %{          "shortcode" => shortcode,          "static_url" => url, +        "visible_in_picker" => true,          "url" => url        }      end) @@ -244,7 +247,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do      end    end -  def dm_timeline(%{assigns: %{user: user}} = conn, params) do +  def dm_timeline(%{assigns: %{user: user}} = conn, _params) do      query =        ActivityPub.fetch_activities_query([user.ap_id], %{"type" => "Create", visibility: "direct"}) @@ -297,6 +300,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do      end    end +  def post_status(conn, %{"status" => "", "media_ids" => media_ids} = params) +      when length(media_ids) > 0 do +    params = +      params +      |> Map.put("status", ".") + +    post_status(conn, params) +  end +    def post_status(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do      params =        params @@ -327,27 +339,27 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do    end    def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do -    with {:ok, announce, _activity} = CommonAPI.repeat(ap_id_or_id, user) do +    with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user) do        render(conn, StatusView, "status.json", %{activity: announce, for: user, as: :activity})      end    end    def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do -    with {:ok, _, _, %{data: %{"id" => id}}} = CommonAPI.unrepeat(ap_id_or_id, user), +    with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do        render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})      end    end    def fav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do -    with {:ok, _fav, %{data: %{"id" => id}}} = CommonAPI.favorite(ap_id_or_id, user), +    with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user),           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do        render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})      end    end    def unfav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do -    with {:ok, _, _, %{data: %{"id" => id}}} = CommonAPI.unfavorite(ap_id_or_id, user), +    with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unfavorite(ap_id_or_id, user),           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do        render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})      end @@ -933,4 +945,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do          nil      end    end + +  def errors(conn, _) do +    conn +    |> put_status(500) +    |> json("Something went wrong") +  end  end diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 11dc1806f..3dd87d0ab 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -56,12 +56,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do    # TODO    # - proper scope handling    def token_exchange(conn, %{"grant_type" => "authorization_code"} = params) do -    with %App{} = app <- -           Repo.get_by( -             App, -             client_id: params["client_id"], -             client_secret: params["client_secret"] -           ), +    with %App{} = app <- get_app_from_request(conn, params),           fixed_token = fix_padding(params["code"]),           %Authorization{} = auth <-             Repo.get_by(Authorization, token: fixed_token, app_id: app.id), @@ -76,7 +71,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do        json(conn, response)      else -      _error -> json(conn, %{error: "Invalid credentials"}) +      _error -> +        put_status(conn, 400) +        |> json(%{error: "Invalid credentials"})      end    end @@ -86,12 +83,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do          conn,          %{"grant_type" => "password", "name" => name, "password" => password} = params        ) do -    with %App{} = app <- -           Repo.get_by( -             App, -             client_id: params["client_id"], -             client_secret: params["client_secret"] -           ), +    with %App{} = app <- get_app_from_request(conn, params),           %User{} = user <- User.get_cached_by_nickname(name),           true <- Pbkdf2.checkpw(password, user.password_hash),           {:ok, auth} <- Authorization.create_authorization(app, user), @@ -106,7 +98,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do        json(conn, response)      else -      _error -> json(conn, %{error: "Invalid credentials"}) +      _error -> +        put_status(conn, 400) +        |> json(%{error: "Invalid credentials"})      end    end @@ -115,4 +109,28 @@ defmodule Pleroma.Web.OAuth.OAuthController do      |> Base.url_decode64!(padding: false)      |> Base.url_encode64()    end + +  defp get_app_from_request(conn, params) do +    # Per RFC 6749, HTTP Basic is preferred to body params +    {client_id, client_secret} = +      with ["Basic " <> encoded] <- get_req_header(conn, "authorization"), +           {:ok, decoded} <- Base.decode64(encoded), +           [id, secret] <- +             String.split(decoded, ":") +             |> Enum.map(fn s -> URI.decode_www_form(s) end) do +        {id, secret} +      else +        _ -> {params["client_id"], params["client_secret"]} +      end + +    if client_id && client_secret do +      Repo.get_by( +        App, +        client_id: client_id, +        client_secret: client_secret +      ) +    else +      nil +    end +  end  end diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 53278431e..2f72fdb16 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -9,36 +9,47 @@ defmodule Pleroma.Web.OStatus.OStatusController do    alias Pleroma.Web.ActivityPub.ActivityPubController    alias Pleroma.Web.ActivityPub.ActivityPub -  def feed_redirect(conn, %{"nickname" => nickname} = params) do -    user = User.get_cached_by_nickname(nickname) +  action_fallback(:errors) +  def feed_redirect(conn, %{"nickname" => nickname}) do      case get_format(conn) do -      "html" -> Fallback.RedirectController.redirector(conn, nil) -      "activity+json" -> ActivityPubController.user(conn, params) -      _ -> redirect(conn, external: OStatus.feed_path(user)) +      "html" -> +        Fallback.RedirectController.redirector(conn, nil) + +      "activity+json" -> +        ActivityPubController.call(conn, :user) + +      _ -> +        with %User{} = user <- User.get_cached_by_nickname(nickname) do +          redirect(conn, external: OStatus.feed_path(user)) +        else +          nil -> {:error, :not_found} +        end      end    end    def feed(conn, %{"nickname" => nickname} = params) do -    user = User.get_cached_by_nickname(nickname) - -    query_params = -      Map.take(params, ["max_id"]) -      |> Map.merge(%{"whole_db" => true, "actor_id" => user.ap_id}) - -    activities = -      ActivityPub.fetch_public_activities(query_params) -      |> Enum.reverse() - -    response = -      user -      |> FeedRepresenter.to_simple_form(activities, [user]) -      |> :xmerl.export_simple(:xmerl_xml) -      |> to_string - -    conn -    |> put_resp_content_type("application/atom+xml") -    |> send_resp(200, response) +    with %User{} = user <- User.get_cached_by_nickname(nickname) do +      query_params = +        Map.take(params, ["max_id"]) +        |> Map.merge(%{"whole_db" => true, "actor_id" => user.ap_id}) + +      activities = +        ActivityPub.fetch_public_activities(query_params) +        |> Enum.reverse() + +      response = +        user +        |> FeedRepresenter.to_simple_form(activities, [user]) +        |> :xmerl.export_simple(:xmerl_xml) +        |> to_string + +      conn +      |> put_resp_content_type("application/atom+xml") +      |> send_resp(200, response) +    else +      nil -> {:error, :not_found} +    end    end    defp decode_or_retry(body) do @@ -68,12 +79,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do      |> send_resp(200, "")    end -  def object(conn, %{"uuid" => uuid} = params) do +  def object(conn, %{"uuid" => uuid}) do      if get_format(conn) == "activity+json" do -      ActivityPubController.object(conn, params) +      ActivityPubController.call(conn, :object)      else        with id <- o_status_url(conn, :object, uuid), -           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id), +           {_, %Activity{} = activity} <- +             {:activity, Activity.get_create_activity_by_object_ap_id(id)},             {_, true} <- {:public?, ActivityPub.is_public?(activity)},             %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do          case get_format(conn) do @@ -82,16 +94,20 @@ defmodule Pleroma.Web.OStatus.OStatusController do          end        else          {:public?, false} -> -          conn -          |> put_status(404) -          |> json("Not found") +          {:error, :not_found} + +        {:activity, nil} -> +          {:error, :not_found} + +        e -> +          e        end      end    end    def activity(conn, %{"uuid" => uuid}) do      with id <- o_status_url(conn, :activity, uuid), -         %Activity{} = activity <- Activity.get_by_ap_id(id), +         {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(id)},           {_, true} <- {:public?, ActivityPub.is_public?(activity)},           %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do        case get_format(conn) do @@ -100,14 +116,18 @@ defmodule Pleroma.Web.OStatus.OStatusController do        end      else        {:public?, false} -> -        conn -        |> put_status(404) -        |> json("Not found") +        {:error, :not_found} + +      {:activity, nil} -> +        {:error, :not_found} + +      e -> +        e      end    end    def notice(conn, %{"id" => id}) do -    with %Activity{} = activity <- Repo.get(Activity, id), +    with {_, %Activity{} = activity} <- {:activity, Repo.get(Activity, id)},           {_, true} <- {:public?, ActivityPub.is_public?(activity)},           %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do        case get_format(conn) do @@ -121,9 +141,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do        end      else        {:public?, false} -> -        conn -        |> put_status(404) -        |> json("Not found") +        {:error, :not_found} + +      {:activity, nil} -> +        {:error, :not_found} + +      e -> +        e      end    end @@ -139,4 +163,16 @@ defmodule Pleroma.Web.OStatus.OStatusController do      |> put_resp_content_type("application/atom+xml")      |> send_resp(200, response)    end + +  def errors(conn, {:error, :not_found}) do +    conn +    |> put_status(404) +    |> text("Not found") +  end + +  def errors(conn, _) do +    conn +    |> put_status(500) +    |> text("Something went wrong") +  end  end diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index cc5146566..7a0c37ce9 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -189,7 +189,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do               {:ok, follower} <- User.follow(follower, followed) do            ActivityPub.follow(follower, followed)          else -          _e -> Logger.debug("follow_import: following #{account} failed") +          err -> Logger.debug("follow_import: following #{account} failed with #{inspect(err)}")          end        end)      end) diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 331efa90b..ccc6fe8e7 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -64,7 +64,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do    end    def repeat(%User{} = user, ap_id_or_id) do -    with {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(ap_id_or_id, user), +    with {:ok, _announce, %{data: %{"id" => id}}} <- CommonAPI.repeat(ap_id_or_id, user),           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do        {:ok, activity}      end @@ -77,14 +77,14 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do    end    def fav(%User{} = user, ap_id_or_id) do -    with {:ok, _fav, %{data: %{"id" => id}}} = CommonAPI.favorite(ap_id_or_id, user), +    with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user),           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do        {:ok, activity}      end    end    def unfav(%User{} = user, ap_id_or_id) do -    with {:ok, _unfav, _fav, %{data: %{"id" => id}}} = CommonAPI.unfavorite(ap_id_or_id, user), +    with {:ok, _unfav, _fav, %{data: %{"id" => id}}} <- CommonAPI.unfavorite(ap_id_or_id, user),           %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do        {:ok, activity}      end diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 320f2fcf4..d53dd0c44 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -8,6 +8,8 @@ defmodule Pleroma.Web.TwitterAPI.Controller do    require Logger +  action_fallback(:errors) +    def verify_credentials(%{assigns: %{user: user}} = conn, _params) do      token = Phoenix.Token.sign(conn, "user socket", user.id)      render(conn, UserView, "show.json", %{user: user, token: token}) @@ -218,19 +220,22 @@ defmodule Pleroma.Web.TwitterAPI.Controller do    end    def favorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do -    with {:ok, activity} <- TwitterAPI.fav(user, id) do +    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)}, +         {:ok, activity} <- TwitterAPI.fav(user, id) do        render(conn, ActivityView, "activity.json", %{activity: activity, for: user})      end    end    def unfavorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do -    with {:ok, activity} <- TwitterAPI.unfav(user, id) do +    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)}, +         {:ok, activity} <- TwitterAPI.unfav(user, id) do        render(conn, ActivityView, "activity.json", %{activity: activity, for: user})      end    end    def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do -    with {:ok, activity} <- TwitterAPI.repeat(user, id) do +    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)}, +         {:ok, activity} <- TwitterAPI.repeat(user, id) do        render(conn, ActivityView, "activity.json", %{activity: activity, for: user})      end    end @@ -389,4 +394,16 @@ defmodule Pleroma.Web.TwitterAPI.Controller do    defp error_json(conn, error_message) do      %{"error" => error_message, "request" => conn.request_path} |> Jason.encode!()    end + +  def errors(conn, {:param_cast, _}) do +    conn +    |> put_status(400) +    |> json("Invalid parameters") +  end + +  def errors(conn, _) do +    conn +    |> put_status(500) +    |> json("Something went wrong") +  end  end diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index 9c6f1cb68..e7ee810f9 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -144,41 +144,50 @@ defmodule Pleroma.Web.WebFinger do      end    end -  defp webfinger_from_xml(doc) do -    magic_key = XML.string_from_xpath(~s{//Link[@rel="magic-public-key"]/@href}, doc) +  defp get_magic_key(magic_key) do      "data:application/magic-public-key," <> magic_key = magic_key +    {:ok, magic_key} +  rescue +    MatchError -> {:error, "Missing magic key data."} +  end -    topic = -      XML.string_from_xpath( -        ~s{//Link[@rel="http://schemas.google.com/g/2010#updates-from"]/@href}, -        doc -      ) - -    subject = XML.string_from_xpath("//Subject", doc) -    salmon = XML.string_from_xpath(~s{//Link[@rel="salmon"]/@href}, doc) - -    subscribe_address = -      XML.string_from_xpath( -        ~s{//Link[@rel="http://ostatus.org/schema/1.0/subscribe"]/@template}, -        doc -      ) - -    ap_id = -      XML.string_from_xpath( -        ~s{//Link[@rel="self" and @type="application/activity+json"]/@href}, -        doc -      ) - -    data = %{ -      "magic_key" => magic_key, -      "topic" => topic, -      "subject" => subject, -      "salmon" => salmon, -      "subscribe_address" => subscribe_address, -      "ap_id" => ap_id -    } +  defp webfinger_from_xml(doc) do +    with magic_key <- XML.string_from_xpath(~s{//Link[@rel="magic-public-key"]/@href}, doc), +         {:ok, magic_key} <- get_magic_key(magic_key), +         topic <- +           XML.string_from_xpath( +             ~s{//Link[@rel="http://schemas.google.com/g/2010#updates-from"]/@href}, +             doc +           ), +         subject <- XML.string_from_xpath("//Subject", doc), +         salmon <- XML.string_from_xpath(~s{//Link[@rel="salmon"]/@href}, doc), +         subscribe_address <- +           XML.string_from_xpath( +             ~s{//Link[@rel="http://ostatus.org/schema/1.0/subscribe"]/@template}, +             doc +           ), +         ap_id <- +           XML.string_from_xpath( +             ~s{//Link[@rel="self" and @type="application/activity+json"]/@href}, +             doc +           ) do +      data = %{ +        "magic_key" => magic_key, +        "topic" => topic, +        "subject" => subject, +        "salmon" => salmon, +        "subscribe_address" => subscribe_address, +        "ap_id" => ap_id +      } -    {:ok, data} +      {:ok, data} +    else +      {:error, e} -> +        {:error, e} + +      e -> +        {:error, e} +    end    end    defp webfinger_from_json(doc) do @@ -253,7 +262,7 @@ defmodule Pleroma.Web.WebFinger do            String.replace(template, "{uri}", URI.encode(account))          _ -> -          "http://#{domain}/.well-known/webfinger?resource=acct:#{account}" +          "https://#{domain}/.well-known/webfinger?resource=acct:#{account}"        end      with response <- @@ -268,8 +277,11 @@ defmodule Pleroma.Web.WebFinger do        if doc != :error do          webfinger_from_xml(doc)        else -        {:ok, doc} = Jason.decode(body) -        webfinger_from_json(doc) +        with {:ok, doc} <- Jason.decode(body) do +          webfinger_from_json(doc) +        else +          {:error, e} -> e +        end        end      else        e -> diff --git a/lib/pleroma/web/xml/xml.ex b/lib/pleroma/web/xml/xml.ex index 36430a3fa..da3f68ecb 100644 --- a/lib/pleroma/web/xml/xml.ex +++ b/lib/pleroma/web/xml/xml.ex @@ -32,6 +32,10 @@ defmodule Pleroma.Web.XML do        :exit, _error ->          Logger.debug("Couldn't parse XML: #{inspect(text)}")          :error +    rescue +      e -> +        Logger.debug("Couldn't parse XML: #{inspect(text)}") +        :error      end    end  end | 
