Compare commits
No commits in common. "aee44ac25e58d1e46d5b078d36f3d72757680b51" and "e944b1529862a2a40158803da5fe04a024f7aa4f" have entirely different histories.
aee44ac25e
...
e944b15298
|
@ -1 +0,0 @@
|
||||||
Implement `/api/v1/accounts/familiar_followers`
|
|
|
@ -1 +0,0 @@
|
||||||
The query for marking notifications as read has been simplified
|
|
|
@ -1 +0,0 @@
|
||||||
Startup detection for configured MRF modules that are missing or incorrectly defined
|
|
|
@ -1 +0,0 @@
|
||||||
Add "status" notification type
|
|
|
@ -0,0 +1 @@
|
||||||
|
Strip actor property from objects before federating
|
|
@ -28,7 +28,6 @@ def verify! do
|
||||||
|> check_welcome_message_config!()
|
|> check_welcome_message_config!()
|
||||||
|> check_rum!()
|
|> check_rum!()
|
||||||
|> check_repo_pool_size!()
|
|> check_repo_pool_size!()
|
||||||
|> check_mrfs()
|
|
||||||
|> handle_result()
|
|> handle_result()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -235,25 +234,4 @@ defp check_filter(filter, command_required) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp check_mrfs(:ok) do
|
|
||||||
mrfs = Config.get!([:mrf, :policies])
|
|
||||||
|
|
||||||
missing_mrfs =
|
|
||||||
Enum.reduce(mrfs, [], fn x, acc ->
|
|
||||||
if Code.ensure_compiled(x) do
|
|
||||||
acc
|
|
||||||
else
|
|
||||||
acc ++ [x]
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
if Enum.empty?(missing_mrfs) do
|
|
||||||
:ok
|
|
||||||
else
|
|
||||||
{:error, "The following MRF modules are configured but missing: #{inspect(missing_mrfs)}"}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp check_mrfs(result), do: result
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Constants do
|
||||||
|
|
||||||
const(object_internal_fields,
|
const(object_internal_fields,
|
||||||
do: [
|
do: [
|
||||||
|
"actor",
|
||||||
"reactions",
|
"reactions",
|
||||||
"reaction_count",
|
"reaction_count",
|
||||||
"likes",
|
"likes",
|
||||||
|
|
|
@ -73,7 +73,6 @@ def unread_notifications_count(%User{id: user_id}) do
|
||||||
pleroma:report
|
pleroma:report
|
||||||
reblog
|
reblog
|
||||||
poll
|
poll
|
||||||
status
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def changeset(%Notification{} = notification, attrs) do
|
def changeset(%Notification{} = notification, attrs) do
|
||||||
|
@ -281,10 +280,15 @@ def set_read_up_to(%{id: user_id} = user, id) do
|
||||||
select: n.id
|
select: n.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
{:ok, %{ids: {_, notification_ids}}} =
|
||||||
Multi.new()
|
Multi.new()
|
||||||
|> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()])
|
|> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()])
|
||||||
|> Marker.multi_set_last_read_id(user, "notifications")
|
|> Marker.multi_set_last_read_id(user, "notifications")
|
||||||
|> Repo.transaction()
|
|> Repo.transaction()
|
||||||
|
|
||||||
|
for_user_query(user)
|
||||||
|
|> where([n], n.id in ^notification_ids)
|
||||||
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec read_one(User.t(), String.t()) ::
|
@spec read_one(User.t(), String.t()) ::
|
||||||
|
@ -295,6 +299,10 @@ def read_one(%User{} = user, notification_id) do
|
||||||
|> Multi.update(:update, changeset(notification, %{seen: true}))
|
|> Multi.update(:update, changeset(notification, %{seen: true}))
|
||||||
|> Marker.multi_set_last_read_id(user, "notifications")
|
|> Marker.multi_set_last_read_id(user, "notifications")
|
||||||
|> Repo.transaction()
|
|> Repo.transaction()
|
||||||
|
|> case do
|
||||||
|
{:ok, %{update: notification}} -> {:ok, notification}
|
||||||
|
{:error, :update, changeset, _} -> {:error, changeset}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -376,15 +384,10 @@ def create_notifications(_), do: {:ok, []}
|
||||||
defp do_create_notifications(%Activity{} = activity) do
|
defp do_create_notifications(%Activity{} = activity) do
|
||||||
enabled_receivers = get_notified_from_activity(activity)
|
enabled_receivers = get_notified_from_activity(activity)
|
||||||
|
|
||||||
enabled_subscribers = get_notified_subscribers_from_activity(activity)
|
|
||||||
|
|
||||||
notifications =
|
notifications =
|
||||||
(Enum.map(enabled_receivers, fn user ->
|
Enum.map(enabled_receivers, fn user ->
|
||||||
create_notification(activity, user)
|
create_notification(activity, user)
|
||||||
end) ++
|
end)
|
||||||
Enum.map(enabled_subscribers -- enabled_receivers, fn user ->
|
|
||||||
create_notification(activity, user, type: "status")
|
|
||||||
end))
|
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
{:ok, notifications}
|
{:ok, notifications}
|
||||||
|
@ -517,25 +520,7 @@ def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, lo
|
||||||
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
|
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_notified_from_activity(_, _local_only), do: []
|
def get_notified_from_activity(_, _local_only), do: {[], []}
|
||||||
|
|
||||||
def get_notified_subscribers_from_activity(activity, local_only \\ true)
|
|
||||||
|
|
||||||
def get_notified_subscribers_from_activity(
|
|
||||||
%Activity{data: %{"type" => "Create"}} = activity,
|
|
||||||
local_only
|
|
||||||
) do
|
|
||||||
notification_enabled_ap_ids =
|
|
||||||
[]
|
|
||||||
|> Utils.maybe_notify_subscribers(activity)
|
|
||||||
|
|
||||||
potential_receivers =
|
|
||||||
User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only)
|
|
||||||
|
|
||||||
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_notified_subscribers_from_activity(_, _), do: []
|
|
||||||
|
|
||||||
# For some activities, only notify the author of the object
|
# For some activities, only notify the author of the object
|
||||||
def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}})
|
def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}})
|
||||||
|
@ -578,6 +563,7 @@ def get_potential_receiver_ap_ids(activity) do
|
||||||
[]
|
[]
|
||||||
|> Utils.maybe_notify_to_recipients(activity)
|
|> Utils.maybe_notify_to_recipients(activity)
|
||||||
|> Utils.maybe_notify_mentioned_recipients(activity)
|
|> Utils.maybe_notify_mentioned_recipients(activity)
|
||||||
|
|> Utils.maybe_notify_subscribers(activity)
|
||||||
|> Utils.maybe_notify_followers(activity)
|
|> Utils.maybe_notify_followers(activity)
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,6 @@ def key_id_to_actor_id(key_id) do
|
||||||
key_id
|
key_id
|
||||||
|> URI.parse()
|
|> URI.parse()
|
||||||
|> Map.put(:fragment, nil)
|
|> Map.put(:fragment, nil)
|
||||||
|> remove_query()
|
|
||||||
|> remove_suffix(@known_suffixes)
|
|> remove_suffix(@known_suffixes)
|
||||||
|
|
||||||
maybe_ap_id = URI.to_string(uri)
|
maybe_ap_id = URI.to_string(uri)
|
||||||
|
@ -34,23 +33,6 @@ def key_id_to_actor_id(key_id) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp remove_query(uri) do
|
|
||||||
if uri.query do
|
|
||||||
new_query =
|
|
||||||
URI.decode_query(uri.query)
|
|
||||||
|> Map.delete("operation")
|
|
||||||
|> URI.encode_query()
|
|
||||||
|> case do
|
|
||||||
"" -> nil
|
|
||||||
query -> query
|
|
||||||
end
|
|
||||||
|
|
||||||
Map.put(uri, :query, new_query)
|
|
||||||
else
|
|
||||||
uri
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp remove_suffix(uri, [test | rest]) do
|
defp remove_suffix(uri, [test | rest]) do
|
||||||
if not is_nil(uri.path) and String.ends_with?(uri.path, test) do
|
if not is_nil(uri.path) and String.ends_with?(uri.path, test) do
|
||||||
Map.put(uri, :path, String.replace(uri.path, test, ""))
|
Map.put(uri, :path, String.replace(uri.path, test, ""))
|
||||||
|
|
|
@ -1404,40 +1404,6 @@ def get_friends_ids(%User{} = user, page \\ nil) do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_familiar_followers_query(User.t(), User.t(), pos_integer() | nil) :: Ecto.Query.t()
|
|
||||||
def get_familiar_followers_query(%User{} = user, %User{} = current_user, nil) do
|
|
||||||
friends =
|
|
||||||
get_friends_query(current_user)
|
|
||||||
|> where([u], not u.hide_follows)
|
|
||||||
|> select([u], u.id)
|
|
||||||
|
|
||||||
User.Query.build(%{is_active: true})
|
|
||||||
|> where([u], u.id not in ^[user.id, current_user.id])
|
|
||||||
|> join(:inner, [u], r in FollowingRelationship,
|
|
||||||
as: :followers_relationships,
|
|
||||||
on: r.following_id == ^user.id and r.follower_id == u.id
|
|
||||||
)
|
|
||||||
|> where([followers_relationships: r], r.state == ^:follow_accept)
|
|
||||||
|> where([followers_relationships: r], r.follower_id in subquery(friends))
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_familiar_followers_query(%User{} = user, %User{} = current_user, page) do
|
|
||||||
user
|
|
||||||
|> get_familiar_followers_query(current_user, nil)
|
|
||||||
|> User.Query.paginate(page, 20)
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec get_familiar_followers_query(User.t(), User.t()) :: Ecto.Query.t()
|
|
||||||
def get_familiar_followers_query(%User{} = user, %User{} = current_user),
|
|
||||||
do: get_familiar_followers_query(user, current_user, nil)
|
|
||||||
|
|
||||||
@spec get_familiar_followers(User.t(), User.t(), pos_integer() | nil) :: {:ok, list(User.t())}
|
|
||||||
def get_familiar_followers(%User{} = user, %User{} = current_user, page \\ nil) do
|
|
||||||
user
|
|
||||||
|> get_familiar_followers_query(current_user, page)
|
|
||||||
|> Repo.all()
|
|
||||||
end
|
|
||||||
|
|
||||||
def increase_note_count(%User{} = user) do
|
def increase_note_count(%User{} = user) do
|
||||||
User
|
User
|
||||||
|> where(id: ^user.id)
|
|> where(id: ^user.id)
|
||||||
|
|
|
@ -11,7 +11,6 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.ActorType
|
alias Pleroma.Web.ApiSpec.Schemas.ActorType
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.List
|
alias Pleroma.Web.ApiSpec.Schemas.List
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.Status
|
alias Pleroma.Web.ApiSpec.Schemas.Status
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
||||||
|
@ -514,48 +513,6 @@ def identity_proofs_operation do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def familiar_followers_operation do
|
|
||||||
%Operation{
|
|
||||||
tags: ["Retrieve account information"],
|
|
||||||
summary: "Followers that you follow",
|
|
||||||
operationId: "AccountController.familiar_followers",
|
|
||||||
description:
|
|
||||||
"Obtain a list of all accounts that follow a given account, filtered for accounts you follow.",
|
|
||||||
security: [%{"oAuth" => ["read:follows"]}],
|
|
||||||
parameters: [
|
|
||||||
Operation.parameter(
|
|
||||||
:id,
|
|
||||||
:query,
|
|
||||||
%Schema{
|
|
||||||
oneOf: [%Schema{type: :array, items: %Schema{type: :string}}, %Schema{type: :string}]
|
|
||||||
},
|
|
||||||
"Account IDs",
|
|
||||||
example: "123"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
responses: %{
|
|
||||||
200 =>
|
|
||||||
Operation.response("Accounts", "application/json", %Schema{
|
|
||||||
title: "ArrayOfAccounts",
|
|
||||||
type: :array,
|
|
||||||
items: %Schema{
|
|
||||||
title: "Account",
|
|
||||||
type: :object,
|
|
||||||
properties: %{
|
|
||||||
id: FlakeID,
|
|
||||||
accounts: %Schema{
|
|
||||||
title: "ArrayOfAccounts",
|
|
||||||
type: :array,
|
|
||||||
items: Account,
|
|
||||||
example: [Account.schema().example]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp create_request do
|
defp create_request do
|
||||||
%Schema{
|
%Schema{
|
||||||
title: "AccountCreateRequest",
|
title: "AccountCreateRequest",
|
||||||
|
|
|
@ -202,8 +202,7 @@ defp notification_type do
|
||||||
"pleroma:report",
|
"pleroma:report",
|
||||||
"move",
|
"move",
|
||||||
"follow_request",
|
"follow_request",
|
||||||
"poll",
|
"poll"
|
||||||
"status"
|
|
||||||
],
|
],
|
||||||
description: """
|
description: """
|
||||||
The type of event that resulted in the notification.
|
The type of event that resulted in the notification.
|
||||||
|
@ -217,7 +216,6 @@ defp notification_type do
|
||||||
- `pleroma:emoji_reaction` - Someone reacted with emoji to your status
|
- `pleroma:emoji_reaction` - Someone reacted with emoji to your status
|
||||||
- `pleroma:chat_mention` - Someone mentioned you in a chat message
|
- `pleroma:chat_mention` - Someone mentioned you in a chat message
|
||||||
- `pleroma:report` - Someone was reported
|
- `pleroma:report` - Someone was reported
|
||||||
- `status` - Someone you are subscribed to created a status
|
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Web.ApiSpec.PleromaNotificationOperation do
|
defmodule Pleroma.Web.ApiSpec.PleromaNotificationOperation do
|
||||||
alias OpenApiSpex.Operation
|
alias OpenApiSpex.Operation
|
||||||
alias OpenApiSpex.Schema
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.NotificationOperation
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
|
||||||
import Pleroma.Web.ApiSpec.Helpers
|
import Pleroma.Web.ApiSpec.Helpers
|
||||||
|
@ -34,7 +35,12 @@ def mark_as_read_operation do
|
||||||
Operation.response(
|
Operation.response(
|
||||||
"A Notification or array of Notifications",
|
"A Notification or array of Notifications",
|
||||||
"application/json",
|
"application/json",
|
||||||
%Schema{type: :string}
|
%Schema{
|
||||||
|
anyOf: [
|
||||||
|
%Schema{type: :array, items: NotificationOperation.notification()},
|
||||||
|
NotificationOperation.notification()
|
||||||
|
]
|
||||||
|
}
|
||||||
),
|
),
|
||||||
400 => Operation.response("Bad Request", "application/json", ApiError)
|
400 => Operation.response("Bad Request", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,10 +72,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
%{scopes: ["follow", "write:blocks"]} when action in [:block, :unblock]
|
%{scopes: ["follow", "write:blocks"]} when action in [:block, :unblock]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(
|
plug(OAuthScopesPlug, %{scopes: ["read:follows"]} when action == :relationships)
|
||||||
OAuthScopesPlug,
|
|
||||||
%{scopes: ["read:follows"]} when action in [:relationships, :familiar_followers]
|
|
||||||
)
|
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
|
@ -632,35 +629,6 @@ def endorsements(%{assigns: %{user: user}} = conn, params) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "GET /api/v1/accounts/familiar_followers"
|
|
||||||
def familiar_followers(
|
|
||||||
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
|
|
||||||
_id
|
|
||||||
) do
|
|
||||||
users =
|
|
||||||
User.get_all_by_ids(List.wrap(id))
|
|
||||||
|> Enum.map(&%{id: &1.id, accounts: get_familiar_followers(&1, user)})
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> render("familiar_followers.json",
|
|
||||||
for: user,
|
|
||||||
users: users,
|
|
||||||
as: :user
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_familiar_followers(%{id: id} = user, %{id: id}) do
|
|
||||||
User.get_familiar_followers(user, user)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_familiar_followers(%{hide_followers: true}, _current_user) do
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_familiar_followers(user, current_user) do
|
|
||||||
User.get_familiar_followers(user, current_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc "GET /api/v1/identity_proofs"
|
@doc "GET /api/v1/identity_proofs"
|
||||||
def identity_proofs(conn, params), do: MastodonAPIController.empty_array(conn, params)
|
def identity_proofs(conn, params), do: MastodonAPIController.empty_array(conn, params)
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,6 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
||||||
pleroma:emoji_reaction
|
pleroma:emoji_reaction
|
||||||
poll
|
poll
|
||||||
update
|
update
|
||||||
status
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# GET /api/v1/notifications
|
# GET /api/v1/notifications
|
||||||
|
|
|
@ -193,25 +193,6 @@ def render("relationships.json", %{user: user, targets: targets} = opts) do
|
||||||
render_many(targets, AccountView, "relationship.json", render_opts)
|
render_many(targets, AccountView, "relationship.json", render_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("familiar_followers.json", %{users: users} = opts) do
|
|
||||||
opts =
|
|
||||||
opts
|
|
||||||
|> Map.merge(%{as: :user})
|
|
||||||
|> Map.delete(:users)
|
|
||||||
|
|
||||||
users
|
|
||||||
|> render_many(AccountView, "familiar_followers.json", opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("familiar_followers.json", %{user: %{id: id, accounts: accounts}} = opts) do
|
|
||||||
accounts =
|
|
||||||
accounts
|
|
||||||
|> render_many(AccountView, "show.json", opts)
|
|
||||||
|> Enum.filter(&Enum.any?/1)
|
|
||||||
|
|
||||||
%{id: id, accounts: accounts}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp do_render("show.json", %{user: user} = opts) do
|
defp do_render("show.json", %{user: user} = opts) do
|
||||||
self = opts[:for] == user
|
self = opts[:for] == user
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,6 @@ def render(
|
||||||
"mention" ->
|
"mention" ->
|
||||||
put_status(response, activity, reading_user, status_render_opts)
|
put_status(response, activity, reading_user, status_render_opts)
|
||||||
|
|
||||||
"status" ->
|
|
||||||
put_status(response, activity, reading_user, status_render_opts)
|
|
||||||
|
|
||||||
"favourite" ->
|
"favourite" ->
|
||||||
put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
|
put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,8 @@ def mark_as_read(
|
||||||
} = conn,
|
} = conn,
|
||||||
_
|
_
|
||||||
) do
|
) do
|
||||||
with {:ok, _} <- Notification.read_one(user, notification_id) do
|
with {:ok, notification} <- Notification.read_one(user, notification_id) do
|
||||||
conn
|
render(conn, "show.json", notification: notification, for: user)
|
||||||
|> json("ok")
|
|
||||||
else
|
else
|
||||||
{:error, message} ->
|
{:error, message} ->
|
||||||
conn
|
conn
|
||||||
|
@ -39,14 +38,11 @@ def mark_as_read(
|
||||||
conn,
|
conn,
|
||||||
_
|
_
|
||||||
) do
|
) do
|
||||||
with {:ok, _} <- Notification.set_read_up_to(user, max_id) do
|
notifications =
|
||||||
conn
|
user
|
||||||
|> json("ok")
|
|> Notification.set_read_up_to(max_id)
|
||||||
else
|
|> Enum.take(80)
|
||||||
{:error, message} ->
|
|
||||||
conn
|
render(conn, "index.json", notifications: notifications, for: user)
|
||||||
|> put_status(:bad_request)
|
|
||||||
|> json(%{"error" => message})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -192,7 +192,6 @@ def format_title(%{activity: %{data: %{"directMessage" => true}}}, _mastodon_typ
|
||||||
def format_title(%{type: type}, mastodon_type) do
|
def format_title(%{type: type}, mastodon_type) do
|
||||||
case mastodon_type || type do
|
case mastodon_type || type do
|
||||||
"mention" -> "New Mention"
|
"mention" -> "New Mention"
|
||||||
"status" -> "New Status"
|
|
||||||
"follow" -> "New Follower"
|
"follow" -> "New Follower"
|
||||||
"follow_request" -> "New Follow Request"
|
"follow_request" -> "New Follow Request"
|
||||||
"reblog" -> "New Repeat"
|
"reblog" -> "New Repeat"
|
||||||
|
|
|
@ -638,7 +638,6 @@ defmodule Pleroma.Web.Router do
|
||||||
patch("/accounts/update_credentials", AccountController, :update_credentials)
|
patch("/accounts/update_credentials", AccountController, :update_credentials)
|
||||||
|
|
||||||
get("/accounts/relationships", AccountController, :relationships)
|
get("/accounts/relationships", AccountController, :relationships)
|
||||||
get("/accounts/familiar_followers", AccountController, :familiar_followers)
|
|
||||||
get("/accounts/:id/lists", AccountController, :lists)
|
get("/accounts/:id/lists", AccountController, :lists)
|
||||||
get("/accounts/:id/identity_proofs", AccountController, :identity_proofs)
|
get("/accounts/:id/identity_proofs", AccountController, :identity_proofs)
|
||||||
get("/endorsements", AccountController, :endorsements)
|
get("/endorsements", AccountController, :endorsements)
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
defmodule Pleroma.Repo.Migrations.AddStatusToNotificationsEnum do
|
|
||||||
use Ecto.Migration
|
|
||||||
|
|
||||||
@disable_ddl_transaction true
|
|
||||||
|
|
||||||
def up do
|
|
||||||
"""
|
|
||||||
alter type notification_type add value 'status'
|
|
||||||
"""
|
|
||||||
|> execute()
|
|
||||||
end
|
|
||||||
|
|
||||||
def down do
|
|
||||||
alter table(:notifications) do
|
|
||||||
modify(:type, :string)
|
|
||||||
end
|
|
||||||
|
|
||||||
"""
|
|
||||||
delete from notifications where type = 'status'
|
|
||||||
"""
|
|
||||||
|> execute()
|
|
||||||
|
|
||||||
"""
|
|
||||||
drop type if exists notification_type
|
|
||||||
"""
|
|
||||||
|> execute()
|
|
||||||
|
|
||||||
"""
|
|
||||||
create type notification_type as enum (
|
|
||||||
'follow',
|
|
||||||
'follow_request',
|
|
||||||
'mention',
|
|
||||||
'move',
|
|
||||||
'pleroma:emoji_reaction',
|
|
||||||
'pleroma:chat_mention',
|
|
||||||
'reblog',
|
|
||||||
'favourite',
|
|
||||||
'pleroma:report',
|
|
||||||
'poll',
|
|
||||||
'update'
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
|> execute()
|
|
||||||
|
|
||||||
"""
|
|
||||||
alter table notifications
|
|
||||||
alter column type type notification_type using (type::notification_type)
|
|
||||||
"""
|
|
||||||
|> execute()
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"actor": "http://2hu.gensokyo/users/raymoo",
|
"actor": "http://mastodon.example.org/users/admin",
|
||||||
"id": "http://2hu.gensokyo/objects/1",
|
"id": "http://mastodon.example.org/objects/1",
|
||||||
"object": {
|
"object": {
|
||||||
"attributedTo": "http://2hu.gensokyo/users/raymoo",
|
"attributedTo": "http://mastodon.example.org/users/admin",
|
||||||
"content": "You expected a cute girl? Too bad. <script>alert('XSS')</script>",
|
"content": "You expected a cute girl? Too bad. <script>alert('XSS')</script>",
|
||||||
"id": "http://2hu.gensokyo/objects/2",
|
"id": "http://mastodon.example.org/objects/2",
|
||||||
"published": "2020-02-12T14:08:20Z",
|
"published": "2020-02-12T14:08:20Z",
|
||||||
"to": [
|
"to": [
|
||||||
"http://2hu.gensokyo/users/marisa"
|
"http://2hu.gensokyo/users/marisa"
|
||||||
|
|
|
@ -112,7 +112,6 @@ test "it creates a notification for subscribed users" do
|
||||||
{:ok, [notification]} = Notification.create_notifications(status)
|
{:ok, [notification]} = Notification.create_notifications(status)
|
||||||
|
|
||||||
assert notification.user_id == subscriber.id
|
assert notification.user_id == subscriber.id
|
||||||
assert notification.type == "status"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not create a notification for subscribed users if status is a reply" do
|
test "does not create a notification for subscribed users if status is a reply" do
|
||||||
|
@ -137,21 +136,6 @@ test "does not create a notification for subscribed users if status is a reply"
|
||||||
assert Enum.empty?(subscriber_notifications)
|
assert Enum.empty?(subscriber_notifications)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not create subscriber notification if mentioned" do
|
|
||||||
user = insert(:user)
|
|
||||||
subscriber = insert(:user)
|
|
||||||
|
|
||||||
User.subscribe(subscriber, user)
|
|
||||||
|
|
||||||
{:ok, status} = CommonAPI.post(user, %{status: "mentioning @#{subscriber.nickname}"})
|
|
||||||
{:ok, [notification] = notifications} = Notification.create_notifications(status)
|
|
||||||
|
|
||||||
assert length(notifications) == 1
|
|
||||||
|
|
||||||
assert notification.user_id == subscriber.id
|
|
||||||
assert notification.type == "mention"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "it sends edited notifications to those who repeated a status" do
|
test "it sends edited notifications to those who repeated a status" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
repeated_user = insert(:user)
|
repeated_user = insert(:user)
|
||||||
|
@ -465,7 +449,9 @@ test "it sets all notifications as read up to a specified notification ID" do
|
||||||
status: "hey yet again @#{other_user.nickname}!"
|
status: "hey yet again @#{other_user.nickname}!"
|
||||||
})
|
})
|
||||||
|
|
||||||
Notification.set_read_up_to(other_user, n2.id)
|
[_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
|
||||||
|
|
||||||
|
assert read_notification.activity.object
|
||||||
|
|
||||||
[n3, n2, n1] = Notification.for_user(other_user)
|
[n3, n2, n1] = Notification.for_user(other_user)
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,6 @@ test "it creates a zip archive with user data" do
|
||||||
"orderedItems" => [
|
"orderedItems" => [
|
||||||
%{
|
%{
|
||||||
"object" => %{
|
"object" => %{
|
||||||
"actor" => "http://cofe.io/users/cofe",
|
|
||||||
"content" => "status1",
|
"content" => "status1",
|
||||||
"type" => "Note"
|
"type" => "Note"
|
||||||
},
|
},
|
||||||
|
@ -229,7 +228,6 @@ test "it creates a zip archive with user data" do
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
"object" => %{
|
"object" => %{
|
||||||
"actor" => "http://cofe.io/users/cofe",
|
|
||||||
"content" => "status2"
|
"content" => "status2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -2894,20 +2894,6 @@ test "should report error on non-existing alias" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "get_familiar_followers/3" do
|
|
||||||
test "returns familiar followers for a pair of users" do
|
|
||||||
user1 = insert(:user)
|
|
||||||
%{id: id2} = user2 = insert(:user)
|
|
||||||
user3 = insert(:user)
|
|
||||||
_user4 = insert(:user)
|
|
||||||
|
|
||||||
User.follow(user1, user2)
|
|
||||||
User.follow(user2, user3)
|
|
||||||
|
|
||||||
assert [%{id: ^id2}] = User.get_familiar_followers(user3, user1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "account endorsements" do
|
describe "account endorsements" do
|
||||||
test "it pins people" do
|
test "it pins people" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
|
@ -116,8 +116,6 @@ test "it fetches the actor if they aren't in our system" do
|
||||||
data =
|
data =
|
||||||
File.read!("test/fixtures/create-chat-message.json")
|
File.read!("test/fixtures/create-chat-message.json")
|
||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.put("actor", "http://mastodon.example.org/users/admin")
|
|
||||||
|> put_in(["object", "actor"], "http://mastodon.example.org/users/admin")
|
|
||||||
|
|
||||||
_recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
|
_recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ test "it inlines private announced objects" do
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data)
|
{:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data)
|
||||||
|
|
||||||
assert modified["object"]["content"] == "hey"
|
assert modified["object"]["content"] == "hey"
|
||||||
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
|
assert activity.actor == modified["object"]["attributedTo"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it turns mentions into tags" do
|
test "it turns mentions into tags" do
|
||||||
|
@ -220,7 +220,7 @@ test "it sets the 'attributedTo' property to the actor of the object if it doesn
|
||||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
|
|
||||||
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
|
assert activity.actor == modified["object"]["attributedTo"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it strips internal hashtag data" do
|
test "it strips internal hashtag data" do
|
||||||
|
@ -266,6 +266,7 @@ test "it strips internal fields" do
|
||||||
assert is_nil(modified["object"]["announcements"])
|
assert is_nil(modified["object"]["announcements"])
|
||||||
assert is_nil(modified["object"]["announcement_count"])
|
assert is_nil(modified["object"]["announcement_count"])
|
||||||
assert is_nil(modified["object"]["generator"])
|
assert is_nil(modified["object"]["generator"])
|
||||||
|
assert is_nil(modified["object"]["actor"])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it strips internal fields of article" do
|
test "it strips internal fields of article" do
|
||||||
|
|
|
@ -2172,55 +2172,6 @@ test "max pinned accounts", %{user: user, conn: conn} do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "familiar followers" do
|
|
||||||
setup do: oauth_access(["read:follows"])
|
|
||||||
|
|
||||||
test "fetch user familiar followers", %{user: user, conn: conn} do
|
|
||||||
%{id: id1} = other_user1 = insert(:user)
|
|
||||||
%{id: id2} = other_user2 = insert(:user)
|
|
||||||
_ = insert(:user)
|
|
||||||
|
|
||||||
User.follow(user, other_user1)
|
|
||||||
User.follow(other_user1, other_user2)
|
|
||||||
|
|
||||||
assert [%{"accounts" => [%{"id" => ^id1}], "id" => ^id2}] =
|
|
||||||
conn
|
|
||||||
|> put_req_header("content-type", "application/json")
|
|
||||||
|> get("/api/v1/accounts/familiar_followers?id[]=#{id2}")
|
|
||||||
|> json_response_and_validate_schema(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "returns empty array if followers are hidden", %{user: user, conn: conn} do
|
|
||||||
other_user1 = insert(:user, hide_follows: true)
|
|
||||||
%{id: id2} = other_user2 = insert(:user)
|
|
||||||
_ = insert(:user)
|
|
||||||
|
|
||||||
User.follow(user, other_user1)
|
|
||||||
User.follow(other_user1, other_user2)
|
|
||||||
|
|
||||||
assert [%{"accounts" => [], "id" => ^id2}] =
|
|
||||||
conn
|
|
||||||
|> put_req_header("content-type", "application/json")
|
|
||||||
|> get("/api/v1/accounts/familiar_followers?id[]=#{id2}")
|
|
||||||
|> json_response_and_validate_schema(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "it respects hide_followers", %{user: user, conn: conn} do
|
|
||||||
other_user1 = insert(:user)
|
|
||||||
%{id: id2} = other_user2 = insert(:user, hide_followers: true)
|
|
||||||
_ = insert(:user)
|
|
||||||
|
|
||||||
User.follow(user, other_user1)
|
|
||||||
User.follow(other_user1, other_user2)
|
|
||||||
|
|
||||||
assert [%{"accounts" => [], "id" => ^id2}] =
|
|
||||||
conn
|
|
||||||
|> put_req_header("content-type", "application/json")
|
|
||||||
|> get("/api/v1/accounts/familiar_followers?id[]=#{id2}")
|
|
||||||
|> json_response_and_validate_schema(200)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "remove from followers" do
|
describe "remove from followers" do
|
||||||
setup do: oauth_access(["follow"])
|
setup do: oauth_access(["follow"])
|
||||||
|
|
||||||
|
|
|
@ -331,31 +331,4 @@ test "muted notification" do
|
||||||
|
|
||||||
test_notifications_rendering([notification], user, [expected])
|
test_notifications_rendering([notification], user, [expected])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Subscribed status notification" do
|
|
||||||
user = insert(:user)
|
|
||||||
subscriber = insert(:user)
|
|
||||||
|
|
||||||
User.subscribe(subscriber, user)
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{status: "hi"})
|
|
||||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
|
||||||
|
|
||||||
user = User.get_cached_by_id(user.id)
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
id: to_string(notification.id),
|
|
||||||
pleroma: %{is_seen: false, is_muted: false},
|
|
||||||
type: "status",
|
|
||||||
account:
|
|
||||||
AccountView.render("show.json", %{
|
|
||||||
user: user,
|
|
||||||
for: subscriber
|
|
||||||
}),
|
|
||||||
status: StatusView.render("show.json", %{activity: activity, for: subscriber}),
|
|
||||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
|
||||||
}
|
|
||||||
|
|
||||||
test_notifications_rendering([notification], subscriber, [expected])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,11 +21,13 @@ test "it marks a single notification as read", %{user: user1, conn: conn} do
|
||||||
{:ok, [notification1]} = Notification.create_notifications(activity1)
|
{:ok, [notification1]} = Notification.create_notifications(activity1)
|
||||||
{:ok, [notification2]} = Notification.create_notifications(activity2)
|
{:ok, [notification2]} = Notification.create_notifications(activity2)
|
||||||
|
|
||||||
|
response =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "application/json")
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/pleroma/notifications/read", %{id: notification1.id})
|
|> post("/api/v1/pleroma/notifications/read", %{id: notification1.id})
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert %{"pleroma" => %{"is_seen" => true}} = response
|
||||||
assert Repo.get(Notification, notification1.id).seen
|
assert Repo.get(Notification, notification1.id).seen
|
||||||
refute Repo.get(Notification, notification2.id).seen
|
refute Repo.get(Notification, notification2.id).seen
|
||||||
end
|
end
|
||||||
|
@ -38,17 +40,14 @@ test "it marks multiple notifications as read", %{user: user1, conn: conn} do
|
||||||
|
|
||||||
[notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
|
[notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
|
||||||
|
|
||||||
refute Repo.get(Notification, notification1.id).seen
|
[response1, response2] =
|
||||||
refute Repo.get(Notification, notification2.id).seen
|
|
||||||
refute Repo.get(Notification, notification3.id).seen
|
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "application/json")
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/v1/pleroma/notifications/read", %{max_id: notification2.id})
|
|> post("/api/v1/pleroma/notifications/read", %{max_id: notification2.id})
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
[notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
|
assert %{"pleroma" => %{"is_seen" => true}} = response1
|
||||||
|
assert %{"pleroma" => %{"is_seen" => true}} = response2
|
||||||
assert Repo.get(Notification, notification1.id).seen
|
assert Repo.get(Notification, notification1.id).seen
|
||||||
assert Repo.get(Notification, notification2.id).seen
|
assert Repo.get(Notification, notification2.id).seen
|
||||||
refute Repo.get(Notification, notification3.id).seen
|
refute Repo.get(Notification, notification3.id).seen
|
||||||
|
|
Loading…
Reference in New Issue