Merge branch 'develop' into issue/1276

This commit is contained in:
Maksim Pechnikov 2019-10-29 22:23:19 +03:00
commit b27a92e8fa
66 changed files with 1283 additions and 377 deletions

View file

@ -0,0 +1,149 @@
defmodule Pleroma.Repo.Migrations.CreateFollowingRelationships do
use Ecto.Migration
def change do
create_if_not_exists table(:following_relationships) do
add(:follower_id, references(:users, type: :uuid, on_delete: :delete_all), null: false)
add(:following_id, references(:users, type: :uuid, on_delete: :delete_all), null: false)
add(:state, :string, null: false)
timestamps()
end
create_if_not_exists(index(:following_relationships, :follower_id))
create_if_not_exists(unique_index(:following_relationships, [:follower_id, :following_id]))
execute(update_thread_visibility(), restore_thread_visibility())
end
# The only difference between the original version: `actor_user` replaced with `actor_user_following`
def update_thread_visibility do
"""
CREATE OR REPLACE FUNCTION thread_visibility(actor varchar, activity_id varchar) RETURNS boolean AS $$
DECLARE
public varchar := 'https://www.w3.org/ns/activitystreams#Public';
child objects%ROWTYPE;
activity activities%ROWTYPE;
author_fa varchar;
valid_recipients varchar[];
actor_user_following varchar[];
BEGIN
--- Fetch actor following
SELECT array_agg(following.follower_address) INTO actor_user_following FROM following_relationships
JOIN users ON users.id = following_relationships.follower_id
JOIN users AS following ON following.id = following_relationships.following_id
WHERE users.ap_id = actor;
--- Fetch our initial activity.
SELECT * INTO activity FROM activities WHERE activities.data->>'id' = activity_id;
LOOP
--- Ensure that we have an activity before continuing.
--- If we don't, the thread is not satisfiable.
IF activity IS NULL THEN
RETURN false;
END IF;
--- We only care about Create activities.
IF activity.data->>'type' != 'Create' THEN
RETURN true;
END IF;
--- Normalize the child object into child.
SELECT * INTO child FROM objects
INNER JOIN activities ON COALESCE(activities.data->'object'->>'id', activities.data->>'object') = objects.data->>'id'
WHERE COALESCE(activity.data->'object'->>'id', activity.data->>'object') = objects.data->>'id';
--- Fetch the author's AS2 following collection.
SELECT COALESCE(users.follower_address, '') INTO author_fa FROM users WHERE users.ap_id = activity.actor;
--- Prepare valid recipients array.
valid_recipients := ARRAY[actor, public];
IF ARRAY[author_fa] && actor_user_following THEN
valid_recipients := valid_recipients || author_fa;
END IF;
--- Check visibility.
IF NOT valid_recipients && activity.recipients THEN
--- activity not visible, break out of the loop
RETURN false;
END IF;
--- If there's a parent, load it and do this all over again.
IF (child.data->'inReplyTo' IS NOT NULL) AND (child.data->'inReplyTo' != 'null'::jsonb) THEN
SELECT * INTO activity FROM activities
INNER JOIN objects ON COALESCE(activities.data->'object'->>'id', activities.data->>'object') = objects.data->>'id'
WHERE child.data->>'inReplyTo' = objects.data->>'id';
ELSE
RETURN true;
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
"""
end
# priv/repo/migrations/20190515222404_add_thread_visibility_function.exs
def restore_thread_visibility do
"""
CREATE OR REPLACE FUNCTION thread_visibility(actor varchar, activity_id varchar) RETURNS boolean AS $$
DECLARE
public varchar := 'https://www.w3.org/ns/activitystreams#Public';
child objects%ROWTYPE;
activity activities%ROWTYPE;
actor_user users%ROWTYPE;
author_fa varchar;
valid_recipients varchar[];
BEGIN
--- Fetch our actor.
SELECT * INTO actor_user FROM users WHERE users.ap_id = actor;
--- Fetch our initial activity.
SELECT * INTO activity FROM activities WHERE activities.data->>'id' = activity_id;
LOOP
--- Ensure that we have an activity before continuing.
--- If we don't, the thread is not satisfiable.
IF activity IS NULL THEN
RETURN false;
END IF;
--- We only care about Create activities.
IF activity.data->>'type' != 'Create' THEN
RETURN true;
END IF;
--- Normalize the child object into child.
SELECT * INTO child FROM objects
INNER JOIN activities ON COALESCE(activities.data->'object'->>'id', activities.data->>'object') = objects.data->>'id'
WHERE COALESCE(activity.data->'object'->>'id', activity.data->>'object') = objects.data->>'id';
--- Fetch the author's AS2 following collection.
SELECT COALESCE(users.follower_address, '') INTO author_fa FROM users WHERE users.ap_id = activity.actor;
--- Prepare valid recipients array.
valid_recipients := ARRAY[actor, public];
IF ARRAY[author_fa] && actor_user.following THEN
valid_recipients := valid_recipients || author_fa;
END IF;
--- Check visibility.
IF NOT valid_recipients && activity.recipients THEN
--- activity not visible, break out of the loop
RETURN false;
END IF;
--- If there's a parent, load it and do this all over again.
IF (child.data->'inReplyTo' IS NOT NULL) AND (child.data->'inReplyTo' != 'null'::jsonb) THEN
SELECT * INTO activity FROM activities
INNER JOIN objects ON COALESCE(activities.data->'object'->>'id', activities.data->>'object') = objects.data->>'id'
WHERE child.data->>'inReplyTo' = objects.data->>'id';
ELSE
RETURN true;
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
"""
end
end

