aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/application.ex8
-rw-r--r--lib/pleroma/list.ex87
-rw-r--r--lib/pleroma/object.ex20
-rw-r--r--lib/pleroma/plugs/http_signature.ex2
-rw-r--r--lib/pleroma/user.ex79
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex45
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex150
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex77
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex2
-rw-r--r--lib/pleroma/web/common_api/utils.ex6
-rw-r--r--lib/pleroma/web/http_signatures/http_signatures.ex4
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex125
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/views/list_view.ex15
-rw-r--r--lib/pleroma/web/ostatus/activity_representer.ex51
-rw-r--r--lib/pleroma/web/ostatus/handlers/unfollow_handler.ex17
-rw-r--r--lib/pleroma/web/ostatus/ostatus.ex5
-rw-r--r--lib/pleroma/web/router.ex12
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex25
-rw-r--r--lib/pleroma/web/twitter_api/representers/activity_representer.ex2
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex17
21 files changed, 613 insertions, 138 deletions
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index e1e3bcd63..a89728471 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -5,6 +5,7 @@ defmodule Pleroma.Application do
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec
+ import Cachex.Spec
# Define workers and child supervisors to be supervised
children =
@@ -28,8 +29,11 @@ defmodule Pleroma.Application do
[
:idempotency_cache,
[
- default_ttl: :timer.seconds(6 * 60 * 60),
- ttl_interval: :timer.seconds(60),
+ expiration:
+ expiration(
+ default: :timer.seconds(6 * 60 * 60),
+ interval: :timer.seconds(60)
+ ),
limit: 2500
]
],
diff --git a/lib/pleroma/list.ex b/lib/pleroma/list.ex
new file mode 100644
index 000000000..9d0b9285b
--- /dev/null
+++ b/lib/pleroma/list.ex
@@ -0,0 +1,87 @@
+defmodule Pleroma.List do
+ use Ecto.Schema
+ import Ecto.{Changeset, Query}
+ alias Pleroma.{User, Repo}
+
+ schema "lists" do
+ belongs_to(:user, Pleroma.User)
+ field(:title, :string)
+ field(:following, {:array, :string}, default: [])
+
+ timestamps()
+ end
+
+ def title_changeset(list, attrs \\ %{}) do
+ list
+ |> cast(attrs, [:title])
+ |> validate_required([:title])
+ end
+
+ def follow_changeset(list, attrs \\ %{}) do
+ list
+ |> cast(attrs, [:following])
+ |> validate_required([:following])
+ end
+
+ def for_user(user, opts) do
+ query =
+ from(
+ l in Pleroma.List,
+ where: l.user_id == ^user.id,
+ order_by: [desc: l.id],
+ limit: 50
+ )
+
+ Repo.all(query)
+ end
+
+ def get(id, %{id: user_id} = _user) do
+ query =
+ from(
+ l in Pleroma.List,
+ where: l.id == ^id,
+ where: l.user_id == ^user_id
+ )
+
+ Repo.one(query)
+ end
+
+ def get_following(%Pleroma.List{following: following} = list) do
+ q =
+ from(
+ u in User,
+ where: u.follower_address in ^following
+ )
+
+ {:ok, Repo.all(q)}
+ end
+
+ def rename(%Pleroma.List{} = list, title) do
+ list
+ |> title_changeset(%{title: title})
+ |> Repo.update()
+ end
+
+ def create(title, %User{} = creator) do
+ list = %Pleroma.List{user_id: creator.id, title: title}
+ Repo.insert(list)
+ end
+
+ def follow(%Pleroma.List{following: following} = list, %User{} = followed) do
+ update_follows(list, %{following: Enum.uniq([followed.follower_address | following])})
+ end
+
+ def unfollow(%Pleroma.List{following: following} = list, %User{} = unfollowed) do
+ update_follows(list, %{following: List.delete(following, unfollowed.follower_address)})
+ end
+
+ def delete(%Pleroma.List{} = list) do
+ Repo.delete(list)
+ end
+
+ def update_follows(%Pleroma.List{} = list, attrs) do
+ list
+ |> follow_changeset(attrs)
+ |> Repo.update()
+ end
+end
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index 558e151b0..ff2af4a6f 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -33,19 +33,15 @@ defmodule Pleroma.Object do
else
key = "object:#{ap_id}"
- Cachex.get!(
- :user_cache,
- key,
- fallback: fn _ ->
- object = get_by_ap_id(ap_id)
-
- if object do
- {:commit, object}
- else
- {:ignore, object}
- end
+ Cachex.fetch!(:user_cache, key, fn _ ->
+ object = get_by_ap_id(ap_id)
+
+ if object do
+ {:commit, object}
+ else
+ {:ignore, object}
end
- )
+ end)
end
end
diff --git a/lib/pleroma/plugs/http_signature.ex b/lib/pleroma/plugs/http_signature.ex
index 2d0e10cad..38bcd3a78 100644
--- a/lib/pleroma/plugs/http_signature.ex
+++ b/lib/pleroma/plugs/http_signature.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
end
def call(conn, _opts) do
- user = Utils.normalize_actor(conn.params["actor"])
+ user = Utils.get_ap_id(conn.params["actor"])
Logger.debug("Checking sig for #{user}")
[signature | _] = get_req_header(conn, "signature")
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 6a8129ac8..b1b935a0f 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -67,7 +67,8 @@ defmodule Pleroma.User do
%{
following_count: length(user.following) - oneself,
note_count: user.info["note_count"] || 0,
- follower_count: user.info["follower_count"] || 0
+ follower_count: user.info["follower_count"] || 0,
+ locked: user.info["locked"] || false
}
end
@@ -167,28 +168,62 @@ defmodule Pleroma.User do
end
end
+ def maybe_direct_follow(%User{} = follower, %User{info: info} = followed) do
+ user_info = user_info(followed)
+
+ should_direct_follow =
+ cond do
+ # if the account is locked, don't pre-create the relationship
+ user_info["locked"] == true ->
+ false
+
+ # if the users are blocking each other, we shouldn't even be here, but check for it anyway
+ User.blocks?(follower, followed) == true or User.blocks?(followed, follower) == true ->
+ false
+
+ # if OStatus, then there is no three-way handshake to follow
+ User.ap_enabled?(followed) != true ->
+ true
+
+ # if there are no other reasons not to, just pre-create the relationship
+ true ->
+ true
+ end
+
+ if should_direct_follow do
+ follow(follower, followed)
+ else
+ follower
+ end
+ end
+
def follow(%User{} = follower, %User{info: info} = followed) do
ap_followers = followed.follower_address
- if following?(follower, followed) or info["deactivated"] do
- {:error, "Could not follow user: #{followed.nickname} is already on your list."}
- else
- if !followed.local && follower.local && !ap_enabled?(followed) do
- Websub.subscribe(follower, followed)
- end
+ cond do
+ following?(follower, followed) or info["deactivated"] ->
+ {:error, "Could not follow user: #{followed.nickname} is already on your list."}
- following =
- [ap_followers | follower.following]
- |> Enum.uniq()
+ blocks?(followed, follower) ->
+ {:error, "Could not follow user: #{followed.nickname} blocked you."}
- follower =
- follower
- |> follow_changeset(%{following: following})
- |> update_and_set_cache
+ true ->
+ if !followed.local && follower.local && !ap_enabled?(followed) do
+ Websub.subscribe(follower, followed)
+ end
- {:ok, _} = update_follower_count(followed)
+ following =
+ [ap_followers | follower.following]
+ |> Enum.uniq()
- follower
+ follower =
+ follower
+ |> follow_changeset(%{following: following})
+ |> update_and_set_cache
+
+ {:ok, _} = update_follower_count(followed)
+
+ follower
end
end
@@ -223,9 +258,9 @@ defmodule Pleroma.User do
def update_and_set_cache(changeset) do
with {:ok, user} <- Repo.update(changeset) do
- Cachex.set(:user_cache, "ap_id:#{user.ap_id}", user)
- Cachex.set(:user_cache, "nickname:#{user.nickname}", user)
- Cachex.set(:user_cache, "user_info:#{user.id}", user_info(user))
+ Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
+ Cachex.put(:user_cache, "nickname:#{user.nickname}", user)
+ Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user))
{:ok, user}
else
e -> e
@@ -239,12 +274,12 @@ defmodule Pleroma.User do
def get_cached_by_ap_id(ap_id) do
key = "ap_id:#{ap_id}"
- Cachex.get!(:user_cache, key, fallback: fn _ -> get_by_ap_id(ap_id) end)
+ Cachex.fetch!(:user_cache, key, fn _ -> get_by_ap_id(ap_id) end)
end
def get_cached_by_nickname(nickname) do
key = "nickname:#{nickname}"
- Cachex.get!(:user_cache, key, fallback: fn _ -> get_or_fetch_by_nickname(nickname) end)
+ Cachex.fetch!(:user_cache, key, fn _ -> get_or_fetch_by_nickname(nickname) end)
end
def get_by_nickname(nickname) do
@@ -260,7 +295,7 @@ defmodule Pleroma.User do
def get_cached_user_info(user) do
key = "user_info:#{user.id}"
- Cachex.get!(:user_cache, key, fallback: fn _ -> user_info(user) end)
+ Cachex.fetch!(:user_cache, key, fn _ -> user_info(user) end)
end
def fetch_by_nickname(nickname) do
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index f07e26afd..d54dc224d 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -104,6 +104,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
+ def reject(%{to: to, actor: actor, object: object} = params) do
+ # only accept false as false value
+ local = !(params[:local] == false)
+
+ with data <- %{"to" => to, "type" => "Reject", "actor" => actor, "object" => object},
+ {:ok, activity} <- insert(data, local),
+ :ok <- maybe_federate(activity) do
+ {:ok, activity}
+ end
+ end
+
def update(%{to: to, cc: cc, actor: actor, object: object} = params) do
# only accept false as false value
local = !(params[:local] == false)
@@ -201,12 +212,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- def unfollow(follower, followed, local \\ true) do
+ def unfollow(follower, followed, activity_id \\ nil, local \\ true) do
with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed),
- unfollow_data <- make_unfollow_data(follower, followed, follow_activity),
+ unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
{:ok, activity} <- insert(unfollow_data, local),
- :ok,
- maybe_federate(activity) do
+ :ok <- maybe_federate(activity) do
{:ok, activity}
end
end
@@ -230,6 +240,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
+ def block(blocker, blocked, activity_id \\ nil, local \\ true) do
+ follow_activity = fetch_latest_follow(blocker, blocked)
+
+ if follow_activity do
+ unfollow(blocker, blocked, nil, local)
+ end
+
+ with block_data <- make_block_data(blocker, blocked, activity_id),
+ {:ok, activity} <- insert(block_data, local),
+ :ok <- maybe_federate(activity) do
+ {:ok, activity}
+ end
+ end
+
+ def unblock(blocker, blocked, activity_id \\ nil, local \\ true) do
+ with %Activity{} = block_activity <- fetch_latest_block(blocker, blocked),
+ unblock_data <- make_unblock_data(blocker, blocked, block_activity, activity_id),
+ {:ok, activity} <- insert(unblock_data, local),
+ :ok <- maybe_federate(activity) do
+ {:ok, activity}
+ end
+ end
+
def fetch_activities_for_context(context, opts \\ %{}) do
public = ["https://www.w3.org/ns/activitystreams#Public"]
@@ -476,6 +509,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
"url" => [%{"href" => data["image"]["url"]}]
}
+ locked = data["manuallyApprovesFollowers"] || false
data = Transmogrifier.maybe_fix_user_object(data)
user_data = %{
@@ -483,7 +517,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
info: %{
"ap_enabled" => true,
"source_data" => data,
- "banner" => banner
+ "banner" => banner,
+ "locked" => locked
},
avatar: avatar,
nickname: "#{data["preferredUsername"]}@#{URI.parse(data["id"]).host}",
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index a31452a63..3c9377be9 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Activity
alias Pleroma.Repo
alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Utils
import Ecto.Query
@@ -145,6 +146,78 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
+ defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
+ with true <- id =~ "follows",
+ %User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
+ %Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do
+ {:ok, activity}
+ else
+ _ -> {:error, nil}
+ end
+ end
+
+ defp mastodon_follow_hack(_), do: {:error, nil}
+
+ defp get_follow_activity(follow_object, followed) do
+ with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object),
+ {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do
+ {:ok, activity}
+ else
+ # Can't find the activity. This might a Mastodon 2.3 "Accept"
+ {:activity, nil} ->
+ mastodon_follow_hack(follow_object, followed)
+
+ _ ->
+ {:error, nil}
+ end
+ end
+
+ def handle_incoming(
+ %{"type" => "Accept", "object" => follow_object, "actor" => actor, "id" => id} = data
+ ) do
+ with %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, follow_activity} <- get_follow_activity(follow_object, followed),
+ %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
+ {:ok, activity} <-
+ ActivityPub.accept(%{
+ to: follow_activity.data["to"],
+ type: "Accept",
+ actor: followed.ap_id,
+ object: follow_activity.data["id"],
+ local: false
+ }) do
+ if not User.following?(follower, followed) do
+ {:ok, follower} = User.follow(follower, followed)
+ end
+
+ {:ok, activity}
+ else
+ _e -> :error
+ end
+ end
+
+ def handle_incoming(
+ %{"type" => "Reject", "object" => follow_object, "actor" => actor, "id" => id} = data
+ ) do
+ with %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, follow_activity} <- get_follow_activity(follow_object, followed),
+ %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
+ {:ok, activity} <-
+ ActivityPub.accept(%{
+ to: follow_activity.data["to"],
+ type: "Accept",
+ actor: followed.ap_id,
+ object: follow_activity.data["id"],
+ local: false
+ }) do
+ User.unfollow(follower, followed)
+
+ {:ok, activity}
+ else
+ _e -> :error
+ end
+ end
+
def handle_incoming(
%{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = _data
) do
@@ -207,11 +280,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def handle_incoming(
%{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data
) do
- object_id =
- case object_id do
- %{"id" => id} -> id
- id -> id
- end
+ object_id = Utils.get_ap_id(object_id)
with %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <-
@@ -229,7 +298,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
"object" => %{"type" => "Announce", "object" => object_id},
"actor" => actor,
"id" => id
- } = data
+ } = _data
) do
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <-
@@ -237,6 +306,61 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, activity, _, _} <- ActivityPub.unannounce(actor, object, id, false) do
{:ok, activity}
else
+ _e -> :error
+ end
+ end
+
+ def handle_incoming(
+ %{
+ "type" => "Undo",
+ "object" => %{"type" => "Follow", "object" => followed},
+ "actor" => follower,
+ "id" => id
+ } = _data
+ ) do
+ with %User{local: true} = followed <- User.get_cached_by_ap_id(followed),
+ %User{} = follower <- User.get_or_fetch_by_ap_id(follower),
+ {:ok, activity} <- ActivityPub.unfollow(follower, followed, id, false) do
+ User.unfollow(follower, followed)
+ {:ok, activity}
+ else
+ e -> :error
+ end
+ end
+
+ @ap_config Application.get_env(:pleroma, :activitypub)
+ @accept_blocks Keyword.get(@ap_config, :accept_blocks)
+
+ def handle_incoming(
+ %{
+ "type" => "Undo",
+ "object" => %{"type" => "Block", "object" => blocked},
+ "actor" => blocker,
+ "id" => id
+ } = _data
+ ) do
+ with true <- @accept_blocks,
+ %User{local: true} = blocked <- User.get_cached_by_ap_id(blocked),
+ %User{} = blocker <- User.get_or_fetch_by_ap_id(blocker),
+ {:ok, activity} <- ActivityPub.unblock(blocker, blocked, id, false) do
+ User.unblock(blocker, blocked)
+ {:ok, activity}
+ else
+ e -> :error
+ end
+ end
+
+ def handle_incoming(
+ %{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = data
+ ) do
+ with true <- @accept_blocks,
+ %User{local: true} = blocked = User.get_cached_by_ap_id(blocked),
+ %User{} = blocker = User.get_or_fetch_by_ap_id(blocker),
+ {:ok, activity} <- ActivityPub.block(blocker, blocked, id, false) do
+ User.unfollow(blocker, blocked)
+ User.block(blocker, blocked)
+ {:ok, activity}
+ else
e -> :error
end
end
@@ -247,7 +371,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
"object" => %{"type" => "Like", "object" => object_id},
"actor" => actor,
"id" => id
- } = data
+ } = _data
) do
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <-
@@ -255,14 +379,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, activity, _, _} <- ActivityPub.unlike(actor, object, id, false) do
{:ok, activity}
else
- e -> :error
+ _e -> :error
end
end
- # TODO
- # Accept
- # Undo for non-Announce
-
def handle_incoming(_), do: :error
def get_obj_helper(id) do
@@ -516,10 +636,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def maybe_fix_user_url(data) do
if is_map(data["url"]) do
- data = Map.put(data, "url", data["url"]["href"])
+ Map.put(data, "url", data["url"]["href"])
+ else
+ data
end
-
- data
end
def maybe_fix_user_object(data) do
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 937f032c3..56b80a8db 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -7,18 +7,15 @@ defmodule Pleroma.Web.ActivityPub.Utils do
# 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"]
+ def get_ap_id(object) do
+ case object do
+ %{"id" => id} -> id
+ id -> id
end
end
def normalize_params(params) do
- Map.put(params, "actor", normalize_actor(params["actor"]))
+ Map.put(params, "actor", get_ap_id(params["actor"]))
end
def make_json_ld_header do
@@ -240,9 +237,15 @@ defmodule Pleroma.Web.ActivityPub.Utils do
activity in Activity,
where:
fragment(
+ "? ->> 'type' = 'Follow'",
+ activity.data
+ ),
+ where: activity.actor == ^follower_id,
+ where:
+ fragment(
"? @> ?",
activity.data,
- ^%{type: "Follow", actor: follower_id, object: followed_id}
+ ^%{object: followed_id}
),
order_by: [desc: :id],
limit: 1
@@ -260,7 +263,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
query =
from(
activity in Activity,
- where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
+ where: activity.actor == ^actor,
# this is to use the index
where:
fragment(
@@ -346,13 +349,61 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Unfollow-related helpers
- def make_unfollow_data(follower, followed, follow_activity) do
- %{
+ def make_unfollow_data(follower, followed, follow_activity, activity_id) do
+ data = %{
"type" => "Undo",
"actor" => follower.ap_id,
"to" => [followed.ap_id],
- "object" => follow_activity.data["id"]
+ "object" => follow_activity.data
+ }
+
+ if activity_id, do: Map.put(data, "id", activity_id), else: data
+ end
+
+ #### Block-related helpers
+ def fetch_latest_block(%User{ap_id: blocker_id}, %User{ap_id: blocked_id}) do
+ query =
+ from(
+ activity in Activity,
+ where:
+ fragment(
+ "? ->> 'type' = 'Block'",
+ activity.data
+ ),
+ where: activity.actor == ^blocker_id,
+ where:
+ fragment(
+ "? @> ?",
+ activity.data,
+ ^%{object: blocked_id}
+ ),
+ order_by: [desc: :id],
+ limit: 1
+ )
+
+ Repo.one(query)
+ end
+
+ def make_block_data(blocker, blocked, activity_id) do
+ data = %{
+ "type" => "Block",
+ "actor" => blocker.ap_id,
+ "to" => [blocked.ap_id],
+ "object" => blocked.ap_id
+ }
+
+ if activity_id, do: Map.put(data, "id", activity_id), else: data
+ end
+
+ def make_unblock_data(blocker, blocked, block_activity, activity_id) do
+ data = %{
+ "type" => "Undo",
+ "actor" => blocker.ap_id,
+ "to" => [blocked.ap_id],
+ "object" => block_activity.data
}
+
+ if activity_id, do: Map.put(data, "id", activity_id), else: data
end
#### Create-related helpers
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index ffd76b529..f4b2e0610 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"name" => user.name,
"summary" => user.bio,
"url" => user.ap_id,
- "manuallyApprovesFollowers" => false,
+ "manuallyApprovesFollowers" => user.info["locked"] || false,
"publicKey" => %{
"id" => "#{user.ap_id}#main-key",
"owner" => user.ap_id,
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index e774743a2..9c9951371 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -133,7 +133,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
"context" => context,
"attachment" => attachments,
"actor" => actor,
- "tag" => tags |> Enum.map(fn {_, tag} -> tag end)
+ "tag" => tags |> Enum.map(fn {_, tag} -> tag end) |> Enum.uniq()
}
if inReplyTo do
@@ -187,9 +187,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
end
- def confirm_current_password(user, params) do
+ def confirm_current_password(user, password) do
with %User{local: true} = db_user <- Repo.get(User, user.id),
- true <- Pbkdf2.checkpw(params["password"], db_user.password_hash) do
+ true <- Pbkdf2.checkpw(password, db_user.password_hash) do
{:ok, db_user}
else
_ -> {:error, "Invalid password."}
diff --git a/lib/pleroma/web/http_signatures/http_signatures.ex b/lib/pleroma/web/http_signatures/http_signatures.ex
index 4e0adbc1d..5e42a871b 100644
--- a/lib/pleroma/web/http_signatures/http_signatures.ex
+++ b/lib/pleroma/web/http_signatures/http_signatures.ex
@@ -32,14 +32,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 <- Utils.normalize_actor(conn.params["actor"]),
+ with actor_id <- Utils.get_ap_id(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 <- Utils.normalize_actor(conn.params["actor"]),
+ with actor_id <- Utils.get_ap_id(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 c38412911..8dbbe3871 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -2,7 +2,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
use Pleroma.Web, :controller
alias Pleroma.{Repo, Activity, User, Notification, Stats}
alias Pleroma.Web
- alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView}
+ alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView}
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.{CommonAPI, OStatus}
alias Pleroma.Web.OAuth.{Authorization, Token, App}
@@ -284,11 +284,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
{:ok, activity} =
- Cachex.get!(
- :idempotency_cache,
- idempotency_key,
- fallback: fn _ -> CommonAPI.post(user, params) end
- )
+ Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ -> CommonAPI.post(user, params) end)
render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
end
@@ -442,7 +438,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
with %User{} = followed <- Repo.get(User, id),
- {:ok, follower} <- User.follow(follower, followed),
+ {:ok, follower} <- User.maybe_direct_follow(follower, followed),
{:ok, _activity} <- ActivityPub.follow(follower, followed) do
render(conn, AccountView, "relationship.json", %{user: follower, target: followed})
else
@@ -455,7 +451,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
with %User{} = followed <- Repo.get_by(User, nickname: uri),
- {:ok, follower} <- User.follow(follower, followed),
+ {:ok, follower} <- User.maybe_direct_follow(follower, followed),
{:ok, _activity} <- ActivityPub.follow(follower, followed) do
render(conn, AccountView, "account.json", %{user: followed})
else
@@ -466,24 +462,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
- # TODO: Clean up and unify
def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
with %User{} = followed <- Repo.get(User, id),
- {:ok, follower, follow_activity} <- User.unfollow(follower, followed),
- {:ok, _activity} <-
- ActivityPub.insert(%{
- "type" => "Undo",
- "actor" => follower.ap_id,
- # get latest Follow for these users
- "object" => follow_activity.data["id"]
- }) do
+ {:ok, _activity} <- ActivityPub.unfollow(follower, followed),
+ {:ok, follower, _} <- User.unfollow(follower, followed) do
render(conn, AccountView, "relationship.json", %{user: follower, target: followed})
end
end
def block(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
with %User{} = blocked <- Repo.get(User, id),
- {:ok, blocker} <- User.block(blocker, blocked) do
+ {:ok, blocker} <- User.block(blocker, blocked),
+ {:ok, _activity} <- ActivityPub.block(blocker, blocked) do
render(conn, AccountView, "relationship.json", %{user: blocker, target: blocked})
else
{:error, message} ->
@@ -495,7 +485,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def unblock(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
with %User{} = blocked <- Repo.get(User, id),
- {:ok, blocker} <- User.unblock(blocker, blocked) do
+ {:ok, blocker} <- User.unblock(blocker, blocked),
+ {:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do
render(conn, AccountView, "relationship.json", %{user: blocker, target: blocked})
else
{:error, message} ->
@@ -586,6 +577,102 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity})
end
+ def get_lists(%{assigns: %{user: user}} = conn, opts) do
+ lists = Pleroma.List.for_user(user, opts)
+ res = ListView.render("lists.json", lists: lists)
+ json(conn, res)
+ end
+
+ def get_list(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ with %Pleroma.List{} = list <- Pleroma.List.get(id, user) do
+ res = ListView.render("list.json", list: list)
+ json(conn, res)
+ else
+ _e -> json(conn, "error")
+ end
+ end
+
+ def delete_list(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ with %Pleroma.List{} = list <- Pleroma.List.get(id, user),
+ {:ok, _list} <- Pleroma.List.delete(list) do
+ json(conn, %{})
+ else
+ _e ->
+ json(conn, "error")
+ end
+ end
+
+ def create_list(%{assigns: %{user: user}} = conn, %{"title" => title}) do
+ with {:ok, %Pleroma.List{} = list} <- Pleroma.List.create(title, user) do
+ res = ListView.render("list.json", list: list)
+ json(conn, res)
+ end
+ end
+
+ def add_to_list(%{assigns: %{user: user}} = conn, %{"id" => id, "account_ids" => accounts}) do
+ accounts
+ |> Enum.each(fn account_id ->
+ with %Pleroma.List{} = list <- Pleroma.List.get(id, user),
+ %User{} = followed <- Repo.get(User, account_id) do
+ Pleroma.List.follow(list, followed)
+ end
+ end)
+
+ json(conn, %{})
+ end
+
+ def remove_from_list(%{assigns: %{user: user}} = conn, %{"id" => id, "account_ids" => accounts}) do
+ accounts
+ |> Enum.each(fn account_id ->
+ with %Pleroma.List{} = list <- Pleroma.List.get(id, user),
+ %User{} = followed <- Repo.get(Pleroma.User, account_id) do
+ Pleroma.List.unfollow(list, followed)
+ end
+ end)
+
+ json(conn, %{})
+ end
+
+ def list_accounts(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ with %Pleroma.List{} = list <- Pleroma.List.get(id, user),
+ {:ok, users} = Pleroma.List.get_following(list) do
+ render(conn, AccountView, "accounts.json", %{users: users, as: :user})
+ end
+ end
+
+ def rename_list(%{assigns: %{user: user}} = conn, %{"id" => id, "title" => title}) do
+ with %Pleroma.List{} = list <- Pleroma.List.get(id, user),
+ {:ok, list} <- Pleroma.List.rename(list, title) do
+ res = ListView.render("list.json", list: list)
+ json(conn, res)
+ else
+ _e ->
+ json(conn, "error")
+ end
+ end
+
+ def list_timeline(%{assigns: %{user: user}} = conn, %{"list_id" => id} = params) do
+ with %Pleroma.List{title: title, following: following} <- Pleroma.List.get(id, user) do
+ params =
+ params
+ |> Map.put("type", "Create")
+ |> Map.put("blocking_user", user)
+
+ # adding title is a hack to not make empty lists function like a public timeline
+ activities =
+ ActivityPub.fetch_activities([title | following], params)
+ |> Enum.reverse()
+
+ conn
+ |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity})
+ else
+ _e ->
+ conn
+ |> put_status(403)
+ |> json(%{error: "Error."})
+ end
+ end
+
def index(%{assigns: %{user: user}} = conn, _params) do
token =
conn
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index f378bb36e..9db683f44 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
username: hd(String.split(user.nickname, "@")),
acct: user.nickname,
display_name: user.name || user.nickname,
- locked: false,
+ locked: user_info.locked,
created_at: Utils.to_masto_date(user.inserted_at),
followers_count: user_info.follower_count,
following_count: user_info.following_count,
diff --git a/lib/pleroma/web/mastodon_api/views/list_view.ex b/lib/pleroma/web/mastodon_api/views/list_view.ex
new file mode 100644
index 000000000..1a1b7430b
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/views/list_view.ex
@@ -0,0 +1,15 @@
+defmodule Pleroma.Web.MastodonAPI.ListView do
+ use Pleroma.Web, :view
+ alias Pleroma.Web.MastodonAPI.ListView
+
+ def render("lists.json", %{lists: lists} = opts) do
+ render_many(lists, ListView, "list.json", opts)
+ end
+
+ def render("list.json", %{list: list}) do
+ %{
+ id: to_string(list.id),
+ title: list.title
+ }
+ end
+end
diff --git a/lib/pleroma/web/ostatus/activity_representer.ex b/lib/pleroma/web/ostatus/activity_representer.ex
index 64cadba1b..4179d86c9 100644
--- a/lib/pleroma/web/ostatus/activity_representer.ex
+++ b/lib/pleroma/web/ostatus/activity_representer.ex
@@ -232,7 +232,12 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
end
# Only undos of follow for now. Will need to get redone once there are more
- def to_simple_form(%{data: %{"type" => "Undo"}} = activity, user, with_author) do
+ def to_simple_form(
+ %{data: %{"type" => "Undo", "object" => %{"type" => "Follow"} = follow_activity}} =
+ activity,
+ user,
+ with_author
+ ) do
h = fn str -> [to_charlist(str)] end
updated_at = activity.data["published"]
@@ -240,34 +245,26 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: []
- follow_activity =
- if is_map(activity.data["object"]) do
- Activity.get_by_ap_id(activity.data["object"]["id"])
- else
- Activity.get_by_ap_id(activity.data["object"])
- end
-
mentions = (activity.recipients || []) |> get_mentions
+ follow_activity = Activity.get_by_ap_id(follow_activity["id"])
- if follow_activity do
- [
- {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']},
- {:"activity:verb", ['http://activitystrea.ms/schema/1.0/unfollow']},
- {:id, h.(activity.data["id"])},
- {:title, ['#{user.nickname} stopped following #{follow_activity.data["object"]}']},
- {:content, [type: 'html'],
- ['#{user.nickname} stopped following #{follow_activity.data["object"]}']},
- {:published, h.(inserted_at)},
- {:updated, h.(updated_at)},
- {:"activity:object",
- [
- {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/person']},
- {:id, h.(follow_activity.data["object"])},
- {:uri, h.(follow_activity.data["object"])}
- ]},
- {:link, [rel: 'self', type: ['application/atom+xml'], href: h.(activity.data["id"])], []}
- ] ++ mentions ++ author
- end
+ [
+ {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']},
+ {:"activity:verb", ['http://activitystrea.ms/schema/1.0/unfollow']},
+ {:id, h.(activity.data["id"])},
+ {:title, ['#{user.nickname} stopped following #{follow_activity.data["object"]}']},
+ {:content, [type: 'html'],
+ ['#{user.nickname} stopped following #{follow_activity.data["object"]}']},
+ {:published, h.(inserted_at)},
+ {:updated, h.(updated_at)},
+ {:"activity:object",
+ [
+ {:"activity:object-type", ['http://activitystrea.ms/schema/1.0/person']},
+ {:id, h.(follow_activity.data["object"])},
+ {:uri, h.(follow_activity.data["object"])}
+ ]},
+ {:link, [rel: 'self', type: ['application/atom+xml'], href: h.(activity.data["id"])], []}
+ ] ++ mentions ++ author
end
def to_simple_form(%{data: %{"type" => "Delete"}} = activity, user, with_author) do
diff --git a/lib/pleroma/web/ostatus/handlers/unfollow_handler.ex b/lib/pleroma/web/ostatus/handlers/unfollow_handler.ex
new file mode 100644
index 000000000..a115bf4c8
--- /dev/null
+++ b/lib/pleroma/web/ostatus/handlers/unfollow_handler.ex
@@ -0,0 +1,17 @@
+defmodule Pleroma.Web.OStatus.UnfollowHandler do
+ alias Pleroma.Web.{XML, OStatus}
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.User
+
+ def handle(entry, doc) do
+ with {:ok, actor} <- OStatus.find_make_or_update_user(doc),
+ id when not is_nil(id) <- XML.string_from_xpath("/entry/id", entry),
+ followed_uri when not is_nil(followed_uri) <-
+ XML.string_from_xpath("/entry/activity:object/id", entry),
+ {:ok, followed} <- OStatus.find_or_make_user(followed_uri),
+ {:ok, activity} <- ActivityPub.unfollow(actor, followed, id, false) do
+ User.unfollow(actor, followed)
+ {:ok, activity}
+ end
+ end
+end
diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex
index 5c4a1fd69..f0ff0624f 100644
--- a/lib/pleroma/web/ostatus/ostatus.ex
+++ b/lib/pleroma/web/ostatus/ostatus.ex
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.OStatus do
alias Pleroma.{Repo, User, Web, Object, Activity}
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.{WebFinger, Websub}
- alias Pleroma.Web.OStatus.{FollowHandler, NoteHandler, DeleteHandler}
+ alias Pleroma.Web.OStatus.{FollowHandler, UnfollowHandler, NoteHandler, DeleteHandler}
alias Pleroma.Web.ActivityPub.Transmogrifier
def feed_path(user) do
@@ -47,6 +47,9 @@ defmodule Pleroma.Web.OStatus do
'http://activitystrea.ms/schema/1.0/follow' ->
with {:ok, activity} <- FollowHandler.handle(entry, doc), do: activity
+ 'http://activitystrea.ms/schema/1.0/unfollow' ->
+ with {:ok, activity} <- UnfollowHandler.handle(entry, doc), do: activity
+
'http://activitystrea.ms/schema/1.0/share' ->
with {:ok, activity, retweeted_activity} <- handle_share(entry, doc),
do: [activity, retweeted_activity]
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 87fd664f6..924254895 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("/change_password", UtilController, :change_password)
post("/delete_account", UtilController, :delete_account)
end
@@ -103,7 +104,6 @@ defmodule Pleroma.Web.Router do
get("/domain_blocks", MastodonAPIController, :empty_array)
get("/follow_requests", MastodonAPIController, :empty_array)
get("/mutes", MastodonAPIController, :empty_array)
- get("/lists", MastodonAPIController, :empty_array)
get("/timelines/home", MastodonAPIController, :home_timeline)
@@ -125,6 +125,15 @@ defmodule Pleroma.Web.Router do
get("/notifications/:id", MastodonAPIController, :get_notification)
post("/media", MastodonAPIController, :upload)
+
+ get("/lists", MastodonAPIController, :get_lists)
+ get("/lists/:id", MastodonAPIController, :get_list)
+ delete("/lists/:id", MastodonAPIController, :delete_list)
+ post("/lists", MastodonAPIController, :create_list)
+ put("/lists/:id", MastodonAPIController, :rename_list)
+ get("/lists/:id/accounts", MastodonAPIController, :list_accounts)
+ post("/lists/:id/accounts", MastodonAPIController, :add_to_list)
+ delete("/lists/:id/accounts", MastodonAPIController, :remove_from_list)
end
scope "/api/web", Pleroma.Web.MastodonAPI do
@@ -142,6 +151,7 @@ defmodule Pleroma.Web.Router do
get("/timelines/public", MastodonAPIController, :public_timeline)
get("/timelines/tag/:tag", MastodonAPIController, :hashtag_timeline)
+ get("/timelines/list/:list_id", MastodonAPIController, :list_timeline)
get("/statuses/:id", MastodonAPIController, :get_status)
get("/statuses/:id/context", MastodonAPIController, :get_context)
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 23e7408a0..cc5146566 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -197,8 +197,31 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
json(conn, "job started")
end
+ def change_password(%{assigns: %{user: user}} = conn, params) do
+ case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
+ {:ok, user} ->
+ with {:ok, _user} <-
+ User.reset_password(user, %{
+ password: params["new_password"],
+ password_confirmation: params["new_password_confirmation"]
+ }) do
+ json(conn, %{status: "success"})
+ else
+ {:error, changeset} ->
+ {_, {error, _}} = Enum.at(changeset.errors, 0)
+ json(conn, %{error: "New password #{error}."})
+
+ _ ->
+ json(conn, %{error: "Unable to change password."})
+ end
+
+ {:error, msg} ->
+ json(conn, %{error: msg})
+ end
+ end
+
def delete_account(%{assigns: %{user: user}} = conn, params) do
- case CommonAPI.Utils.confirm_current_password(user, params) do
+ case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
{:ok, user} ->
Task.start(fn -> User.delete(user) end)
json(conn, %{status: "success"})
diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex
index c2e1f07a5..57837205e 100644
--- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex
+++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
) do
created_at = created_at |> Utils.date_to_asctime()
- text = "#{user.nickname} undid the action at #{undid_activity}"
+ text = "#{user.nickname} undid the action at #{undid_activity["id"]}"
%{
"id" => activity.id,
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 722e436e2..331efa90b 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
def follow(%User{} = follower, params) do
with {:ok, %User{} = followed} <- get_user(params),
- {:ok, follower} <- User.follow(follower, followed),
+ {:ok, follower} <- User.maybe_direct_follow(follower, followed),
{:ok, activity} <- ActivityPub.follow(follower, followed) do
{:ok, follower, followed, activity}
else
@@ -36,14 +36,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
def unfollow(%User{} = follower, params) do
with {:ok, %User{} = unfollowed} <- get_user(params),
{:ok, follower, follow_activity} <- User.unfollow(follower, unfollowed),
- {:ok, _activity} <-
- ActivityPub.insert(%{
- "type" => "Undo",
- "actor" => follower.ap_id,
- # get latest Follow for these users
- "object" => follow_activity.data["id"],
- "published" => make_date()
- }) do
+ {:ok, _activity} <- ActivityPub.unfollow(follower, unfollowed) do
{:ok, follower, unfollowed}
else
err -> err
@@ -52,7 +45,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
def block(%User{} = blocker, params) do
with {:ok, %User{} = blocked} <- get_user(params),
- {:ok, blocker} <- User.block(blocker, blocked) do
+ {:ok, blocker} <- User.block(blocker, blocked),
+ {:ok, _activity} <- ActivityPub.block(blocker, blocked) do
{:ok, blocker, blocked}
else
err -> err
@@ -61,7 +55,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
def unblock(%User{} = blocker, params) do
with {:ok, %User{} = blocked} <- get_user(params),
- {:ok, blocker} <- User.unblock(blocker, blocked) do
+ {:ok, blocker} <- User.unblock(blocker, blocked),
+ {:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do
{:ok, blocker, blocked}
else
err -> err