Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
This commit is contained in:
commit
c137545a84
7 changed files with 147 additions and 25 deletions
|
@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
### Security
|
||||
- OStatus: eliminate the possibility of a protocol downgrade attack.
|
||||
- OStatus: prevent following locked accounts, bypassing the approval process.
|
||||
- Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
|
||||
|
||||
### Removed
|
||||
- **Breaking:** GNU Social API with Qvitter extensions support
|
||||
|
|
|
@ -174,11 +174,25 @@ def following_count(%User{} = user) do
|
|||
|> Repo.aggregate(:count, :id)
|
||||
end
|
||||
|
||||
defp truncate_if_exists(params, key, max_length) do
|
||||
if Map.has_key?(params, key) and is_binary(params[key]) do
|
||||
{value, _chopped} = String.split_at(params[key], max_length)
|
||||
Map.put(params, key, value)
|
||||
else
|
||||
params
|
||||
end
|
||||
end
|
||||
|
||||
def remote_user_creation(params) do
|
||||
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
|
||||
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
|
||||
|
||||
params = Map.put(params, :info, params[:info] || %{})
|
||||
params =
|
||||
params
|
||||
|> Map.put(:info, params[:info] || %{})
|
||||
|> truncate_if_exists(:name, name_limit)
|
||||
|> truncate_if_exists(:bio, bio_limit)
|
||||
|
||||
info_cng = User.Info.remote_user_creation(%User.Info{}, params[:info])
|
||||
|
||||
changes =
|
||||
|
|
|
@ -242,6 +242,13 @@ def set_keys(info, keys) do
|
|||
end
|
||||
|
||||
def remote_user_creation(info, params) do
|
||||
params =
|
||||
if Map.has_key?(params, :fields) do
|
||||
Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
|
||||
else
|
||||
params
|
||||
end
|
||||
|
||||
info
|
||||
|> cast(params, [
|
||||
:ap_enabled,
|
||||
|
@ -326,6 +333,16 @@ defp valid_field?(%{"name" => name, "value" => value}) do
|
|||
|
||||
defp valid_field?(_), do: false
|
||||
|
||||
defp truncate_field(%{"name" => name, "value" => value}) do
|
||||
{name, _chopped} =
|
||||
String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
|
||||
|
||||
{value, _chopped} =
|
||||
String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
|
||||
|
||||
%{"name" => name, "value" => value}
|
||||
end
|
||||
|
||||
@spec confirmation_changeset(Info.t(), keyword()) :: Changeset.t()
|
||||
def confirmation_changeset(info, opts) do
|
||||
need_confirmation? = Keyword.get(opts, :need_confirmation)
|
||||
|
|
|
@ -842,6 +842,7 @@ def get_mascot(%{assigns: %{user: user}} = conn, _params) do
|
|||
|
||||
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
|
||||
%Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
|
||||
q = from(u in User, where: u.ap_id in ^likes)
|
||||
|
||||
|
@ -853,12 +854,14 @@ def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
|> put_view(AccountView)
|
||||
|> render("accounts.json", %{for: user, users: users, as: :user})
|
||||
else
|
||||
{:visible, false} -> {:error, :not_found}
|
||||
_ -> json(conn, [])
|
||||
end
|
||||
end
|
||||
|
||||
def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
|
||||
%Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
|
||||
q = from(u in User, where: u.ap_id in ^announces)
|
||||
|
||||
|
@ -870,6 +873,7 @@ def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
|> put_view(AccountView)
|
||||
|> render("accounts.json", %{for: user, users: users, as: :user})
|
||||
else
|
||||
{:visible, false} -> {:error, :not_found}
|
||||
_ -> json(conn, [])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -213,7 +213,11 @@ test "all_by_actor_and_id/2" do
|
|||
|
||||
assert [] == Activity.all_by_actor_and_id(user, [])
|
||||
|
||||
assert [%Activity{id: ^id2}, %Activity{id: ^id1}] =
|
||||
Activity.all_by_actor_and_id(user.ap_id, [id1, id2])
|
||||
activities =
|
||||
user.ap_id
|
||||
|> Activity.all_by_actor_and_id([id1, id2])
|
||||
|> Enum.sort(&(&1.id < &2.id))
|
||||
|
||||
assert [%Activity{id: ^id1}, %Activity{id: ^id2}] = activities
|
||||
end
|
||||
end
|
||||
|
|
|
@ -570,22 +570,6 @@ test "it has required fields" do
|
|||
refute cs.valid?
|
||||
end)
|
||||
end
|
||||
|
||||
test "it restricts some sizes" do
|
||||
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
|
||||
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
|
||||
|
||||
[bio: bio_limit, name: name_limit]
|
||||
|> Enum.each(fn {field, size} ->
|
||||
string = String.pad_leading(".", size)
|
||||
cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
|
||||
assert cs.valid?
|
||||
|
||||
string = String.pad_leading(".", size + 1)
|
||||
cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
|
||||
refute cs.valid?
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "followers and friends" do
|
||||
|
@ -1117,11 +1101,60 @@ 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
|
||||
|
||||
test "insert or update a user from given data" do
|
||||
user = insert(:user, %{nickname: "nick@name.de"})
|
||||
data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
|
||||
describe "insert or update a user from given data" do
|
||||
test "with normal data" do
|
||||
user = insert(:user, %{nickname: "nick@name.de"})
|
||||
data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
|
||||
|
||||
assert {:ok, %User{}} = User.insert_or_update_user(data)
|
||||
assert {:ok, %User{}} = User.insert_or_update_user(data)
|
||||
end
|
||||
|
||||
test "with overly long fields" do
|
||||
current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
|
||||
user = insert(:user, nickname: "nickname@supergood.domain")
|
||||
|
||||
data = %{
|
||||
ap_id: user.ap_id,
|
||||
name: user.name,
|
||||
nickname: user.nickname,
|
||||
info: %{
|
||||
fields: [
|
||||
%{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %User{}} = User.insert_or_update_user(data)
|
||||
end
|
||||
|
||||
test "with an overly long bio" do
|
||||
current_max_length = Pleroma.Config.get([:instance, :user_bio_length], 5000)
|
||||
user = insert(:user, nickname: "nickname@supergood.domain")
|
||||
|
||||
data = %{
|
||||
ap_id: user.ap_id,
|
||||
name: user.name,
|
||||
nickname: user.nickname,
|
||||
bio: String.duplicate("h", current_max_length + 1),
|
||||
info: %{}
|
||||
}
|
||||
|
||||
assert {:ok, %User{}} = User.insert_or_update_user(data)
|
||||
end
|
||||
|
||||
test "with an overly long display name" do
|
||||
current_max_length = Pleroma.Config.get([:instance, :user_name_length], 100)
|
||||
user = insert(:user, nickname: "nickname@supergood.domain")
|
||||
|
||||
data = %{
|
||||
ap_id: user.ap_id,
|
||||
name: String.duplicate("h", current_max_length + 1),
|
||||
nickname: user.nickname,
|
||||
info: %{}
|
||||
}
|
||||
|
||||
assert {:ok, %User{}} = User.insert_or_update_user(data)
|
||||
end
|
||||
end
|
||||
|
||||
describe "per-user rich-text filtering" do
|
||||
|
|
|
@ -3698,7 +3698,7 @@ test "returns 404 when poll is private and not available for user", %{conn: conn
|
|||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|
||||
[conn: conn, activity: activity]
|
||||
[conn: conn, activity: activity, user: user]
|
||||
end
|
||||
|
||||
test "returns users who have favorited the status", %{conn: conn, activity: activity} do
|
||||
|
@ -3758,6 +3758,32 @@ test "does not fail on an unauthenticated request", %{conn: conn, activity: acti
|
|||
[%{"id" => id}] = response
|
||||
assert id == other_user.id
|
||||
end
|
||||
|
||||
test "requires authentification for private posts", %{conn: conn, user: user} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "@#{other_user.nickname} wanna get some #cofe together?",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
conn
|
||||
|> assign(:user, nil)
|
||||
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
|
||||
|> json_response(404)
|
||||
|
||||
response =
|
||||
build_conn()
|
||||
|> assign(:user, other_user)
|
||||
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
|
||||
|> json_response(200)
|
||||
|
||||
[%{"id" => id}] = response
|
||||
assert id == other_user.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/v1/statuses/:id/reblogged_by" do
|
||||
|
@ -3769,7 +3795,7 @@ test "does not fail on an unauthenticated request", %{conn: conn, activity: acti
|
|||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|
||||
[conn: conn, activity: activity]
|
||||
[conn: conn, activity: activity, user: user]
|
||||
end
|
||||
|
||||
test "returns users who have reblogged the status", %{conn: conn, activity: activity} do
|
||||
|
@ -3829,6 +3855,29 @@ test "does not fail on an unauthenticated request", %{conn: conn, activity: acti
|
|||
[%{"id" => id}] = response
|
||||
assert id == other_user.id
|
||||
end
|
||||
|
||||
test "requires authentification for private posts", %{conn: conn, user: user} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "@#{other_user.nickname} wanna get some #cofe together?",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
conn
|
||||
|> assign(:user, nil)
|
||||
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
|
||||
|> json_response(404)
|
||||
|
||||
response =
|
||||
build_conn()
|
||||
|> assign(:user, other_user)
|
||||
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
|
||||
|> json_response(200)
|
||||
|
||||
assert [] == response
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /auth/password, with valid parameters" do
|
||||
|
|
Loading…
Reference in a new issue