Merge branch 'develop' into feature/multiple-users-activation-permissions

This commit is contained in:
Maxim Filippov 2019-10-11 15:59:35 +03:00
commit c0aca32dd0
110 changed files with 831 additions and 300 deletions

View file

@ -1,3 +1,3 @@
[ [
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}", "priv/repo/migrations/*.exs"]
] ]

View file

@ -16,10 +16,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- OAuth: support for hierarchical permissions / [Mastodon 2.4.3 OAuth permissions](https://docs.joinmastodon.org/api/permissions/) - OAuth: support for hierarchical permissions / [Mastodon 2.4.3 OAuth permissions](https://docs.joinmastodon.org/api/permissions/)
- Authentication: Added rate limit for password-authorized actions / login existence checks - Authentication: Added rate limit for password-authorized actions / login existence checks
- Metadata Link: Atom syndication Feed - Metadata Link: Atom syndication Feed
- Mix task to re-count statuses for all users (`mix pleroma.count_statuses`)
- Admin API: `/users/:nickname/toggle_activation` endpoint is now deprecated in favor of: `/users/activate`, `/users/deactivate`, both accept `nicknames` array - Admin API: `/users/:nickname/toggle_activation` endpoint is now deprecated in favor of: `/users/activate`, `/users/deactivate`, both accept `nicknames` array
- Admin API: `POST /api/pleroma/admin/users/:nickname/permission_group/:permission_group` / `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST /api/pleroma/admin/users/permission_group/:permission_group` / `DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array) - Admin API: `POST /api/pleroma/admin/users/:nickname/permission_group/:permission_group` / `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST /api/pleroma/admin/users/permission_group/:permission_group` / `DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array)
### Changed ### Changed
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7) - **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
- **Breaking:** Admin API: Return link alongside with token on password reset - **Breaking:** Admin API: Return link alongside with token on password reset
@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Admin API: Return link alongside with token on password reset - Admin API: Return link alongside with token on password reset
- MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities - MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities
- OStatus: Extract RSS functionality - OStatus: Extract RSS functionality
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
### Fixed ### Fixed
- Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`) - Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)

View file

@ -0,0 +1,22 @@
defmodule Mix.Tasks.Pleroma.CountStatuses do
@shortdoc "Re-counts statuses for all users"
use Mix.Task
alias Pleroma.User
import Ecto.Query
def run([]) do
Mix.Pleroma.start_pleroma()
stream =
User
|> where(local: true)
|> Pleroma.Repo.stream()
Pleroma.Repo.transaction(fn ->
Enum.each(stream, &User.update_note_count/1)
end)
Mix.Pleroma.shell_info("Done")
end
end

View file

@ -167,7 +167,11 @@ def create(%{assigns: %{user: _user}} = conn, %{"media_ids" => _} = params) do
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id), with %Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do true <- Visibility.visible_for_user?(activity, user) do
try_render(conn, "show.json", activity: activity, for: user) try_render(conn, "show.json",
activity: activity,
for: user,
with_direct_conversation_id: true
)
end end
end end

View file

@ -3,14 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreatePleroma.User do
def change do def change do
create_if_not_exists table(:users) do create_if_not_exists table(:users) do
add :email, :string add(:email, :string)
add :password_hash, :string add(:password_hash, :string)
add :name, :string add(:name, :string)
add :nickname, :string add(:nickname, :string)
add :bio, :string add(:bio, :string)
timestamps() timestamps()
end end
end end
end end

View file

@ -3,12 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreatePleroma.Activity do
def change do def change do
create_if_not_exists table(:activities) do create_if_not_exists table(:activities) do
add :data, :map add(:data, :map)
timestamps() timestamps()
end end
create_if_not_exists index(:activities, [:data], using: :gin) create_if_not_exists(index(:activities, [:data], using: :gin))
end end
end end

View file

@ -3,10 +3,9 @@ defmodule Pleroma.Repo.Migrations.CreatePleroma.Object do
def change do def change do
create_if_not_exists table(:objects) do create_if_not_exists table(:objects) do
add :data, :map add(:data, :map)
timestamps() timestamps()
end end
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddFollowingListToUsers do
def change do def change do
alter table(:users) do alter table(:users) do
add :following, :map add(:following, :map)
end end
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddApIdToUsers do
def change do def change do
alter table(:users) do alter table(:users) do
add :ap_id, :string add(:ap_id, :string)
end end
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddIndexToObjects do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:objects, [:data], using: :gin) create_if_not_exists(index(:objects, [:data], using: :gin))
end end
end end

View file

@ -2,7 +2,7 @@ defmodule Pleroma.Repo.Migrations.AddUniqueIndexToEmailAndNickname do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists unique_index(:users, [:email]) create_if_not_exists(unique_index(:users, [:email]))
create_if_not_exists unique_index(:users, [:nickname]) create_if_not_exists(unique_index(:users, [:nickname]))
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddAvatarObjectToUsers do
def change do def change do
alter table(:users) do alter table(:users) do
add :avatar, :map add(:avatar, :map)
end end
end end
end end

View file

@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateWebsubServerSubscription do
def change do def change do
create_if_not_exists table(:websub_server_subscriptions) do create_if_not_exists table(:websub_server_subscriptions) do
add :topic, :string add(:topic, :string)
add :callback, :string add(:callback, :string)
add :secret, :string add(:secret, :string)
add :valid_until, :naive_datetime add(:valid_until, :naive_datetime)
add :state, :string add(:state, :string)
timestamps() timestamps()
end end

View file

@ -3,8 +3,8 @@ defmodule Pleroma.Repo.Migrations.AddFieldsToUsers do
def change do def change do
alter table(:users) do alter table(:users) do
add :local, :boolean, default: true add(:local, :boolean, default: true)
add :info, :map add(:info, :map)
end end
end end
end end

View file

@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateWebsubClientSubscription do
def change do def change do
create_if_not_exists table(:websub_client_subscriptions) do create_if_not_exists table(:websub_client_subscriptions) do
add :topic, :string add(:topic, :string)
add :secret, :string add(:secret, :string)
add :valid_until, :naive_datetime_usec add(:valid_until, :naive_datetime_usec)
add :state, :string add(:state, :string)
add :subscribers, :map add(:subscribers, :map)
timestamps() timestamps()
end end

View file

@ -3,8 +3,8 @@ defmodule Pleroma.Repo.Migrations.AddUserAndHub do
def change do def change do
alter table(:websub_client_subscriptions) do alter table(:websub_client_subscriptions) do
add :hub, :string add(:hub, :string)
add :user_id, references(:users) add(:user_id, references(:users))
end end
end end
end end

View file

@ -2,10 +2,16 @@ defmodule Pleroma.Repo.Migrations.AddIdContraintsToActivitiesAndObjectsPartTwo d
use Ecto.Migration use Ecto.Migration
def up do def up do
drop_if_exists index(:objects, ["(data->>\"id\")"], name: :objects_unique_apid_index) drop_if_exists(index(:objects, ["(data->>\"id\")"], name: :objects_unique_apid_index))
drop_if_exists index(:activities, ["(data->>\"id\")"], name: :activities_unique_apid_index) drop_if_exists(index(:activities, ["(data->>\"id\")"], name: :activities_unique_apid_index))
create_if_not_exists unique_index(:objects, ["(data->>'id')"], name: :objects_unique_apid_index)
create_if_not_exists unique_index(:activities, ["(data->>'id')"], name: :activities_unique_apid_index) create_if_not_exists(
unique_index(:objects, ["(data->>'id')"], name: :objects_unique_apid_index)
)
create_if_not_exists(
unique_index(:activities, ["(data->>'id')"], name: :activities_unique_apid_index)
)
end end
def down, do: :ok def down, do: :ok

View file

@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.AddLocalFieldToActivities do
def change do def change do
alter table(:activities) do alter table(:activities) do
add :local, :boolean, default: true add(:local, :boolean, default: true)
end end
create_if_not_exists index(:activities, [:local]) create_if_not_exists(index(:activities, [:local]))
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddUniqueIndexToAPID do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists unique_index(:users, [:ap_id]) create_if_not_exists(unique_index(:users, [:ap_id]))
end end
end end

View file

@ -3,14 +3,13 @@ defmodule Pleroma.Repo.Migrations.LongerBios do
def up do def up do
alter table(:users) do alter table(:users) do
modify :bio, :text modify(:bio, :text)
end end
end end
def down do def down do
alter table(:users) do alter table(:users) do
modify :bio, :string modify(:bio, :string)
end end
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.RemoveActivitiesIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
drop_if_exists index(:activities, [:data]) drop_if_exists(index(:activities, [:data]))
end end
end end

View file

@ -2,7 +2,16 @@ defmodule Pleroma.Repo.Migrations.AddObjectActivityIndexPartTwo do
use Ecto.Migration use Ecto.Migration
def change do def change do
drop_if_exists index(:objects, ["(data->'object'->>'id')", "(data->>'type')"], name: :activities_create_objects_index) drop_if_exists(
create_if_not_exists index(:activities, ["(data->'object'->>'id')", "(data->>'type')"], name: :activities_create_objects_index) index(:objects, ["(data->'object'->>'id')", "(data->>'type')"],
name: :activities_create_objects_index
)
)
create_if_not_exists(
index(:activities, ["(data->'object'->>'id')", "(data->>'type')"],
name: :activities_create_objects_index
)
)
end end
end end

View file

@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.AddActorIndexToActivity do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:activities, ["(data->>'actor')", "inserted_at desc"], name: :activities_actor_index) create_if_not_exists(
index(:activities, ["(data->>'actor')", "inserted_at desc"], name: :activities_actor_index)
)
end end
end end

View file

@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.AddFollowerAddressToUser do
def up do def up do
alter table(:users) do alter table(:users) do
add :follower_address, :string, unique: true add(:follower_address, :string, unique: true)
end end
end end
def down do def down do
alter table(:users) do alter table(:users) do
remove :follower_address remove(:follower_address)
end end
end end
end end

View file

@ -3,12 +3,12 @@ defmodule Pleroma.Repo.Migrations.AddMastodonApps do
def change do def change do
create_if_not_exists table(:apps) do create_if_not_exists table(:apps) do
add :client_name, :string add(:client_name, :string)
add :redirect_uris, :string add(:redirect_uris, :string)
add :scopes, :string add(:scopes, :string)
add :website, :string add(:website, :string)
add :client_id, :string add(:client_id, :string)
add :client_secret, :string add(:client_secret, :string)
timestamps() timestamps()
end end

View file

@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateOAuthAuthorizations do
def change do def change do
create_if_not_exists table(:oauth_authorizations) do create_if_not_exists table(:oauth_authorizations) do
add :app_id, references(:apps) add(:app_id, references(:apps))
add :user_id, references(:users) add(:user_id, references(:users))
add :token, :string add(:token, :string)
add :valid_until, :naive_datetime_usec add(:valid_until, :naive_datetime_usec)
add :used, :boolean, default: false add(:used, :boolean, default: false)
timestamps() timestamps()
end end

View file

@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateOAuthToken do
def change do def change do
create_if_not_exists table(:oauth_tokens) do create_if_not_exists table(:oauth_tokens) do
add :app_id, references(:apps) add(:app_id, references(:apps))
add :user_id, references(:users) add(:user_id, references(:users))
add :token, :string add(:token, :string)
add :refresh_token, :string add(:refresh_token, :string)
add :valid_until, :naive_datetime_usec add(:valid_until, :naive_datetime_usec)
timestamps() timestamps()
end end

View file

@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreateNotifications do
def change do def change do
create_if_not_exists table(:notifications) do create_if_not_exists table(:notifications) do
add :user_id, references(:users, on_delete: :delete_all) add(:user_id, references(:users, on_delete: :delete_all))
add :activity_id, references(:activities, on_delete: :delete_all) add(:activity_id, references(:activities, on_delete: :delete_all))
add :seen, :boolean, default: false add(:seen, :boolean, default: false)
timestamps() timestamps()
end end
create_if_not_exists index(:notifications, [:user_id]) create_if_not_exists(index(:notifications, [:user_id]))
end end
end end

View file

@ -3,6 +3,11 @@ defmodule Pleroma.Repo.Migrations.AddContextIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["(data->>'type')", "(data->>'context')"], name: :activities_context_index, concurrently: true) create(
index(:activities, ["(data->>'type')", "(data->>'context')"],
name: :activities_context_index,
concurrently: true
)
)
end end
end end

View file

@ -3,6 +3,12 @@ defmodule Pleroma.Repo.Migrations.AddFTSIndexToActivities do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["(to_tsvector('english', data->'object'->>'content'))"], concurrently: true, using: :gin, name: :activities_fts) create(
index(:activities, ["(to_tsvector('english', data->'object'->>'content'))"],
concurrently: true,
using: :gin,
name: :activities_fts
)
)
end end
end end

View file

@ -4,6 +4,12 @@ defmodule Pleroma.Repo.Migrations.AddTagIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["(data #> '{\"object\",\"tag\"}')"], concurrently: true, using: :gin, name: :activities_tags) create(
index(:activities, ["(data #> '{\"object\",\"tag\"}')"],
concurrently: true,
using: :gin,
name: :activities_tags
)
)
end end
end end

View file

@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.CreatePasswordResetTokens do
def change do def change do
create_if_not_exists table(:password_reset_tokens) do create_if_not_exists table(:password_reset_tokens) do
add :token, :string add(:token, :string)
add :user_id, references(:users) add(:user_id, references(:users))
add :used, :boolean, default: false add(:used, :boolean, default: false)
timestamps() timestamps()
end end

View file

@ -4,7 +4,17 @@ defmodule Pleroma.Repo.Migrations.AddSecondObjectIndexToActivty do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
drop_if_exists index(:activities, ["(data->'object'->>'id')", "(data->>'type')"], name: :activities_create_objects_index) drop_if_exists(
create index(:activities, ["(coalesce(data->'object'->>'id', data->>'object'))"], name: :activities_create_objects_index, concurrently: true) index(:activities, ["(data->'object'->>'id')", "(data->>'type')"],
name: :activities_create_objects_index
)
)
create(
index(:activities, ["(coalesce(data->'object'->>'id', data->>'object'))"],
name: :activities_create_objects_index,
concurrently: true
)
)
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.DropObjectIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
drop_if_exists index(:objects, [:data], using: :gin) drop_if_exists(index(:objects, [:data], using: :gin))
end end
end end

View file

@ -4,6 +4,11 @@ defmodule Pleroma.Repo.Migrations.AddObjectActorIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:objects, ["(data->>'actor')", "(data->>'type')"], concurrently: true, name: :objects_actor_type) create(
index(:objects, ["(data->>'actor')", "(data->>'type')"],
concurrently: true,
name: :objects_actor_type
)
)
end end
end end

View file

@ -5,16 +5,17 @@ defmodule Pleroma.Repo.Migrations.AddActorToActivity do
def up do def up do
alter table(:activities) do alter table(:activities) do
add :actor, :string add(:actor, :string)
end end
create index(:activities, [:actor, "id DESC NULLS LAST"], concurrently: true) create(index(:activities, [:actor, "id DESC NULLS LAST"], concurrently: true))
end end
def down do def down do
drop_if_exists index(:activities, [:actor, "id DESC NULLS LAST"]) drop_if_exists(index(:activities, [:actor, "id DESC NULLS LAST"]))
alter table(:activities) do alter table(:activities) do
remove :actor remove(:actor)
end end
end end
end end

View file

@ -5,17 +5,19 @@ defmodule Pleroma.Repo.Migrations.FillActorField do
def up do def up do
max = Repo.aggregate(Activity, :max, :id) max = Repo.aggregate(Activity, :max, :id)
if max do if max do
IO.puts("#{max} activities") IO.puts("#{max} activities")
chunks = 0..(round(max / 10_000)) chunks = 0..round(max / 10_000)
Enum.each(chunks, fn (i) -> Enum.each(chunks, fn i ->
min = i * 10_000 min = i * 10_000
max = min + 10_000 max = min + 10_000
execute(""" execute("""
update activities set actor = data->>'actor' where id > #{min} and id <= #{max}; update activities set actor = data->>'actor' where id > #{min} and id <= #{max};
""") """)
|> IO.inspect |> IO.inspect()
end) end)
end end
end end
@ -23,4 +25,3 @@ def up do
def down do def down do
end end
end end

View file

@ -3,6 +3,6 @@ defmodule Pleroma.Repo.Migrations.AddSortIndexToActivities do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["id desc nulls last"], concurrently: true) create(index(:activities, ["id desc nulls last"], concurrently: true))
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddLocalIndexToUser do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:users, [:local]) create_if_not_exists(index(:users, [:local]))
end end
end end

View file

@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.AddRecipientsToActivities do
def change do def change do
alter table(:activities) do alter table(:activities) do
add :recipients, {:array, :string} add(:recipients, {:array, :string})
end end
create_if_not_exists index(:activities, [:recipients], using: :gin) create_if_not_exists(index(:activities, [:recipients], using: :gin))
end end
end end

View file

@ -4,17 +4,21 @@ defmodule Pleroma.Repo.Migrations.FillRecipientsInActivities do
def up do def up do
max = Repo.aggregate(Activity, :max, :id) max = Repo.aggregate(Activity, :max, :id)
if max do if max do
IO.puts("#{max} activities") IO.puts("#{max} activities")
chunks = 0..(round(max / 10_000)) chunks = 0..round(max / 10_000)
Enum.each(chunks, fn (i) -> Enum.each(chunks, fn i ->
min = i * 10_000 min = i * 10_000
max = min + 10_000 max = min + 10_000
execute(""" execute("""
update activities set recipients = array(select jsonb_array_elements_text(data->'to')) where id > #{min} and id <= #{max}; update activities set recipients = array(select jsonb_array_elements_text(data->'to')) where id > #{
min
} and id <= #{max};
""") """)
|> IO.inspect |> IO.inspect()
end) end)
end end
end end

View file

@ -3,17 +3,18 @@ defmodule Pleroma.Repo.Migrations.MakeFollowingPostgresArray do
def up do def up do
alter table(:users) do alter table(:users) do
add :following_temp, {:array, :string} add(:following_temp, {:array, :string})
end end
execute """ execute("""
update users set following_temp = array(select jsonb_array_elements_text(following)); update users set following_temp = array(select jsonb_array_elements_text(following));
""" """)
alter table(:users) do alter table(:users) do
remove :following remove(:following)
end end
rename table(:users), :following_temp, to: :following
rename(table(:users), :following_temp, to: :following)
end end
def down, do: :ok def down, do: :ok

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddFollowerAddressIndexToUsers do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:users, [:follower_address], concurrently: true) create(index(:users, [:follower_address], concurrently: true))
create index(:users, [:following], concurrently: true, using: :gin) create(index(:users, [:following], concurrently: true, using: :gin))
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.DropLocalIndexOnActivities do
use Ecto.Migration use Ecto.Migration
def change do def change do
drop_if_exists index(:users, [:local]) drop_if_exists(index(:users, [:local]))
end end
end end

View file

@ -2,7 +2,7 @@ defmodule Pleroma.Repo.Migrations.ActuallyDropLocalIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:users, [:local]) create_if_not_exists(index(:users, [:local]))
drop_if_exists index("activities", :local) drop_if_exists(index("activities", :local))
end end
end end

View file

@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreateLists do
def change do def change do
create_if_not_exists table(:lists) do create_if_not_exists table(:lists) do
add :user_id, references(:users, on_delete: :delete_all) add(:user_id, references(:users, on_delete: :delete_all))
add :title, :string add(:title, :string)
add :following, {:array, :string} add(:following, {:array, :string})
timestamps() timestamps()
end end
create_if_not_exists index(:lists, [:user_id]) create_if_not_exists(index(:lists, [:user_id]))
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.ModifyActivityIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["id desc nulls last", "local"], concurrently: true) create(index(:activities, ["id desc nulls last", "local"], concurrently: true))
drop_if_exists index(:activities, ["id desc nulls last"]) drop_if_exists(index(:activities, ["id desc nulls last"]))
end end
end end

View file

@ -4,8 +4,15 @@ defmodule Pleroma.Repo.Migrations.AddTrigramExtension do
def up do def up do
Logger.warn("ATTENTION ATTENTION ATTENTION\n") Logger.warn("ATTENTION ATTENTION ATTENTION\n")
Logger.warn("This will try to create the pg_trgm extension on your database. If your database user does NOT have the necessary rights, you will have to do it manually and re-run the migrations.\nYou can probably do this by running the following:\n")
Logger.warn("sudo -u postgres psql pleroma_dev -c \"create extension if not exists pg_trgm\"\n") Logger.warn(
"This will try to create the pg_trgm extension on your database. If your database user does NOT have the necessary rights, you will have to do it manually and re-run the migrations.\nYou can probably do this by running the following:\n"
)
Logger.warn(
"sudo -u postgres psql pleroma_dev -c \"create extension if not exists pg_trgm\"\n"
)
execute("create extension if not exists pg_trgm") execute("create extension if not exists pg_trgm")
end end

View file

@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.CreateUserTrigramIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:users, ["(nickname || name) gist_trgm_ops"], name: :users_trigram_index, using: :gist) create_if_not_exists(
index(:users, ["(nickname || name) gist_trgm_ops"], name: :users_trigram_index, using: :gist)
)
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddListFollowIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:lists, [:following]) create_if_not_exists(index(:lists, [:following]))
end end
end end

View file

@ -3,6 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateApidHostExtractionIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["(split_part(actor, '/', 3))"], concurrently: true, name: :activities_hosts) create(
index(:activities, ["(split_part(actor, '/', 3))"],
concurrently: true,
name: :activities_hosts
)
)
end end
end end

View file

@ -3,8 +3,8 @@ defmodule Pleroma.Repo.Migrations.CreateUserInviteTokens do
def change do def change do
create_if_not_exists table(:user_invite_tokens) do create_if_not_exists table(:user_invite_tokens) do
add :token, :string add(:token, :string)
add :used, :boolean, default: false add(:used, :boolean, default: false)
timestamps() timestamps()
end end

View file

@ -3,6 +3,11 @@ defmodule Pleroma.Repo.Migrations.CreateActivitiesInReplyToIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["(data->'object'->>'inReplyTo')"], concurrently: true, name: :activities_in_reply_to) create(
index(:activities, ["(data->'object'->>'inReplyTo')"],
concurrently: true,
name: :activities_in_reply_to
)
)
end end
end end

View file

@ -3,18 +3,21 @@ defmodule Pleroma.Repo.Migrations.CreateFilters do
def change do def change do
create_if_not_exists table(:filters) do create_if_not_exists table(:filters) do
add :user_id, references(:users, on_delete: :delete_all) add(:user_id, references(:users, on_delete: :delete_all))
add :filter_id, :integer add(:filter_id, :integer)
add :hide, :boolean add(:hide, :boolean)
add :phrase, :string add(:phrase, :string)
add :context, {:array, :string} add(:context, {:array, :string})
add :expires_at, :utc_datetime add(:expires_at, :utc_datetime)
add :whole_word, :boolean add(:whole_word, :boolean)
timestamps() timestamps()
end end
create_if_not_exists index(:filters, [:user_id]) create_if_not_exists(index(:filters, [:user_id]))
create_if_not_exists index(:filters, [:phrase], where: "hide = true", name: :hided_phrases_index)
create_if_not_exists(
index(:filters, [:phrase], where: "hide = true", name: :hided_phrases_index)
)
end end
end end

View file

@ -3,11 +3,11 @@ defmodule Pleroma.Repo.Migrations.AddRecipientsToAndCcFieldsToActivities do
def change do def change do
alter table(:activities) do alter table(:activities) do
add :recipients_to, {:array, :string} add(:recipients_to, {:array, :string})
add :recipients_cc, {:array, :string} add(:recipients_cc, {:array, :string})
end end
create_if_not_exists index(:activities, [:recipients_to], using: :gin) create_if_not_exists(index(:activities, [:recipients_to], using: :gin))
create_if_not_exists index(:activities, [:recipients_cc], using: :gin) create_if_not_exists(index(:activities, [:recipients_cc], using: :gin))
end end
end end

View file

@ -2,7 +2,12 @@ defmodule Pleroma.Repo.Migrations.ActivitiesAddToCcIndices do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:activities, ["(data->'to')"], name: :activities_to_index, using: :gin) create_if_not_exists(
create_if_not_exists index(:activities, ["(data->'cc')"], name: :activities_cc_index, using: :gin) index(:activities, ["(data->'to')"], name: :activities_to_index, using: :gin)
)
create_if_not_exists(
index(:activities, ["(data->'cc')"], name: :activities_cc_index, using: :gin)
)
end end
end end

View file

@ -3,15 +3,15 @@ defmodule Pleroma.Repo.Migrations.RemoveRecipientsToAndCcFieldsFromActivities do
def up do def up do
alter table(:activities) do alter table(:activities) do
remove :recipients_to remove(:recipients_to)
remove :recipients_cc remove(:recipients_cc)
end end
end end
def down do def down do
alter table(:activities) do alter table(:activities) do
add :recipients_to, {:array, :string} add(:recipients_to, {:array, :string})
add :recipients_cc, {:array, :string} add(:recipients_cc, {:array, :string})
end end
end end
end end

View file

@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.UsersAddIsModeratorIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:users, ["(info->'is_moderator')"], name: :users_is_moderator_index, using: :gin) create_if_not_exists(
index(:users, ["(info->'is_moderator')"], name: :users_is_moderator_index, using: :gin)
)
end end
end end

View file

@ -3,16 +3,16 @@ defmodule Pleroma.Repo.Migrations.CreatePushSubscriptions do
def change do def change do
create_if_not_exists table("push_subscriptions") do create_if_not_exists table("push_subscriptions") do
add :user_id, references("users", on_delete: :delete_all) add(:user_id, references("users", on_delete: :delete_all))
add :token_id, references("oauth_tokens", on_delete: :delete_all) add(:token_id, references("oauth_tokens", on_delete: :delete_all))
add :endpoint, :string add(:endpoint, :string)
add :key_p256dh, :string add(:key_p256dh, :string)
add :key_auth, :string add(:key_auth, :string)
add :data, :map add(:data, :map)
timestamps() timestamps()
end end
create_if_not_exists index("push_subscriptions", [:user_id, :token_id], unique: true) create_if_not_exists(index("push_subscriptions", [:user_id, :token_id], unique: true))
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.UsersAddLastRefreshedAt do
def change do def change do
alter table(:users) do alter table(:users) do
add :last_refreshed_at, :naive_datetime_usec add(:last_refreshed_at, :naive_datetime_usec)
end end
end end
end end

View file

@ -3,9 +3,9 @@ defmodule Pleroma.Repo.Migrations.AddTagsToUsers do
def change do def change do
alter table(:users) do alter table(:users) do
add :tags, {:array, :string} add(:tags, {:array, :string})
end end
create_if_not_exists index(:users, [:tags], using: :gin) create_if_not_exists(index(:users, [:tags], using: :gin))
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddBookmarksToUsers do
def change do def change do
alter table(:users) do alter table(:users) do
add :bookmarks, {:array, :string}, null: false, default: [] add(:bookmarks, {:array, :string}, null: false, default: [])
end end
end end
end end

View file

@ -16,32 +16,34 @@ def up do
# Old serial int ids are transformed to 128bits with extra padding. # Old serial int ids are transformed to 128bits with extra padding.
# The application (in `Pleroma.FlakeId`) handles theses IDs properly as integers; to keep compatibility # The application (in `Pleroma.FlakeId`) handles theses IDs properly as integers; to keep compatibility
# with previously issued ids. # with previously issued ids.
#execute "update activities set external_id = CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid);" # execute "update activities set external_id = CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid);"
#execute "update users set external_id = CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid);" # execute "update users set external_id = CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid);"
clippy = start_clippy_heartbeats() clippy = start_clippy_heartbeats()
# Lock both tables to avoid a running server to meddling with our transaction # Lock both tables to avoid a running server to meddling with our transaction
execute "LOCK TABLE activities;" execute("LOCK TABLE activities;")
execute "LOCK TABLE users;" execute("LOCK TABLE users;")
execute """ execute("""
ALTER TABLE activities ALTER TABLE activities
DROP CONSTRAINT activities_pkey CASCADE, DROP CONSTRAINT activities_pkey CASCADE,
ALTER COLUMN id DROP default, ALTER COLUMN id DROP default,
ALTER COLUMN id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid), ALTER COLUMN id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid),
ADD PRIMARY KEY (id); ADD PRIMARY KEY (id);
""" """)
execute """ execute("""
ALTER TABLE users ALTER TABLE users
DROP CONSTRAINT users_pkey CASCADE, DROP CONSTRAINT users_pkey CASCADE,
ALTER COLUMN id DROP default, ALTER COLUMN id DROP default,
ALTER COLUMN id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid), ALTER COLUMN id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(id), 32, '0' ) AS uuid),
ADD PRIMARY KEY (id); ADD PRIMARY KEY (id);
""" """)
execute "UPDATE users SET info = jsonb_set(info, '{pinned_activities}', array_to_json(ARRAY(select jsonb_array_elements_text(info->'pinned_activities')))::jsonb);" execute(
"UPDATE users SET info = jsonb_set(info, '{pinned_activities}', array_to_json(ARRAY(select jsonb_array_elements_text(info->'pinned_activities')))::jsonb);"
)
# Fkeys: # Fkeys:
# Activities - Referenced by: # Activities - Referenced by:
@ -56,18 +58,19 @@ def up do
# TABLE "push_subscriptions" CONSTRAINT "push_subscriptions_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE # TABLE "push_subscriptions" CONSTRAINT "push_subscriptions_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
# TABLE "websub_client_subscriptions" CONSTRAINT "websub_client_subscriptions_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) # TABLE "websub_client_subscriptions" CONSTRAINT "websub_client_subscriptions_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
execute """ execute("""
ALTER TABLE notifications ALTER TABLE notifications
ALTER COLUMN activity_id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(activity_id), 32, '0' ) AS uuid), ALTER COLUMN activity_id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(activity_id), 32, '0' ) AS uuid),
ADD CONSTRAINT notifications_activity_id_fkey FOREIGN KEY (activity_id) REFERENCES activities(id) ON DELETE CASCADE; ADD CONSTRAINT notifications_activity_id_fkey FOREIGN KEY (activity_id) REFERENCES activities(id) ON DELETE CASCADE;
""" """)
for table <- ~w(notifications filters lists oauth_authorizations oauth_tokens password_reset_tokens push_subscriptions websub_client_subscriptions) do for table <-
execute """ ~w(notifications filters lists oauth_authorizations oauth_tokens password_reset_tokens push_subscriptions websub_client_subscriptions) do
execute("""
ALTER TABLE #{table} ALTER TABLE #{table}
ALTER COLUMN user_id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(user_id), 32, '0' ) AS uuid), ALTER COLUMN user_id SET DATA TYPE uuid USING CAST( LPAD( TO_HEX(user_id), 32, '0' ) AS uuid),
ADD CONSTRAINT #{table}_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ADD CONSTRAINT #{table}_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
""" """)
end end
flush() flush()
@ -78,41 +81,50 @@ def up do
def down, do: :ok def down, do: :ok
defp start_clippy_heartbeats() do defp start_clippy_heartbeats() do
count = from(a in "activities", select: count(a.id)) |> Repo.one! count = from(a in "activities", select: count(a.id)) |> Repo.one!()
if count > 5000 do if count > 5000 do
heartbeat_interval = :timer.minutes(2) + :timer.seconds(30) heartbeat_interval = :timer.minutes(2) + :timer.seconds(30)
all_tips = Clippy.tips() ++ [
all_tips =
Clippy.tips() ++
[
"The migration is still running, maybe it's time for another “tea”?", "The migration is still running, maybe it's time for another “tea”?",
"Happy rabbits practice a cute behavior known as a\n“binky:” they jump up in the air\nand twist\nand spin around!", "Happy rabbits practice a cute behavior known as a\n“binky:” they jump up in the air\nand twist\nand spin around!",
"Nothing and everything.\n\nI still work.", "Nothing and everything.\n\nI still work.",
"Pleroma runs on a Raspberry Pi!\n\n … but this migration will take forever if you\nactually run on a raspberry pi", "Pleroma runs on a Raspberry Pi!\n\n … but this migration will take forever if you\nactually run on a raspberry pi",
"Status? Stati? Post? Note? Toot?\nRepeat? Reboost? Boost? Retweet? Retoot??\n\nI-I'm confused.", "Status? Stati? Post? Note? Toot?\nRepeat? Reboost? Boost? Retweet? Retoot??\n\nI-I'm confused."
] ]
heartbeat = fn(heartbeat, runs, all_tips, tips) -> heartbeat = fn heartbeat, runs, all_tips, tips ->
tips = if Integer.is_even(runs) do tips =
if Integer.is_even(runs) do
tips = if tips == [], do: all_tips, else: tips tips = if tips == [], do: all_tips, else: tips
[tip | tips] = Enum.shuffle(tips) [tip | tips] = Enum.shuffle(tips)
Clippy.puts(tip) Clippy.puts(tip)
tips tips
else else
IO.puts "\n -- #{DateTime.to_string(DateTime.utc_now())} Migration still running, please wait…\n" IO.puts(
"\n -- #{DateTime.to_string(DateTime.utc_now())} Migration still running, please wait…\n"
)
tips tips
end end
:timer.sleep(heartbeat_interval) :timer.sleep(heartbeat_interval)
heartbeat.(heartbeat, runs + 1, all_tips, tips) heartbeat.(heartbeat, runs + 1, all_tips, tips)
end end
Clippy.puts [ Clippy.puts([
[:red, :bright, "It looks like you are running an older instance!"], [:red, :bright, "It looks like you are running an older instance!"],
[""], [""],
[:bright, "This migration may take a long time", :reset, " -- so you probably should"], [:bright, "This migration may take a long time", :reset, " -- so you probably should"],
["go drink a cofe, or a tea, or a beer, a whiskey, a vodka,"], ["go drink a cofe, or a tea, or a beer, a whiskey, a vodka,"],
["while it runs to deal with your temporary fediverse pause!"] ["while it runs to deal with your temporary fediverse pause!"]
] ])
:timer.sleep(heartbeat_interval) :timer.sleep(heartbeat_interval)
spawn_link(fn() -> heartbeat.(heartbeat, 1, all_tips, []) end) spawn_link(fn -> heartbeat.(heartbeat, 1, all_tips, []) end)
end end
end end
@ -120,8 +132,7 @@ defp stop_clippy_heartbeats(pid) do
if pid do if pid do
Process.unlink(pid) Process.unlink(pid)
Process.exit(pid, :kill) Process.exit(pid, :kill)
Clippy.puts [[:green, :bright, "Hurray!!", "", "", "Migration completed!"]] Clippy.puts([[:green, :bright, "Hurray!!", "", "", "Migration completed!"]])
end end
end end
end end

View file

@ -43,6 +43,8 @@ def down do
) )
) )
execute("drop function if exists activity_visibility(actor varchar, recipients varchar[], data jsonb)") execute(
"drop function if exists activity_visibility(actor varchar, recipients varchar[], data jsonb)"
)
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Pleroma.Repo.Migrations.CreateUserFtsIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index( create_if_not_exists(
index(
:users, :users,
[ [
""" """
@ -13,5 +14,6 @@ def change do
name: :users_fts_index, name: :users_fts_index,
using: :gin using: :gin
) )
)
end end
end end

View file

@ -27,10 +27,8 @@ def up do
""" """
execute(definition) execute(definition)
end end
def down do def down do
end end
end end

View file

@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.UsersAddIsAdminIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists(index(:users, ["(info->'is_admin')"], name: :users_is_admin_index, using: :gin)) create_if_not_exists(
index(:users, ["(info->'is_admin')"], name: :users_is_admin_index, using: :gin)
)
end end
end end

View file

@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.CreateInstances do
def change do def change do
create_if_not_exists table(:instances) do create_if_not_exists table(:instances) do
add :host, :string add(:host, :string)
add :unreachable_since, :naive_datetime_usec add(:unreachable_since, :naive_datetime_usec)
timestamps() timestamps()
end end
create_if_not_exists unique_index(:instances, [:host]) create_if_not_exists(unique_index(:instances, [:host]))
create_if_not_exists index(:instances, [:unreachable_since]) create_if_not_exists(index(:instances, [:unreachable_since]))
end end
end end

View file

@ -27,11 +27,8 @@ def up do
""" """
execute(definition) execute(definition)
end end
def down do def down do
end end
end end

View file

@ -3,6 +3,12 @@ defmodule Pleroma.Repo.Migrations.AddActivitiesLikesIndex do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:activities, ["((data #> '{\"object\",\"likes\"}'))"], concurrently: true, name: :activities_likes, using: :gin) create(
index(:activities, ["((data #> '{\"object\",\"likes\"}'))"],
concurrently: true,
name: :activities_likes,
using: :gin
)
)
end end
end end

View file

@ -2,9 +2,17 @@ defmodule Pleroma.Repo.Migrations.SplitHideNetwork do
use Ecto.Migration use Ecto.Migration
def up do def up do
execute("UPDATE users SET info = jsonb_set(info, '{hide_network}'::text[], 'false'::jsonb) WHERE NOT(info::jsonb ? 'hide_network') AND local") execute(
execute("UPDATE users SET info = jsonb_set(info, '{hide_followings}'::text[], info->'hide_network') WHERE local") "UPDATE users SET info = jsonb_set(info, '{hide_network}'::text[], 'false'::jsonb) WHERE NOT(info::jsonb ? 'hide_network') AND local"
execute("UPDATE users SET info = jsonb_set(info, '{hide_followers}'::text[], info->'hide_network') WHERE local") )
execute(
"UPDATE users SET info = jsonb_set(info, '{hide_followings}'::text[], info->'hide_network') WHERE local"
)
execute(
"UPDATE users SET info = jsonb_set(info, '{hide_followers}'::text[], info->'hide_network') WHERE local"
)
end end
def down do def down do

View file

@ -3,10 +3,10 @@ defmodule Pleroma.Repo.Migrations.CreateThreadMutes do
def change do def change do
create_if_not_exists table(:thread_mutes) do create_if_not_exists table(:thread_mutes) do
add :user_id, references(:users, type: :uuid, on_delete: :delete_all) add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
add :context, :string add(:context, :string)
end end
create_if_not_exists unique_index(:thread_mutes, [:user_id, :context], name: :unique_index) create_if_not_exists(unique_index(:thread_mutes, [:user_id, :context], name: :unique_index))
end end
end end

View file

@ -4,7 +4,7 @@ defmodule Pleroma.Repo.Migrations.AddScopeSToOAuthEntities do
def change do def change do
for t <- [:oauth_authorizations, :oauth_tokens] do for t <- [:oauth_authorizations, :oauth_tokens] do
alter table(t) do alter table(t) do
add :scopes, {:array, :string}, default: [], null: false add(:scopes, {:array, :string}, default: [], null: false)
end end
end end
end end

View file

@ -4,14 +4,20 @@ defmodule Pleroma.Repo.Migrations.ChangeAppsScopesToVarcharArray do
@alter_apps_scopes "ALTER TABLE apps ALTER COLUMN scopes" @alter_apps_scopes "ALTER TABLE apps ALTER COLUMN scopes"
def up do def up do
execute "#{@alter_apps_scopes} TYPE varchar(255)[] USING string_to_array(scopes, ',')::varchar(255)[];" execute(
execute "#{@alter_apps_scopes} SET DEFAULT ARRAY[]::character varying[];" "#{@alter_apps_scopes} TYPE varchar(255)[] USING string_to_array(scopes, ',')::varchar(255)[];"
execute "#{@alter_apps_scopes} SET NOT NULL;" )
execute("#{@alter_apps_scopes} SET DEFAULT ARRAY[]::character varying[];")
execute("#{@alter_apps_scopes} SET NOT NULL;")
end end
def down do def down do
execute "#{@alter_apps_scopes} DROP NOT NULL;" execute("#{@alter_apps_scopes} DROP NOT NULL;")
execute "#{@alter_apps_scopes} DROP DEFAULT;" execute("#{@alter_apps_scopes} DROP DEFAULT;")
execute "#{@alter_apps_scopes} TYPE varchar(255) USING array_to_string(scopes, ',')::varchar(255);"
execute(
"#{@alter_apps_scopes} TYPE varchar(255) USING array_to_string(scopes, ',')::varchar(255);"
)
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.DataMigrationPopulateOAuthScopes do
def up do def up do
for t <- [:oauth_authorizations, :oauth_tokens] do for t <- [:oauth_authorizations, :oauth_tokens] do
execute "UPDATE #{t} SET scopes = apps.scopes FROM apps WHERE #{t}.app_id = apps.id;" execute("UPDATE #{t} SET scopes = apps.scopes FROM apps WHERE #{t}.app_id = apps.id;")
end end
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.DataMigrationNormalizeScopes do
def up do def up do
for t <- [:apps, :oauth_authorizations, :oauth_tokens] do for t <- [:apps, :oauth_authorizations, :oauth_tokens] do
execute "UPDATE #{t} SET scopes = string_to_array(array_to_string(scopes, ' '), ' ');" execute("UPDATE #{t} SET scopes = string_to_array(array_to_string(scopes, ' '), ' ');")
end end
end end

View file

@ -2,7 +2,7 @@ defmodule Pleroma.Repo.Migrations.AddDefaultTagsToUser do
use Ecto.Migration use Ecto.Migration
def up do def up do
execute "UPDATE users SET tags = array[]::varchar[] where tags IS NULL" execute("UPDATE users SET tags = array[]::varchar[] where tags IS NULL")
end end
def down, do: :noop def down, do: :noop

View file

@ -4,7 +4,7 @@ defmodule Pleroma.Repo.Migrations.UpdateUserNoteCounters do
@public "https://www.w3.org/ns/activitystreams#Public" @public "https://www.w3.org/ns/activitystreams#Public"
def up do def up do
execute """ execute("""
WITH public_note_count AS ( WITH public_note_count AS (
SELECT SELECT
data->>'actor' AS actor, data->>'actor' AS actor,
@ -19,11 +19,11 @@ def up do
SET "info" = jsonb_set(u.info, '{note_count}', o.count::varchar::jsonb, true) SET "info" = jsonb_set(u.info, '{note_count}', o.count::varchar::jsonb, true)
FROM public_note_count AS o FROM public_note_count AS o
WHERE u.ap_id = o.actor WHERE u.ap_id = o.actor
""" """)
end end
def down do def down do
execute """ execute("""
WITH public_note_count AS ( WITH public_note_count AS (
SELECT SELECT
data->>'actor' AS actor, data->>'actor' AS actor,
@ -36,6 +36,6 @@ def down do
SET "info" = jsonb_set(u.info, '{note_count}', o.count::varchar::jsonb, true) SET "info" = jsonb_set(u.info, '{note_count}', o.count::varchar::jsonb, true)
FROM public_note_count AS o FROM public_note_count AS o
WHERE u.ap_id = o.actor WHERE u.ap_id = o.actor
""" """)
end end
end end

View file

@ -3,16 +3,16 @@ defmodule Pleroma.Repo.Migrations.CreateRegistrations do
def change do def change do
create_if_not_exists table(:registrations, primary_key: false) do create_if_not_exists table(:registrations, primary_key: false) do
add :id, :uuid, primary_key: true add(:id, :uuid, primary_key: true)
add :user_id, references(:users, type: :uuid, on_delete: :delete_all) add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
add :provider, :string add(:provider, :string)
add :uid, :string add(:uid, :string)
add :info, :map, default: %{} add(:info, :map, default: %{})
timestamps() timestamps()
end end
create_if_not_exists unique_index(:registrations, [:provider, :uid]) create_if_not_exists(unique_index(:registrations, [:provider, :uid]))
create_if_not_exists unique_index(:registrations, [:user_id, :provider, :uid]) create_if_not_exists(unique_index(:registrations, [:user_id, :provider, :uid]))
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.CreateNotificationIdIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:notifications, ["id desc nulls last"]) create_if_not_exists(index(:notifications, ["id desc nulls last"]))
end end
end end

View file

@ -3,6 +3,12 @@ defmodule Pleroma.Repo.Migrations.AddIndexOnSubscribers do
@disable_ddl_transaction true @disable_ddl_transaction true
def change do def change do
create index(:users, ["(info->'subscribers')"], name: :users_subscribers_index, using: :gin, concurrently: true) create(
index(:users, ["(info->'subscribers')"],
name: :users_subscribers_index,
using: :gin,
concurrently: true
)
)
end end
end end

View file

@ -19,8 +19,8 @@ def change do
timestamps() timestamps()
end end
create_if_not_exists index(:conversation_participations, [:conversation_id]) create_if_not_exists(index(:conversation_participations, [:conversation_id]))
create_if_not_exists unique_index(:conversation_participations, [:user_id, :conversation_id]) create_if_not_exists(unique_index(:conversation_participations, [:user_id, :conversation_id]))
create_if_not_exists unique_index(:conversations, [:ap_id]) create_if_not_exists(unique_index(:conversations, [:ap_id]))
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddParticipationUpdatedAtIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:conversation_participations, ["updated_at desc"]) create_if_not_exists(index(:conversation_participations, ["updated_at desc"]))
end end
end end

View file

@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.AddIndexOnUserInfoDeactivated do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists(index(:users, ["(info->'deactivated')"], name: :users_deactivated_index, using: :gin)) create_if_not_exists(
index(:users, ["(info->'deactivated')"], name: :users_deactivated_index, using: :gin)
)
end end
end end

View file

@ -29,7 +29,7 @@ def up do
def down do def down do
alter table(:users) do alter table(:users) do
add :bookmarks, {:array, :string}, null: false, default: [] add(:bookmarks, {:array, :string}, null: false, default: [])
end end
end end
end end

View file

@ -2,7 +2,18 @@ defmodule Pleroma.Repo.Migrations.AddFTSIndexToObjects do
use Ecto.Migration use Ecto.Migration
def change do def change do
drop_if_exists index(:activities, ["(to_tsvector('english', data->'object'->>'content'))"], using: :gin, name: :activities_fts) drop_if_exists(
create_if_not_exists index(:objects, ["(to_tsvector('english', data->>'content'))"], using: :gin, name: :objects_fts) index(:activities, ["(to_tsvector('english', data->'object'->>'content'))"],
using: :gin,
name: :activities_fts
)
)
create_if_not_exists(
index(:objects, ["(to_tsvector('english', data->>'content'))"],
using: :gin,
name: :objects_fts
)
)
end end
end end

View file

@ -2,18 +2,18 @@ defmodule Pleroma.Repo.Migrations.SetDefaultStateToReports do
use Ecto.Migration use Ecto.Migration
def up do def up do
execute """ execute("""
UPDATE activities AS a UPDATE activities AS a
SET data = jsonb_set(data, '{state}', '"open"', true) SET data = jsonb_set(data, '{state}', '"open"', true)
WHERE data->>'type' = 'Flag' WHERE data->>'type' = 'Flag'
""" """)
end end
def down do def down do
execute """ execute("""
UPDATE activities AS a UPDATE activities AS a
SET data = data #- '{state}' SET data = data #- '{state}'
WHERE data->>'type' = 'Flag' WHERE data->>'type' = 'Flag'
""" """)
end end
end end

View file

@ -3,13 +3,13 @@ defmodule Pleroma.Repo.Migrations.ChangeHideColumnInFilterTable do
def up do def up do
alter table(:filters) do alter table(:filters) do
modify :hide, :boolean, default: false modify(:hide, :boolean, default: false)
end end
end end
def down do def down do
alter table(:filters) do alter table(:filters) do
modify :hide, :boolean modify(:hide, :boolean)
end end
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddObjectInReplyToIndex do
use Ecto.Migration use Ecto.Migration
def change do def change do
create index(:objects, ["(data->>'inReplyTo')"], name: :objects_in_reply_to_index) create(index(:objects, ["(data->>'inReplyTo')"], name: :objects_in_reply_to_index))
end end
end end

View file

@ -2,7 +2,10 @@ defmodule Pleroma.Repo.Migrations.AddTagIndexToObjects do
use Ecto.Migration use Ecto.Migration
def change do def change do
drop_if_exists index(:activities, ["(data #> '{\"object\",\"tag\"}')"], using: :gin, name: :activities_tags) drop_if_exists(
create_if_not_exists index(:objects, ["(data->'tag')"], using: :gin, name: :objects_tags) index(:activities, ["(data #> '{\"object\",\"tag\"}')"], using: :gin, name: :activities_tags)
)
create_if_not_exists(index(:objects, ["(data->'tag')"], using: :gin, name: :objects_tags))
end end
end end

View file

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

View file

@ -7,7 +7,7 @@ def change do
add(:participation_id, references(:conversation_participations, on_delete: :delete_all)) add(:participation_id, references(:conversation_participations, on_delete: :delete_all))
end end
create_if_not_exists index(:conversation_participation_recipient_ships, [:user_id]) create_if_not_exists(index(:conversation_participation_recipient_ships, [:user_id]))
create_if_not_exists index(:conversation_participation_recipient_ships, [:participation_id]) create_if_not_exists(index(:conversation_participation_recipient_ships, [:participation_id]))
end end
end end

View file

@ -2,6 +2,6 @@ defmodule Pleroma.Repo.Migrations.AddLikesIndexToObjects do
use Ecto.Migration use Ecto.Migration
def change do def change do
create_if_not_exists index(:objects, ["(data->'likes')"], using: :gin, name: :objects_likes) create_if_not_exists(index(:objects, ["(data->'likes')"], using: :gin, name: :objects_likes))
end end
end end

View file

@ -6,7 +6,8 @@ def change do
add(:object_id, references(:objects, type: :id), null: false) add(:object_id, references(:objects, type: :id), null: false)
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all), null: false) add(:user_id, references(:users, type: :uuid, on_delete: :delete_all), null: false)
end end
create_if_not_exists index(:deliveries, :object_id, name: :deliveries_object_id)
create_if_not_exists(index(:deliveries, :object_id, name: :deliveries_object_id))
create_if_not_exists(unique_index(:deliveries, [:user_id, :object_id])) create_if_not_exists(unique_index(:deliveries, [:user_id, :object_id]))
end end
end end

View file

@ -2,7 +2,6 @@ defmodule Pleroma.Repo.Migrations.DropSubscriptionIfExists do
use Ecto.Migration use Ecto.Migration
def change do def change do
end end
def up do def up do
@ -10,6 +9,7 @@ def up do
drop_if_exists(index(:subscription_notifications, ["id desc nulls last"])) drop_if_exists(index(:subscription_notifications, ["id desc nulls last"]))
drop_if_exists(table(:subscription_notifications)) drop_if_exists(table(:subscription_notifications))
end end
def down do def down do
:ok :ok
end end

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.AddKeysColumn do
def change do def change do
alter table("users") do alter table("users") do
add_if_not_exists :keys, :text add_if_not_exists(:keys, :text)
end end
end end
end end

View file

@ -2,6 +2,9 @@ defmodule Pleroma.Repo.Migrations.MoveKeysToSeparateColumn do
use Ecto.Migration use Ecto.Migration
def change do def change do
execute("update users set keys = info->>'keys' where local", "update users set info = jsonb_set(info, '{keys}'::text[], to_jsonb(keys)) where local") execute(
"update users set keys = info->>'keys' where local",
"update users set info = jsonb_set(info, '{keys}'::text[], to_jsonb(keys)) where local"
)
end end
end end

View file

@ -45,21 +45,52 @@ detect_branch() {
} }
update() { update() {
set -e set -e
NO_RM=false
while echo "$1" | grep "^-" >/dev/null; do
case "$1" in
--zip-url)
FULL_URI="$2"
shift 2
;;
--no-rm)
NO_RM=true
shift
;;
--flavour)
FLAVOUR="$2"
shift 2
;;
--branch)
BRANCH="$2"
shift 2
;;
--tmp-dir)
TMP_DIR="$2"
shift 2
;;
-*)
echo "invalid option: $1" 1>&2
shift
;;
esac
done
RELEASE_ROOT=$(dirname "$SCRIPTPATH") RELEASE_ROOT=$(dirname "$SCRIPTPATH")
uri="${PLEROMA_CTL_URI:-https://git.pleroma.social}" uri="https://git.pleroma.social"
project_id="${PLEROMA_CTL_PROJECT_ID:-2}" project_id="2"
project_branch="$(detect_branch)" project_branch="${BRANCH:-$(detect_branch)}"
flavour="${PLEROMA_CTL_FLAVOUR:-$(detect_flavour)}" flavour="${FLAVOUR:-$(detect_flavour)}"
echo "Detected flavour: $flavour" tmp="${TMP_DIR:-/tmp}"
tmp="${PLEROMA_CTL_TMP_DIR:-/tmp}"
artifact="$tmp/pleroma.zip" artifact="$tmp/pleroma.zip"
full_uri="${uri}/api/v4/projects/${project_id}/jobs/artifacts/${project_branch}/download?job=${flavour}" full_uri="${FULL_URI:-${uri}/api/v4/projects/${project_id}/jobs/artifacts/${project_branch}/download?job=${flavour}}"
echo "Downloading the artifact from ${full_uri} to ${artifact}" echo "Downloading the artifact from ${full_uri} to ${artifact}"
curl "$full_uri" -o "${artifact}" curl "$full_uri" -o "${artifact}"
echo "Unpacking ${artifact} to ${tmp}" echo "Unpacking ${artifact} to ${tmp}"
unzip -q "$artifact" -d "$tmp" unzip -q "$artifact" -d "$tmp"
echo "Copying files over to $RELEASE_ROOT" echo "Copying files over to $RELEASE_ROOT"
if [ "$1" != "--no-rm" ]; then if [ "$NO_RM" = false ]; then
echo "Removing files from the previous release"
rm -r "${RELEASE_ROOT:-?}"/* rm -r "${RELEASE_ROOT:-?}"/*
fi fi
cp -rf "$tmp/release"/* "$RELEASE_ROOT" cp -rf "$tmp/release"/* "$RELEASE_ROOT"
@ -86,36 +117,41 @@ if [ -z "$1" ] || [ "$1" = "help" ]; then
Rollback database migrations (needs to be done before downgrading) Rollback database migrations (needs to be done before downgrading)
update [OPTIONS] update [OPTIONS]
Update the instance using the latest CI artifact for the current branch. Update the instance.
The only supported option is --no-rm, when set the script won't delete the whole directory, but
just force copy over files from the new release. This wastes more space, but may be useful if
some files are stored inside of the release directories (although you really shouldn't store them
there), or if you want to be able to quickly revert a broken update.
The script will try to detect your architecture and ABI and set a flavour automatically,
but if it is wrong, you can overwrite it by setting PLEROMA_CTL_FLAVOUR to the desired flavour.
By default the artifact will be downloaded from https://git.pleroma.social for pleroma/pleroma (project id: 2)
to /tmp/, you can overwrite these settings by setting PLEROMA_CTL_URI, PLEROMA_CTL_PROJECT_ID and PLEROMA_CTL_TMP_DIR
respectively.
Options:
--branch Update to a specified branch, instead of the latest version of the current one.
--flavour Update to a specified flavour (CPU architecture+libc), instead of the current one.
--zip-url Get the release from a specified url. If set, renders the previous 2 options inactive.
--no-rm Do not erase previous release's files.
--tmp-dir Download the temporary files to a specified directory.
and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is
equivalent to \`$(basename "$0") user COMMAND\` equivalent to \`$(basename "$0") user COMMAND\`
By default pleroma_ctl will try calling into a running instance to execute non migration-related commands, By default pleroma_ctl will try calling into a running instance to execute non migration-related commands,
if for some reason this is undesired, set PLEROMA_CTL_RPC_DISABLED environment variable if for some reason this is undesired, set PLEROMA_CTL_RPC_DISABLED environment variable.
" "
else else
SCRIPT=$(readlink -f "$0") SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") SCRIPTPATH=$(dirname "$SCRIPT")
if [ "$1" = "update" ]; then FULL_ARGS="$*"
update "$2"
elif [ "$1" = "migrate" ] || [ "$1" = "rollback" ] || [ "$1" = "create" ] || [ "$1 $2" = "instance gen" ] || [ -n "$PLEROMA_CTL_RPC_DISABLED" ]; then ACTION="$1"
"$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")' shift
if [ "$(echo \"$1\" | grep \"^-\" >/dev/null)" = false ]; then
SUBACTION="$1"
shift
fi
if [ "$ACTION" = "update" ]; then
update "$@"
elif [ "$ACTION" = "migrate" ] || [ "$ACTION" = "rollback" ] || [ "$ACTION" = "create" ] || [ "$ACTION $SUBACTION" = "instance gen" ] || [ "$PLEROMA_CTL_RPC_DISABLED" = true ]; then
"$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run("'"$FULL_ARGS"'")'
else else
"$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run("'"$*"'")' "$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run("'"$FULL_ARGS"'")'
fi fi
fi fi

View file

@ -126,9 +126,25 @@ test "when association is not loaded" do
} }
{:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "find me!"}) {:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "find me!"})
{:ok, japanese_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "更新情報"})
{:ok, job} = Pleroma.Web.Federator.incoming_ap_doc(params) {:ok, job} = Pleroma.Web.Federator.incoming_ap_doc(params)
{:ok, remote_activity} = ObanHelpers.perform(job) {:ok, remote_activity} = ObanHelpers.perform(job)
%{local_activity: local_activity, remote_activity: remote_activity, user: user}
%{
japanese_activity: japanese_activity,
local_activity: local_activity,
remote_activity: remote_activity,
user: user
}
end
test "finds utf8 text in statuses", %{
japanese_activity: japanese_activity,
user: user
} do
activities = Activity.search(user, "更新情報")
assert [^japanese_activity] = activities
end end
test "find local and remote statuses for authenticated users", %{ test "find local and remote statuses for authenticated users", %{

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" type="application/xrd+xml" template="https://mstdn.jp/.well-known/webfinger?resource={uri}"/>
</XRD>

Some files were not shown because too many files have changed in this diff Show more