diff --git a/config/test.exs b/config/test.exs index e0461e93d..0c73f892a 100644 --- a/config/test.exs +++ b/config/test.exs @@ -26,3 +26,12 @@ config :pleroma, :websub, Pleroma.Web.WebsubMock config :pleroma, :ostatus, Pleroma.Web.OStatusMock config :pleroma, :httpoison, HTTPoisonMock + +try do + import_config "test.secret.exs" +rescue + _ -> + IO.puts( + "You may want to create test.secret.exs to declare custom database connection parameters." + ) +end diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 895799a8e..44905da49 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -59,6 +59,16 @@ server { } # stop removing lines here. + add_header X-XSS-Protection "1; mode=block"; + add_header X-Permitted-Cross-Domain-Policies none; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header Referrer-Policy same-origin; + add_header X-Download-Options noopen; + + # Uncomment this only after you get HTTPS working. + # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; + proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; diff --git a/installation/pleroma.service b/installation/pleroma.service index fe314ed2b..fd4180985 100644 --- a/installation/pleroma.service +++ b/installation/pleroma.service @@ -13,4 +13,3 @@ Restart=on-failure [Install] WantedBy=multi-user.target -Alias=pleroma.service diff --git a/installation/pleroma.vcl b/installation/pleroma.vcl index fe9bf056b..63c1cb74d 100644 --- a/installation/pleroma.vcl +++ b/installation/pleroma.vcl @@ -39,15 +39,9 @@ sub vcl_recv { return (hash); } - # Hack to enable a Terms of Service page missing from Pleroma - if (req.url ~ "^/about/more$") { - set req.http.x-redir = "https://" + req.http.host + "/static/terms-of-service.html"; - return (synth(750, "")); - } - # Strip headers that will affect caching from all other static content # This also permits caching of individual toots and AP Activities - if ((req.url ~ "^/(media|notice|objects|static)/") || + if ((req.url ~ "^/(media|static)/") || (req.url ~ "(?i)\.(html|js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$")) { unset req.http.Cookie; @@ -99,8 +93,7 @@ sub vcl_backend_response { # Strip cache-restricting headers from Pleroma on static content that we want to cache # Also enable streaming of cached content to clients (no waiting for Varnish to complete backend fetch) - if ((bereq.url ~ "^/(notice|objects)/") || - (bereq.url ~ "(?i)\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$")) + if (bereq.url ~ "(?i)\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$") { unset beresp.http.set-cookie; unset beresp.http.Cache-Control; diff --git a/lib/mix/tasks/fix_ap_users.ex b/lib/mix/tasks/fix_ap_users.ex index 2523cdbcb..7e970850e 100644 --- a/lib/mix/tasks/fix_ap_users.ex +++ b/lib/mix/tasks/fix_ap_users.ex @@ -1,6 +1,5 @@ defmodule Mix.Tasks.FixApUsers do use Mix.Task - import Mix.Ecto import Ecto.Query alias Pleroma.{Repo, User} diff --git a/lib/mix/tasks/generate_password_reset.ex b/lib/mix/tasks/generate_password_reset.ex index e39134007..6bf640150 100644 --- a/lib/mix/tasks/generate_password_reset.ex +++ b/lib/mix/tasks/generate_password_reset.ex @@ -1,7 +1,6 @@ defmodule Mix.Tasks.GeneratePasswordReset do use Mix.Task - import Mix.Ecto - alias Pleroma.{Repo, User} + alias Pleroma.User @shortdoc "Generate password reset link for user" def run([nickname]) do diff --git a/lib/mix/tasks/register_user.ex b/lib/mix/tasks/register_user.ex index 4bec6b9d9..e74721c49 100644 --- a/lib/mix/tasks/register_user.ex +++ b/lib/mix/tasks/register_user.ex @@ -1,6 +1,5 @@ defmodule Mix.Tasks.RegisterUser do use Mix.Task - import Mix.Ecto alias Pleroma.{Repo, User} @shortdoc "Register user" diff --git a/lib/mix/tasks/rm_user.ex b/lib/mix/tasks/rm_user.ex index 6a698f360..27521b745 100644 --- a/lib/mix/tasks/rm_user.ex +++ b/lib/mix/tasks/rm_user.ex @@ -1,7 +1,6 @@ defmodule Mix.Tasks.RmUser do use Mix.Task - import Mix.Ecto - alias Pleroma.{User, Repo} + alias Pleroma.User @shortdoc "Permanently delete a user" def run([nickname]) do diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 89826f515..e1e3bcd63 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -23,6 +23,18 @@ def start(_type, _args) do limit: 2500 ] ]), + worker( + Cachex, + [ + :idempotency_cache, + [ + default_ttl: :timer.seconds(6 * 60 * 60), + ttl_interval: :timer.seconds(60), + limit: 2500 + ] + ], + id: :cachex_idem + ), worker(Pleroma.Web.Federator, []), worker(Pleroma.Gopher.Server, []), worker(Pleroma.Stats, []) diff --git a/lib/pleroma/gopher/server.ex b/lib/pleroma/gopher/server.ex index 82e241f21..f6abcd4d0 100644 --- a/lib/pleroma/gopher/server.ex +++ b/lib/pleroma/gopher/server.ex @@ -65,12 +65,6 @@ def link(name, selector, type \\ 1) do "#{type}#{name}\t#{selector}\t#{address}\t#{port}\r\n" end - def response("") do - info("Welcome to #{Keyword.get(@instance, :name, "Pleroma")}!") <> - link("Public Timeline", "/main/public") <> - link("Federated Timeline", "/main/all") <> ".\r\n" - end - def render_activities(activities) do activities |> Enum.reverse() @@ -93,6 +87,12 @@ def render_activities(activities) do |> Enum.join("\r\n") end + def response("") do + info("Welcome to #{Keyword.get(@instance, :name, "Pleroma")}!") <> + link("Public Timeline", "/main/public") <> + link("Federated Timeline", "/main/all") <> ".\r\n" + end + def response("/main/public") do posts = ActivityPub.fetch_public_activities(%{"type" => ["Create"], "local_only" => true}) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index e26e49c8c..e0dcd9823 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -91,7 +91,8 @@ def create_notifications(_), do: {:ok, []} # TODO move to sql, too. def create_notification(%Activity{} = activity, %User{} = user) do - unless User.blocks?(user, %{ap_id: activity.data["actor"]}) do + unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or + user.ap_id == activity.data["actor"] do notification = %Notification{user_id: user.id, activity: activity} {:ok, notification} = Repo.insert(notification) Pleroma.Web.Streamer.stream("user", notification) diff --git a/lib/pleroma/plugs/http_signature.ex b/lib/pleroma/plugs/http_signature.ex index 8b9ccdd2d..efde652f5 100644 --- a/lib/pleroma/plugs/http_signature.ex +++ b/lib/pleroma/plugs/http_signature.ex @@ -7,11 +7,11 @@ def init(options) do options end - def call(%{assigns: %{valid_signature: true}} = conn, opts) do + def call(%{assigns: %{valid_signature: true}} = conn, _opts) do conn end - def call(conn, opts) do + def call(conn, _opts) do user = conn.params["actor"] Logger.debug("Checking sig for #{user}") [signature | _] = get_req_header(conn, "signature") diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index 83b896a16..8478fe4ce 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -1,6 +1,6 @@ defmodule Pleroma.Stats do import Ecto.Query - alias Pleroma.{User, Repo, Activity} + alias Pleroma.{User, Repo} def start_link do agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 9e0b038ed..6a413c69c 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1,6 +1,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.{Activity, Repo, Object, Upload, User, Notification} - alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.ActivityPub.{Transmogrifier, MRF} alias Pleroma.Web.WebFinger alias Pleroma.Web.Federator alias Pleroma.Web.OStatus @@ -11,7 +11,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do @httpoison Application.get_env(:pleroma, :httpoison) @instance Application.get_env(:pleroma, :instance) - @rewrite_policy Keyword.get(@instance, :rewrite_policy) def get_recipients(data) do (data["to"] || []) ++ (data["cc"] || []) @@ -20,8 +19,8 @@ def get_recipients(data) do 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 <- insert_full_object(map), - {:ok, map} <- @rewrite_policy.filter(map) do + {:ok, map} <- MRF.filter(map), + :ok <- insert_full_object(map) do {:ok, activity} = Repo.insert(%Activity{ data: map, @@ -66,7 +65,7 @@ def create(%{to: to, actor: actor, context: context, object: object} = params) d ), {:ok, activity} <- insert(create_data, local), :ok <- maybe_federate(activity), - {:ok, actor} <- User.increase_note_count(actor) do + {:ok, _actor} <- User.increase_note_count(actor) do {:ok, activity} end end @@ -177,7 +176,7 @@ def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, local \\ tru Repo.delete_all(Activity.all_non_create_by_object_ap_id_q(id)), {:ok, activity} <- insert(data, local), :ok <- maybe_federate(activity), - {:ok, actor} <- User.decrease_note_count(user) do + {:ok, _actor} <- User.decrease_note_count(user) do {:ok, activity} end end @@ -236,7 +235,7 @@ defp restrict_tag(query, %{"tag" => tag}) do defp restrict_tag(query, _), do: query - defp restrict_recipients(query, [], user), do: query + defp restrict_recipients(query, [], _user), do: query defp restrict_recipients(query, recipients, nil) do from(activity in query, where: fragment("? && ?", ^recipients, activity.recipients)) @@ -313,7 +312,9 @@ defp restrict_recent(query, _) do defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do blocks = info["blocks"] || [] - from(activity in query, + + from( + activity in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocks), where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks) ) @@ -405,7 +406,7 @@ def fetch_and_prepare_user_from_ap_id(ap_id) do end def make_user_from_ap_id(ap_id) do - if user = User.get_by_ap_id(ap_id) do + if _user = User.get_by_ap_id(ap_id) do Transmogrifier.upgrade_user_from_ap_id(ap_id) else with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do @@ -501,7 +502,7 @@ def fetch_object_from_id(id) do object = %Object{} -> {:ok, object} - e -> + _e -> Logger.info("Couldn't get object via AP, trying out OStatus fetching...") case OStatus.fetch_activity_from_url(id) do diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 12f61f5f0..80aae4f0f 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do use Pleroma.Web, :controller - alias Pleroma.{User, Repo, Object, Activity} - alias Pleroma.Web.ActivityPub.{ObjectView, UserView, Transmogrifier} + alias Pleroma.{User, Object} + alias Pleroma.Web.ActivityPub.{ObjectView, UserView} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.Federator diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex new file mode 100644 index 000000000..0a4e2bf80 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf.ex @@ -0,0 +1,24 @@ +defmodule Pleroma.Web.ActivityPub.MRF do + @callback filter(Map.t()) :: {:ok | :reject, Map.t()} + + def filter(object) do + get_policies() + |> Enum.reduce({:ok, object}, fn + policy, {:ok, object} -> + policy.filter(object) + + _, error -> + error + end) + end + + def get_policies() do + Application.get_env(:pleroma, :instance, []) + |> Keyword.get(:rewrite_policy, []) + |> get_policies() + end + + defp get_policies(policy) when is_atom(policy), do: [policy] + defp get_policies(policies) when is_list(policies), do: policies + defp get_policies(_), do: [] +end diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex index 4333bca28..811947943 100644 --- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex @@ -1,6 +1,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do require Logger + @behaviour Pleroma.Web.ActivityPub.MRF + @impl true def filter(object) do Logger.info("REJECTING #{inspect(object)}") {:reject, object} diff --git a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex index 9dd3acb04..e26f60d26 100644 --- a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex @@ -1,4 +1,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do + @behaviour Pleroma.Web.ActivityPub.MRF + + @impl true def filter(object) do {:ok, object} end diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex index ea1af0f4d..8d770387d 100644 --- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex @@ -1,5 +1,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do alias Pleroma.User + @behaviour Pleroma.Web.ActivityPub.MRF @mrf_policy Application.get_env(:pleroma, :mrf_simple) @@ -17,9 +18,10 @@ defp check_media_removal(actor_info, object) do if actor_info.host in @media_removal do child_object = Map.delete(object["object"], "attachment") object = Map.put(object, "object", child_object) + {:ok, object} + else + {:ok, object} end - - {:ok, object} end @media_nsfw Keyword.get(@mrf_policy, :media_nsfw) @@ -32,9 +34,10 @@ defp check_media_nsfw(actor_info, object) do child_object = Map.put(child_object, "tags", tags) child_object = Map.put(child_object, "sensitive", true) object = Map.put(object, "object", child_object) + {:ok, object} + else + {:ok, object} end - - {:ok, object} end @ftl_removal Keyword.get(@mrf_policy, :federated_timeline_removal) @@ -43,24 +46,31 @@ defp check_ftl_removal(actor_info, object) do user = User.get_by_ap_id(object["actor"]) # flip to/cc relationship to make the post unlisted - if "https://www.w3.org/ns/activitystreams#Public" in object["to"] and - user.follower_address in object["cc"] do - to = - List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++ - [user.follower_address] + object = + if "https://www.w3.org/ns/activitystreams#Public" in object["to"] and + user.follower_address in object["cc"] do + to = + List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++ + [user.follower_address] - cc = - List.delete(object["cc"], user.follower_address) ++ - ["https://www.w3.org/ns/activitystreams#Public"] + cc = + List.delete(object["cc"], user.follower_address) ++ + ["https://www.w3.org/ns/activitystreams#Public"] - object = Map.put(object, "to", to) - object = Map.put(object, "cc", cc) - end + object + |> Map.put("to", to) + |> Map.put("cc", cc) + else + object + end + + {:ok, object} + else + {:ok, object} end - - {:ok, object} end + @impl true def filter(object) do actor_info = URI.parse(object["actor"]) @@ -70,7 +80,7 @@ def filter(object) do {:ok, object} <- check_ftl_removal(actor_info, object) do {:ok, object} else - e -> {:reject, nil} + _e -> {:reject, nil} end end end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 2871a2544..5f86f67cd 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -72,9 +72,12 @@ def fix_emoji(object) do |> Enum.reduce(%{}, fn data, mapping -> name = data["name"] - if String.starts_with?(name, ":") do - name = name |> String.slice(1..-2) - end + name = + if String.starts_with?(name, ":") do + name |> String.slice(1..-2) + else + name + end mapping |> Map.put(name, data["icon"]["url"]) end) @@ -143,12 +146,12 @@ def handle_incoming( end def handle_incoming( - %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data + %{"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, object} <- ActivityPub.like(actor, object, id, false) do + {:ok, activity, _object} <- ActivityPub.like(actor, object, id, false) do {:ok, activity} else _e -> :error @@ -156,12 +159,12 @@ def handle_incoming( end def handle_incoming( - %{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data + %{"type" => "Announce", "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, object} <- ActivityPub.announce(actor, object, id, false) do + {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false) do {:ok, activity} else _e -> :error @@ -202,7 +205,7 @@ def handle_incoming( # TODO: Make secure. def handle_incoming( - %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data + %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data ) do object_id = case object_id do @@ -210,13 +213,13 @@ def handle_incoming( id -> id end - with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), + 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.delete(object, false) do {:ok, activity} else - e -> :error + _e -> :error end end @@ -254,10 +257,10 @@ def prepare_object(object) do |> set_reply_to_uri end - @doc - """ - internal -> Mastodon - """ + # @doc + # """ + # internal -> Mastodon + # """ def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do object = @@ -272,7 +275,7 @@ def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = obj {:ok, data} end - def prepare_outgoing(%{"type" => type} = data) do + def prepare_outgoing(%{"type" => _type} = data) do data = data |> maybe_fix_object_url @@ -286,7 +289,7 @@ def maybe_fix_object_url(data) do case ActivityPub.fetch_object_from_id(data["object"]) do {:ok, relative_object} -> if relative_object.data["external_url"] do - data = + _data = data |> Map.put("object", relative_object.data["external_url"]) else diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 92afd0872..ffd76b529 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -47,25 +47,6 @@ def render("user.json", %{user: user}) do |> Map.merge(Utils.make_json_ld_header()) end - def collection(collection, iri, page, total \\ nil) do - offset = (page - 1) * 10 - items = Enum.slice(collection, offset, 10) - items = Enum.map(items, fn user -> user.ap_id end) - total = total || length(collection) - - map = %{ - "id" => "#{iri}?page=#{page}", - "type" => "OrderedCollectionPage", - "partOf" => iri, - "totalItems" => length(collection), - "orderedItems" => items - } - - if offset < length(collection) do - Map.put(map, "next", "#{iri}?page=#{page + 1}") - end - end - def render("following.json", %{user: user, page: page}) do query = User.get_friends_query(user) query = from(user in query, select: [:ap_id]) @@ -123,9 +104,12 @@ def render("outbox.json", %{user: user, max_id: max_qid}) do "limit" => "10" } - if max_qid != nil do - params = Map.put(params, "max_id", max_qid) - end + params = + if max_qid != nil do + Map.put(params, "max_id", max_qid) + else + params + end activities = ActivityPub.fetch_public_activities(params) min_id = Enum.at(activities, 0).id @@ -162,4 +146,23 @@ def render("outbox.json", %{user: user, max_id: max_qid}) do page |> Map.merge(Utils.make_json_ld_header()) end end + + def collection(collection, iri, page, total \\ nil) do + offset = (page - 1) * 10 + items = Enum.slice(collection, offset, 10) + items = Enum.map(items, fn user -> user.ap_id end) + total = total || length(collection) + + map = %{ + "id" => "#{iri}?page=#{page}", + "type" => "OrderedCollectionPage", + "partOf" => iri, + "totalItems" => total, + "orderedItems" => items + } + + if offset < total do + Map.put(map, "next", "#{iri}?page=#{page + 1}") + end + end end diff --git a/lib/pleroma/web/channels/user_socket.ex b/lib/pleroma/web/channels/user_socket.ex index fd8918a7d..21b22b409 100644 --- a/lib/pleroma/web/channels/user_socket.ex +++ b/lib/pleroma/web/channels/user_socket.ex @@ -1,7 +1,6 @@ defmodule Pleroma.Web.UserSocket do use Phoenix.Socket alias Pleroma.User - alias Comeonin.Pbkdf2 ## Channels # channel "room:*", Pleroma.Web.RoomChannel diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 2c4b591d4..14a68929d 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -1,5 +1,5 @@ defmodule Pleroma.Web.CommonAPI do - alias Pleroma.{Repo, Activity, Object, User} + alias Pleroma.{Repo, Activity, Object} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Formatter diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 3c092d524..57f8be894 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -1,5 +1,5 @@ defmodule Pleroma.Web.CommonAPI.Utils do - alias Pleroma.{Repo, Object, Formatter, User, Activity} + alias Pleroma.{Repo, Object, Formatter, Activity} alias Pleroma.Web.ActivityPub.Utils alias Calendar.Strftime @@ -49,7 +49,7 @@ def to_for_user_and_mentions(user, mentions, inReplyTo, "private") do {[user.follower_address | to], cc} end - def to_for_user_and_mentions(user, mentions, inReplyTo, "direct") do + def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) if inReplyTo do @@ -69,7 +69,7 @@ def make_content_html(status, mentions, attachments, tags, no_attachment_links \ def make_context(%Activity{data: %{"context" => context}}), do: context def make_context(_), do: Utils.generate_context_id() - def maybe_add_attachments(text, attachments, _no_links = true), do: text + def maybe_add_attachments(text, _attachments, _no_links = true), do: text def maybe_add_attachments(text, attachments, _no_links) do add_attachments(text, attachments) diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex index 8335add9c..f84af2f15 100644 --- a/lib/pleroma/web/federator/federator.ex +++ b/lib/pleroma/web/federator/federator.ex @@ -14,6 +14,10 @@ defmodule Pleroma.Web.Federator do @federating Keyword.get(@instance, :federating) @max_jobs 20 + def init(args) do + {:ok, args} + end + def start_link do spawn(fn -> # 1 minute @@ -89,12 +93,12 @@ def handle(:incoming_ap_doc, params) do with {:ok, _user} <- ap_enabled_actor(params["actor"]), nil <- Activity.get_by_ap_id(params["id"]), - {:ok, activity} <- Transmogrifier.handle_incoming(params) do + {:ok, _activity} <- Transmogrifier.handle_incoming(params) do else %Activity{} -> Logger.info("Already had #{params["id"]}") - e -> + _e -> # Just drop those for now Logger.info("Unhandled activity") Logger.info(Poison.encode!(params, pretty: 2)) @@ -154,7 +158,7 @@ def maybe_start_job(running_jobs, queue) do end end - def handle_cast({:enqueue, type, payload, priority}, state) + def handle_cast({:enqueue, type, payload, _priority}, state) when type in [:incoming_doc, :incoming_ap_doc] do %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}} = state i_queue = enqueue_sorted(i_queue, {type, payload}, 1) @@ -162,7 +166,7 @@ def handle_cast({:enqueue, type, payload, priority}, state) {:noreply, %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}}} end - def handle_cast({:enqueue, type, payload, priority}, state) do + def handle_cast({:enqueue, type, payload, _priority}, state) do %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}} = state o_queue = enqueue_sorted(o_queue, {type, payload}, 1) {o_running_jobs, o_queue} = maybe_start_job(o_running_jobs, o_queue) diff --git a/lib/pleroma/web/http_signatures/http_signatures.ex b/lib/pleroma/web/http_signatures/http_signatures.ex index 0ea3b7554..9035f5eb6 100644 --- a/lib/pleroma/web/http_signatures/http_signatures.ex +++ b/lib/pleroma/web/http_signatures/http_signatures.ex @@ -45,7 +45,7 @@ def validate_conn(conn) do end end else - e -> + _e -> Logger.debug("Could not public key!") false end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index c84c226e8..9f4261143 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -112,7 +112,7 @@ def masto_instance(conn, _params) do version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})", email: Keyword.get(@instance, :email), urls: %{ - streaming_api: String.replace(Web.base_url(), ["http", "https"], "wss") + streaming_api: String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws") }, stats: Stats.get_stats(), thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg", @@ -212,14 +212,14 @@ def user_statuses(%{assigns: %{user: user}} = conn, params) do |> Map.put("actor_id", ap_id) |> Map.put("whole_db", true) - if params["pinned"] == "true" do - # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here - activities = [] - else - activities = + 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() - end + end conn |> add_link_headers(:user_statuses, activities, params["id"]) @@ -275,7 +275,19 @@ def post_status(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do |> Map.put("in_reply_to_status_id", params["in_reply_to_id"]) |> Map.put("no_attachment_links", true) - {:ok, activity} = CommonAPI.post(user, params) + idempotency_key = + case get_req_header(conn, "idempotency-key") do + [key] -> key + _ -> Ecto.UUID.generate() + end + + {:ok, activity} = + Cachex.get!( + :idempotency_cache, + idempotency_key, + fallback: fn _ -> CommonAPI.post(user, params) end + ) + render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index df360644a..5c6fd05f3 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -82,19 +82,6 @@ def render( } end - def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do - id = activity.data["object"]["inReplyTo"] - replied_to_activities[activity.data["object"]["inReplyTo"]] - end - - def get_reply_to(%{data: %{"object" => object}}, _) do - if object["inReplyTo"] && object["inReplyTo"] != "" do - Activity.get_create_activity_by_object_ap_id(object["inReplyTo"]) - else - nil - end - end - def render("status.json", %{activity: %{data: %{"object" => object}} = activity} = opts) do user = User.get_cached_by_ap_id(activity.data["actor"]) @@ -164,19 +151,6 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity} } end - def get_visibility(object) do - public = "https://www.w3.org/ns/activitystreams#Public" - to = object["to"] || [] - cc = object["cc"] || [] - - cond do - public in to -> "public" - public in cc -> "unlisted" - Enum.any?(to, &String.contains?(&1, "/followers")) -> "private" - true -> "direct" - end - end - def render("attachment.json", %{attachment: attachment}) do [%{"mediaType" => media_type, "href" => href} | _] = attachment["url"] @@ -199,4 +173,30 @@ def render("attachment.json", %{attachment: attachment}) do type: type } end + + def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do + _id = activity.data["object"]["inReplyTo"] + replied_to_activities[activity.data["object"]["inReplyTo"]] + end + + def get_reply_to(%{data: %{"object" => object}}, _) do + if object["inReplyTo"] && object["inReplyTo"] != "" do + Activity.get_create_activity_by_object_ap_id(object["inReplyTo"]) + else + nil + end + end + + def get_visibility(object) do + public = "https://www.w3.org/ns/activitystreams#Public" + to = object["to"] || [] + cc = object["cc"] || [] + + cond do + public in to -> "public" + public in cc -> "unlisted" + Enum.any?(to, &String.contains?(&1, "/followers")) -> "private" + true -> "direct" + end + end end diff --git a/lib/pleroma/web/nodeinfo/nodeinfo.ex b/lib/pleroma/web/nodeinfo/nodeinfo.ex new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/lib/pleroma/web/nodeinfo/nodeinfo.ex @@ -0,0 +1 @@ + diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex new file mode 100644 index 000000000..aec77168a --- /dev/null +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -0,0 +1,62 @@ +defmodule Pleroma.Web.Nodeinfo.NodeinfoController do + use Pleroma.Web, :controller + + alias Pleroma.Stats + alias Pleroma.Web + + @instance Application.get_env(:pleroma, :instance) + + def schemas(conn, _params) do + response = %{ + links: [ + %{ + rel: "http://nodeinfo.diaspora.software/ns/schema/2.0", + href: Web.base_url() <> "/nodeinfo/2.0.json" + } + ] + } + + json(conn, response) + end + + # Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json + def nodeinfo(conn, %{"version" => "2.0"}) do + stats = Stats.get_stats() + + response = %{ + version: "2.0", + software: %{ + name: "pleroma", + version: Keyword.get(@instance, :version) + }, + protocols: ["ostatus", "activitypub"], + services: %{ + inbound: [], + outbound: [] + }, + openRegistrations: Keyword.get(@instance, :registrations_open), + usage: %{ + users: %{ + total: stats.user_count || 0 + }, + localPosts: stats.status_count || 0 + }, + metadata: %{ + nodeName: Keyword.get(@instance, :name) + } + } + + conn + |> put_resp_header( + "content-type", + "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8" + ) + |> json(response) + end + + def nodeinfo(conn, _) do + conn + |> put_status(404) + |> json(%{error: "Nodeinfo schema version not handled"}) + end +end diff --git a/lib/pleroma/web/oauth/authorization.ex b/lib/pleroma/web/oauth/authorization.ex index 94f44c9f2..23e8eb7b1 100644 --- a/lib/pleroma/web/oauth/authorization.ex +++ b/lib/pleroma/web/oauth/authorization.ex @@ -11,7 +11,7 @@ defmodule Pleroma.Web.OAuth.Authorization do field(:valid_until, :naive_datetime) field(:used, :boolean, default: false) belongs_to(:user, Pleroma.User) - belongs_to(:app, Pleroma.App) + belongs_to(:app, App) timestamps() end diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex index 65abd78c8..343fc0c45 100644 --- a/lib/pleroma/web/oauth/token.ex +++ b/lib/pleroma/web/oauth/token.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.OAuth.Token do field(:refresh_token, :string) field(:valid_until, :naive_datetime) belongs_to(:user, Pleroma.User) - belongs_to(:app, Pleroma.App) + belongs_to(:app, App) timestamps() end diff --git a/lib/pleroma/web/ostatus/activity_representer.ex b/lib/pleroma/web/ostatus/activity_representer.ex index 921a89bd0..e8841a856 100644 --- a/lib/pleroma/web/ostatus/activity_representer.ex +++ b/lib/pleroma/web/ostatus/activity_representer.ex @@ -1,7 +1,6 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do alias Pleroma.{Activity, User, Object} alias Pleroma.Web.OStatus.UserRepresenter - alias Pleroma.Formatter require Logger defp get_href(id) do diff --git a/lib/pleroma/web/ostatus/handlers/note_handler.ex b/lib/pleroma/web/ostatus/handlers/note_handler.ex index bd6e92238..0d4080291 100644 --- a/lib/pleroma/web/ostatus/handlers/note_handler.ex +++ b/lib/pleroma/web/ostatus/handlers/note_handler.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Web.OStatus.NoteHandler do require Logger alias Pleroma.Web.{XML, OStatus} - alias Pleroma.{Object, User, Activity} + alias Pleroma.{Object, Activity} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.CommonAPI diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index a02f55fe6..f39ebaf2b 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -8,7 +8,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Web.XML alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPub - import Ecto.Query def feed_redirect(conn, %{"nickname" => nickname} = params) do user = User.get_cached_by_nickname(nickname) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index cecf5527c..c025dea33 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -295,6 +295,11 @@ def user_fetcher(username) do get("/host-meta", WebFinger.WebFingerController, :host_meta) get("/webfinger", WebFinger.WebFingerController, :webfinger) + get("/nodeinfo", Nodeinfo.NodeinfoController, :schemas) + end + + scope "/nodeinfo", Pleroma.Web do + get("/:version", Nodeinfo.NodeinfoController, :nodeinfo) end end diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 10670e71f..33041ec12 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -3,6 +3,10 @@ defmodule Pleroma.Web.Streamer do require Logger alias Pleroma.{User, Notification} + def init(args) do + {:ok, args} + end + def start_link do spawn(fn -> # 30 seconds @@ -110,20 +114,26 @@ def handle_cast(m, state) do def push_to_socket(topics, topic, item) do Enum.each(topics[topic] || [], fn socket -> - json = - %{ - event: "update", - payload: - Pleroma.Web.MastodonAPI.StatusView.render( - "status.json", - activity: item, - for: socket.assigns[:user] - ) - |> Jason.encode!() - } - |> Jason.encode!() + # Get the current user so we have up-to-date blocks etc. + user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id) + blocks = user.info["blocks"] || [] - send(socket.transport_pid, {:text, json}) + unless item.actor in blocks do + json = + %{ + event: "update", + payload: + Pleroma.Web.MastodonAPI.StatusView.render( + "status.json", + activity: item, + for: user + ) + |> Jason.encode!() + } + |> Jason.encode!() + + send(socket.transport_pid, {:text, json}) + end 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 c7b1a5b95..ea540b34c 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -92,7 +92,7 @@ def do_remote_follow(conn, %{ with %User{} = user <- User.get_cached_by_nickname(username), true <- Pbkdf2.checkpw(password, user.password_hash), - %User{} = followed <- Repo.get(User, id), + %User{} = _followed <- Repo.get(User, id), {:ok, follower} <- User.follow(user, followee), {:ok, _activity} <- ActivityPub.follow(follower, followee) do conn diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index c12cd7f8a..44ea40a4e 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -1,7 +1,6 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do alias Pleroma.{User, Activity, Repo, Object} alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter alias Pleroma.Web.TwitterAPI.UserView alias Pleroma.Web.{OStatus, CommonAPI} import Ecto.Query @@ -184,7 +183,7 @@ defp parse_int(string, default) when is_binary(string) do defp parse_int(_, default), do: default - def search(user, %{"q" => query} = params) do + def search(_user, %{"q" => query} = params) do limit = parse_int(params["rpp"], 20) page = parse_int(params["page"], 1) offset = (page - 1) * limit @@ -206,7 +205,7 @@ def search(user, %{"q" => query} = params) do order_by: [desc: :inserted_at] ) - activities = Repo.all(q) + _activities = Repo.all(q) end defp make_date do diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 6cf8682b8..960925f42 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -347,7 +347,8 @@ def empty_array(conn, _params) do def update_profile(%{assigns: %{user: user}} = conn, params) do params = if bio = params["description"] do - Map.put(params, "bio", bio) + bio_brs = Regex.replace(~r/\r?\n/, bio, "
") + Map.put(params, "bio", bio_brs) else params end diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 4e4433aed..580d4648c 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -31,7 +31,7 @@ defp query_users(user_ids) do end defp collect_context_ids(activities) do - contexts = + _contexts = activities |> Enum.reject(& &1.data["context_id"]) |> Enum.map(fn %{data: data} -> diff --git a/lib/pleroma/web/twitter_api/views/notification_view.ex b/lib/pleroma/web/twitter_api/views/notification_view.ex index f41edea0b..9eeb3afdc 100644 --- a/lib/pleroma/web/twitter_api/views/notification_view.ex +++ b/lib/pleroma/web/twitter_api/views/notification_view.ex @@ -2,7 +2,6 @@ defmodule Pleroma.Web.TwitterAPI.NotificationView do use Pleroma.Web, :view alias Pleroma.{Notification, User} alias Pleroma.Web.CommonAPI.Utils - alias Pleroma.Web.MediaProxy alias Pleroma.Web.TwitterAPI.UserView alias Pleroma.Web.TwitterAPI.ActivityView diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index dc9ad2014..6ffa80a43 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Web.WebFinger do @httpoison Application.get_env(:pleroma, :httpoison) - alias Pleroma.{Repo, User, XmlBuilder} + alias Pleroma.{User, XmlBuilder} alias Pleroma.Web alias Pleroma.Web.{XML, Salmon, OStatus} require Jason @@ -239,13 +239,14 @@ def finger(account) do URI.parse(account).host end - case find_lrdd_template(domain) do - {:ok, template} -> - address = String.replace(template, "{uri}", URI.encode(account)) + address = + case find_lrdd_template(domain) do + {:ok, template} -> + String.replace(template, "{uri}", URI.encode(account)) - _ -> - address = "http://#{domain}/.well-known/webfinger?resource=acct:#{account}" - end + _ -> + "http://#{domain}/.well-known/webfinger?resource=acct:#{account}" + end with response <- @httpoison.get( diff --git a/lib/pleroma/web/xml/xml.ex b/lib/pleroma/web/xml/xml.ex index 8b609f695..36430a3fa 100644 --- a/lib/pleroma/web/xml/xml.ex +++ b/lib/pleroma/web/xml/xml.ex @@ -14,7 +14,7 @@ def string_from_xpath(xpath, doc) do if res == "", do: nil, else: res catch - e -> + _e -> Logger.debug("Couldn't find xpath #{xpath} in XML doc") nil end diff --git a/priv/static/index.html b/priv/static/index.html index 533007819..cf1c24b0e 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +Pleroma
\ No newline at end of file diff --git a/priv/static/static/config.json b/priv/static/static/config.json index 797f03377..5cf4cdeca 100644 --- a/priv/static/static/config.json +++ b/priv/static/static/config.json @@ -2,7 +2,8 @@ "theme": "pleroma-dark", "background": "/static/aurora_borealis.jpg", "logo": "/static/logo.png", - "defaultPath": "/main/all", + "redirectRootNoLogin": "/main/all", + "redirectRootLogin": "/main/friends", "chatDisabled": false, - "showInstanceSpecificPanel": true + "showInstanceSpecificPanel": false } diff --git a/priv/static/static/js/app.408cea515c3032097a51.js b/priv/static/static/js/app.408cea515c3032097a51.js deleted file mode 100644 index 2db7c5ed1..000000000 Binary files a/priv/static/static/js/app.408cea515c3032097a51.js and /dev/null differ diff --git a/priv/static/static/js/app.408cea515c3032097a51.js.map b/priv/static/static/js/app.408cea515c3032097a51.js.map deleted file mode 100644 index 5ff9793da..000000000 Binary files a/priv/static/static/js/app.408cea515c3032097a51.js.map and /dev/null differ diff --git a/priv/static/static/js/app.af121efa5ff89725b4c6.js b/priv/static/static/js/app.af121efa5ff89725b4c6.js new file mode 100644 index 000000000..86117e499 Binary files /dev/null and b/priv/static/static/js/app.af121efa5ff89725b4c6.js differ diff --git a/priv/static/static/js/app.af121efa5ff89725b4c6.js.map b/priv/static/static/js/app.af121efa5ff89725b4c6.js.map new file mode 100644 index 000000000..b0a7bd44d Binary files /dev/null and b/priv/static/static/js/app.af121efa5ff89725b4c6.js.map differ diff --git a/priv/static/static/js/manifest.38e369a50eccc2857845.js b/priv/static/static/js/manifest.38e369a50eccc2857845.js new file mode 100644 index 000000000..2d2e8ab20 Binary files /dev/null and b/priv/static/static/js/manifest.38e369a50eccc2857845.js differ diff --git a/priv/static/static/js/manifest.cdeff2a56af285544b89.js.map b/priv/static/static/js/manifest.38e369a50eccc2857845.js.map similarity index 93% rename from priv/static/static/js/manifest.cdeff2a56af285544b89.js.map rename to priv/static/static/js/manifest.38e369a50eccc2857845.js.map index a918c1acf..e8d587798 100644 Binary files a/priv/static/static/js/manifest.cdeff2a56af285544b89.js.map and b/priv/static/static/js/manifest.38e369a50eccc2857845.js.map differ diff --git a/priv/static/static/js/manifest.cdeff2a56af285544b89.js b/priv/static/static/js/manifest.cdeff2a56af285544b89.js deleted file mode 100644 index fa511ff82..000000000 Binary files a/priv/static/static/js/manifest.cdeff2a56af285544b89.js and /dev/null differ diff --git a/test/notification_test.exs b/test/notification_test.exs index 568ad642c..2ca1ac13d 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -33,6 +33,13 @@ test "it doesn't create a notification for user if the user blocks the activity assert nil == Notification.create_notification(activity, user) end + + test "it doesn't create a notification for user if he is the activity author" do + activity = insert(:note_activity) + author = User.get_by_ap_id(activity.data["actor"]) + + assert nil == Notification.create_notification(activity, author) + end end describe "get notification" do diff --git a/test/support/builders/activity_builder.ex b/test/support/builders/activity_builder.ex index d9c188955..eb72d5ba9 100644 --- a/test/support/builders/activity_builder.ex +++ b/test/support/builders/activity_builder.ex @@ -26,7 +26,7 @@ def insert(data \\ %{}, opts \\ %{}) do end def insert_list(times, data \\ %{}, opts \\ %{}) do - Enum.map(1..times, fn n -> + Enum.map(1..times, fn _n -> {:ok, activity} = insert(data, opts) activity end) diff --git a/test/support/httpoison_mock.ex b/test/support/httpoison_mock.ex index ba35c4460..4a5a9ea85 100644 --- a/test/support/httpoison_mock.ex +++ b/test/support/httpoison_mock.ex @@ -367,7 +367,7 @@ def get("https://shitposter.club/api/statuses/user_timeline/1.atom", _body, _hea def post( "https://social.heldscal.la/main/push/hub", - {:form, data}, + {:form, _data}, "Content-type": "application/x-www-form-urlencoded" ) do {:ok, @@ -711,11 +711,11 @@ def get(url, body, headers) do }"} end - def post(url, body, headers) do + def post(url, _body, _headers) do {:error, "Not implemented the mock response for post #{inspect(url)}"} end - def post(url, body, headers, options) do + def post(url, _body, _headers, _options) do {:error, "Not implemented the mock response for post #{inspect(url)}"} end end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 5293b9364..883ebc61e 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -63,7 +63,42 @@ test "the public timeline", %{conn: conn} do test "posting a status", %{conn: conn} do user = insert(:user) - conn = + idempotency_key = "Pikachu rocks!" + + conn_one = + conn + |> assign(:user, user) + |> put_req_header("idempotency-key", idempotency_key) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) + + {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key) + # Six hours + assert ttl > :timer.seconds(6 * 60 * 60 - 1) + + assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = + json_response(conn_one, 200) + + assert Repo.get(Activity, id) + + conn_two = + conn + |> assign(:user, user) + |> put_req_header("idempotency-key", idempotency_key) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) + + assert %{"id" => second_id} = json_response(conn_two, 200) + + assert id == second_id + + conn_three = conn |> assign(:user, user) |> post("/api/v1/statuses", %{ @@ -72,10 +107,9 @@ test "posting a status", %{conn: conn} do "sensitive" => "false" }) - assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = - json_response(conn, 200) + assert %{"id" => third_id} = json_response(conn_three, 200) - assert Repo.get(Activity, id) + refute id == third_id end test "posting a sensitive status", %{conn: conn} do diff --git a/test/web/streamer_test.exs b/test/web/streamer_test.exs new file mode 100644 index 000000000..47d491d1b --- /dev/null +++ b/test/web/streamer_test.exs @@ -0,0 +1,63 @@ +defmodule Pleroma.Web.StreamerTest do + use Pleroma.DataCase + + alias Pleroma.Web.Streamer + alias Pleroma.User + alias Pleroma.Web.CommonAPI + import Pleroma.Factory + + test "it sends to public" do + user = insert(:user) + other_user = insert(:user) + + task = + Task.async(fn -> + assert_receive {:text, _}, 4_000 + end) + + fake_socket = %{ + transport_pid: task.pid, + assigns: %{ + user: user + } + } + + {:ok, activity} = CommonAPI.post(other_user, %{"status" => "Test"}) + + topics = %{ + "public" => [fake_socket] + } + + Streamer.push_to_socket(topics, "public", activity) + + Task.await(task) + end + + test "it doesn't send to blocked users" do + user = insert(:user) + blocked_user = insert(:user) + {:ok, user} = User.block(user, blocked_user) + + task = + Task.async(fn -> + refute_receive {:text, _}, 1_000 + end) + + fake_socket = %{ + transport_pid: task.pid, + assigns: %{ + user: user + } + } + + {:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"}) + + topics = %{ + "public" => [fake_socket] + } + + Streamer.push_to_socket(topics, "public", activity) + + Task.await(task) + end +end diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs index 406dace1c..896fe246d 100644 --- a/test/web/twitter_api/twitter_api_controller_test.exs +++ b/test/web/twitter_api/twitter_api_controller_test.exs @@ -257,8 +257,10 @@ test "without valid credentials", %{conn: conn} do end test "with credentials", %{conn: conn, user: current_user} do + other_user = insert(:user) + {:ok, activity} = - ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user}) + ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user}) conn = conn @@ -784,4 +786,18 @@ test "it returns the tags timeline", %{conn: conn} do assert status["id"] == activity.id end end + + test "Convert newlines to
in bio", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/account/update_profile.json", %{ + "description" => "Hello,\r\nWorld! I\n am a test." + }) + + user = Repo.get!(User, user.id) + assert user.bio == "Hello,
World! I
am a test." + end end