diff options
Diffstat (limited to 'lib')
23 files changed, 252 insertions, 125 deletions
| diff --git a/lib/mix/pleroma.ex b/lib/mix/pleroma.ex index faeb30e1d..73a076a53 100644 --- a/lib/mix/pleroma.ex +++ b/lib/mix/pleroma.ex @@ -6,6 +6,11 @@ defmodule Mix.Pleroma do    @doc "Common functions to be reused in mix tasks"    def start_pleroma do      Application.put_env(:phoenix, :serve_endpoints, false, persistent: true) + +    if Pleroma.Config.get(:env) != :test do +      Application.put_env(:logger, :console, level: :debug) +    end +      {:ok, _} = Application.ensure_all_started(:pleroma)    end diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 4e3b80db3..bc8eacda8 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -364,6 +364,24 @@ defmodule Mix.Tasks.Pleroma.User do      end    end +  def run(["list"]) do +    start_pleroma() + +    Pleroma.User.Query.build(%{local: true}) +    |> Pleroma.RepoStreamer.chunk_stream(500) +    |> Stream.each(fn users -> +      users +      |> Enum.each(fn user -> +        shell_info( +          "#{user.nickname} moderator: #{user.info.is_moderator}, admin: #{user.info.is_admin}, locked: #{ +            user.info.locked +          }, deactivated: #{user.info.deactivated}" +        ) +      end) +    end) +    |> Stream.run() +  end +    defp set_moderator(user, value) do      {:ok, user} =        user diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 7e283df32..cd7a5aae9 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -303,4 +303,17 @@ defmodule Pleroma.Activity do    end    defdelegate search(user, query, options \\ []), to: Pleroma.Activity.Search + +  def direct_conversation_id(activity, for_user) do +    alias Pleroma.Conversation.Participation + +    with %{data: %{"context" => context}} when is_binary(context) <- activity, +         %Pleroma.Conversation{} = conversation <- Pleroma.Conversation.get_for_ap_id(context), +         %Participation{id: participation_id} <- +           Participation.for_user_and_conversation(for_user, conversation) do +      participation_id +    else +      _ -> nil +    end +  end  end diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 2b6a55f98..9dbd1e26b 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -17,8 +17,14 @@ defmodule Pleroma.Application do    def repository, do: @repository    def user_agent do -    info = "#{Pleroma.Web.base_url()} <#{Pleroma.Config.get([:instance, :email], "")}>" -    named_version() <> "; " <> info +    case Pleroma.Config.get([:http, :user_agent], :default) do +      :default -> +        info = "#{Pleroma.Web.base_url()} <#{Pleroma.Config.get([:instance, :email], "")}>" +        named_version() <> "; " <> info + +      custom -> +        custom +    end    end    # See http://elixir-lang.org/docs/stable/elixir/Application.html diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex index 2ffac17ee..3aff9fb76 100644 --- a/lib/pleroma/following_relationship.ex +++ b/lib/pleroma/following_relationship.ex @@ -101,7 +101,7 @@ defmodule Pleroma.FollowingRelationship do        |> select([r, u], u.follower_address)        |> Repo.all() -    if not user.local or user.nickname in [nil, "internal.fetch"] do +    if not user.local or user.invisible do        following      else        [user.follower_address | following] diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex index 997e965f0..4acd46253 100644 --- a/lib/pleroma/html.ex +++ b/lib/pleroma/html.ex @@ -91,6 +91,7 @@ defmodule Pleroma.HTML do      Cachex.fetch!(:scrubber_cache, key, fn _key ->        result =          content +        |> HtmlEntities.decode()          |> Floki.filter_out("a.mention,a.hashtag,a[rel~=\"tag\"]")          |> Floki.attribute("a", "href")          |> Enum.at(0) diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex index ffa5dc25d..706f089dc 100644 --- a/lib/pleroma/moderation_log.ex +++ b/lib/pleroma/moderation_log.ex @@ -624,7 +624,31 @@ defmodule Pleroma.ModerationLog do            "subject" => subjects          }        }) do -    "@#{actor_nickname} force password reset for users: #{users_to_nicknames_string(subjects)}" +    "@#{actor_nickname} forced password reset for users: #{users_to_nicknames_string(subjects)}" +  end + +  @spec get_log_entry_message(ModerationLog) :: String.t() +  def get_log_entry_message(%ModerationLog{ +        data: %{ +          "actor" => %{"nickname" => actor_nickname}, +          "action" => "confirm_email", +          "subject" => subjects +        } +      }) do +    "@#{actor_nickname} confirmed email for users: #{users_to_nicknames_string(subjects)}" +  end + +  @spec get_log_entry_message(ModerationLog) :: String.t() +  def get_log_entry_message(%ModerationLog{ +        data: %{ +          "actor" => %{"nickname" => actor_nickname}, +          "action" => "resend_confirmation_email", +          "subject" => subjects +        } +      }) do +    "@#{actor_nickname} re-sent confirmation email for users: #{ +      users_to_nicknames_string(subjects) +    }"    end    defp nicknames_to_string(nicknames) do diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index d9b41d710..b4ed3a9b2 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -63,7 +63,7 @@ defmodule Pleroma.Object do    end    defp warn_on_no_object_preloaded(ap_id) do -    "Object.normalize() called without preloaded object (#{ap_id}). Consider preloading the object" +    "Object.normalize() called without preloaded object (#{inspect(ap_id)}). Consider preloading the object"      |> Logger.debug()      Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}") @@ -255,4 +255,8 @@ defmodule Pleroma.Object do      |> Object.change(%{data: Map.merge(data || %{}, attrs)})      |> Repo.update()    end + +  def local?(%Object{data: %{"id" => id}}) do +    String.starts_with?(id, Pleroma.Web.base_url() <> "/") +  end  end diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index 9a9a46550..4d71c91a8 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -49,7 +49,7 @@ defmodule Pleroma.Object.Fetcher do    end    def refetch_object(%Object{data: %{"id" => id}} = object) do -    with {:local, false} <- {:local, String.starts_with?(id, Pleroma.Web.base_url() <> "/")}, +    with {:local, false} <- {:local, Object.local?(object)},           {:ok, data} <- fetch_and_contain_remote_object_from_id(id),           {:ok, object} <- reinject_object(object, data) do        {:ok, object} diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index fcb1d5143..b18a4c6a5 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -67,8 +67,7 @@ defmodule Pleroma.User do      field(:source_data, :map, default: %{})      field(:note_count, :integer, default: 0)      field(:follower_count, :integer, default: 0) -    # Should be filled in only for remote users -    field(:following_count, :integer, default: nil) +    field(:following_count, :integer, default: 0)      field(:locked, :boolean, default: false)      field(:confirmation_pending, :boolean, default: false)      field(:password_reset_pending, :boolean, default: false) @@ -134,6 +133,8 @@ defmodule Pleroma.User do    def visible_for?(user, for_user \\ nil) +  def visible_for?(%User{invisible: true}, _), do: false +    def visible_for?(%User{id: user_id}, %User{id: for_id}) when user_id == for_id, do: true    def visible_for?(%User{} = user, for_user) do @@ -176,22 +177,6 @@ defmodule Pleroma.User do    def ap_following(%User{following_address: fa}) when is_binary(fa), do: fa    def ap_following(%User{} = user), do: "#{ap_id(user)}/following" -  def user_info(%User{} = user, args \\ %{}) do -    following_count = -      Map.get(args, :following_count, user.following_count || following_count(user)) - -    follower_count = Map.get(args, :follower_count, user.follower_count) - -    %{ -      note_count: user.note_count, -      locked: user.locked, -      confirmation_pending: user.confirmation_pending, -      default_scope: user.default_scope -    } -    |> Map.put(:following_count, following_count) -    |> Map.put(:follower_count, follower_count) -  end -    def follow_state(%User{} = user, %User{} = target) do      case Utils.fetch_latest_follow(user, target) do        %{data: %{"state" => state}} -> state @@ -210,10 +195,6 @@ defmodule Pleroma.User do      Cachex.put(:user_cache, "follow_state:#{user_ap_id}|#{target_ap_id}", state)    end -  def set_info_cache(user, args) do -    Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user, args)) -  end -    @spec restrict_deactivated(Ecto.Query.t()) :: Ecto.Query.t()    def restrict_deactivated(query) do      from(u in query, where: u.deactivated != ^true) @@ -492,6 +473,10 @@ defmodule Pleroma.User do      end    end +  def try_send_confirmation_email(users) do +    Enum.each(users, &try_send_confirmation_email/1) +  end +    def needs_update?(%User{local: true}), do: false    def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true @@ -522,14 +507,9 @@ defmodule Pleroma.User do    @doc "A mass follow for local users. Respects blocks in both directions but does not create activities."    @spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()}    def follow_all(follower, followeds) do -    followeds = -      Enum.reject(followeds, fn followed -> -        blocks?(follower, followed) || blocks?(followed, follower) -      end) - -    Enum.each(followeds, &follow(follower, &1, "accept")) - -    Enum.each(followeds, &update_follower_count/1) +    followeds +    |> Enum.reject(fn followed -> blocks?(follower, followed) || blocks?(followed, follower) end) +    |> Enum.each(&follow(follower, &1, "accept"))      set_cache(follower)    end @@ -549,11 +529,11 @@ defmodule Pleroma.User do        true ->          FollowingRelationship.follow(follower, followed, state) -        follower = maybe_update_following_count(follower) -          {:ok, _} = update_follower_count(followed) -        set_cache(follower) +        follower +        |> update_following_count() +        |> set_cache()      end    end @@ -561,11 +541,12 @@ defmodule Pleroma.User do      if following?(follower, followed) and follower.ap_id != followed.ap_id do        FollowingRelationship.unfollow(follower, followed) -      follower = maybe_update_following_count(follower) -        {:ok, followed} = update_follower_count(followed) -      set_cache(follower) +      {:ok, follower} = +        follower +        |> update_following_count() +        |> set_cache()        {:ok, follower, Utils.fetch_latest_follow(follower, followed)}      else @@ -615,7 +596,6 @@ defmodule Pleroma.User do    def set_cache(%User{} = user) do      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}    end @@ -634,7 +614,6 @@ defmodule Pleroma.User do    def invalidate_cache(user) do      Cachex.del(:user_cache, "ap_id:#{user.ap_id}")      Cachex.del(:user_cache, "nickname:#{user.nickname}") -    Cachex.del(:user_cache, "user_info:#{user.id}")    end    def get_cached_by_ap_id(ap_id) do @@ -702,11 +681,6 @@ defmodule Pleroma.User do      get_by_nickname(nickname_or_email) || get_by_email(nickname_or_email)    end -  def get_cached_user_info(user) do -    key = "user_info:#{user.id}" -    Cachex.fetch!(:user_cache, key, fn -> user_info(user) end) -  end -    def fetch_by_nickname(nickname), do: ActivityPub.make_user_from_nickname(nickname)    def get_or_fetch_by_nickname(nickname) do @@ -895,8 +869,8 @@ defmodule Pleroma.User do      end    end -  @spec maybe_update_following_count(User.t()) :: User.t() -  def maybe_update_following_count(%User{local: false} = user) do +  @spec update_following_count(User.t()) :: User.t() +  def update_following_count(%User{local: false} = user) do      if Pleroma.Config.get([:instance, :external_user_synchronization]) do        maybe_fetch_follow_information(user)      else @@ -904,7 +878,13 @@ defmodule Pleroma.User do      end    end -  def maybe_update_following_count(user), do: user +  def update_following_count(%User{local: true} = user) do +    following_count = FollowingRelationship.following_count(user) + +    user +    |> follow_information_changeset(%{following_count: following_count}) +    |> Repo.update!() +  end    def set_unread_conversation_count(%User{local: true} = user) do      unread_query = Participation.unread_conversation_count_for_user(user) @@ -1097,7 +1077,12 @@ defmodule Pleroma.User do    def deactivate(%User{} = user, status) do      with {:ok, user} <- set_activation_status(user, status) do -      Enum.each(get_followers(user), &invalidate_cache/1) +      user +      |> get_followers() +      |> Enum.filter(& &1.local) +      |> Enum.each(fn follower -> +        follower |> update_following_count() |> set_cache() +      end)        # Only update local user counts, remote will be update during the next pull.        user @@ -1317,22 +1302,23 @@ defmodule Pleroma.User do      end    end -  @doc "Creates an internal service actor by URI if missing.  Optionally takes nickname for addressing." +  @doc """ +  Creates an internal service actor by URI if missing. +  Optionally takes nickname for addressing. +  """    def get_or_create_service_actor_by_ap_id(uri, nickname \\ nil) do -    with %User{} = user <- get_cached_by_ap_id(uri) do -      user -    else -      _ -> -        {:ok, user} = -          %User{} -          |> cast(%{}, [:ap_id, :nickname, :local]) -          |> put_change(:ap_id, uri) -          |> put_change(:nickname, nickname) -          |> put_change(:local, true) -          |> put_change(:follower_address, uri <> "/followers") -          |> Repo.insert() +    with user when is_nil(user) <- get_cached_by_ap_id(uri) do +      {:ok, user} = +        %User{ +          invisible: true, +          local: true, +          ap_id: uri, +          nickname: nickname, +          follower_address: uri <> "/followers" +        } +        |> Repo.insert() -        user +      user      end    end @@ -1575,6 +1561,11 @@ defmodule Pleroma.User do      |> update_and_set_cache()    end +  @spec toggle_confirmation([User.t()]) :: [{:ok, User.t()} | {:error, Changeset.t()}] +  def toggle_confirmation(users) do +    Enum.map(users, &toggle_confirmation/1) +  end +    def get_mascot(%{mascot: %{} = mascot}) when not is_nil(mascot) do      mascot    end diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index 09664db76..b1bb9d4da 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -45,6 +45,7 @@ defmodule Pleroma.User.Search do      for_user      |> base_query(following)      |> filter_blocked_user(for_user) +    |> filter_invisible_users()      |> filter_blocked_domains(for_user)      |> fts_search(query_string)      |> trigram_rank(query_string) @@ -98,6 +99,10 @@ defmodule Pleroma.User.Search do    defp base_query(_user, false), do: User    defp base_query(user, true), do: User.get_followers_query(user) +  defp filter_invisible_users(query) do +    from(q in query, where: q.invisible == false) +  end +    defp filter_blocked_user(query, %User{blocks: blocks})         when length(blocks) > 0 do      from(q in query, where: not (q.ap_id in ^blocks)) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index d0c014e9d..f25314ff6 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -734,6 +734,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      |> Enum.reverse()    end +  def fetch_instance_activities(params) do +    params = +      params +      |> Map.put("type", ["Create", "Announce"]) +      |> Map.put("instance", params["instance"]) +      |> Map.put("whole_db", true) + +    fetch_activities([Pleroma.Constants.as_public()], params, :offset) +    |> Enum.reverse() +  end +    defp user_activities_recipients(%{"godmode" => true}) do      []    end @@ -961,6 +972,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    defp restrict_muted_reblogs(query, _), do: query +  defp restrict_instance(query, %{"instance" => instance}) do +    users = +      from( +        u in User, +        select: u.ap_id, +        where: fragment("? LIKE ?", u.nickname, ^"%@#{instance}") +      ) +      |> Repo.all() + +    from(activity in query, where: activity.actor in ^users) +  end + +  defp restrict_instance(query, _), do: query +    defp exclude_poll_votes(query, %{"include_poll_votes" => true}), do: query    defp exclude_poll_votes(query, _) do @@ -1041,6 +1066,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      |> restrict_reblogs(opts)      |> restrict_pinned(opts)      |> restrict_muted_reblogs(opts) +    |> restrict_instance(opts)      |> Activity.restrict_deactivated_users()      |> exclude_poll_votes(opts)      |> exclude_visibility(opts) diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index b2cd965fe..dec5da0d3 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do    end    def user(conn, %{"nickname" => nickname}) do -    with %User{} = user <- User.get_cached_by_nickname(nickname), +    with %User{local: true} = user <- User.get_cached_by_nickname(nickname),           {:ok, user} <- User.ensure_keys_present(user) do        conn        |> put_resp_content_type("application/activity+json") @@ -53,6 +53,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do        |> render("user.json", %{user: user})      else        nil -> {:error, :not_found} +      %{local: false} -> {:error, :not_found}      end    end diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex index fc2619680..99a804568 100644 --- a/lib/pleroma/web/activity_pub/relay.ex +++ b/lib/pleroma/web/activity_pub/relay.ex @@ -14,7 +14,6 @@ defmodule Pleroma.Web.ActivityPub.Relay do        relay_ap_id()        |> User.get_or_create_service_actor_by_ap_id() -    {:ok, actor} = User.set_invisible(actor, true)      actor    end diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index c45662359..01aacbde3 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -903,7 +903,13 @@ defmodule Pleroma.Web.ActivityPub.Utils do    def strip_report_status_data(activity) do      [actor | reported_activities] = activity.data["object"] -    stripped_activities = Enum.map(reported_activities, & &1["id"]) + +    stripped_activities = +      Enum.map(reported_activities, fn +        act when is_map(act) -> act["id"] +        act when is_binary(act) -> act +      end) +      new_data = put_in(activity.data, ["object"], [actor | stripped_activities])      {:ok, %{activity | data: new_data}} diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 8c1318d1b..24fdc3c82 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -227,6 +227,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do      end    end +  def list_instance_statuses(conn, %{"instance" => instance} = params) do +    {page, page_size} = page_params(params) + +    activities = +      ActivityPub.fetch_instance_activities(%{ +        "instance" => instance, +        "limit" => page_size, +        "offset" => (page - 1) * page_size +      }) + +    conn +    |> put_view(StatusView) +    |> render("index.json", %{activities: activities, as: :activity}) +  end +    def list_user_statuses(conn, %{"nickname" => nickname} = params) do      godmode = params["godmode"] == "true" || params["godmode"] == true @@ -335,7 +350,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do      }      with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)), -         {:ok, users, count} <- filter_relay_user(users, count), +         {:ok, users, count} <- filter_service_users(users, count),           do:             conn             |> json( @@ -347,15 +362,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do             )    end -  defp filter_relay_user(users, count) do -    filtered_users = Enum.reject(users, &relay_user?/1) -    count = if Enum.any?(users, &relay_user?/1), do: length(filtered_users), else: count +  defp filter_service_users(users, count) do +    filtered_users = Enum.reject(users, &service_user?/1) +    count = if Enum.any?(users, &service_user?/1), do: length(filtered_users), else: count      {:ok, filtered_users, count}    end -  defp relay_user?(user) do -    user.ap_id == Relay.relay_ap_id() +  defp service_user?(user) do +    String.match?(user.ap_id, ~r/.*\/relay$/) or +      String.match?(user.ap_id, ~r/.*\/internal\/fetch$/)    end    @filters ~w(local external active deactivated is_admin is_moderator) @@ -799,6 +815,34 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do      conn |> json("ok")    end +  def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do +    users = nicknames |> Enum.map(&User.get_cached_by_nickname/1) + +    User.toggle_confirmation(users) + +    ModerationLog.insert_log(%{ +      actor: admin, +      subject: users, +      action: "confirm_email" +    }) + +    conn |> json("") +  end + +  def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do +    users = nicknames |> Enum.map(&User.get_cached_by_nickname/1) + +    User.try_send_confirmation_email(users) + +    ModerationLog.insert_log(%{ +      actor: admin, +      subject: users, +      action: "resend_confirmation_email" +    }) + +    conn |> json("") +  end +    def errors(conn, {:error, :not_found}) do      conn      |> put_status(:not_found) diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 6aa7257ce..d9dba5c51 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -36,7 +36,8 @@ defmodule Pleroma.Web.AdminAPI.AccountView do        "deactivated" => user.deactivated,        "local" => user.local,        "roles" => User.roles(user), -      "tags" => user.tags || [] +      "tags" => user.tags || [], +      "confirmation_pending" => user.confirmation_pending      }    end diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 5b01b964b..5f2544640 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -238,7 +238,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do    @doc "GET /api/v1/accounts/:id"    def show(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do      with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user), -         true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do +         true <- User.visible_for?(user, for_user) do        render(conn, "show.json", user: user, for: for_user)      else        _e -> render_error(conn, :not_found, "Can't find user") diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index e30fed610..1068f8823 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -71,18 +71,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do      image = User.avatar_url(user) |> MediaProxy.url()      header = User.banner_url(user) |> MediaProxy.url() -    user_info = User.get_cached_user_info(user)      following_count =        if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do -        user_info.following_count +        user.following_count || 0        else          0        end      followers_count =        if !user.hide_followers_count or !user.hide_followers or opts[:for] == user do -        user_info.follower_count +        user.follower_count || 0        else          0        end @@ -144,7 +143,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do        # Pleroma extension        pleroma: %{ -        confirmation_pending: user_info.confirmation_pending, +        confirmation_pending: user.confirmation_pending,          tags: user.tags,          hide_followers_count: user.hide_followers_count,          hide_follows_count: user.hide_follows_count, @@ -157,7 +156,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do        }      }      |> maybe_put_role(user, opts[:for]) -    |> maybe_put_settings(user, opts[:for], user_info) +    |> maybe_put_settings(user, opts[:for], opts)      |> maybe_put_notification_settings(user, opts[:for])      |> maybe_put_settings_store(user, opts[:for], opts)      |> maybe_put_chat_token(user, opts[:for], opts) @@ -191,7 +190,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do           data,           %User{id: user_id} = user,           %User{id: user_id}, -         _user_info +         _opts         ) do      data      |> Kernel.put_in([:source, :privacy], user.default_scope) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index baff54151..a0257dfa6 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -9,8 +9,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do    alias Pleroma.Activity    alias Pleroma.ActivityExpiration -  alias Pleroma.Conversation -  alias Pleroma.Conversation.Participation    alias Pleroma.HTML    alias Pleroma.Object    alias Pleroma.Repo @@ -245,12 +243,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do      direct_conversation_id =        with {_, nil} <- {:direct_conversation_id, opts[:direct_conversation_id]},             {_, true} <- {:include_id, opts[:with_direct_conversation_id]}, -           {_, %User{} = for_user} <- {:for_user, opts[:for]}, -           %{data: %{"context" => context}} when is_binary(context) <- activity, -           %Conversation{} = conversation <- Conversation.get_for_ap_id(context), -           %Participation{id: participation_id} <- -             Participation.for_user_and_conversation(for_user, conversation) do -        participation_id +           {_, %User{} = for_user} <- {:for_user, opts[:for]} do +        Activity.direct_conversation_id(activity, for_user)        else          {:direct_conversation_id, participation_id} when is_integer(participation_id) ->            participation_id diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 12a7c2365..01ec7941e 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -11,7 +11,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do    alias Pleroma.Plugs.RateLimiter    alias Pleroma.User    alias Pleroma.Web.ActivityPub.ActivityPubController -  alias Pleroma.Web.ActivityPub.ObjectView    alias Pleroma.Web.ActivityPub.Visibility    alias Pleroma.Web.Endpoint    alias Pleroma.Web.Metadata.PlayerView @@ -38,11 +37,9 @@ defmodule Pleroma.Web.OStatus.OStatusController do      with id <- o_status_url(conn, :object, uuid),           {_, %Activity{} = activity} <-             {:activity, Activity.get_create_by_object_ap_id_with_object(id)}, -         {_, true} <- {:public?, Visibility.is_public?(activity)}, -         %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do +         {_, true} <- {:public?, Visibility.is_public?(activity)} do        case format do -        "html" -> redirect(conn, to: "/notice/#{activity.id}") -        _ -> represent_activity(conn, nil, activity, user) +        _ -> redirect(conn, to: "/notice/#{activity.id}")        end      else        reason when reason in [{:public?, false}, {:activity, nil}] -> @@ -61,11 +58,9 @@ defmodule Pleroma.Web.OStatus.OStatusController do    def activity(%{assigns: %{format: format}} = conn, %{"uuid" => uuid}) do      with id <- o_status_url(conn, :activity, uuid),           {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, -         {_, true} <- {:public?, Visibility.is_public?(activity)}, -         %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do +         {_, true} <- {:public?, Visibility.is_public?(activity)} do        case format do -        "html" -> redirect(conn, to: "/notice/#{activity.id}") -        _ -> represent_activity(conn, format, activity, user) +        _ -> redirect(conn, to: "/notice/#{activity.id}")        end      else        reason when reason in [{:public?, false}, {:activity, nil}] -> @@ -81,7 +76,15 @@ defmodule Pleroma.Web.OStatus.OStatusController do           {_, true} <- {:public?, Visibility.is_public?(activity)},           %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do        cond do -        format == "html" && activity.data["type"] == "Create" -> +        format in ["json", "activity+json"] -> +          if activity.local do +            %{data: %{"id" => redirect_url}} = Object.normalize(activity) +            redirect(conn, external: redirect_url) +          else +            {:error, :not_found} +          end + +        activity.data["type"] == "Create" ->            %Object{} = object = Object.normalize(activity)            RedirectController.redirector_with_meta( @@ -94,11 +97,8 @@ defmodule Pleroma.Web.OStatus.OStatusController do              }            ) -        format == "html" -> -          RedirectController.redirector(conn, nil) -          true -> -          represent_activity(conn, format, activity, user) +          RedirectController.redirector(conn, nil)        end      else        reason when reason in [{:public?, false}, {:activity, nil}] -> @@ -135,24 +135,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do      end    end -  defp represent_activity( -         conn, -         "activity+json", -         %Activity{data: %{"type" => "Create"}} = activity, -         _user -       ) do -    object = Object.normalize(activity) - -    conn -    |> put_resp_header("content-type", "application/activity+json") -    |> put_view(ObjectView) -    |> render("object.json", %{object: object}) -  end - -  defp represent_activity(_conn, _, _, _) do -    {:error, :not_found} -  end -    def errors(conn, {:error, :not_found}) do      render_error(conn, :not_found, "Not found")    end diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex index dd445e8bf..3de7af708 100644 --- a/lib/pleroma/web/push/impl.ex +++ b/lib/pleroma/web/push/impl.ex @@ -33,6 +33,8 @@ defmodule Pleroma.Web.Push.Impl do      gcm_api_key = Application.get_env(:web_push_encryption, :gcm_api_key)      avatar_url = User.avatar_url(actor)      object = Object.normalize(activity) +    user = User.get_cached_by_id(user_id) +    direct_conversation_id = Activity.direct_conversation_id(activity, user)      for subscription <- fetch_subsriptions(user_id),          get_in(subscription.data, ["alerts", type]) do @@ -45,7 +47,8 @@ defmodule Pleroma.Web.Push.Impl do          icon: avatar_url,          preferred_locale: "en",          pleroma: %{ -          activity_id: activity_id +          activity_id: activity_id, +          direct_conversation_id: direct_conversation_id          }        }        |> Jason.encode!() diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 129da422c..e6c4f6f14 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -178,6 +178,11 @@ defmodule Pleroma.Web.Router do      get("/users/:nickname", AdminAPIController, :user_show)      get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) +    get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses) + +    patch("/users/confirm_email", AdminAPIController, :confirm_email) +    patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email) +      get("/reports", AdminAPIController, :list_reports)      get("/grouped_reports", AdminAPIController, :list_grouped_reports)      get("/reports/:id", AdminAPIController, :report_show) | 
