Merge branch 'bugfix/jsonb-set-fuckup' into 'release/1.1.1'

Fix a migration wiping user info of users that don't have any mutes

See merge request pleroma/pleroma!1856
This commit is contained in:
rinpatch 2019-10-18 11:49:27 +00:00
commit deee9f3196
8 changed files with 50 additions and 9 deletions

View file

@ -3,6 +3,13 @@ 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/).
## [1.1.1] - 2019-10-18
### Fixed
- One of the migrations between 1.0.0 and 1.1.0 wiping user info of the relay user because of unexpected behavior of postgresql's `jsonb_set`, resulting in inability to post in the default configuration. If you were affected, please run the following query in postgres console, the relay user will be recreated automatically:
```
delete from users where ap_id = 'https://your.instance.hostname/relay';
```
## [1.1.0] - 2019-10-14 ## [1.1.0] - 2019-10-14
**Breaking:** The stable branch has been changed from `master` to `stable`. If you want to keep using 1.0, the `release/1.0` branch will receive security updates for 6 months after 1.1 release. **Breaking:** The stable branch has been changed from `master` to `stable`. If you want to keep using 1.0, the `release/1.0` branch will receive security updates for 6 months after 1.1 release.

View file

@ -54,7 +54,7 @@ def run(["remove_embedded_objects" | args]) do
Logger.info("Removing embedded objects") Logger.info("Removing embedded objects")
Repo.query!( Repo.query!(
"update activities set data = jsonb_set(data, '{object}'::text[], data->'object'->'id') where data->'object'->>'id' is not null;", "update activities set data = safe_jsonb_set(data, '{object}'::text[], data->'object'->'id') where data->'object'->>'id' is not null;",
[], [],
timeout: :infinity timeout: :infinity
) )
@ -152,7 +152,7 @@ def run(["fix_likes_collections"]) do
set: [ set: [
data: data:
fragment( fragment(
"jsonb_set(?, '{likes}', '[]'::jsonb, true)", "safe_jsonb_set(?, '{likes}', '[]'::jsonb, true)",
object.data object.data
) )
] ]

View file

@ -181,7 +181,7 @@ def increase_replies_count(ap_id) do
data: data:
fragment( fragment(
""" """
jsonb_set(?, '{repliesCount}', safe_jsonb_set(?, '{repliesCount}',
(coalesce((?->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true) (coalesce((?->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true)
""", """,
o.data, o.data,
@ -204,7 +204,7 @@ def decrease_replies_count(ap_id) do
data: data:
fragment( fragment(
""" """
jsonb_set(?, '{repliesCount}', safe_jsonb_set(?, '{repliesCount}',
(greatest(0, (?->>'repliesCount')::int - 1))::varchar::jsonb, true) (greatest(0, (?->>'repliesCount')::int - 1))::varchar::jsonb, true)
""", """,
o.data, o.data,

View file

@ -718,7 +718,7 @@ def increase_note_count(%User{} = user) do
set: [ set: [
info: info:
fragment( fragment(
"jsonb_set(?, '{note_count}', ((?->>'note_count')::int + 1)::varchar::jsonb, true)", "safe_jsonb_set(?, '{note_count}', ((?->>'note_count')::int + 1)::varchar::jsonb, true)",
u.info, u.info,
u.info u.info
) )
@ -739,7 +739,7 @@ def decrease_note_count(%User{} = user) do
set: [ set: [
info: info:
fragment( fragment(
"jsonb_set(?, '{note_count}', (greatest(0, (?->>'note_count')::int - 1))::varchar::jsonb, true)", "safe_jsonb_set(?, '{note_count}', (greatest(0, (?->>'note_count')::int - 1))::varchar::jsonb, true)",
u.info, u.info,
u.info u.info
) )
@ -812,7 +812,7 @@ def update_follower_count(%User{} = user) do
set: [ set: [
info: info:
fragment( fragment(
"jsonb_set(?, '{follower_count}', ?::varchar::jsonb, true)", "safe_jsonb_set(?, '{follower_count}', ?::varchar::jsonb, true)",
u.info, u.info,
s.count s.count
) )

View file

@ -349,7 +349,7 @@ def update_follow_state_for_all(
try do try do
Ecto.Adapters.SQL.query!( Ecto.Adapters.SQL.query!(
Repo, Repo,
"UPDATE activities SET data = jsonb_set(data, '{state}', $1) WHERE data->>'type' = 'Follow' AND data->>'actor' = $2 AND data->>'object' = $3 AND data->>'state' = 'pending'", "UPDATE activities SET data = safe_jsonb_set(data, '{state}', $1) WHERE data->>'type' = 'Follow' AND data->>'actor' = $2 AND data->>'object' = $3 AND data->>'state' = 'pending'",
[state, actor, object] [state, actor, object]
) )

View file

@ -0,0 +1,22 @@
defmodule Pleroma.Repo.Migrations.CreateSafeJsonbSet do
use Ecto.Migration
alias Pleroma.User
def change do
execute("""
create or replace function safe_jsonb_set(target jsonb, path text[], new_value jsonb, create_missing boolean default true) returns jsonb as $$
declare
result jsonb;
begin
result := jsonb_set(target, path, coalesce(new_value, 'null'::jsonb), create_missing);
if result is NULL then
raise 'jsonb_set tried to wipe the object, please report this incindent to Pleroma bug tracker. https://git.pleroma.social/pleroma/pleroma/issues/new';
return target;
else
return result;
end if;
end;
$$ language plpgsql;
""")
end
end

View file

@ -3,6 +3,6 @@ defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do
alias Pleroma.User alias Pleroma.User
def change do def change do
execute("update users set info = jsonb_set(info, '{muted_notifications}', info->'mutes', true) where local = true") execute("update users set info = safe_jsonb_set(info, '{muted_notifications}', info->'mutes', true) where local = true")
end end
end end

View file

@ -0,0 +1,12 @@
defmodule Pleroma.SafeJsonbSetTest do
use Pleroma.DataCase
test "it doesn't wipe the object when asked to set the value to NULL" do
assert %{rows: [[%{"key" => "value", "test" => nil}]]} =
Ecto.Adapters.SQL.query!(
Pleroma.Repo,
"select safe_jsonb_set('{\"key\": \"value\"}'::jsonb, '{test}', NULL);",
[]
)
end
end