Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into emr_develop

This commit is contained in:
a1batross 2021-12-22 19:13:11 +01:00
commit b7851c87ad
39 changed files with 672 additions and 50 deletions

View File

@ -65,6 +65,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Attachment dimensions and blurhashes are federated when available.
- Mastodon API: support `poll` notification.
- Pinned posts federation
- AdminAPI: allow moderators to manage reports, users, invites, and custom emojis
### Fixed
- Don't crash so hard when email settings are invalid.

View File

@ -12,7 +12,7 @@ RUN apk add git gcc g++ musl-dev make cmake file-dev &&\
mkdir release &&\
mix release --path release
FROM alpine:3.11
FROM alpine:3.14
ARG BUILD_DATE
ARG VCS_REF
@ -31,8 +31,7 @@ LABEL maintainer="ops@pleroma.social" \
ARG HOME=/opt/pleroma
ARG DATA=/var/lib/pleroma
RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
apk update &&\
RUN apk update &&\
apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\
adduser --system --shell /bin/false --home ${HOME} pleroma &&\
mkdir -p ${DATA}/uploads &&\

View File

@ -139,6 +139,7 @@ config :pleroma, Pleroma.Web.Endpoint,
],
protocol: "https",
secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",
live_view: [signing_salt: "U5ELgdEwTD3n1+D5s0rY0AMg8/y1STxZ3Zvsl3bWh+oBcGrYdil0rXqPMRd3Glcq"],
signing_salt: "CqaoopA2",
render_errors: [view: Pleroma.Web.ErrorView, accepts: ~w(json)],
pubsub_server: Pleroma.PubSub,

View File

