Add migration cooldown period
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
54daefaecc
commit
c6fddd6e0a
9 changed files with 100 additions and 3 deletions
|
@ -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: [
|
||||||
|
|
|
@ -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]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -450,6 +450,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`"}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue