Merge remote-tracking branch 'soapbox/develop' into pleroma-events

This commit is contained in:
marcin mikołajczak 2022-09-30 20:04:29 +02:00
commit 58e0ca0d68
13 changed files with 142 additions and 4 deletions

View file

@ -262,7 +262,8 @@
max_endorsed_users: 20, max_endorsed_users: 20,
birthday_required: false, birthday_required: false,
birthday_min_age: 0, birthday_min_age: 0,
max_media_attachments: 1_000 max_media_attachments: 1_000,
migration_cooldown_period: 30
config :pleroma, :welcome, config :pleroma, :welcome,
direct_message: [ direct_message: [

View file

@ -1015,6 +1015,13 @@
description: description:
"Minimum required age (in days) for users to create account. Only used if birthday is required.", "Minimum required age (in days) for users to create account. Only used if birthday is required.",
suggestions: [6570] suggestions: [6570]
},
%{
key: :migration_cooldown_period,
type: :integer,
description:
"Number of days for which users won't be able to migrate account again after successful migration.",
suggestions: [30]
} }
] ]
}, },

View file

@ -160,6 +160,7 @@ defmodule Pleroma.User do
field(:show_birthday, :boolean, default: false) field(:show_birthday, :boolean, default: false)
field(:location, :string) field(:location, :string)
field(:language, :string) field(:language, :string)
field(:last_move_at, :naive_datetime)
embeds_one( embeds_one(
:notification_settings, :notification_settings,
@ -2707,4 +2708,10 @@ def get_friends_birthdays_query(%User{} = user, day, month) do
birthday_month: month birthday_month: month
}) })
end end
def update_last_move_at(%__MODULE__{local: true} = user) do
user
|> cast(%{last_move_at: NaiveDateTime.utc_now()}, [:last_move_at])
|> update_and_set_cache()
end
end end

View file

@ -457,6 +457,8 @@ def move(%User{} = origin, %User{} = target, local \\ true) do
"target_id" => target.id "target_id" => target.id
}) })
User.update_last_move_at(origin)
{:ok, activity} {:ok, activity}
else else
false -> {:error, "Target account must have the origin in `alsoKnownAs`"} false -> {:error, "Target account must have the origin in `alsoKnownAs`"}

View file

@ -229,7 +229,8 @@ def move_account_operation do
}), }),
400 => Operation.response("Error", "application/json", ApiError), 400 => Operation.response("Error", "application/json", ApiError),
403 => Operation.response("Error", "application/json", ApiError), 403 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError) 404 => Operation.response("Error", "application/json", ApiError),
429 => Operation.response("Error", "application/json", ApiError)
} }
} }
end end

View file

@ -51,7 +51,8 @@ def render("show.json", _) do
post_formats: Config.get([:instance, :allowed_post_formats]), post_formats: Config.get([:instance, :allowed_post_formats]),
privileged_staff: Config.get([:instance, :privileged_staff]), privileged_staff: Config.get([:instance, :privileged_staff]),
birthday_required: Config.get([:instance, :birthday_required]), birthday_required: Config.get([:instance, :birthday_required]),
birthday_min_age: Config.get([:instance, :birthday_min_age]) birthday_min_age: Config.get([:instance, :birthday_min_age]),
migration_cooldown_period: Config.get([:instance, :migration_cooldown_period])
}, },
stats: %{mau: Pleroma.User.active_user_count()}, stats: %{mau: Pleroma.User.active_user_count()},
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key), vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key),

View file