@ -261,6 +261,46 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
}
```
## `PATCH /api/v1/pleroma/admin/users/suggest`
### Suggest a user
Adds the user(s) to follower recommendations.
- Params:
- `nicknames`: nicknames array
- Response:
```json
{
users: [
{
// user object
}
]
}
```
## `PATCH /api/v1/pleroma/admin/users/unsuggest`
### Unsuggest a user
Removes the user(s) from follower recommendations.
- Params:
- `nicknames`: nicknames array
- Response:
```json
{
users: [
{
// user object
}
]
}
```
## `GET /api/v1/pleroma/admin/users/:nickname_or_id`
### Retrive the details of a user

View File

@ -199,6 +199,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
jwt_secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
lv_signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
template_dir = Application.app_dir(:pleroma, "priv") <> "/templates"
@ -217,6 +218,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
secret: secret,
jwt_secret: jwt_secret,
signing_salt: signing_salt,
lv_signing_salt: lv_signing_salt,
web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
web_push_private_key: Base.url_encode64(web_push_private_key, padding: false),
db_configurable?: db_configurable?,

View File

@ -9,7 +9,8 @@ defenum(Pleroma.UserRelationship.Type,
mute: 2,
reblog_mute: 3,
notification_mute: 4,
inverse_subscription: 5
inverse_subscription: 5,
suggestion_dismiss: 6
)
defenum(Pleroma.FollowingRelationship.State,

View File

@ -103,6 +103,7 @@ defmodule Pleroma.Emoji.Loader do
pack_file = Path.join(pack_dir, "pack.json")
if File.exists?(pack_file) do
Logger.info("Loading emoji pack from JSON: #{pack_file}")
contents = Jason.decode!(File.read!(pack_file))
contents["files"]
@ -115,6 +116,7 @@ defmodule Pleroma.Emoji.Loader do
emoji_txt = Path.join(pack_dir, "emoji.txt")
if File.exists?(emoji_txt) do
Logger.info("Loading emoji pack from emoji.txt: #{emoji_txt}")
load_from_file(emoji_txt, emoji_groups)
else
extensions = Config.get([:emoji, :pack_extensions])

View File

@ -338,6 +338,26 @@ defmodule Pleroma.ModerationLog do
"@#{actor_nickname} approved users: #{users_to_nicknames_string(users)}"
end
def get_log_entry_message(%ModerationLog{
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "add_suggestion",
"subject" => users
}
}) do
"@#{actor_nickname} added suggested users: #{users_to_nicknames_string(users)}"
end
def get_log_entry_message(%ModerationLog{
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "remove_suggestion",
"subject" => users
}
}) do
"@#{actor_nickname} removed suggested users: #{users_to_nicknames_string(users)}"
end
def get_log_entry_message(%ModerationLog{
data: %{
"actor" => %{"nickname" => actor_nickname},

View File

@ -148,6 +148,7 @@ defmodule Pleroma.User do
field(:last_active_at, :naive_datetime)
field(:disclose_client, :boolean, default: true)
field(:pinned_objects, :map, default: %{})
field(:is_suggested, :boolean, default: false)
embeds_one(
:notification_settings,
@ -1676,6 +1677,22 @@ defmodule Pleroma.User do
def confirm(%User{} = user), do: {:ok, user}
def set_suggestion(users, is_suggested) when is_list(users) do
Repo.transaction(fn ->
Enum.map(users, fn user ->
with {:ok, user} <- set_suggestion(user, is_suggested), do: user
end)
end)
end
def set_suggestion(%User{is_suggested: is_suggested} = user, is_suggested), do: {:ok, user}
def set_suggestion(%User{} = user, is_suggested) when is_boolean(is_suggested) do
user
|> change(is_suggested: is_suggested)
|> update_and_set_cache()
end
def update_notification_settings(%User{} = user, settings) do
user
|> cast(%{notification_settings: settings}, [])

View File

@ -46,6 +46,7 @@ defmodule Pleroma.User.Query do
unconfirmed: boolean(),
is_admin: boolean(),
is_moderator: boolean(),
is_suggested: boolean(),
super_users: boolean(),
invisible: boolean(),
internal: boolean(),
@ -167,6 +168,10 @@ defmodule Pleroma.User.Query do
where(query, [u], u.is_confirmed == false)
end
defp compose_query({:is_suggested, bool}, query) do
where(query, [u], u.is_suggested == ^bool)
end
defp compose_query({:followers, %User{id: id}}, query) do
query
|> where([u], u.id != ^id)

View File

@ -200,7 +200,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:ok, notifications} = Notification.create_notifications(activity, do_send: false)
{:ok, _user} = ActivityPub.increase_note_count_if_public(user, object)
if in_reply_to = object.data["inReplyTo"] && object.data["type"] != "Answer" do
if in_reply_to = object.data["type"] != "Answer" && object.data["inReplyTo"] do
Object.increase_replies_count(in_reply_to)
end

View File

@ -35,7 +35,9 @@ defmodule Pleroma.Web.AdminAPI.UserController do
:toggle_activation,
:activate,
:deactivate,
:approve
:approve,
:suggest,
:unsuggest
]
)
@ -239,6 +241,32 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users)
end
def suggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_suggestion(users, true)
ModerationLog.insert_log(%{
actor: admin,
subject: users,
action: "add_suggestion"
})
render(conn, "index.json", users: updated_users)
end
def unsuggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_suggestion(users, false)
ModerationLog.insert_log(%{
actor: admin,
subject: users,
action: "remove_suggestion"
})
render(conn, "index.json", users: updated_users)
end
def index(conn, params) do
{page, page_size} = page_params(params)
filters = maybe_parse_filters(params[:filters])

View File

@ -80,6 +80,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
"tags" => user.tags || [],
"is_confirmed" => user.is_confirmed,
"is_approved" => user.is_approved,
"is_suggested" => user.is_suggested,
"url" => user.uri || user.ap_id,
"registration_reason" => user.registration_reason,
"actor_type" => user.actor_type,

View File

@ -216,7 +216,71 @@ defmodule Pleroma.Web.ApiSpec.Admin.UserOperation do
request_body(
"Parameters",
%Schema{
description: "POST body for deleting multiple users",
description: "POST body for approving multiple users",
type: :object,
properties: %{
nicknames: %Schema{
type: :array,
items: %Schema{type: :string}
}
}
}
),
responses: %{
200 =>
Operation.response("Response", "application/json", %Schema{
type: :object,
properties: %{user: %Schema{type: :array, items: user()}}
}),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
def suggest_operation do
%Operation{
tags: ["User administration"],
summary: "Suggest multiple users",
operationId: "AdminAPI.UserController.suggest",
security: [%{"oAuth" => ["admin:write:accounts"]}],
parameters: admin_api_params(),
requestBody:
request_body(
"Parameters",
%Schema{
description: "POST body for adding multiple suggested users",
type: :object,
properties: %{
nicknames: %Schema{
type: :array,
items: %Schema{type: :string}
}
}
}
),
responses: %{
200 =>
Operation.response("Response", "application/json", %Schema{
type: :object,
properties: %{user: %Schema{type: :array, items: user()}}
}),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
def unsuggest_operation do
%Operation{
tags: ["User administration"],
summary: "Unsuggest multiple users",
operationId: "AdminAPI.UserController.unsuggest",
security: [%{"oAuth" => ["admin:write:accounts"]}],
parameters: admin_api_params(),
requestBody:
request_body(
"Parameters",
%Schema{
description: "POST body for removing multiple suggested users",
type: :object,
properties: %{
nicknames: %Schema{

View File

@ -10,6 +10,7 @@ defmodule Pleroma.Web.Endpoint do
alias Pleroma.Config
socket("/socket", Pleroma.Web.UserSocket)
socket("/live", Phoenix.LiveView.Socket)
plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint])

View File

@ -0,0 +1,14 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ManifestController do
use Pleroma.Web, :controller
plug(:skip_auth when action == :show)
@doc "GET /manifest.json"
def show(conn, _params) do
render(conn, "manifest.json")
end
end

View File

@ -17,6 +17,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
require Logger
@search_limit 40
plug(Pleroma.Web.ApiSpec.CastAndValidate)
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
@ -77,7 +79,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
[
resolve: params[:resolve],
following: params[:following],
limit: params[:limit],
limit: min(params[:limit], @search_limit),
offset: params[:offset],
type: params[:type],
author: get_author(params),

View File

@ -4,11 +4,16 @@
defmodule Pleroma.Web.MastodonAPI.SuggestionController do
use Pleroma.Web, :controller
import Ecto.Query
alias Pleroma.FollowingRelationship
alias Pleroma.User
alias Pleroma.UserRelationship
require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["read"]} when action == :index)
plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["read"]} when action in [:index, :index2])
plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["write"]} when action in [:dismiss])
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
@ -26,7 +31,90 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
}
end
def index2_operation do
%OpenApiSpex.Operation{
tags: ["Suggestions"],
summary: "Follow suggestions",
operationId: "SuggestionController.index2",
responses: %{
200 => Pleroma.Web.ApiSpec.Helpers.empty_array_response()
}
}
end
def dismiss_operation do
%OpenApiSpex.Operation{
tags: ["Suggestions"],
summary: "Remove a suggestion",
operationId: "SuggestionController.dismiss",
parameters: [
OpenApiSpex.Operation.parameter(
:account_id,
:path,
%OpenApiSpex.Schema{type: :string},
"Account to dismiss",
required: true
)
],
responses: %{
200 => Pleroma.Web.ApiSpec.Helpers.empty_object_response()
}
}
end
@doc "GET /api/v1/suggestions"
def index(conn, params),
do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params)
@doc "GET /api/v2/suggestions"
def index2(%{assigns: %{user: user}} = conn, params) do
limit = Map.get(params, :limit, 40) |> min(80)
users =
%{is_suggested: true, invisible: false, limit: limit}
|> User.Query.build()
|> exclude_user(user)
|> exclude_relationships(user, [:block, :mute, :suggestion_dismiss])
|> exclude_following(user)
|> Pleroma.Repo.all()
render(conn, "index.json", %{
users: users,
source: :staff,
for: user,
skip_visibility_check: true
})
end
defp exclude_user(query, %User{id: user_id}) do
where(query, [u], u.id != ^user_id)
end
defp exclude_relationships(query, %User{id: user_id}, relationship_types) do
query
|> join(:left, [u], r in UserRelationship,
as: :user_relationships,
on:
r.target_id == u.id and r.source_id == ^user_id and
r.relationship_type in ^relationship_types
)
|> where([user_relationships: r], is_nil(r.target_id))
end
defp exclude_following(query, %User{id: user_id}) do
query
|> join(:left, [u], r in FollowingRelationship,
as: :following_relationships,
on: r.following_id == u.id and r.follower_id == ^user_id and r.state == :follow_accept
)
|> where([following_relationships: r], is_nil(r.following_id))
end
@doc "DELETE /api/v1/suggestions/:account_id"
def dismiss(%{assigns: %{user: source}} = conn, %{account_id: user_id}) do
with %User{} = target <- User.get_cached_by_id(user_id),
{:ok, _} <- UserRelationship.create(:suggestion_dismiss, source, target) do
json(conn, %{})
end
end
end

View File

@ -269,6 +269,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
ap_id: user.ap_id,
also_known_as: user.also_known_as,
is_confirmed: user.is_confirmed,
is_suggested: user.is_suggested,
tags: user.tags,
hide_followers_count: user.hide_followers_count,
hide_follows_count: user.hide_follows_count,

View File

@ -59,6 +59,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
"mastodon_api",
"mastodon_api_streaming",
"polls",
"v2_suggestions",
"pleroma_explicit_addressing",
"shareable_emoji_packs",
"multifetch",
@ -83,7 +84,10 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
"safe_dm_mentions"
end,
"pleroma_emoji_reactions",
"pleroma_chat_messages"
"pleroma_chat_messages",
if Config.get([:instance, :show_reactions]) do
"exposable_reactions"
end
]
|> Enum.filter(& &1)
end

View File

@ -0,0 +1,28 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.SuggestionView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI.AccountView
@source_types [:staff, :global, :past_interactions]
def render("index.json", %{users: users} = opts) do
Enum.map(users, fn user ->
opts =
opts
|> Map.put(:user, user)
|> Map.delete(:users)
render("show.json", opts)
end)
end
def render("show.json", %{source: source, user: _user} = opts) when source in @source_types do
%{
source: source,
account: AccountView.render("show.json", opts)
}
end
end

View File

@ -151,7 +151,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
index_query(user, params)
|> Pagination.fetch_paginated(params)
render(conn, "index.json", chats: chats)
conn
|> add_link_headers(chats)
|> render("index.json", chats: chats)
end
defp index_query(%{id: user_id} = user, params) do

View File

@ -4,6 +4,7 @@
defmodule Pleroma.Web.Router do
use Pleroma.Web, :router
import Phoenix.LiveDashboard.Router
pipeline :accepts_html do
plug(:accepts, ["html"])
@ -157,12 +158,11 @@ defmodule Pleroma.Web.Router do
post("/uploader_callback/:upload_path", UploaderController, :callback)
end
# AdminAPI: only admins can perform these actions
scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
pipe_through([:admin_api, :require_admin])
put("/users/disable_mfa", AdminAPIController, :disable_mfa)
put("/users/tag", AdminAPIController, :tag_users)
delete("/users/tag", AdminAPIController, :untag_users)
get("/users/:nickname/permission_group", AdminAPIController, :right_get)
get("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_get)
@ -185,16 +185,61 @@ defmodule Pleroma.Web.Router do
post("/users/follow", UserController, :follow)
post("/users/unfollow", UserController, :unfollow)
delete("/users", UserController, :delete)
post("/users", UserController, :create)
patch("/users/suggest", UserController, :suggest)
patch("/users/unsuggest", UserController, :unsuggest)
get("/relay", RelayController, :index)
post("/relay", RelayController, :follow)
delete("/relay", RelayController, :unfollow)
get("/users/:nickname/password_reset", AdminAPIController, :get_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("/instance_document/:name", InstanceDocumentController, :show)
patch("/instance_document/:name", InstanceDocumentController, :update)
delete("/instance_document/:name", InstanceDocumentController, :delete)
patch("/users/confirm_email", AdminAPIController, :confirm_email)
patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email)
get("/config", ConfigController, :show)
post("/config", ConfigController, :update)
get("/config/descriptions", ConfigController, :descriptions)
get("/need_reboot", AdminAPIController, :need_reboot)
get("/restart", AdminAPIController, :restart)
get("/oauth_app", OAuthAppController, :index)
post("/oauth_app", OAuthAppController, :create)
patch("/oauth_app/:id", OAuthAppController, :update)
delete("/oauth_app/:id", OAuthAppController, :delete)
get("/media_proxy_caches", MediaProxyCacheController, :index)
post("/media_proxy_caches/delete", MediaProxyCacheController, :delete)
post("/media_proxy_caches/purge", MediaProxyCacheController, :purge)
get("/frontends", FrontendController, :index)
post("/frontends/install", FrontendController, :install)
post("/backups", AdminAPIController, :create_backup)
end
# AdminAPI: admins and mods (staff) can perform these actions
scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
pipe_through(:admin_api)
put("/users/tag", AdminAPIController, :tag_users)
delete("/users/tag", AdminAPIController, :untag_users)
patch("/users/:nickname/toggle_activation", UserController, :toggle_activation)
patch("/users/activate", UserController, :activate)
patch("/users/deactivate", UserController, :deactivate)
patch("/users/approve", UserController, :approve)
get("/relay", RelayController, :index)
post("/relay", RelayController, :follow)
delete("/relay", RelayController, :unfollow)
delete("/users", UserController, :delete)
post("/users/invite_token", InviteController, :create)
get("/users/invites", InviteController, :index)
@ -214,13 +259,6 @@ defmodule Pleroma.Web.Router do
get("/instances/:instance/statuses", InstanceController, :list_statuses)
delete("/instances/:instance", InstanceController, :delete)
get("/instance_document/:name", InstanceDocumentController, :show)
patch("/instance_document/:name", InstanceDocumentController, :update)
delete("/instance_document/:name", InstanceDocumentController, :delete)
patch("/users/confirm_email", AdminAPIController, :confirm_email)
patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email)
get("/reports", ReportController, :index)
get("/reports/:id", ReportController, :show)
patch("/reports", ReportController, :update)
@ -232,39 +270,19 @@ defmodule Pleroma.Web.Router do
delete("/statuses/:id", StatusController, :delete)
get("/statuses", StatusController, :index)
get("/config", ConfigController, :show)
post("/config", ConfigController, :update)
get("/config/descriptions", ConfigController, :descriptions)
get("/need_reboot", AdminAPIController, :need_reboot)
get("/restart", AdminAPIController, :restart)
get("/moderation_log", AdminAPIController, :list_log)
post("/reload_emoji", AdminAPIController, :reload_emoji)
get("/stats", AdminAPIController, :stats)
get("/oauth_app", OAuthAppController, :index)
post("/oauth_app", OAuthAppController, :create)
patch("/oauth_app/:id", OAuthAppController, :update)
delete("/oauth_app/:id", OAuthAppController, :delete)
get("/media_proxy_caches", MediaProxyCacheController, :index)
post("/media_proxy_caches/delete", MediaProxyCacheController, :delete)
post("/media_proxy_caches/purge", MediaProxyCacheController, :purge)
get("/chats/:id", ChatController, :show)
get("/chats/:id/messages", ChatController, :messages)
delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
get("/frontends", FrontendController, :index)
post("/frontends/install", FrontendController, :install)
post("/backups", AdminAPIController, :create_backup)
end
scope "/api/v1/pleroma/emoji", Pleroma.Web.PleromaAPI do
scope "/pack" do
pipe_through([:admin_api, :require_admin])
pipe_through(:admin_api)
post("/", EmojiPackController, :create)
patch("/", EmojiPackController, :update)
@ -279,7 +297,7 @@ defmodule Pleroma.Web.Router do
# Modifying packs
scope "/packs" do
pipe_through([:admin_api, :require_admin])
pipe_through(:admin_api)
get("/import", EmojiPackController, :import_from_filesystem)
get("/remote", EmojiPackController, :remote)
@ -535,6 +553,7 @@ defmodule Pleroma.Web.Router do
delete("/push/subscription", SubscriptionController, :delete)
get("/suggestions", SuggestionController, :index)
delete("/suggestions/:account_id", SuggestionController, :dismiss)
get("/timelines/home", TimelineController, :home)
get("/timelines/direct", TimelineController, :direct)
@ -586,6 +605,8 @@ defmodule Pleroma.Web.Router do
get("/search", SearchController, :search2)
post("/media", MediaController, :create2)
get("/suggestions", SuggestionController, :index2)
end
scope "/api", Pleroma.Web do
@ -736,6 +757,12 @@ defmodule Pleroma.Web.Router do
get("/:version", Nodeinfo.NodeinfoController, :nodeinfo)
end
scope "/", Pleroma.Web do
pipe_through(:api)
get("/manifest.json", ManifestController, :show)
end
scope "/", Pleroma.Web do
pipe_through(:pleroma_html)
@ -757,6 +784,11 @@ defmodule Pleroma.Web.Router do
end
end
scope "/" do
pipe_through([:pleroma_html, :authenticate, :require_admin])
live_dashboard("/phoenix/live_dashboard")
end
# Test-only routes needed to test action dispatching and plug chain execution
if Pleroma.Config.get(:env) == :test do
@test_actions [

View File

@ -0,0 +1,28 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ManifestView do
use Pleroma.Web, :view
alias Pleroma.Config
alias Pleroma.Web.Endpoint
def render("manifest.json", _params) do
%{
name: Config.get([:instance, :name]),
description: Config.get([:instance, :description]),
icons: Config.get([:manifest, :icons]),
theme_color: Config.get([:manifest, :theme_color]),
background_color: Config.get([:manifest, :background_color]),
display: "standalone",
scope: Endpoint.url(),
start_url: "/",
categories: [
"social"
],
serviceworker: %{
src: "/sw.js"
}
}
end
end

View File

@ -79,6 +79,7 @@ defmodule Pleroma.Mixfile do
:comeonin,
:quack,
:fast_sanitize,
:os_mon,
:ssl
],
included_applications: [:ex_syslogger]
@ -131,7 +132,7 @@ defmodule Pleroma.Mixfile do
{:trailing_format_plug, "~> 0.0.7"},
{:fast_sanitize, "~> 0.2.0"},
{:html_entities, "~> 0.5", override: true},
{:phoenix_html, "~> 2.14"},
{:phoenix_html, "~> 3.1", override: true},
{:calendar, "~> 1.0"},
{:cachex, "~> 3.2"},
{:poison, "~> 3.0", override: true},
@ -199,6 +200,8 @@ defmodule Pleroma.Mixfile do
ref: "289cda1b6d0d70ccb2ba508a2b0bd24638db2880"},
{:eblurhash, "~> 1.1.0"},
{:open_api_spex, "~> 3.10"},
{:phoenix_live_dashboard, "~> 0.6.2"},
{:ecto_psql_extras, "~> 0.6"},
# indirect dependency version override
{:plug, "~> 1.10.4", override: true},

View File

@ -32,6 +32,7 @@
"eblurhash": {:hex, :eblurhash, "1.1.0", "e10ccae762598507ebfacf0b645ed49520f2afa3e7e9943e73a91117dffce415", [:rebar3], [], "hexpm", "2e6b889d09fddd374e3c5ac57c486138768763264e99ac1074ae5fa7fc9ab51d"},
"ecto": {:hex, :ecto, "3.6.2", "efdf52acfc4ce29249bab5417415bd50abd62db7b0603b8bab0d7b996548c2bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "efad6dfb04e6f986b8a3047822b0f826d9affe8e4ebdd2aeedbfcb14fd48884e"},
"ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.4", "5d43fd088d39a158c860b17e8d210669587f63ec89ea122a4654861c8c6e2db4", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.15.7", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "311db02f1b772e3d0dc7f56a05044b5e1499d78ed6abf38885e1ca70059449e5"},
"ecto_sql": {:hex, :ecto_sql, "3.6.2", "9526b5f691701a5181427634c30655ac33d11e17e4069eff3ae1176c764e0ba3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ec9d7e6f742ea39b63aceaea9ac1d1773d574ea40df5a53ef8afbd9242fdb6b"},
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
@ -91,7 +92,9 @@
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"},
"phoenix": {:hex, :phoenix, "1.5.9", "a6368d36cfd59d917b37c44386e01315bc89f7609a10a45a22f47c007edf2597", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7e4bce20a67c012f1fbb0af90e5da49fa7bf0d34e3a067795703b74aef75427d"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
"phoenix_html": {:hex, :phoenix_html, "3.1.0", "0b499df05aad27160d697a9362f0e89fa0e24d3c7a9065c2bd9d38b4d1416c09", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0c0a98a2cefa63433657983a2a594c7dee5927e4391e0f1bfd3a151d1def33fc"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.2", "0769470265eb13af01b5001b29cb935f4710d6adaa1ffc18417a570a337a2f0f", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5bc6c6b38a2ca8b5020b442322fcee6afd5e641637a0b1fb059d4bd89bc58e7b"},
"phoenix_live_view": {:hex, :phoenix_live_view, "0.17.5", "63f52a6f9f6983f04e424586ff897c016ecc5e4f8d1e2c22c2887af1c57215d8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c5586e6a3d4df71b8214c769d4f5eb8ece2b4001711a7ca0f97323c36958b0e3"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
"phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.3", "039435dd975f7e55953525b88f1d596f26c6141412584c16f4db109708a8ee68", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "4a540cea32e05356541737033d666ee7fea7700eb2101bf76783adbfe06601cd"},
"plug": {:hex, :plug, "1.10.4", "41eba7d1a2d671faaf531fa867645bd5a3dce0957d8e2a3f398ccff7d2ef017f", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad1e233fe73d2eec56616568d260777b67f53148a999dc2d048f4eb9778fe4a0"},
@ -117,7 +120,9 @@
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"},
"swoosh": {:hex, :swoosh, "1.3.11", "34f79c57f19892b43bd2168de9ff5de478a721a26328ef59567aad4243e7a77b", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "f1e2a048db454f9982b9cf840f75e7399dd48be31ecc2a7dc10012a803b913af"},
"syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
"table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"},
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
"tesla": {:hex, :tesla, "1.4.1", "ff855f1cac121e0d16281b49e8f066c4a0d89965f98864515713878cca849ac8", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "95f5de35922c8c4b3945bee7406f66eb680b0955232f78f5fb7e853aa1ce201a"},
"timex": {:hex, :timex, "3.7.5", "3eca56e23bfa4e0848f0b0a29a92fa20af251a975116c6d504966e8a90516dfd", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "a15608dca680f2ef663d71c95842c67f0af08a0f3b1d00e17bbd22872e2874e4"},
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},

View File

@ -0,0 +1,11 @@
defmodule Pleroma.Repo.Migrations.AddSuggestions do
use Ecto.Migration
def change do
alter table(:users) do
add(:is_suggested, :boolean, default: false, null: false)
end
create_if_not_exists(index(:users, [:is_suggested]))
end
end

View File

@ -13,6 +13,7 @@ config :pleroma, Pleroma.Web.Endpoint,
url: [host: "<%= domain %>", scheme: "https", port: <%= port %>],
http: [ip: {<%= String.replace(listen_ip, ".", ", ") %>}, port: <%= listen_port %>],
secret_key_base: "<%= secret %>",
live_view: [signing_salt: "<%= lv_signing_salt %>"],
signing_salt: "<%= signing_salt %>"
config :pleroma, :instance,

View File

@ -82,6 +82,7 @@ defmodule Pleroma.Config.TransferTaskTest do
on_exit(fn -> Restarter.Pleroma.refresh() end)
end
@tag :erratic
test "don't restart if no reboot time settings were changed" do
clear_config(:emoji)
insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]])
@ -92,18 +93,21 @@ defmodule Pleroma.Config.TransferTaskTest do
)
end
@tag :erratic
test "on reboot time key" do
clear_config(:shout)
insert(:config, key: :shout, value: [enabled: false])
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
end
@tag :erratic
test "on reboot time subkey" do
clear_config(Pleroma.Captcha)
insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
end
@tag :erratic
test "don't restart pleroma on reboot time key and subkey if there is false flag" do
clear_config(:shout)
clear_config(Pleroma.Captcha)

View File

@ -34,4 +34,14 @@ defmodule Pleroma.User.QueryTest do
assert %{internal: true} |> Query.build() |> Repo.aggregate(:count) == 2
end
end
test "is_suggested param" do
_user1 = insert(:user, is_suggested: false)
user2 = insert(:user, is_suggested: true)
assert [^user2] =
%{is_suggested: true}
|> User.Query.build()
|> Repo.all()
end
end

View File

@ -1718,6 +1718,38 @@ defmodule Pleroma.UserTest do
assert user.banner == %{}
end
describe "set_suggestion" do
test "suggests a user" do
user = insert(:user, is_suggested: false)
refute user.is_suggested
{:ok, user} = User.set_suggestion(user, true)
assert user.is_suggested
end
test "suggests a list of users" do
unsuggested_users = [
insert(:user, is_suggested: false),
insert(:user, is_suggested: false),
insert(:user, is_suggested: false)
]
{:ok, users} = User.set_suggestion(unsuggested_users, true)
assert Enum.count(users) == 3
Enum.each(users, fn user ->
assert user.is_suggested
end)
end
test "unsuggests a user" do
user = insert(:user, is_suggested: true)
assert user.is_suggested
{:ok, user} = User.set_suggestion(user, false)
refute user.is_suggested
end
end
test "get_public_key_for_ap_id fetches a user that's not in the db" do
assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
end

View File

@ -873,6 +873,56 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
"@#{admin.nickname} approved users: @#{user_one.nickname}, @#{user_two.nickname}"
end
test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do
user1 = insert(:user, is_suggested: false)
user2 = insert(:user, is_suggested: false)
response =
conn
|> put_req_header("content-type", "application/json")
|> patch(
"/api/pleroma/admin/users/suggest",
%{nicknames: [user1.nickname, user2.nickname]}
)
|> json_response_and_validate_schema(200)
assert Enum.map(response["users"], & &1["is_suggested"]) == [true, true]
[user1, user2] = Repo.reload!([user1, user2])
assert user1.is_suggested
assert user2.is_suggested
log_entry = Repo.one(ModerationLog)
assert ModerationLog.get_log_entry_message(log_entry) ==
"@#{admin.nickname} added suggested users: @#{user1.nickname}, @#{user2.nickname}"
end
test "PATCH /api/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do
user1 = insert(:user, is_suggested: true)
user2 = insert(:user, is_suggested: true)
response =
conn
|> put_req_header("content-type", "application/json")
|> patch(
"/api/pleroma/admin/users/unsuggest",
%{nicknames: [user1.nickname, user2.nickname]}
)
|> json_response_and_validate_schema(200)
assert Enum.map(response["users"], & &1["is_suggested"]) == [false, false]
[user1, user2] = Repo.reload!([user1, user2])
refute user1.is_suggested
refute user2.is_suggested
log_entry = Repo.one(ModerationLog)
assert ModerationLog.get_log_entry_message(log_entry) ==
"@#{admin.nickname} removed suggested users: @#{user1.nickname}, @#{user2.nickname}"
end
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
user = insert(:user)
@ -906,6 +956,7 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
"display_name" => HTML.strip_tags(user.name || user.nickname),
"is_confirmed" => true,
"is_approved" => true,
"is_suggested" => false,
"url" => user.ap_id,
"registration_reason" => nil,
"actor_type" => "Person",

View File

@ -0,0 +1,17 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ManifestControllerTest do
use Pleroma.Web.ConnCase
setup do
clear_config([:instance, :name], "Manifest Test")
clear_config([:manifest, :theme_color], "#ff0000")
end
test "manifest.json", %{conn: conn} do
conn = get(conn, "/manifest.json")
assert %{"name" => "Manifest Test", "theme_color" => "#ff0000"} = json_response(conn, 200)
end
end

View File

@ -4,8 +4,11 @@
defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
use Pleroma.Web.ConnCase, async: true
alias Pleroma.UserRelationship
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
setup do: oauth_access(["read"])
setup do: oauth_access(["read", "write"])
test "returns empty result", %{conn: conn} do
res =
@ -15,4 +18,66 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
assert res == []
end
test "returns v2 suggestions", %{conn: conn} do
%{id: user_id} = insert(:user, is_suggested: true)
res =
conn
|> get("/api/v2/suggestions")
|> json_response_and_validate_schema(200)
assert [%{"source" => "staff", "account" => %{"id" => ^user_id}}] = res
end
test "returns v2 suggestions excluding dismissed accounts", %{conn: conn} do
%{id: user_id} = insert(:user, is_suggested: true)
conn
|> delete("/api/v1/suggestions/#{user_id}")
|> json_response_and_validate_schema(200)
res =
conn
|> get("/api/v2/suggestions")
|> json_response_and_validate_schema(200)
assert [] = res
end
test "returns v2 suggestions excluding blocked accounts", %{conn: conn, user: blocker} do
blocked = insert(:user, is_suggested: true)
{:ok, _} = CommonAPI.block(blocker, blocked)
res =
conn
|> get("/api/v2/suggestions")
|> json_response_and_validate_schema(200)
assert [] = res
end
test "returns v2 suggestions excluding followed accounts", %{conn: conn, user: follower} do
followed = insert(:user, is_suggested: true)
{:ok, _, _, _} = CommonAPI.follow(follower, followed)
res =
conn
|> get("/api/v2/suggestions")
|> json_response_and_validate_schema(200)
assert [] = res
end
test "dismiss suggestion", %{conn: conn, user: source} do
target = insert(:user, is_suggested: true)
res =
conn
|> delete("/api/v1/suggestions/#{target.id}")
|> json_response_and_validate_schema(200)
assert res == %{}
assert UserRelationship.exists?(:suggestion_dismiss, source, target)
end
end

View File

@ -83,6 +83,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
tags: [],
is_admin: false,
is_moderator: false,
is_suggested: false,
hide_favorites: true,
hide_followers: false,
hide_follows: false,
@ -183,6 +184,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
tags: [],
is_admin: false,
is_moderator: false,
is_suggested: false,
hide_favorites: true,
hide_followers: false,
hide_follows: false,

View File

@ -0,0 +1,34 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.SuggestionViewTest do
use Pleroma.DataCase, async: true
import Pleroma.Factory
alias Pleroma.Web.MastodonAPI.SuggestionView, as: View
test "show.json" do
user = insert(:user, is_suggested: true)
json = View.render("show.json", %{user: user, source: :staff, skip_visibility_check: true})
assert json.source == :staff
assert json.account.id == user.id
end
test "index.json" do
user1 = insert(:user, is_suggested: true)
user2 = insert(:user, is_suggested: true)
user3 = insert(:user, is_suggested: true)
[suggestion1, suggestion2, suggestion3] =
View.render("index.json", %{
users: [user1, user2, user3],
source: :staff,
skip_visibility_check: true
})
assert suggestion1.source == :staff
assert suggestion2.account.id == user2.id
assert suggestion3.account.url == user3.ap_id
end
end

View File

@ -94,8 +94,10 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
"internal",
".well-known",
"nodeinfo",
"manifest.json",
"auth",
"proxy",
"phoenix",
"test",
"user_exists",
"check_password"

View File

@ -48,6 +48,7 @@ defmodule Pleroma.Web.Plugs.RateLimiterTest do
refute RateLimiter.disabled?(build_conn())
end
@tag :erratic
test "it restricts based on config values" do
limiter_name = :test_plug_opts
scale = 80
@ -137,6 +138,7 @@ defmodule Pleroma.Web.Plugs.RateLimiterTest do
end
describe "unauthenticated users" do
@tag :erratic
test "are restricted based on remote IP" do
limiter_name = :test_unauthenticated
clear_config([:rate_limit, limiter_name], [{1000, 5}, {1, 10}])
@ -174,6 +176,7 @@ defmodule Pleroma.Web.Plugs.RateLimiterTest do
:ok
end
@tag :erratic
test "can have limits separate from unauthenticated connections" do
limiter_name = :test_authenticated1
@ -199,6 +202,7 @@ defmodule Pleroma.Web.Plugs.RateLimiterTest do
assert conn.halted
end
@tag :erratic
test "different users are counted independently" do
limiter_name = :test_authenticated2
clear_config([:rate_limit, limiter_name], [{1, 10}, {1000, 5}])

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
os_exclude = if :os.type() == {:unix, :darwin}, do: [skip_on_mac: true], else: []
ExUnit.start(exclude: [:federated | os_exclude])
ExUnit.start(exclude: [:federated, :erratic] ++ os_exclude)
Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual)