diff options
| author | Francis Dinh <normandy@firemail.cc> | 2018-05-20 19:17:15 -0400 | 
|---|---|---|
| committer | Francis Dinh <normandy@firemail.cc> | 2018-05-20 19:17:15 -0400 | 
| commit | 1afd6d37bd2febb58ee09d273b9c7d690022d3c3 (patch) | |
| tree | 8be53801457cae7e31f7efdb501b81974ca3b36f /lib | |
| parent | d46393f6efd6475bb20b6a12a7c6ebf800f6c5b5 (diff) | |
| parent | 961f1312571843209487cc1caa9355fa6552d965 (diff) | |
| download | pleroma-1afd6d37bd2febb58ee09d273b9c7d690022d3c3.tar.gz pleroma-1afd6d37bd2febb58ee09d273b9c7d690022d3c3.zip  | |
Merge remote-tracking branch 'upstream/develop' into feature/incoming-remote-unfollow
Fixed some conflicts in transmogrifier.ex
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/mix/tasks/deactivate_user.ex | 13 | ||||
| -rw-r--r-- | lib/pleroma/formatter.ex | 1 | ||||
| -rw-r--r-- | lib/pleroma/plugs/http_signature.ex | 3 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 53 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 32 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 33 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/web/federator/federator.ex | 3 | ||||
| -rw-r--r-- | lib/pleroma/web/http_signatures/http_signatures.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 17 | ||||
| -rw-r--r-- | lib/pleroma/web/router.ex | 1 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/controllers/util_controller.ex | 12 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/representers/activity_representer.ex | 3 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 4 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 8 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/views/activity_view.ex | 3 | ||||
| -rw-r--r-- | lib/pleroma/web/web_finger/web_finger.ex | 8 | 
17 files changed, 178 insertions, 33 deletions
diff --git a/lib/mix/tasks/deactivate_user.ex b/lib/mix/tasks/deactivate_user.ex new file mode 100644 index 000000000..96b3db6e4 --- /dev/null +++ b/lib/mix/tasks/deactivate_user.ex @@ -0,0 +1,13 @@ +defmodule Mix.Tasks.DeactivateUser do +  use Mix.Task +  alias Pleroma.User + +  @shortdoc "Toggle deactivation status for a user" +  def run([nickname]) do +    Mix.Task.run("app.start") + +    with user <- User.get_by_nickname(nickname) do +      User.deactivate(user) +    end +  end +end diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index 456416fbd..53e2c204f 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -160,6 +160,7 @@ defmodule Pleroma.Formatter do      links =        Regex.scan(@link_regex, text)        |> Enum.map(fn [url] -> {Ecto.UUID.generate(), url} end) +      |> Enum.sort_by(fn {_, url} -> -String.length(url) end)      uuid_text =        links diff --git a/lib/pleroma/plugs/http_signature.ex b/lib/pleroma/plugs/http_signature.ex index efde652f5..2d0e10cad 100644 --- a/lib/pleroma/plugs/http_signature.ex +++ b/lib/pleroma/plugs/http_signature.ex @@ -1,5 +1,6 @@  defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do    alias Pleroma.Web.HTTPSignatures +  alias Pleroma.Web.ActivityPub.Utils    import Plug.Conn    require Logger @@ -12,7 +13,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do    end    def call(conn, _opts) do -    user = conn.params["actor"] +    user = Utils.normalize_actor(conn.params["actor"])      Logger.debug("Checking sig for #{user}")      [signature | _] = get_req_header(conn, "signature") diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 48eba36fd..a711e6b76 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -16,9 +16,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      (data["to"] || []) ++ (data["cc"] || [])    end +  defp check_actor_is_active(actor) do +    if not is_nil(actor) do +      with user <- User.get_cached_by_ap_id(actor), +           nil <- user.info["deactivated"] do +        :ok +      else +        _e -> :reject +      end +    else +      :ok +    end +  end +    def insert(map, local \\ true) when is_map(map) do      with nil <- Activity.get_by_ap_id(map["id"]),           map <- lazy_put_activity_defaults(map), +         :ok <- check_actor_is_active(map["actor"]),           {:ok, map} <- MRF.filter(map),           :ok <- insert_full_object(map) do        {:ok, activity} = @@ -117,11 +131,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      end    end -  def unlike(%User{} = actor, %Object{} = object) do -    with %Activity{} = activity <- get_existing_like(actor.ap_id, object), -         {:ok, _activity} <- Repo.delete(activity), -         {:ok, object} <- remove_like_from_object(activity, object) do -      {:ok, object} +  def unlike( +        %User{} = actor, +        %Object{} = object, +        activity_id \\ nil, +        local \\ true +      ) do +    with %Activity{} = like_activity <- get_existing_like(actor.ap_id, object), +         unlike_data <- make_unlike_data(actor, like_activity, activity_id), +         {:ok, unlike_activity} <- insert(unlike_data, local), +         {:ok, _activity} <- Repo.delete(like_activity), +         {:ok, object} <- remove_like_from_object(like_activity, object), +         :ok <- maybe_federate(unlike_activity) do +      {:ok, unlike_activity, like_activity, object}      else        _e -> {:ok, object}      end @@ -261,6 +283,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      |> Enum.reverse()    end +  def fetch_user_activities(user, reading_user, params \\ %{}) do +    params = +      params +      |> Map.put("type", ["Create", "Announce"]) +      |> Map.put("actor_id", user.ap_id) +      |> Map.put("whole_db", true) + +    recipients = +      if reading_user do +        ["https://www.w3.org/ns/activitystreams#Public"] ++ +          [reading_user.ap_id | reading_user.following] +      else +        ["https://www.w3.org/ns/activitystreams#Public"] +      end + +    fetch_activities(recipients, params) +    |> Enum.reverse() +  end +    defp restrict_since(query, %{"since_id" => since_id}) do      from(activity in query, where: activity.id > ^since_id)    end @@ -424,6 +465,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do            "url" => [%{"href" => data["image"]["url"]}]          } +    data = Transmogrifier.maybe_fix_user_object(data) +      user_data = %{        ap_id: data["id"],        info: %{ diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 47b84a469..d92ca9b65 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -273,9 +273,26 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      end    end +  def handle_incoming( +        %{ +          "type" => "Undo", +          "object" => %{"type" => "Like", "object" => object_id}, +          "actor" => actor, +          "id" => id +        } = data +      ) do +    with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), +         {:ok, object} <- +           get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), +         {:ok, activity, _, _} <- ActivityPub.unlike(actor, object, id, false) do +      {:ok, activity} +    else +      e -> :error +    end +  end +    # TODO    # Accept -  # Undo for non-Announce    def handle_incoming(_), do: :error @@ -527,4 +544,17 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do        Repo.delete_all(q)      end    end + +  def maybe_fix_user_url(data) do +    if is_map(data["url"]) do +      data = Map.put(data, "url", data["url"]["href"]) +    end + +    data +  end + +  def maybe_fix_user_object(data) do +    data +    |> maybe_fix_user_url +  end  end diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 846dd97c2..050413d51 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -5,6 +5,22 @@ defmodule Pleroma.Web.ActivityPub.Utils do    alias Ecto.{Changeset, UUID}    import Ecto.Query +  # Some implementations send the actor URI as the actor field, others send the entire actor object, +  # so figure out what the actor's URI is based on what we have. +  def normalize_actor(actor) do +    cond do +      is_binary(actor) -> +        actor + +      is_map(actor) -> +        actor["id"] +    end +  end + +  def normalize_params(params) do +    Map.put(params, "actor", normalize_actor(params["actor"])) +  end +    def make_json_ld_header do      %{        "@context" => [ @@ -299,6 +315,23 @@ defmodule Pleroma.Web.ActivityPub.Utils do      if activity_id, do: Map.put(data, "id", activity_id), else: data    end +  def make_unlike_data( +        %User{ap_id: ap_id} = user, +        %Activity{data: %{"context" => context}} = activity, +        activity_id +      ) do +    data = %{ +      "type" => "Undo", +      "actor" => ap_id, +      "object" => activity.data, +      "to" => [user.follower_address, activity.data["actor"]], +      "cc" => ["https://www.w3.org/ns/activitystreams#Public"], +      "context" => context +    } + +    if activity_id, do: Map.put(data, "id", activity_id), else: data +  end +    def add_announce_to_object(%Activity{data: %{"actor" => actor}}, object) do      with announcements <- [actor | object.data["announcements"] || []] |> Enum.uniq() do        update_element_in_object("announcement", announcements, object) diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 57f8be894..e774743a2 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -1,7 +1,9 @@  defmodule Pleroma.Web.CommonAPI.Utils do    alias Pleroma.{Repo, Object, Formatter, Activity}    alias Pleroma.Web.ActivityPub.Utils +  alias Pleroma.User    alias Calendar.Strftime +  alias Comeonin.Pbkdf2    # This is a hack for twidere.    def get_by_id_or_ap_id(id) do @@ -184,4 +186,13 @@ defmodule Pleroma.Web.CommonAPI.Utils do        String.slice(name, 0..30) <> "…"      end    end + +  def confirm_current_password(user, params) do +    with %User{local: true} = db_user <- Repo.get(User, user.id), +         true <- Pbkdf2.checkpw(params["password"], db_user.password_hash) do +      {:ok, db_user} +    else +      _ -> {:error, "Invalid password."} +    end +  end  end diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex index f84af2f15..8ca530031 100644 --- a/lib/pleroma/web/federator/federator.ex +++ b/lib/pleroma/web/federator/federator.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.Federator do    alias Pleroma.Web.{WebFinger, Websub}    alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Transmogrifier +  alias Pleroma.Web.ActivityPub.Utils    require Logger    @websub Application.get_env(:pleroma, :websub) @@ -91,6 +92,8 @@ defmodule Pleroma.Web.Federator do    def handle(:incoming_ap_doc, params) do      Logger.info("Handling incoming AP activity") +    params = Utils.normalize_params(params) +      with {:ok, _user} <- ap_enabled_actor(params["actor"]),           nil <- Activity.get_by_ap_id(params["id"]),           {:ok, _activity} <- Transmogrifier.handle_incoming(params) do diff --git a/lib/pleroma/web/http_signatures/http_signatures.ex b/lib/pleroma/web/http_signatures/http_signatures.ex index 9035f5eb6..dd3f825db 100644 --- a/lib/pleroma/web/http_signatures/http_signatures.ex +++ b/lib/pleroma/web/http_signatures/http_signatures.ex @@ -1,7 +1,7 @@  # https://tools.ietf.org/html/draft-cavage-http-signatures-08  defmodule Pleroma.Web.HTTPSignatures do    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.Utils    require Logger    def split_signature(sig) do @@ -31,14 +31,14 @@ defmodule Pleroma.Web.HTTPSignatures do    def validate_conn(conn) do      # TODO: How to get the right key and see if it is actually valid for that request.      # For now, fetch the key for the actor. -    with actor_id <- conn.params["actor"], +    with actor_id <- Utils.normalize_actor(conn.params["actor"]),           {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do        if validate_conn(conn, public_key) do          true        else          Logger.debug("Could not validate, re-fetching user and trying one more time")          # Fetch user anew and try one more time -        with actor_id <- conn.params["actor"], +        with actor_id <- Utils.normalize_actor(conn.params["actor"]),               {:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),               {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do            validate_conn(conn, public_key) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 5475cb505..85f9c5b7b 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -204,21 +204,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do      |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity})    end -  def user_statuses(%{assigns: %{user: user}} = conn, params) do -    with %User{ap_id: ap_id} <- Repo.get(User, params["id"]) do -      params = -        params -        |> Map.put("type", ["Create", "Announce"]) -        |> Map.put("actor_id", ap_id) -        |> Map.put("whole_db", true) - +  def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do +    with %User{} = user <- Repo.get(User, params["id"]) do +      # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here        activities =          if params["pinned"] == "true" do -          # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here            []          else -          ActivityPub.fetch_public_activities(params) -          |> Enum.reverse() +          ActivityPub.fetch_user_activities(user, reading_user, params)          end        conn @@ -323,7 +316,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do    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 diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index c202cb810..2b5209b75 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -73,6 +73,7 @@ defmodule Pleroma.Web.Router do    scope "/api/pleroma", Pleroma.Web.TwitterAPI do      pipe_through(:authenticated_api)      post("/follow_import", UtilController, :follow_import) +    post("/delete_account", UtilController, :delete_account)    end    scope "/oauth", Pleroma.Web.OAuth do diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index ea540b34c..23e7408a0 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do    alias Pleroma.Web    alias Pleroma.Web.OStatus    alias Pleroma.Web.WebFinger +  alias Pleroma.Web.CommonAPI    alias Comeonin.Pbkdf2    alias Pleroma.Formatter    alias Pleroma.Web.ActivityPub.ActivityPub @@ -195,4 +196,15 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do      json(conn, "job started")    end + +  def delete_account(%{assigns: %{user: user}} = conn, params) do +    case CommonAPI.Utils.confirm_current_password(user, params) do +      {:ok, user} -> +        Task.start(fn -> User.delete(user) end) +        json(conn, %{status: "success"}) + +      {:error, msg} -> +        json(conn, %{error: msg}) +    end +  end  end diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index 9a4954de8..c2e1f07a5 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -197,7 +197,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do        "external_url" => object["external_url"] || object["id"],        "tags" => tags,        "activity_type" => "post", -      "possibly_sensitive" => possibly_sensitive +      "possibly_sensitive" => possibly_sensitive, +      "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)      }    end diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 8177a4988..722e436e2 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -82,14 +82,14 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do    end    def fav(%User{} = user, ap_id_or_id) do -    with {:ok, _announce, %{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, %{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 a99487738..dd1dc241d 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -96,13 +96,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do    def user_timeline(%{assigns: %{user: user}} = conn, params) do      case TwitterAPI.get_user(user, params) do        {:ok, target_user} -> -        params = -          params -          |> Map.put("type", ["Create", "Announce"]) -          |> Map.put("actor_id", target_user.ap_id) -          |> Map.put("whole_db", true) - -        activities = ActivityPub.fetch_public_activities(params) +        activities = ActivityPub.fetch_user_activities(target_user, user, params)          conn          |> render(ActivityView, "index.json", %{activities: activities, for: user}) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 580d4648c..62ce3b7b5 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -262,7 +262,8 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do        "external_url" => object["external_url"] || object["id"],        "tags" => tags,        "activity_type" => "post", -      "possibly_sensitive" => possibly_sensitive +      "possibly_sensitive" => possibly_sensitive, +      "visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)      }    end  end diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index 6ffa80a43..6e5fc1401 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -87,6 +87,11 @@ defmodule Pleroma.Web.WebFinger do          },          %{"rel" => "self", "type" => "application/activity+json", "href" => user.ap_id},          %{ +          "rel" => "self", +          "type" => "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"", +          "href" => user.ap_id +        }, +        %{            "rel" => "http://ostatus.org/schema/1.0/subscribe",            "template" => OStatus.remote_follow_path()          } @@ -183,6 +188,9 @@ defmodule Pleroma.Web.WebFinger do            {"application/activity+json", "self"} ->              Map.put(data, "ap_id", link["href"]) +          {"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"", "self"} -> +            Map.put(data, "ap_id", link["href"]) +            {_, "magic-public-key"} ->              "data:application/magic-public-key," <> magic_key = link["href"]              Map.put(data, "magic_key", magic_key)  | 