View file

@ -0,0 +1,89 @@
defmodule Pleroma.Repo.Migrations.MigrateFollowingRelationships do
use Ecto.Migration
def change do
execute(import_following_from_users(), "")
execute(import_following_from_activities(), restore_following_column())
end
defp import_following_from_users do
"""
INSERT INTO following_relationships (follower_id, following_id, state, inserted_at, updated_at)
SELECT
relations.follower_id,
following.id,
'accept',
now(),
now()
FROM (
SELECT
users.id AS follower_id,
unnest(users.following) AS following_ap_id
FROM
users
WHERE
users.following != '{}'
AND users.local = false OR users.local = true AND users.email IS NOT NULL -- Exclude `internal/fetch` and `relay`
) AS relations
JOIN users AS "following" ON "following".follower_address = relations.following_ap_id
WHERE relations.follower_id != following.id
ON CONFLICT DO NOTHING
"""
end
defp import_following_from_activities do
"""
INSERT INTO
following_relationships (
follower_id,
following_id,
state,
inserted_at,
updated_at
)
SELECT
followers.id,
following.id,
activities.data ->> 'state',
(activities.data ->> 'published') :: timestamp,
now()
FROM
activities
JOIN users AS followers ON (activities.actor = followers.ap_id)
JOIN users AS following ON (activities.data ->> 'object' = following.ap_id)
WHERE
activities.data ->> 'type' = 'Follow'
AND activities.data ->> 'state' IN ('accept', 'pending', 'reject')
ORDER BY activities.updated_at DESC
ON CONFLICT DO NOTHING
"""
end
defp restore_following_column do
"""
UPDATE
users
SET
following = following_query.following_array,
updated_at = now()
FROM (
SELECT
follower.id AS follower_id,
CASE follower.local
WHEN TRUE THEN
array_prepend(follower.follower_address, array_agg(following.follower_address))
ELSE
array_agg(following.follower_address)
END AS following_array
FROM
following_relationships
JOIN users AS follower ON follower.id = following_relationships.follower_id
JOIN users AS following ON following.id = following_relationships.following_id
GROUP BY
follower.id) AS following_query
WHERE
following_query.follower_id = users.id
"""
end
end

View file

@ -0,0 +1,16 @@
defmodule Pleroma.Repo.Migrations.DropUsersFollowing do
use Ecto.Migration
# had to disable these to be able to restore `following` index concurrently
# https://hexdocs.pm/ecto_sql/Ecto.Migration.html#index/3-adding-dropping-indexes-concurrently
@disable_ddl_transaction true
@disable_migration_lock true
def change do
drop(index(:users, [:following], concurrently: true, using: :gin))
alter table(:users) do
remove(:following, {:array, :string}, default: [])
end
end
end

View file

