summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/activity.ex46
-rw-r--r--lib/pleroma/object.ex46
-rw-r--r--lib/pleroma/user.ex14
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex35
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex23
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex25
-rw-r--r--lib/pleroma/web/mastodon_api/views/app_view.ex41
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex2
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex12
-rw-r--r--lib/pleroma/web/router.ex1
-rw-r--r--lib/pleroma/web/twitter_api/representers/activity_representer.ex15
11 files changed, 212 insertions, 48 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index 3dfabe9f3..bc3f8caba 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -245,4 +245,50 @@ defmodule Pleroma.Activity do
|> where([s], s.actor == ^actor)
|> Repo.all()
end
+
+ def increase_replies_count(id) do
+ Activity
+ |> where(id: ^id)
+ |> update([a],
+ set: [
+ data:
+ fragment(
+ """
+ jsonb_set(?, '{object, repliesCount}',
+ (coalesce((?->'object'->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true)
+ """,
+ a.data,
+ a.data
+ )
+ ]
+ )
+ |> Repo.update_all([])
+ |> case do
+ {1, [activity]} -> activity
+ _ -> {:error, "Not found"}
+ end
+ end
+
+ def decrease_replies_count(id) do
+ Activity
+ |> where(id: ^id)
+ |> update([a],
+ set: [
+ data:
+ fragment(
+ """
+ jsonb_set(?, '{object, repliesCount}',
+ (greatest(0, (?->'object'->>'repliesCount')::int - 1))::varchar::jsonb, true)
+ """,
+ a.data,
+ a.data
+ )
+ ]
+ )
+ |> Repo.update_all([])
+ |> case do
+ {1, [activity]} -> activity
+ _ -> {:error, "Not found"}
+ end
+ end
end
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index 193ae3fa8..8a670645d 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -133,4 +133,50 @@ defmodule Pleroma.Object do
e -> e
end
end
+
+ def increase_replies_count(ap_id) do
+ Object
+ |> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
+ |> update([o],
+ set: [
+ data:
+ fragment(
+ """
+ jsonb_set(?, '{repliesCount}',
+ (coalesce((?->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true)
+ """,
+ o.data,
+ o.data
+ )
+ ]
+ )
+ |> Repo.update_all([])
+ |> case do
+ {1, [object]} -> set_cache(object)
+ _ -> {:error, "Not found"}
+ end
+ end
+
+ def decrease_replies_count(ap_id) do
+ Object
+ |> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
+ |> update([o],
+ set: [
+ data:
+ fragment(
+ """
+ jsonb_set(?, '{repliesCount}',
+ (greatest(0, (?->>'repliesCount')::int - 1))::varchar::jsonb, true)
+ """,
+ o.data,
+ o.data
+ )
+ ]
+ )
+ |> Repo.update_all([])
+ |> case do
+ {1, [object]} -> set_cache(object)
+ _ -> {:error, "Not found"}
+ end
+ end
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 495f9bdf5..728b00a56 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -60,14 +60,10 @@ defmodule Pleroma.User do
timestamps()
end
- def auth_active?(%User{local: false}), do: true
-
- def auth_active?(%User{info: %User.Info{confirmation_pending: false}}), do: true
-
def auth_active?(%User{info: %User.Info{confirmation_pending: true}}),
do: !Pleroma.Config.get([:instance, :account_activation_required])
- def auth_active?(_), do: false
+ def auth_active?(%User{}), do: true
def visible_for?(user, for_user \\ nil)
@@ -83,17 +79,17 @@ defmodule Pleroma.User do
def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true
def superuser?(_), do: false
- def avatar_url(user) do
+ def avatar_url(user, options \\ []) do
case user.avatar do
%{"url" => [%{"href" => href} | _]} -> href
- _ -> "#{Web.base_url()}/images/avi.png"
+ _ -> !options[:no_default] && "#{Web.base_url()}/images/avi.png"
end
end
- def banner_url(user) do
+ def banner_url(user, options \\ []) do
case user.info.banner do
%{"url" => [%{"href" => href} | _]} -> href
- _ -> "#{Web.base_url()}/images/banner.png"
+ _ -> !options[:no_default] && "#{Web.base_url()}/images/banner.png"
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 80c64ae04..6e1ed7ec9 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -89,6 +89,30 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
if is_public?(object), do: User.decrease_note_count(actor), else: {:ok, actor}
end
+ def increase_replies_count_if_reply(%{
+ "object" =>
+ %{"inReplyTo" => reply_ap_id, "inReplyToStatusId" => reply_status_id} = object,
+ "type" => "Create"
+ }) do
+ if is_public?(object) do
+ Activity.increase_replies_count(reply_status_id)
+ Object.increase_replies_count(reply_ap_id)
+ end
+ end
+
+ def increase_replies_count_if_reply(_create_data), do: :noop
+
+ def decrease_replies_count_if_reply(%Object{
+ data: %{"inReplyTo" => reply_ap_id, "inReplyToStatusId" => reply_status_id} = object
+ }) do
+ if is_public?(object) do
+ Activity.decrease_replies_count(reply_status_id)
+ Object.decrease_replies_count(reply_ap_id)
+ end
+ end
+
+ def decrease_replies_count_if_reply(_object), do: :noop
+
def insert(map, local \\ true) when is_map(map) do
with nil <- Activity.normalize(map),
map <- lazy_put_activity_defaults(map),
@@ -178,6 +202,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
additional
),
{:ok, activity} <- insert(create_data, local),
+ _ <- increase_replies_count_if_reply(create_data),
# Changing note count prior to enqueuing federation task in order to avoid
# race conditions on updating user.info
{:ok, _actor} <- increase_note_count_if_public(actor, activity),
@@ -329,6 +354,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
"deleted_activity_id" => activity && activity.id
},
{:ok, activity} <- insert(data, local),
+ _ <- decrease_replies_count_if_reply(object),
# Changing note count prior to enqueuing federation task in order to avoid
# race conditions on updating user.info
{:ok, _actor} <- decrease_note_count_if_public(user, object),
@@ -711,8 +737,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
from(
activity in query,
- where: fragment("not ?->>'type' = 'Announce'", activity.data),
- where: fragment("not ? = ANY(?)", activity.actor, ^muted_reblogs)
+ where:
+ fragment(
+ "not ( ?->>'type' = 'Announce' and ? = ANY(?))",
+ activity.data,
+ activity.actor,
+ ^muted_reblogs
+ )
)
end
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 3d00dcbf2..5926a3294 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -87,16 +87,10 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"publicKeyPem" => public_key
},
"endpoints" => endpoints,
- "icon" => %{
- "type" => "Image",
- "url" => User.avatar_url(user)
- },
- "image" => %{
- "type" => "Image",
- "url" => User.banner_url(user)
- },
"tag" => user.info.source_data["tag"] || []
}
+ |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
+ |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
|> Map.merge(Utils.make_json_ld_header())
end
@@ -294,4 +288,17 @@ defmodule Pleroma.Web.ActivityPub.UserView do
map
end
end
+
+ defp maybe_make_image(func, key, user) do
+ if image = func.(user, no_default: true) do
+ %{
+ key => %{
+ "type" => "Image",
+ "url" => image
+ }
+ }
+ else
+ %{}
+ end
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 6be0f2baf..eee4e7678 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -18,6 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.AccountView
+ alias Pleroma.Web.MastodonAPI.AppView
alias Pleroma.Web.MastodonAPI.FilterView
alias Pleroma.Web.MastodonAPI.ListView
alias Pleroma.Web.MastodonAPI.MastodonAPI
@@ -51,16 +52,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
with cs <- App.register_changeset(%App{}, app_attrs),
false <- cs.changes[:client_name] == @local_mastodon_name,
{:ok, app} <- Repo.insert(cs) do
- res = %{
- id: app.id |> to_string,
- name: app.client_name,
- client_id: app.client_id,
- client_secret: app.client_secret,
- redirect_uri: app.redirect_uris,
- website: app.website
- }
-
- json(conn, res)
+ conn
+ |> put_view(AppView)
+ |> render("show.json", %{app: app})
end
end
@@ -132,6 +126,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
json(conn, account)
end
+ def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do
+ with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
+ conn
+ |> put_view(AppView)
+ |> render("short.json", %{app: app})
+ end
+ end
+
def user(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id),
true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do
@@ -161,6 +163,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
},
stats: Stats.get_stats(),
thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg",
+ languages: ["en"],
+ registrations: Pleroma.Config.get([:instance, :registrations_open]),
+ # Extra (not present in Mastodon):
max_toot_chars: Keyword.get(instance, :limit)
}
diff --git a/lib/pleroma/web/mastodon_api/views/app_view.ex b/lib/pleroma/web/mastodon_api/views/app_view.ex
new file mode 100644
index 000000000..f52b693a6
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/views/app_view.ex
@@ -0,0 +1,41 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.AppView do
+ use Pleroma.Web, :view
+
+ alias Pleroma.Web.OAuth.App
+
+ @vapid_key :web_push_encryption
+ |> Application.get_env(:vapid_details, [])
+ |> Keyword.get(:public_key)
+
+ def render("show.json", %{app: %App{} = app}) do
+ %{
+ id: app.id |> to_string,
+ name: app.client_name,
+ client_id: app.client_id,
+ client_secret: app.client_secret,
+ redirect_uri: app.redirect_uris,
+ website: app.website
+ }
+ |> with_vapid_key()
+ end
+
+ def render("short.json", %{app: %App{website: webiste, client_name: name}}) do
+ %{
+ name: name,
+ website: webiste
+ }
+ |> with_vapid_key()
+ end
+
+ defp with_vapid_key(data) do
+ if @vapid_key do
+ Map.put(data, "vapid_key", @vapid_key)
+ else
+ data
+ end
+ end
+end
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 1ca8338cc..200bb453d 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -174,7 +174,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
content: content,
created_at: created_at,
reblogs_count: announcement_count,
- replies_count: 0,
+ replies_count: object["repliesCount"] || 0,
favourites_count: like_count,
reblogged: present?(repeated),
favourited: present?(favorited),
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index d151efe9e..ebb3dd253 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -83,14 +83,18 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end
else
{scopes_issue, _} when scopes_issue in [:unsupported_scopes, :missing_scopes] ->
+ # Per https://github.com/tootsuite/mastodon/blob/
+ # 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L39
conn
- |> put_flash(:error, "Permissions not specified.")
+ |> put_flash(:error, "This action is outside the authorized scopes")
|> put_status(:unauthorized)
|> authorize(auth_params)
{:auth_active, false} ->
+ # Per https://github.com/tootsuite/mastodon/blob/
+ # 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76
conn
- |> put_flash(:error, "Account confirmation pending.")
+ |> put_flash(:error, "Your login is missing a confirmed e-mail address")
|> put_status(:forbidden)
|> authorize(auth_params)
@@ -149,9 +153,11 @@ defmodule Pleroma.Web.OAuth.OAuthController do
json(conn, response)
else
{:auth_active, false} ->
+ # Per https://github.com/tootsuite/mastodon/blob/
+ # 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76
conn
|> put_status(:forbidden)
- |> json(%{error: "Account confirmation pending"})
+ |> json(%{error: "Your login is missing a confirmed e-mail address"})
_error ->
put_status(conn, 400)
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index befd382ba..32e5f7644 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -328,6 +328,7 @@ defmodule Pleroma.Web.Router do
get("/instance", MastodonAPIController, :masto_instance)
get("/instance/peers", MastodonAPIController, :peers)
post("/apps", MastodonAPIController, :create_app)
+ get("/apps/verify_credentials", MastodonAPIController, :verify_app_credentials)
get("/custom_emojis", MastodonAPIController, :custom_emojis)
get("/statuses/:id/card", MastodonAPIController, :status_card)
diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex
deleted file mode 100644
index 55c612ddd..000000000
--- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex
+++ /dev/null
@@ -1,15 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-# FIXME: Remove this module?
-# THIS MODULE IS DEPRECATED! DON'T USE IT!
-# USE THE Pleroma.Web.TwitterAPI.Views.ActivityView MODULE!
-defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
- def to_map(activity, opts) do
- Pleroma.Web.TwitterAPI.ActivityView.render(
- "activity.json",
- Map.put(opts, :activity, activity)
- )
- end
-end