diff options
Diffstat (limited to 'priv/repo')
63 files changed, 1689 insertions, 12 deletions
| diff --git a/priv/repo/migrations/20190408123347_create_conversations.exs b/priv/repo/migrations/20190408123347_create_conversations.exs index d75459e82..3eaa6136c 100644 --- a/priv/repo/migrations/20190408123347_create_conversations.exs +++ b/priv/repo/migrations/20190408123347_create_conversations.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Repo.Migrations.CreateConversations do diff --git a/priv/repo/migrations/20190414125034_migrate_old_bookmarks.exs b/priv/repo/migrations/20190414125034_migrate_old_bookmarks.exs index f3928a149..b6f0ac66b 100644 --- a/priv/repo/migrations/20190414125034_migrate_old_bookmarks.exs +++ b/priv/repo/migrations/20190414125034_migrate_old_bookmarks.exs @@ -3,21 +3,24 @@ defmodule Pleroma.Repo.Migrations.MigrateOldBookmarks do    import Ecto.Query    alias Pleroma.Activity    alias Pleroma.Bookmark -  alias Pleroma.User    alias Pleroma.Repo    def up do      query = -      from(u in User, +      from(u in "users",          where: u.local == true, -        where: fragment("array_length(bookmarks, 1)") > 0, -        select: %{id: u.id, bookmarks: fragment("bookmarks")} +        where: fragment("array_length(?, 1)", u.bookmarks) > 0, +        select: %{id: u.id, bookmarks: u.bookmarks}        )      Repo.stream(query)      |> Enum.each(fn %{id: user_id, bookmarks: bookmarks} ->        Enum.each(bookmarks, fn ap_id -> -        activity = Activity.get_create_by_object_ap_id(ap_id) +        activity = +          ap_id +          |> Activity.create_by_object_ap_id() +          |> Repo.one() +          unless is_nil(activity), do: {:ok, _} = Bookmark.create(user_id, activity.id)        end)      end) diff --git a/priv/repo/migrations/20190506054542_add_multi_factor_authentication_settings_to_user.exs b/priv/repo/migrations/20190506054542_add_multi_factor_authentication_settings_to_user.exs new file mode 100644 index 000000000..8b653c61f --- /dev/null +++ b/priv/repo/migrations/20190506054542_add_multi_factor_authentication_settings_to_user.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.AddMultiFactorAuthenticationSettingsToUser do +  use Ecto.Migration + +  def change do +    alter table(:users) do +      add(:multi_factor_authentication_settings, :map, default: %{}) +    end +  end +end diff --git a/priv/repo/migrations/20190508193213_create_mfa_tokens.exs b/priv/repo/migrations/20190508193213_create_mfa_tokens.exs new file mode 100644 index 000000000..da9f8fabe --- /dev/null +++ b/priv/repo/migrations/20190508193213_create_mfa_tokens.exs @@ -0,0 +1,16 @@ +defmodule Pleroma.Repo.Migrations.CreateMfaTokens do +  use Ecto.Migration + +  def change do +    create table(:mfa_tokens) do +      add(:user_id, references(:users, type: :uuid, on_delete: :delete_all)) +      add(:authorization_id, references(:oauth_authorizations, on_delete: :delete_all)) +      add(:token, :string) +      add(:valid_until, :naive_datetime_usec) + +      timestamps() +    end + +    create(unique_index(:mfa_tokens, :token)) +  end +end diff --git a/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs b/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs index 779aa382e..44f9891b1 100644 --- a/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs +++ b/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs @@ -1,11 +1,16 @@  defmodule Pleroma.Repo.Migrations.AddFollowingAddressFromSourceData do -  use Ecto.Migration -  import Ecto.Query    alias Pleroma.User +  import Ecto.Query +  require Logger +  use Ecto.Migration    def change do      query = -      User.external_users_query() +      User.Query.build(%{ +        external: true, +        legacy_active: true, +        order_by: :id +      })        |> select([u], struct(u, [:id, :ap_id, :info]))      Pleroma.Repo.stream(query) @@ -15,6 +20,9 @@ defmodule Pleroma.Repo.Migrations.AddFollowingAddressFromSourceData do            :following_address          ])          |> Pleroma.Repo.update() + +      user -> +        Logger.warn("User #{user.id} / #{user.nickname} does not seem to have source_data")      end)    end  end diff --git a/priv/repo/migrations/20190711042021_create_safe_jsonb_set.exs b/priv/repo/migrations/20190711042021_create_safe_jsonb_set.exs index 2f336a5e8..43d616705 100644 --- a/priv/repo/migrations/20190711042021_create_safe_jsonb_set.exs +++ b/priv/repo/migrations/20190711042021_create_safe_jsonb_set.exs @@ -1,6 +1,5 @@  defmodule Pleroma.Repo.Migrations.CreateSafeJsonbSet do    use Ecto.Migration -  alias Pleroma.User    def change do      execute(""" diff --git a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs index a5eec848b..bbd502044 100644 --- a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs +++ b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs @@ -1,8 +1,9 @@  defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do    use Ecto.Migration -  alias Pleroma.User    def change do +    execute("update users set info = '{}' where info is null") +      execute(        "update users set info = safe_jsonb_set(info, '{muted_notifications}', info->'mutes', true) where local = true"      ) diff --git a/priv/repo/migrations/20191007073319_create_following_relationships.exs b/priv/repo/migrations/20191007073319_create_following_relationships.exs new file mode 100644 index 000000000..d49e24ee4 --- /dev/null +++ b/priv/repo/migrations/20191007073319_create_following_relationships.exs @@ -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 diff --git a/priv/repo/migrations/20191008132217_migrate_following_relationships.exs b/priv/repo/migrations/20191008132217_migrate_following_relationships.exs new file mode 100644 index 000000000..9d5c2648f --- /dev/null +++ b/priv/repo/migrations/20191008132217_migrate_following_relationships.exs @@ -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 diff --git a/priv/repo/migrations/20191008132427_drop_users_following.exs b/priv/repo/migrations/20191008132427_drop_users_following.exs new file mode 100644 index 000000000..21c0af9f4 --- /dev/null +++ b/priv/repo/migrations/20191008132427_drop_users_following.exs @@ -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 diff --git a/priv/repo/migrations/20191009154606_add_user_info_columns.exs b/priv/repo/migrations/20191009154606_add_user_info_columns.exs new file mode 100644 index 000000000..22a5a377f --- /dev/null +++ b/priv/repo/migrations/20191009154606_add_user_info_columns.exs @@ -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 diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs new file mode 100644 index 000000000..cc5ae6920 --- /dev/null +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -0,0 +1,145 @@ +defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do +  use Ecto.Migration + +  @jsonb_array_default "'[]'::jsonb" + +  @info_fields [ +    :banner, +    :background, +    :source_data, +    :note_count, +    :follower_count, +    :following_count, +    :locked, +    :confirmation_pending, +    :password_reset_pending, +    :confirmation_token, +    :default_scope, +    :blocks, +    :domain_blocks, +    :mutes, +    :muted_reblogs, +    :muted_notifications, +    :subscribers, +    :deactivated, +    :no_rich_text, +    :ap_enabled, +    :is_moderator, +    :is_admin, +    :show_role, +    :settings, +    :magic_key, +    :uri, +    :hide_followers_count, +    :hide_follows_count, +    :hide_followers, +    :hide_follows, +    :hide_favorites, +    :unread_conversation_count, +    :pinned_activities, +    :email_notifications, +    :mascot, +    :emoji, +    :pleroma_settings_store, +    :fields, +    :raw_fields, +    :discoverable, +    :invisible, +    :skip_thread_containment, +    :notification_settings +  ] + +  @jsonb_fields [ +    :banner, +    :background, +    :source_data, +    :settings, +    :email_notifications, +    :mascot, +    :pleroma_settings_store, +    :notification_settings +  ] + +  @array_jsonb_fields [:emoji, :fields, :raw_fields] + +  @int_fields [:note_count, :follower_count, :following_count, :unread_conversation_count] + +  @boolean_fields [ +    :locked, +    :confirmation_pending, +    :password_reset_pending, +    :deactivated, +    :no_rich_text, +    :ap_enabled, +    :is_moderator, +    :is_admin, +    :show_role, +    :hide_followers_count, +    :hide_follows_count, +    :hide_followers, +    :hide_follows, +    :hide_favorites, +    :discoverable, +    :invisible, +    :skip_thread_containment +  ] + +  @array_text_fields [ +    :blocks, +    :domain_blocks, +    :mutes, +    :muted_reblogs, +    :muted_notifications, +    :subscribers, +    :pinned_activities +  ] + +  def change do +    if direction() == :up do +      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" + +          cond do +            f in @jsonb_fields -> +              "#{set_field} #{jsonb}" + +            f in @array_jsonb_fields -> +              "#{set_field} coalesce(#{jsonb}, #{@jsonb_array_default})" + +            f in @int_fields -> +              "#{set_field} (info->>'#{f}')::int" + +            f in @boolean_fields -> +              "#{set_field} coalesce((info->>'#{f}')::boolean, false)" + +            f in @array_text_fields -> +              "#{set_field} ARRAY(SELECT jsonb_array_elements_text(#{jsonb}))" + +            true -> +              "#{set_field} info->>'#{f}'" +          end +        end +        |> Enum.join(", ") + +      execute("update users set " <> sets) + +      for index_name <- [ +            :users_deactivated_index, +            :users_is_moderator_index, +            :users_is_admin_index, +            :users_subscribers_index +          ] do +        drop_if_exists(index(:users, [], name: index_name)) +      end +    end + +    create_if_not_exists(index(:users, [:deactivated])) +    create_if_not_exists(index(:users, [:is_moderator])) +    create_if_not_exists(index(:users, [:is_admin])) +    create_if_not_exists(index(:users, [:subscribers])) +  end +end diff --git a/priv/repo/migrations/20191017225002_drop_websub_tables.exs b/priv/repo/migrations/20191017225002_drop_websub_tables.exs index 9e483b2a1..4cf67a59c 100644 --- a/priv/repo/migrations/20191017225002_drop_websub_tables.exs +++ b/priv/repo/migrations/20191017225002_drop_websub_tables.exs @@ -1,8 +1,10 @@  defmodule Pleroma.Repo.Migrations.DropWebsubTables do    use Ecto.Migration -  def change do +  def up do      drop_if_exists(table(:websub_client_subscriptions))      drop_if_exists(table(:websub_server_subscriptions))    end + +  def down, do: :noop  end diff --git a/priv/repo/migrations/20191025081729_add_move_support_to_users.exs b/priv/repo/migrations/20191025081729_add_move_support_to_users.exs new file mode 100644 index 000000000..580b9eb0f --- /dev/null +++ b/priv/repo/migrations/20191025081729_add_move_support_to_users.exs @@ -0,0 +1,10 @@ +defmodule Pleroma.Repo.Migrations.AddMoveSupportToUsers do +  use Ecto.Migration + +  def change do +    alter table(:users) do +      add(:also_known_as, {:array, :string}, default: [], null: false) +      add(:allow_following_move, :boolean, default: true, null: false) +    end +  end +end diff --git a/priv/repo/migrations/20191025143434_add_defaults_to_tables.exs b/priv/repo/migrations/20191025143434_add_defaults_to_tables.exs new file mode 100644 index 000000000..a5bc82335 --- /dev/null +++ b/priv/repo/migrations/20191025143434_add_defaults_to_tables.exs @@ -0,0 +1,68 @@ +defmodule Pleroma.Repo.Migrations.AddDefaultsToTables do +  use Ecto.Migration + +  def up do +    execute("ALTER TABLE activities +    ALTER COLUMN recipients SET DEFAULT ARRAY[]::character varying[]") + +    execute("ALTER TABLE filters +    ALTER COLUMN whole_word SET DEFAULT true") + +    execute("ALTER TABLE push_subscriptions +    ALTER COLUMN data SET DEFAULT '{}'::jsonb") + +    execute(~s(ALTER TABLE users +    ALTER COLUMN tags SET DEFAULT ARRAY[]::character varying[], +    ALTER COLUMN notification_settings SET DEFAULT +      '{"followers": true, "follows": true, "non_follows": true, "non_followers": true}'::jsonb)) + +    # irreversible updates + +    execute( +      "UPDATE activities SET recipients = ARRAY[]::character varying[] WHERE recipients IS NULL" +    ) + +    execute("UPDATE filters SET whole_word = true WHERE whole_word IS NULL") + +    execute("UPDATE push_subscriptions SET data = '{}'::jsonb WHERE data IS NULL") + +    execute("UPDATE users SET source_data = '{}'::jsonb where source_data IS NULL") +    execute("UPDATE users SET note_count = 0 where note_count IS NULL") +    execute("UPDATE users SET background = '{}'::jsonb where background IS NULL") +    execute("UPDATE users SET follower_count = 0 where follower_count IS NULL") + +    execute( +      "UPDATE users SET unread_conversation_count = 0 where unread_conversation_count IS NULL" +    ) + +    execute( +      ~s(UPDATE users SET email_notifications = '{"digest": false}'::jsonb where email_notifications IS NULL) +    ) + +    execute("UPDATE users SET default_scope = 'public' where default_scope IS NULL") + +    execute( +      "UPDATE users SET pleroma_settings_store = '{}'::jsonb where pleroma_settings_store IS NULL" +    ) + +    execute("UPDATE users SET tags = ARRAY[]::character varying[] WHERE tags IS NULL") +    execute(~s(UPDATE users SET notification_settings = +      '{"followers": true, "follows": true, "non_follows": true, "non_followers": true}'::jsonb +      WHERE notification_settings = '{}'::jsonb)) +  end + +  def down do +    execute("ALTER TABLE activities +    ALTER COLUMN recipients DROP DEFAULT") + +    execute("ALTER TABLE filters +    ALTER COLUMN whole_word DROP DEFAULT") + +    execute("ALTER TABLE push_subscriptions +    ALTER COLUMN data DROP DEFAULT") + +    execute("ALTER TABLE users +    ALTER COLUMN tags DROP DEFAULT, +    ALTER COLUMN notification_settings SET DEFAULT '{}'::jsonb") +  end +end diff --git a/priv/repo/migrations/20191026190317_set_not_null_for_activities.exs b/priv/repo/migrations/20191026190317_set_not_null_for_activities.exs new file mode 100644 index 000000000..9b66f3cff --- /dev/null +++ b/priv/repo/migrations/20191026190317_set_not_null_for_activities.exs @@ -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 diff --git a/priv/repo/migrations/20191026190415_set_not_null_for_activity_expirations.exs b/priv/repo/migrations/20191026190415_set_not_null_for_activity_expirations.exs new file mode 100644 index 000000000..e41c69e4c --- /dev/null +++ b/priv/repo/migrations/20191026190415_set_not_null_for_activity_expirations.exs @@ -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 diff --git a/priv/repo/migrations/20191026190500_set_not_null_for_apps.exs b/priv/repo/migrations/20191026190500_set_not_null_for_apps.exs new file mode 100644 index 000000000..a6a44ddfe --- /dev/null +++ b/priv/repo/migrations/20191026190500_set_not_null_for_apps.exs @@ -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 diff --git a/priv/repo/migrations/20191026190533_set_not_null_for_bookmarks.exs b/priv/repo/migrations/20191026190533_set_not_null_for_bookmarks.exs new file mode 100644 index 000000000..5f3224003 --- /dev/null +++ b/priv/repo/migrations/20191026190533_set_not_null_for_bookmarks.exs @@ -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 diff --git a/priv/repo/migrations/20191026190622_set_not_null_for_config.exs b/priv/repo/migrations/20191026190622_set_not_null_for_config.exs new file mode 100644 index 000000000..204272442 --- /dev/null +++ b/priv/repo/migrations/20191026190622_set_not_null_for_config.exs @@ -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 diff --git a/priv/repo/migrations/20191026190712_set_not_null_for_conversation_participation_recipient_ships.exs b/priv/repo/migrations/20191026190712_set_not_null_for_conversation_participation_recipient_ships.exs new file mode 100644 index 000000000..a5ab1d3c9 --- /dev/null +++ b/priv/repo/migrations/20191026190712_set_not_null_for_conversation_participation_recipient_ships.exs @@ -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 diff --git a/priv/repo/migrations/20191026190759_set_not_null_for_conversation_participations.exs b/priv/repo/migrations/20191026190759_set_not_null_for_conversation_participations.exs new file mode 100644 index 000000000..cabb1f29f --- /dev/null +++ b/priv/repo/migrations/20191026190759_set_not_null_for_conversation_participations.exs @@ -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 diff --git a/priv/repo/migrations/20191026190841_set_not_null_for_filters.exs b/priv/repo/migrations/20191026190841_set_not_null_for_filters.exs new file mode 100644 index 000000000..52d7e687a --- /dev/null +++ b/priv/repo/migrations/20191026190841_set_not_null_for_filters.exs @@ -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 diff --git a/priv/repo/migrations/20191026191023_set_not_null_for_instances.exs b/priv/repo/migrations/20191026191023_set_not_null_for_instances.exs new file mode 100644 index 000000000..4c2560da5 --- /dev/null +++ b/priv/repo/migrations/20191026191023_set_not_null_for_instances.exs @@ -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 diff --git a/priv/repo/migrations/20191026191100_set_not_null_for_lists.exs b/priv/repo/migrations/20191026191100_set_not_null_for_lists.exs new file mode 100644 index 000000000..40b8b136a --- /dev/null +++ b/priv/repo/migrations/20191026191100_set_not_null_for_lists.exs @@ -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 diff --git a/priv/repo/migrations/20191026191134_set_not_null_for_markers.exs b/priv/repo/migrations/20191026191134_set_not_null_for_markers.exs new file mode 100644 index 000000000..7d7b73e7b --- /dev/null +++ b/priv/repo/migrations/20191026191134_set_not_null_for_markers.exs @@ -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 diff --git a/priv/repo/migrations/20191026191218_set_not_null_for_moderation_log.exs b/priv/repo/migrations/20191026191218_set_not_null_for_moderation_log.exs new file mode 100644 index 000000000..7238ca7f5 --- /dev/null +++ b/priv/repo/migrations/20191026191218_set_not_null_for_moderation_log.exs @@ -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 diff --git a/priv/repo/migrations/20191026191249_set_not_null_for_notifications.exs b/priv/repo/migrations/20191026191249_set_not_null_for_notifications.exs new file mode 100644 index 000000000..7e2976bab --- /dev/null +++ b/priv/repo/migrations/20191026191249_set_not_null_for_notifications.exs @@ -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 diff --git a/priv/repo/migrations/20191026191328_set_not_null_for_oauth_authorizations.exs b/priv/repo/migrations/20191026191328_set_not_null_for_oauth_authorizations.exs new file mode 100644 index 000000000..bc6b36e69 --- /dev/null +++ b/priv/repo/migrations/20191026191328_set_not_null_for_oauth_authorizations.exs @@ -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 diff --git a/priv/repo/migrations/20191026191401_set_not_null_for_oauth_tokens.exs b/priv/repo/migrations/20191026191401_set_not_null_for_oauth_tokens.exs new file mode 100644 index 000000000..fe67db8cc --- /dev/null +++ b/priv/repo/migrations/20191026191401_set_not_null_for_oauth_tokens.exs @@ -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 diff --git a/priv/repo/migrations/20191026191442_set_not_null_for_objects.exs b/priv/repo/migrations/20191026191442_set_not_null_for_objects.exs new file mode 100644 index 000000000..59e89d6da --- /dev/null +++ b/priv/repo/migrations/20191026191442_set_not_null_for_objects.exs @@ -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 diff --git a/priv/repo/migrations/20191026191524_set_not_null_for_password_reset_tokens.exs b/priv/repo/migrations/20191026191524_set_not_null_for_password_reset_tokens.exs new file mode 100644 index 000000000..51efadbd3 --- /dev/null +++ b/priv/repo/migrations/20191026191524_set_not_null_for_password_reset_tokens.exs @@ -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 diff --git a/priv/repo/migrations/20191026191603_set_not_null_for_push_subscriptions.exs b/priv/repo/migrations/20191026191603_set_not_null_for_push_subscriptions.exs new file mode 100644 index 000000000..0f3a73067 --- /dev/null +++ b/priv/repo/migrations/20191026191603_set_not_null_for_push_subscriptions.exs @@ -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 diff --git a/priv/repo/migrations/20191026191635_set_not_null_for_registrations.exs b/priv/repo/migrations/20191026191635_set_not_null_for_registrations.exs new file mode 100644 index 000000000..ddfbf4c5e --- /dev/null +++ b/priv/repo/migrations/20191026191635_set_not_null_for_registrations.exs @@ -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 diff --git a/priv/repo/migrations/20191026191711_set_not_null_for_scheduled_activities.exs b/priv/repo/migrations/20191026191711_set_not_null_for_scheduled_activities.exs new file mode 100644 index 000000000..f1830c8c3 --- /dev/null +++ b/priv/repo/migrations/20191026191711_set_not_null_for_scheduled_activities.exs @@ -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 diff --git a/priv/repo/migrations/20191026191753_set_not_null_for_thread_mutes.exs b/priv/repo/migrations/20191026191753_set_not_null_for_thread_mutes.exs new file mode 100644 index 000000000..daa7ce314 --- /dev/null +++ b/priv/repo/migrations/20191026191753_set_not_null_for_thread_mutes.exs @@ -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 diff --git a/priv/repo/migrations/20191026191826_set_not_null_for_user_invite_tokens.exs b/priv/repo/migrations/20191026191826_set_not_null_for_user_invite_tokens.exs new file mode 100644 index 000000000..836544f7f --- /dev/null +++ b/priv/repo/migrations/20191026191826_set_not_null_for_user_invite_tokens.exs @@ -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 diff --git a/priv/repo/migrations/20191026191910_set_not_null_for_users.exs b/priv/repo/migrations/20191026191910_set_not_null_for_users.exs new file mode 100644 index 000000000..9d8d0ccf8 --- /dev/null +++ b/priv/repo/migrations/20191026191910_set_not_null_for_users.exs @@ -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 diff --git a/priv/repo/migrations/20191029101340_migrate_missing_follow_requests.exs b/priv/repo/migrations/20191029101340_migrate_missing_follow_requests.exs new file mode 100644 index 000000000..90b18efc8 --- /dev/null +++ b/priv/repo/migrations/20191029101340_migrate_missing_follow_requests.exs @@ -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 diff --git a/priv/repo/migrations/20191029172832_fix_blocked_follows.exs b/priv/repo/migrations/20191029172832_fix_blocked_follows.exs new file mode 100644 index 000000000..71f8f1330 --- /dev/null +++ b/priv/repo/migrations/20191029172832_fix_blocked_follows.exs @@ -0,0 +1,112 @@ +defmodule Pleroma.Repo.Migrations.FixBlockedFollows do +  use Ecto.Migration + +  import Ecto.Query +  alias Pleroma.Config +  alias Pleroma.Repo + +  def up do +    unfollow_blocked = Config.get([:activitypub, :unfollow_blocked]) + +    if unfollow_blocked do +      "activities" +      |> where([activity], fragment("? ->> 'type' = 'Block'", activity.data)) +      |> distinct([activity], [ +        activity.actor, +        fragment( +          "coalesce((?)->'object'->>'id', (?)->>'object')", +          activity.data, +          activity.data +        ) +      ]) +      |> order_by([activity], [fragment("? desc nulls last", activity.id)]) +      |> select([activity], %{ +        blocker: activity.actor, +        blocked: +          fragment("coalesce((?)->'object'->>'id', (?)->>'object')", activity.data, activity.data), +        created_at: activity.id +      }) +      |> Repo.stream() +      |> Enum.map(&unfollow_if_blocked/1) +      |> Enum.uniq() +      |> Enum.each(&update_follower_count/1) +    end +  end + +  def down do +  end + +  def unfollow_if_blocked(%{blocker: blocker_id, blocked: blocked_id, created_at: blocked_at}) do +    query = +      from( +        activity in "activities", +        where: fragment("? ->> 'type' = 'Follow'", activity.data), +        where: activity.actor == ^blocked_id, +        # this is to use the index +        where: +          fragment( +            "coalesce((?)->'object'->>'id', (?)->>'object') = ?", +            activity.data, +            activity.data, +            ^blocker_id +          ), +        where: activity.id > ^blocked_at, +        where: fragment("(?)->>'state' = 'accept'", activity.data), +        order_by: [fragment("? desc nulls last", activity.id)] +      ) + +    unless Repo.exists?(query) do +      blocker = "users" |> select([:id, :local]) |> Repo.get_by(ap_id: blocker_id) +      blocked = "users" |> select([:id]) |> Repo.get_by(ap_id: blocked_id) + +      if !is_nil(blocker) && !is_nil(blocked) do +        unfollow(blocked, blocker) +      end +    end +  end + +  def unfollow(%{id: follower_id}, %{id: followed_id} = followed) do +    following_relationship = +      "following_relationships" +      |> where(follower_id: ^follower_id, following_id: ^followed_id, state: "accept") +      |> select([:id]) +      |> Repo.one() + +    case following_relationship do +      nil -> +        {:ok, nil} + +      %{id: following_relationship_id} -> +        "following_relationships" +        |> where(id: ^following_relationship_id) +        |> Repo.delete_all() + +        followed +    end +  end + +  def update_follower_count(%{id: user_id} = user) do +    if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do +      follower_count_query = +        "users" +        |> where([u], u.id != ^user_id) +        |> where([u], u.deactivated != ^true) +        |> join(:inner, [u], r in "following_relationships", +          as: :relationships, +          on: r.following_id == ^user_id and r.follower_id == u.id +        ) +        |> where([relationships: r], r.state == "accept") +        |> select([u], %{count: count(u.id)}) + +      "users" +      |> where(id: ^user_id) +      |> join(:inner, [u], s in subquery(follower_count_query)) +      |> update([u, s], +        set: [follower_count: s.count] +      ) +      |> Repo.update_all([]) +    end +  end + +  def update_follower_count(_), do: :noop +end diff --git a/priv/repo/migrations/20191104133100_set_visible_service_actors.exs b/priv/repo/migrations/20191104133100_set_visible_service_actors.exs new file mode 100644 index 000000000..62907093c --- /dev/null +++ b/priv/repo/migrations/20191104133100_set_visible_service_actors.exs @@ -0,0 +1,22 @@ +defmodule Pleroma.Repo.Migrations.SetVisibleServiceActors do +  use Ecto.Migration +  import Ecto.Query +  alias Pleroma.Repo + +  def up do +    user_nicknames = ["relay", "internal.fetch"] + +    from( +      u in "users", +      where: u.nickname in ^user_nicknames, +      update: [ +        set: [invisible: true] +      ] +    ) +    |> Repo.update_all([]) +  end + +  def down do +    :ok +  end +end diff --git a/priv/repo/migrations/20191118084425_create_user_relationships.exs b/priv/repo/migrations/20191118084425_create_user_relationships.exs new file mode 100644 index 000000000..c281f887d --- /dev/null +++ b/priv/repo/migrations/20191118084425_create_user_relationships.exs @@ -0,0 +1,17 @@ +defmodule Pleroma.Repo.Migrations.CreateUserRelationships do +  use Ecto.Migration + +  def change do +    create_if_not_exists table(:user_relationships) do +      add(:source_id, references(:users, type: :uuid, on_delete: :delete_all)) +      add(:target_id, references(:users, type: :uuid, on_delete: :delete_all)) +      add(:relationship_type, :integer, null: false) + +      timestamps(updated_at: false) +    end + +    create_if_not_exists( +      unique_index(:user_relationships, [:source_id, :relationship_type, :target_id]) +    ) +  end +end diff --git a/priv/repo/migrations/20191118084500_data_migration_populate_user_relationships.exs b/priv/repo/migrations/20191118084500_data_migration_populate_user_relationships.exs new file mode 100644 index 000000000..990e9f3b8 --- /dev/null +++ b/priv/repo/migrations/20191118084500_data_migration_populate_user_relationships.exs @@ -0,0 +1,68 @@ +defmodule Pleroma.Repo.Migrations.DataMigrationPopulateUserRelationships do +  use Ecto.Migration + +  alias Ecto.Adapters.SQL +  alias Pleroma.Repo + +  require Logger + +  def up do +    Enum.each( +      [blocks: 1, mutes: 2, muted_reblogs: 3, muted_notifications: 4, subscribers: 5], +      fn {field, relationship_type_code} -> +        migrate(field, relationship_type_code) + +        if field == :subscribers do +          drop_if_exists(index(:users, [:subscribers])) +        end +      end +    ) +  end + +  def down, do: :noop + +  defp migrate(field, relationship_type_code) do +    Logger.info("Processing users.#{field}...") + +    {:ok, %{rows: field_rows}} = +      SQL.query(Repo, "SELECT id, #{field} FROM users WHERE #{field} != '{}'") + +    target_ap_ids = +      Enum.flat_map( +        field_rows, +        fn [_, ap_ids] -> ap_ids end +      ) +      |> Enum.uniq() + +    # Selecting ids of all targets at once in order to reduce the number of SELECT queries +    {:ok, %{rows: target_ap_id_id}} = +      SQL.query(Repo, "SELECT ap_id, id FROM users WHERE ap_id = ANY($1)", [target_ap_ids]) + +    target_id_by_ap_id = Enum.into(target_ap_id_id, %{}, fn [k, v] -> {k, v} end) + +    Enum.each( +      field_rows, +      fn [source_id, target_ap_ids] -> +        source_uuid = Ecto.UUID.cast!(source_id) + +        for target_ap_id <- target_ap_ids do +          target_id = target_id_by_ap_id[target_ap_id] + +          with {:ok, target_uuid} <- target_id && Ecto.UUID.cast(target_id) do +            execute(""" +            INSERT INTO user_relationships( +              source_id, target_id, relationship_type, inserted_at +            ) +            VALUES( +              '#{source_uuid}'::uuid, '#{target_uuid}'::uuid, #{relationship_type_code}, now() +            ) +            ON CONFLICT (source_id, relationship_type, target_id) DO NOTHING +            """) +          else +            _ -> Logger.warn("Unresolved #{field} reference: (#{source_uuid}, #{target_id})") +          end +        end +      end +    ) +  end +end diff --git a/priv/repo/migrations/20191123030554_add_activitypub_actor_type.exs b/priv/repo/migrations/20191123030554_add_activitypub_actor_type.exs new file mode 100644 index 000000000..76d3b32c4 --- /dev/null +++ b/priv/repo/migrations/20191123030554_add_activitypub_actor_type.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.AddActivitypubActorType do +  use Ecto.Migration + +  def change do +    alter table("users") do +      add(:actor_type, :string, null: false, default: "Person") +    end +  end +end diff --git a/priv/repo/migrations/20191123103423_remove_info_from_users.exs b/priv/repo/migrations/20191123103423_remove_info_from_users.exs new file mode 100644 index 000000000..b251255ea --- /dev/null +++ b/priv/repo/migrations/20191123103423_remove_info_from_users.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.RemoveInfoFromUsers do +  use Ecto.Migration + +  def change do +    alter table(:users) do +      remove(:info, :map, default: %{}) +    end +  end +end diff --git a/priv/repo/migrations/20191128153944_fix_missing_following_count.exs b/priv/repo/migrations/20191128153944_fix_missing_following_count.exs new file mode 100644 index 000000000..3236de7a4 --- /dev/null +++ b/priv/repo/migrations/20191128153944_fix_missing_following_count.exs @@ -0,0 +1,53 @@ +defmodule Pleroma.Repo.Migrations.FixMissingFollowingCount do +  use Ecto.Migration + +  def up do +    """ +    UPDATE +      users +    SET +      following_count = sub.count +    FROM +      ( +        SELECT +          users.id AS sub_id +          ,COUNT (following_relationships.id) +        FROM +          following_relationships +          ,users +        WHERE +          users.id = following_relationships.follower_id +        AND following_relationships.state = 'accept' +        GROUP BY +          users.id +      ) AS sub +    WHERE +      users.id = sub.sub_id +    AND users.local = TRUE +    ; +    """ +    |> execute() + +    """ +    UPDATE +      users +    SET +      following_count = 0 +    WHERE +      following_count IS NULL +    """ +    |> execute() + +    execute("ALTER TABLE users +      ALTER COLUMN following_count SET DEFAULT 0, +      ALTER COLUMN following_count SET NOT NULL +    ") +  end + +  def down do +    execute("ALTER TABLE users +      ALTER COLUMN following_count DROP DEFAULT, +      ALTER COLUMN following_count DROP NOT NULL +    ") +  end +end diff --git a/priv/repo/migrations/20191203043610_create_report_notes.exs b/priv/repo/migrations/20191203043610_create_report_notes.exs new file mode 100644 index 000000000..a4f8c096d --- /dev/null +++ b/priv/repo/migrations/20191203043610_create_report_notes.exs @@ -0,0 +1,13 @@ +defmodule Pleroma.Repo.Migrations.CreateReportNotes do +  use Ecto.Migration + +  def change do +    create_if_not_exists table(:report_notes) do +      add(:user_id, references(:users, type: :uuid)) +      add(:activity_id, references(:activities, type: :uuid)) +      add(:content, :string) + +      timestamps() +    end +  end +end diff --git a/priv/repo/migrations/20191220174645_add_scopes_to_pleroma_feo_auth_records.exs b/priv/repo/migrations/20191220174645_add_scopes_to_pleroma_feo_auth_records.exs new file mode 100644 index 000000000..6b160ad16 --- /dev/null +++ b/priv/repo/migrations/20191220174645_add_scopes_to_pleroma_feo_auth_records.exs @@ -0,0 +1,17 @@ +defmodule Pleroma.Repo.Migrations.AddScopesToPleromaFEOAuthRecords do +  use Ecto.Migration + +  def up do +    update_scopes_clause = "SET scopes = '{read,write,follow,push,admin}'" +    apps_where = "WHERE apps.client_name like 'PleromaFE_%' or apps.client_name like 'AdminFE_%'" +    app_id_subquery_where = "WHERE app_id IN (SELECT apps.id FROM apps #{apps_where})" + +    execute("UPDATE apps #{update_scopes_clause} #{apps_where}") + +    for table <- ["oauth_authorizations", "oauth_tokens"] do +      execute("UPDATE #{table} #{update_scopes_clause} #{app_id_subquery_where}") +    end +  end + +  def down, do: :noop +end diff --git a/priv/repo/migrations/20200109123126_add_counter_cache_table.exs b/priv/repo/migrations/20200109123126_add_counter_cache_table.exs new file mode 100644 index 000000000..df9e21193 --- /dev/null +++ b/priv/repo/migrations/20200109123126_add_counter_cache_table.exs @@ -0,0 +1,55 @@ +defmodule Pleroma.Repo.Migrations.AddCounterCacheTable do +  use Ecto.Migration + +  def up do +    create_if_not_exists table(:counter_cache) do +      add(:name, :string, null: false) +      add(:count, :bigint, null: false, default: 0) +    end + +    create_if_not_exists(unique_index(:counter_cache, [:name])) + +    """ +    CREATE OR REPLACE FUNCTION update_status_visibility_counter_cache() +    RETURNS TRIGGER AS +    $$ +      DECLARE +      BEGIN +      IF TG_OP = 'INSERT' THEN +          IF NEW.data->>'type' = 'Create' THEN +            EXECUTE 'INSERT INTO counter_cache (name, count) VALUES (''status_visibility_' || activity_visibility(NEW.actor, NEW.recipients, NEW.data) || ''', 1) ON CONFLICT (name) DO UPDATE SET count = counter_cache.count + 1'; +          END IF; +          RETURN NEW; +      ELSIF TG_OP = 'UPDATE' THEN +          IF (NEW.data->>'type' = 'Create') and (OLD.data->>'type' = 'Create') and activity_visibility(NEW.actor, NEW.recipients, NEW.data) != activity_visibility(OLD.actor, OLD.recipients, OLD.data) THEN +             EXECUTE 'INSERT INTO counter_cache (name, count) VALUES (''status_visibility_' || activity_visibility(NEW.actor, NEW.recipients, NEW.data) || ''', 1) ON CONFLICT (name) DO UPDATE SET count = counter_cache.count + 1'; +             EXECUTE 'update counter_cache SET count = counter_cache.count - 1 where count > 0 and name = ''status_visibility_' || activity_visibility(OLD.actor, OLD.recipients, OLD.data) || ''';'; +          END IF; +          RETURN NEW; +      ELSIF TG_OP = 'DELETE' THEN +          IF OLD.data->>'type' = 'Create' THEN +            EXECUTE 'update counter_cache SET count = counter_cache.count - 1 where count > 0 and name = ''status_visibility_' || activity_visibility(OLD.actor, OLD.recipients, OLD.data) || ''';'; +          END IF; +          RETURN OLD; +      END IF; +      END; +    $$ +    LANGUAGE 'plpgsql'; +    """ +    |> execute() + +    """ +    CREATE TRIGGER status_visibility_counter_cache_trigger BEFORE INSERT OR UPDATE of recipients, data OR DELETE ON activities +    FOR EACH ROW +    EXECUTE PROCEDURE update_status_visibility_counter_cache(); +    """ +    |> execute() +  end + +  def down do +    execute("drop trigger if exists status_visibility_counter_cache_trigger on activities") +    execute("drop function if exists update_status_visibility_counter_cache()") +    drop_if_exists(unique_index(:counter_cache, [:name])) +    drop_if_exists(table(:counter_cache)) +  end +end diff --git a/priv/repo/migrations/20200227122417_add_trusted_to_apps.exs b/priv/repo/migrations/20200227122417_add_trusted_to_apps.exs new file mode 100644 index 000000000..4e2a62af0 --- /dev/null +++ b/priv/repo/migrations/20200227122417_add_trusted_to_apps.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.AddTrustedToApps do +  use Ecto.Migration + +  def change do +    alter table(:apps) do +      add(:trusted, :boolean, default: false) +    end +  end +end diff --git a/priv/repo/migrations/20200307103755_fix_moderation_log_subjects.exs b/priv/repo/migrations/20200307103755_fix_moderation_log_subjects.exs new file mode 100644 index 000000000..d1c8539e1 --- /dev/null +++ b/priv/repo/migrations/20200307103755_fix_moderation_log_subjects.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.FixModerationLogSubjects do +  use Ecto.Migration + +  def change do +    execute( +      "update moderation_log set data = safe_jsonb_set(data, '{subject}', safe_jsonb_set('[]'::jsonb, '{0}', data->'subject')) where jsonb_typeof(data->'subject') != 'array' and data->>'action' = ANY('{revoke,grant,activate,deactivate,delete}');" +    ) +  end +end diff --git a/priv/repo/migrations/20200314123607_config_remove_fetch_initial_posts.exs b/priv/repo/migrations/20200314123607_config_remove_fetch_initial_posts.exs new file mode 100644 index 000000000..392f531e8 --- /dev/null +++ b/priv/repo/migrations/20200314123607_config_remove_fetch_initial_posts.exs @@ -0,0 +1,10 @@ +defmodule Pleroma.Repo.Migrations.ConfigRemoveFetchInitialPosts do +  use Ecto.Migration + +  def change do +    execute( +      "delete from config where config.key = ':fetch_initial_posts' and config.group = ':pleroma';", +      "" +    ) +  end +end diff --git a/priv/repo/migrations/20200315125756_delete_fetch_initial_posts_jobs.exs b/priv/repo/migrations/20200315125756_delete_fetch_initial_posts_jobs.exs new file mode 100644 index 000000000..5b8e3ab91 --- /dev/null +++ b/priv/repo/migrations/20200315125756_delete_fetch_initial_posts_jobs.exs @@ -0,0 +1,10 @@ +defmodule Pleroma.Repo.Migrations.DeleteFetchInitialPostsJobs do +  use Ecto.Migration + +  def change do +    execute( +      "delete from oban_jobs where worker = 'Pleroma.Workers.BackgroundWorker' and args->>'op' = 'fetch_initial_posts';", +      "" +    ) +  end +end diff --git a/priv/repo/migrations/20200328124805_change_following_relationships_state_to_integer.exs b/priv/repo/migrations/20200328124805_change_following_relationships_state_to_integer.exs new file mode 100644 index 000000000..2b0820f3f --- /dev/null +++ b/priv/repo/migrations/20200328124805_change_following_relationships_state_to_integer.exs @@ -0,0 +1,29 @@ +defmodule Pleroma.Repo.Migrations.ChangeFollowingRelationshipsStateToInteger do +  use Ecto.Migration + +  @alter_following_relationship_state "ALTER TABLE following_relationships ALTER COLUMN state" + +  def up do +    execute(""" +    #{@alter_following_relationship_state} TYPE integer USING +    CASE +      WHEN state = 'pending' THEN 1 +      WHEN state = 'accept' THEN 2 +      WHEN state = 'reject' THEN 3 +      ELSE 0 +    END; +    """) +  end + +  def down do +    execute(""" +    #{@alter_following_relationship_state} TYPE varchar(255) USING +    CASE +      WHEN state = 1 THEN 'pending' +      WHEN state = 2 THEN 'accept' +      WHEN state = 3 THEN 'reject' +      ELSE '' +    END; +    """) +  end +end diff --git a/priv/repo/migrations/20200328130139_add_following_relationships_following_id_index.exs b/priv/repo/migrations/20200328130139_add_following_relationships_following_id_index.exs new file mode 100644 index 000000000..884832f84 --- /dev/null +++ b/priv/repo/migrations/20200328130139_add_following_relationships_following_id_index.exs @@ -0,0 +1,11 @@ +defmodule Pleroma.Repo.Migrations.AddFollowingRelationshipsFollowingIdIndex do +  use Ecto.Migration + +  # [:follower_index] index is useless because of [:follower_id, :following_id] index +  # [:following_id] index makes sense because of user's followers-targeted queries +  def change do +    drop_if_exists(index(:following_relationships, [:follower_id])) + +    create_if_not_exists(index(:following_relationships, [:following_id])) +  end +end diff --git a/priv/repo/migrations/20200401030751_users_add_public_key.exs b/priv/repo/migrations/20200401030751_users_add_public_key.exs new file mode 100644 index 000000000..04e5ad1e2 --- /dev/null +++ b/priv/repo/migrations/20200401030751_users_add_public_key.exs @@ -0,0 +1,17 @@ +defmodule Pleroma.Repo.Migrations.UsersAddPublicKey do +  use Ecto.Migration + +  def up do +    alter table(:users) do +      add_if_not_exists(:public_key, :text) +    end + +    execute("UPDATE users SET public_key = source_data->'publicKey'->>'publicKeyPem'") +  end + +  def down do +    alter table(:users) do +      remove_if_exists(:public_key, :text) +    end +  end +end diff --git a/priv/repo/migrations/20200401072456_users_add_inboxes.exs b/priv/repo/migrations/20200401072456_users_add_inboxes.exs new file mode 100644 index 000000000..0947f0ab2 --- /dev/null +++ b/priv/repo/migrations/20200401072456_users_add_inboxes.exs @@ -0,0 +1,20 @@ +defmodule Pleroma.Repo.Migrations.UsersAddInboxes do +  use Ecto.Migration + +  def up do +    alter table(:users) do +      add_if_not_exists(:inbox, :text) +      add_if_not_exists(:shared_inbox, :text) +    end + +    execute("UPDATE users SET inbox = source_data->>'inbox'") +    execute("UPDATE users SET shared_inbox = source_data->'endpoints'->>'sharedInbox'") +  end + +  def down do +    alter table(:users) do +      remove_if_exists(:inbox, :text) +      remove_if_exists(:shared_inbox, :text) +    end +  end +end diff --git a/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs b/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs new file mode 100644 index 000000000..e7ff04008 --- /dev/null +++ b/priv/repo/migrations/20200402063221_update_oban_jobs_table.exs @@ -0,0 +1,11 @@ +defmodule Pleroma.Repo.Migrations.UpdateObanJobsTable do +  use Ecto.Migration + +  def up do +    Oban.Migrations.up(version: 8) +  end + +  def down do +    Oban.Migrations.down(version: 7) +  end +end diff --git a/priv/repo/migrations/20200406100225_users_add_emoji.exs b/priv/repo/migrations/20200406100225_users_add_emoji.exs new file mode 100644 index 000000000..f248108de --- /dev/null +++ b/priv/repo/migrations/20200406100225_users_add_emoji.exs @@ -0,0 +1,38 @@ +defmodule Pleroma.Repo.Migrations.UsersPopulateEmoji do +  use Ecto.Migration + +  import Ecto.Query + +  alias Pleroma.User +  alias Pleroma.Repo + +  def up do +    execute("ALTER TABLE users ALTER COLUMN emoji SET DEFAULT '{}'::jsonb") +    execute("UPDATE users SET emoji = DEFAULT WHERE emoji = '[]'::jsonb") + +    from(u in User) +    |> select([u], struct(u, [:id, :ap_id, :source_data])) +    |> Repo.stream() +    |> Enum.each(fn user -> +      emoji = +        user.source_data +        |> Map.get("tag", []) +        |> Enum.filter(fn +          %{"type" => "Emoji"} -> true +          _ -> false +        end) +        |> Enum.reduce(%{}, fn %{"icon" => %{"url" => url}, "name" => name}, acc -> +          Map.put(acc, String.trim(name, ":"), url) +        end) + +      user +      |> Ecto.Changeset.cast(%{emoji: emoji}, [:emoji]) +      |> Repo.update() +    end) +  end + +  def down do +    execute("ALTER TABLE users ALTER COLUMN emoji SET DEFAULT '[]'::jsonb") +    execute("UPDATE users SET emoji = DEFAULT WHERE emoji = '{}'::jsonb") +  end +end diff --git a/priv/repo/migrations/20200406105422_users_remove_source_data.exs b/priv/repo/migrations/20200406105422_users_remove_source_data.exs new file mode 100644 index 000000000..9812d480f --- /dev/null +++ b/priv/repo/migrations/20200406105422_users_remove_source_data.exs @@ -0,0 +1,15 @@ +defmodule Pleroma.Repo.Migrations.UsersRemoveSourceData do +  use Ecto.Migration + +  def up do +    alter table(:users) do +      remove_if_exists(:source_data, :map) +    end +  end + +  def down do +    alter table(:users) do +      add_if_not_exists(:source_data, :map, default: %{}) +    end +  end +end diff --git a/priv/repo/migrations/20200415181818_update_markers.exs b/priv/repo/migrations/20200415181818_update_markers.exs new file mode 100644 index 000000000..bb9d8e860 --- /dev/null +++ b/priv/repo/migrations/20200415181818_update_markers.exs @@ -0,0 +1,44 @@ +defmodule Pleroma.Repo.Migrations.UpdateMarkers do +  use Ecto.Migration +  import Ecto.Query +  alias Pleroma.Repo + +  def up do +    update_markers() +  end + +  def down do +    :ok +  end + +  defp update_markers do +    now = NaiveDateTime.utc_now() + +    markers_attrs = +      from(q in "notifications", +        select: %{ +          timeline: "notifications", +          user_id: q.user_id, +          last_read_id: +            type(fragment("MAX( CASE WHEN seen = true THEN id ELSE null END )"), :string) +        }, +        group_by: [q.user_id] +      ) +      |> Repo.all() +      |> Enum.map(fn %{last_read_id: last_read_id} = attrs -> +        attrs +        |> Map.put(:last_read_id, last_read_id || "") +        |> Map.put_new(:inserted_at, now) +        |> Map.put_new(:updated_at, now) +      end) + +    markers_attrs +    |> Enum.chunk_every(1000) +    |> Enum.each(fn markers_attrs_chunked -> +      Repo.insert_all("markers", markers_attrs_chunked, +        on_conflict: {:replace, [:last_read_id]}, +        conflict_target: [:user_id, :timeline] +      ) +    end) +  end +end diff --git a/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs b/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs new file mode 100644 index 000000000..2adc38186 --- /dev/null +++ b/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs @@ -0,0 +1,45 @@ +defmodule Pleroma.Repo.Migrations.InsertSkeletonsForDeletedUsers do +  use Ecto.Migration + +  alias Pleroma.User +  alias Pleroma.Repo + +  import Ecto.Query + +  def change do +    Application.ensure_all_started(:flake_id) + +    local_ap_id = +      User.Query.build(%{local: true}) +      |> select([u], u.ap_id) +      |> limit(1) +      |> Repo.one() + +    unless local_ap_id == nil do +      # Hack to get instance base url because getting it from Phoenix +      # would require starting the whole application +      instance_uri = +        local_ap_id +        |> URI.parse() +        |> Map.put(:query, nil) +        |> Map.put(:path, nil) +        |> URI.to_string() + +      {:ok, %{rows: ap_ids}} = +        Ecto.Adapters.SQL.query( +          Repo, +          "select distinct unnest(nonexistent_locals.recipients) from activities, lateral (select array_agg(recipient) as recipients from unnest(activities.recipients) as recipient where recipient similar to '#{ +            instance_uri +          }/users/[A-Za-z0-9]*' and not(recipient in (select ap_id from users))) nonexistent_locals;", +          [], +          timeout: :infinity +        ) + +      ap_ids +      |> Enum.each(fn [ap_id] -> +        Ecto.Changeset.change(%User{}, deactivated: true, ap_id: ap_id) +        |> Repo.insert() +      end) +    end +  end +end diff --git a/priv/repo/migrations/20200505072231_remove_magic_key_field.exs b/priv/repo/migrations/20200505072231_remove_magic_key_field.exs new file mode 100644 index 000000000..2635e671b --- /dev/null +++ b/priv/repo/migrations/20200505072231_remove_magic_key_field.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.RemoveMagicKeyField do +  use Ecto.Migration + +  def change do +    alter table(:users) do +      remove(:magic_key, :string) +    end +  end +end | 