@ -259,6 +259,7 @@ def move_account(%{assigns: %{user: user}, body_params: body_params} = conn, %{}
case CommonAPI.Utils.confirm_current_password(user, body_params.password) do case CommonAPI.Utils.confirm_current_password(user, body_params.password) do
{:ok, user} -> {:ok, user} ->
with {:ok, target_user} <- find_or_fetch_user_by_nickname(body_params.target_account), with {:ok, target_user} <- find_or_fetch_user_by_nickname(body_params.target_account),
{:period, false} <- {:period, within_cooldown?(user)},
{:ok, _user} <- ActivityPub.move(user, target_user) do {:ok, _user} <- ActivityPub.move(user, target_user) do
json(conn, %{status: "success"}) json(conn, %{status: "success"})
else else
@ -267,6 +268,11 @@ def move_account(%{assigns: %{user: user}, body_params: body_params} = conn, %{}
|> put_status(404) |> put_status(404)
|> json(%{error: "Target account not found."}) |> json(%{error: "Target account not found."})
{:period, true} ->
conn
|> put_status(429)
|> json(%{error: "You are within cooldown period."})
{:error, error} -> {:error, error} ->
json(conn, %{error: error}) json(conn, %{error: error})
end end
@ -276,6 +282,19 @@ def move_account(%{assigns: %{user: user}, body_params: body_params} = conn, %{}
end end
end end
defp within_cooldown?(%{last_move_at: nil}), do: false
defp within_cooldown?(user) do
cooldown_period =
Pleroma.Config.get([:instance, :migration_cooldown_period], 0) * 60 * 60 * 24
now = NaiveDateTime.utc_now()
difference = NaiveDateTime.diff(now, user.last_move_at)
difference < cooldown_period
end
def add_alias(%{assigns: %{user: user}, body_params: body_params} = conn, _) do def add_alias(%{assigns: %{user: user}, body_params: body_params} = conn, _) do
with {:ok, alias_user} <- find_user_by_nickname(body_params.alias), with {:ok, alias_user} <- find_user_by_nickname(body_params.alias),
{:ok, _user} <- user |> User.add_alias(alias_user) do {:ok, _user} <- user |> User.add_alias(alias_user) do

View file

@ -22,7 +22,48 @@ def render("manifest.json", _params) do
], ],
serviceworker: %{ serviceworker: %{
src: "/sw.js" src: "/sw.js"
} },
share_target: %{
action: "share",
method: "GET",
params: %{
title: "title",
text: "text",
url: "url"
}
},
shortcuts: [
%{
name: "Search",
url: "/search",
icons: [
%{
src: "/images/shortcuts/search.png",
sizes: "192x192"
}
]
},
%{
name: "Notifications",
url: "/notifications",
icons: [
%{
src: "/images/shortcuts/notifications.png",
sizes: "192x192"
}
]
},
%{
name: "Chats",
url: "/chats",
icons: [
%{
src: "/images/shortcuts/chats.png",
sizes: "192x192"
}
]
}
]
} }
end end
end end

View file

@ -0,0 +1,13 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Repo.Migrations.AddLastMoveAtToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add(:last_move_at, :naive_datetime)
end
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -6,9 +6,11 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
use Oban.Testing, repo: Pleroma.Repo use Oban.Testing, repo: Pleroma.Repo
alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers alias Pleroma.Tests.ObanHelpers
alias Pleroma.User alias Pleroma.User
import Ecto.Changeset
import Pleroma.Factory import Pleroma.Factory
import Mock import Mock
@ -838,6 +840,50 @@ test "prefix nickname by @ should work", %{
refute User.following?(follower, user) refute User.following?(follower, user)
assert User.following?(follower, target_user) assert User.following?(follower, target_user)
end end
test "do not allow to migrate account within cooldown period", %{conn: conn, user: user} do
user
|> cast(
%{last_move_at: NaiveDateTime.utc_now() |> NaiveDateTime.add(-1 * 24 * 60 * 60, :second)},
[:last_move_at]
)
|> Repo.update()
target_user = insert(:user, also_known_as: [user.ap_id])
target_nick = target_user |> User.full_nickname()
conn =
conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/move_account", %{password: "test", target_account: target_nick})
assert json_response_and_validate_schema(conn, 429) == %{
"error" => "You are within cooldown period."
}
end
test "allow to migrate account after cooldown period", %{conn: conn, user: user} do
user
|> cast(
%{
last_move_at: NaiveDateTime.utc_now() |> NaiveDateTime.add(-31 * 24 * 60 * 60, :second)
},
[:last_move_at]
)
|> Repo.update()
target_user = insert(:user, also_known_as: [user.ap_id])
target_nick = target_user |> User.full_nickname()
conn =
conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/move_account", %{password: "test", target_account: target_nick})
assert json_response_and_validate_schema(conn, 200) == %{"status" => "success"}
end
end end
describe "GET /api/pleroma/aliases" do describe "GET /api/pleroma/aliases" do