@ -0,0 +1,53 @@
defmodule Pleroma.Repo.Migrations.AddUsersInfoColumns do
use Ecto.Migration
@jsonb_array_default "'[]'::jsonb"
def change do
alter table(:users) do
add_if_not_exists(:banner, :map, default: %{})
add_if_not_exists(:background, :map, default: %{})
add_if_not_exists(:source_data, :map, default: %{})
add_if_not_exists(:note_count, :integer, default: 0)
add_if_not_exists(:follower_count, :integer, default: 0)
add_if_not_exists(:following_count, :integer, default: nil)
add_if_not_exists(:locked, :boolean, default: false, null: false)
add_if_not_exists(:confirmation_pending, :boolean, default: false, null: false)
add_if_not_exists(:password_reset_pending, :boolean, default: false, null: false)
add_if_not_exists(:confirmation_token, :text, default: nil)
add_if_not_exists(:default_scope, :string, default: "public")
add_if_not_exists(:blocks, {:array, :text}, default: [])
add_if_not_exists(:domain_blocks, {:array, :text}, default: [])
add_if_not_exists(:mutes, {:array, :text}, default: [])
add_if_not_exists(:muted_reblogs, {:array, :text}, default: [])
add_if_not_exists(:muted_notifications, {:array, :text}, default: [])
add_if_not_exists(:subscribers, {:array, :text}, default: [])
add_if_not_exists(:deactivated, :boolean, default: false, null: false)
add_if_not_exists(:no_rich_text, :boolean, default: false, null: false)
add_if_not_exists(:ap_enabled, :boolean, default: false, null: false)
add_if_not_exists(:is_moderator, :boolean, default: false, null: false)
add_if_not_exists(:is_admin, :boolean, default: false, null: false)
add_if_not_exists(:show_role, :boolean, default: true, null: false)
add_if_not_exists(:settings, :map, default: nil)
add_if_not_exists(:magic_key, :text, default: nil)
add_if_not_exists(:uri, :text, default: nil)
add_if_not_exists(:hide_followers_count, :boolean, default: false, null: false)
add_if_not_exists(:hide_follows_count, :boolean, default: false, null: false)
add_if_not_exists(:hide_followers, :boolean, default: false, null: false)
add_if_not_exists(:hide_follows, :boolean, default: false, null: false)
add_if_not_exists(:hide_favorites, :boolean, default: true, null: false)
add_if_not_exists(:unread_conversation_count, :integer, default: 0)
add_if_not_exists(:pinned_activities, {:array, :text}, default: [])
add_if_not_exists(:email_notifications, :map, default: %{"digest" => false})
add_if_not_exists(:mascot, :map, default: nil)
add_if_not_exists(:emoji, :map, default: fragment(@jsonb_array_default))
add_if_not_exists(:pleroma_settings_store, :map, default: %{})
add_if_not_exists(:fields, :map, default: fragment(@jsonb_array_default))
add_if_not_exists(:raw_fields, :map, default: fragment(@jsonb_array_default))
add_if_not_exists(:discoverable, :boolean, default: false, null: false)
add_if_not_exists(:invisible, :boolean, default: false, null: false)
add_if_not_exists(:notification_settings, :map, default: %{})
add_if_not_exists(:skip_thread_containment, :boolean, default: false, null: false)
end
end
end

View file

