diff options
Diffstat (limited to 'lib')
20 files changed, 340 insertions, 82 deletions
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 0060d966b..ff84e7b0a 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -261,6 +261,7 @@ defmodule Pleroma.User do def register(%Ecto.Changeset{} = changeset) do with {:ok, user} <- Repo.insert(changeset), {:ok, user} <- autofollow_users(user), + {:ok, _} <- Pleroma.User.WelcomeMessage.post_welcome_message_to_user(user), {:ok, _} <- try_send_confirmation_email(user) do {:ok, user} end @@ -311,12 +312,12 @@ defmodule Pleroma.User do end end - @doc "A mass follow for local users. Respects blocks but does not create activities." + @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 followed_addresses = followeds - |> Enum.reject(fn %{ap_id: ap_id} -> ap_id in follower.info.blocks end) + |> Enum.reject(fn followed -> blocks?(follower, followed) || blocks?(followed, follower) end) |> Enum.map(fn %{follower_address: fa} -> fa end) q = @@ -618,6 +619,32 @@ defmodule Pleroma.User do ) end + def update_follow_request_count(%User{} = user) do + subquery = + user + |> User.get_follow_requests_query() + |> select([a], %{count: count(a.id)}) + + User + |> where(id: ^user.id) + |> join(:inner, [u], s in subquery(subquery)) + |> update([u, s], + set: [ + info: + fragment( + "jsonb_set(?, '{follow_request_count}', ?::varchar::jsonb, true)", + u.info, + s.count + ) + ] + ) + |> Repo.update_all([], returning: true) + |> case do + {1, [user]} -> {:ok, user} + _ -> {:error, user} + end + end + def get_follow_requests(%User{} = user) do q = get_follow_requests_query(user) reqs = Repo.all(q) @@ -731,7 +758,7 @@ defmodule Pleroma.User do # Strip the beginning @ off if there is a query query = String.trim_leading(query, "@") - if resolve, do: User.get_or_fetch_by_nickname(query) + if resolve, do: get_or_fetch(query) fts_results = do_search(fts_search_subquery(query), for_user) diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 9d8779fab..9099d7fbb 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -12,6 +12,7 @@ defmodule Pleroma.User.Info do field(:source_data, :map, default: %{}) field(:note_count, :integer, default: 0) field(:follower_count, :integer, default: 0) + field(:follow_request_count, :integer, default: 0) field(:locked, :boolean, default: false) field(:confirmation_pending, :boolean, default: false) field(:confirmation_token, :string, default: nil) @@ -34,6 +35,7 @@ defmodule Pleroma.User.Info do field(:hide_followers, :boolean, default: false) field(:hide_follows, :boolean, default: false) field(:pinned_activities, {:array, :string}, default: []) + field(:flavour, :string, default: nil) # Found in the wild # ap_id -> Where is this used? @@ -186,6 +188,14 @@ defmodule Pleroma.User.Info do |> validate_required([:settings]) end + def mastodon_flavour_update(info, flavour) do + params = %{flavour: flavour} + + info + |> cast(params, [:flavour]) + |> validate_required([:flavour]) + end + def set_source_data(info, source_data) do params = %{source_data: source_data} diff --git a/lib/pleroma/user/welcome_message.ex b/lib/pleroma/user/welcome_message.ex new file mode 100644 index 000000000..8018ac22f --- /dev/null +++ b/lib/pleroma/user/welcome_message.ex @@ -0,0 +1,30 @@ +defmodule Pleroma.User.WelcomeMessage do + alias Pleroma.User + alias Pleroma.Web.CommonAPI + + def post_welcome_message_to_user(user) do + with %User{} = sender_user <- welcome_user(), + message when is_binary(message) <- welcome_message() do + CommonAPI.post(sender_user, %{ + "visibility" => "direct", + "status" => "@#{user.nickname}\n#{message}" + }) + else + _ -> {:ok, nil} + end + end + + defp welcome_user() do + with nickname when is_binary(nickname) <- + Pleroma.Config.get([:instance, :welcome_user_nickname]), + %User{local: true} = user <- User.get_cached_by_nickname(nickname) do + user + else + _ -> nil + end + end + + defp welcome_message() do + Pleroma.Config.get([:instance, :welcome_message]) + end +end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c46d8233e..a4ef47b40 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -172,9 +172,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do # only accept false as false value local = !(params[:local] == false) - with data <- %{"to" => to, "type" => "Accept", "actor" => actor, "object" => object}, + with data <- %{"to" => to, "type" => "Accept", "actor" => actor.ap_id, "object" => object}, {:ok, activity} <- insert(data, local), - :ok <- maybe_federate(activity) do + :ok <- maybe_federate(activity), + _ <- User.update_follow_request_count(actor) do {:ok, activity} end end @@ -183,9 +184,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do # only accept false as false value local = !(params[:local] == false) - with data <- %{"to" => to, "type" => "Reject", "actor" => actor, "object" => object}, + with data <- %{"to" => to, "type" => "Reject", "actor" => actor.ap_id, "object" => object}, {:ok, activity} <- insert(data, local), - :ok <- maybe_federate(activity) do + :ok <- maybe_federate(activity), + _ <- User.update_follow_request_count(actor) do {:ok, activity} end end @@ -283,7 +285,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def follow(follower, followed, activity_id \\ nil, local \\ true) do with data <- make_follow_data(follower, followed, activity_id), {:ok, activity} <- insert(data, local), - :ok <- maybe_federate(activity) do + :ok <- maybe_federate(activity), + _ <- User.update_follow_request_count(followed) do {:ok, activity} end end @@ -293,7 +296,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"), 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), + _ <- User.update_follow_request_count(followed) do {:ok, activity} end end @@ -818,8 +822,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do if object = Object.get_cached_by_ap_id(id) do {:ok, object} else - Logger.info("Fetching #{id} via AP") - with {:ok, data} <- fetch_and_contain_remote_object_from_id(id), nil <- Object.normalize(data), params <- %{ @@ -851,7 +853,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end def fetch_and_contain_remote_object_from_id(id) do - Logger.info("Fetching #{id} via AP") + Logger.info("Fetching object #{id} via AP") with true <- String.starts_with?(id, "http"), {:ok, %{body: body, status: code}} when code in 200..299 <- diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex index 4c6e612b2..6736f3cb9 100644 --- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex @@ -6,40 +6,80 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do alias Pleroma.User @behaviour Pleroma.Web.ActivityPub.MRF - defp delist_message(message) do + defp delist_message(message, threshold) when threshold > 0 do follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address - message - |> Map.put("to", [follower_collection]) - |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"]) + follower_collection? = Enum.member?(message["to"] ++ message["cc"], follower_collection) + + message = + case get_recipient_count(message) do + {:public, recipients} + when follower_collection? and recipients > threshold -> + message + |> Map.put("to", [follower_collection]) + |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"]) + + {:public, recipients} when recipients > threshold -> + message + |> Map.put("to", []) + |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"]) + + _ -> + message + end + + {:ok, message} + end + + defp delist_message(message, _threshold), do: {:ok, message} + + defp reject_message(message, threshold) when threshold > 0 do + with {_, recipients} <- get_recipient_count(message) do + if recipients > threshold do + {:reject, nil} + else + {:ok, message} + end + end + end + + defp reject_message(message, _threshold), do: {:ok, message} + + defp get_recipient_count(message) do + recipients = (message["to"] || []) ++ (message["cc"] || []) + follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address + + if Enum.member?(recipients, "https://www.w3.org/ns/activitystreams#Public") do + recipients = + recipients + |> List.delete("https://www.w3.org/ns/activitystreams#Public") + |> List.delete(follower_collection) + + {:public, length(recipients)} + else + recipients = + recipients + |> List.delete(follower_collection) + + {:not_public, length(recipients)} + end end @impl true def filter(%{"type" => "Create"} = message) do - delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold]) - reject_threshold = Pleroma.Config.get( [:mrf_hellthread, :reject_threshold], Pleroma.Config.get([:mrf_hellthread, :threshold]) ) - recipients = (message["to"] || []) ++ (message["cc"] || []) - - cond do - length(recipients) > reject_threshold and reject_threshold > 0 -> - {:reject, nil} - - length(recipients) > delist_threshold and delist_threshold > 0 -> - if Enum.member?(message["to"], "https://www.w3.org/ns/activitystreams#Public") or - Enum.member?(message["cc"], "https://www.w3.org/ns/activitystreams#Public") do - {:ok, delist_message(message)} - else - {:ok, message} - end + delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold]) - true -> - {:ok, message} + with {:ok, message} <- reject_message(message, reject_threshold), + {:ok, message} <- delist_message(message, delist_threshold) do + {:ok, message} + else + _e -> {:reject, nil} end end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 98a2af819..41d89a02b 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -406,7 +406,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do if not User.locked?(followed) do ActivityPub.accept(%{ to: [follower.ap_id], - actor: followed.ap_id, + actor: followed, object: data, local: true }) @@ -432,7 +432,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do ActivityPub.accept(%{ to: follow_activity.data["to"], type: "Accept", - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], local: false }) do @@ -458,7 +458,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do ActivityPub.reject(%{ to: follow_activity.data["to"], type: "Reject", - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], local: false }) do @@ -649,7 +649,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do if object = Object.normalize(id), do: {:ok, object}, else: nil end - def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do + def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) when is_binary(inReplyTo) do with false <- String.starts_with?(inReplyTo, "http"), {:ok, %{data: replied_to_object}} <- get_obj_helper(inReplyTo) do Map.put(object, "inReplyTo", replied_to_object["external_url"] || inReplyTo) @@ -765,12 +765,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def add_hashtags(object) do tags = (object["tag"] || []) - |> Enum.map(fn tag -> - %{ - "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}", - "name" => "##{tag}", - "type" => "Hashtag" - } + |> Enum.map(fn + # Expand internal representation tags into AS2 tags. + tag when is_binary(tag) -> + %{ + "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}", + "name" => "##{tag}", + "type" => "Hashtag" + } + + # Do not process tags which are already AS2 tag objects. + tag when is_map(tag) -> + tag end) object diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 15e6c1f68..c8e154989 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -12,9 +12,26 @@ defmodule Pleroma.Web.ActivityPub.UserView do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Utils + alias Pleroma.Web.Router.Helpers + alias Pleroma.Web.Endpoint import Ecto.Query + def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do + %{"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox)} + end + + def render("endpoints.json", %{user: %User{local: true} = _user}) do + %{ + "oauthAuthorizationEndpoint" => Helpers.o_auth_url(Endpoint, :authorize), + "oauthRegistrationEndpoint" => Helpers.mastodon_api_url(Endpoint, :create_app), + "oauthTokenEndpoint" => Helpers.o_auth_url(Endpoint, :token_exchange), + "sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox) + } + end + + def render("endpoints.json", _), do: %{} + # the instance itself is not a Person, but instead an Application def render("user.json", %{user: %{nickname: nil} = user}) do {:ok, user} = WebFinger.ensure_keys_present(user) @@ -22,6 +39,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) public_key = :public_key.pem_encode([public_key]) + endpoints = render("endpoints.json", %{user: user}) + %{ "id" => user.ap_id, "type" => "Application", @@ -37,9 +56,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "owner" => user.ap_id, "publicKeyPem" => public_key }, - "endpoints" => %{ - "sharedInbox" => "#{Pleroma.Web.Endpoint.url()}/inbox" - } + "endpoints" => endpoints } |> Map.merge(Utils.make_json_ld_header()) end @@ -50,6 +67,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key) public_key = :public_key.pem_encode([public_key]) + endpoints = render("endpoints.json", %{user: user}) + %{ "id" => user.ap_id, "type" => "Person", @@ -67,9 +86,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "owner" => user.ap_id, "publicKeyPem" => public_key }, - "endpoints" => %{ - "sharedInbox" => "#{Pleroma.Web.Endpoint.url()}/inbox" - }, + "endpoints" => endpoints, "icon" => %{ "type" => "Image", "url" => User.avatar_url(user) @@ -88,7 +105,14 @@ defmodule Pleroma.Web.ActivityPub.UserView do query = from(user in query, select: [:ap_id]) following = Repo.all(query) - collection(following, "#{user.ap_id}/following", page, !user.info.hide_follows) + total = + if !user.info.hide_follows do + length(following) + else + 0 + end + + collection(following, "#{user.ap_id}/following", page, !user.info.hide_follows, total) |> Map.merge(Utils.make_json_ld_header()) end @@ -97,10 +121,17 @@ defmodule Pleroma.Web.ActivityPub.UserView do query = from(user in query, select: [:ap_id]) following = Repo.all(query) + total = + if !user.info.hide_follows do + length(following) + else + 0 + end + %{ "id" => "#{user.ap_id}/following", "type" => "OrderedCollection", - "totalItems" => length(following), + "totalItems" => total, "first" => collection(following, "#{user.ap_id}/following", 1, !user.info.hide_follows) } |> Map.merge(Utils.make_json_ld_header()) @@ -111,7 +142,14 @@ defmodule Pleroma.Web.ActivityPub.UserView do query = from(user in query, select: [:ap_id]) followers = Repo.all(query) - collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_followers) + total = + if !user.info.hide_followers do + length(followers) + else + 0 + end + + collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_followers, total) |> Map.merge(Utils.make_json_ld_header()) end @@ -120,19 +158,24 @@ defmodule Pleroma.Web.ActivityPub.UserView do query = from(user in query, select: [:ap_id]) followers = Repo.all(query) + total = + if !user.info.hide_followers do + length(followers) + else + 0 + end + %{ "id" => "#{user.ap_id}/followers", "type" => "OrderedCollection", - "totalItems" => length(followers), - "first" => collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_followers) + "totalItems" => total, + "first" => + collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_followers, total) } |> Map.merge(Utils.make_json_ld_header()) end def render("outbox.json", %{user: user, max_id: max_qid}) do - # XXX: technically note_count is wrong for this, but it's better than nothing - info = User.user_info(user) - params = %{ "limit" => "10" } @@ -160,7 +203,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do "id" => "#{iri}?max_id=#{max_id}", "type" => "OrderedCollectionPage", "partOf" => iri, - "totalItems" => info.note_count, "orderedItems" => collection, "next" => "#{iri}?max_id=#{min_id}" } @@ -169,7 +211,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do %{ "id" => iri, "type" => "OrderedCollection", - "totalItems" => info.note_count, "first" => page } |> Map.merge(Utils.make_json_ld_header()) @@ -207,7 +248,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do "id" => "#{iri}?max_id=#{max_id}", "type" => "OrderedCollectionPage", "partOf" => iri, - "totalItems" => -1, "orderedItems" => collection, "next" => "#{iri}?max_id=#{min_id}" } @@ -216,7 +256,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do %{ "id" => iri, "type" => "OrderedCollection", - "totalItems" => -1, "first" => page } |> Map.merge(Utils.make_json_ld_header()) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index dcaeccac6..e2715bd08 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -680,7 +680,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do {:ok, _activity} <- ActivityPub.accept(%{ to: [follower.ap_id], - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], type: "Accept" }) do @@ -702,7 +702,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do {:ok, _activity} <- ActivityPub.reject(%{ to: [follower.ap_id], - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], type: "Reject" }) do @@ -1051,6 +1051,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do accounts = Map.put(%{}, user.id, AccountView.render("account.json", %{user: user, for: user})) + flavour = get_user_flavour(user) + initial_state = %{ meta: %{ @@ -1135,7 +1137,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do conn |> put_layout(false) |> put_view(MastodonView) - |> render("index.html", %{initial_state: initial_state}) + |> render("index.html", %{initial_state: initial_state, flavour: flavour}) else conn |> redirect(to: "/web/login") @@ -1157,6 +1159,43 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + @supported_flavours ["glitch", "vanilla"] + + def set_flavour(%{assigns: %{user: user}} = conn, %{"flavour" => flavour} = _params) + when flavour in @supported_flavours do + flavour_cng = User.Info.mastodon_flavour_update(user.info, flavour) + + with changeset <- Ecto.Changeset.change(user), + changeset <- Ecto.Changeset.put_embed(changeset, :info, flavour_cng), + {:ok, user} <- User.update_and_set_cache(changeset), + flavour <- user.info.flavour do + json(conn, flavour) + else + e -> + conn + |> put_resp_content_type("application/json") + |> send_resp(500, Jason.encode!(%{"error" => inspect(e)})) + end + end + + def set_flavour(conn, _params) do + conn + |> put_status(400) + |> json(%{error: "Unsupported flavour"}) + end + + def get_flavour(%{assigns: %{user: user}} = conn, _params) do + json(conn, get_user_flavour(user)) + end + + defp get_user_flavour(%User{info: %{flavour: flavour}}) when flavour in @supported_flavours do + flavour + end + + defp get_user_flavour(_) do + "glitch" + end + def login(conn, %{"code" => code}) do with {:ok, app} <- get_or_make_app(), %Authorization{} = auth <- Repo.get_by(Authorization, token: code, app_id: app.id), diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 69f5f992c..a49b381c9 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -166,7 +166,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do sensitive: sensitive, spoiler_text: object["summary"] || "", visibility: get_visibility(object), - media_attachments: attachments |> Enum.take(4), + media_attachments: attachments, mentions: mentions, tags: build_tags(tags), application: %{ diff --git a/lib/pleroma/web/media_proxy/media_proxy.ex b/lib/pleroma/web/media_proxy/media_proxy.ex index 1e9da7283..39a725a69 100644 --- a/lib/pleroma/web/media_proxy/media_proxy.ex +++ b/lib/pleroma/web/media_proxy/media_proxy.ex @@ -19,11 +19,16 @@ defmodule Pleroma.Web.MediaProxy do else secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base] + # Must preserve `%2F` for compatibility with S3 (https://git.pleroma.social/pleroma/pleroma/issues/580) + replacement = get_replacement(url, ":2F:") + # The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice. base64 = url + |> String.replace("%2F", replacement) |> URI.decode() |> URI.encode() + |> String.replace(replacement, "%2F") |> Base.url_encode64(@base64_opts) sig = :crypto.hmac(:sha, secret, base64) @@ -60,4 +65,12 @@ defmodule Pleroma.Web.MediaProxy do |> Enum.filter(fn value -> value end) |> Path.join() end + + defp get_replacement(url, replacement) do + if String.contains?(url, replacement) do + get_replacement(url, replacement <> replacement) + else + replacement + end + end end diff --git a/lib/pleroma/web/oauth/app.ex b/lib/pleroma/web/oauth/app.ex index 3e8acde31..8b61bf3a4 100644 --- a/lib/pleroma/web/oauth/app.ex +++ b/lib/pleroma/web/oauth/app.ex @@ -25,8 +25,14 @@ defmodule Pleroma.Web.OAuth.App do if changeset.valid? do changeset - |> put_change(:client_id, :crypto.strong_rand_bytes(32) |> Base.url_encode64()) - |> put_change(:client_secret, :crypto.strong_rand_bytes(32) |> Base.url_encode64()) + |> put_change( + :client_id, + :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) + ) + |> put_change( + :client_secret, + :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) + ) else changeset end diff --git a/lib/pleroma/web/oauth/authorization.ex b/lib/pleroma/web/oauth/authorization.ex index 75c9ab9aa..9039b8b45 100644 --- a/lib/pleroma/web/oauth/authorization.ex +++ b/lib/pleroma/web/oauth/authorization.ex @@ -24,7 +24,7 @@ defmodule Pleroma.Web.OAuth.Authorization do end def create_authorization(%App{} = app, %User{} = user) do - token = :crypto.strong_rand_bytes(32) |> Base.url_encode64() + token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) authorization = %Authorization{ token: token, diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index e4d0601f8..dddfcf299 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -173,7 +173,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do token |> URI.decode() |> Base.url_decode64!(padding: false) - |> Base.url_encode64() + |> Base.url_encode64(padding: false) end defp get_app_from_request(conn, params) do diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex index 7fe58f6a2..71fd1b874 100644 --- a/lib/pleroma/web/oauth/token.ex +++ b/lib/pleroma/web/oauth/token.ex @@ -31,8 +31,8 @@ defmodule Pleroma.Web.OAuth.Token do end def create_token(%App{} = app, %User{} = user) do - token = :crypto.strong_rand_bytes(32) |> Base.url_encode64() - refresh_token = :crypto.strong_rand_bytes(32) |> Base.url_encode64() + token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) + refresh_token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) token = %Token{ token: token, diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d45fa526e..9a6cf2232 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -236,6 +236,9 @@ defmodule Pleroma.Web.Router do get("/suggestions", MastodonAPIController, :suggestions) get("/endorsements", MastodonAPIController, :empty_array) + + post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour) + get("/pleroma/flavour", MastodonAPIController, :get_flavour) end scope "/api/web", Pleroma.Web.MastodonAPI do @@ -471,8 +474,8 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web.ActivityPub do pipe_through(:activitypub) - post("/users/:nickname/inbox", ActivityPubController, :inbox) post("/inbox", ActivityPubController, :inbox) + post("/users/:nickname/inbox", ActivityPubController, :inbox) end scope "/.well-known", Pleroma.Web do diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex index 8dd3284d6..520e4b3d5 100644 --- a/lib/pleroma/web/templates/layout/app.html.eex +++ b/lib/pleroma/web/templates/layout/app.html.eex @@ -67,6 +67,32 @@ font-weight: 500; font-size: 16px; } + + .alert-danger { + box-sizing: border-box; + width: 100%; + color: #D8000C; + background-color: #FFD2D2; + border-radius: 4px; + border: none; + padding: 10px; + margin-top: 20px; + font-weight: 500; + font-size: 16px; + } + + .alert-info { + box-sizing: border-box; + width: 100%; + color: #00529B; + background-color: #BDE5F8; + border-radius: 4px; + border: none; + padding: 10px; + margin-top: 20px; + font-weight: 500; + font-size: 16px; + } </style> </head> <body> diff --git a/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex b/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex index 9a725e420..5659c7828 100644 --- a/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex +++ b/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex @@ -8,7 +8,7 @@ </title> <link rel="icon" type="image/png" href="/favicon.png"/> <script crossorigin='anonymous' src="/packs/locales.js"></script> -<script crossorigin='anonymous' src="/packs/locales/glitch/en.js"></script> +<script crossorigin='anonymous' src="/packs/locales/<%= @flavour %>/en.js"></script> <link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/getting_started.js'> <link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/compose.js'> @@ -19,10 +19,10 @@ <script src="/packs/core/common.js"></script> <link rel="stylesheet" media="all" href="/packs/core/common.css" /> -<script src="/packs/flavours/glitch/common.js"></script> -<link rel="stylesheet" media="all" href="/packs/flavours/glitch/common.css" /> +<script src="/packs/flavours/<%= @flavour %>/common.js"></script> +<link rel="stylesheet" media="all" href="/packs/flavours/<%= @flavour %>/common.css" /> -<script src="/packs/flavours/glitch/home.js"></script> +<script src="/packs/flavours/<%= @flavour %>/home.js"></script> </head> <body class='app-body no-reduce-motion system-font'> <div class='app-holder' data-props='{"locale":"en"}' id='mastodon'> diff --git a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex index de2241ec9..32c458f0c 100644 --- a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex +++ b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex @@ -1,5 +1,9 @@ +<%= if get_flash(@conn, :info) do %> <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p> +<% end %> +<%= if get_flash(@conn, :error) do %> <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p> +<% end %> <h2>OAuth Authorization</h2> <%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %> <%= label f, :name, "Name or email" %> diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index fac05f288..b815379fd 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -528,6 +528,9 @@ defmodule Pleroma.Web.TwitterAPI.Controller do def friends(%{assigns: %{user: for_user}} = conn, params) do {:ok, page} = Ecto.Type.cast(:integer, params["page"] || 1) + {:ok, export} = Ecto.Type.cast(:boolean, params["all"] || false) + + page = if export, do: nil, else: page with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params), {:ok, friends} <- User.get_friends(user, page) do @@ -588,7 +591,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do {:ok, _activity} <- ActivityPub.accept(%{ to: [follower.ap_id], - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], type: "Accept" }) do @@ -608,7 +611,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do {:ok, _activity} <- ActivityPub.reject(%{ to: [follower.ap_id], - actor: followed.ap_id, + actor: followed, object: follow_activity.data["id"], type: "Reject" }) do diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index a09450df7..df7384476 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -113,10 +113,12 @@ defmodule Pleroma.Web.TwitterAPI.UserView do "fields" => fields, # Pleroma extension - "pleroma" => %{ - "confirmation_pending" => user_info.confirmation_pending, - "tags" => user.tags - } + "pleroma" => + %{ + "confirmation_pending" => user_info.confirmation_pending, + "tags" => user.tags + } + |> maybe_with_follow_request_count(user, for_user) } data = @@ -132,6 +134,14 @@ defmodule Pleroma.Web.TwitterAPI.UserView do end end + defp maybe_with_follow_request_count(data, %User{id: id, info: %{locked: true}} = user, %User{ + id: id + }) do + Map.put(data, "follow_request_count", user.info.follow_request_count) + end + + defp maybe_with_follow_request_count(data, _, _), do: data + defp maybe_with_role(data, %User{id: id} = user, %User{id: id}) do Map.merge(data, %{"role" => role(user), "show_role" => user.info.show_role}) end |