Merge branch 'develop' into 'fix/reverse-proxy-body-too-large'
# Conflicts: # CHANGELOG.md
This commit is contained in:
commit
d2c9befc64
92 changed files with 1358 additions and 751 deletions
|
@ -37,14 +37,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Rich Media: The crawled URL is now spliced into the rich media data.
|
||||
- ActivityPub S2S: sharedInbox usage has been mostly aligned with the rules in the AP specification.
|
||||
- ActivityPub S2S: remote user deletions now work the same as local user deletions.
|
||||
- ActivityPub S2S: POST requests are now signed with `(request-target)` pseudo-header.
|
||||
- Not being able to access the Mastodon FE login page on private instances
|
||||
- Invalid SemVer version generation, when the current branch does not have commits ahead of tag/checked out on a tag
|
||||
- Pleroma.Upload base_url was not automatically whitelisted by MediaProxy. Now your custom CDN or file hosting will be accessed directly as expected.
|
||||
- Report email not being sent to admins when the reporter is a remote user
|
||||
- MRF: ensure that subdomain_match calls are case-insensitive
|
||||
- Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
|
||||
- MRF: fix use of unserializable keyword lists in describe() implementations
|
||||
|
||||
### Added
|
||||
- Conversations: Add Pleroma-specific conversation endpoints and status posting extensions. Run the `bump_all_conversations` task again to create the necessary data.
|
||||
- **Breaking:** MRF describe API, which adds support for exposing configuration information about MRF policies to NodeInfo.
|
||||
Custom modules will need to be updated by adding, at the very least, `def describe, do: {:ok, %{}}` to the MRF policy modules.
|
||||
- MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
|
||||
|
|
|
@ -59,12 +59,19 @@ Has these additional fields under the `pleroma` object:
|
|||
- `show_role`: boolean, nullable, true when the user wants his role (e.g admin, moderator) to be shown
|
||||
- `no_rich_text` - boolean, nullable, true when html tags are stripped from all statuses requested from the API
|
||||
|
||||
## Conversations
|
||||
|
||||
Has an additional field under the `pleroma` object:
|
||||
|
||||
- `recipients`: The list of the recipients of this Conversation. These will be addressed when replying to this conversation.
|
||||
|
||||
## Account Search
|
||||
|
||||
Behavior has changed:
|
||||
|
||||
- `/api/v1/accounts/search`: Does not require authentication
|
||||
|
||||
|
||||
## Notifications
|
||||
|
||||
Has these additional fields under the `pleroma` object:
|
||||
|
@ -79,6 +86,7 @@ Additional parameters can be added to the JSON body/Form data:
|
|||
- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
|
||||
- `to`: A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply.
|
||||
- `visibility`: string, besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`.
|
||||
- `in_reply_to_conversation_id`: Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`.
|
||||
|
||||
## PATCH `/api/v1/update_credentials`
|
||||
|
||||
|
|
|
@ -319,3 +319,38 @@ See [Admin-API](Admin-API.md)
|
|||
"healthy": true # Instance state
|
||||
}
|
||||
```
|
||||
|
||||
# Pleroma Conversations
|
||||
|
||||
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:
|
||||
|
||||
1. Pleroma Conversations never add or remove recipients, unless explicitly changed by the user.
|
||||
2. Pleroma Conversations statuses can be requested by Conversation id.
|
||||
3. Pleroma Conversations can be replied to.
|
||||
|
||||
Conversations have the additional field "recipients" under the "pleroma" key. This holds a list of all the accounts that will receive a message in this conversation.
|
||||
|
||||
The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visiblity to direct and address only the people who are the recipients of that Conversation.
|
||||
|
||||
|
||||
## `GET /api/v1/pleroma/conversations/:id/statuses`
|
||||
### Timeline for a given conversation
|
||||
* Method `GET`
|
||||
* Authentication: required
|
||||
* Params: Like other timelines
|
||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
|
||||
|
||||
## `GET /api/v1/pleroma/conversations/:id`
|
||||
### The conversation with the given ID.
|
||||
* Method `GET`
|
||||
* Authentication: required
|
||||
* Params: None
|
||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
|
||||
|
||||
## `PATCH /api/v1/pleroma/conversations/:id`
|
||||
### Update a conversation. Used to change the set of recipients.
|
||||
* Method `PATCH`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
* `recipients`: A list of ids of users that should receive posts to this conversation. This will replace the current list of recipients, so submit the full list. The owner of owner of the conversation will always be part of the set of recipients, though.
|
||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy)
|
||||
|
|
|
@ -26,4 +26,48 @@ def run(["tag"]) do
|
|||
end
|
||||
})
|
||||
end
|
||||
|
||||
def run(["render_timeline", nickname]) do
|
||||
start_pleroma()
|
||||
user = Pleroma.User.get_by_nickname(nickname)
|
||||
|
||||
activities =
|
||||
%{}
|
||||
|> Map.put("type", ["Create", "Announce"])
|
||||
|> Map.put("blocking_user", user)
|
||||
|> Map.put("muting_user", user)
|
||||
|> Map.put("user", user)
|
||||
|> Map.put("limit", 80)
|
||||
|> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities()
|
||||
|> Enum.reverse()
|
||||
|
||||
inputs = %{
|
||||
"One activity" => Enum.take_random(activities, 1),
|
||||
"Ten activities" => Enum.take_random(activities, 10),
|
||||
"Twenty activities" => Enum.take_random(activities, 20),
|
||||
"Forty activities" => Enum.take_random(activities, 40),
|
||||
"Eighty activities" => Enum.take_random(activities, 80)
|
||||
}
|
||||
|
||||
Benchee.run(
|
||||
%{
|
||||
"Parallel rendering" => fn activities ->
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
|
||||
activities: activities,
|
||||
for: user,
|
||||
as: :activity
|
||||
})
|
||||
end,
|
||||
"Standart rendering" => fn activities ->
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
|
||||
activities: activities,
|
||||
for: user,
|
||||
as: :activity,
|
||||
parallel: false
|
||||
})
|
||||
end
|
||||
},
|
||||
inputs: inputs
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,13 +53,11 @@ def run(["unfollow", target]) do
|
|||
def run(["list"]) do
|
||||
start_pleroma()
|
||||
|
||||
with %User{} = user <- Relay.get_actor() do
|
||||
user.following
|
||||
|> Enum.each(fn entry ->
|
||||
URI.parse(entry)
|
||||
|> Map.get(:host)
|
||||
|> shell_info()
|
||||
end)
|
||||
with %User{following: following} = _user <- Relay.get_actor() do
|
||||
following
|
||||
|> Enum.map(fn entry -> URI.parse(entry).host end)
|
||||
|> Enum.uniq()
|
||||
|> Enum.each(&shell_info(&1))
|
||||
else
|
||||
e -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
|
||||
end
|
||||
|
|
|
@ -96,6 +96,7 @@ def with_set_thread_muted_field(query, %User{} = user) do
|
|||
from([a] in query,
|
||||
left_join: tm in ThreadMute,
|
||||
on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data),
|
||||
as: :thread_mute,
|
||||
select: %Activity{a | thread_muted?: not is_nil(tm.id)}
|
||||
)
|
||||
end
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Application do
|
||||
import Cachex.Spec
|
||||
use Application
|
||||
|
||||
@name Mix.Project.config()[:name]
|
||||
@version Mix.Project.config()[:version]
|
||||
@repository Mix.Project.config()[:source_url]
|
||||
@env Mix.env()
|
||||
|
||||
def name, do: @name
|
||||
def version, do: @version
|
||||
def named_version, do: @name <> " " <> @version
|
||||
|
@ -21,116 +24,24 @@ def user_agent do
|
|||
# See http://elixir-lang.org/docs/stable/elixir/Application.html
|
||||
# for more information on OTP Applications
|
||||
def start(_type, _args) do
|
||||
import Cachex.Spec
|
||||
|
||||
Pleroma.Config.DeprecationWarnings.warn()
|
||||
setup_instrumenters()
|
||||
|
||||
# Define workers and child supervisors to be supervised
|
||||
children =
|
||||
[
|
||||
# Start the Ecto repository
|
||||
%{id: Pleroma.Repo, start: {Pleroma.Repo, :start_link, []}, type: :supervisor},
|
||||
%{id: Pleroma.Config.TransferTask, start: {Pleroma.Config.TransferTask, :start_link, []}},
|
||||
%{id: Pleroma.Emoji, start: {Pleroma.Emoji, :start_link, []}},
|
||||
%{id: Pleroma.Captcha, start: {Pleroma.Captcha, :start_link, []}},
|
||||
%{
|
||||
id: :cachex_used_captcha_cache,
|
||||
start:
|
||||
{Cachex, :start_link,
|
||||
[
|
||||
:used_captcha_cache,
|
||||
[
|
||||
ttl_interval:
|
||||
:timer.seconds(Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid]))
|
||||
]
|
||||
]}
|
||||
},
|
||||
%{
|
||||
id: :cachex_user,
|
||||
start:
|
||||
{Cachex, :start_link,
|
||||
[
|
||||
:user_cache,
|
||||
[
|
||||
default_ttl: 25_000,
|
||||
ttl_interval: 1000,
|
||||
limit: 2500
|
||||
]
|
||||
]}
|
||||
},
|
||||
%{
|
||||
id: :cachex_object,
|
||||
start:
|
||||
{Cachex, :start_link,
|
||||
[
|
||||
:object_cache,
|
||||
[
|
||||
default_ttl: 25_000,
|
||||
ttl_interval: 1000,
|
||||
limit: 2500
|
||||
]
|
||||
]}
|
||||
},
|
||||
%{
|
||||
id: :cachex_rich_media,
|
||||
start:
|
||||
{Cachex, :start_link,
|
||||
[
|
||||
:rich_media_cache,
|
||||
[
|
||||
default_ttl: :timer.minutes(120),
|
||||
limit: 5000
|
||||
]
|
||||
]}
|
||||
},
|
||||
%{
|
||||
id: :cachex_scrubber,
|
||||
start:
|
||||
{Cachex, :start_link,
|
||||
[
|
||||
:scrubber_cache,
|
||||
[
|
||||
limit: 2500
|
||||
]
|
||||
]}
|
||||
},
|
||||
%{
|
||||
id: :cachex_idem,
|
||||
start:
|
||||
{Cachex, :start_link,
|
||||
[
|
||||
:idempotency_cache,
|
||||
[
|
||||
expiration:
|
||||
expiration(
|
||||
default: :timer.seconds(6 * 60 * 60),
|
||||
interval: :timer.seconds(60)
|
||||
),
|
||||
limit: 2500
|
||||
]
|
||||
]}
|
||||
},
|
||||
%{id: Pleroma.FlakeId, start: {Pleroma.FlakeId, :start_link, []}},
|
||||
%{
|
||||
id: Pleroma.ScheduledActivityWorker,
|
||||
start: {Pleroma.ScheduledActivityWorker, :start_link, []}
|
||||
}
|
||||
Pleroma.Repo,
|
||||
Pleroma.Config.TransferTask,
|
||||
Pleroma.Emoji,
|
||||
Pleroma.Captcha,
|
||||
Pleroma.FlakeId,
|
||||
Pleroma.ScheduledActivityWorker
|
||||
] ++
|
||||
cachex_children() ++
|
||||
hackney_pool_children() ++
|
||||
[
|
||||
%{
|
||||
id: Pleroma.Web.Federator.RetryQueue,
|
||||
start: {Pleroma.Web.Federator.RetryQueue, :start_link, []}
|
||||
},
|
||||
%{
|
||||
id: Pleroma.Web.OAuth.Token.CleanWorker,
|
||||
start: {Pleroma.Web.OAuth.Token.CleanWorker, :start_link, []}
|
||||
},
|
||||
%{
|
||||
id: Pleroma.Stats,
|
||||
start: {Pleroma.Stats, :start_link, []}
|
||||
},
|
||||
Pleroma.Web.Federator.RetryQueue,
|
||||
Pleroma.Stats,
|
||||
%{
|
||||
id: :web_push_init,
|
||||
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
|
||||
|
@ -147,16 +58,12 @@ def start(_type, _args) do
|
|||
restart: :temporary
|
||||
}
|
||||
] ++
|
||||
streamer_child() ++
|
||||
chat_child() ++
|
||||
oauth_cleanup_child(oauth_cleanup_enabled?()) ++
|
||||
streamer_child(@env) ++
|
||||
chat_child(@env, chat_enabled?()) ++
|
||||
[
|
||||
# Start the endpoint when the application starts
|
||||
%{
|
||||
id: Pleroma.Web.Endpoint,
|
||||
start: {Pleroma.Web.Endpoint, :start_link, []},
|
||||
type: :supervisor
|
||||
},
|
||||
%{id: Pleroma.Gopher.Server, start: {Pleroma.Gopher.Server, :start_link, []}}
|
||||
Pleroma.Web.Endpoint,
|
||||
Pleroma.Gopher.Server
|
||||
]
|
||||
|
||||
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
|
||||
|
@ -201,28 +108,54 @@ def enabled_hackney_pools do
|
|||
end
|
||||
end
|
||||
|
||||
if Pleroma.Config.get(:env) == :test do
|
||||
defp streamer_child, do: []
|
||||
defp chat_child, do: []
|
||||
else
|
||||
defp streamer_child do
|
||||
[%{id: Pleroma.Web.Streamer, start: {Pleroma.Web.Streamer, :start_link, []}}]
|
||||
end
|
||||
|
||||
defp chat_child do
|
||||
if Pleroma.Config.get([:chat, :enabled]) do
|
||||
[
|
||||
%{
|
||||
id: Pleroma.Web.ChatChannel.ChatChannelState,
|
||||
start: {Pleroma.Web.ChatChannel.ChatChannelState, :start_link, []}
|
||||
}
|
||||
]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
defp cachex_children do
|
||||
[
|
||||
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
|
||||
build_cachex("user", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
|
||||
build_cachex("object", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
|
||||
build_cachex("rich_media", default_ttl: :timer.minutes(120), limit: 5000),
|
||||
build_cachex("scrubber", limit: 2500),
|
||||
build_cachex("idempotency", expiration: idempotency_expiration(), limit: 2500)
|
||||
]
|
||||
end
|
||||
|
||||
defp idempotency_expiration,
|
||||
do: expiration(default: :timer.seconds(6 * 60 * 60), interval: :timer.seconds(60))
|
||||
|
||||
defp seconds_valid_interval,
|
||||
do: :timer.seconds(Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid]))
|
||||
|
||||
defp build_cachex(type, opts),
|
||||
do: %{
|
||||
id: String.to_atom("cachex_" <> type),
|
||||
start: {Cachex, :start_link, [String.to_atom(type <> "_cache"), opts]},
|
||||
type: :worker
|
||||
}
|
||||
|
||||
defp chat_enabled?, do: Pleroma.Config.get([:chat, :enabled])
|
||||
|
||||
defp oauth_cleanup_enabled?,
|
||||
do: Pleroma.Config.get([:oauth2, :clean_expired_tokens], false)
|
||||
|
||||
defp streamer_child(:test), do: []
|
||||
|
||||
defp streamer_child(_) do
|
||||
[Pleroma.Web.Streamer]
|
||||
end
|
||||
|
||||
defp oauth_cleanup_child(true),
|
||||
do: [Pleroma.Web.OAuth.Token.CleanWorker]
|
||||
|
||||
defp oauth_cleanup_child(_), do: []
|
||||
|
||||
defp chat_child(:test, _), do: []
|
||||
|
||||
defp chat_child(_env, true) do
|
||||
[Pleroma.Web.ChatChannel.ChatChannelState]
|
||||
end
|
||||
|
||||
defp chat_child(_, _), do: []
|
||||
|
||||
defp hackney_pool_children do
|
||||
for pool <- enabled_hackney_pools() do
|
||||
options = Pleroma.Config.get([:hackney_pools, pool])
|
||||
|
|
|
@ -12,7 +12,7 @@ defmodule Pleroma.Captcha do
|
|||
use GenServer
|
||||
|
||||
@doc false
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Config.TransferTask do
|
|||
use Task
|
||||
alias Pleroma.Web.AdminAPI.Config
|
||||
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
load_and_update_env()
|
||||
if Pleroma.Config.get(:env) == :test, do: Ecto.Adapters.SQL.Sandbox.checkin(Pleroma.Repo)
|
||||
:ignore
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Conversation do
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Conversation.Participation.RecipientShip
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
use Ecto.Schema
|
||||
|
@ -39,6 +40,15 @@ def get_for_ap_id(ap_id) do
|
|||
Repo.get_by(__MODULE__, ap_id: ap_id)
|
||||
end
|
||||
|
||||
def maybe_create_recipientships(participation, activity) do
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
||||
if participation.recipients |> Enum.empty?() do
|
||||
recipients = User.get_all_by_ap_id(activity.recipients)
|
||||
RecipientShip.create(recipients, participation)
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
This will
|
||||
1. Create a conversation if there isn't one already
|
||||
|
@ -60,6 +70,7 @@ def create_or_bump_for(activity, opts \\ []) do
|
|||
{:ok, participation} =
|
||||
Participation.create_for_user_and_conversation(user, conversation, opts)
|
||||
|
||||
maybe_create_recipientships(participation, activity)
|
||||
participation
|
||||
end)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.Conversation.Participation do
|
||||
use Ecto.Schema
|
||||
alias Pleroma.Conversation
|
||||
alias Pleroma.Conversation.Participation.RecipientShip
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
@ -17,6 +18,9 @@ defmodule Pleroma.Conversation.Participation do
|
|||
field(:read, :boolean, default: false)
|
||||
field(:last_activity_id, Pleroma.FlakeId, virtual: true)
|
||||
|
||||
has_many(:recipient_ships, RecipientShip)
|
||||
has_many(:recipients, through: [:recipient_ships, :user])
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
|
@ -65,6 +69,14 @@ def for_user(user, params \\ %{}) do
|
|||
|> Pleroma.Pagination.fetch_paginated(params)
|
||||
end
|
||||
|
||||
def for_user_and_conversation(user, conversation) do
|
||||
from(p in __MODULE__,
|
||||
where: p.user_id == ^user.id,
|
||||
where: p.conversation_id == ^conversation.id
|
||||
)
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
def for_user_with_last_activity_id(user, params \\ %{}) do
|
||||
for_user(user, params)
|
||||
|> Enum.map(fn participation ->
|
||||
|
@ -81,4 +93,46 @@ def for_user_with_last_activity_id(user, params \\ %{}) do
|
|||
end)
|
||||
|> Enum.filter(& &1.last_activity_id)
|
||||
end
|
||||
|
||||
def get(_, _ \\ [])
|
||||
def get(nil, _), do: nil
|
||||
|
||||
def get(id, params) do
|
||||
query =
|
||||
if preload = params[:preload] do
|
||||
from(p in __MODULE__,
|
||||
preload: ^preload
|
||||
)
|
||||
else
|
||||
__MODULE__
|
||||
end
|
||||
|
||||
Repo.get(query, id)
|
||||
end
|
||||
|
||||
def set_recipients(participation, user_ids) do
|
||||
user_ids =
|
||||
[participation.user_id | user_ids]
|
||||
|> Enum.uniq()
|
||||
|
||||
Repo.transaction(fn ->
|
||||
query =
|
||||
from(r in RecipientShip,
|
||||
where: r.participation_id == ^participation.id
|
||||
)
|
||||
|
||||
Repo.delete_all(query)
|
||||
|
||||
users =
|
||||
from(u in User,
|
||||
where: u.id in ^user_ids
|
||||
)
|
||||
|> Repo.all()
|
||||
|
||||
RecipientShip.create(users, participation)
|
||||
:ok
|
||||
end)
|
||||
|
||||
{:ok, Repo.preload(participation, :recipients, force: true)}
|
||||
end
|
||||
end
|
||||
|
|
34
lib/pleroma/conversation/participation_recipient_ship.ex
Normal file
34
lib/pleroma/conversation/participation_recipient_ship.ex
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Conversation.Participation.RecipientShip do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
import Ecto.Changeset
|
||||
|
||||
schema "conversation_participation_recipient_ships" do
|
||||
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||
belongs_to(:participation, Participation)
|
||||
end
|
||||
|
||||
def creation_cng(struct, params) do
|
||||
struct
|
||||
|> cast(params, [:user_id, :participation_id])
|
||||
|> validate_required([:user_id, :participation_id])
|
||||
end
|
||||
|
||||
def create(%User{} = user, participation), do: create([user], participation)
|
||||
|
||||
def create(users, participation) do
|
||||
Enum.each(users, fn user ->
|
||||
%__MODULE__{}
|
||||
|> creation_cng(%{user_id: user.id, participation_id: participation.id})
|
||||
|> Repo.insert!()
|
||||
end)
|
||||
end
|
||||
end
|
|
@ -1,3 +1,7 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.DigestEmailWorker do
|
||||
import Ecto.Query
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ defmodule Pleroma.Emoji do
|
|||
@ets_options [:ordered_set, :protected, :named_table, {:read_concurrency, true}]
|
||||
|
||||
@doc false
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
||||
end
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ def dump(value) do
|
|||
def autogenerate, do: get()
|
||||
|
||||
# -- GenServer API
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
:gen_server.start_link({:local, :flake}, __MODULE__, [], [])
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Gopher.Server do
|
|||
use GenServer
|
||||
require Logger
|
||||
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
config = Pleroma.Config.get(:gopher, [])
|
||||
ip = Keyword.get(config, :ip, {0, 0, 0, 0})
|
||||
port = Keyword.get(config, :port, 1234)
|
||||
|
|
|
@ -203,6 +203,8 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
Meta.allow_tag_with_these_attributes("p", [])
|
||||
Meta.allow_tag_with_these_attributes("pre", [])
|
||||
Meta.allow_tag_with_these_attributes("strong", [])
|
||||
Meta.allow_tag_with_these_attributes("sub", [])
|
||||
Meta.allow_tag_with_these_attributes("sup", [])
|
||||
Meta.allow_tag_with_these_attributes("u", [])
|
||||
Meta.allow_tag_with_these_attributes("ul", [])
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule Pleroma.ScheduledActivityWorker do
|
|||
|
||||
@schedule_interval :timer.minutes(1)
|
||||
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, nil)
|
||||
end
|
||||
|
||||
|
|
|
@ -7,31 +7,56 @@ defmodule Pleroma.Stats do
|
|||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
def start_link do
|
||||
agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__)
|
||||
spawn(fn -> schedule_update() end)
|
||||
agent
|
||||
use GenServer
|
||||
|
||||
@interval 1000 * 60 * 60
|
||||
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, initial_data(), name: __MODULE__)
|
||||
end
|
||||
|
||||
def force_update do
|
||||
GenServer.call(__MODULE__, :force_update)
|
||||
end
|
||||
|
||||
def get_stats do
|
||||
Agent.get(__MODULE__, fn {_, stats} -> stats end)
|
||||
%{stats: stats} = GenServer.call(__MODULE__, :get_state)
|
||||
|
||||
stats
|
||||
end
|
||||
|
||||
def get_peers do
|
||||
Agent.get(__MODULE__, fn {peers, _} -> peers end)
|
||||
%{peers: peers} = GenServer.call(__MODULE__, :get_state)
|
||||
|
||||
peers
|
||||
end
|
||||
|
||||
def schedule_update do
|
||||
spawn(fn ->
|
||||
# 1 hour
|
||||
Process.sleep(1000 * 60 * 60)
|
||||
schedule_update()
|
||||
end)
|
||||
|
||||
update_stats()
|
||||
def init(args) do
|
||||
Process.send(self(), :run_update, [])
|
||||
{:ok, args}
|
||||
end
|
||||
|
||||
def update_stats do
|
||||
def handle_call(:force_update, _from, _state) do
|
||||
new_stats = get_stat_data()
|
||||
{:reply, new_stats, new_stats}
|
||||
end
|
||||
|
||||
def handle_call(:get_state, _from, state) do
|
||||
{:reply, state, state}
|
||||
end
|
||||
|
||||
def handle_info(:run_update, _state) do
|
||||
new_stats = get_stat_data()
|
||||
|
||||
Process.send_after(self(), :run_update, @interval)
|
||||
{:noreply, new_stats}
|
||||
end
|
||||
|
||||
defp initial_data do
|
||||
%{peers: [], stats: %{}}
|
||||
end
|
||||
|
||||
defp get_stat_data do
|
||||
peers =
|
||||
from(
|
||||
u in User,
|
||||
|
@ -52,8 +77,9 @@ def update_stats do
|
|||
|
||||
user_count = Repo.aggregate(User.Query.build(%{local: true, active: true}), :count, :id)
|
||||
|
||||
Agent.update(__MODULE__, fn _ ->
|
||||
{peers, %{domain_count: domain_count, status_count: status_count, user_count: user_count}}
|
||||
end)
|
||||
%{
|
||||
peers: peers,
|
||||
stats: %{domain_count: domain_count, status_count: status_count, user_count: user_count}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,6 +21,7 @@ defmodule Pleroma.User do
|
|||
alias Pleroma.Web
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
|
||||
alias Pleroma.Web.OAuth
|
||||
alias Pleroma.Web.OStatus
|
||||
|
@ -132,6 +133,28 @@ def user_info(%User{} = user, args \\ %{}) do
|
|||
|> Map.put(:follower_count, follower_count)
|
||||
end
|
||||
|
||||
def follow_state(%User{} = user, %User{} = target) do
|
||||
follow_activity = Utils.fetch_latest_follow(user, target)
|
||||
|
||||
if follow_activity,
|
||||
do: follow_activity.data["state"],
|
||||
# Ideally this would be nil, but then Cachex does not commit the value
|
||||
else: false
|
||||
end
|
||||
|
||||
def get_cached_follow_state(user, target) do
|
||||
key = "follow_state:#{user.ap_id}|#{target.ap_id}"
|
||||
Cachex.fetch!(:user_cache, key, fn _ -> {:commit, follow_state(user, target)} end)
|
||||
end
|
||||
|
||||
def set_follow_state_cache(user_ap_id, target_ap_id, state) 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
|
||||
|
@ -463,6 +486,13 @@ def get_by_ap_id(ap_id) do
|
|||
Repo.get_by(User, ap_id: ap_id)
|
||||
end
|
||||
|
||||
def get_all_by_ap_id(ap_ids) do
|
||||
from(u in __MODULE__,
|
||||
where: u.ap_id in ^ap_ids
|
||||
)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
# This is mostly an SPC migration fix. This guesses the user nickname by taking the last part
|
||||
# of the ap_id and the domain and tries to get that user
|
||||
def get_by_guessed_nickname(ap_id) do
|
||||
|
@ -720,6 +750,7 @@ def update_note_count(%User{} = user) do
|
|||
|> update_and_set_cache()
|
||||
end
|
||||
|
||||
@spec maybe_fetch_follow_information(User.t()) :: User.t()
|
||||
def maybe_fetch_follow_information(user) do
|
||||
with {:ok, user} <- fetch_follow_information(user) do
|
||||
user
|
||||
|
@ -777,9 +808,10 @@ def update_follower_count(%User{} = user) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec maybe_update_following_count(User.t()) :: User.t()
|
||||
def maybe_update_following_count(%User{local: false} = user) do
|
||||
if Pleroma.Config.get([:instance, :external_user_synchronization]) do
|
||||
{:ok, maybe_fetch_follow_information(user)}
|
||||
maybe_fetch_follow_information(user)
|
||||
else
|
||||
user
|
||||
end
|
||||
|
@ -885,6 +917,13 @@ def block(blocker, %User{ap_id: ap_id} = blocked) do
|
|||
blocker
|
||||
end
|
||||
|
||||
# clear any requested follows as well
|
||||
blocked =
|
||||
case CommonAPI.reject_follow_request(blocked, blocker) do
|
||||
{:ok, %User{} = updated_blocked} -> updated_blocked
|
||||
nil -> blocked
|
||||
end
|
||||
|
||||
blocker =
|
||||
if subscribed_to?(blocked, blocker) do
|
||||
{:ok, blocker} = unsubscribe(blocked, blocker)
|
||||
|
|
|
@ -388,7 +388,8 @@ def unannounce(
|
|||
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.set_follow_state_cache(follower.ap_id, followed.ap_id, activity.data["state"]) do
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
@ -790,14 +791,20 @@ defp restrict_reblogs(query, _), do: query
|
|||
|
||||
defp restrict_muted(query, %{"with_muted" => val}) when val in [true, "true", "1"], do: query
|
||||
|
||||
defp restrict_muted(query, %{"muting_user" => %User{info: info}}) do
|
||||
defp restrict_muted(query, %{"muting_user" => %User{info: info}} = opts) do
|
||||
mutes = info.mutes
|
||||
|
||||
from(
|
||||
activity in query,
|
||||
where: fragment("not (? = ANY(?))", activity.actor, ^mutes),
|
||||
where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes)
|
||||
)
|
||||
query =
|
||||
from([activity] in query,
|
||||
where: fragment("not (? = ANY(?))", activity.actor, ^mutes),
|
||||
where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes)
|
||||
)
|
||||
|
||||
unless opts["skip_preload"] do
|
||||
from([thread_mute: tm] in query, where: is_nil(tm))
|
||||
else
|
||||
query
|
||||
end
|
||||
end
|
||||
|
||||
defp restrict_muted(query, _), do: query
|
||||
|
@ -898,7 +905,7 @@ defp maybe_set_thread_muted_field(query, %{"skip_preload" => true}), do: query
|
|||
|
||||
defp maybe_set_thread_muted_field(query, opts) do
|
||||
query
|
||||
|> Activity.with_set_thread_muted_field(opts["user"])
|
||||
|> Activity.with_set_thread_muted_field(opts["muting_user"] || opts["user"])
|
||||
end
|
||||
|
||||
defp maybe_order(query, %{order: :desc}) do
|
||||
|
|
|
@ -92,5 +92,6 @@ def filter(%{"type" => "Create"} = message) do
|
|||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{mrf_hellthread: Pleroma.Config.get([:mrf_hellthread])}}
|
||||
def describe,
|
||||
do: {:ok, %{mrf_hellthread: Pleroma.Config.get(:mrf_hellthread) |> Enum.into(%{})}}
|
||||
end
|
||||
|
|
|
@ -46,5 +46,6 @@ def filter(%{"type" => "Create"} = object) do
|
|||
def filter(object), do: {:ok, object}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{mrf_rejectnonpublic: Pleroma.Config.get([:mrf_rejectnonpublic])}}
|
||||
def describe,
|
||||
do: {:ok, %{mrf_rejectnonpublic: Pleroma.Config.get(:mrf_rejectnonpublic) |> Enum.into(%{})}}
|
||||
end
|
||||
|
|
|
@ -32,5 +32,6 @@ def filter(%{"type" => message_type} = message) do
|
|||
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
def describe, do: {:ok, %{mrf_vocabulary: Pleroma.Config.get(:mrf_vocabulary)}}
|
||||
def describe,
|
||||
do: {:ok, %{mrf_vocabulary: Pleroma.Config.get(:mrf_vocabulary) |> Enum.into(%{})}}
|
||||
end
|
||||
|
|
|
@ -46,7 +46,7 @@ def is_representable?(%Activity{} = activity) do
|
|||
"""
|
||||
def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
|
||||
Logger.info("Federating #{id} to #{inbox}")
|
||||
host = URI.parse(inbox).host
|
||||
%{host: host, path: path} = URI.parse(inbox)
|
||||
|
||||
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
|
||||
|
||||
|
@ -56,6 +56,7 @@ def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = pa
|
|||
|
||||
signature =
|
||||
Pleroma.Signature.sign(actor, %{
|
||||
"(request-target)": "post #{path}",
|
||||
host: host,
|
||||
"content-length": byte_size(json),
|
||||
digest: digest,
|
||||
|
|
|
@ -374,6 +374,7 @@ def update_follow_state_for_all(
|
|||
[state, actor, object]
|
||||
)
|
||||
|
||||
User.set_follow_state_cache(actor, object, state)
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
{:ok, activity}
|
||||
rescue
|
||||
|
@ -382,12 +383,16 @@ def update_follow_state_for_all(
|
|||
end
|
||||
end
|
||||
|
||||
def update_follow_state(%Activity{} = activity, state) do
|
||||
def update_follow_state(
|
||||
%Activity{data: %{"actor" => actor, "object" => object}} = activity,
|
||||
state
|
||||
) do
|
||||
with new_data <-
|
||||
activity.data
|
||||
|> Map.put("state", state),
|
||||
changeset <- Changeset.change(activity, data: new_data),
|
||||
{:ok, activity} <- Repo.update(changeset) do
|
||||
{:ok, activity} <- Repo.update(changeset),
|
||||
_ <- User.set_follow_state_cache(actor, object, state) do
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,9 +33,11 @@ def handle_in("new_msg", %{"text" => text}, %{assigns: %{user_name: user_name}}
|
|||
end
|
||||
|
||||
defmodule Pleroma.Web.ChatChannel.ChatChannelState do
|
||||
use Agent
|
||||
|
||||
@max_messages 20
|
||||
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
Agent.start_link(fn -> %{max_id: 1, messages: []} end, name: __MODULE__)
|
||||
end
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPI do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.ThreadMute
|
||||
|
@ -171,21 +172,25 @@ defp normalize_and_validate_choice_indices(choices, count) do
|
|||
end)
|
||||
end
|
||||
|
||||
def get_visibility(%{"visibility" => visibility}, in_reply_to)
|
||||
def get_visibility(_, _, %Participation{}) do
|
||||
{"direct", "direct"}
|
||||
end
|
||||
|
||||
def get_visibility(%{"visibility" => visibility}, in_reply_to, _)
|
||||
when visibility in ~w{public unlisted private direct},
|
||||
do: {visibility, get_replied_to_visibility(in_reply_to)}
|
||||
|
||||
def get_visibility(%{"visibility" => "list:" <> list_id}, in_reply_to) do
|
||||
def get_visibility(%{"visibility" => "list:" <> list_id}, in_reply_to, _) do
|
||||
visibility = {:list, String.to_integer(list_id)}
|
||||
{visibility, get_replied_to_visibility(in_reply_to)}
|
||||
end
|
||||
|
||||
def get_visibility(_, in_reply_to) when not is_nil(in_reply_to) do
|
||||
def get_visibility(_, in_reply_to, _) when not is_nil(in_reply_to) do
|
||||
visibility = get_replied_to_visibility(in_reply_to)
|
||||
{visibility, visibility}
|
||||
end
|
||||
|
||||
def get_visibility(_, in_reply_to), do: {"public", get_replied_to_visibility(in_reply_to)}
|
||||
def get_visibility(_, in_reply_to, _), do: {"public", get_replied_to_visibility(in_reply_to)}
|
||||
|
||||
def get_replied_to_visibility(nil), do: nil
|
||||
|
||||
|
@ -201,7 +206,9 @@ def post(user, %{"status" => status} = data) do
|
|||
with status <- String.trim(status),
|
||||
attachments <- attachments_from_ids(data),
|
||||
in_reply_to <- get_replied_to_activity(data["in_reply_to_status_id"]),
|
||||
{visibility, in_reply_to_visibility} <- get_visibility(data, in_reply_to),
|
||||
in_reply_to_conversation <- Participation.get(data["in_reply_to_conversation_id"]),
|
||||
{visibility, in_reply_to_visibility} <-
|
||||
get_visibility(data, in_reply_to, in_reply_to_conversation),
|
||||
{_, false} <-
|
||||
{:private_to_public, in_reply_to_visibility == "direct" && visibility != "direct"},
|
||||
{content_html, mentions, tags} <-
|
||||
|
@ -214,8 +221,9 @@ def post(user, %{"status" => status} = data) do
|
|||
mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.ap_id),
|
||||
addressed_users <- get_addressed_users(mentioned_users, data["to"]),
|
||||
{poll, poll_emoji} <- make_poll_data(data),
|
||||
{to, cc} <- get_to_and_cc(user, addressed_users, in_reply_to, visibility),
|
||||
context <- make_context(in_reply_to),
|
||||
{to, cc} <-
|
||||
get_to_and_cc(user, addressed_users, in_reply_to, visibility, in_reply_to_conversation),
|
||||
context <- make_context(in_reply_to, in_reply_to_conversation),
|
||||
cw <- data["spoiler_text"] || "",
|
||||
sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}),
|
||||
full_payload <- String.trim(status <> cw),
|
||||
|
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
alias Calendar.Strftime
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Plugs.AuthenticationPlug
|
||||
|
@ -86,9 +87,21 @@ def attachments_from_ids_descs(ids, descs_str) do
|
|||
|> Enum.filter(& &1)
|
||||
end
|
||||
|
||||
@spec get_to_and_cc(User.t(), list(String.t()), Activity.t() | nil, String.t()) ::
|
||||
@spec get_to_and_cc(
|
||||
User.t(),
|
||||
list(String.t()),
|
||||
Activity.t() | nil,
|
||||
String.t(),
|
||||
Participation.t() | nil
|
||||
) ::
|
||||
{list(String.t()), list(String.t())}
|
||||
def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do
|
||||
|
||||
def get_to_and_cc(_, _, _, _, %Participation{} = participation) do
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
{Enum.map(participation.recipients, & &1.ap_id), []}
|
||||
end
|
||||
|
||||
def get_to_and_cc(user, mentioned_users, inReplyTo, "public", _) do
|
||||
to = [Pleroma.Constants.as_public() | mentioned_users]
|
||||
cc = [user.follower_address]
|
||||
|
||||
|
@ -99,7 +112,7 @@ def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do
|
|||
end
|
||||
end
|
||||
|
||||
def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do
|
||||
def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted", _) do
|
||||
to = [user.follower_address | mentioned_users]
|
||||
cc = [Pleroma.Constants.as_public()]
|
||||
|
||||
|
@ -110,12 +123,12 @@ def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do
|
|||
end
|
||||
end
|
||||
|
||||
def get_to_and_cc(user, mentioned_users, inReplyTo, "private") do
|
||||
{to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct")
|
||||
def get_to_and_cc(user, mentioned_users, inReplyTo, "private", _) do
|
||||
{to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct", nil)
|
||||
{[user.follower_address | to], cc}
|
||||
end
|
||||
|
||||
def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do
|
||||
def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct", _) do
|
||||
if inReplyTo do
|
||||
{Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []}
|
||||
else
|
||||
|
@ -123,7 +136,7 @@ def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do
|
|||
end
|
||||
end
|
||||
|
||||
def get_to_and_cc(_user, mentions, _inReplyTo, {:list, _}), do: {mentions, []}
|
||||
def get_to_and_cc(_user, mentions, _inReplyTo, {:list, _}, _), do: {mentions, []}
|
||||
|
||||
def get_addressed_users(_, to) when is_list(to) do
|
||||
User.get_ap_ids_by_nicknames(to)
|
||||
|
@ -253,8 +266,12 @@ defp maybe_add_nsfw_tag({text, mentions, tags}, %{"sensitive" => sensitive})
|
|||
|
||||
defp maybe_add_nsfw_tag(data, _), do: data
|
||||
|
||||
def make_context(%Activity{data: %{"context" => context}}), do: context
|
||||
def make_context(_), do: Utils.generate_context_id()
|
||||
def make_context(_, %Participation{} = participation) do
|
||||
Repo.preload(participation, :conversation).conversation.ap_id
|
||||
end
|
||||
|
||||
def make_context(%Activity{data: %{"context" => context}}, _), do: context
|
||||
def make_context(_, _), do: Utils.generate_context_id()
|
||||
|
||||
def maybe_add_attachments(parsed, _attachments, true = _no_links), do: parsed
|
||||
|
||||
|
|
|
@ -33,4 +33,80 @@ defp param_to_integer(val, default) when is_binary(val) do
|
|||
end
|
||||
|
||||
defp param_to_integer(_, default), do: default
|
||||
|
||||
def add_link_headers(
|
||||
conn,
|
||||
method,
|
||||
activities,
|
||||
param \\ nil,
|
||||
params \\ %{},
|
||||
func3 \\ nil,
|
||||
func4 \\ nil
|
||||
) do
|
||||
params =
|
||||
conn.params
|
||||
|> Map.drop(["since_id", "max_id", "min_id"])
|
||||
|> Map.merge(params)
|
||||
|
||||
last = List.last(activities)
|
||||
|
||||
func3 = func3 || (&mastodon_api_url/3)
|
||||
func4 = func4 || (&mastodon_api_url/4)
|
||||
|
||||
if last do
|
||||
max_id = last.id
|
||||
|
||||
limit =
|
||||
params
|
||||
|> Map.get("limit", "20")
|
||||
|> String.to_integer()
|
||||
|
||||
min_id =
|
||||
if length(activities) <= limit do
|
||||
activities
|
||||
|> List.first()
|
||||
|> Map.get(:id)
|
||||
else
|
||||
activities
|
||||
|> Enum.at(limit * -1)
|
||||
|> Map.get(:id)
|
||||
end
|
||||
|
||||
{next_url, prev_url} =
|
||||
if param do
|
||||
{
|
||||
func4.(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
param,
|
||||
Map.merge(params, %{max_id: max_id})
|
||||
),
|
||||
func4.(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
param,
|
||||
Map.merge(params, %{min_id: min_id})
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
func3.(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
Map.merge(params, %{max_id: max_id})
|
||||
),
|
||||
func3.(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
Map.merge(params, %{min_id: min_id})
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
conn
|
||||
|> put_resp_header("link", "<#{next_url}>; rel=\"next\", <#{prev_url}>; rel=\"prev\"")
|
||||
else
|
||||
conn
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ def init(args) do
|
|||
{:ok, %{args | queue_table: queue_table, running_jobs: :sets.new()}}
|
||||
end
|
||||
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
enabled =
|
||||
if Pleroma.Config.get(:env) == :test,
|
||||
do: true,
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
|
||||
import Pleroma.Web.ControllerHelper,
|
||||
only: [json_response: 3, add_link_headers: 5, add_link_headers: 4, add_link_headers: 3]
|
||||
|
||||
alias Ecto.Changeset
|
||||
alias Pleroma.Activity
|
||||
|
@ -342,71 +343,6 @@ def custom_emojis(conn, _params) do
|
|||
json(conn, mastodon_emoji)
|
||||
end
|
||||
|
||||
defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
|
||||
params =
|
||||
conn.params
|
||||
|> Map.drop(["since_id", "max_id", "min_id"])
|
||||
|> Map.merge(params)
|
||||
|
||||
last = List.last(activities)
|
||||
|
||||
if last do
|
||||
max_id = last.id
|
||||
|
||||
limit =
|
||||
params
|
||||
|> Map.get("limit", "20")
|
||||
|> String.to_integer()
|
||||
|
||||
min_id =
|
||||
if length(activities) <= limit do
|
||||
activities
|
||||
|> List.first()
|
||||
|> Map.get(:id)
|
||||
else
|
||||
activities
|
||||
|> Enum.at(limit * -1)
|
||||
|> Map.get(:id)
|
||||
end
|
||||
|
||||
{next_url, prev_url} =
|
||||
if param do
|
||||
{
|
||||
mastodon_api_url(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
param,
|
||||
Map.merge(params, %{max_id: max_id})
|
||||
),
|
||||
mastodon_api_url(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
param,
|
||||
Map.merge(params, %{min_id: min_id})
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
mastodon_api_url(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
Map.merge(params, %{max_id: max_id})
|
||||
),
|
||||
mastodon_api_url(
|
||||
Pleroma.Web.Endpoint,
|
||||
method,
|
||||
Map.merge(params, %{min_id: min_id})
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
conn
|
||||
|> put_resp_header("link", "<#{next_url}>; rel=\"next\", <#{prev_url}>; rel=\"prev\"")
|
||||
else
|
||||
conn
|
||||
end
|
||||
end
|
||||
|
||||
def home_timeline(%{assigns: %{user: user}} = conn, params) do
|
||||
params =
|
||||
params
|
||||
|
@ -1797,7 +1733,7 @@ def conversations(%{assigns: %{user: user}} = conn, params) do
|
|||
|
||||
conversations =
|
||||
Enum.map(participations, fn participation ->
|
||||
ConversationView.render("participation.json", %{participation: participation, user: user})
|
||||
ConversationView.render("participation.json", %{participation: participation, for: user})
|
||||
end)
|
||||
|
||||
conn
|
||||
|
@ -1810,7 +1746,7 @@ def conversation_read(%{assigns: %{user: user}} = conn, %{"id" => participation_
|
|||
Repo.get_by(Participation, id: participation_id, user_id: user.id),
|
||||
{:ok, participation} <- Participation.mark_as_read(participation) do
|
||||
participation_view =
|
||||
ConversationView.render("participation.json", %{participation: participation, user: user})
|
||||
ConversationView.render("participation.json", %{participation: participation, for: user})
|
||||
|
||||
conn
|
||||
|> json(participation_view)
|
||||
|
|
|
@ -37,11 +37,11 @@ def render("relationship.json", %{user: nil, target: _target}) do
|
|||
end
|
||||
|
||||
def render("relationship.json", %{user: %User{} = user, target: %User{} = target}) do
|
||||
follow_activity = Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, target)
|
||||
follow_state = User.get_cached_follow_state(user, target)
|
||||
|
||||
requested =
|
||||
if follow_activity && !User.following?(target, user) do
|
||||
follow_activity.data["state"] == "pending"
|
||||
if follow_state && !User.following?(user, target) do
|
||||
follow_state == "pending"
|
||||
else
|
||||
false
|
||||
end
|
||||
|
|
|
@ -11,8 +11,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do
|
|||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
def render("participation.json", %{participation: participation, user: user}) do
|
||||
participation = Repo.preload(participation, conversation: :users)
|
||||
def render("participation.json", %{participation: participation, for: user}) do
|
||||
participation = Repo.preload(participation, conversation: [], recipients: [])
|
||||
|
||||
last_activity_id =
|
||||
with nil <- participation.last_activity_id do
|
||||
|
@ -28,7 +28,7 @@ def render("participation.json", %{participation: participation, user: user}) do
|
|||
|
||||
# Conversations return all users except the current user.
|
||||
users =
|
||||
participation.conversation.users
|
||||
participation.recipients
|
||||
|> Enum.reject(&(&1.id == user.id))
|
||||
|
||||
accounts =
|
||||
|
|
|
@ -8,6 +8,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
require Pleroma.Constants
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Conversation
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.HTML
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
@ -70,12 +72,14 @@ defp reblogged?(activity, user) do
|
|||
|
||||
def render("index.json", opts) do
|
||||
replied_to_activities = get_replied_to_activities(opts.activities)
|
||||
parallel = unless is_nil(opts[:parallel]), do: opts[:parallel], else: true
|
||||
|
||||
opts.activities
|
||||
|> safe_render_many(
|
||||
StatusView,
|
||||
"status.json",
|
||||
Map.put(opts, :replied_to_activities, replied_to_activities)
|
||||
Map.put(opts, :replied_to_activities, replied_to_activities),
|
||||
parallel
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -233,6 +237,19 @@ def render("status.json", %{activity: %{data: %{"object" => _object}} = activity
|
|||
object.data["url"] || object.data["external_url"] || object.data["id"]
|
||||
end
|
||||
|
||||
direct_conversation_id =
|
||||
with {_, 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
|
||||
else
|
||||
_e ->
|
||||
nil
|
||||
end
|
||||
|
||||
%{
|
||||
id: to_string(activity.id),
|
||||
uri: object.data["id"],
|
||||
|
@ -270,7 +287,8 @@ def render("status.json", %{activity: %{data: %{"object" => _object}} = activity
|
|||
conversation_id: get_context_id(activity),
|
||||
in_reply_to_account_acct: reply_to_user && reply_to_user.nickname,
|
||||
content: %{"text/plain" => content_plaintext},
|
||||
spoiler_text: %{"text/plain" => summary_plaintext}
|
||||
spoiler_text: %{"text/plain" => summary_plaintext},
|
||||
direct_conversation_id: direct_conversation_id
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -6,36 +6,30 @@ defmodule Pleroma.Web.OAuth.Token.CleanWorker do
|
|||
@moduledoc """
|
||||
The module represents functions to clean an expired oauth tokens.
|
||||
"""
|
||||
use GenServer
|
||||
|
||||
@ten_seconds 10_000
|
||||
@one_day 86_400_000
|
||||
|
||||
# 10 seconds
|
||||
@start_interval 10_000
|
||||
@interval Pleroma.Config.get(
|
||||
# 24 hours
|
||||
[:oauth2, :clean_expired_tokens_interval],
|
||||
86_400_000
|
||||
@one_day
|
||||
)
|
||||
@queue :background
|
||||
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
def start_link, do: GenServer.start_link(__MODULE__, nil)
|
||||
def start_link(_), do: GenServer.start_link(__MODULE__, %{})
|
||||
|
||||
def init(_) do
|
||||
if Pleroma.Config.get([:oauth2, :clean_expired_tokens], false) do
|
||||
Process.send_after(self(), :perform, @start_interval)
|
||||
{:ok, nil}
|
||||
else
|
||||
:ignore
|
||||
end
|
||||
Process.send_after(self(), :perform, @ten_seconds)
|
||||
{:ok, nil}
|
||||
end
|
||||
|
||||
@doc false
|
||||
def handle_info(:perform, state) do
|
||||
Token.delete_expired_tokens()
|
||||
|
||||
Process.send_after(self(), :perform, @interval)
|
||||
PleromaJobQueue.enqueue(@queue, __MODULE__, [:clean])
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
# Job Worker Callbacks
|
||||
def perform(:clean), do: Token.delete_expired_tokens()
|
||||
end
|
||||
|
|
73
lib/pleroma/web/pleroma_api/pleroma_api_controller.ex
Normal file
73
lib/pleroma/web/pleroma_api/pleroma_api_controller.ex
Normal file
|
@ -0,0 +1,73 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 7]
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.MastodonAPI.ConversationView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
|
||||
with %Participation{} = participation <- Participation.get(participation_id),
|
||||
true <- user.id == participation.user_id do
|
||||
conn
|
||||
|> put_view(ConversationView)
|
||||
|> render("participation.json", %{participation: participation, for: user})
|
||||
end
|
||||
end
|
||||
|
||||
def conversation_statuses(
|
||||
%{assigns: %{user: user}} = conn,
|
||||
%{"id" => participation_id} = params
|
||||
) do
|
||||
params =
|
||||
params
|
||||
|> Map.put("blocking_user", user)
|
||||
|> Map.put("muting_user", user)
|
||||
|> Map.put("user", user)
|
||||
|
||||
participation =
|
||||
participation_id
|
||||
|> Participation.get(preload: [:conversation])
|
||||
|
||||
if user.id == participation.user_id do
|
||||
activities =
|
||||
participation.conversation.ap_id
|
||||
|> ActivityPub.fetch_activities_for_context(params)
|
||||
|> Enum.reverse()
|
||||
|
||||
conn
|
||||
|> add_link_headers(
|
||||
:conversation_statuses,
|
||||
activities,
|
||||
participation_id,
|
||||
params,
|
||||
nil,
|
||||
&pleroma_api_url/4
|
||||
)
|
||||
|> put_view(StatusView)
|
||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||
end
|
||||
end
|
||||
|
||||
def update_conversation(
|
||||
%{assigns: %{user: user}} = conn,
|
||||
%{"id" => participation_id, "recipients" => recipients}
|
||||
) do
|
||||
participation =
|
||||
participation_id
|
||||
|> Participation.get()
|
||||
|
||||
with true <- user.id == participation.user_id,
|
||||
{:ok, participation} <- Participation.set_recipients(participation, recipients) do
|
||||
conn
|
||||
|> put_view(ConversationView)
|
||||
|> render("participation.json", %{participation: participation, for: user})
|
||||
end
|
||||
end
|
||||
end
|
|
@ -259,6 +259,21 @@ defmodule Pleroma.Web.Router do
|
|||
end
|
||||
end
|
||||
|
||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||
pipe_through(:authenticated_api)
|
||||
|
||||
scope [] do
|
||||
pipe_through(:oauth_read)
|
||||
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
|
||||
get("/conversations/:id", PleromaAPIController, :conversation)
|
||||
end
|
||||
|
||||
scope [] do
|
||||
pipe_through(:oauth_write)
|
||||
patch("/conversations/:id", PleromaAPIController, :update_conversation)
|
||||
end
|
||||
end
|
||||
|
||||
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
||||
pipe_through(:authenticated_api)
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Web.Streamer do
|
|||
|
||||
@keepalive_interval :timer.seconds(30)
|
||||
|
||||
def start_link do
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
|
||||
end
|
||||
|
||||
|
@ -35,28 +35,21 @@ def stream(topic, item) do
|
|||
end
|
||||
|
||||
def init(args) do
|
||||
spawn(fn ->
|
||||
# 30 seconds
|
||||
Process.sleep(@keepalive_interval)
|
||||
GenServer.cast(__MODULE__, %{action: :ping})
|
||||
end)
|
||||
Process.send_after(self(), %{action: :ping}, @keepalive_interval)
|
||||
|
||||
{:ok, args}
|
||||
end
|
||||
|
||||
def handle_cast(%{action: :ping}, topics) do
|
||||
Map.values(topics)
|
||||
def handle_info(%{action: :ping}, topics) do
|
||||
topics
|
||||
|> Map.values()
|
||||
|> List.flatten()
|
||||
|> Enum.each(fn socket ->
|
||||
Logger.debug("Sending keepalive ping")
|
||||
send(socket.transport_pid, {:text, ""})
|
||||
end)
|
||||
|
||||
spawn(fn ->
|
||||
# 30 seconds
|
||||
Process.sleep(@keepalive_interval)
|
||||
GenServer.cast(__MODULE__, %{action: :ping})
|
||||
end)
|
||||
Process.send_after(self(), %{action: :ping}, @keepalive_interval)
|
||||
|
||||
{:noreply, topics}
|
||||
end
|
||||
|
@ -120,8 +113,7 @@ def handle_cast(
|
|||
|> Map.get("#{topic}:#{item.user_id}", [])
|
||||
|> Enum.each(fn socket ->
|
||||
with %User{} = user <- User.get_cached_by_ap_id(socket.assigns[:user].ap_id),
|
||||
true <- should_send?(user, item),
|
||||
false <- CommonAPI.thread_muted?(user, item.activity) do
|
||||
true <- should_send?(user, item) do
|
||||
send(
|
||||
socket.transport_pid,
|
||||
{:text, represent_notification(socket.assigns[:user], item)}
|
||||
|
@ -209,7 +201,7 @@ def represent_conversation(%Participation{} = participation) do
|
|||
payload:
|
||||
Pleroma.Web.MastodonAPI.ConversationView.render("participation.json", %{
|
||||
participation: participation,
|
||||
user: participation.user
|
||||
for: participation.user
|
||||
})
|
||||
|> Jason.encode!()
|
||||
}
|
||||
|
@ -243,7 +235,8 @@ defp should_send?(%User{} = user, %Activity{} = item) do
|
|||
%{host: parent_host} <- URI.parse(parent.data["actor"]),
|
||||
false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, item_host),
|
||||
false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, parent_host),
|
||||
true <- thread_containment(item, user) do
|
||||
true <- thread_containment(item, user),
|
||||
false <- CommonAPI.thread_muted?(user, item) do
|
||||
true
|
||||
else
|
||||
_ -> false
|
||||
|
|
|
@ -66,9 +66,23 @@ def safe_render(view, template, assigns \\ %{}) do
|
|||
end
|
||||
|
||||
@doc """
|
||||
Same as `render_many/4` but wrapped in rescue block.
|
||||
Same as `render_many/4` but wrapped in rescue block and parallelized (unless disabled by passing false as a fifth argument).
|
||||
"""
|
||||
def safe_render_many(collection, view, template, assigns \\ %{}) do
|
||||
def safe_render_many(collection, view, template, assigns \\ %{}, parallel \\ true)
|
||||
|
||||
def safe_render_many(collection, view, template, assigns, true) do
|
||||
Enum.map(collection, fn resource ->
|
||||
Task.async(fn ->
|
||||
as = Map.get(assigns, :as) || view.__resource__
|
||||
assigns = Map.put(assigns, as, resource)
|
||||
safe_render(view, template, assigns)
|
||||
end)
|
||||
end)
|
||||
|> Enum.map(&Task.await(&1, :infinity))
|
||||
|> Enum.filter(& &1)
|
||||
end
|
||||
|
||||
def safe_render_many(collection, view, template, assigns, false) do
|
||||
Enum.map(collection, fn resource ->
|
||||
as = Map.get(assigns, :as) || view.__resource__
|
||||
assigns = Map.put(assigns, as, resource)
|
||||
|
|
|
@ -6,7 +6,7 @@ def change do
|
|||
add :user_id, references(:users, type: :uuid, on_delete: :delete_all)
|
||||
add :context, :string
|
||||
end
|
||||
|
||||
|
||||
create_if_not_exists unique_index(:thread_mutes, [:user_id, :context], name: :unique_index)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
defmodule Pleroma.Repo.Migrations.CreateConversationParticipationRecipientShips do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create_if_not_exists table(:conversation_participation_recipient_ships) do
|
||||
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
|
||||
add(:participation_id, references(:conversation_participations, on_delete: :delete_all))
|
||||
end
|
||||
|
||||
create_if_not_exists index(:conversation_participation_recipient_ships, [:user_id])
|
||||
create_if_not_exists index(:conversation_participation_recipient_ships, [:participation_id])
|
||||
end
|
||||
end
|
|
@ -5,14 +5,8 @@
|
|||
defmodule Pleroma.Config.TransferTaskTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
setup do
|
||||
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
|
||||
|
||||
clear_config([:instance, :dynamic_configuration]) do
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
|
||||
end)
|
||||
end
|
||||
|
||||
test "transfer config values from db to env" do
|
||||
|
@ -31,7 +25,7 @@ test "transfer config values from db to env" do
|
|||
value: [live: 15, com: 35]
|
||||
})
|
||||
|
||||
Pleroma.Config.TransferTask.start_link()
|
||||
Pleroma.Config.TransferTask.start_link([])
|
||||
|
||||
assert Application.get_env(:pleroma, :test_key) == [live: 2, com: 3]
|
||||
assert Application.get_env(:idna, :test_key) == [live: 15, com: 35]
|
||||
|
@ -50,7 +44,7 @@ test "non existing atom" do
|
|||
})
|
||||
|
||||
assert ExUnit.CaptureLog.capture_log(fn ->
|
||||
Pleroma.Config.TransferTask.start_link()
|
||||
Pleroma.Config.TransferTask.start_link([])
|
||||
end) =~
|
||||
"updating env causes error, key: \"undefined_atom_key\", error: %ArgumentError{message: \"argument error\"}"
|
||||
end
|
||||
|
|
|
@ -8,6 +8,50 @@ defmodule Pleroma.Conversation.ParticipationTest do
|
|||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "getting a participation will also preload things" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
participation = Participation.get(participation.id, preload: [:conversation])
|
||||
|
||||
assert %Pleroma.Conversation{} = participation.conversation
|
||||
end
|
||||
|
||||
test "for a new conversation, it sets the recipents of the participation" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
participation = Pleroma.Repo.preload(participation, :recipients)
|
||||
|
||||
assert length(participation.recipients) == 2
|
||||
assert user in participation.recipients
|
||||
assert other_user in participation.recipients
|
||||
|
||||
# Mentioning another user in the same conversation will not add a new recipients.
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"in_reply_to_status_id" => activity.id,
|
||||
"status" => "Hey @#{third_user.nickname}.",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
participation = Pleroma.Repo.preload(participation, :recipients)
|
||||
|
||||
assert length(participation.recipients) == 2
|
||||
end
|
||||
|
||||
test "it creates a participation for a conversation and a user" do
|
||||
user = insert(:user)
|
||||
conversation = insert(:conversation)
|
||||
|
@ -102,4 +146,23 @@ test "Doesn't die when the conversation gets empty" do
|
|||
|
||||
[] = Participation.for_user_with_last_activity_id(user)
|
||||
end
|
||||
|
||||
test "it sets recipients, always keeping the owner of the participation even when not explicitly set" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
[participation] = Participation.for_user_with_last_activity_id(user)
|
||||
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
||||
assert participation.recipients |> length() == 1
|
||||
assert user in participation.recipients
|
||||
|
||||
{:ok, participation} = Participation.set_recipients(participation, [other_user.id])
|
||||
|
||||
assert participation.recipients |> length() == 2
|
||||
assert user in participation.recipients
|
||||
assert other_user in participation.recipients
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,14 +11,8 @@ defmodule Pleroma.ConversationTest do
|
|||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
clear_config_all([:instance, :federating]) do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
end
|
||||
|
||||
test "it goes through old direct conversations" do
|
||||
|
|
|
@ -15,11 +15,7 @@ defmodule Pleroma.Emails.MailerTest do
|
|||
to: [{"Test User", "user1@example.com"}]
|
||||
}
|
||||
|
||||
setup do
|
||||
value = Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled])
|
||||
on_exit(fn -> Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], value) end)
|
||||
:ok
|
||||
end
|
||||
clear_config([Pleroma.Emails.Mailer, :enabled])
|
||||
|
||||
test "not send email when mailer is disabled" do
|
||||
Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], false)
|
||||
|
|
|
@ -4,21 +4,19 @@
|
|||
|
||||
defmodule Pleroma.HTTP.RequestBuilderTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Pleroma.Tests.Helpers
|
||||
alias Pleroma.HTTP.RequestBuilder
|
||||
|
||||
describe "headers/2" do
|
||||
clear_config([:http, :send_user_agent])
|
||||
|
||||
test "don't send pleroma user agent" do
|
||||
assert RequestBuilder.headers(%{}, []) == %{headers: []}
|
||||
end
|
||||
|
||||
test "send pleroma user agent" do
|
||||
send = Pleroma.Config.get([:http, :send_user_agent])
|
||||
Pleroma.Config.put([:http, :send_user_agent], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:http, :send_user_agent], send)
|
||||
end)
|
||||
|
||||
assert RequestBuilder.headers(%{}, []) == %{
|
||||
headers: [{"User-Agent", Pleroma.Application.user_agent()}]
|
||||
}
|
||||
|
|
|
@ -159,32 +159,28 @@ test "it can refetch pruned objects" do
|
|||
end
|
||||
|
||||
describe "signed fetches" do
|
||||
clear_config([:activitypub, :sign_object_fetches])
|
||||
|
||||
test_with_mock "it signs fetches when configured to do so",
|
||||
Pleroma.Signature,
|
||||
[:passthrough],
|
||||
[] do
|
||||
option = Pleroma.Config.get([:activitypub, :sign_object_fetches])
|
||||
Pleroma.Config.put([:activitypub, :sign_object_fetches], true)
|
||||
|
||||
Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert called(Pleroma.Signature.sign(:_, :_))
|
||||
|
||||
Pleroma.Config.put([:activitypub, :sign_object_fetches], option)
|
||||
end
|
||||
|
||||
test_with_mock "it doesn't sign fetches when not configured to do so",
|
||||
Pleroma.Signature,
|
||||
[:passthrough],
|
||||
[] do
|
||||
option = Pleroma.Config.get([:activitypub, :sign_object_fetches])
|
||||
Pleroma.Config.put([:activitypub, :sign_object_fetches], false)
|
||||
|
||||
Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
refute called(Pleroma.Signature.sign(:_, :_))
|
||||
|
||||
Pleroma.Config.put([:activitypub, :sign_object_fetches], option)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,8 +9,10 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do
|
|||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||
alias Pleroma.User
|
||||
|
||||
clear_config([:instance, :public])
|
||||
|
||||
test "it halts if not public and no user is assigned", %{conn: conn} do
|
||||
set_public_to(false)
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|
@ -21,7 +23,7 @@ test "it halts if not public and no user is assigned", %{conn: conn} do
|
|||
end
|
||||
|
||||
test "it continues if public", %{conn: conn} do
|
||||
set_public_to(true)
|
||||
Config.put([:instance, :public], true)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|
@ -31,7 +33,7 @@ test "it continues if public", %{conn: conn} do
|
|||
end
|
||||
|
||||
test "it continues if a user is assigned, even if not public", %{conn: conn} do
|
||||
set_public_to(false)
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|
@ -43,13 +45,4 @@ test "it continues if a user is assigned, even if not public", %{conn: conn} do
|
|||
|
||||
assert ret_conn == conn
|
||||
end
|
||||
|
||||
defp set_public_to(value) do
|
||||
orig = Config.get!([:instance, :public])
|
||||
Config.put([:instance, :public], value)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([:instance, :public], orig)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,17 +7,12 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do
|
|||
alias Pleroma.Config
|
||||
alias Plug.Conn
|
||||
|
||||
clear_config([:http_securiy, :enabled])
|
||||
clear_config([:http_security, :sts])
|
||||
|
||||
describe "http security enabled" do
|
||||
setup do
|
||||
enabled = Config.get([:http_securiy, :enabled])
|
||||
|
||||
Config.put([:http_security, :enabled], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([:http_security, :enabled], enabled)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it sends CSP headers when enabled", %{conn: conn} do
|
||||
|
@ -81,14 +76,8 @@ test "it sends `report-to` & `report-uri` CSP response headers" do
|
|||
end
|
||||
|
||||
test "it does not send CSP headers when disabled", %{conn: conn} do
|
||||
enabled = Config.get([:http_securiy, :enabled])
|
||||
|
||||
Config.put([:http_security, :enabled], false)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([:http_security, :enabled], enabled)
|
||||
end)
|
||||
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
assert Conn.get_resp_header(conn, "x-xss-protection") == []
|
||||
|
|
|
@ -8,14 +8,12 @@ defmodule Pleroma.Web.RuntimeStaticPlugTest do
|
|||
@dir "test/tmp/instance_static"
|
||||
|
||||
setup do
|
||||
static_dir = Pleroma.Config.get([:instance, :static_dir])
|
||||
Pleroma.Config.put([:instance, :static_dir], @dir)
|
||||
File.mkdir_p!(@dir)
|
||||
on_exit(fn -> File.rm_rf(@dir) end)
|
||||
end
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :static_dir], static_dir)
|
||||
File.rm_rf(@dir)
|
||||
end)
|
||||
clear_config([:instance, :static_dir]) do
|
||||
Pleroma.Config.put([:instance, :static_dir], @dir)
|
||||
end
|
||||
|
||||
test "overrides index" do
|
||||
|
|
|
@ -7,8 +7,52 @@ defmodule Pleroma.Tests.Helpers do
|
|||
Helpers for use in tests.
|
||||
"""
|
||||
|
||||
defmacro clear_config(config_path) do
|
||||
quote do
|
||||
clear_config(unquote(config_path)) do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmacro clear_config(config_path, do: yield) do
|
||||
quote do
|
||||
setup do
|
||||
initial_setting = Pleroma.Config.get(unquote(config_path))
|
||||
unquote(yield)
|
||||
on_exit(fn -> Pleroma.Config.put(unquote(config_path), initial_setting) end)
|
||||
:ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmacro clear_config_all(config_path) do
|
||||
quote do
|
||||
clear_config_all(unquote(config_path)) do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmacro clear_config_all(config_path, do: yield) do
|
||||
quote do
|
||||
setup_all do
|
||||
initial_setting = Pleroma.Config.get(unquote(config_path))
|
||||
unquote(yield)
|
||||
on_exit(fn -> Pleroma.Config.put(unquote(config_path), initial_setting) end)
|
||||
:ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmacro __using__(_opts) do
|
||||
quote do
|
||||
import Pleroma.Tests.Helpers,
|
||||
only: [
|
||||
clear_config: 1,
|
||||
clear_config: 2,
|
||||
clear_config_all: 1,
|
||||
clear_config_all: 2
|
||||
]
|
||||
|
||||
def collect_ids(collection) do
|
||||
collection
|
||||
|> Enum.map(& &1.id)
|
||||
|
@ -30,6 +74,15 @@ def render_json(view, template, assigns) do
|
|||
|> Poison.encode!()
|
||||
|> Poison.decode!()
|
||||
end
|
||||
|
||||
defmacro guards_config(config_path) do
|
||||
quote do
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,21 +11,20 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
|
|||
Mix.shell(Mix.Shell.Process)
|
||||
temp_file = "config/temp.exported_from_db.secret.exs"
|
||||
|
||||
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
|
||||
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Mix.shell(Mix.Shell.IO)
|
||||
Application.delete_env(:pleroma, :first_setting)
|
||||
Application.delete_env(:pleroma, :second_setting)
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
|
||||
:ok = File.rm(temp_file)
|
||||
end)
|
||||
|
||||
{:ok, temp_file: temp_file}
|
||||
end
|
||||
|
||||
clear_config_all([:instance, :dynamic_configuration]) do
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
end
|
||||
|
||||
test "settings are migrated to db" do
|
||||
assert Repo.all(Config) == []
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
@ -22,6 +23,52 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
describe "running remove_embedded_objects" do
|
||||
test "it replaces objects with references" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
|
||||
new_data = Map.put(activity.data, "object", activity.object.data)
|
||||
|
||||
{:ok, activity} =
|
||||
activity
|
||||
|> Activity.change(%{data: new_data})
|
||||
|> Repo.update()
|
||||
|
||||
assert is_map(activity.data["object"])
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["remove_embedded_objects"])
|
||||
|
||||
activity = Activity.get_by_id_with_object(activity.id)
|
||||
assert is_binary(activity.data["object"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "prune_objects" do
|
||||
test "it prunes old objects from the database" do
|
||||
insert(:note)
|
||||
deadline = Pleroma.Config.get([:instance, :remote_post_retention_days]) + 1
|
||||
|
||||
date =
|
||||
Timex.now()
|
||||
|> Timex.shift(days: -deadline)
|
||||
|> Timex.to_naive_datetime()
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
%{id: id} =
|
||||
:note
|
||||
|> insert()
|
||||
|> Ecto.Changeset.change(%{inserted_at: date})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects"])
|
||||
|
||||
assert length(Repo.all(Object)) == 1
|
||||
refute Object.get_by_id(id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "running update_users_following_followers_counts" do
|
||||
test "following and followers count are updated" do
|
||||
[user, user2] = insert_pair(:user)
|
||||
|
|
|
@ -69,4 +69,27 @@ test "relay is unfollowed" do
|
|||
assert undo_activity.data["object"] == cancelled_activity.data
|
||||
end
|
||||
end
|
||||
|
||||
describe "mix pleroma.relay list" do
|
||||
test "Prints relay subscription list" do
|
||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||
|
||||
refute_receive {:mix_shell, :info, _}
|
||||
|
||||
Pleroma.Web.ActivityPub.Relay.get_actor()
|
||||
|> Ecto.Changeset.change(
|
||||
following: [
|
||||
"http://test-app.com/user/test1",
|
||||
"http://test-app.com/user/test1",
|
||||
"http://test-app-42.com/user/test1"
|
||||
]
|
||||
)
|
||||
|> Pleroma.User.update_and_set_cache()
|
||||
|
||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||
|
||||
assert_receive {:mix_shell, :info, ["test-app.com"]}
|
||||
assert_receive {:mix_shell, :info, ["test-app-42.com"]}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
|
||||
defmodule Mix.Tasks.Pleroma.RobotsTxtTest do
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
alias Mix.Tasks.Pleroma.RobotsTxt
|
||||
|
||||
clear_config([:instance, :static_dir])
|
||||
|
||||
test "creates new dir" do
|
||||
path = "test/fixtures/new_dir/"
|
||||
file_path = path <> "robots.txt"
|
||||
|
||||
static_dir = Pleroma.Config.get([:instance, :static_dir])
|
||||
Pleroma.Config.put([:instance, :static_dir], path)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :static_dir], static_dir)
|
||||
{:ok, ["test/fixtures/new_dir/", "test/fixtures/new_dir/robots.txt"]} = File.rm_rf(path)
|
||||
end)
|
||||
|
||||
|
@ -29,11 +29,9 @@ test "creates new dir" do
|
|||
test "to existance folder" do
|
||||
path = "test/fixtures/"
|
||||
file_path = path <> "robots.txt"
|
||||
static_dir = Pleroma.Config.get([:instance, :static_dir])
|
||||
Pleroma.Config.put([:instance, :static_dir], path)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :static_dir], static_dir)
|
||||
:ok = File.rm(file_path)
|
||||
end)
|
||||
|
||||
|
|
|
@ -9,12 +9,6 @@ defmodule Pleroma.Upload.Filter.AnonymizeFilenameTest do
|
|||
alias Pleroma.Upload
|
||||
|
||||
setup do
|
||||
custom_filename = Config.get([Upload.Filter.AnonymizeFilename, :text])
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([Upload.Filter.AnonymizeFilename, :text], custom_filename)
|
||||
end)
|
||||
|
||||
upload_file = %Upload{
|
||||
name: "an… image.jpg",
|
||||
content_type: "image/jpg",
|
||||
|
@ -24,6 +18,8 @@ defmodule Pleroma.Upload.Filter.AnonymizeFilenameTest do
|
|||
%{upload_file: upload_file}
|
||||
end
|
||||
|
||||
clear_config([Pleroma.Upload.Filter.AnonymizeFilename, :text])
|
||||
|
||||
test "it replaces filename on pre-defined text", %{upload_file: upload_file} do
|
||||
Config.put([Upload.Filter.AnonymizeFilename, :text], "custom-file.png")
|
||||
{:ok, %Upload{name: name}} = Upload.Filter.AnonymizeFilename.filter(upload_file)
|
||||
|
|
|
@ -10,13 +10,7 @@ defmodule Pleroma.Upload.Filter.MogrifyTest do
|
|||
alias Pleroma.Upload
|
||||
alias Pleroma.Upload.Filter
|
||||
|
||||
setup do
|
||||
filter = Config.get([Filter.Mogrify, :args])
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([Filter.Mogrify, :args], filter)
|
||||
end)
|
||||
end
|
||||
clear_config([Filter.Mogrify, :args])
|
||||
|
||||
test "apply mogrify filter" do
|
||||
Config.put([Filter.Mogrify, :args], [{"tint", "40"}])
|
||||
|
|
|
@ -8,13 +8,7 @@ defmodule Pleroma.Upload.FilterTest do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.Upload.Filter
|
||||
|
||||
setup do
|
||||
custom_filename = Config.get([Pleroma.Upload.Filter.AnonymizeFilename, :text])
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([Pleroma.Upload.Filter.AnonymizeFilename, :text], custom_filename)
|
||||
end)
|
||||
end
|
||||
clear_config([Pleroma.Upload.Filter.AnonymizeFilename, :text])
|
||||
|
||||
test "applies filters" do
|
||||
Config.put([Pleroma.Upload.Filter.AnonymizeFilename, :text], "custom-file.png")
|
||||
|
|
|
@ -250,12 +250,8 @@ test "escapes reserved uri characters" do
|
|||
end
|
||||
|
||||
describe "Setting a custom base_url for uploaded media" do
|
||||
setup do
|
||||
clear_config([Pleroma.Upload, :base_url]) do
|
||||
Pleroma.Config.put([Pleroma.Upload, :base_url], "https://cache.pleroma.social")
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([Pleroma.Upload, :base_url], nil)
|
||||
end)
|
||||
end
|
||||
|
||||
test "returns a media url with configured base_url" do
|
||||
|
|
|
@ -11,19 +11,11 @@ defmodule Pleroma.Uploaders.S3Test do
|
|||
import Mock
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
setup do
|
||||
config = Config.get([Pleroma.Uploaders.S3])
|
||||
|
||||
clear_config([Pleroma.Uploaders.S3]) do
|
||||
Config.put([Pleroma.Uploaders.S3],
|
||||
bucket: "test_bucket",
|
||||
public_endpoint: "https://s3.amazonaws.com"
|
||||
)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([Pleroma.Uploaders.S3], config)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "get_file/1" do
|
||||
|
|
|
@ -21,6 +21,8 @@ defmodule Pleroma.UserTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
clear_config([:instance, :account_activation_required])
|
||||
|
||||
describe "when tags are nil" do
|
||||
test "tagging a user" do
|
||||
user = insert(:user, %{tags: nil})
|
||||
|
@ -90,6 +92,17 @@ test "doesn't return already accepted or duplicate follow requests" do
|
|||
assert activity
|
||||
end
|
||||
|
||||
test "clears follow requests when requester is blocked" do
|
||||
followed = insert(:user, %{info: %{locked: true}})
|
||||
follower = insert(:user)
|
||||
|
||||
CommonAPI.follow(follower, followed)
|
||||
assert {:ok, [_activity]} = User.get_follow_requests(followed)
|
||||
|
||||
{:ok, _follower} = User.block(followed, follower)
|
||||
assert {:ok, []} = User.get_follow_requests(followed)
|
||||
end
|
||||
|
||||
test "follow_all follows mutliple users" do
|
||||
user = insert(:user)
|
||||
followed_zero = insert(:user)
|
||||
|
@ -192,24 +205,64 @@ test "local users do not automatically follow local locked accounts" do
|
|||
# assert websub
|
||||
# end
|
||||
|
||||
test "unfollow takes a user and another user" do
|
||||
followed = insert(:user)
|
||||
user = insert(:user, %{following: [User.ap_followers(followed)]})
|
||||
describe "unfollow/2" do
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :external_user_synchronization])
|
||||
|
||||
{:ok, user, _activity} = User.unfollow(user, followed)
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :external_user_synchronization], setting)
|
||||
end)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
:ok
|
||||
end
|
||||
|
||||
assert user.following == []
|
||||
end
|
||||
test "unfollow with syncronizes external user" do
|
||||
Pleroma.Config.put([:instance, :external_user_synchronization], true)
|
||||
|
||||
test "unfollow doesn't unfollow yourself" do
|
||||
user = insert(:user)
|
||||
followed =
|
||||
insert(:user,
|
||||
nickname: "fuser1",
|
||||
follower_address: "http://localhost:4001/users/fuser1/followers",
|
||||
following_address: "http://localhost:4001/users/fuser1/following",
|
||||
ap_id: "http://localhost:4001/users/fuser1"
|
||||
)
|
||||
|
||||
{:error, _} = User.unfollow(user, user)
|
||||
user =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "fuser2",
|
||||
ap_id: "http://localhost:4001/users/fuser2",
|
||||
follower_address: "http://localhost:4001/users/fuser2/followers",
|
||||
following_address: "http://localhost:4001/users/fuser2/following",
|
||||
following: [User.ap_followers(followed)]
|
||||
})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.following == [user.ap_id]
|
||||
{:ok, user, _activity} = User.unfollow(user, followed)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert user.following == []
|
||||
end
|
||||
|
||||
test "unfollow takes a user and another user" do
|
||||
followed = insert(:user)
|
||||
user = insert(:user, %{following: [User.ap_followers(followed)]})
|
||||
|
||||
{:ok, user, _activity} = User.unfollow(user, followed)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
assert user.following == []
|
||||
end
|
||||
|
||||
test "unfollow doesn't unfollow yourself" do
|
||||
user = insert(:user)
|
||||
|
||||
{:error, _} = User.unfollow(user, user)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.following == [user.ap_id]
|
||||
end
|
||||
end
|
||||
|
||||
test "test if a user is following another user" do
|
||||
|
@ -236,6 +289,9 @@ test "fetches correct profile for nickname beginning with number" do
|
|||
password_confirmation: "test",
|
||||
email: "email@example.com"
|
||||
}
|
||||
clear_config([:instance, :autofollowed_nicknames])
|
||||
clear_config([:instance, :welcome_message])
|
||||
clear_config([:instance, :welcome_user_nickname])
|
||||
|
||||
test "it autofollows accounts that are set for it" do
|
||||
user = insert(:user)
|
||||
|
@ -252,8 +308,6 @@ test "it autofollows accounts that are set for it" do
|
|||
|
||||
assert User.following?(registered_user, user)
|
||||
refute User.following?(registered_user, remote_user)
|
||||
|
||||
Pleroma.Config.put([:instance, :autofollowed_nicknames], [])
|
||||
end
|
||||
|
||||
test "it sends a welcome message if it is set" do
|
||||
|
@ -269,9 +323,6 @@ test "it sends a welcome message if it is set" do
|
|||
assert registered_user.ap_id in activity.recipients
|
||||
assert Object.normalize(activity).data["content"] =~ "cool site"
|
||||
assert activity.actor == welcome_user.ap_id
|
||||
|
||||
Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
|
||||
Pleroma.Config.put([:instance, :welcome_message], nil)
|
||||
end
|
||||
|
||||
test "it requires an email, name, nickname and password, bio is optional" do
|
||||
|
@ -337,15 +388,8 @@ test "it ensures info is not nil" do
|
|||
email: "email@example.com"
|
||||
}
|
||||
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :account_activation_required])
|
||||
|
||||
unless setting do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
|
||||
end
|
||||
|
||||
:ok
|
||||
clear_config([:instance, :account_activation_required]) do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
end
|
||||
|
||||
test "it creates unconfirmed user" do
|
||||
|
@ -992,6 +1036,8 @@ test "hide a user's statuses from timelines and notifications" do
|
|||
[user: user]
|
||||
end
|
||||
|
||||
clear_config([:instance, :federating])
|
||||
|
||||
test ".delete_user_activities deletes all create activities", %{user: user} do
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
|
||||
|
||||
|
@ -1042,9 +1088,7 @@ test "it deletes a user, all follow relationships and all activities", %{user: u
|
|||
Pleroma.Web.ActivityPub.Publisher,
|
||||
[:passthrough],
|
||||
[] do
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
Pleroma.Config.put(config_path, true)
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
|
||||
{:ok, follower} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
{:ok, _} = User.follow(follower, user)
|
||||
|
@ -1056,8 +1100,6 @@ test "it deletes a user, all follow relationships and all activities", %{user: u
|
|||
inbox: "http://mastodon.example.org/inbox"
|
||||
})
|
||||
)
|
||||
|
||||
Pleroma.Config.put(config_path, initial_setting)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1123,8 +1165,6 @@ test "auth_active?/1 works correctly" do
|
|||
refute User.auth_active?(local_user)
|
||||
assert User.auth_active?(confirmed_user)
|
||||
assert User.auth_active?(remote_user)
|
||||
|
||||
Pleroma.Config.put([:instance, :account_activation_required], false)
|
||||
end
|
||||
|
||||
describe "superuser?/1" do
|
||||
|
@ -1169,8 +1209,6 @@ test "returns false when the account is unauthenticated and auth is required" do
|
|||
other_user = insert(:user, local: true)
|
||||
|
||||
refute User.visible_for?(user, other_user)
|
||||
|
||||
Pleroma.Config.put([:instance, :account_activation_required], false)
|
||||
end
|
||||
|
||||
test "returns true when the account is unauthenticated and auth is not required" do
|
||||
|
@ -1187,8 +1225,6 @@ test "returns true when the account is unauthenticated and being viewed by a pri
|
|||
other_user = insert(:user, local: true, info: %{is_admin: true})
|
||||
|
||||
assert User.visible_for?(user, other_user)
|
||||
|
||||
Pleroma.Config.put([:instance, :account_activation_required], false)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1501,10 +1537,7 @@ test "performs update cache if user updated" do
|
|||
end
|
||||
|
||||
describe "following/followers synchronization" do
|
||||
setup do
|
||||
sync = Pleroma.Config.get([:instance, :external_user_synchronization])
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :external_user_synchronization], sync) end)
|
||||
end
|
||||
clear_config([:instance, :external_user_synchronization])
|
||||
|
||||
test "updates the counters normally on following/getting a follow when disabled" do
|
||||
Pleroma.Config.put([:instance, :external_user_synchronization], false)
|
||||
|
|
|
@ -16,17 +16,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
clear_config_all([:instance, :federating],
|
||||
do: Pleroma.Config.put([:instance, :federating], true)
|
||||
)
|
||||
|
||||
describe "/relay" do
|
||||
clear_config([:instance, :allow_relay])
|
||||
|
||||
test "with the relay active, it returns the relay user", %{conn: conn} do
|
||||
res =
|
||||
conn
|
||||
|
@ -43,8 +42,6 @@ test "with the relay disabled, it returns 404", %{conn: conn} do
|
|||
|> get(activity_pub_path(conn, :relay))
|
||||
|> json_response(404)
|
||||
|> assert
|
||||
|
||||
Pleroma.Config.put([:instance, :allow_relay], true)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -538,6 +538,29 @@ test "doesn't return muted activities" do
|
|||
assert Enum.member?(activities, activity_one)
|
||||
end
|
||||
|
||||
test "doesn't return thread muted activities" do
|
||||
user = insert(:user)
|
||||
_activity_one = insert(:note_activity)
|
||||
note_two = insert(:note, data: %{"context" => "suya.."})
|
||||
activity_two = insert(:note_activity, note: note_two)
|
||||
|
||||
{:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
|
||||
|
||||
assert [_activity_one] = ActivityPub.fetch_activities([], %{"muting_user" => user})
|
||||
end
|
||||
|
||||
test "returns thread muted activities when with_muted is set" do
|
||||
user = insert(:user)
|
||||
_activity_one = insert(:note_activity)
|
||||
note_two = insert(:note, data: %{"context" => "suya.."})
|
||||
activity_two = insert(:note_activity, note: note_two)
|
||||
|
||||
{:ok, activity_two} = CommonAPI.add_mute(user, activity_two)
|
||||
|
||||
assert [_activity_two, _activity_one] =
|
||||
ActivityPub.fetch_activities([], %{"muting_user" => user, "with_muted" => true})
|
||||
end
|
||||
|
||||
test "does include announces on request" do
|
||||
activity_three = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Pleroma.Web.ActivityPub.MRFTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Pleroma.Tests.Helpers
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
test "subdomains_regex/1" do
|
||||
|
@ -59,6 +60,8 @@ test "matches are case-insensitive" do
|
|||
end
|
||||
|
||||
describe "describe/0" do
|
||||
clear_config([:instance, :rewrite_policy])
|
||||
|
||||
test "it works as expected with noop policy" do
|
||||
expected = %{
|
||||
mrf_policies: ["NoOpPolicy"],
|
||||
|
@ -69,7 +72,6 @@ test "it works as expected with noop policy" do
|
|||
end
|
||||
|
||||
test "it works as expected with mock policy" do
|
||||
config = Pleroma.Config.get([:instance, :rewrite_policy])
|
||||
Pleroma.Config.put([:instance, :rewrite_policy], [MRFModuleMock])
|
||||
|
||||
expected = %{
|
||||
|
@ -79,8 +81,6 @@ test "it works as expected with mock policy" do
|
|||
}
|
||||
|
||||
{:ok, ^expected} = MRF.describe()
|
||||
|
||||
Pleroma.Config.put([:instance, :rewrite_policy], config)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,12 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
|
|||
|
||||
alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic
|
||||
|
||||
setup do
|
||||
policy = Pleroma.Config.get([:mrf_rejectnonpublic])
|
||||
on_exit(fn -> Pleroma.Config.put([:mrf_rejectnonpublic], policy) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
clear_config([:mrf_rejectnonpublic])
|
||||
|
||||
describe "public message" do
|
||||
test "it's allowed when address is public" do
|
||||
|
|
|
@ -8,9 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
||||
|
||||
setup do
|
||||
orig = Config.get!(:mrf_simple)
|
||||
|
||||
clear_config([:mrf_simple]) do
|
||||
Config.put(:mrf_simple,
|
||||
media_removal: [],
|
||||
media_nsfw: [],
|
||||
|
@ -21,10 +19,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
avatar_removal: [],
|
||||
banner_removal: []
|
||||
)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put(:mrf_simple, orig)
|
||||
end)
|
||||
end
|
||||
|
||||
describe "when :media_removal" do
|
||||
|
|
|
@ -7,12 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
|
|||
|
||||
alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
|
||||
|
||||
setup do
|
||||
policy = Pleroma.Config.get([:mrf_user_allowlist]) || []
|
||||
on_exit(fn -> Pleroma.Config.put([:mrf_user_allowlist], policy) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
clear_config([:mrf_user_allowlist, :localhost])
|
||||
|
||||
test "pass filter if allow list is empty" do
|
||||
actor = insert(:user)
|
||||
|
|
|
@ -8,8 +8,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do
|
|||
alias Pleroma.Web.ActivityPub.MRF.VocabularyPolicy
|
||||
|
||||
describe "accept" do
|
||||
clear_config([:mrf_vocabulary, :accept])
|
||||
|
||||
test "it accepts based on parent activity type" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :accept])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Like"])
|
||||
|
||||
message = %{
|
||||
|
@ -18,12 +19,9 @@ test "it accepts based on parent activity type" do
|
|||
}
|
||||
|
||||
{:ok, ^message} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], config)
|
||||
end
|
||||
|
||||
test "it accepts based on child object type" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :accept])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Create", "Note"])
|
||||
|
||||
message = %{
|
||||
|
@ -35,12 +33,9 @@ test "it accepts based on child object type" do
|
|||
}
|
||||
|
||||
{:ok, ^message} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], config)
|
||||
end
|
||||
|
||||
test "it does not accept disallowed child objects" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :accept])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Create", "Note"])
|
||||
|
||||
message = %{
|
||||
|
@ -52,12 +47,9 @@ test "it does not accept disallowed child objects" do
|
|||
}
|
||||
|
||||
{:reject, nil} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], config)
|
||||
end
|
||||
|
||||
test "it does not accept disallowed parent types" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :accept])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Announce", "Note"])
|
||||
|
||||
message = %{
|
||||
|
@ -69,14 +61,13 @@ test "it does not accept disallowed parent types" do
|
|||
}
|
||||
|
||||
{:reject, nil} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], config)
|
||||
end
|
||||
end
|
||||
|
||||
describe "reject" do
|
||||
clear_config([:mrf_vocabulary, :reject])
|
||||
|
||||
test "it rejects based on parent activity type" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :reject])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"])
|
||||
|
||||
message = %{
|
||||
|
@ -85,12 +76,9 @@ test "it rejects based on parent activity type" do
|
|||
}
|
||||
|
||||
{:reject, nil} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], config)
|
||||
end
|
||||
|
||||
test "it rejects based on child object type" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :reject])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], ["Note"])
|
||||
|
||||
message = %{
|
||||
|
@ -102,12 +90,9 @@ test "it rejects based on child object type" do
|
|||
}
|
||||
|
||||
{:reject, nil} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], config)
|
||||
end
|
||||
|
||||
test "it passes through objects that aren't disallowed" do
|
||||
config = Pleroma.Config.get([:mrf_vocabulary, :reject])
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"])
|
||||
|
||||
message = %{
|
||||
|
@ -116,8 +101,6 @@ test "it passes through objects that aren't disallowed" do
|
|||
}
|
||||
|
||||
{:ok, ^message} = VocabularyPolicy.filter(message)
|
||||
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], config)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -294,20 +294,17 @@ test "returns 403 when requested by a non-admin", %{conn: conn} do
|
|||
|
||||
describe "POST /api/pleroma/admin/email_invite, with valid config" do
|
||||
setup do
|
||||
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
|
||||
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
Pleroma.Config.put([:instance, :invites_enabled], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
|
||||
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
|
||||
:ok
|
||||
end)
|
||||
|
||||
[user: insert(:user, info: %{is_admin: true})]
|
||||
end
|
||||
|
||||
clear_config([:instance, :registrations_open]) do
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
end
|
||||
|
||||
clear_config([:instance, :invites_enabled]) do
|
||||
Pleroma.Config.put([:instance, :invites_enabled], true)
|
||||
end
|
||||
|
||||
test "sends invitation and returns 204", %{conn: conn, user: user} do
|
||||
recipient_email = "foo@bar.com"
|
||||
recipient_name = "J. D."
|
||||
|
@ -360,18 +357,13 @@ test "it returns 403 if requested by a non-admin", %{conn: conn} do
|
|||
[user: insert(:user, info: %{is_admin: true})]
|
||||
end
|
||||
|
||||
clear_config([:instance, :registrations_open])
|
||||
clear_config([:instance, :invites_enabled])
|
||||
|
||||
test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
|
||||
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
|
||||
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
|
||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
||||
Pleroma.Config.put([:instance, :invites_enabled], false)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
|
||||
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
|
||||
:ok
|
||||
end)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
@ -381,17 +373,9 @@ test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: u
|
|||
end
|
||||
|
||||
test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
|
||||
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
|
||||
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
|
||||
Pleroma.Config.put([:instance, :registrations_open], true)
|
||||
Pleroma.Config.put([:instance, :invites_enabled], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
|
||||
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
|
||||
:ok
|
||||
end)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
@ -1402,17 +1386,13 @@ test "with settings in db", %{conn: conn} do
|
|||
:ok = File.rm(temp_file)
|
||||
end)
|
||||
|
||||
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
|
||||
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
|
||||
end)
|
||||
|
||||
%{conn: assign(conn, :user, admin)}
|
||||
end
|
||||
|
||||
clear_config([:instance, :dynamic_configuration]) do
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
end
|
||||
|
||||
test "create new config setting in db", %{conn: conn} do
|
||||
conn =
|
||||
post(conn, "/api/pleroma/admin/config", %{
|
||||
|
@ -1961,17 +1941,13 @@ test "delete part of settings by atom subkeys", %{conn: conn} do
|
|||
:ok = File.rm(temp_file)
|
||||
end)
|
||||
|
||||
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
|
||||
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
|
||||
end)
|
||||
|
||||
%{conn: assign(conn, :user, admin), admin: admin}
|
||||
end
|
||||
|
||||
clear_config([:instance, :dynamic_configuration]) do
|
||||
Pleroma.Config.put([:instance, :dynamic_configuration], true)
|
||||
end
|
||||
|
||||
test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
|
||||
assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
|
||||
conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
|
||||
|
|
|
@ -5,18 +5,66 @@
|
|||
defmodule Pleroma.Web.CommonAPITest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
clear_config([:instance, :safe_dm_mentions])
|
||||
clear_config([:instance, :limit])
|
||||
clear_config([:instance, :max_pinned_statuses])
|
||||
|
||||
test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
{:ok, convo_reply} =
|
||||
CommonAPI.post(user, %{"status" => ".", "in_reply_to_conversation_id" => participation.id})
|
||||
|
||||
assert Visibility.is_direct?(convo_reply)
|
||||
|
||||
assert activity.data["context"] == convo_reply.data["context"]
|
||||
end
|
||||
|
||||
test "when replying to a conversation / participation, it only mentions the recipients explicitly declared in the participation" do
|
||||
har = insert(:user)
|
||||
jafnhar = insert(:user)
|
||||
tridi = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{
|
||||
"status" => "@#{jafnhar.nickname} hey",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
assert har.ap_id in activity.recipients
|
||||
assert jafnhar.ap_id in activity.recipients
|
||||
|
||||
[participation] = Participation.for_user(har)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{
|
||||
"status" => "I don't really like @#{tridi.nickname}",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity.id,
|
||||
"in_reply_to_conversation_id" => participation.id
|
||||
})
|
||||
|
||||
assert har.ap_id in activity.recipients
|
||||
assert jafnhar.ap_id in activity.recipients
|
||||
refute tridi.ap_id in activity.recipients
|
||||
end
|
||||
|
||||
test "with the safe_dm_mention option set, it does not mention people beyond the initial tags" do
|
||||
har = insert(:user)
|
||||
jafnhar = insert(:user)
|
||||
tridi = insert(:user)
|
||||
option = Pleroma.Config.get([:instance, :safe_dm_mentions])
|
||||
Pleroma.Config.put([:instance, :safe_dm_mentions], true)
|
||||
|
||||
{:ok, activity} =
|
||||
|
@ -27,7 +75,6 @@ test "with the safe_dm_mention option set, it does not mention people beyond the
|
|||
|
||||
refute tridi.ap_id in activity.recipients
|
||||
assert jafnhar.ap_id in activity.recipients
|
||||
Pleroma.Config.put([:instance, :safe_dm_mentions], option)
|
||||
end
|
||||
|
||||
test "it de-duplicates tags" do
|
||||
|
@ -150,15 +197,12 @@ test "it returns error when status is empty and no attachments" do
|
|||
end
|
||||
|
||||
test "it returns error when character limit is exceeded" do
|
||||
limit = Pleroma.Config.get([:instance, :limit])
|
||||
Pleroma.Config.put([:instance, :limit], 5)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
assert {:error, "The status is over the character limit"} =
|
||||
CommonAPI.post(user, %{"status" => "foobar"})
|
||||
|
||||
Pleroma.Config.put([:instance, :limit], limit)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ test "for public posts, not a reply" do
|
|||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 1
|
||||
|
@ -256,7 +256,7 @@ test "for public posts, a reply" do
|
|||
{:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 1
|
||||
|
@ -272,7 +272,7 @@ test "for unlisted posts, not a reply" do
|
|||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 1
|
||||
|
@ -289,7 +289,7 @@ test "for unlisted posts, a reply" do
|
|||
{:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 1
|
||||
|
@ -305,7 +305,7 @@ test "for private posts, not a reply" do
|
|||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private", nil)
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 0
|
||||
|
||||
|
@ -320,7 +320,7 @@ test "for private posts, a reply" do
|
|||
{:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 0
|
||||
|
@ -335,7 +335,7 @@ test "for direct posts, not a reply" do
|
|||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct", nil)
|
||||
|
||||
assert length(to) == 1
|
||||
assert length(cc) == 0
|
||||
|
@ -350,7 +350,7 @@ test "for direct posts, a reply" do
|
|||
{:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct")
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 0
|
||||
|
|
31
test/web/digest_email_worker_test.exs
Normal file
31
test/web/digest_email_worker_test.exs
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.DigestEmailWorkerTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.DigestEmailWorker
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "it sends digest emails" do
|
||||
user = insert(:user)
|
||||
|
||||
date =
|
||||
Timex.now()
|
||||
|> Timex.shift(days: -10)
|
||||
|> Timex.to_naive_datetime()
|
||||
|
||||
user2 = insert(:user, last_digest_emailed_at: date)
|
||||
User.switch_email_notifications(user2, "digest", true)
|
||||
CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"})
|
||||
|
||||
DigestEmailWorker.perform()
|
||||
|
||||
assert_received {:email, email}
|
||||
assert email.to == [{user2.name, user2.email}]
|
||||
assert email.subject == "Your digest from #{Pleroma.Config.get(:instance)[:name]}"
|
||||
end
|
||||
end
|
|
@ -13,15 +13,17 @@ defmodule Pleroma.Web.FederatorTest do
|
|||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
clear_config_all([:instance, :federating]) do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
end
|
||||
|
||||
clear_config([:instance, :allow_relay])
|
||||
clear_config([:instance, :rewrite_policy])
|
||||
clear_config([:mrf_keyword])
|
||||
|
||||
describe "Publisher.perform" do
|
||||
test "call `perform` with unknown task" do
|
||||
assert {
|
||||
|
@ -67,8 +69,6 @@ test "with relays deactivated, it does not publish to the relay", %{
|
|||
end
|
||||
|
||||
refute_received :relay_publish
|
||||
|
||||
Pleroma.Config.put([:instance, :allow_relay], true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -231,19 +231,18 @@ test "rejects incoming AP docs with incorrect origin" do
|
|||
end
|
||||
|
||||
test "it does not crash if MRF rejects the post" do
|
||||
policies = Pleroma.Config.get([:instance, :rewrite_policy])
|
||||
mrf_keyword_policy = Pleroma.Config.get(:mrf_keyword)
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["lain"])
|
||||
Pleroma.Config.put([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.KeywordPolicy)
|
||||
|
||||
Pleroma.Config.put(
|
||||
[:instance, :rewrite_policy],
|
||||
Pleroma.Web.ActivityPub.MRF.KeywordPolicy
|
||||
)
|
||||
|
||||
params =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
assert Federator.incoming_ap_doc(params) == :error
|
||||
|
||||
Pleroma.Config.put([:instance, :rewrite_policy], policies)
|
||||
Pleroma.Config.put(:mrf_keyword, mrf_keyword_policy)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,14 +10,8 @@ defmodule Pleroma.Instances.InstanceTest do
|
|||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
config_path = [:instance, :federation_reachability_timeout_days]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, 1)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
clear_config_all([:instance, :federation_reachability_timeout_days]) do
|
||||
Pleroma.Config.put([:instance, :federation_reachability_timeout_days], 1)
|
||||
end
|
||||
|
||||
describe "set_reachable/1" do
|
||||
|
|
|
@ -7,14 +7,8 @@ defmodule Pleroma.InstancesTest do
|
|||
|
||||
use Pleroma.DataCase
|
||||
|
||||
setup_all do
|
||||
config_path = [:instance, :federation_reachability_timeout_days]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, 1)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
clear_config_all([:instance, :federation_reachability_timeout_days]) do
|
||||
Pleroma.Config.put([:instance, :federation_reachability_timeout_days], 1)
|
||||
end
|
||||
|
||||
describe "reachable?/1" do
|
||||
|
|
34
test/web/mastodon_api/conversation_view_test.exs
Normal file
34
test/web/mastodon_api/conversation_view_test.exs
Normal file
|
@ -0,0 +1,34 @@
|
|||
# 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.ConversationViewTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.ConversationView
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "represents a Mastodon Conversation entity" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user_with_last_activity_id(user)
|
||||
|
||||
assert participation
|
||||
|
||||
conversation =
|
||||
ConversationView.render("participation.json", %{participation: participation, for: user})
|
||||
|
||||
assert conversation.id == participation.id |> to_string()
|
||||
assert conversation.last_status.id == activity.id
|
||||
|
||||
assert [account] = conversation.accounts
|
||||
assert account.id == other_user.id
|
||||
end
|
||||
end
|
|
@ -33,6 +33,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
clear_config([:instance, :public])
|
||||
clear_config([:rich_media, :enabled])
|
||||
|
||||
test "the home timeline", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
following = insert(:user)
|
||||
|
@ -86,13 +89,8 @@ test "the public timeline", %{conn: conn} do
|
|||
end
|
||||
|
||||
test "the public timeline when public is set to false", %{conn: conn} do
|
||||
public = Config.get([:instance, :public])
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([:instance, :public], public)
|
||||
end)
|
||||
|
||||
assert conn
|
||||
|> get("/api/v1/timelines/public", %{"local" => "False"})
|
||||
|> json_response(403) == %{"error" => "This resource requires authentication."}
|
||||
|
@ -261,7 +259,6 @@ test "posting a status with OGP link preview", %{conn: conn} do
|
|||
|
||||
assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
|
||||
assert Activity.get_by_id(id)
|
||||
Config.put([:rich_media, :enabled], false)
|
||||
end
|
||||
|
||||
test "posting a direct status", %{conn: conn} do
|
||||
|
@ -1634,14 +1631,6 @@ test "returns the relationships for the current user", %{conn: conn} do
|
|||
|
||||
describe "media upload" do
|
||||
setup do
|
||||
upload_config = Config.get([Pleroma.Upload])
|
||||
proxy_config = Config.get([:media_proxy])
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([Pleroma.Upload], upload_config)
|
||||
Config.put([:media_proxy], proxy_config)
|
||||
end)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
|
@ -1657,6 +1646,9 @@ test "returns the relationships for the current user", %{conn: conn} do
|
|||
[conn: conn, image: image]
|
||||
end
|
||||
|
||||
clear_config([:media_proxy])
|
||||
clear_config([Pleroma.Upload])
|
||||
|
||||
test "returns uploaded image", %{conn: conn, image: image} do
|
||||
desc = "Description of the image"
|
||||
|
||||
|
@ -2624,7 +2616,7 @@ test "get instance stats", %{conn: conn} do
|
|||
|> Changeset.put_embed(:info, info_change)
|
||||
|> User.update_and_set_cache()
|
||||
|
||||
Pleroma.Stats.update_stats()
|
||||
Pleroma.Stats.force_update()
|
||||
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
|
@ -2642,7 +2634,7 @@ test "get peers", %{conn: conn} do
|
|||
insert(:user, %{local: false, nickname: "u@peer1.com"})
|
||||
insert(:user, %{local: false, nickname: "u@peer2.com"})
|
||||
|
||||
Pleroma.Stats.update_stats()
|
||||
Pleroma.Stats.force_update()
|
||||
|
||||
conn = get(conn, "/api/v1/instance/peers")
|
||||
|
||||
|
@ -2667,14 +2659,16 @@ test "put settings", %{conn: conn} do
|
|||
|
||||
describe "pinned statuses" do
|
||||
setup do
|
||||
Config.put([:instance, :max_pinned_statuses], 1)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
|
||||
|
||||
[user: user, activity: activity]
|
||||
end
|
||||
|
||||
clear_config([:instance, :max_pinned_statuses]) do
|
||||
Config.put([:instance, :max_pinned_statuses], 1)
|
||||
end
|
||||
|
||||
test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.pin(activity.id, user)
|
||||
|
||||
|
@ -2769,10 +2763,6 @@ test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
|
|||
setup do
|
||||
Config.put([:rich_media, :enabled], true)
|
||||
|
||||
on_exit(fn ->
|
||||
Config.put([:rich_media, :enabled], false)
|
||||
end)
|
||||
|
||||
user = insert(:user)
|
||||
%{user: user}
|
||||
end
|
||||
|
@ -3127,15 +3117,12 @@ test "redirects not logged-in users to the login page on private instances", %{
|
|||
conn: conn,
|
||||
path: path
|
||||
} do
|
||||
is_public = Config.get([:instance, :public])
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn = get(conn, path)
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == "/web/login"
|
||||
|
||||
Config.put([:instance, :public], is_public)
|
||||
end
|
||||
|
||||
test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
|
||||
|
@ -3910,13 +3897,6 @@ test "it returns 400 when user is not local", %{conn: conn, user: user} do
|
|||
|
||||
describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
|
||||
setup do
|
||||
setting = Config.get([:instance, :account_activation_required])
|
||||
|
||||
unless setting do
|
||||
Config.put([:instance, :account_activation_required], true)
|
||||
on_exit(fn -> Config.put([:instance, :account_activation_required], setting) end)
|
||||
end
|
||||
|
||||
user = insert(:user)
|
||||
info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
|
||||
|
||||
|
@ -3931,6 +3911,10 @@ test "it returns 400 when user is not local", %{conn: conn, user: user} do
|
|||
[user: user]
|
||||
end
|
||||
|
||||
clear_config([:instance, :account_activation_required]) do
|
||||
Config.put([:instance, :account_activation_required], true)
|
||||
end
|
||||
|
||||
test "resend account confirmation email", %{conn: conn, user: user} do
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
@ -3953,9 +3937,6 @@ test "resend account confirmation email", %{conn: conn, user: user} do
|
|||
setup do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
config = Config.get(:suggestions)
|
||||
on_exit(fn -> Config.put(:suggestions, config) end)
|
||||
|
||||
host = Config.get([Pleroma.Web.Endpoint, :url, :host])
|
||||
url500 = "http://test500?#{host}&#{user.nickname}"
|
||||
url200 = "http://test200?#{host}&#{user.nickname}"
|
||||
|
@ -3977,6 +3958,8 @@ test "resend account confirmation email", %{conn: conn, user: user} do
|
|||
[user: user, other_user: other_user]
|
||||
end
|
||||
|
||||
clear_config(:suggestions)
|
||||
|
||||
test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
|
||||
Config.put([:suggestions, :enabled], false)
|
||||
|
||||
|
|
|
@ -23,6 +23,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
test "returns the direct conversation id when given the `with_conversation_id` option" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
||||
|
||||
status =
|
||||
StatusView.render("status.json",
|
||||
activity: activity,
|
||||
with_direct_conversation_id: true,
|
||||
for: user
|
||||
)
|
||||
|
||||
assert status[:pleroma][:direct_conversation_id]
|
||||
end
|
||||
|
||||
test "returns a temporary ap_id based user for activities missing db users" do
|
||||
user = insert(:user)
|
||||
|
||||
|
@ -133,7 +148,8 @@ test "a note activity" do
|
|||
conversation_id: convo_id,
|
||||
in_reply_to_account_acct: nil,
|
||||
content: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["content"])},
|
||||
spoiler_text: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["summary"])}
|
||||
spoiler_text: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["summary"])},
|
||||
direct_conversation_id: nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,14 +4,11 @@
|
|||
|
||||
defmodule Pleroma.Web.MediaProxyTest do
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
import Pleroma.Web.MediaProxy
|
||||
alias Pleroma.Web.MediaProxy.MediaProxyController
|
||||
|
||||
setup do
|
||||
enabled = Pleroma.Config.get([:media_proxy, :enabled])
|
||||
on_exit(fn -> Pleroma.Config.put([:media_proxy, :enabled], enabled) end)
|
||||
:ok
|
||||
end
|
||||
clear_config([:media_proxy, :enabled])
|
||||
|
||||
describe "when enabled" do
|
||||
setup do
|
||||
|
|
|
@ -12,21 +12,12 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
|
|||
|
||||
@skip if !Code.ensure_loaded?(:eldap), do: :skip
|
||||
|
||||
setup_all do
|
||||
ldap_authenticator =
|
||||
Pleroma.Config.get(Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.PleromaAuthenticator)
|
||||
|
||||
ldap_enabled = Pleroma.Config.get([:ldap, :enabled])
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put(Pleroma.Web.Auth.Authenticator, ldap_authenticator)
|
||||
Pleroma.Config.put([:ldap, :enabled], ldap_enabled)
|
||||
end)
|
||||
|
||||
Pleroma.Config.put(Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.LDAPAuthenticator)
|
||||
clear_config_all([:ldap, :enabled]) do
|
||||
Pleroma.Config.put([:ldap, :enabled], true)
|
||||
end
|
||||
|
||||
:ok
|
||||
clear_config_all(Pleroma.Web.Auth.Authenticator) do
|
||||
Pleroma.Config.put(Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.LDAPAuthenticator)
|
||||
end
|
||||
|
||||
@tag @skip
|
||||
|
|
|
@ -11,23 +11,15 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
alias Pleroma.Web.OAuth.OAuthController
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
@oauth_config_path [:oauth2, :issue_new_refresh_token]
|
||||
@session_opts [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
clear_config_all([:instance, :account_activation_required])
|
||||
|
||||
describe "in OAuth consumer mode, " do
|
||||
setup do
|
||||
oauth_consumer_strategies_path = [:auth, :oauth_consumer_strategies]
|
||||
oauth_consumer_strategies = Pleroma.Config.get(oauth_consumer_strategies_path)
|
||||
Pleroma.Config.put(oauth_consumer_strategies_path, ~w(twitter facebook))
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put(oauth_consumer_strategies_path, oauth_consumer_strategies)
|
||||
end)
|
||||
|
||||
[
|
||||
app: insert(:oauth_app),
|
||||
conn:
|
||||
|
@ -37,6 +29,13 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||
]
|
||||
end
|
||||
|
||||
clear_config([:auth, :oauth_consumer_strategies]) do
|
||||
Pleroma.Config.put(
|
||||
[:auth, :oauth_consumer_strategies],
|
||||
~w(twitter facebook)
|
||||
)
|
||||
end
|
||||
|
||||
test "GET /oauth/authorize renders auth forms, including OAuth consumer form", %{
|
||||
app: app,
|
||||
conn: conn
|
||||
|
@ -775,12 +774,7 @@ test "rejects token exchange with invalid client credentials" do
|
|||
end
|
||||
|
||||
test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do
|
||||
setting = Pleroma.Config.get([:instance, :account_activation_required])
|
||||
|
||||
unless setting do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
|
||||
end
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
|
||||
password = "testpassword"
|
||||
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|
||||
|
@ -857,16 +851,10 @@ test "rejects an invalid authorization code" do
|
|||
end
|
||||
|
||||
describe "POST /oauth/token - refresh token" do
|
||||
setup do
|
||||
oauth_token_config = Pleroma.Config.get(@oauth_config_path)
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.get(@oauth_config_path, oauth_token_config)
|
||||
end)
|
||||
end
|
||||
clear_config([:oauth2, :issue_new_refresh_token])
|
||||
|
||||
test "issues a new access token with keep fresh token" do
|
||||
Pleroma.Config.put(@oauth_config_path, true)
|
||||
Pleroma.Config.put([:oauth2, :issue_new_refresh_token], true)
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
|
@ -906,7 +894,7 @@ test "issues a new access token with keep fresh token" do
|
|||
end
|
||||
|
||||
test "issues a new access token with new fresh token" do
|
||||
Pleroma.Config.put(@oauth_config_path, false)
|
||||
Pleroma.Config.put([:oauth2, :issue_new_refresh_token], false)
|
||||
user = insert(:user)
|
||||
app = insert(:oauth_app, scopes: ["read", "write"])
|
||||
|
||||
|
|
|
@ -15,16 +15,13 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
|||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
clear_config_all([:instance, :federating]) do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
end
|
||||
|
||||
describe "salmon_incoming" do
|
||||
test "decodes a salmon", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
|
94
test/web/pleroma_api/pleroma_api_controller_test.exs
Normal file
94
test/web/pleroma_api/pleroma_api_controller_test.exs
Normal file
|
@ -0,0 +1,94 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "/api/v1/pleroma/conversations/:id", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user(other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, other_user)
|
||||
|> get("/api/v1/pleroma/conversations/#{participation.id}")
|
||||
|> json_response(200)
|
||||
|
||||
assert result["id"] == participation.id |> to_string()
|
||||
end
|
||||
|
||||
test "/api/v1/pleroma/conversations/:id/statuses", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hi @#{third_user.nickname}!", "visibility" => "direct"})
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user(other_user)
|
||||
|
||||
{:ok, activity_two} =
|
||||
CommonAPI.post(other_user, %{
|
||||
"status" => "Hi!",
|
||||
"in_reply_to_status_id" => activity.id,
|
||||
"in_reply_to_conversation_id" => participation.id
|
||||
})
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, other_user)
|
||||
|> get("/api/v1/pleroma/conversations/#{participation.id}/statuses")
|
||||
|> json_response(200)
|
||||
|
||||
assert length(result) == 2
|
||||
|
||||
id_one = activity.id
|
||||
id_two = activity_two.id
|
||||
assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result
|
||||
end
|
||||
|
||||
test "PATCH /api/v1/pleroma/conversations/:id", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{"status" => "Hi", "visibility" => "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
||||
assert [user] == participation.recipients
|
||||
assert other_user not in participation.recipients
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/pleroma/conversations/#{participation.id}", %{
|
||||
"recipients" => [user.id, other_user.id]
|
||||
})
|
||||
|> json_response(200)
|
||||
|
||||
assert result["id"] == participation.id |> to_string
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
||||
assert user in participation.recipients
|
||||
assert other_user in participation.recipients
|
||||
end
|
||||
end
|
|
@ -4,15 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.FederatingPlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
setup_all do
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
clear_config_all([:instance, :federating])
|
||||
|
||||
test "returns and halt the conn when federating is disabled" do
|
||||
Pleroma.Config.put([:instance, :federating], false)
|
||||
|
|
|
@ -15,12 +15,12 @@ defmodule Pleroma.Web.RichMedia.HelpersTest do
|
|||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
rich_media = Config.get([:rich_media, :enabled])
|
||||
on_exit(fn -> Config.put([:rich_media, :enabled], rich_media) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
clear_config([:rich_media, :enabled])
|
||||
|
||||
test "refuses to crawl incomplete URLs" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
@ -11,15 +11,7 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
alias Pleroma.Web.Streamer
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
skip_thread_containment = Pleroma.Config.get([:instance, :skip_thread_containment])
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :skip_thread_containment], skip_thread_containment)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
clear_config_all([:instance, :skip_thread_containment])
|
||||
|
||||
describe "user streams" do
|
||||
setup do
|
||||
|
@ -414,6 +406,26 @@ test "it doesn't send muted reblogs" do
|
|||
Task.await(task)
|
||||
end
|
||||
|
||||
test "it doesn't send posts from muted threads" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
{:ok, user2, user, _activity} = CommonAPI.follow(user2, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||
|
||||
{:ok, activity} = CommonAPI.add_mute(user2, activity)
|
||||
|
||||
task = Task.async(fn -> refute_receive {:text, _}, 4_000 end)
|
||||
|
||||
Streamer.add_socket(
|
||||
"user",
|
||||
%{transport_pid: task.pid, assigns: %{user: user2}}
|
||||
)
|
||||
|
||||
Streamer.stream("user", activity)
|
||||
Task.await(task)
|
||||
end
|
||||
|
||||
describe "direct streams" do
|
||||
setup do
|
||||
GenServer.start(Streamer, %{}, name: Streamer)
|
||||
|
|
|
@ -151,6 +151,7 @@ test "with credentials", %{conn: conn, user: user} do
|
|||
|
||||
describe "GET /statuses/public_timeline.json" do
|
||||
setup [:valid_user]
|
||||
clear_config([:instance, :public])
|
||||
|
||||
test "returns statuses", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
@ -173,8 +174,6 @@ test "returns 403 to unauthenticated request when the instance is not public", %
|
|||
conn
|
||||
|> get("/api/statuses/public_timeline.json")
|
||||
|> json_response(403)
|
||||
|
||||
Pleroma.Config.put([:instance, :public], true)
|
||||
end
|
||||
|
||||
test "returns 200 to authenticated request when the instance is not public",
|
||||
|
@ -185,8 +184,6 @@ test "returns 200 to authenticated request when the instance is not public",
|
|||
|> with_credentials(user.nickname, "test")
|
||||
|> get("/api/statuses/public_timeline.json")
|
||||
|> json_response(200)
|
||||
|
||||
Pleroma.Config.put([:instance, :public], true)
|
||||
end
|
||||
|
||||
test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
|
||||
|
@ -220,6 +217,7 @@ test "returns 200 to authenticated request when the instance is public",
|
|||
|
||||
describe "GET /statuses/public_and_external_timeline.json" do
|
||||
setup [:valid_user]
|
||||
clear_config([:instance, :public])
|
||||
|
||||
test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
|
||||
Pleroma.Config.put([:instance, :public], false)
|
||||
|
@ -227,8 +225,6 @@ test "returns 403 to unauthenticated request when the instance is not public", %
|
|||
conn
|
||||
|> get("/api/statuses/public_and_external_timeline.json")
|
||||
|> json_response(403)
|
||||
|
||||
Pleroma.Config.put([:instance, :public], true)
|
||||
end
|
||||
|
||||
test "returns 200 to authenticated request when the instance is not public",
|
||||
|
@ -239,8 +235,6 @@ test "returns 200 to authenticated request when the instance is not public",
|
|||
|> with_credentials(user.nickname, "test")
|
||||
|> get("/api/statuses/public_and_external_timeline.json")
|
||||
|> json_response(200)
|
||||
|
||||
Pleroma.Config.put([:instance, :public], true)
|
||||
end
|
||||
|
||||
test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
|
||||
|
@ -1176,13 +1170,6 @@ test "it returns 500 if token is invalid", %{conn: conn, user: user} do
|
|||
|
||||
describe "POST /api/account/resend_confirmation_email" do
|
||||
setup do
|
||||
setting = Pleroma.Config.get([:instance, :account_activation_required])
|
||||
|
||||
unless setting do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
|
||||
end
|
||||
|
||||
user = insert(:user)
|
||||
info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
|
||||
|
||||
|
@ -1197,6 +1184,10 @@ test "it returns 500 if token is invalid", %{conn: conn, user: user} do
|
|||
[user: user]
|
||||
end
|
||||
|
||||
clear_config([:instance, :account_activation_required]) do
|
||||
Pleroma.Config.put([:instance, :account_activation_required], true)
|
||||
end
|
||||
|
||||
test "it returns 204 No Content", %{conn: conn, user: user} do
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
|
|
@ -14,20 +14,13 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
|||
|
||||
setup do
|
||||
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
instance_config = Pleroma.Config.get([:instance])
|
||||
pleroma_fe = Pleroma.Config.get([:frontend_configurations, :pleroma_fe])
|
||||
deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance], instance_config)
|
||||
Pleroma.Config.put([:frontend_configurations, :pleroma_fe], pleroma_fe)
|
||||
Pleroma.Config.put([:user, :deny_follow_blocked], deny_follow_blocked)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
clear_config([:instance])
|
||||
clear_config([:frontend_configurations, :pleroma_fe])
|
||||
clear_config([:user, :deny_follow_blocked])
|
||||
|
||||
describe "POST /api/pleroma/follow_import" do
|
||||
test "it returns HTTP 200", %{conn: conn} do
|
||||
user1 = insert(:user)
|
||||
|
@ -260,7 +253,6 @@ test "it returns config in json format", %{conn: conn} do
|
|||
end
|
||||
|
||||
test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
||||
option = Pleroma.Config.get([:instance, :safe_dm_mentions])
|
||||
Pleroma.Config.put([:instance, :safe_dm_mentions], true)
|
||||
|
||||
response =
|
||||
|
@ -278,8 +270,6 @@ test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
|||
|> json_response(:ok)
|
||||
|
||||
assert response["site"]["safeDMMentionsEnabled"] == "0"
|
||||
|
||||
Pleroma.Config.put([:instance, :safe_dm_mentions], option)
|
||||
end
|
||||
|
||||
test "it returns the managed config", %{conn: conn} do
|
||||
|
@ -534,15 +524,7 @@ test "returns error when user is blocked", %{conn: conn} do
|
|||
end
|
||||
|
||||
describe "GET /api/pleroma/healthcheck" do
|
||||
setup do
|
||||
config_healthcheck = Pleroma.Config.get([:instance, :healthcheck])
|
||||
|
||||
on_exit(fn ->
|
||||
Pleroma.Config.put([:instance, :healthcheck], config_healthcheck)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
clear_config([:instance, :healthcheck])
|
||||
|
||||
test "returns 503 when healthcheck disabled", %{conn: conn} do
|
||||
Pleroma.Config.put([:instance, :healthcheck], false)
|
||||
|
|
|
@ -10,15 +10,13 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
|
|||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
clear_config_all([:instance, :federating]) do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
end
|
||||
|
||||
test "GET host-meta" do
|
||||
response =
|
||||
build_conn()
|
||||
|
|
|
@ -9,14 +9,8 @@ defmodule Pleroma.Web.Websub.WebsubControllerTest do
|
|||
alias Pleroma.Web.Websub
|
||||
alias Pleroma.Web.Websub.WebsubClientSubscription
|
||||
|
||||
setup_all do
|
||||
config_path = [:instance, :federating]
|
||||
initial_setting = Pleroma.Config.get(config_path)
|
||||
|
||||
Pleroma.Config.put(config_path, true)
|
||||
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
|
||||
|
||||
:ok
|
||||
clear_config_all([:instance, :federating]) do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
end
|
||||
|
||||
test "websub subscription request", %{conn: conn} do
|
||||
|
|
Loading…
Reference in a new issue