Merge branch 'release/2.0.2' into 'stable'
2.0.2 Release See merge request pleroma/pleroma!2336
This commit is contained in:
commit
3b15a0eecc
@ -62,19 +62,21 @@ unit-testing:
|
|||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
- mix coveralls --preload-modules
|
- mix coveralls --preload-modules
|
||||||
|
|
||||||
federated-testing:
|
# Removed to fix CI issue. In this early state it wasn't adding much value anyway.
|
||||||
stage: test
|
# TODO Fix and reinstate federated testing
|
||||||
cache: *testing_cache_policy
|
# federated-testing:
|
||||||
services:
|
# stage: test
|
||||||
- name: minibikini/postgres-with-rum:12
|
# cache: *testing_cache_policy
|
||||||
alias: postgres
|
# services:
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
# - name: minibikini/postgres-with-rum:12
|
||||||
script:
|
# alias: postgres
|
||||||
- mix deps.get
|
# command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||||
- mix ecto.create
|
# script:
|
||||||
- mix ecto.migrate
|
# - mix deps.get
|
||||||
- epmd -daemon
|
# - mix ecto.create
|
||||||
- mix test --trace --only federated
|
# - mix ecto.migrate
|
||||||
|
# - epmd -daemon
|
||||||
|
# - mix test --trace --only federated
|
||||||
|
|
||||||
unit-testing-rum:
|
unit-testing-rum:
|
||||||
stage: test
|
stage: test
|
||||||
|
16
CHANGELOG.md
16
CHANGELOG.md
@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## [2.0.2] - 2020-04-08
|
||||||
|
### Added
|
||||||
|
- Support for Funkwhale's `Audio` activity
|
||||||
|
- Admin API: `PATCH /api/pleroma/admin/users/:nickname/update_credentials`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Blocked/muted users still generating push notifications
|
||||||
|
- Input textbox for bio ignoring newlines
|
||||||
|
- OTP: Inability to use PostgreSQL databases with SSL
|
||||||
|
- `user delete_activities` breaking when trying to delete already deleted posts
|
||||||
|
- Incorrect URL for Funkwhale channels
|
||||||
|
|
||||||
|
### Upgrade notes
|
||||||
|
1. Restart Pleroma
|
||||||
|
|
||||||
## [2.0.1] - 2020-03-15
|
## [2.0.1] - 2020-03-15
|
||||||
### Security
|
### Security
|
||||||
- Static-FE: Fix remote posts not being sanitized
|
- Static-FE: Fix remote posts not being sanitized
|
||||||
@ -91,6 +106,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
- Mastodon API: User timelines will now respect blocks, unless you are getting the user timeline of somebody you blocked (which would be empty otherwise).
|
- Mastodon API: User timelines will now respect blocks, unless you are getting the user timeline of somebody you blocked (which would be empty otherwise).
|
||||||
- Mastodon API: Favoriting / Repeating a post multiple times will now return the identical response every time. Before, executing that action twice would return an error ("already favorited") on the second try.
|
- Mastodon API: Favoriting / Repeating a post multiple times will now return the identical response every time. Before, executing that action twice would return an error ("already favorited") on the second try.
|
||||||
- Mastodon API: Limit timeline requests to 3 per timeline per 500ms per user/ip by default.
|
- Mastodon API: Limit timeline requests to 3 per timeline per 500ms per user/ip by default.
|
||||||
|
- Admin API: `PATCH /api/pleroma/admin/users/:nickname/credentials` and `GET /api/pleroma/admin/users/:nickname/credentials`
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -2461,7 +2461,7 @@ config :pleroma, :config_description, [
|
|||||||
%{
|
%{
|
||||||
key: :relations_actions,
|
key: :relations_actions,
|
||||||
type: [:tuple, {:list, :tuple}],
|
type: [:tuple, {:list, :tuple}],
|
||||||
description: "For actions on relations with all users (follow, unfollow)",
|
description: "For actions on relationships with all users (follow, unfollow)",
|
||||||
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
|
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -414,6 +414,83 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
|||||||
- `nicknames`
|
- `nicknames`
|
||||||
- Response: none (code `204`)
|
- Response: none (code `204`)
|
||||||
|
|
||||||
|
## `GET /api/pleroma/admin/users/:nickname/credentials`
|
||||||
|
|
||||||
|
### Get the user's email, password, display and settings-related fields
|
||||||
|
|
||||||
|
- Params:
|
||||||
|
- `nickname`
|
||||||
|
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"actor_type": "Person",
|
||||||
|
"allow_following_move": true,
|
||||||
|
"avatar": "https://pleroma.social/media/7e8e7508fd545ef580549b6881d80ec0ff2c81ed9ad37b9bdbbdf0e0d030159d.jpg",
|
||||||
|
"background": "https://pleroma.social/media/4de34c0bd10970d02cbdef8972bef0ebbf55f43cadc449554d4396156162fe9a.jpg",
|
||||||
|
"banner": "https://pleroma.social/media/8d92ba2bd244b613520abf557dd448adcd30f5587022813ee9dd068945986946.jpg",
|
||||||
|
"bio": "bio",
|
||||||
|
"default_scope": "public",
|
||||||
|
"discoverable": false,
|
||||||
|
"email": "user@example.com",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "example",
|
||||||
|
"value": "<a href=\"https://example.com\" rel=\"ugc\">https://example.com</a>"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hide_favorites": false,
|
||||||
|
"hide_followers": false,
|
||||||
|
"hide_followers_count": false,
|
||||||
|
"hide_follows": false,
|
||||||
|
"hide_follows_count": false,
|
||||||
|
"id": "9oouHaEEUR54hls968",
|
||||||
|
"locked": true,
|
||||||
|
"name": "user",
|
||||||
|
"no_rich_text": true,
|
||||||
|
"pleroma_settings_store": {},
|
||||||
|
"raw_fields": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "example",
|
||||||
|
"value": "https://example.com"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"show_role": true,
|
||||||
|
"skip_thread_containment": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `PATCH /api/pleroma/admin/users/:nickname/credentials`
|
||||||
|
|
||||||
|
### Change the user's email, password, display and settings-related fields
|
||||||
|
|
||||||
|
- Params:
|
||||||
|
- `email`
|
||||||
|
- `password`
|
||||||
|
- `name`
|
||||||
|
- `bio`
|
||||||
|
- `avatar`
|
||||||
|
- `locked`
|
||||||
|
- `no_rich_text`
|
||||||
|
- `default_scope`
|
||||||
|
- `banner`
|
||||||
|
- `hide_follows`
|
||||||
|
- `hide_followers`
|
||||||
|
- `hide_followers_count`
|
||||||
|
- `hide_follows_count`
|
||||||
|
- `hide_favorites`
|
||||||
|
- `allow_following_move`
|
||||||
|
- `background`
|
||||||
|
- `show_role`
|
||||||
|
- `skip_thread_containment`
|
||||||
|
- `fields`
|
||||||
|
- `discoverable`
|
||||||
|
- `actor_type`
|
||||||
|
|
||||||
|
- Response: none (code `200`)
|
||||||
|
|
||||||
## `GET /api/pleroma/admin/reports`
|
## `GET /api/pleroma/admin/reports`
|
||||||
|
|
||||||
### Get a list of reports
|
### Get a list of reports
|
||||||
|
@ -138,7 +138,8 @@ config :pleroma, :mrf_user_allowlist,
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### :mrf_object_age
|
#### :mrf_object_age
|
||||||
* `threshold`: Required age (in seconds) of a post before actions are taken.
|
* `threshold`: Required time offset (in seconds) compared to your server clock of an incoming post before actions are taken.
|
||||||
|
e.g., A value of 900 results in any post with a timestamp older than 15 minutes will be acted upon.
|
||||||
* `actions`: A list of actions to apply to the post:
|
* `actions`: A list of actions to apply to the post:
|
||||||
* `:delist` removes the post from public timelines
|
* `:delist` removes the post from public timelines
|
||||||
* `:strip_followers` removes followers from the ActivityPub recipient list, ensuring they won't be delivered to home timelines
|
* `:strip_followers` removes followers from the ActivityPub recipient list, ensuring they won't be delivered to home timelines
|
||||||
|
@ -95,6 +95,17 @@ defmodule Pleroma.Activity do
|
|||||||
|> preload([activity, object: object], object: object)
|
|> preload([activity, object: object], object: object)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Note: applies to fake activities (ActivityPub.Utils.get_notified_from_object/1 etc.)
|
||||||
|
def user_actor(%Activity{actor: nil}), do: nil
|
||||||
|
|
||||||
|
def user_actor(%Activity{} = activity) do
|
||||||
|
with %User{} <- activity.user_actor do
|
||||||
|
activity.user_actor
|
||||||
|
else
|
||||||
|
_ -> User.get_cached_by_ap_id(activity.actor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def with_joined_user_actor(query, join_type \\ :inner) do
|
def with_joined_user_actor(query, join_type \\ :inner) do
|
||||||
join(query, join_type, [activity], u in User,
|
join(query, join_type, [activity], u in User,
|
||||||
on: u.ap_id == activity.actor,
|
on: u.ap_id == activity.actor,
|
||||||
|
@ -605,6 +605,17 @@ defmodule Pleroma.ModerationLog do
|
|||||||
}"
|
}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
|
def get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "updated_users",
|
||||||
|
"subject" => subjects
|
||||||
|
}
|
||||||
|
}) do
|
||||||
|
"@#{actor_nickname} updated users: #{users_to_nicknames_string(subjects)}"
|
||||||
|
end
|
||||||
|
|
||||||
defp nicknames_to_string(nicknames) do
|
defp nicknames_to_string(nicknames) do
|
||||||
nicknames
|
nicknames
|
||||||
|> Enum.map(&"@#{&1}")
|
|> Enum.map(&"@#{&1}")
|
||||||
|
@ -10,6 +10,7 @@ defmodule Pleroma.Notification do
|
|||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Pagination
|
alias Pleroma.Pagination
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.ThreadMute
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.Push
|
alias Pleroma.Web.Push
|
||||||
@ -17,6 +18,7 @@ defmodule Pleroma.Notification do
|
|||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@type t :: %__MODULE__{}
|
@type t :: %__MODULE__{}
|
||||||
@ -37,11 +39,11 @@ defmodule Pleroma.Notification do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp for_user_query_ap_id_opts(user, opts) do
|
defp for_user_query_ap_id_opts(user, opts) do
|
||||||
ap_id_relations =
|
ap_id_relationships =
|
||||||
[:block] ++
|
[:block] ++
|
||||||
if opts[@include_muted_option], do: [], else: [:notification_mute]
|
if opts[@include_muted_option], do: [], else: [:notification_mute]
|
||||||
|
|
||||||
preloaded_ap_ids = User.outgoing_relations_ap_ids(user, ap_id_relations)
|
preloaded_ap_ids = User.outgoing_relationships_ap_ids(user, ap_id_relationships)
|
||||||
|
|
||||||
exclude_blocked_opts = Map.merge(%{blocked_users_ap_ids: preloaded_ap_ids[:block]}, opts)
|
exclude_blocked_opts = Map.merge(%{blocked_users_ap_ids: preloaded_ap_ids[:block]}, opts)
|
||||||
|
|
||||||
@ -101,7 +103,7 @@ defmodule Pleroma.Notification do
|
|||||||
|
|
||||||
query
|
query
|
||||||
|> where([n, a], a.actor not in ^notification_muted_ap_ids)
|
|> where([n, a], a.actor not in ^notification_muted_ap_ids)
|
||||||
|> join(:left, [n, a], tm in Pleroma.ThreadMute,
|
|> join(:left, [n, a], tm in ThreadMute,
|
||||||
on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
|
on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
|
||||||
)
|
)
|
||||||
|> where([n, a, o, tm], is_nil(tm.user_id))
|
|> where([n, a, o, tm], is_nil(tm.user_id))
|
||||||
@ -284,58 +286,111 @@ defmodule Pleroma.Notification do
|
|||||||
def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity) do
|
def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity) do
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
unless object && object.data["type"] == "Answer" do
|
if object && object.data["type"] == "Answer" do
|
||||||
users = get_notified_from_activity(activity)
|
|
||||||
notifications = Enum.map(users, fn user -> create_notification(activity, user) end)
|
|
||||||
{:ok, notifications}
|
|
||||||
else
|
|
||||||
{:ok, []}
|
{:ok, []}
|
||||||
|
else
|
||||||
|
do_create_notifications(activity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_notifications(%Activity{data: %{"type" => type}} = activity)
|
def create_notifications(%Activity{data: %{"type" => type}} = activity)
|
||||||
when type in ["Like", "Announce", "Follow", "Move", "EmojiReact"] do
|
when type in ["Like", "Announce", "Follow", "Move", "EmojiReact"] do
|
||||||
notifications =
|
do_create_notifications(activity)
|
||||||
activity
|
|
||||||
|> get_notified_from_activity()
|
|
||||||
|> Enum.map(&create_notification(activity, &1))
|
|
||||||
|
|
||||||
{:ok, notifications}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_notifications(_), do: {:ok, []}
|
def create_notifications(_), do: {:ok, []}
|
||||||
|
|
||||||
|
defp do_create_notifications(%Activity{} = activity) do
|
||||||
|
{enabled_receivers, disabled_receivers} = get_notified_from_activity(activity)
|
||||||
|
potential_receivers = enabled_receivers ++ disabled_receivers
|
||||||
|
|
||||||
|
notifications =
|
||||||
|
Enum.map(potential_receivers, fn user ->
|
||||||
|
do_send = user in enabled_receivers
|
||||||
|
create_notification(activity, user, do_send)
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, notifications}
|
||||||
|
end
|
||||||
|
|
||||||
# TODO move to sql, too.
|
# TODO move to sql, too.
|
||||||
def create_notification(%Activity{} = activity, %User{} = user) do
|
def create_notification(%Activity{} = activity, %User{} = user, do_send \\ true) do
|
||||||
unless skip?(activity, user) do
|
unless skip?(activity, user) do
|
||||||
notification = %Notification{user_id: user.id, activity: activity}
|
notification = %Notification{user_id: user.id, activity: activity}
|
||||||
{:ok, notification} = Repo.insert(notification)
|
{:ok, notification} = Repo.insert(notification)
|
||||||
|
|
||||||
["user", "user:notification"]
|
if do_send do
|
||||||
|> Streamer.stream(notification)
|
Streamer.stream(["user", "user:notification"], notification)
|
||||||
|
Push.send(notification)
|
||||||
|
end
|
||||||
|
|
||||||
Push.send(notification)
|
|
||||||
notification
|
notification
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns a tuple with 2 elements:
|
||||||
|
{enabled notification receivers, currently disabled receivers (blocking / [thread] muting)}
|
||||||
|
|
||||||
|
NOTE: might be called for FAKE Activities, see ActivityPub.Utils.get_notified_from_object/1
|
||||||
|
"""
|
||||||
def get_notified_from_activity(activity, local_only \\ true)
|
def get_notified_from_activity(activity, local_only \\ true)
|
||||||
|
|
||||||
def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only)
|
def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only)
|
||||||
when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do
|
when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do
|
||||||
[]
|
potential_receiver_ap_ids =
|
||||||
|> Utils.maybe_notify_to_recipients(activity)
|
[]
|
||||||
|> Utils.maybe_notify_mentioned_recipients(activity)
|
|> Utils.maybe_notify_to_recipients(activity)
|
||||||
|> Utils.maybe_notify_subscribers(activity)
|
|> Utils.maybe_notify_mentioned_recipients(activity)
|
||||||
|> Utils.maybe_notify_followers(activity)
|
|> Utils.maybe_notify_subscribers(activity)
|
||||||
|> Enum.uniq()
|
|> Utils.maybe_notify_followers(activity)
|
||||||
|> User.get_users_from_set(local_only)
|
|> Enum.uniq()
|
||||||
|
|
||||||
|
# Since even subscribers and followers can mute / thread-mute, filtering all above AP IDs
|
||||||
|
notification_enabled_ap_ids =
|
||||||
|
potential_receiver_ap_ids
|
||||||
|
|> exclude_relationship_restricted_ap_ids(activity)
|
||||||
|
|> exclude_thread_muter_ap_ids(activity)
|
||||||
|
|
||||||
|
potential_receivers =
|
||||||
|
potential_receiver_ap_ids
|
||||||
|
|> Enum.uniq()
|
||||||
|
|> User.get_users_from_set(local_only)
|
||||||
|
|
||||||
|
notification_enabled_users =
|
||||||
|
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
|
||||||
|
|
||||||
|
{notification_enabled_users, potential_receivers -- notification_enabled_users}
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_notified_from_activity(_, _local_only), do: []
|
def get_notified_from_activity(_, _local_only), do: {[], []}
|
||||||
|
|
||||||
|
@doc "Filters out AP IDs of users basing on their relationships with activity actor user"
|
||||||
|
def exclude_relationship_restricted_ap_ids([], _activity), do: []
|
||||||
|
|
||||||
|
def exclude_relationship_restricted_ap_ids(ap_ids, %Activity{} = activity) do
|
||||||
|
relationship_restricted_ap_ids =
|
||||||
|
activity
|
||||||
|
|> Activity.user_actor()
|
||||||
|
|> User.incoming_relationships_ungrouped_ap_ids([
|
||||||
|
:block,
|
||||||
|
:notification_mute
|
||||||
|
])
|
||||||
|
|
||||||
|
Enum.uniq(ap_ids) -- relationship_restricted_ap_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "Filters out AP IDs of users who mute activity thread"
|
||||||
|
def exclude_thread_muter_ap_ids([], _activity), do: []
|
||||||
|
|
||||||
|
def exclude_thread_muter_ap_ids(ap_ids, %Activity{} = activity) do
|
||||||
|
thread_muter_ap_ids = ThreadMute.muter_ap_ids(activity.data["context"])
|
||||||
|
|
||||||
|
Enum.uniq(ap_ids) -- thread_muter_ap_ids
|
||||||
|
end
|
||||||
|
|
||||||
@spec skip?(Activity.t(), User.t()) :: boolean()
|
@spec skip?(Activity.t(), User.t()) :: boolean()
|
||||||
def skip?(activity, user) do
|
def skip?(%Activity{} = activity, %User{} = user) do
|
||||||
[
|
[
|
||||||
:self,
|
:self,
|
||||||
:followers,
|
:followers,
|
||||||
@ -344,18 +399,20 @@ defmodule Pleroma.Notification do
|
|||||||
:non_follows,
|
:non_follows,
|
||||||
:recently_followed
|
:recently_followed
|
||||||
]
|
]
|
||||||
|> Enum.any?(&skip?(&1, activity, user))
|
|> Enum.find(&skip?(&1, activity, user))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def skip?(_, _), do: false
|
||||||
|
|
||||||
@spec skip?(atom(), Activity.t(), User.t()) :: boolean()
|
@spec skip?(atom(), Activity.t(), User.t()) :: boolean()
|
||||||
def skip?(:self, activity, user) do
|
def skip?(:self, %Activity{} = activity, %User{} = user) do
|
||||||
activity.data["actor"] == user.ap_id
|
activity.data["actor"] == user.ap_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def skip?(
|
def skip?(
|
||||||
:followers,
|
:followers,
|
||||||
activity,
|
%Activity{} = activity,
|
||||||
%{notification_settings: %{followers: false}} = user
|
%User{notification_settings: %{followers: false}} = user
|
||||||
) do
|
) do
|
||||||
actor = activity.data["actor"]
|
actor = activity.data["actor"]
|
||||||
follower = User.get_cached_by_ap_id(actor)
|
follower = User.get_cached_by_ap_id(actor)
|
||||||
@ -364,15 +421,19 @@ defmodule Pleroma.Notification do
|
|||||||
|
|
||||||
def skip?(
|
def skip?(
|
||||||
:non_followers,
|
:non_followers,
|
||||||
activity,
|
%Activity{} = activity,
|
||||||
%{notification_settings: %{non_followers: false}} = user
|
%User{notification_settings: %{non_followers: false}} = user
|
||||||
) do
|
) do
|
||||||
actor = activity.data["actor"]
|
actor = activity.data["actor"]
|
||||||
follower = User.get_cached_by_ap_id(actor)
|
follower = User.get_cached_by_ap_id(actor)
|
||||||
!User.following?(follower, user)
|
!User.following?(follower, user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def skip?(:follows, activity, %{notification_settings: %{follows: false}} = user) do
|
def skip?(
|
||||||
|
:follows,
|
||||||
|
%Activity{} = activity,
|
||||||
|
%User{notification_settings: %{follows: false}} = user
|
||||||
|
) do
|
||||||
actor = activity.data["actor"]
|
actor = activity.data["actor"]
|
||||||
followed = User.get_cached_by_ap_id(actor)
|
followed = User.get_cached_by_ap_id(actor)
|
||||||
User.following?(user, followed)
|
User.following?(user, followed)
|
||||||
@ -380,15 +441,16 @@ defmodule Pleroma.Notification do
|
|||||||
|
|
||||||
def skip?(
|
def skip?(
|
||||||
:non_follows,
|
:non_follows,
|
||||||
activity,
|
%Activity{} = activity,
|
||||||
%{notification_settings: %{non_follows: false}} = user
|
%User{notification_settings: %{non_follows: false}} = user
|
||||||
) do
|
) do
|
||||||
actor = activity.data["actor"]
|
actor = activity.data["actor"]
|
||||||
followed = User.get_cached_by_ap_id(actor)
|
followed = User.get_cached_by_ap_id(actor)
|
||||||
!User.following?(user, followed)
|
!User.following?(user, followed)
|
||||||
end
|
end
|
||||||
|
|
||||||
def skip?(:recently_followed, %{data: %{"type" => "Follow"}} = activity, user) do
|
# To do: consider defining recency in hours and checking FollowingRelationship with a single SQL
|
||||||
|
def skip?(:recently_followed, %Activity{data: %{"type" => "Follow"}} = activity, %User{} = user) do
|
||||||
actor = activity.data["actor"]
|
actor = activity.data["actor"]
|
||||||
|
|
||||||
Notification.for_user(user)
|
Notification.for_user(user)
|
||||||
|
@ -9,7 +9,8 @@ defmodule Pleroma.ThreadMute do
|
|||||||
alias Pleroma.ThreadMute
|
alias Pleroma.ThreadMute
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
require Ecto.Query
|
import Ecto.Changeset
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
schema "thread_mutes" do
|
schema "thread_mutes" do
|
||||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||||
@ -18,19 +19,44 @@ defmodule Pleroma.ThreadMute do
|
|||||||
|
|
||||||
def changeset(mute, params \\ %{}) do
|
def changeset(mute, params \\ %{}) do
|
||||||
mute
|
mute
|
||||||
|> Ecto.Changeset.cast(params, [:user_id, :context])
|
|> cast(params, [:user_id, :context])
|
||||||
|> Ecto.Changeset.foreign_key_constraint(:user_id)
|
|> foreign_key_constraint(:user_id)
|
||||||
|> Ecto.Changeset.unique_constraint(:user_id, name: :unique_index)
|
|> unique_constraint(:user_id, name: :unique_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
def query(user_id, context) do
|
def query(user_id, context) do
|
||||||
{:ok, user_id} = FlakeId.Ecto.CompatType.dump(user_id)
|
{:ok, user_id} = FlakeId.Ecto.CompatType.dump(user_id)
|
||||||
|
|
||||||
ThreadMute
|
ThreadMute
|
||||||
|> Ecto.Query.where(user_id: ^user_id)
|
|> where(user_id: ^user_id)
|
||||||
|> Ecto.Query.where(context: ^context)
|
|> where(context: ^context)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def muters_query(context) do
|
||||||
|
ThreadMute
|
||||||
|
|> join(:inner, [tm], u in assoc(tm, :user))
|
||||||
|
|> where([tm], tm.context == ^context)
|
||||||
|
|> select([tm, u], u.ap_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def muter_ap_ids(context, ap_ids \\ nil)
|
||||||
|
|
||||||
|
# Note: applies to fake activities (ActivityPub.Utils.get_notified_from_object/1 etc.)
|
||||||
|
def muter_ap_ids(context, _ap_ids) when is_nil(context), do: []
|
||||||
|
|
||||||
|
def muter_ap_ids(context, ap_ids) do
|
||||||
|
context
|
||||||
|
|> muters_query()
|
||||||
|
|> maybe_filter_on_ap_id(ap_ids)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_filter_on_ap_id(query, ap_ids) when is_list(ap_ids) do
|
||||||
|
where(query, [tm, u], u.ap_id in ^ap_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_filter_on_ap_id(query, _ap_ids), do: query
|
||||||
|
|
||||||
def add_mute(user_id, context) do
|
def add_mute(user_id, context) do
|
||||||
%ThreadMute{}
|
%ThreadMute{}
|
||||||
|> changeset(%{user_id: user_id, context: context})
|
|> changeset(%{user_id: user_id, context: context})
|
||||||
|
@ -16,6 +16,7 @@ defmodule Pleroma.User do
|
|||||||
alias Pleroma.Conversation.Participation
|
alias Pleroma.Conversation.Participation
|
||||||
alias Pleroma.Delivery
|
alias Pleroma.Delivery
|
||||||
alias Pleroma.FollowingRelationship
|
alias Pleroma.FollowingRelationship
|
||||||
|
alias Pleroma.Formatter
|
||||||
alias Pleroma.HTML
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Keys
|
alias Pleroma.Keys
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
@ -150,22 +151,26 @@ defmodule Pleroma.User do
|
|||||||
{outgoing_relation, outgoing_relation_target},
|
{outgoing_relation, outgoing_relation_target},
|
||||||
{incoming_relation, incoming_relation_source}
|
{incoming_relation, incoming_relation_source}
|
||||||
]} <- @user_relationships_config do
|
]} <- @user_relationships_config do
|
||||||
# Definitions of `has_many :blocker_blocks`, `has_many :muter_mutes` etc.
|
# Definitions of `has_many` relations: :blocker_blocks, :muter_mutes, :reblog_muter_mutes,
|
||||||
|
# :notification_muter_mutes, :subscribee_subscriptions
|
||||||
has_many(outgoing_relation, UserRelationship,
|
has_many(outgoing_relation, UserRelationship,
|
||||||
foreign_key: :source_id,
|
foreign_key: :source_id,
|
||||||
where: [relationship_type: relationship_type]
|
where: [relationship_type: relationship_type]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Definitions of `has_many :blockee_blocks`, `has_many :mutee_mutes` etc.
|
# Definitions of `has_many` relations: :blockee_blocks, :mutee_mutes, :reblog_mutee_mutes,
|
||||||
|
# :notification_mutee_mutes, :subscriber_subscriptions
|
||||||
has_many(incoming_relation, UserRelationship,
|
has_many(incoming_relation, UserRelationship,
|
||||||
foreign_key: :target_id,
|
foreign_key: :target_id,
|
||||||
where: [relationship_type: relationship_type]
|
where: [relationship_type: relationship_type]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Definitions of `has_many :blocked_users`, `has_many :muted_users` etc.
|
# Definitions of `has_many` relations: :blocked_users, :muted_users, :reblog_muted_users,
|
||||||
|
# :notification_muted_users, :subscriber_users
|
||||||
has_many(outgoing_relation_target, through: [outgoing_relation, :target])
|
has_many(outgoing_relation_target, through: [outgoing_relation, :target])
|
||||||
|
|
||||||
# Definitions of `has_many :blocker_users`, `has_many :muter_users` etc.
|
# Definitions of `has_many` relations: :blocker_users, :muter_users, :reblog_muter_users,
|
||||||
|
# :notification_muter_users, :subscribee_users
|
||||||
has_many(incoming_relation_source, through: [incoming_relation, :source])
|
has_many(incoming_relation_source, through: [incoming_relation, :source])
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -185,7 +190,9 @@ defmodule Pleroma.User do
|
|||||||
|
|
||||||
for {_relationship_type, [{_outgoing_relation, outgoing_relation_target}, _]} <-
|
for {_relationship_type, [{_outgoing_relation, outgoing_relation_target}, _]} <-
|
||||||
@user_relationships_config do
|
@user_relationships_config do
|
||||||
# Definitions of `blocked_users_relation/1`, `muted_users_relation/1`, etc.
|
# `def blocked_users_relation/2`, `def muted_users_relation/2`,
|
||||||
|
# `def reblog_muted_users_relation/2`, `def notification_muted_users/2`,
|
||||||
|
# `def subscriber_users/2`
|
||||||
def unquote(:"#{outgoing_relation_target}_relation")(user, restrict_deactivated? \\ false) do
|
def unquote(:"#{outgoing_relation_target}_relation")(user, restrict_deactivated? \\ false) do
|
||||||
target_users_query = assoc(user, unquote(outgoing_relation_target))
|
target_users_query = assoc(user, unquote(outgoing_relation_target))
|
||||||
|
|
||||||
@ -196,7 +203,8 @@ defmodule Pleroma.User do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Definitions of `blocked_users/1`, `muted_users/1`, etc.
|
# `def blocked_users/2`, `def muted_users/2`, `def reblog_muted_users/2`,
|
||||||
|
# `def notification_muted_users/2`, `def subscriber_users/2`
|
||||||
def unquote(outgoing_relation_target)(user, restrict_deactivated? \\ false) do
|
def unquote(outgoing_relation_target)(user, restrict_deactivated? \\ false) do
|
||||||
__MODULE__
|
__MODULE__
|
||||||
|> apply(unquote(:"#{outgoing_relation_target}_relation"), [
|
|> apply(unquote(:"#{outgoing_relation_target}_relation"), [
|
||||||
@ -206,7 +214,8 @@ defmodule Pleroma.User do
|
|||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
# Definitions of `blocked_users_ap_ids/1`, `muted_users_ap_ids/1`, etc.
|
# `def blocked_users_ap_ids/2`, `def muted_users_ap_ids/2`, `def reblog_muted_users_ap_ids/2`,
|
||||||
|
# `def notification_muted_users_ap_ids/2`, `def subscriber_users_ap_ids/2`
|
||||||
def unquote(:"#{outgoing_relation_target}_ap_ids")(user, restrict_deactivated? \\ false) do
|
def unquote(:"#{outgoing_relation_target}_ap_ids")(user, restrict_deactivated? \\ false) do
|
||||||
__MODULE__
|
__MODULE__
|
||||||
|> apply(unquote(:"#{outgoing_relation_target}_relation"), [
|
|> apply(unquote(:"#{outgoing_relation_target}_relation"), [
|
||||||
@ -268,16 +277,12 @@ defmodule Pleroma.User do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def profile_url(%User{source_data: %{"url" => url}}), do: url
|
|
||||||
def profile_url(%User{ap_id: ap_id}), do: ap_id
|
|
||||||
def profile_url(_), do: nil
|
|
||||||
|
|
||||||
def ap_id(%User{nickname: nickname}), do: "#{Web.base_url()}/users/#{nickname}"
|
def ap_id(%User{nickname: nickname}), do: "#{Web.base_url()}/users/#{nickname}"
|
||||||
|
|
||||||
def ap_followers(%User{follower_address: fa}) when is_binary(fa), do: fa
|
def ap_followers(%User{follower_address: fa}) when is_binary(fa), do: fa
|
||||||
def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers"
|
def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers"
|
||||||
|
|
||||||
@spec ap_following(User.t()) :: Sring.t()
|
@spec ap_following(User.t()) :: String.t()
|
||||||
def ap_following(%User{following_address: fa}) when is_binary(fa), do: fa
|
def ap_following(%User{following_address: fa}) when is_binary(fa), do: fa
|
||||||
def ap_following(%User{} = user), do: "#{ap_id(user)}/following"
|
def ap_following(%User{} = user), do: "#{ap_id(user)}/following"
|
||||||
|
|
||||||
@ -417,9 +422,61 @@ defmodule Pleroma.User do
|
|||||||
|> validate_format(:nickname, local_nickname_regex())
|
|> validate_format(:nickname, local_nickname_regex())
|
||||||
|> validate_length(:bio, max: bio_limit)
|
|> validate_length(:bio, max: bio_limit)
|
||||||
|> validate_length(:name, min: 1, max: name_limit)
|
|> validate_length(:name, min: 1, max: name_limit)
|
||||||
|
|> put_fields()
|
||||||
|
|> put_change_if_present(:bio, &{:ok, parse_bio(&1, struct)})
|
||||||
|
|> put_change_if_present(:avatar, &put_upload(&1, :avatar))
|
||||||
|
|> put_change_if_present(:banner, &put_upload(&1, :banner))
|
||||||
|
|> put_change_if_present(:background, &put_upload(&1, :background))
|
||||||
|
|> put_change_if_present(
|
||||||
|
:pleroma_settings_store,
|
||||||
|
&{:ok, Map.merge(struct.pleroma_settings_store, &1)}
|
||||||
|
)
|
||||||
|> validate_fields(false)
|
|> validate_fields(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp put_fields(changeset) do
|
||||||
|
if raw_fields = get_change(changeset, :raw_fields) do
|
||||||
|
raw_fields =
|
||||||
|
raw_fields
|
||||||
|
|> Enum.filter(fn %{"name" => n} -> n != "" end)
|
||||||
|
|
||||||
|
fields =
|
||||||
|
raw_fields
|
||||||
|
|> Enum.map(fn f -> Map.update!(f, "value", &parse_fields(&1)) end)
|
||||||
|
|
||||||
|
changeset
|
||||||
|
|> put_change(:raw_fields, raw_fields)
|
||||||
|
|> put_change(:fields, fields)
|
||||||
|
else
|
||||||
|
changeset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_fields(value) do
|
||||||
|
value
|
||||||
|
|> Formatter.linkify(mentions_format: :full)
|
||||||
|
|> elem(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp put_change_if_present(changeset, map_field, value_function) do
|
||||||
|
if value = get_change(changeset, map_field) do
|
||||||
|
with {:ok, new_value} <- value_function.(value) do
|
||||||
|
put_change(changeset, map_field, new_value)
|
||||||
|
else
|
||||||
|
_ -> changeset
|
||||||
|
end
|
||||||
|
else
|
||||||
|
changeset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp put_upload(value, type) do
|
||||||
|
with %Plug.Upload{} <- value,
|
||||||
|
{:ok, object} <- ActivityPub.upload(value, type: type) do
|
||||||
|
{:ok, object.data}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do
|
def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do
|
||||||
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
|
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
|
||||||
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
|
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
|
||||||
@ -463,6 +520,27 @@ defmodule Pleroma.User do
|
|||||||
|> validate_fields(remote?)
|
|> validate_fields(remote?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_as_admin_changeset(struct, params) do
|
||||||
|
struct
|
||||||
|
|> update_changeset(params)
|
||||||
|
|> cast(params, [:email])
|
||||||
|
|> delete_change(:also_known_as)
|
||||||
|
|> unique_constraint(:email)
|
||||||
|
|> validate_format(:email, @email_regex)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec update_as_admin(%User{}, map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||||
|
def update_as_admin(user, params) do
|
||||||
|
params = Map.put(params, "password_confirmation", params["password"])
|
||||||
|
changeset = update_as_admin_changeset(user, params)
|
||||||
|
|
||||||
|
if params["password"] do
|
||||||
|
reset_password(user, changeset, params)
|
||||||
|
else
|
||||||
|
User.update_and_set_cache(changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def password_update_changeset(struct, params) do
|
def password_update_changeset(struct, params) do
|
||||||
struct
|
struct
|
||||||
|> cast(params, [:password, :password_confirmation])
|
|> cast(params, [:password, :password_confirmation])
|
||||||
@ -473,10 +551,14 @@ defmodule Pleroma.User do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@spec reset_password(User.t(), map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
@spec reset_password(User.t(), map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||||
def reset_password(%User{id: user_id} = user, data) do
|
def reset_password(%User{} = user, params) do
|
||||||
|
reset_password(user, user, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_password(%User{id: user_id} = user, struct, params) do
|
||||||
multi =
|
multi =
|
||||||
Multi.new()
|
Multi.new()
|
||||||
|> Multi.update(:user, password_update_changeset(user, data))
|
|> Multi.update(:user, password_update_changeset(struct, params))
|
||||||
|> Multi.delete_all(:tokens, OAuth.Token.Query.get_by_user(user_id))
|
|> Multi.delete_all(:tokens, OAuth.Token.Query.get_by_user(user_id))
|
||||||
|> Multi.delete_all(:auth, OAuth.Authorization.delete_by_user_query(user))
|
|> Multi.delete_all(:auth, OAuth.Authorization.delete_by_user_query(user))
|
||||||
|
|
||||||
@ -1214,13 +1296,15 @@ defmodule Pleroma.User do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns map of outgoing (blocked, muted etc.) relations' user AP IDs by relation type.
|
Returns map of outgoing (blocked, muted etc.) relationships' user AP IDs by relation type.
|
||||||
E.g. `outgoing_relations_ap_ids(user, [:block])` -> `%{block: ["https://some.site/users/userapid"]}`
|
E.g. `outgoing_relationships_ap_ids(user, [:block])` -> `%{block: ["https://some.site/users/userapid"]}`
|
||||||
"""
|
"""
|
||||||
@spec outgoing_relations_ap_ids(User.t(), list(atom())) :: %{atom() => list(String.t())}
|
@spec outgoing_relationships_ap_ids(User.t(), list(atom())) :: %{atom() => list(String.t())}
|
||||||
def outgoing_relations_ap_ids(_, []), do: %{}
|
def outgoing_relationships_ap_ids(_user, []), do: %{}
|
||||||
|
|
||||||
def outgoing_relations_ap_ids(%User{} = user, relationship_types)
|
def outgoing_relationships_ap_ids(nil, _relationship_types), do: %{}
|
||||||
|
|
||||||
|
def outgoing_relationships_ap_ids(%User{} = user, relationship_types)
|
||||||
when is_list(relationship_types) do
|
when is_list(relationship_types) do
|
||||||
db_result =
|
db_result =
|
||||||
user
|
user
|
||||||
@ -1239,6 +1323,30 @@ defmodule Pleroma.User do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def incoming_relationships_ungrouped_ap_ids(user, relationship_types, ap_ids \\ nil)
|
||||||
|
|
||||||
|
def incoming_relationships_ungrouped_ap_ids(_user, [], _ap_ids), do: []
|
||||||
|
|
||||||
|
def incoming_relationships_ungrouped_ap_ids(nil, _relationship_types, _ap_ids), do: []
|
||||||
|
|
||||||
|
def incoming_relationships_ungrouped_ap_ids(%User{} = user, relationship_types, ap_ids)
|
||||||
|
when is_list(relationship_types) do
|
||||||
|
user
|
||||||
|
|> assoc(:incoming_relationships)
|
||||||
|
|> join(:inner, [user_rel], u in assoc(user_rel, :source))
|
||||||
|
|> where([user_rel, u], user_rel.relationship_type in ^relationship_types)
|
||||||
|
|> maybe_filter_on_ap_id(ap_ids)
|
||||||
|
|> select([user_rel, u], u.ap_id)
|
||||||
|
|> distinct(true)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_filter_on_ap_id(query, ap_ids) when is_list(ap_ids) do
|
||||||
|
where(query, [user_rel, u], u.ap_id in ^ap_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_filter_on_ap_id(query, _ap_ids), do: query
|
||||||
|
|
||||||
def deactivate_async(user, status \\ true) do
|
def deactivate_async(user, status \\ true) do
|
||||||
BackgroundWorker.enqueue("deactivate_user", %{"user_id" => user.id, "status" => status})
|
BackgroundWorker.enqueue("deactivate_user", %{"user_id" => user.id, "status" => status})
|
||||||
end
|
end
|
||||||
|
@ -21,15 +21,18 @@ defmodule Pleroma.UserRelationship do
|
|||||||
end
|
end
|
||||||
|
|
||||||
for relationship_type <- Keyword.keys(UserRelationshipTypeEnum.__enum_map__()) do
|
for relationship_type <- Keyword.keys(UserRelationshipTypeEnum.__enum_map__()) do
|
||||||
# Definitions of `create_block/2`, `create_mute/2` etc.
|
# `def create_block/2`, `def create_mute/2`, `def create_reblog_mute/2`,
|
||||||
|
# `def create_notification_mute/2`, `def create_inverse_subscription/2`
|
||||||
def unquote(:"create_#{relationship_type}")(source, target),
|
def unquote(:"create_#{relationship_type}")(source, target),
|
||||||
do: create(unquote(relationship_type), source, target)
|
do: create(unquote(relationship_type), source, target)
|
||||||
|
|
||||||
# Definitions of `delete_block/2`, `delete_mute/2` etc.
|
# `def delete_block/2`, `def delete_mute/2`, `def delete_reblog_mute/2`,
|
||||||
|
# `def delete_notification_mute/2`, `def delete_inverse_subscription/2`
|
||||||
def unquote(:"delete_#{relationship_type}")(source, target),
|
def unquote(:"delete_#{relationship_type}")(source, target),
|
||||||
do: delete(unquote(relationship_type), source, target)
|
do: delete(unquote(relationship_type), source, target)
|
||||||
|
|
||||||
# Definitions of `block_exists?/2`, `mute_exists?/2` etc.
|
# `def block_exists?/2`, `def mute_exists?/2`, `def reblog_mute_exists?/2`,
|
||||||
|
# `def notification_mute_exists?/2`, `def inverse_subscription_exists?/2`
|
||||||
def unquote(:"#{relationship_type}_exists?")(source, target),
|
def unquote(:"#{relationship_type}_exists?")(source, target),
|
||||||
do: exists?(unquote(relationship_type), source, target)
|
do: exists?(unquote(relationship_type), source, target)
|
||||||
end
|
end
|
||||||
|
@ -584,6 +584,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp do_delete(%Object{data: %{"type" => "Tombstone", "id" => ap_id}}, _) do
|
||||||
|
activity =
|
||||||
|
ap_id
|
||||||
|
|> Activity.Queries.by_object_id()
|
||||||
|
|> Activity.Queries.by_type("Delete")
|
||||||
|
|> Repo.one()
|
||||||
|
|
||||||
|
{:ok, activity}
|
||||||
|
end
|
||||||
|
|
||||||
@spec block(User.t(), User.t(), String.t() | nil, boolean()) ::
|
@spec block(User.t(), User.t(), String.t() | nil, boolean()) ::
|
||||||
{:ok, Activity.t()} | {:error, any()}
|
{:ok, Activity.t()} | {:error, any()}
|
||||||
def block(blocker, blocked, activity_id \\ nil, local \\ true) do
|
def block(blocker, blocked, activity_id \\ nil, local \\ true) do
|
||||||
@ -1230,17 +1240,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||||||
|
|
||||||
defp fetch_activities_query_ap_ids_ops(opts) do
|
defp fetch_activities_query_ap_ids_ops(opts) do
|
||||||
source_user = opts["muting_user"]
|
source_user = opts["muting_user"]
|
||||||
ap_id_relations = if source_user, do: [:mute, :reblog_mute], else: []
|
ap_id_relationships = if source_user, do: [:mute, :reblog_mute], else: []
|
||||||
|
|
||||||
ap_id_relations =
|
ap_id_relationships =
|
||||||
ap_id_relations ++
|
ap_id_relationships ++
|
||||||
if opts["blocking_user"] && opts["blocking_user"] == source_user do
|
if opts["blocking_user"] && opts["blocking_user"] == source_user do
|
||||||
[:block]
|
[:block]
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
preloaded_ap_ids = User.outgoing_relations_ap_ids(source_user, ap_id_relations)
|
preloaded_ap_ids = User.outgoing_relationships_ap_ids(source_user, ap_id_relationships)
|
||||||
|
|
||||||
restrict_blocked_opts = Map.merge(%{"blocked_users_ap_ids" => preloaded_ap_ids[:block]}, opts)
|
restrict_blocked_opts = Map.merge(%{"blocked_users_ap_ids" => preloaded_ap_ids[:block]}, opts)
|
||||||
restrict_muted_opts = Map.merge(%{"muted_users_ap_ids" => preloaded_ap_ids[:mute]}, opts)
|
restrict_muted_opts = Map.merge(%{"muted_users_ap_ids" => preloaded_ap_ids[:mute]}, opts)
|
||||||
@ -1370,6 +1380,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_actor_url(any()) :: binary() | nil
|
||||||
|
defp get_actor_url(url) when is_binary(url), do: url
|
||||||
|
defp get_actor_url(%{"href" => href}) when is_binary(href), do: href
|
||||||
|
|
||||||
|
defp get_actor_url(url) when is_list(url) do
|
||||||
|
url
|
||||||
|
|> List.first()
|
||||||
|
|> get_actor_url()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_actor_url(_url), do: nil
|
||||||
|
|
||||||
defp object_to_user_data(data) do
|
defp object_to_user_data(data) do
|
||||||
avatar =
|
avatar =
|
||||||
data["icon"]["url"] &&
|
data["icon"]["url"] &&
|
||||||
@ -1399,6 +1421,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||||||
|
|
||||||
user_data = %{
|
user_data = %{
|
||||||
ap_id: data["id"],
|
ap_id: data["id"],
|
||||||
|
uri: get_actor_url(data["url"]),
|
||||||
ap_enabled: true,
|
ap_enabled: true,
|
||||||
source_data: data,
|
source_data: data,
|
||||||
banner: banner,
|
banner: banner,
|
||||||
|
@ -229,7 +229,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
Map.put(object, "url", url["href"])
|
Map.put(object, "url", url["href"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do
|
def fix_url(%{"type" => object_type, "url" => url} = object)
|
||||||
|
when object_type in ["Video", "Audio"] and is_list(url) do
|
||||||
first_element = Enum.at(url, 0)
|
first_element = Enum.at(url, 0)
|
||||||
|
|
||||||
link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
|
link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
|
||||||
@ -398,7 +399,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
%{"type" => "Create", "object" => %{"type" => objtype} = object} = data,
|
%{"type" => "Create", "object" => %{"type" => objtype} = object} = data,
|
||||||
options
|
options
|
||||||
)
|
)
|
||||||
when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer"] do
|
when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer", "Audio"] do
|
||||||
actor = Containment.get_actor(data)
|
actor = Containment.get_actor(data)
|
||||||
|
|
||||||
data =
|
data =
|
||||||
@ -1108,13 +1109,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_mention_tags(object) do
|
def add_mention_tags(object) do
|
||||||
mentions =
|
{enabled_receivers, disabled_receivers} = Utils.get_notified_from_object(object)
|
||||||
object
|
potential_receivers = enabled_receivers ++ disabled_receivers
|
||||||
|> Utils.get_notified_from_object()
|
mentions = Enum.map(potential_receivers, &build_mention_tag/1)
|
||||||
|> Enum.map(&build_mention_tag/1)
|
|
||||||
|
|
||||||
tags = object["tag"] || []
|
tags = object["tag"] || []
|
||||||
|
|
||||||
Map.put(object, "tag", tags ++ mentions)
|
Map.put(object, "tag", tags ++ mentions)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["read:accounts"], admin: true}
|
%{scopes: ["read:accounts"], admin: true}
|
||||||
when action in [:list_users, :user_show, :right_get]
|
when action in [:list_users, :user_show, :right_get, :show_user_credentials]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
@ -54,7 +54,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||||||
:tag_users,
|
:tag_users,
|
||||||
:untag_users,
|
:untag_users,
|
||||||
:right_add,
|
:right_add,
|
||||||
:right_delete
|
:right_delete,
|
||||||
|
:update_user_credentials
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -658,6 +659,52 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||||||
json_response(conn, :no_content, "")
|
json_response(conn, :no_content, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "Show a given user's credentials"
|
||||||
|
def show_user_credentials(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
|
||||||
|
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
|
||||||
|
conn
|
||||||
|
|> put_view(AccountView)
|
||||||
|
|> render("credentials.json", %{user: user, for: admin})
|
||||||
|
else
|
||||||
|
_ -> {:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "Updates a given user"
|
||||||
|
def update_user_credentials(
|
||||||
|
%{assigns: %{user: admin}} = conn,
|
||||||
|
%{"nickname" => nickname} = params
|
||||||
|
) do
|
||||||
|
with {_, user} <- {:user, User.get_cached_by_nickname(nickname)},
|
||||||
|
{:ok, _user} <-
|
||||||
|
User.update_as_admin(user, params) do
|
||||||
|
ModerationLog.insert_log(%{
|
||||||
|
actor: admin,
|
||||||
|
subject: [user],
|
||||||
|
action: "updated_users"
|
||||||
|
})
|
||||||
|
|
||||||
|
if params["password"] do
|
||||||
|
User.force_password_reset_async(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
ModerationLog.insert_log(%{
|
||||||
|
actor: admin,
|
||||||
|
subject: [user],
|
||||||
|
action: "force_password_reset"
|
||||||
|
})
|
||||||
|
|
||||||
|
json(conn, %{status: "success"})
|
||||||
|
else
|
||||||
|
{:error, changeset} ->
|
||||||
|
{_, {error, _}} = Enum.at(changeset.errors, 0)
|
||||||
|
json(conn, %{error: "New password #{error}."})
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
json(conn, %{error: "Unable to change password."})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def list_reports(conn, params) do
|
def list_reports(conn, params) do
|
||||||
{page, page_size} = page_params(params)
|
{page, page_size} = page_params(params)
|
||||||
|
|
||||||
|
@ -23,6 +23,43 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render("credentials.json", %{user: user, for: for_user}) do
|
||||||
|
user = User.sanitize_html(user, User.html_filter_policy(for_user))
|
||||||
|
avatar = User.avatar_url(user) |> MediaProxy.url()
|
||||||
|
banner = User.banner_url(user) |> MediaProxy.url()
|
||||||
|
background = image_url(user.background) |> MediaProxy.url()
|
||||||
|
|
||||||
|
user
|
||||||
|
|> Map.take([
|
||||||
|
:id,
|
||||||
|
:bio,
|
||||||
|
:email,
|
||||||
|
:fields,
|
||||||
|
:name,
|
||||||
|
:nickname,
|
||||||
|
:locked,
|
||||||
|
:no_rich_text,
|
||||||
|
:default_scope,
|
||||||
|
:hide_follows,
|
||||||
|
:hide_followers_count,
|
||||||
|
:hide_follows_count,
|
||||||
|
:hide_followers,
|
||||||
|
:hide_favorites,
|
||||||
|
:allow_following_move,
|
||||||
|
:show_role,
|
||||||
|
:skip_thread_containment,
|
||||||
|
:pleroma_settings_store,
|
||||||
|
:raw_fields,
|
||||||
|
:discoverable,
|
||||||
|
:actor_type
|
||||||
|
])
|
||||||
|
|> Map.merge(%{
|
||||||
|
"avatar" => avatar,
|
||||||
|
"banner" => banner,
|
||||||
|
"background" => background
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
def render("show.json", %{user: user}) do
|
def render("show.json", %{user: user}) do
|
||||||
avatar = User.avatar_url(user) |> MediaProxy.url()
|
avatar = User.avatar_url(user) |> MediaProxy.url()
|
||||||
display_name = Pleroma.HTML.strip_tags(user.name || user.nickname)
|
display_name = Pleroma.HTML.strip_tags(user.name || user.nickname)
|
||||||
@ -104,4 +141,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
|
|||||||
""
|
""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
||||||
|
defp image_url(_), do: nil
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
import Pleroma.Web.ControllerHelper,
|
import Pleroma.Web.ControllerHelper,
|
||||||
only: [add_link_headers: 2, truthy_param?: 1, assign_account_by_id: 2, json_response: 3]
|
only: [add_link_headers: 2, truthy_param?: 1, assign_account_by_id: 2, json_response: 3]
|
||||||
|
|
||||||
alias Pleroma.Emoji
|
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
@ -63,11 +62,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
when action != :create
|
when action != :create
|
||||||
)
|
)
|
||||||
|
|
||||||
@relations [:follow, :unfollow]
|
@relationship_actions [:follow, :unfollow]
|
||||||
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
|
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
|
||||||
|
|
||||||
plug(RateLimiter, [name: :relations_id_action, params: ["id", "uri"]] when action in @relations)
|
plug(
|
||||||
plug(RateLimiter, [name: :relations_actions] when action in @relations)
|
RateLimiter,
|
||||||
|
[name: :relation_id_action, params: ["id", "uri"]] when action in @relationship_actions
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(RateLimiter, [name: :relations_actions] when action in @relationship_actions)
|
||||||
plug(RateLimiter, [name: :app_account_creation] when action == :create)
|
plug(RateLimiter, [name: :app_account_creation] when action == :create)
|
||||||
plug(:assign_account_by_id when action in @needs_account)
|
plug(:assign_account_by_id when action in @needs_account)
|
||||||
|
|
||||||
@ -140,17 +143,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
||||||
user = original_user
|
user = original_user
|
||||||
|
|
||||||
params =
|
|
||||||
if Map.has_key?(params, "fields_attributes") do
|
|
||||||
Map.update!(params, "fields_attributes", fn fields ->
|
|
||||||
fields
|
|
||||||
|> normalize_fields_attributes()
|
|
||||||
|> Enum.filter(fn %{"name" => n} -> n != "" end)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
params
|
|
||||||
end
|
|
||||||
|
|
||||||
user_params =
|
user_params =
|
||||||
[
|
[
|
||||||
:no_rich_text,
|
:no_rich_text,
|
||||||
@ -169,46 +161,20 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||||||
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
|
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
|
||||||
end)
|
end)
|
||||||
|> add_if_present(params, "display_name", :name)
|
|> add_if_present(params, "display_name", :name)
|
||||||
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
|
|> add_if_present(params, "note", :bio)
|
||||||
|> add_if_present(params, "avatar", :avatar, fn value ->
|
|> add_if_present(params, "avatar", :avatar)
|
||||||
with %Plug.Upload{} <- value,
|
|> add_if_present(params, "header", :banner)
|
||||||
{:ok, object} <- ActivityPub.upload(value, type: :avatar) do
|
|> add_if_present(params, "pleroma_background_image", :background)
|
||||||
{:ok, object.data}
|
|> add_if_present(
|
||||||
end
|
params,
|
||||||
end)
|
"fields_attributes",
|
||||||
|> add_if_present(params, "header", :banner, fn value ->
|
:raw_fields,
|
||||||
with %Plug.Upload{} <- value,
|
&{:ok, normalize_fields_attributes(&1)}
|
||||||
{:ok, object} <- ActivityPub.upload(value, type: :banner) do
|
)
|
||||||
{:ok, object.data}
|
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store)
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "pleroma_background_image", :background, fn value ->
|
|
||||||
with %Plug.Upload{} <- value,
|
|
||||||
{:ok, object} <- ActivityPub.upload(value, type: :background) do
|
|
||||||
{:ok, object.data}
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "fields_attributes", :fields, fn fields ->
|
|
||||||
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
|
||||||
|
|
||||||
{:ok, fields}
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "fields_attributes", :raw_fields)
|
|
||||||
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
|
||||||
{:ok, Map.merge(user.pleroma_settings_store, value)}
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "default_scope", :default_scope)
|
|> add_if_present(params, "default_scope", :default_scope)
|
||||||
|> add_if_present(params, "actor_type", :actor_type)
|
|> add_if_present(params, "actor_type", :actor_type)
|
||||||
|
|
||||||
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
|
|
||||||
|
|
||||||
user_emojis =
|
|
||||||
user
|
|
||||||
|> Map.get(:emoji, [])
|
|
||||||
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|
|
||||||
|> Enum.dedup()
|
|
||||||
|
|
||||||
user_params = Map.put(user_params, :emoji, user_emojis)
|
|
||||||
changeset = User.update_changeset(user, user_params)
|
changeset = User.update_changeset(user, user_params)
|
||||||
|
|
||||||
with {:ok, user} <- User.update_and_set_cache(changeset) do
|
with {:ok, user} <- User.update_and_set_cache(changeset) do
|
||||||
|
@ -27,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||||||
id: to_string(user.id),
|
id: to_string(user.id),
|
||||||
acct: user.nickname,
|
acct: user.nickname,
|
||||||
username: username_from_nickname(user.nickname),
|
username: username_from_nickname(user.nickname),
|
||||||
url: User.profile_url(user)
|
url: user.uri || user.ap_id
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||||||
following_count: following_count,
|
following_count: following_count,
|
||||||
statuses_count: user.note_count,
|
statuses_count: user.note_count,
|
||||||
note: user.bio || "",
|
note: user.bio || "",
|
||||||
url: User.profile_url(user),
|
url: user.uri || user.ap_id,
|
||||||
avatar: image,
|
avatar: image,
|
||||||
avatar_static: image,
|
avatar_static: image,
|
||||||
header: header,
|
header: header,
|
||||||
@ -122,7 +122,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||||||
fields: user.fields,
|
fields: user.fields,
|
||||||
bot: bot,
|
bot: bot,
|
||||||
source: %{
|
source: %{
|
||||||
note: Pleroma.HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
note: (user.bio || "") |> String.replace(~r(<br */?>), "\n") |> Pleroma.HTML.strip_tags(),
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
fields: user.raw_fields,
|
fields: user.raw_fields,
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
|
@ -421,7 +421,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_content(%{data: %{"type" => object_type}} = object)
|
def render_content(%{data: %{"type" => object_type}} = object)
|
||||||
when object_type in ["Video", "Event"] do
|
when object_type in ["Video", "Event", "Audio"] do
|
||||||
with name when not is_nil(name) and name != "" <- object.data["name"] do
|
with name when not is_nil(name) and name != "" <- object.data["name"] do
|
||||||
"<p><a href=\"#{object.data["id"]}\">#{name}</a></p>#{object.data["content"]}"
|
"<p><a href=\"#{object.data["id"]}\">#{name}</a></p>#{object.data["content"]}"
|
||||||
else
|
else
|
||||||
|
@ -68,7 +68,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
|
|||||||
property: "og:title",
|
property: "og:title",
|
||||||
content: Utils.user_name_string(user)
|
content: Utils.user_name_string(user)
|
||||||
], []},
|
], []},
|
||||||
{:meta, [property: "og:url", content: User.profile_url(user)], []},
|
{:meta, [property: "og:url", content: user.uri || user.ap_id], []},
|
||||||
{:meta, [property: "og:description", content: truncated_bio], []},
|
{:meta, [property: "og:description", content: truncated_bio], []},
|
||||||
{:meta, [property: "og:type", content: "website"], []},
|
{:meta, [property: "og:type", content: "website"], []},
|
||||||
{:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))], []},
|
{:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))], []},
|
||||||
|
@ -173,6 +173,8 @@ defmodule Pleroma.Web.Router do
|
|||||||
|
|
||||||
get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset)
|
get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset)
|
||||||
patch("/users/force_password_reset", AdminAPIController, :force_password_reset)
|
patch("/users/force_password_reset", AdminAPIController, :force_password_reset)
|
||||||
|
get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials)
|
||||||
|
patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials)
|
||||||
|
|
||||||
get("/users", AdminAPIController, :list_users)
|
get("/users", AdminAPIController, :list_users)
|
||||||
get("/users/:nickname", AdminAPIController, :user_show)
|
get("/users/:nickname", AdminAPIController, :user_show)
|
||||||
|
@ -130,7 +130,7 @@ defmodule Pleroma.Web.Streamer.Worker do
|
|||||||
|
|
||||||
defp should_send?(%User{} = user, %Activity{} = item) do
|
defp should_send?(%User{} = user, %Activity{} = item) do
|
||||||
%{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
|
%{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
|
||||||
User.outgoing_relations_ap_ids(user, [:block, :mute, :reblog_mute])
|
User.outgoing_relationships_ap_ids(user, [:block, :mute, :reblog_mute])
|
||||||
|
|
||||||
recipient_blocks = MapSet.new(blocked_ap_ids ++ muted_ap_ids)
|
recipient_blocks = MapSet.new(blocked_ap_ids ++ muted_ap_ids)
|
||||||
recipients = MapSet.new(item.recipients)
|
recipients = MapSet.new(item.recipients)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="p-author h-card">
|
<div class="p-author h-card">
|
||||||
<a class="u-url" rel="author noopener" href="<%= User.profile_url(@user) %>">
|
<a class="u-url" rel="author noopener" href="<%= (@user.uri || @user.ap_id) %>">
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<img src="<%= User.avatar_url(@user) |> MediaProxy.url %>" width="48" height="48" alt="">
|
<img src="<%= User.avatar_url(@user) |> MediaProxy.url %>" width="48" height="48" alt="">
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<button type="submit" class="collapse">Remote follow</button>
|
<button type="submit" class="collapse">Remote follow</button>
|
||||||
</form>
|
</form>
|
||||||
<%= raw Formatter.emojify(@user.name, emoji_for_user(@user)) %> |
|
<%= raw Formatter.emojify(@user.name, emoji_for_user(@user)) %> |
|
||||||
<%= link "@#{@user.nickname}@#{Endpoint.host()}", to: User.profile_url(@user) %>
|
<%= link "@#{@user.nickname}@#{Endpoint.host()}", to: (@user.uri || @user.ap_id) %>
|
||||||
</h3>
|
</h3>
|
||||||
<p><%= raw @user.bio %></p>
|
<p><%= raw @user.bio %></p>
|
||||||
</header>
|
</header>
|
||||||
|
4
mix.exs
4
mix.exs
@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
|
|||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :pleroma,
|
app: :pleroma,
|
||||||
version: version("2.0.1"),
|
version: version("2.0.2"),
|
||||||
elixir: "~> 1.8",
|
elixir: "~> 1.8",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||||
@ -63,7 +63,7 @@ defmodule Pleroma.Mixfile do
|
|||||||
def application do
|
def application do
|
||||||
[
|
[
|
||||||
mod: {Pleroma.Application, []},
|
mod: {Pleroma.Application, []},
|
||||||
extra_applications: [:logger, :runtime_tools, :comeonin, :quack, :fast_sanitize],
|
extra_applications: [:logger, :runtime_tools, :comeonin, :quack, :fast_sanitize, :ssl],
|
||||||
included_applications: [:ex_syslogger]
|
included_applications: [:ex_syslogger]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -1 +1 @@
|
|||||||
.select-field[data-v-29abde8c]{width:350px}@media only screen and (max-width:480px){.select-field[data-v-29abde8c]{width:100%;margin-bottom:5px}}@media only screen and (max-width:801px) and (min-width:481px){.select-field[data-v-29abde8c]{width:50%}}.actions-button[data-v-3850612b]{text-align:left;width:350px;padding:10px}.actions-button-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-dropdown[data-v-3850612b]{float:right}.el-icon-edit[data-v-3850612b]{margin-right:5px}.tag-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.tag-text[data-v-3850612b]{padding-right:20px}.no-hover[data-v-3850612b]:hover{color:#606266;background-color:#fff;cursor:auto}.el-dialog__body{padding:20px}.create-account-form-item{margin-bottom:20px}.create-account-form-item-without-margin{margin-bottom:0}@media only screen and (max-width:480px){.create-user-dialog{width:85%}.create-account-form-item{margin-bottom:20px}.el-dialog__body{padding:20px}}.moderate-user-button{text-align:left;width:200px;padding:10px}.moderate-user-button-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.actions-button{text-align:left;width:350px;padding:10px}.actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:0 15px 10px}.active-tag{color:#409eff;font-weight:700}.active-tag .el-icon-check{color:#409eff;float:right;margin:7px 0 0 15px}.el-dropdown-link:hover{cursor:pointer;color:#409eff}.create-account>.el-icon-plus{margin-right:5px}.password-reset-token{margin:0 0 14px}.password-reset-token-dialog{width:50%}.reset-password-link{text-decoration:underline}.users-container h1{margin:22px 0 0 15px}.users-container .pagination{margin:25px 0;text-align:center}.users-container .search{width:350px;float:right}.users-container .filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:22px 15px 15px}.users-container .user-count{color:grey;font-size:28px}@media only screen and (max-width:480px){.password-reset-token-dialog{width:85%}.users-container h1{margin:7px 10px 15px}.users-container .actions-button{width:100%}.users-container .actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 10px 7px}.users-container .el-icon-arrow-down{font-size:12px}.users-container .search{width:100%}.users-container .filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 10px}.users-container .el-tag{width:30px;display:inline-block;margin-bottom:4px;font-weight:700}.users-container .el-tag.el-tag--danger,.users-container .el-tag.el-tag--success{padding-left:8px}}
|
.select-field[data-v-29abde8c]{width:350px}@media only screen and (max-width:480px){.select-field[data-v-29abde8c]{width:100%;margin-bottom:5px}}@media only screen and (max-width:801px) and (min-width:481px){.select-field[data-v-29abde8c]{width:50%}}.actions-button[data-v-3850612b]{text-align:left;width:350px;padding:10px}.actions-button-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-dropdown[data-v-3850612b]{float:right}.el-icon-edit[data-v-3850612b]{margin-right:5px}.tag-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.tag-text[data-v-3850612b]{padding-right:20px}.no-hover[data-v-3850612b]:hover{color:#606266;background-color:#fff;cursor:auto}.el-dialog__body{padding:20px}.create-account-form-item{margin-bottom:20px}.create-account-form-item-without-margin{margin-bottom:0}@media only screen and (max-width:480px){.create-user-dialog{width:85%}.create-account-form-item{margin-bottom:20px}.el-dialog__body{padding:20px}}.moderate-user-button{text-align:left;width:200px;padding:10px}.moderate-user-button-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.actions-button{text-align:left;width:350px;padding:10px}.actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:0 15px 10px}.active-tag{color:#409eff;font-weight:700}.active-tag .el-icon-check{color:#409eff;float:right;margin:7px 0 0 15px}.el-dropdown-link:hover{cursor:pointer;color:#409eff}.create-account>.el-icon-plus{margin-right:5px}.password-reset-token{margin:0 0 14px}.password-reset-token-dialog{width:50%}.reset-password-link{text-decoration:underline}.users-container h1{margin:10px 0 0 15px}.users-container .pagination{margin:25px 0;text-align:center}.users-container .search{width:350px;float:right}.users-container .filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:22px 15px 15px}.users-container .user-count{color:grey;font-size:28px}@media only screen and (max-width:480px){.password-reset-token-dialog{width:85%}.users-container h1{margin:7px 10px 15px}.users-container .actions-button{width:100%}.users-container .actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 10px 7px}.users-container .el-icon-arrow-down{font-size:12px}.users-container .search{width:100%}.users-container .filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 10px}.users-container .el-tag{width:30px;display:inline-block;margin-bottom:4px;font-weight:700}.users-container .el-tag.el-tag--danger,.users-container .el-tag.el-tag--success{padding-left:8px}}
|
@ -1 +1 @@
|
|||||||
.copy-popover{width:330px}.emoji-buttons{place-self:center;min-width:200px}.emoji-container-grid{display:grid;grid-template-columns:75px auto auto 200px;grid-column-gap:15px;margin-bottom:10px}.emoji-preview-img{max-width:100%;place-self:center}.emoji-info{place-self:center}.copy-pack-container{place-self:center stretch}.copy-pack-select{width:100%}.remote-emoji-container-grid{display:grid;grid-template-columns:75px auto auto 160px;grid-column-gap:15px;margin-bottom:10px}@media only screen and (max-width:480px){.emoji-container-flex{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border:1px solid #dcdfe6;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:4px;padding:15px;margin:0 15px 15px 0}.emoji-info,.emoji-preview-img{margin-bottom:10px}.emoji-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:100%}.emoji-buttons button{padding:10px 5px;width:47%}}@media only screen and (max-width:801px) and (min-width:481px){.emoji-container-grid{grid-column-gap:10px}.emoji-buttons .el-button+.el-button{margin-left:5px}.remote-emoji-container-grid{grid-column-gap:10px}}.add-new-emoji{height:36px;font-size:14px;font-weight:700;color:#606266}.text{line-height:20px;margin-right:15px}.upload-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.upload-button{margin-left:10px}.upload-file-url{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}@media only screen and (max-width:480px){.new-emoji-uploader-form label.el-form-item__label{padding:0}}.download-archive{width:250px}.download-pack-button-container{width:265px}.download-pack-button-container .el-link,.download-pack-button-container .el-link span,.download-pack-button-container .el-link span .download-archive{width:inherit}.download-shared-pack{display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:10px}.download-shared-pack-button{margin-left:10px}.el-collapse-item__content{padding-bottom:0}.el-collapse-item__header{height:36px;font-size:14px;font-weight:700;color:#606266}.emoji-pack-card{margin-top:5px}.emoji-pack-metadata .el-form-item{margin-bottom:10px}.has-background .el-collapse-item__header{background:#f6f6f6}.no-background .el-collapse-item__header{background:#fff}.pack-button-container{margin:0 0 18px 120px}.save-pack-button-container{margin-bottom:8px;width:265px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}@media only screen and (max-width:480px){.delete-pack-button{width:45%}.download-pack-button-container{width:100%}.download-shared-pack{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.download-shared-pack-button{margin-left:0;margin-top:10px;padding:10px}.pack-button-container{width:100%;margin:0 0 22px}.remote-pack-metadata .el-form-item__content{line-height:24px;margin-top:4px}.save-pack-button{width:54%}.save-pack-button-container{margin-bottom:8px;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.save-pack-button-container button{padding:10px 5px}.save-pack-button-container .el-button+.el-button{margin-left:3px}}.emoji-packs-header-button-container{margin:0 0 22px 15px}.create-pack,.emoji-packs-header-button-container{display:-webkit-box;display:-ms-flexbox;display:flex}.create-pack{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.create-pack-button{margin-left:10px}.emoji-packs-form{margin:0 30px}.emoji-packs-header{margin:22px 0 20px 15px}.import-pack-button{margin-left:10px}.line{width:100%;height:0;border:1px solid #eee;margin-bottom:22px}@media only screen and (min-width:1824px){.emoji-packs{max-width:1824px;margin:auto}}@media only screen and (max-width:480px){.create-pack{height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.create-pack-button{margin-left:0}.divider{margin:15px 0}.el-message{min-width:80%}.el-message-box{width:80%}.emoji-packs-form{margin:0 7px}.emoji-packs-form label{padding-right:8px}.emoji-packs-form .el-form-item{margin-bottom:15px}.emoji-packs-header{margin:15px}.emoji-packs-header-button-container{height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.emoji-packs-header-button-container .el-button+.el-button{margin:7px 0 0}.emoji-packs-header-button-container .el-button+.el-button,.reload-emoji-button{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}}
|
.copy-popover{width:330px}.emoji-buttons{place-self:center;min-width:200px}.emoji-container-grid{display:grid;grid-template-columns:75px auto auto 200px;grid-column-gap:15px;margin-bottom:10px}.emoji-preview-img{max-width:100%;place-self:center}.emoji-info{place-self:center}.copy-pack-container{place-self:center stretch}.copy-pack-select{width:100%}.remote-emoji-container-grid{display:grid;grid-template-columns:75px auto auto 160px;grid-column-gap:15px;margin-bottom:10px}@media only screen and (max-width:480px){.emoji-container-flex{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border:1px solid #dcdfe6;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:4px;padding:15px;margin:0 15px 15px 0}.emoji-info,.emoji-preview-img{margin-bottom:10px}.emoji-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:100%}.emoji-buttons button{padding:10px 5px;width:47%}}@media only screen and (max-width:801px) and (min-width:481px){.emoji-container-grid{grid-column-gap:10px}.emoji-buttons .el-button+.el-button{margin-left:5px}.remote-emoji-container-grid{grid-column-gap:10px}}.add-new-emoji{height:36px;font-size:14px;font-weight:700;color:#606266}.text{line-height:20px;margin-right:15px}.upload-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.upload-button{margin-left:10px}.upload-file-url{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}@media only screen and (max-width:480px){.new-emoji-uploader-form label.el-form-item__label{padding:0}}.download-archive{width:250px}.download-pack-button-container{width:265px}.download-pack-button-container .el-link,.download-pack-button-container .el-link span,.download-pack-button-container .el-link span .download-archive{width:inherit}.download-shared-pack{display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:10px}.download-shared-pack-button{margin-left:10px}.el-collapse-item__content{padding-bottom:0}.el-collapse-item__header{height:36px;font-size:14px;font-weight:700;color:#606266}.emoji-pack-card{margin-top:5px}.emoji-pack-metadata .el-form-item{margin-bottom:10px}.has-background .el-collapse-item__header{background:#f6f6f6}.no-background .el-collapse-item__header{background:#fff}.pack-button-container{margin:0 0 18px 120px}.save-pack-button-container{margin-bottom:8px;width:265px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}@media only screen and (max-width:480px){.delete-pack-button{width:45%}.download-pack-button-container{width:100%}.download-shared-pack{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.download-shared-pack-button{margin-left:0;margin-top:10px;padding:10px}.pack-button-container{width:100%;margin:0 0 22px}.remote-pack-metadata .el-form-item__content{line-height:24px;margin-top:4px}.save-pack-button{width:54%}.save-pack-button-container{margin-bottom:8px;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.save-pack-button-container button{padding:10px 5px}.save-pack-button-container .el-button+.el-button{margin-left:3px}}.emoji-packs-header-button-container{margin:0 0 22px 15px}.create-pack,.emoji-packs-header-button-container{display:-webkit-box;display:-ms-flexbox;display:flex}.create-pack{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.create-pack-button{margin-left:10px}.emoji-packs-form{margin:0 30px}.emoji-packs-header{margin:10px 0 20px 15px}.import-pack-button{margin-left:10px}.line{width:100%;height:0;border:1px solid #eee;margin-bottom:22px}@media only screen and (min-width:1824px){.emoji-packs{max-width:1824px;margin:auto}}@media only screen and (max-width:480px){.create-pack{height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.create-pack-button{margin-left:0}.divider{margin:15px 0}.el-message{min-width:80%}.el-message-box{width:80%}.emoji-packs-form{margin:0 7px}.emoji-packs-form label{padding-right:8px}.emoji-packs-form .el-form-item{margin-bottom:15px}.emoji-packs-header{margin:15px}.emoji-packs-header-button-container{height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.emoji-packs-header-button-container .el-button+.el-button{margin:7px 0 0}.emoji-packs-header-button-container .el-button+.el-button,.reload-emoji-button{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}}
|
1
priv/static/adminfe/chunk-13e9.98eaadba.css
Normal file
1
priv/static/adminfe/chunk-13e9.98eaadba.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
.moderation-log-container[data-v-5d520014]{margin:0 15px}h1[data-v-5d520014]{margin:10px 0 20px}.el-timeline[data-v-5d520014]{margin:25px 45px 0 0;padding:0}.moderation-log-date-panel[data-v-5d520014]{width:350px}.moderation-log-nav-container[data-v-5d520014]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.moderation-log-search[data-v-5d520014]{width:350px}.moderation-log-user-select[data-v-5d520014]{margin:0 0 20px;width:350px}.search-container[data-v-5d520014]{text-align:right}.pagination[data-v-5d520014]{text-align:center}@media only screen and (max-width:480px){.moderation-log-date-panel[data-v-5d520014]{width:100%}.moderation-log-user-select[data-v-5d520014]{margin:0 0 10px;width:55%}.moderation-log-search[data-v-5d520014]{width:40%}}@media only screen and (max-width:801px) and (min-width:481px){.moderation-log-date-panel[data-v-5d520014]{width:55%}.moderation-log-user-select[data-v-5d520014]{margin:0 0 10px;width:55%}.moderation-log-search[data-v-5d520014]{width:40%}}
|
1
priv/static/adminfe/chunk-2b9c.feb61a2b.css
Normal file
1
priv/static/adminfe/chunk-2b9c.feb61a2b.css
Normal file
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
|||||||
.moderation-log-container[data-v-5798cff5]{margin:0 15px}h1[data-v-5798cff5]{margin:22px 0 20px}.el-timeline[data-v-5798cff5]{margin:25px 45px 0 0;padding:0}.moderation-log-date-panel[data-v-5798cff5]{width:350px}.moderation-log-nav-container[data-v-5798cff5]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.moderation-log-search[data-v-5798cff5]{width:350px}.moderation-log-user-select[data-v-5798cff5]{margin:0 0 20px;width:350px}.search-container[data-v-5798cff5]{text-align:right}.pagination[data-v-5798cff5]{text-align:center}@media only screen and (max-width:480px){.moderation-log-date-panel[data-v-5798cff5]{width:100%}.moderation-log-user-select[data-v-5798cff5]{margin:0 0 10px;width:55%}.moderation-log-search[data-v-5798cff5]{width:40%}}@media only screen and (max-width:801px) and (min-width:481px){.moderation-log-date-panel[data-v-5798cff5]{width:55%}.moderation-log-user-select[data-v-5798cff5]{margin:0 0 10px;width:55%}.moderation-log-search[data-v-5798cff5]{width:40%}}
|
|
@ -1 +1 @@
|
|||||||
.invites-container .actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:20px 15px 15px}.invites-container .create-invite-token{text-align:left;width:350px;padding:10px}.invites-container .create-new-token-dialog{width:40%}.invites-container .el-dialog__body{padding:5px 20px 0}.invites-container h1{margin:22px 0 0 15px}.invites-container .icon{margin-right:5px}.invites-container .invite-token-table{width:100%;margin:0 15px}.invites-container .invite-via-email{text-align:left;width:350px;padding:10px}.invites-container .invite-via-email-dialog{width:50%}.invites-container .info{color:#666;font-size:13px;line-height:22px;margin:0 0 10px}@media only screen and (max-width:480px){.invites-container .actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:15px 10px 7px}.invites-container .cell{padding:0}.invites-container .create-invite-token{width:100%}.invites-container .create-new-token-dialog{width:85%}.invites-container .el-date-editor{width:150px}.invites-container .el-dialog__body{padding:5px 15px 0}.invites-container h1{margin:7px 10px 15px}.invites-container .invite-token-table{width:100%;margin:0 5px;font-size:12px;font-weight:500}.invites-container .invite-via-email{width:100%;margin:10px 0 0}.invites-container .invite-via-email-dialog{width:85%}.invites-container .info{margin:0 0 10px 5px}.invites-container th .cell{padding:0}.create-invite-token,.invite-via-email{width:100%}}
|
.invites-container .actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:20px 15px 15px}.invites-container .create-invite-token{text-align:left;width:350px;padding:10px}.invites-container .create-new-token-dialog{width:40%}.invites-container .el-dialog__body{padding:5px 20px 0}.invites-container h1{margin:10px 0 0 15px}.invites-container .icon{margin-right:5px}.invites-container .invite-token-table{width:100%;margin:0 15px}.invites-container .invite-via-email{text-align:left;width:350px;padding:10px}.invites-container .invite-via-email-dialog{width:50%}.invites-container .info{color:#666;font-size:13px;line-height:22px;margin:0 0 10px}@media only screen and (max-width:480px){.invites-container .actions-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:82px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:15px 10px 7px}.invites-container .cell{padding:0}.invites-container .create-invite-token{width:100%}.invites-container .create-new-token-dialog{width:85%}.invites-container .el-date-editor{width:150px}.invites-container .el-dialog__body{padding:5px 15px 0}.invites-container h1{margin:7px 10px 15px}.invites-container .invite-token-table{width:100%;margin:0 5px;font-size:12px;font-weight:500}.invites-container .invite-via-email{width:100%;margin:10px 0 0}.invites-container .invite-via-email-dialog{width:85%}.invites-container .info{margin:0 0 10px 5px}.invites-container th .cell{padding:0}.create-invite-token,.invite-via-email{width:100%}}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/chunk-87b3.3c6ede9c.css
Normal file
1
priv/static/adminfe/chunk-87b3.3c6ede9c.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
.actions-button[data-v-3850612b]{text-align:left;width:350px;padding:10px}.actions-button-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-dropdown[data-v-3850612b]{float:right}.el-icon-edit[data-v-3850612b]{margin-right:5px}.tag-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.tag-text[data-v-3850612b]{padding-right:20px}.no-hover[data-v-3850612b]:hover{color:#606266;background-color:#fff;cursor:auto}.status-card{margin-bottom:10px}.status-card .account{text-decoration:underline;line-height:26px;font-size:13px}.status-card .image{width:20%}.status-card .image img{width:100%}.status-card .show-more-button{margin-left:5px}.status-card .status-account{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.status-card .status-avatar-img{display:inline-block;width:15px;height:15px;margin-right:5px}.status-card .status-account-name{display:inline-block;margin:0;height:22px}.status-card .status-body{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.status-card .status-checkbox{margin-right:7px}.status-card .status-content{font-size:15px;line-height:26px}.status-card .status-deleted{font-style:italic;margin-top:3px}.status-card .status-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.status-card .status-without-content{font-style:italic}@media only screen and (max-width:480px){.el-message{min-width:80%}.el-message-box{width:80%}.status-card .el-card__header{padding:10px 17px}.status-card .el-tag{margin:3px 4px 3px 0}.status-card .status-account-container{margin-bottom:5px}.status-card .status-actions-button{margin:3px 0}.status-card .status-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.status-card .status-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.statuses-container{padding:0 15px}.statuses-container .status-container{margin:0 0 10px}.checkbox-container{margin-bottom:15px}.filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:22px 0 15px}.select-instance{width:350px}.statuses-pagination{padding:15px 0;text-align:center}h1{margin:22px 0 0}@media only screen and (max-width:480px){.checkbox-container{margin-bottom:10px}.filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:10px 0}.select-field{width:100%;margin-bottom:5px}.select-instance{width:100%}}
|
.actions-button[data-v-3850612b]{text-align:left;width:350px;padding:10px}.actions-button-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-dropdown[data-v-3850612b]{float:right}.el-icon-edit[data-v-3850612b]{margin-right:5px}.tag-container[data-v-3850612b]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.tag-text[data-v-3850612b]{padding-right:20px}.no-hover[data-v-3850612b]:hover{color:#606266;background-color:#fff;cursor:auto}.status-card{margin-bottom:10px}.status-card .account{text-decoration:underline;line-height:26px;font-size:13px}.status-card .image{width:20%}.status-card .image img{width:100%}.status-card .show-more-button{margin-left:5px}.status-card .status-account{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.status-card .status-avatar-img{display:inline-block;width:15px;height:15px;margin-right:5px}.status-card .status-account-name{display:inline-block;margin:0;height:22px}.status-card .status-body{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.status-card .status-checkbox{margin-right:7px}.status-card .status-content{font-size:15px;line-height:26px}.status-card .status-deleted{font-style:italic;margin-top:3px}.status-card .status-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.status-card .status-without-content{font-style:italic}@media only screen and (max-width:480px){.el-message{min-width:80%}.el-message-box{width:80%}.status-card .el-card__header{padding:10px 17px}.status-card .el-tag{margin:3px 4px 3px 0}.status-card .status-account-container{margin-bottom:5px}.status-card .status-actions-button{margin:3px 0}.status-card .status-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.status-card .status-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.statuses-container{padding:0 15px}.statuses-container h1{margin:10px 0 15px}.statuses-container .status-container{margin:0 0 10px}.checkbox-container{margin-bottom:15px}.filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:22px 0 15px}.select-instance{width:350px}.statuses-pagination{padding:15px 0;text-align:center}@media only screen and (max-width:480px){.checkbox-container{margin-bottom:10px}.filter-container{display:-webkit-box;display:-ms-flexbox;display:flex;height:36px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:10px 0}.select-field{width:100%;margin-bottom:5px}.select-instance{width:100%}}
|
@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Admin FE</title><link rel="shortcut icon" href=favicon.ico><link href=chunk-elementUI.1abbc9b8.css rel=stylesheet><link href=chunk-libs.686b5876.css rel=stylesheet><link href=app.c836e084.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=static/js/runtime.fa19e5d1.js></script><script type=text/javascript src=static/js/chunk-elementUI.fba0efec.js></script><script type=text/javascript src=static/js/chunk-libs.b8c453ab.js></script><script type=text/javascript src=static/js/app.d2c3c6b3.js></script></body></html>
|
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Admin FE</title><link rel="shortcut icon" href=favicon.ico><link href=chunk-elementUI.1abbc9b8.css rel=stylesheet><link href=chunk-libs.686b5876.css rel=stylesheet><link href=app.85534e14.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=static/js/runtime.cb26bbd1.js></script><script type=text/javascript src=static/js/chunk-elementUI.fba0efec.js></script><script type=text/javascript src=static/js/chunk-libs.b8c453ab.js></script><script type=text/javascript src=static/js/app.d898cc2b.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/adminfe/static/js/app.d898cc2b.js
Normal file
2
priv/static/adminfe/static/js/app.d898cc2b.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/static/js/app.d898cc2b.js.map
Normal file
1
priv/static/adminfe/static/js/app.d898cc2b.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/adminfe/static/js/chunk-13e9.79da1569.js
Normal file
2
priv/static/adminfe/static/js/chunk-13e9.79da1569.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/static/js/chunk-13e9.79da1569.js.map
Normal file
1
priv/static/adminfe/static/js/chunk-13e9.79da1569.js.map
Normal file
File diff suppressed because one or more lines are too long
2
priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js
Normal file
2
priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js.map
Normal file
1
priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js.map
Normal file
1
priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/adminfe/static/js/chunk-88c9.e3583744.js
Normal file
2
priv/static/adminfe/static/js/chunk-88c9.e3583744.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/static/js/chunk-88c9.e3583744.js.map
Normal file
1
priv/static/adminfe/static/js/chunk-88c9.e3583744.js.map
Normal file
File diff suppressed because one or more lines are too long
2
priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js
Normal file
2
priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js.map
Normal file
1
priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/adminfe/static/js/runtime.cb26bbd1.js
Normal file
2
priv/static/adminfe/static/js/runtime.cb26bbd1.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
!function(e){function n(n){for(var r,c,o=n[0],a=n[1],i=n[2],h=0,l=[];h<o.length;h++)c=o[h],u[c]&&l.push(u[c][0]),u[c]=0;for(r in a)Object.prototype.hasOwnProperty.call(a,r)&&(e[r]=a[r]);for(d&&d(n);l.length;)l.shift()();return f.push.apply(f,i||[]),t()}function t(){for(var e,n=0;n<f.length;n++){for(var t=f[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(f.splice(n--,1),e=o(o.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},f=[];function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=[];c[e]?n.push(c[e]):0!==c[e]&&{"chunk-0d8f":1,"chunk-136a":1,"chunk-15fa":1,"chunk-46ef":1,"chunk-4ffb":1,"chunk-87b3":1,"chunk-88c9":1,"chunk-13e9":1,"chunk-2b9c":1,"chunk-cf57":1,"chunk-876c":1}[e]&&n.push(c[e]=new Promise(function(n,t){for(var r=({}[e]||e)+"."+{"7zzA":"31d6cfe0",JEtC:"31d6cfe0",ZhIB:"31d6cfe0","chunk-0d8f":"d85f5a29","chunk-136a":"f1130f8e","chunk-15fa":"5a5f973d","chunk-46ef":"145de4f9","chunk-4ffb":"dd09fe2e","chunk-7f9e":"31d6cfe0","chunk-87b3":"3c6ede9c","chunk-df62":"31d6cfe0","chunk-88c9":"184084df","chunk-13e9":"98eaadba","chunk-2b9c":"feb61a2b","chunk-cf57":"26596375",oAJy:"31d6cfe0","chunk-16d0":"31d6cfe0","chunk-876c":"90dffac4"}[e]+".css",c=o.p+r,u=document.getElementsByTagName("link"),f=0;f<u.length;f++){var a=(h=u[f]).getAttribute("data-href")||h.getAttribute("href");if("stylesheet"===h.rel&&(a===r||a===c))return n()}var i=document.getElementsByTagName("style");for(f=0;f<i.length;f++){var h;if((a=(h=i[f]).getAttribute("data-href"))===r||a===c)return n()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=n,d.onerror=function(n){var r=n&&n.target&&n.target.src||c,u=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");u.request=r,t(u)},d.href=c,document.getElementsByTagName("head")[0].appendChild(d)}).then(function(){c[e]=0}));var t=u[e];if(0!==t)if(t)n.push(t[2]);else{var r=new Promise(function(n,r){t=u[e]=[n,r]});n.push(t[2]=r);var f,a=document.createElement("script");a.charset="utf-8",a.timeout=120,o.nc&&a.setAttribute("nonce",o.nc),a.src=function(e){return o.p+"static/js/"+({}[e]||e)+"."+{"7zzA":"e1ae1c94",JEtC:"f9ba4594",ZhIB:"861df339","chunk-0d8f":"6d50ff86","chunk-136a":"c4719e3e","chunk-15fa":"34070731","chunk-46ef":"671cac7d","chunk-4ffb":"0e8f3772","chunk-7f9e":"c49aa694","chunk-87b3":"3c11ef09","chunk-df62":"6c5105a6","chunk-88c9":"e3583744","chunk-13e9":"79da1569","chunk-2b9c":"cf321c74","chunk-cf57":"3e45f57f",oAJy:"840fb1c2","chunk-16d0":"6ce78978","chunk-876c":"e4ceccca"}[e]+".js"}(e),f=function(n){a.onerror=a.onload=null,clearTimeout(i);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,f=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");f.type=r,f.request=c,t[1](f)}u[e]=void 0}};var i=setTimeout(function(){f({type:"timeout",target:a})},12e4);a.onerror=a.onload=f,document.head.appendChild(a)}return Promise.all(n)},o.m=e,o.c=r,o.d=function(e,n,t){o.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,n){if(1&n&&(e=o(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(o.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)o.d(t,r,function(n){return e[n]}.bind(null,r));return t},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],i=a.push.bind(a);a.push=n,a=a.slice();for(var h=0;h<a.length;h++)n(a[h]);var d=i;t()}([]);
|
||||||
|
//# sourceMappingURL=runtime.cb26bbd1.js.map
|
File diff suppressed because one or more lines are too long
@ -1,2 +0,0 @@
|
|||||||
!function(e){function n(n){for(var r,c,f=n[0],o=n[1],i=n[2],h=0,l=[];h<f.length;h++)c=f[h],u[c]&&l.push(u[c][0]),u[c]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(e[r]=o[r]);for(d&&d(n);l.length;)l.shift()();return a.push.apply(a,i||[]),t()}function t(){for(var e,n=0;n<a.length;n++){for(var t=a[n],r=!0,c=1;c<t.length;c++){var o=t[c];0!==u[o]&&(r=!1)}r&&(a.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},a=[];function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[];c[e]?n.push(c[e]):0!==c[e]&&{"chunk-0d8f":1,"chunk-136a":1,"chunk-15fa":1,"chunk-46ef":1,"chunk-4ffb":1,"chunk-87b3":1,"chunk-e5cf":1,"chunk-46cf":1,"chunk-4e7d":1,"chunk-cf57":1,"chunk-876c":1}[e]&&n.push(c[e]=new Promise(function(n,t){for(var r=({}[e]||e)+"."+{"7zzA":"31d6cfe0",JEtC:"31d6cfe0",ZhIB:"31d6cfe0","chunk-0d8f":"650c8e81","chunk-136a":"3936457d","chunk-15fa":"5a5f973d","chunk-46ef":"d45db7be","chunk-4ffb":"dd09fe2e","chunk-7f9e":"31d6cfe0","chunk-87b3":"2affd602","chunk-df62":"31d6cfe0","chunk-e5cf":"cba3ae06","chunk-46cf":"a43e9415","chunk-4e7d":"7aace723","chunk-cf57":"4d39576f",oAJy:"31d6cfe0","chunk-16d0":"31d6cfe0","chunk-876c":"90dffac4"}[e]+".css",c=f.p+r,u=document.getElementsByTagName("link"),a=0;a<u.length;a++){var o=(h=u[a]).getAttribute("data-href")||h.getAttribute("href");if("stylesheet"===h.rel&&(o===r||o===c))return n()}var i=document.getElementsByTagName("style");for(a=0;a<i.length;a++){var h;if((o=(h=i[a]).getAttribute("data-href"))===r||o===c)return n()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=n,d.onerror=function(n){var r=n&&n.target&&n.target.src||c,u=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");u.request=r,t(u)},d.href=c,document.getElementsByTagName("head")[0].appendChild(d)}).then(function(){c[e]=0}));var t=u[e];if(0!==t)if(t)n.push(t[2]);else{var r=new Promise(function(n,r){t=u[e]=[n,r]});n.push(t[2]=r);var a,o=document.createElement("script");o.charset="utf-8",o.timeout=120,f.nc&&o.setAttribute("nonce",f.nc),o.src=function(e){return f.p+"static/js/"+({}[e]||e)+"."+{"7zzA":"e1ae1c94",JEtC:"f9ba4594",ZhIB:"861df339","chunk-0d8f":"a85e3222","chunk-136a":"142aa42a","chunk-15fa":"34070731","chunk-46ef":"215af110","chunk-4ffb":"0e8f3772","chunk-7f9e":"c49aa694","chunk-87b3":"4704cadf","chunk-df62":"6c5105a6","chunk-e5cf":"501d7902","chunk-46cf":"3bd3567a","chunk-4e7d":"a40ad735","chunk-cf57":"42b96339",oAJy:"840fb1c2","chunk-16d0":"6ce78978","chunk-876c":"e4ceccca"}[e]+".js"}(e),a=function(n){o.onerror=o.onload=null,clearTimeout(i);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,a=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");a.type=r,a.request=c,t[1](a)}u[e]=void 0}};var i=setTimeout(function(){a({type:"timeout",target:o})},12e4);o.onerror=o.onload=a,document.head.appendChild(o)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var o=window.webpackJsonp=window.webpackJsonp||[],i=o.push.bind(o);o.push=n,o=o.slice();for(var h=0;h<o.length;h++)n(o[h]);var d=i;t()}([]);
|
|
||||||
//# sourceMappingURL=runtime.fa19e5d1.js.map
|
|
@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.1055039ce3f2fe4dd110.css rel=stylesheet><link href=/static/fontello.1583594169021.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.c5bbd3734647f0cc7eef.js></script><script type=text/javascript src=/static/js/app.5c94bdec79a7d0f3cfcb.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.1055039ce3f2fe4dd110.css rel=stylesheet><link href=/static/fontello.1586352043988.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.de343579e844e698d456.js></script><script type=text/javascript src=/static/js/app.89eafa17d89159680407.js></script></body></html>
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Binary file not shown.
BIN
priv/static/static/font/fontello.1586352043988.woff2
Normal file
BIN
priv/static/static/font/fontello.1586352043988.woff2
Normal file
Binary file not shown.
138
priv/static/static/fontello.1586352043988.css
vendored
Normal file
138
priv/static/static/fontello.1586352043988.css
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "Icons";
|
||||||
|
src: url("./font/fontello.1586352043988.eot");
|
||||||
|
src: url("./font/fontello.1586352043988.eot") format("embedded-opentype"),
|
||||||
|
url("./font/fontello.1586352043988.woff2") format("woff2"),
|
||||||
|
url("./font/fontello.1586352043988.woff") format("woff"),
|
||||||
|
url("./font/fontello.1586352043988.ttf") format("truetype"),
|
||||||
|
url("./font/fontello.1586352043988.svg") format("svg");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class^="icon-"]::before,
|
||||||
|
[class*=" icon-"]::before {
|
||||||
|
font-family: "Icons";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
speak: none;
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: inherit;
|
||||||
|
width: 1em;
|
||||||
|
margin-right: .2em;
|
||||||
|
text-align: center;
|
||||||
|
font-variant: normal;
|
||||||
|
text-transform: none;
|
||||||
|
line-height: 1em;
|
||||||
|
margin-left: .2em;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-spin4::before { content: "\e834"; }
|
||||||
|
|
||||||
|
.icon-cancel::before { content: "\e800"; }
|
||||||
|
|
||||||
|
.icon-upload::before { content: "\e801"; }
|
||||||
|
|
||||||
|
.icon-spin3::before { content: "\e832"; }
|
||||||
|
|
||||||
|
.icon-reply::before { content: "\f112"; }
|
||||||
|
|
||||||
|
.icon-star::before { content: "\e802"; }
|
||||||
|
|
||||||
|
.icon-star-empty::before { content: "\e803"; }
|
||||||
|
|
||||||
|
.icon-retweet::before { content: "\e804"; }
|
||||||
|
|
||||||
|
.icon-eye-off::before { content: "\e805"; }
|
||||||
|
|
||||||
|
.icon-binoculars::before { content: "\f1e5"; }
|
||||||
|
|
||||||
|
.icon-cog::before { content: "\e807"; }
|
||||||
|
|
||||||
|
.icon-user-plus::before { content: "\f234"; }
|
||||||
|
|
||||||
|
.icon-menu::before { content: "\f0c9"; }
|
||||||
|
|
||||||
|
.icon-logout::before { content: "\e808"; }
|
||||||
|
|
||||||
|
.icon-down-open::before { content: "\e809"; }
|
||||||
|
|
||||||
|
.icon-attach::before { content: "\e80a"; }
|
||||||
|
|
||||||
|
.icon-link-ext::before { content: "\f08e"; }
|
||||||
|
|
||||||
|
.icon-link-ext-alt::before { content: "\f08f"; }
|
||||||
|
|
||||||
|
.icon-picture::before { content: "\e80b"; }
|
||||||
|
|
||||||
|
.icon-video::before { content: "\e80c"; }
|
||||||
|
|
||||||
|
.icon-right-open::before { content: "\e80d"; }
|
||||||
|
|
||||||
|
.icon-left-open::before { content: "\e80e"; }
|
||||||
|
|
||||||
|
.icon-up-open::before { content: "\e80f"; }
|
||||||
|
|
||||||
|
.icon-comment-empty::before { content: "\f0e5"; }
|
||||||
|
|
||||||
|
.icon-mail-alt::before { content: "\f0e0"; }
|
||||||
|
|
||||||
|
.icon-lock::before { content: "\e811"; }
|
||||||
|
|
||||||
|
.icon-lock-open-alt::before { content: "\f13e"; }
|
||||||
|
|
||||||
|
.icon-globe::before { content: "\e812"; }
|
||||||
|
|
||||||
|
.icon-brush::before { content: "\e813"; }
|
||||||
|
|
||||||
|
.icon-search::before { content: "\e806"; }
|
||||||
|
|
||||||
|
.icon-adjust::before { content: "\e816"; }
|
||||||
|
|
||||||
|
.icon-thumbs-up-alt::before { content: "\f164"; }
|
||||||
|
|
||||||
|
.icon-attention::before { content: "\e814"; }
|
||||||
|
|
||||||
|
.icon-plus-squared::before { content: "\f0fe"; }
|
||||||
|
|
||||||
|
.icon-plus::before { content: "\e815"; }
|
||||||
|
|
||||||
|
.icon-edit::before { content: "\e817"; }
|
||||||
|
|
||||||
|
.icon-play-circled::before { content: "\f144"; }
|
||||||
|
|
||||||
|
.icon-pencil::before { content: "\e818"; }
|
||||||
|
|
||||||
|
.icon-chart-bar::before { content: "\e81b"; }
|
||||||
|
|
||||||
|
.icon-smile::before { content: "\f118"; }
|
||||||
|
|
||||||
|
.icon-bell-alt::before { content: "\f0f3"; }
|
||||||
|
|
||||||
|
.icon-wrench::before { content: "\e81a"; }
|
||||||
|
|
||||||
|
.icon-pin::before { content: "\e819"; }
|
||||||
|
|
||||||
|
.icon-ellipsis::before { content: "\f141"; }
|
||||||
|
|
||||||
|
.icon-bell-ringing-o::before { content: "\e810"; }
|
||||||
|
|
||||||
|
.icon-zoom-in::before { content: "\e81c"; }
|
||||||
|
|
||||||
|
.icon-gauge::before { content: "\f0e4"; }
|
||||||
|
|
||||||
|
.icon-users::before { content: "\e81d"; }
|
||||||
|
|
||||||
|
.icon-info-circled::before { content: "\e81f"; }
|
||||||
|
|
||||||
|
.icon-home-2::before { content: "\e821"; }
|
||||||
|
|
||||||
|
.icon-chat::before { content: "\e81e"; }
|
||||||
|
|
||||||
|
.icon-login::before { content: "\e820"; }
|
||||||
|
|
||||||
|
.icon-arrow-curved::before { content: "\e822"; }
|
||||||
|
|
||||||
|
.icon-link::before { content: "\e823"; }
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/static/js/app.89eafa17d89159680407.js
Normal file
2
priv/static/static/js/app.89eafa17d89159680407.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.89eafa17d89159680407.js.map
Normal file
1
priv/static/static/js/app.89eafa17d89159680407.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
var serviceWorkerOption = {"assets":["/static/fontello.1583594169021.css","/static/font/fontello.1583594169021.eot","/static/font/fontello.1583594169021.svg","/static/font/fontello.1583594169021.ttf","/static/font/fontello.1583594169021.woff","/static/font/fontello.1583594169021.woff2","/static/img/nsfw.74818f9.png","/static/css/app.1055039ce3f2fe4dd110.css","/static/js/app.5c94bdec79a7d0f3cfcb.js","/static/css/vendors~app.b2603a50868c68a1c192.css","/static/js/vendors~app.c5bbd3734647f0cc7eef.js","/static/js/2.f158cbd2b8770e467dfe.js"]};
|
var serviceWorkerOption = {"assets":["/static/fontello.1586352043988.css","/static/font/fontello.1586352043988.eot","/static/font/fontello.1586352043988.svg","/static/font/fontello.1586352043988.ttf","/static/font/fontello.1586352043988.woff","/static/font/fontello.1586352043988.woff2","/static/img/nsfw.74818f9.png","/static/css/app.1055039ce3f2fe4dd110.css","/static/js/app.89eafa17d89159680407.js","/static/css/vendors~app.b2603a50868c68a1c192.css","/static/js/vendors~app.de343579e844e698d456.js","/static/js/2.f158cbd2b8770e467dfe.js"]};
|
||||||
|
|
||||||
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=1)}([function(e,n){
|
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=1)}([function(e,n){
|
||||||
/*!
|
/*!
|
||||||
|
44
test/fixtures/tesla_mock/funkwhale_audio.json
vendored
Normal file
44
test/fixtures/tesla_mock/funkwhale_audio.json
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"id": "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871",
|
||||||
|
"type": "Audio",
|
||||||
|
"name": "Compositions - Test Audio for Pleroma",
|
||||||
|
"attributedTo": "https://channels.tests.funkwhale.audio/federation/actors/compositions",
|
||||||
|
"published": "2020-03-11T10:01:52.714918+00:00",
|
||||||
|
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"url": [
|
||||||
|
{
|
||||||
|
"type": "Link",
|
||||||
|
"mimeType": "audio/ogg",
|
||||||
|
"href": "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Link",
|
||||||
|
"mimeType": "text/html",
|
||||||
|
"href": "https://channels.tests.funkwhale.audio/library/tracks/74"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"content": "<p>This is a test Audio for Pleroma.</p>",
|
||||||
|
"mediaType": "text/html",
|
||||||
|
"tag": [
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"name": "#funkwhale"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"name": "#test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"name": "#tests"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": "#funkwhale #test #tests",
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
44
test/fixtures/tesla_mock/funkwhale_channel.json
vendored
Normal file
44
test/fixtures/tesla_mock/funkwhale_channel.json
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"id": "https://channels.tests.funkwhale.audio/federation/actors/compositions",
|
||||||
|
"outbox": "https://channels.tests.funkwhale.audio/federation/actors/compositions/outbox",
|
||||||
|
"inbox": "https://channels.tests.funkwhale.audio/federation/actors/compositions/inbox",
|
||||||
|
"preferredUsername": "compositions",
|
||||||
|
"type": "Person",
|
||||||
|
"name": "Compositions",
|
||||||
|
"followers": "https://channels.tests.funkwhale.audio/federation/actors/compositions/followers",
|
||||||
|
"following": "https://channels.tests.funkwhale.audio/federation/actors/compositions/following",
|
||||||
|
"manuallyApprovesFollowers": false,
|
||||||
|
"url": [
|
||||||
|
{
|
||||||
|
"type": "Link",
|
||||||
|
"href": "https://channels.tests.funkwhale.audio/channels/compositions",
|
||||||
|
"mediaType": "text/html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Link",
|
||||||
|
"href": "https://channels.tests.funkwhale.audio/api/v1/channels/compositions/rss",
|
||||||
|
"mediaType": "application/rss+xml"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"type": "Image",
|
||||||
|
"url": "https://channels.tests.funkwhale.audio/media/attachments/75/b4/f1/nosmile.jpeg",
|
||||||
|
"mediaType": "image/jpeg"
|
||||||
|
},
|
||||||
|
"summary": "<p>I'm testing federation with the fediverse :)</p>",
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publicKey": {
|
||||||
|
"owner": "https://channels.tests.funkwhale.audio/federation/actors/compositions",
|
||||||
|
"publicKeyPem": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAv25u57oZfVLV3KltS+HcsdSx9Op4MmzIes1J8Wu8s0KbdXf2zEwS\nsVqyHgs/XCbnzsR3FqyJTo46D2BVnvZcuU5srNcR2I2HMaqQ0oVdnATE4K6KdcgV\nN+98pMWo56B8LTgE1VpvqbsrXLi9jCTzjrkebVMOP+ZVu+64v1qdgddseblYMnBZ\nct0s7ONbHnqrWlTGf5wES1uIZTVdn5r4MduZG+Uenfi1opBS0lUUxfWdW9r0oF2b\nyneZUyaUCbEroeKbqsweXCWVgnMarUOsgqC42KM4cf95lySSwTSaUtZYIbTw7s9W\n2jveU/rVg8BYZu5JK5obgBoxtlUeUoSswwIDAQAB\n-----END RSA PUBLIC KEY-----\n",
|
||||||
|
"id": "https://channels.tests.funkwhale.audio/federation/actors/compositions#main-key"
|
||||||
|
},
|
||||||
|
"endpoints": {
|
||||||
|
"sharedInbox": "https://channels.tests.funkwhale.audio/federation/shared/inbox"
|
||||||
|
}
|
||||||
|
}
|
@ -6,12 +6,14 @@ defmodule Pleroma.NotificationTest do
|
|||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
import Mock
|
||||||
|
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Tests.ObanHelpers
|
alias Pleroma.Tests.ObanHelpers
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.Push
|
||||||
alias Pleroma.Web.Streamer
|
alias Pleroma.Web.Streamer
|
||||||
|
|
||||||
describe "create_notifications" do
|
describe "create_notifications" do
|
||||||
@ -80,6 +82,80 @@ defmodule Pleroma.NotificationTest do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "CommonApi.post/2 notification-related functionality" do
|
||||||
|
test_with_mock "creates but does NOT send notification to blocker user",
|
||||||
|
Push,
|
||||||
|
[:passthrough],
|
||||||
|
[] do
|
||||||
|
user = insert(:user)
|
||||||
|
blocker = insert(:user)
|
||||||
|
{:ok, _user_relationship} = User.block(blocker, user)
|
||||||
|
|
||||||
|
{:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"})
|
||||||
|
|
||||||
|
blocker_id = blocker.id
|
||||||
|
assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
|
||||||
|
refute called(Push.send(:_))
|
||||||
|
end
|
||||||
|
|
||||||
|
test_with_mock "creates but does NOT send notification to notification-muter user",
|
||||||
|
Push,
|
||||||
|
[:passthrough],
|
||||||
|
[] do
|
||||||
|
user = insert(:user)
|
||||||
|
muter = insert(:user)
|
||||||
|
{:ok, _user_relationships} = User.mute(muter, user)
|
||||||
|
|
||||||
|
{:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"})
|
||||||
|
|
||||||
|
muter_id = muter.id
|
||||||
|
assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
|
||||||
|
refute called(Push.send(:_))
|
||||||
|
end
|
||||||
|
|
||||||
|
test_with_mock "creates but does NOT send notification to thread-muter user",
|
||||||
|
Push,
|
||||||
|
[:passthrough],
|
||||||
|
[] do
|
||||||
|
user = insert(:user)
|
||||||
|
thread_muter = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.add_mute(thread_muter, activity)
|
||||||
|
|
||||||
|
{:ok, _same_context_activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "hey-hey-hey @#{thread_muter.nickname}!",
|
||||||
|
"in_reply_to_status_id" => activity.id
|
||||||
|
})
|
||||||
|
|
||||||
|
[pre_mute_notification, post_mute_notification] =
|
||||||
|
Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
|
||||||
|
|
||||||
|
pre_mute_notification_id = pre_mute_notification.id
|
||||||
|
post_mute_notification_id = post_mute_notification.id
|
||||||
|
|
||||||
|
assert called(
|
||||||
|
Push.send(
|
||||||
|
:meck.is(fn
|
||||||
|
%Notification{id: ^pre_mute_notification_id} -> true
|
||||||
|
_ -> false
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
refute called(
|
||||||
|
Push.send(
|
||||||
|
:meck.is(fn
|
||||||
|
%Notification{id: ^post_mute_notification_id} -> true
|
||||||
|
_ -> false
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "create_notification" do
|
describe "create_notification" do
|
||||||
@tag needs_streamer: true
|
@tag needs_streamer: true
|
||||||
test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
|
test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
|
||||||
@ -382,7 +458,7 @@ defmodule Pleroma.NotificationTest do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "notification target determination" do
|
describe "notification target determination / get_notified_from_activity/2" do
|
||||||
test "it sends notifications to addressed users in new messages" do
|
test "it sends notifications to addressed users in new messages" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
@ -392,7 +468,9 @@ defmodule Pleroma.NotificationTest do
|
|||||||
"status" => "hey @#{other_user.nickname}!"
|
"status" => "hey @#{other_user.nickname}!"
|
||||||
})
|
})
|
||||||
|
|
||||||
assert other_user in Notification.get_notified_from_activity(activity)
|
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||||
|
|
||||||
|
assert other_user in enabled_receivers
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it sends notifications to mentioned users in new messages" do
|
test "it sends notifications to mentioned users in new messages" do
|
||||||
@ -420,7 +498,9 @@ defmodule Pleroma.NotificationTest do
|
|||||||
|
|
||||||
{:ok, activity} = Transmogrifier.handle_incoming(create_activity)
|
{:ok, activity} = Transmogrifier.handle_incoming(create_activity)
|
||||||
|
|
||||||
assert other_user in Notification.get_notified_from_activity(activity)
|
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||||
|
|
||||||
|
assert other_user in enabled_receivers
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it does not send notifications to users who are only cc in new messages" do
|
test "it does not send notifications to users who are only cc in new messages" do
|
||||||
@ -442,7 +522,9 @@ defmodule Pleroma.NotificationTest do
|
|||||||
|
|
||||||
{:ok, activity} = Transmogrifier.handle_incoming(create_activity)
|
{:ok, activity} = Transmogrifier.handle_incoming(create_activity)
|
||||||
|
|
||||||
assert other_user not in Notification.get_notified_from_activity(activity)
|
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||||
|
|
||||||
|
assert other_user not in enabled_receivers
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it does not send notification to mentioned users in likes" do
|
test "it does not send notification to mentioned users in likes" do
|
||||||
@ -457,7 +539,10 @@ defmodule Pleroma.NotificationTest do
|
|||||||
|
|
||||||
{:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user)
|
{:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user)
|
||||||
|
|
||||||
assert other_user not in Notification.get_notified_from_activity(activity_two)
|
{enabled_receivers, _disabled_receivers} =
|
||||||
|
Notification.get_notified_from_activity(activity_two)
|
||||||
|
|
||||||
|
assert other_user not in enabled_receivers
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it does not send notification to mentioned users in announces" do
|
test "it does not send notification to mentioned users in announces" do
|
||||||
@ -472,7 +557,57 @@ defmodule Pleroma.NotificationTest do
|
|||||||
|
|
||||||
{:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
|
{:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
|
||||||
|
|
||||||
assert other_user not in Notification.get_notified_from_activity(activity_two)
|
{enabled_receivers, _disabled_receivers} =
|
||||||
|
Notification.get_notified_from_activity(activity_two)
|
||||||
|
|
||||||
|
assert other_user not in enabled_receivers
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns blocking recipient in disabled recipients list" do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, _user_relationship} = User.block(other_user, user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||||
|
|
||||||
|
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||||
|
|
||||||
|
assert [] == enabled_receivers
|
||||||
|
assert [other_user] == disabled_receivers
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns notification-muting recipient in disabled recipients list" do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, _user_relationships} = User.mute(other_user, user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||||
|
|
||||||
|
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||||
|
|
||||||
|
assert [] == enabled_receivers
|
||||||
|
assert [other_user] == disabled_receivers
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns thread-muting recipient in disabled recipients list" do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.add_mute(other_user, activity)
|
||||||
|
|
||||||
|
{:ok, same_context_activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "hey-hey-hey @#{other_user.nickname}!",
|
||||||
|
"in_reply_to_status_id" => activity.id
|
||||||
|
})
|
||||||
|
|
||||||
|
{enabled_receivers, disabled_receivers} =
|
||||||
|
Notification.get_notified_from_activity(same_context_activity)
|
||||||
|
|
||||||
|
assert [other_user] == disabled_receivers
|
||||||
|
refute other_user in enabled_receivers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -720,7 +855,7 @@ defmodule Pleroma.NotificationTest do
|
|||||||
assert Notification.for_user(user) == []
|
assert Notification.for_user(user) == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't return notificatitons for blocked domain" do
|
test "it doesn't return notifications for blocked domain" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
blocked = insert(:user, ap_id: "http://some-domain.com")
|
blocked = insert(:user, ap_id: "http://some-domain.com")
|
||||||
{:ok, user} = User.block_domain(user, "some-domain.com")
|
{:ok, user} = User.block_domain(user, "some-domain.com")
|
||||||
|
@ -1273,6 +1273,21 @@ defmodule HttpRequestMock do
|
|||||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}
|
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get(
|
||||||
|
"https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871",
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_
|
||||||
|
) do
|
||||||
|
{:ok,
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/funkwhale_audio.json")}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("https://channels.tests.funkwhale.audio/federation/actors/compositions", _, _, _) do
|
||||||
|
{:ok,
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json")}}
|
||||||
|
end
|
||||||
|
|
||||||
def get("http://example.com/rel_me/error", _, _, _) do
|
def get("http://example.com/rel_me/error", _, _, _) do
|
||||||
{:ok, %Tesla.Env{status: 404, body: ""}}
|
{:ok, %Tesla.Env{status: 404, body: ""}}
|
||||||
end
|
end
|
||||||
|
@ -86,7 +86,7 @@ defmodule Pleroma.UserTest do
|
|||||||
{:ok, user: insert(:user)}
|
{:ok, user: insert(:user)}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "outgoing_relations_ap_ids/1", %{user: user} do
|
test "outgoing_relationships_ap_ids/1", %{user: user} do
|
||||||
rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]
|
rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription]
|
||||||
|
|
||||||
ap_ids_by_rel =
|
ap_ids_by_rel =
|
||||||
@ -124,10 +124,10 @@ defmodule Pleroma.UserTest do
|
|||||||
assert ap_ids_by_rel[:inverse_subscription] ==
|
assert ap_ids_by_rel[:inverse_subscription] ==
|
||||||
Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id))
|
Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id))
|
||||||
|
|
||||||
outgoing_relations_ap_ids = User.outgoing_relations_ap_ids(user, rel_types)
|
outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types)
|
||||||
|
|
||||||
assert ap_ids_by_rel ==
|
assert ap_ids_by_rel ==
|
||||||
Enum.into(outgoing_relations_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)
|
Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1425,6 +1425,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||||||
assert Repo.get(Object, object.id).data["type"] == "Tombstone"
|
assert Repo.get(Object, object.id).data["type"] == "Tombstone"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it doesn't fail when an activity was already deleted" do
|
||||||
|
{:ok, delete} = insert(:note_activity) |> Object.normalize() |> ActivityPub.delete()
|
||||||
|
|
||||||
|
assert {:ok, ^delete} = delete |> Object.normalize() |> ActivityPub.delete()
|
||||||
|
end
|
||||||
|
|
||||||
test "decrements user note count only for public activities" do
|
test "decrements user note count only for public activities" do
|
||||||
user = insert(:user, note_count: 10)
|
user = insert(:user, note_count: 10)
|
||||||
|
|
||||||
|
@ -3385,6 +3385,75 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "GET /users/:nickname/credentials" do
|
||||||
|
test "gets the user credentials", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
|
||||||
|
|
||||||
|
response = assert json_response(conn, 200)
|
||||||
|
assert response["email"] == user.email
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 403 if requested by a non-admin" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
|
||||||
|
|
||||||
|
assert json_response(conn, :forbidden)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PATCH /users/:nickname/credentials" do
|
||||||
|
test "changes password and email", %{conn: conn, admin: admin} do
|
||||||
|
user = insert(:user)
|
||||||
|
assert user.password_reset_pending == false
|
||||||
|
|
||||||
|
conn =
|
||||||
|
patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
|
||||||
|
"password" => "new_password",
|
||||||
|
"email" => "new_email@example.com",
|
||||||
|
"name" => "new_name"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert json_response(conn, 200) == %{"status" => "success"}
|
||||||
|
|
||||||
|
ObanHelpers.perform_all()
|
||||||
|
|
||||||
|
updated_user = User.get_by_id(user.id)
|
||||||
|
|
||||||
|
assert updated_user.email == "new_email@example.com"
|
||||||
|
assert updated_user.name == "new_name"
|
||||||
|
assert updated_user.password_hash != user.password_hash
|
||||||
|
assert updated_user.password_reset_pending == true
|
||||||
|
|
||||||
|
[log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
|
||||||
|
|
||||||
|
assert ModerationLog.get_log_entry_message(log_entry1) ==
|
||||||
|
"@#{admin.nickname} updated users: @#{user.nickname}"
|
||||||
|
|
||||||
|
assert ModerationLog.get_log_entry_message(log_entry2) ==
|
||||||
|
"@#{admin.nickname} forced password reset for users: @#{user.nickname}"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 403 if requested by a non-admin" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
|
||||||
|
"password" => "new_password",
|
||||||
|
"email" => "new_email@example.com",
|
||||||
|
"name" => "new_name"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert json_response(conn, :forbidden)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "PATCH /users/:nickname/force_password_reset" do
|
describe "PATCH /users/:nickname/force_password_reset" do
|
||||||
test "sets password_reset_pending to true", %{conn: conn} do
|
test "sets password_reset_pending to true", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
@ -75,7 +75,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
|
|
||||||
conn =
|
conn =
|
||||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||||
"note" => "I drink #cofe with @#{user2.nickname}"
|
"note" => "I drink #cofe with @#{user2.nickname}\n\nsuya.."
|
||||||
})
|
})
|
||||||
|
|
||||||
assert user_data = json_response(conn, 200)
|
assert user_data = json_response(conn, 200)
|
||||||
@ -83,7 +83,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
assert user_data["note"] ==
|
assert user_data["note"] ==
|
||||||
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a data-user="#{
|
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a data-user="#{
|
||||||
user2.id
|
user2.id
|
||||||
}" class="u-url mention" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span>)
|
}" class="u-url mention" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "updates the user's locking status", %{conn: conn} do
|
test "updates the user's locking status", %{conn: conn} do
|
||||||
@ -260,7 +260,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
test "update fields", %{conn: conn} do
|
test "update fields", %{conn: conn} do
|
||||||
fields = [
|
fields = [
|
||||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
|
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
%{"name" => "link.io", "value" => "cofe.io"}
|
||||||
]
|
]
|
||||||
|
|
||||||
account_data =
|
account_data =
|
||||||
@ -270,7 +270,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
|
|
||||||
assert account_data["fields"] == [
|
assert account_data["fields"] == [
|
||||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
||||||
%{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)}
|
%{
|
||||||
|
"name" => "link.io",
|
||||||
|
"value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert account_data["source"]["fields"] == [
|
assert account_data["source"]["fields"] == [
|
||||||
@ -278,14 +281,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
"name" => "<a href=\"http://google.com\">foo</a>",
|
"name" => "<a href=\"http://google.com\">foo</a>",
|
||||||
"value" => "<script>bar</script>"
|
"value" => "<script>bar</script>"
|
||||||
},
|
},
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
%{"name" => "link.io", "value" => "cofe.io"}
|
||||||
]
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "update fields via x-www-form-urlencoded", %{conn: conn} do
|
||||||
fields =
|
fields =
|
||||||
[
|
[
|
||||||
"fields_attributes[1][name]=link",
|
"fields_attributes[1][name]=link",
|
||||||
"fields_attributes[1][value]=cofe.io",
|
"fields_attributes[1][value]=http://cofe.io",
|
||||||
"fields_attributes[0][name]=<a href=\"http://google.com\">foo</a>",
|
"fields_attributes[0][name]=foo",
|
||||||
"fields_attributes[0][value]=bar"
|
"fields_attributes[0][value]=bar"
|
||||||
]
|
]
|
||||||
|> Enum.join("&")
|
|> Enum.join("&")
|
||||||
@ -297,51 +302,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert account["fields"] == [
|
assert account["fields"] == [
|
||||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
%{"name" => "foo", "value" => "bar"},
|
||||||
%{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)}
|
%{
|
||||||
|
"name" => "link",
|
||||||
|
"value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>)
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert account["source"]["fields"] == [
|
assert account["source"]["fields"] == [
|
||||||
%{
|
%{"name" => "foo", "value" => "bar"},
|
||||||
"name" => "<a href=\"http://google.com\">foo</a>",
|
%{"name" => "link", "value" => "http://cofe.io"}
|
||||||
"value" => "bar"
|
|
||||||
},
|
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
|
||||||
]
|
]
|
||||||
|
end
|
||||||
|
|
||||||
name_limit = Pleroma.Config.get([:instance, :account_field_name_length])
|
test "update fields with empty name", %{conn: conn} do
|
||||||
value_limit = Pleroma.Config.get([:instance, :account_field_value_length])
|
|
||||||
|
|
||||||
long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join()
|
|
||||||
|
|
||||||
fields = [%{"name" => "<b>foo<b>", "value" => long_value}]
|
|
||||||
|
|
||||||
assert %{"error" => "Invalid request"} ==
|
|
||||||
conn
|
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()
|
|
||||||
|
|
||||||
fields = [%{"name" => long_name, "value" => "bar"}]
|
|
||||||
|
|
||||||
assert %{"error" => "Invalid request"} ==
|
|
||||||
conn
|
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
Pleroma.Config.put([:instance, :max_account_fields], 1)
|
|
||||||
|
|
||||||
fields = [
|
|
||||||
%{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
|
|
||||||
%{"name" => "link", "value" => "cofe.io"}
|
|
||||||
]
|
|
||||||
|
|
||||||
assert %{"error" => "Invalid request"} ==
|
|
||||||
conn
|
|
||||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
%{"name" => "foo", "value" => ""},
|
%{"name" => "foo", "value" => ""},
|
||||||
%{"name" => "", "value" => "bar"}
|
%{"name" => "", "value" => "bar"}
|
||||||
@ -356,5 +330,39 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
|||||||
%{"name" => "foo", "value" => ""}
|
%{"name" => "foo", "value" => ""}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "update fields when invalid request", %{conn: conn} do
|
||||||
|
name_limit = Pleroma.Config.get([:instance, :account_field_name_length])
|
||||||
|
value_limit = Pleroma.Config.get([:instance, :account_field_value_length])
|
||||||
|
|
||||||
|
long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()
|
||||||
|
long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join()
|
||||||
|
|
||||||
|
fields = [%{"name" => "foo", "value" => long_value}]
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid request"} ==
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
fields = [%{"name" => long_name, "value" => "bar"}]
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid request"} ==
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
Pleroma.Config.put([:instance, :max_account_fields], 1)
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
%{"name" => "foo", "value" => "bar"},
|
||||||
|
%{"name" => "link", "value" => "cofe.io"}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid request"} ==
|
||||||
|
conn
|
||||||
|
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,11 +4,19 @@
|
|||||||
|
|
||||||
defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
import Pleroma.Factory
|
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
import Tesla.Mock
|
||||||
|
|
||||||
|
setup do
|
||||||
|
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
test "Represent a user account" do
|
test "Represent a user account" do
|
||||||
source_data = %{
|
source_data = %{
|
||||||
"tag" => [
|
"tag" => [
|
||||||
@ -32,7 +40,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||||||
background: background_image,
|
background: background_image,
|
||||||
nickname: "shp@shitposter.club",
|
nickname: "shp@shitposter.club",
|
||||||
name: ":karjalanpiirakka: shp",
|
name: ":karjalanpiirakka: shp",
|
||||||
bio: "<script src=\"invalid-html\"></script><span>valid html</span>",
|
bio:
|
||||||
|
"<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f",
|
||||||
inserted_at: ~N[2017-08-15 15:47:06.597036]
|
inserted_at: ~N[2017-08-15 15:47:06.597036]
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -46,7 +55,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||||||
followers_count: 3,
|
followers_count: 3,
|
||||||
following_count: 0,
|
following_count: 0,
|
||||||
statuses_count: 5,
|
statuses_count: 5,
|
||||||
note: "<span>valid html</span>",
|
note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f",
|
||||||
url: user.ap_id,
|
url: user.ap_id,
|
||||||
avatar: "http://localhost:4001/images/avi.png",
|
avatar: "http://localhost:4001/images/avi.png",
|
||||||
avatar_static: "http://localhost:4001/images/avi.png",
|
avatar_static: "http://localhost:4001/images/avi.png",
|
||||||
@ -63,7 +72,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||||||
fields: [],
|
fields: [],
|
||||||
bot: false,
|
bot: false,
|
||||||
source: %{
|
source: %{
|
||||||
note: "valid html",
|
note: "valid html. a\nb\nc\nd\nf",
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
actor_type: "Person",
|
actor_type: "Person",
|
||||||
@ -160,6 +169,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||||||
assert expected == AccountView.render("show.json", %{user: user})
|
assert expected == AccountView.render("show.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "Represent a Funkwhale channel" do
|
||||||
|
{:ok, user} =
|
||||||
|
User.get_or_fetch_by_ap_id(
|
||||||
|
"https://channels.tests.funkwhale.audio/federation/actors/compositions"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert represented = AccountView.render("show.json", %{user: user})
|
||||||
|
assert represented.acct == "compositions@channels.tests.funkwhale.audio"
|
||||||
|
assert represented.url == "https://channels.tests.funkwhale.audio/channels/compositions"
|
||||||
|
end
|
||||||
|
|
||||||
test "Represent a deactivated user for an admin" do
|
test "Represent a deactivated user for an admin" do
|
||||||
admin = insert(:user, is_admin: true)
|
admin = insert(:user, is_admin: true)
|
||||||
deactivated_user = insert(:user, deactivated: true)
|
deactivated_user = insert(:user, deactivated: true)
|
||||||
|
@ -420,6 +420,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||||||
assert length(represented[:media_attachments]) == 1
|
assert length(represented[:media_attachments]) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "funkwhale audio" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, object} =
|
||||||
|
Pleroma.Object.Fetcher.fetch_object_from_id(
|
||||||
|
"https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871"
|
||||||
|
)
|
||||||
|
|
||||||
|
%Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||||
|
|
||||||
|
represented = StatusView.render("show.json", %{for: user, activity: activity})
|
||||||
|
|
||||||
|
assert represented[:id] == to_string(activity.id)
|
||||||
|
assert length(represented[:media_attachments]) == 1
|
||||||
|
end
|
||||||
|
|
||||||
test "a Mobilizon event" do
|
test "a Mobilizon event" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
@ -581,7 +581,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
|
|||||||
# In case scope param is missing, expecting _all_ app-supported scopes to be granted
|
# In case scope param is missing, expecting _all_ app-supported scopes to be granted
|
||||||
for user <- [non_admin, admin],
|
for user <- [non_admin, admin],
|
||||||
{requested_scopes, expected_scopes} <-
|
{requested_scopes, expected_scopes} <-
|
||||||
%{scopes_subset => scopes_subset, nil => app_scopes} do
|
%{scopes_subset => scopes_subset, nil: app_scopes} do
|
||||||
conn =
|
conn =
|
||||||
post(
|
post(
|
||||||
build_conn(),
|
build_conn(),
|
||||||
|
Loading…
Reference in New Issue
Block a user