summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFrancis Dinh <normandy@firemail.cc>2018-05-20 19:17:15 -0400
committerFrancis Dinh <normandy@firemail.cc>2018-05-20 19:17:15 -0400
commit1afd6d37bd2febb58ee09d273b9c7d690022d3c3 (patch)
tree8be53801457cae7e31f7efdb501b81974ca3b36f /lib
parentd46393f6efd6475bb20b6a12a7c6ebf800f6c5b5 (diff)
parent961f1312571843209487cc1caa9355fa6552d965 (diff)
downloadpleroma-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.ex13
-rw-r--r--lib/pleroma/formatter.ex1
-rw-r--r--lib/pleroma/plugs/http_signature.ex3
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex53
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex32
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex33
-rw-r--r--lib/pleroma/web/common_api/utils.ex11
-rw-r--r--lib/pleroma/web/federator/federator.ex3
-rw-r--r--lib/pleroma/web/http_signatures/http_signatures.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex17
-rw-r--r--lib/pleroma/web/router.ex1
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex12
-rw-r--r--lib/pleroma/web/twitter_api/representers/activity_representer.ex3
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex4
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex8
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex3
-rw-r--r--lib/pleroma/web/web_finger/web_finger.ex8
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)