@ -95,79 +95,37 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do
]
def change do
alter table(:users) do
add(:banner, :map, default: %{})
add(:background, :map, default: %{})
add(:source_data, :map, default: %{})
add(:note_count, :integer, default: 0)
add(:follower_count, :integer, default: 0)
add(:following_count, :integer, default: nil)
add(:locked, :boolean, default: false, null: false)
add(:confirmation_pending, :boolean, default: false, null: false)
add(:password_reset_pending, :boolean, default: false, null: false)
add(:confirmation_token, :text, default: nil)
add(:default_scope, :string, default: "public")
add(:blocks, {:array, :text}, default: [])
add(:domain_blocks, {:array, :text}, default: [])
add(:mutes, {:array, :text}, default: [])
add(:muted_reblogs, {:array, :text}, default: [])
add(:muted_notifications, {:array, :text}, default: [])
add(:subscribers, {:array, :text}, default: [])
add(:deactivated, :boolean, default: false, null: false)
add(:no_rich_text, :boolean, default: false, null: false)
add(:ap_enabled, :boolean, default: false, null: false)
add(:is_moderator, :boolean, default: false, null: false)
add(:is_admin, :boolean, default: false, null: false)
add(:show_role, :boolean, default: true, null: false)
add(:settings, :map, default: nil)
add(:magic_key, :text, default: nil)
add(:uri, :text, default: nil)
add(:hide_followers_count, :boolean, default: false, null: false)
add(:hide_follows_count, :boolean, default: false, null: false)
add(:hide_followers, :boolean, default: false, null: false)
add(:hide_follows, :boolean, default: false, null: false)
add(:hide_favorites, :boolean, default: true, null: false)
add(:unread_conversation_count, :integer, default: 0)
add(:pinned_activities, {:array, :text}, default: [])
add(:email_notifications, :map, default: %{"digest" => false})
add(:mascot, :map, default: nil)
add(:emoji, :map, default: fragment(@jsonb_array_default))
add(:pleroma_settings_store, :map, default: %{})
add(:fields, :map, default: fragment(@jsonb_array_default))
add(:raw_fields, :map, default: fragment(@jsonb_array_default))
add(:discoverable, :boolean, default: false, null: false)
add(:invisible, :boolean, default: false, null: false)
add(:notification_settings, :map, default: %{})
add(:skip_thread_containment, :boolean, default: false, null: false)
end
if direction() == :up do
for f <- @info_fields do
set_field = "update users set #{f} ="
sets =
for f <- @info_fields do
set_field = "#{f} ="
# Coercion of null::jsonb to NULL
jsonb = "case when info->>'#{f}' IS NULL then null else info->'#{f}' end"
# Coercion of null::jsonb to NULL
jsonb = "case when info->>'#{f}' IS NULL then null else info->'#{f}' end"
cond do
f in @jsonb_fields ->
execute("#{set_field} #{jsonb}")
cond do
f in @jsonb_fields ->
"#{set_field} #{jsonb}"
f in @array_jsonb_fields ->
execute("#{set_field} coalesce(#{jsonb}, #{@jsonb_array_default})")
f in @array_jsonb_fields ->
"#{set_field} coalesce(#{jsonb}, #{@jsonb_array_default})"
f in @int_fields ->
execute("#{set_field} (info->>'#{f}')::int")
f in @int_fields ->
"#{set_field} (info->>'#{f}')::int"
f in @boolean_fields ->
execute("#{set_field} coalesce((info->>'#{f}')::boolean, false)")
f in @boolean_fields ->
"#{set_field} coalesce((info->>'#{f}')::boolean, false)"
f in @array_text_fields ->
execute("#{set_field} ARRAY(SELECT jsonb_array_elements_text(#{jsonb}))")
f in @array_text_fields ->
"#{set_field} ARRAY(SELECT jsonb_array_elements_text(#{jsonb}))"
true ->
execute("#{set_field} info->>'#{f}'")
true ->
"#{set_field} info->>'#{f}'"
end
end
end
|> Enum.join(", ")
execute("update users set " <> sets)
for index_name <- [
:users_deactivated_index,

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForActivities do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE activities
ALTER COLUMN data SET NOT NULL,
ALTER COLUMN local SET NOT NULL")
end
def down do
execute("ALTER TABLE activities
ALTER COLUMN data DROP NOT NULL,
ALTER COLUMN local DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForActivityExpirations do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE activity_expirations
ALTER COLUMN activity_id SET NOT NULL")
end
def down do
execute("ALTER TABLE activity_expirations
ALTER COLUMN activity_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForApps do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE apps
ALTER COLUMN client_name SET NOT NULL,
ALTER COLUMN redirect_uris SET NOT NULL")
end
def down do
execute("ALTER TABLE apps
ALTER COLUMN client_name DROP NOT NULL,
ALTER COLUMN redirect_uris DROP NOT NULL")
end
end

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForBookmarks do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE bookmarks
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN activity_id SET NOT NULL")
end
def down do
execute("ALTER TABLE bookmarks
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN activity_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForConfig do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE config
ALTER COLUMN key SET NOT NULL,
ALTER COLUMN value SET NOT NULL")
end
def down do
execute("ALTER TABLE config
ALTER COLUMN key DROP NOT NULL,
ALTER COLUMN value DROP NOT NULL")
end
end

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForConversationParticipationRecipientShips do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE conversation_participation_recipient_ships
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN participation_id SET NOT NULL")
end
def down do
execute("ALTER TABLE conversation_participation_recipient_ships
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN participation_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,19 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForConversationParticipations do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE conversation_participations
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN conversation_id SET NOT NULL,
ALTER COLUMN read SET NOT NULL")
end
def down do
execute("ALTER TABLE conversation_participations
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN conversation_id DROP NOT NULL,
ALTER COLUMN read DROP NOT NULL")
end
end

View file

@ -0,0 +1,19 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForFilters do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE filters
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN filter_id SET NOT NULL,
ALTER COLUMN whole_word SET NOT NULL")
end
def down do
execute("ALTER TABLE filters
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN filter_id DROP NOT NULL,
ALTER COLUMN whole_word DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForInstances do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE instances
ALTER COLUMN host SET NOT NULL")
end
def down do
execute("ALTER TABLE instances
ALTER COLUMN host DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForLists do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE lists
ALTER COLUMN user_id SET NOT NULL")
end
def down do
execute("ALTER TABLE lists
ALTER COLUMN user_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForMarkers do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE markers
ALTER COLUMN user_id SET NOT NULL")
end
def down do
execute("ALTER TABLE markers
ALTER COLUMN user_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForModerationLog do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE moderation_log
ALTER COLUMN data SET NOT NULL")
end
def down do
execute("ALTER TABLE moderation_log
ALTER COLUMN data DROP NOT NULL")
end
end

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForNotifications do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE notifications
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN seen SET NOT NULL")
end
def down do
execute("ALTER TABLE notifications
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN seen DROP NOT NULL")
end
end

View file

@ -0,0 +1,19 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForOauthAuthorizations do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE oauth_authorizations
ALTER COLUMN app_id SET NOT NULL,
ALTER COLUMN token SET NOT NULL,
ALTER COLUMN used SET NOT NULL")
end
def down do
execute("ALTER TABLE oauth_authorizations
ALTER COLUMN app_id DROP NOT NULL,
ALTER COLUMN token DROP NOT NULL,
ALTER COLUMN used DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForOauthTokens do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE oauth_tokens
ALTER COLUMN app_id SET NOT NULL")
end
def down do
execute("ALTER TABLE oauth_tokens
ALTER COLUMN app_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForObjects do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE objects
ALTER COLUMN data SET NOT NULL")
end
def down do
execute("ALTER TABLE objects
ALTER COLUMN data DROP NOT NULL")
end
end

View file

@ -0,0 +1,19 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForPasswordResetTokens do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE password_reset_tokens
ALTER COLUMN token SET NOT NULL,
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN used SET NOT NULL")
end
def down do
execute("ALTER TABLE password_reset_tokens
ALTER COLUMN token DROP NOT NULL,
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN used DROP NOT NULL")
end
end

View file

@ -0,0 +1,25 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForPushSubscriptions do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE push_subscriptions
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN token_id SET NOT NULL,
ALTER COLUMN endpoint SET NOT NULL,
ALTER COLUMN key_p256dh SET NOT NULL,
ALTER COLUMN key_auth SET NOT NULL,
ALTER COLUMN data SET NOT NULL")
end
def down do
execute("ALTER TABLE push_subscriptions
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN token_id DROP NOT NULL,
ALTER COLUMN endpoint DROP NOT NULL,
ALTER COLUMN key_p256dh DROP NOT NULL,
ALTER COLUMN key_auth DROP NOT NULL,
ALTER COLUMN data DROP NOT NULL")
end
end

View file

@ -0,0 +1,19 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForRegistrations do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE registrations
ALTER COLUMN provider SET NOT NULL,
ALTER COLUMN uid SET NOT NULL,
ALTER COLUMN info SET NOT NULL")
end
def down do
execute("ALTER TABLE registrations
ALTER COLUMN provider DROP NOT NULL,
ALTER COLUMN uid DROP NOT NULL,
ALTER COLUMN info DROP NOT NULL")
end
end

View file

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForScheduledActivities do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE scheduled_activities
ALTER COLUMN user_id SET NOT NULL")
end
def down do
execute("ALTER TABLE scheduled_activities
ALTER COLUMN user_id DROP NOT NULL")
end
end

View file

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForThreadMutes do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE thread_mutes
ALTER COLUMN user_id SET NOT NULL,
ALTER COLUMN context SET NOT NULL")
end
def down do
execute("ALTER TABLE thread_mutes
ALTER COLUMN user_id DROP NOT NULL,
ALTER COLUMN context DROP NOT NULL")
end
end

View file

@ -0,0 +1,19 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForUserInviteTokens do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
execute("ALTER TABLE user_invite_tokens
ALTER COLUMN used SET NOT NULL,
ALTER COLUMN uses SET NOT NULL,
ALTER COLUMN invite_type SET NOT NULL")
end
def down do
execute("ALTER TABLE user_invite_tokens
ALTER COLUMN used DROP NOT NULL,
ALTER COLUMN uses DROP NOT NULL,
ALTER COLUMN invite_type DROP NOT NULL")
end
end

View file

@ -0,0 +1,44 @@
defmodule Pleroma.Repo.Migrations.SetNotNullForUsers do
use Ecto.Migration
# modify/3 function will require index recreation, so using execute/1 instead
def up do
# irreversible
execute("UPDATE users SET follower_count = 0 WHERE follower_count IS NULL")
execute("ALTER TABLE users
ALTER COLUMN local SET NOT NULL,
ALTER COLUMN source_data SET NOT NULL,
ALTER COLUMN note_count SET NOT NULL,
ALTER COLUMN follower_count SET NOT NULL,
ALTER COLUMN blocks SET NOT NULL,
ALTER COLUMN domain_blocks SET NOT NULL,
ALTER COLUMN mutes SET NOT NULL,
ALTER COLUMN muted_reblogs SET NOT NULL,
ALTER COLUMN muted_notifications SET NOT NULL,
ALTER COLUMN subscribers SET NOT NULL,
ALTER COLUMN pinned_activities SET NOT NULL,
ALTER COLUMN emoji SET NOT NULL,
ALTER COLUMN fields SET NOT NULL,
ALTER COLUMN raw_fields SET NOT NULL")
end
def down do
execute("ALTER TABLE users
ALTER COLUMN local DROP NOT NULL,
ALTER COLUMN source_data DROP NOT NULL,
ALTER COLUMN note_count DROP NOT NULL,
ALTER COLUMN follower_count DROP NOT NULL,
ALTER COLUMN blocks DROP NOT NULL,
ALTER COLUMN domain_blocks DROP NOT NULL,
ALTER COLUMN mutes DROP NOT NULL,
ALTER COLUMN muted_reblogs DROP NOT NULL,
ALTER COLUMN muted_notifications DROP NOT NULL,
ALTER COLUMN subscribers DROP NOT NULL,
ALTER COLUMN pinned_activities DROP NOT NULL,
ALTER COLUMN emoji DROP NOT NULL,
ALTER COLUMN fields DROP NOT NULL,
ALTER COLUMN raw_fields DROP NOT NULL")
end
end

View file

@ -0,0 +1,35 @@
defmodule Pleroma.Repo.Migrations.MigrateMissingFollowingRelationships do
use Ecto.Migration
def change do
execute(import_pending_follows_from_activities(), "")
end
defp import_pending_follows_from_activities do
"""
INSERT INTO
following_relationships (
follower_id,
following_id,
state,
inserted_at,
updated_at
)
SELECT
followers.id,
following.id,
activities.data ->> 'state',
(activities.data ->> 'published') :: timestamp,
now()
FROM
activities
JOIN users AS followers ON (activities.actor = followers.ap_id)
JOIN users AS following ON (activities.data ->> 'object' = following.ap_id)
WHERE
activities.data ->> 'type' = 'Follow'
AND activities.data ->> 'state' = 'pending'
ORDER BY activities.updated_at DESC
ON CONFLICT DO NOTHING
"""
end
end