diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/config/transfer_task_test.exs | 35 | ||||
| -rw-r--r-- | test/docs/generator_test.exs | 230 | ||||
| -rw-r--r-- | test/support/factory.ex | 10 | ||||
| -rw-r--r-- | test/tasks/config_test.exs | 232 | ||||
| -rw-r--r-- | test/tasks/instance_test.exs | 2 | ||||
| -rw-r--r-- | test/web/admin_api/admin_api_controller_test.exs | 525 | ||||
| -rw-r--r-- | test/web/admin_api/config_test.exs | 190 | 
7 files changed, 1010 insertions, 214 deletions
| diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs index 9074f3b97..b05191eab 100644 --- a/test/config/transfer_task_test.exs +++ b/test/config/transfer_task_test.exs @@ -5,47 +5,58 @@  defmodule Pleroma.Config.TransferTaskTest do    use Pleroma.DataCase -  clear_config([:instance, :dynamic_configuration]) do -    Pleroma.Config.put([:instance, :dynamic_configuration], true) +  alias Pleroma.Web.AdminAPI.Config + +  clear_config([:configurable_from_database]) do +    Pleroma.Config.put([:configurable_from_database], true)    end    test "transfer config values from db to env" do      refute Application.get_env(:pleroma, :test_key)      refute Application.get_env(:idna, :test_key) +    refute Application.get_env(:quack, :test_key) -    Pleroma.Web.AdminAPI.Config.create(%{ -      group: "pleroma", -      key: "test_key", +    Config.create(%{ +      group: ":pleroma", +      key: ":test_key",        value: [live: 2, com: 3]      }) -    Pleroma.Web.AdminAPI.Config.create(%{ -      group: "idna", -      key: "test_key", +    Config.create(%{ +      group: ":idna", +      key: ":test_key",        value: [live: 15, com: 35]      }) +    Config.create(%{ +      group: ":quack", +      key: ":test_key", +      value: [:test_value1, :test_value2] +    }) +      Pleroma.Config.TransferTask.start_link([])      assert Application.get_env(:pleroma, :test_key) == [live: 2, com: 3]      assert Application.get_env(:idna, :test_key) == [live: 15, com: 35] +    assert Application.get_env(:quack, :test_key) == [:test_value1, :test_value2]      on_exit(fn ->        Application.delete_env(:pleroma, :test_key)        Application.delete_env(:idna, :test_key) +      Application.delete_env(:quack, :test_key)      end)    end    test "non existing atom" do -    Pleroma.Web.AdminAPI.Config.create(%{ -      group: "pleroma", -      key: "undefined_atom_key", +    Config.create(%{ +      group: ":pleroma", +      key: ":undefined_atom_key",        value: [live: 2, com: 3]      })      assert ExUnit.CaptureLog.capture_log(fn ->               Pleroma.Config.TransferTask.start_link([])             end) =~ -             "updating env causes error, key: \"undefined_atom_key\", error: %ArgumentError{message: \"argument error\"}" +             "updating env causes error, key: \":undefined_atom_key\", error: %ArgumentError{message: \"argument error\"}"    end  end diff --git a/test/docs/generator_test.exs b/test/docs/generator_test.exs new file mode 100644 index 000000000..9c9f4357b --- /dev/null +++ b/test/docs/generator_test.exs @@ -0,0 +1,230 @@ +defmodule Pleroma.Docs.GeneratorTest do +  use ExUnit.Case, async: true +  alias Pleroma.Docs.Generator + +  @descriptions [ +    %{ +      group: :pleroma, +      key: Pleroma.Upload, +      type: :group, +      description: "", +      children: [ +        %{ +          key: :uploader, +          type: :module, +          description: "", +          suggestions: +            Generator.list_modules_in_dir( +              "lib/pleroma/upload/filter", +              "Elixir.Pleroma.Upload.Filter." +            ) +        }, +        %{ +          key: :filters, +          type: {:list, :module}, +          description: "", +          suggestions: +            Generator.list_modules_in_dir( +              "lib/pleroma/web/activity_pub/mrf", +              "Elixir.Pleroma.Web.ActivityPub.MRF." +            ) +        }, +        %{ +          key: Pleroma.Upload, +          type: :string, +          description: "", +          suggestions: [""] +        }, +        %{ +          key: :some_key, +          type: :keyword, +          description: "", +          suggestions: [], +          children: [ +            %{ +              key: :another_key, +              type: :integer, +              description: "", +              suggestions: [5] +            }, +            %{ +              key: :another_key_with_label, +              label: "Another label", +              type: :integer, +              description: "", +              suggestions: [7] +            } +          ] +        }, +        %{ +          key: :key1, +          type: :atom, +          description: "", +          suggestions: [ +            :atom, +            Pleroma.Upload, +            {:tuple, "string", 8080}, +            [:atom, Pleroma.Upload, {:atom, Pleroma.Upload}] +          ] +        }, +        %{ +          key: Pleroma.Upload, +          label: "Special Label", +          type: :string, +          description: "", +          suggestions: [""] +        }, +        %{ +          group: {:subgroup, Swoosh.Adapters.SMTP}, +          key: :auth, +          type: :atom, +          description: "`Swoosh.Adapters.SMTP` adapter specific setting", +          suggestions: [:always, :never, :if_available] +        }, +        %{ +          key: "application/xml", +          type: {:list, :string}, +          suggestions: ["xml"] +        }, +        %{ +          key: :versions, +          type: {:list, :atom}, +          description: "List of TLS version to use", +          suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2"] +        } +      ] +    }, +    %{ +      group: :tesla, +      key: :adapter, +      type: :group, +      description: "" +    }, +    %{ +      group: :cors_plug, +      type: :group, +      children: [%{key: :key1, type: :string, suggestions: [""]}] +    }, +    %{group: "Some string group", key: "Some string key", type: :group} +  ] + +  describe "convert_to_strings/1" do +    test "group, key, label" do +      [desc1, desc2 | _] = Generator.convert_to_strings(@descriptions) + +      assert desc1[:group] == ":pleroma" +      assert desc1[:key] == "Pleroma.Upload" +      assert desc1[:label] == "Pleroma.Upload" + +      assert desc2[:group] == ":tesla" +      assert desc2[:key] == ":adapter" +      assert desc2[:label] == "Adapter" +    end + +    test "group without key" do +      descriptions = Generator.convert_to_strings(@descriptions) +      desc = Enum.at(descriptions, 2) + +      assert desc[:group] == ":cors_plug" +      refute desc[:key] +      assert desc[:label] == "Cors plug" +    end + +    test "children key, label, type" do +      [%{children: [child1, child2, child3, child4 | _]} | _] = +        Generator.convert_to_strings(@descriptions) + +      assert child1[:key] == ":uploader" +      assert child1[:label] == "Uploader" +      assert child1[:type] == :module + +      assert child2[:key] == ":filters" +      assert child2[:label] == "Filters" +      assert child2[:type] == {:list, :module} + +      assert child3[:key] == "Pleroma.Upload" +      assert child3[:label] == "Pleroma.Upload" +      assert child3[:type] == :string + +      assert child4[:key] == ":some_key" +      assert child4[:label] == "Some key" +      assert child4[:type] == :keyword +    end + +    test "child with predefined label" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) +      child = Enum.at(children, 5) +      assert child[:key] == "Pleroma.Upload" +      assert child[:label] == "Special Label" +    end + +    test "subchild" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) +      child = Enum.at(children, 3) +      %{children: [subchild | _]} = child + +      assert subchild[:key] == ":another_key" +      assert subchild[:label] == "Another key" +      assert subchild[:type] == :integer +    end + +    test "subchild with predefined label" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) +      child = Enum.at(children, 3) +      %{children: subchildren} = child +      subchild = Enum.at(subchildren, 1) + +      assert subchild[:key] == ":another_key_with_label" +      assert subchild[:label] == "Another label" +    end + +    test "module suggestions" do +      [%{children: [%{suggestions: suggestions} | _]} | _] = +        Generator.convert_to_strings(@descriptions) + +      Enum.each(suggestions, fn suggestion -> +        assert String.starts_with?(suggestion, "Pleroma.") +      end) +    end + +    test "atoms in suggestions with leading `:`" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) +      %{suggestions: suggestions} = Enum.at(children, 4) +      assert Enum.at(suggestions, 0) == ":atom" +      assert Enum.at(suggestions, 1) == "Pleroma.Upload" +      assert Enum.at(suggestions, 2) == {":tuple", "string", 8080} +      assert Enum.at(suggestions, 3) == [":atom", "Pleroma.Upload", {":atom", "Pleroma.Upload"}] + +      %{suggestions: suggestions} = Enum.at(children, 6) +      assert Enum.at(suggestions, 0) == ":always" +      assert Enum.at(suggestions, 1) == ":never" +      assert Enum.at(suggestions, 2) == ":if_available" +    end + +    test "group, key as string in main desc" do +      descriptions = Generator.convert_to_strings(@descriptions) +      desc = Enum.at(descriptions, 3) +      assert desc[:group] == "Some string group" +      assert desc[:key] == "Some string key" +    end + +    test "key as string subchild" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) +      child = Enum.at(children, 7) +      assert child[:key] == "application/xml" +    end + +    test "suggestion for tls versions" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) +      child = Enum.at(children, 8) +      assert child[:suggestions] == [":tlsv1", ":tlsv1.1", ":tlsv1.2"] +    end + +    test "subgroup with module name" do +      [%{children: children} | _] = Generator.convert_to_strings(@descriptions) + +      %{group: subgroup} = Enum.at(children, 6) +      assert subgroup == {":subgroup", "Swoosh.Adapters.SMTP"} +    end +  end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index 100864055..9ff8004dd 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -395,8 +395,14 @@ defmodule Pleroma.Factory do    def config_factory do      %Pleroma.Web.AdminAPI.Config{ -      key: sequence(:key, &"some_key_#{&1}"), -      group: "pleroma", +      key: +        sequence(:key, fn key -> +          # Atom dynamic registration hack in tests +          "some_key_#{key}" +          |> String.to_atom() +          |> inspect() +        end), +      group: ":pleroma",        value:          sequence(            :value, diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs index fab9d6e9a..b967dfdde 100644 --- a/test/tasks/config_test.exs +++ b/test/tasks/config_test.exs @@ -9,138 +9,154 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do    setup_all do      Mix.shell(Mix.Shell.Process) -    temp_file = "config/temp.exported_from_db.secret.exs"      on_exit(fn ->        Mix.shell(Mix.Shell.IO)        Application.delete_env(:pleroma, :first_setting)        Application.delete_env(:pleroma, :second_setting) -      :ok = File.rm(temp_file)      end) -    {:ok, temp_file: temp_file} +    :ok    end -  clear_config_all([:instance, :dynamic_configuration]) do -    Pleroma.Config.put([:instance, :dynamic_configuration], true) +  clear_config_all([:configurable_from_database]) do +    Pleroma.Config.put([:configurable_from_database], true)    end    test "settings are migrated to db" do +    initial = Application.get_env(:quack, :level) +    on_exit(fn -> Application.put_env(:quack, :level, initial) end)      assert Repo.all(Config) == [] -    Application.put_env(:pleroma, :first_setting, key: "value", key2: [Pleroma.Repo]) -    Application.put_env(:pleroma, :second_setting, key: "value2", key2: [Pleroma.Activity]) +    Application.put_env(:pleroma, :first_setting, key: "value", key2: [Repo]) +    Application.put_env(:pleroma, :second_setting, key: "value2", key2: ["Activity"]) +    Application.put_env(:quack, :level, :info)      Mix.Tasks.Pleroma.Config.run(["migrate_to_db"]) -    first_db = Config.get_by_params(%{group: "pleroma", key: ":first_setting"}) -    second_db = Config.get_by_params(%{group: "pleroma", key: ":second_setting"}) -    refute Config.get_by_params(%{group: "pleroma", key: "Pleroma.Repo"}) +    config1 = Config.get_by_params(%{group: ":pleroma", key: ":first_setting"}) +    config2 = Config.get_by_params(%{group: ":pleroma", key: ":second_setting"}) +    config3 = Config.get_by_params(%{group: ":quack", key: ":level"}) +    refute Config.get_by_params(%{group: ":pleroma", key: "Pleroma.Repo"}) -    assert Config.from_binary(first_db.value) == [key: "value", key2: [Pleroma.Repo]] -    assert Config.from_binary(second_db.value) == [key: "value2", key2: [Pleroma.Activity]] +    assert Config.from_binary(config1.value) == [key: "value", key2: [Repo]] +    assert Config.from_binary(config2.value) == [key: "value2", key2: ["Activity"]] +    assert Config.from_binary(config3.value) == :info    end -  test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do -    Config.create(%{ -      group: "pleroma", -      key: ":setting_first", -      value: [key: "value", key2: [Pleroma.Activity]] -    }) - -    Config.create(%{ -      group: "pleroma", -      key: ":setting_second", -      value: [key: "valu2", key2: [Pleroma.Repo]] -    }) - -    Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "temp", "true"]) - -    assert Repo.all(Config) == [] -    assert File.exists?(temp_file) -    {:ok, file} = File.read(temp_file) - -    assert file =~ "config :pleroma, :setting_first," -    assert file =~ "config :pleroma, :setting_second," -  end - -  test "load a settings with large values and pass to file", %{temp_file: temp_file} do -    Config.create(%{ -      group: "pleroma", -      key: ":instance", -      value: [ -        name: "Pleroma", -        email: "example@example.com", -        notify_email: "noreply@example.com", -        description: "A Pleroma instance, an alternative fediverse server", -        limit: 5_000, -        chat_limit: 5_000, -        remote_limit: 100_000, -        upload_limit: 16_000_000, -        avatar_upload_limit: 2_000_000, -        background_upload_limit: 4_000_000, -        banner_upload_limit: 4_000_000, -        poll_limits: %{ -          max_options: 20, -          max_option_chars: 200, -          min_expiration: 0, -          max_expiration: 365 * 24 * 60 * 60 -        }, -        registrations_open: true, -        federating: true, -        federation_incoming_replies_max_depth: 100, -        federation_reachability_timeout_days: 7, -        federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher], -        allow_relay: true, -        rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy, -        public: true, -        quarantined_instances: [], -        managed_config: true, -        static_dir: "instance/static/", -        allowed_post_formats: ["text/plain", "text/html", "text/markdown", "text/bbcode"], -        mrf_transparency: true, -        mrf_transparency_exclusions: [], -        autofollowed_nicknames: [], -        max_pinned_statuses: 1, -        no_attachment_links: true, -        welcome_user_nickname: nil, -        welcome_message: nil, -        max_report_comment_size: 1000, -        safe_dm_mentions: false, -        healthcheck: false, -        remote_post_retention_days: 90, -        skip_thread_containment: true, -        limit_to_local_content: :unauthenticated, -        dynamic_configuration: false, -        user_bio_length: 5000, -        user_name_length: 100, -        max_account_fields: 10, -        max_remote_account_fields: 20, -        account_field_name_length: 512, -        account_field_value_length: 2048, -        external_user_synchronization: true, -        extended_nickname_format: true, -        multi_factor_authentication: [ -          totp: [ -            # digits 6 or 8 -            digits: 6, -            period: 30 -          ], -          backup_codes: [ -            number: 2, -            length: 6 +  describe "with deletion temp file" do +    setup do +      temp_file = "config/temp.exported_from_db.secret.exs" + +      on_exit(fn -> +        :ok = File.rm(temp_file) +      end) + +      {:ok, temp_file: temp_file} +    end + +    test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do +      Config.create(%{ +        group: ":pleroma", +        key: ":setting_first", +        value: [key: "value", key2: ["Activity"]] +      }) + +      Config.create(%{ +        group: ":pleroma", +        key: ":setting_second", +        value: [key: "value2", key2: [Repo]] +      }) + +      Config.create(%{group: ":quack", key: ":level", value: :info}) + +      Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"]) + +      assert Repo.all(Config) == [] + +      file = File.read!(temp_file) +      assert file =~ "config :pleroma, :setting_first," +      assert file =~ "config :pleroma, :setting_second," +      assert file =~ "config :quack, :level, :info" +    end + +    test "load a settings with large values and pass to file", %{temp_file: temp_file} do +      Config.create(%{ +        group: ":pleroma", +        key: ":instance", +        value: [ +          name: "Pleroma", +          email: "example@example.com", +          notify_email: "noreply@example.com", +          description: "A Pleroma instance, an alternative fediverse server", +          limit: 5_000, +          chat_limit: 5_000, +          remote_limit: 100_000, +          upload_limit: 16_000_000, +          avatar_upload_limit: 2_000_000, +          background_upload_limit: 4_000_000, +          banner_upload_limit: 4_000_000, +          poll_limits: %{ +            max_options: 20, +            max_option_chars: 200, +            min_expiration: 0, +            max_expiration: 365 * 24 * 60 * 60 +          }, +          registrations_open: true, +          federating: true, +          federation_incoming_replies_max_depth: 100, +          federation_reachability_timeout_days: 7, +          federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher], +          allow_relay: true, +          rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy, +          public: true, +          quarantined_instances: [], +          managed_config: true, +          static_dir: "instance/static/", +          allowed_post_formats: ["text/plain", "text/html", "text/markdown", "text/bbcode"], +          mrf_transparency: true, +          mrf_transparency_exclusions: [], +          autofollowed_nicknames: [], +          max_pinned_statuses: 1, +          no_attachment_links: true, +          welcome_user_nickname: nil, +          welcome_message: nil, +          max_report_comment_size: 1000, +          safe_dm_mentions: false, +          healthcheck: false, +          remote_post_retention_days: 90, +          skip_thread_containment: true, +          limit_to_local_content: :unauthenticated, +          user_bio_length: 5000, +          user_name_length: 100, +          max_account_fields: 10, +          max_remote_account_fields: 20, +          account_field_name_length: 512, +          account_field_value_length: 2048, +          external_user_synchronization: true, +          extended_nickname_format: true, +          multi_factor_authentication: [ +            totp: [ +              # digits 6 or 8 +              digits: 6, +              period: 30 +            ], +            backup_codes: [ +              number: 2, +              length: 6 +            ]            ]          ] -      ] -    }) +      }) -    Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "temp", "true"]) +      Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"]) -    assert Repo.all(Config) == [] -    assert File.exists?(temp_file) -    {:ok, file} = File.read(temp_file) +      assert Repo.all(Config) == [] +      assert File.exists?(temp_file) +      {:ok, file} = File.read(temp_file) -    assert file == -             "use Mix.Config\n\nconfig :pleroma, :instance,\n  name: \"Pleroma\",\n  email: \"example@example.com\",\n  notify_email: \"noreply@example.com\",\n  description: \"A Pleroma instance, an alternative fediverse server\",\n  limit: 5000,\n  chat_limit: 5000,\n  remote_limit: 100_000,\n  upload_limit: 16_000_000,\n  avatar_upload_limit: 2_000_000,\n  background_upload_limit: 4_000_000,\n  banner_upload_limit: 4_000_000,\n  poll_limits: %{\n    max_expiration: 31_536_000,\n    max_option_chars: 200,\n    max_options: 20,\n    min_expiration: 0\n  },\n  registrations_open: true,\n  federating: true,\n  federation_incoming_replies_max_depth: 100,\n  federation_reachability_timeout_days: 7,\n  federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n  allow_relay: true,\n  rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,\n  public: true,\n  quarantined_instances: [],\n  managed_config: true,\n  static_dir: \"instance/static/\",\n  allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n  mrf_transparency: true,\n  mrf_transparency_exclusions: [],\n  autofollowed_nicknames: [],\n  max_pinned_statuses: 1,\n  no_attachment_links: true,\n  welcome_user_nickname: nil,\n  welcome_message: nil,\n  max_report_comment_size: 1000,\n  safe_dm_mentions: false,\n  healthcheck: false,\n  remote_post_retention_days: 90,\n  skip_thread_containment: true,\n  limit_to_local_content: :unauthenticated,\n  dynamic_configuration: false,\n  user_bio_length: 5000,\n  user_name_length: 100,\n  max_account_fields: 10,\n  max_remote_account_fields: 20,\n  account_field_name_length: 512,\n  account_field_value_length: 2048,\n  external_user_synchronization: true,\n  extended_nickname_format: true,\n  multi_factor_authentication: [\n    totp: [digits: 6, period: 30],\n    backup_codes: [number: 2, length: 6]\n  ]\n" +      assert file == +               "use Mix.Config\n\nconfig :pleroma, :instance,\n  name: \"Pleroma\",\n  email: \"example@example.com\",\n  notify_email: \"noreply@example.com\",\n  description: \"A Pleroma instance, an alternative fediverse server\",\n  limit: 5000,\n  chat_limit: 5000,\n  remote_limit: 100_000,\n  upload_limit: 16_000_000,\n  avatar_upload_limit: 2_000_000,\n  background_upload_limit: 4_000_000,\n  banner_upload_limit: 4_000_000,\n  poll_limits: %{\n    max_expiration: 31_536_000,\n    max_option_chars: 200,\n    max_options: 20,\n    min_expiration: 0\n  },\n  registrations_open: true,\n  federating: true,\n  federation_incoming_replies_max_depth: 100,\n  federation_reachability_timeout_days: 7,\n  federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n  allow_relay: true,\n  rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,\n  public: true,\n  quarantined_instances: [],\n  managed_config: true,\n  static_dir: \"instance/static/\",\n  allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n  mrf_transparency: true,\n  mrf_transparency_exclusions: [],\n  autofollowed_nicknames: [],\n  max_pinned_statuses: 1,\n  no_attachment_links: true,\n  welcome_user_nickname: nil,\n  welcome_message: nil,\n  max_report_comment_size: 1000,\n  safe_dm_mentions: false,\n  healthcheck: false,\n  remote_post_retention_days: 90,\n  skip_thread_containment: true,\n  limit_to_local_content: :unauthenticated,\n  user_bio_length: 5000,\n  user_name_length: 100,\n  max_account_fields: 10,\n  max_remote_account_fields: 20,\n  account_field_name_length: 512,\n  account_field_value_length: 2048,\n  external_user_synchronization: true,\n  extended_nickname_format: true,\n  multi_factor_authentication: [\n    totp: [digits: 6, period: 30],\n    backup_codes: [number: 2, length: 6]\n  ]\n" +    end    end  end diff --git a/test/tasks/instance_test.exs b/test/tasks/instance_test.exs index 6d7eed4c1..d69275726 100644 --- a/test/tasks/instance_test.exs +++ b/test/tasks/instance_test.exs @@ -78,7 +78,7 @@ defmodule Pleroma.InstanceTest do      assert generated_config =~ "database: \"dbname\""      assert generated_config =~ "username: \"dbuser\""      assert generated_config =~ "password: \"dbpass\"" -    assert generated_config =~ "dynamic_configuration: true" +    assert generated_config =~ "configurable_from_database: true"      assert generated_config =~ "http: [ip: {127, 0, 0, 1}, port: 4000]"      assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql()    end diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index a3fbb6041..610fa5271 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -597,7 +597,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, :no_content) -      token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken)) +      token_record = List.last(Repo.all(Pleroma.UserInviteToken))        assert token_record        refute token_record.used @@ -1860,10 +1860,25 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    end    describe "GET /api/pleroma/admin/config" do +    clear_config([:configurable_from_database]) do +      Pleroma.Config.put([:configurable_from_database], true) +    end + +    test "when configuration from database is off", %{conn: conn} do +      initial = Pleroma.Config.get([:configurable_from_database]) +      Pleroma.Config.put([:configurable_from_database], false) +      on_exit(fn -> Pleroma.Config.put([:configurable_from_database], initial) end) +      conn = get(conn, "/api/pleroma/admin/config") + +      assert json_response(conn, 400) == +               "To use this endpoint you need to enable configuration from database." +    end +      test "without any settings in db", %{conn: conn} do        conn = get(conn, "/api/pleroma/admin/config") -      assert json_response(conn, 200) == %{"configs" => []} +      assert json_response(conn, 400) == +               "To use configuration from database migrate your settings to database."      end      test "with settings in db", %{conn: conn} do @@ -1875,6 +1890,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        %{          "configs" => [            %{ +            "group" => ":pleroma",              "key" => key1,              "value" => _            }, @@ -1890,9 +1906,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  test "POST /api/pleroma/admin/config error", %{conn: conn} do +    conn = post(conn, "/api/pleroma/admin/config", %{"configs" => []}) + +    assert json_response(conn, 400) == +             "To use this endpoint you need to enable configuration from database." +  end +    describe "POST /api/pleroma/admin/config" do      setup do -      temp_file = "config/test.exported_from_db.secret.exs" +      http = Application.get_env(:pleroma, :http)        on_exit(fn ->          Application.delete_env(:pleroma, :key1) @@ -1903,12 +1926,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          Application.delete_env(:pleroma, :keyaa2)          Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)          Application.delete_env(:pleroma, Pleroma.Captcha.NotReal) -        :ok = File.rm(temp_file) +        Application.put_env(:pleroma, :http, http) +        Application.put_env(:tesla, :adapter, Tesla.Mock) +        :ok = File.rm("config/test.exported_from_db.secret.exs")        end)      end -    clear_config([:instance, :dynamic_configuration]) do -      Pleroma.Config.put([:instance, :dynamic_configuration], true) +    clear_config([:configurable_from_database]) do +      Pleroma.Config.put([:configurable_from_database], true)      end      @tag capture_log: true @@ -1916,15 +1941,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [ -            %{group: "pleroma", key: "key1", value: "value1"}, +            %{group: ":pleroma", key: ":key1", value: "value1"},              %{ -              group: "ueberauth", +              group: ":ueberauth",                key: "Ueberauth.Strategy.Twitter.OAuth",                value: [%{"tuple" => [":consumer_secret", "aaaa"]}]              },              %{ -              group: "pleroma", -              key: "key2", +              group: ":pleroma", +              key: ":key2",                value: %{                  ":nested_1" => "nested_value1",                  ":nested_2" => [ @@ -1934,21 +1959,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                }              },              %{ -              group: "pleroma", -              key: "key3", +              group: ":pleroma", +              key: ":key3",                value: [                  %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},                  %{"nested_4" => true}                ]              },              %{ -              group: "pleroma", -              key: "key4", +              group: ":pleroma", +              key: ":key4",                value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}              },              %{ -              group: "idna", -              key: "key5", +              group: ":idna", +              key: ":key5",                value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}              }            ] @@ -1957,18 +1982,18 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", -                   "key" => "key1", +                   "group" => ":pleroma", +                   "key" => ":key1",                     "value" => "value1"                   },                   %{ -                   "group" => "ueberauth", +                   "group" => ":ueberauth",                     "key" => "Ueberauth.Strategy.Twitter.OAuth",                     "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]                   },                   %{ -                   "group" => "pleroma", -                   "key" => "key2", +                   "group" => ":pleroma", +                   "key" => ":key2",                     "value" => %{                       ":nested_1" => "nested_value1",                       ":nested_2" => [ @@ -1978,21 +2003,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     }                   },                   %{ -                   "group" => "pleroma", -                   "key" => "key3", +                   "group" => ":pleroma", +                   "key" => ":key3",                     "value" => [                       %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},                       %{"nested_4" => true}                     ]                   },                   %{ -                   "group" => "pleroma", -                   "key" => "key4", +                   "group" => ":pleroma", +                   "key" => ":key4",                     "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}                   },                   %{ -                   "group" => "idna", -                   "key" => "key5", +                   "group" => ":idna", +                   "key" => ":key5",                     "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}                   }                 ] @@ -2021,25 +2046,261 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}      end +    test "save config setting without key", %{conn: conn} do +      level = Application.get_env(:quack, :level) +      meta = Application.get_env(:quack, :meta) +      webhook_url = Application.get_env(:quack, :webhook_url) + +      on_exit(fn -> +        Application.put_env(:quack, :level, level) +        Application.put_env(:quack, :meta, meta) +        Application.put_env(:quack, :webhook_url, webhook_url) +      end) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{ +              group: ":quack", +              key: ":level", +              value: ":info" +            }, +            %{ +              group: ":quack", +              key: ":meta", +              value: [":none"] +            }, +            %{ +              group: ":quack", +              key: ":webhook_url", +              value: "https://hooks.slack.com/services/KEY" +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{"group" => ":quack", "key" => ":level", "value" => ":info"}, +                 %{"group" => ":quack", "key" => ":meta", "value" => [":none"]}, +                 %{ +                   "group" => ":quack", +                   "key" => ":webhook_url", +                   "value" => "https://hooks.slack.com/services/KEY" +                 } +               ] +             } + +      assert Application.get_env(:quack, :level) == :info +      assert Application.get_env(:quack, :meta) == [:none] +      assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY" +    end + +    test "saving config with partial update", %{conn: conn} do +      config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2)) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{group: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]} +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":key1", +                   "value" => [ +                     %{"tuple" => [":key1", 1]}, +                     %{"tuple" => [":key2", 2]}, +                     %{"tuple" => [":key3", 3]} +                   ] +                 } +               ] +             } +    end + +    test "saving config with nested merge", %{conn: conn} do +      config = +        insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2])) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{ +              group: config.group, +              key: config.key, +              value: [ +                %{"tuple" => [":key3", 3]}, +                %{ +                  "tuple" => [ +                    ":key2", +                    [ +                      %{"tuple" => [":k2", 1]}, +                      %{"tuple" => [":k3", 3]} +                    ] +                  ] +                } +              ] +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":key1", +                   "value" => [ +                     %{"tuple" => [":key1", 1]}, +                     %{"tuple" => [":key3", 3]}, +                     %{ +                       "tuple" => [ +                         ":key2", +                         [ +                           %{"tuple" => [":k1", 1]}, +                           %{"tuple" => [":k2", 1]}, +                           %{"tuple" => [":k3", 3]} +                         ] +                       ] +                     } +                   ] +                 } +               ] +             } +    end + +    test "saving special atoms", %{conn: conn} do +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          "configs" => [ +            %{ +              "group" => ":pleroma", +              "key" => ":key1", +              "value" => [ +                %{ +                  "tuple" => [ +                    ":ssl_options", +                    [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}] +                  ] +                } +              ] +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":key1", +                   "value" => [ +                     %{ +                       "tuple" => [ +                         ":ssl_options", +                         [%{"tuple" => [":versions", [":tlsv1", ":tlsv1.1", ":tlsv1.2"]]}] +                       ] +                     } +                   ] +                 } +               ] +             } + +      assert Application.get_env(:pleroma, :key1) == [ +               ssl_options: [versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]] +             ] +    end + +    test "saving full setting if value is in full_key_update list", %{conn: conn} do +      backends = Application.get_env(:logger, :backends) +      on_exit(fn -> Application.put_env(:logger, :backends, backends) end) + +      config = +        insert(:config, +          group: ":logger", +          key: ":backends", +          value: :erlang.term_to_binary([]) +        ) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{ +              group: config.group, +              key: config.key, +              value: [":console", %{"tuple" => ["ExSyslogger", ":ex_syslogger"]}] +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":logger", +                   "key" => ":backends", +                   "value" => [ +                     ":console", +                     %{"tuple" => ["ExSyslogger", ":ex_syslogger"]} +                   ] +                 } +               ] +             } + +      assert Application.get_env(:logger, :backends) == [ +               :console, +               {ExSyslogger, :ex_syslogger} +             ] + +      ExUnit.CaptureLog.capture_log(fn -> +        require Logger +        Logger.warn("Ooops...") +      end) =~ "Ooops..." +    end + +    test "saving full setting if value is not keyword", %{conn: conn} do +      config = +        insert(:config, +          group: ":tesla", +          key: ":adapter", +          value: :erlang.term_to_binary(Tesla.Adapter.Hackey) +        ) + +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{group: config.group, key: config.key, value: "Tesla.Adapter.Httpc"} +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":tesla", +                   "key" => ":adapter", +                   "value" => "Tesla.Adapter.Httpc" +                 } +               ] +             } +    end +      test "update config setting & delete", %{conn: conn} do -      config1 = insert(:config, key: "keyaa1") -      config2 = insert(:config, key: "keyaa2") +      config1 = insert(:config, key: ":keyaa1") +      config2 = insert(:config, key: ":keyaa2")        insert(:config,          group: "ueberauth", -        key: "Ueberauth.Strategy.Microsoft.OAuth", -        value: :erlang.term_to_binary([]) +        key: "Ueberauth.Strategy.Microsoft.OAuth"        )        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{group: config1.group, key: config1.key, value: "another_value"}, -            %{group: config2.group, key: config2.key, delete: "true"}, +            %{group: config2.group, key: config2.key, delete: true},              %{                group: "ueberauth",                key: "Ueberauth.Strategy.Microsoft.OAuth", -              delete: "true" +              delete: true              }            ]          }) @@ -2047,7 +2308,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", +                   "group" => ":pleroma",                     "key" => config1.key,                     "value" => "another_value"                   } @@ -2059,11 +2320,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "common config example", %{conn: conn} do +      adapter = Application.get_env(:tesla, :adapter) +      on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end) +        conn =          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => "Pleroma.Captcha.NotReal",                "value" => [                  %{"tuple" => [":enabled", false]}, @@ -2075,16 +2339,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                  %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},                  %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},                  %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]}, -                %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]} +                %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}, +                %{"tuple" => [":name", "Pleroma"]}                ] -            } +            }, +            %{"group" => ":tesla", "key" => ":adapter", "value" => "Tesla.Adapter.Httpc"}            ]          }) +      assert Application.get_env(:tesla, :adapter) == Tesla.Adapter.Httpc +      assert Pleroma.Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma" +        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", +                   "group" => ":pleroma",                     "key" => "Pleroma.Captcha.NotReal",                     "value" => [                       %{"tuple" => [":enabled", false]}, @@ -2096,9 +2365,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                       %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},                       %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},                       %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]}, -                     %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]} +                     %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}, +                     %{"tuple" => [":name", "Pleroma"]}                     ] -                 } +                 }, +                 %{"group" => ":tesla", "key" => ":adapter", "value" => "Tesla.Adapter.Httpc"}                 ]               }      end @@ -2108,7 +2379,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => "Pleroma.Web.Endpoint.NotReal",                "value" => [                  %{ @@ -2172,7 +2443,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", +                   "group" => ":pleroma",                     "key" => "Pleroma.Web.Endpoint.NotReal",                     "value" => [                       %{ @@ -2239,7 +2510,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => ":key1",                "value" => [                  %{"tuple" => [":key2", "some_val"]}, @@ -2269,7 +2540,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 %{                   "configs" => [                     %{ -                     "group" => "pleroma", +                     "group" => ":pleroma",                       "key" => ":key1",                       "value" => [                         %{"tuple" => [":key2", "some_val"]}, @@ -2301,7 +2572,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => ":key1",                "value" => %{"key" => "some_val"}              } @@ -2312,7 +2583,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 %{                   "configs" => [                     %{ -                     "group" => "pleroma", +                     "group" => ":pleroma",                       "key" => ":key1",                       "value" => %{"key" => "some_val"}                     } @@ -2325,7 +2596,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "pleroma", +              "group" => ":pleroma",                "key" => "Pleroma.Web.Endpoint.NotReal",                "value" => [                  %{ @@ -2358,7 +2629,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "pleroma", +                   "group" => ":pleroma",                     "key" => "Pleroma.Web.Endpoint.NotReal",                     "value" => [                       %{ @@ -2388,7 +2659,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          post(conn, "/api/pleroma/admin/config", %{            configs: [              %{ -              "group" => "oban", +              "group" => ":oban",                "key" => ":queues",                "value" => [                  %{"tuple" => [":federator_incoming", 50]}, @@ -2406,7 +2677,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert json_response(conn, 200) == %{                 "configs" => [                   %{ -                   "group" => "oban", +                   "group" => ":oban",                     "key" => ":queues",                     "value" => [                       %{"tuple" => [":federator_incoming", 50]}, @@ -2425,7 +2696,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      test "delete part of settings by atom subkeys", %{conn: conn} do        config =          insert(:config, -          key: "keyaa1", +          key: ":keyaa1",            value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")          ) @@ -2436,41 +2707,123 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                group: config.group,                key: config.key,                subkeys: [":subkey1", ":subkey3"], -              delete: "true" +              delete: true              }            ]          }) -      assert( -        json_response(conn, 200) == %{ -          "configs" => [ +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":keyaa1", +                   "value" => [%{"tuple" => [":subkey2", "val2"]}] +                 } +               ] +             } +    end + +    test "proxy tuple localhost", %{conn: conn} do +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [              %{ -              "group" => "pleroma", -              "key" => "keyaa1", -              "value" => [%{"tuple" => [":subkey2", "val2"]}] +              group: ":pleroma", +              key: ":http", +              value: [ +                %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}, +                %{"tuple" => [":send_user_agent", false]} +              ]              }            ] -        } -      ) +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":http", +                   "value" => [ +                     %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}, +                     %{"tuple" => [":send_user_agent", false]} +                   ] +                 } +               ] +             } +    end + +    test "proxy tuple domain", %{conn: conn} do +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{ +              group: ":pleroma", +              key: ":http", +              value: [ +                %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}, +                %{"tuple" => [":send_user_agent", false]} +              ] +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":http", +                   "value" => [ +                     %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}, +                     %{"tuple" => [":send_user_agent", false]} +                   ] +                 } +               ] +             } +    end + +    test "proxy tuple ip", %{conn: conn} do +      conn = +        post(conn, "/api/pleroma/admin/config", %{ +          configs: [ +            %{ +              group: ":pleroma", +              key: ":http", +              value: [ +                %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}, +                %{"tuple" => [":send_user_agent", false]} +              ] +            } +          ] +        }) + +      assert json_response(conn, 200) == %{ +               "configs" => [ +                 %{ +                   "group" => ":pleroma", +                   "key" => ":http", +                   "value" => [ +                     %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}, +                     %{"tuple" => [":send_user_agent", false]} +                   ] +                 } +               ] +             }      end    end    describe "config mix tasks run" do      setup do -      temp_file = "config/test.exported_from_db.secret.exs" -        Mix.shell(Mix.Shell.Quiet)        on_exit(fn ->          Mix.shell(Mix.Shell.IO) -        :ok = File.rm(temp_file)        end)        :ok      end -    clear_config([:instance, :dynamic_configuration]) do -      Pleroma.Config.put([:instance, :dynamic_configuration], true) +    clear_config([:configurable_from_database]) do +      Pleroma.Config.put([:configurable_from_database], true)      end      clear_config([:feed, :post_title]) do @@ -2478,15 +2831,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end      test "transfer settings to DB and to file", %{conn: conn} do -      assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == [] -      ret_conn = get(conn, "/api/pleroma/admin/config/migrate_to_db") -      assert json_response(ret_conn, 200) == %{} -      assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0 +      on_exit(fn -> :ok = File.rm("config/test.exported_from_db.secret.exs") end) +      assert Repo.all(Pleroma.Web.AdminAPI.Config) == [] +      Mix.Tasks.Pleroma.Config.run(["migrate_to_db"]) +      assert Repo.aggregate(Pleroma.Web.AdminAPI.Config, :count, :id) > 0 + +      conn = get(conn, "/api/pleroma/admin/config/migrate_from_db") + +      assert json_response(conn, 200) == %{} +      assert Repo.all(Pleroma.Web.AdminAPI.Config) == [] +    end + +    test "returns error if configuration from database is off", %{conn: conn} do +      initial = Pleroma.Config.get([:configurable_from_database]) +      on_exit(fn -> Pleroma.Config.put([:configurable_from_database], initial) end) +      Pleroma.Config.put([:configurable_from_database], false) + +      conn = get(conn, "/api/pleroma/admin/config/migrate_from_db") -      ret_conn = get(conn, "/api/pleroma/admin/config/migrate_from_db") +      assert json_response(conn, 400) == +               "To use this endpoint you need to enable configuration from database." -      assert json_response(ret_conn, 200) == %{} -      assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == [] +      assert Repo.all(Pleroma.Web.AdminAPI.Config) == []      end    end @@ -2955,6 +3321,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert ReportNote |> Repo.all() |> length() == 1      end    end + +  test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do +    admin = insert(:user, is_admin: true) + +    conn = +      assign(conn, :user, admin) +      |> get("/api/pleroma/admin/config/descriptions") + +    assert [child | _others] = json_response(conn, 200) + +    assert child["children"] +    assert child["key"] +    assert String.starts_with?(child["group"], ":") +    assert child["description"] +  end  end  # Needed for testing diff --git a/test/web/admin_api/config_test.exs b/test/web/admin_api/config_test.exs index 204446b79..2c0601b56 100644 --- a/test/web/admin_api/config_test.exs +++ b/test/web/admin_api/config_test.exs @@ -26,26 +26,112 @@ defmodule Pleroma.Web.AdminAPI.ConfigTest do      assert loaded == updated    end -  test "update_or_create/1" do -    config = insert(:config) -    key2 = "another_key" +  describe "update_or_create/1" do +    test "common" do +      config = insert(:config) +      key2 = "another_key" + +      params = [ +        %{group: "pleroma", key: key2, value: "another_value"}, +        %{group: config.group, key: config.key, value: "new_value"} +      ] + +      assert Repo.all(Config) |> length() == 1 + +      Enum.each(params, &Config.update_or_create(&1)) -    params = [ -      %{group: "pleroma", key: key2, value: "another_value"}, -      %{group: config.group, key: config.key, value: "new_value"} -    ] +      assert Repo.all(Config) |> length() == 2 -    assert Repo.all(Config) |> length() == 1 +      config1 = Config.get_by_params(%{group: config.group, key: config.key}) +      config2 = Config.get_by_params(%{group: "pleroma", key: key2}) -    Enum.each(params, &Config.update_or_create(&1)) +      assert config1.value == Config.transform("new_value") +      assert config2.value == Config.transform("another_value") +    end + +    test "partial update" do +      config = insert(:config, value: Config.to_binary(key1: "val1", key2: :val2)) -    assert Repo.all(Config) |> length() == 2 +      {:ok, _config} = +        Config.update_or_create(%{ +          group: config.group, +          key: config.key, +          value: [key1: :val1, key3: :val3] +        }) -    config1 = Config.get_by_params(%{group: config.group, key: config.key}) -    config2 = Config.get_by_params(%{group: "pleroma", key: key2}) +      updated = Config.get_by_params(%{group: config.group, key: config.key}) -    assert config1.value == Config.transform("new_value") -    assert config2.value == Config.transform("another_value") +      value = Config.from_binary(updated.value) +      assert length(value) == 3 +      assert value[:key1] == :val1 +      assert value[:key2] == :val2 +      assert value[:key3] == :val3 +    end + +    test "deep merge" do +      config = insert(:config, value: Config.to_binary(key1: "val1", key2: [k1: :v1, k2: "v2"])) + +      {:ok, config} = +        Config.update_or_create(%{ +          group: config.group, +          key: config.key, +          value: [key1: :val1, key2: [k2: :v2, k3: :v3], key3: :val3] +        }) + +      updated = Config.get_by_params(%{group: config.group, key: config.key}) + +      assert config.value == updated.value + +      value = Config.from_binary(updated.value) +      assert value[:key1] == :val1 +      assert value[:key2] == [k1: :v1, k2: :v2, k3: :v3] +      assert value[:key3] == :val3 +    end + +    test "only full update for some keys" do +      config1 = insert(:config, key: ":ecto_repos", value: Config.to_binary(repo: Pleroma.Repo)) +      config2 = insert(:config, group: ":cors_plug", key: ":max_age", value: Config.to_binary(18)) + +      {:ok, _config} = +        Config.update_or_create(%{ +          group: config1.group, +          key: config1.key, +          value: [another_repo: [Pleroma.Repo]] +        }) + +      {:ok, _config} = +        Config.update_or_create(%{ +          group: config2.group, +          key: config2.key, +          value: 777 +        }) + +      updated1 = Config.get_by_params(%{group: config1.group, key: config1.key}) +      updated2 = Config.get_by_params(%{group: config2.group, key: config2.key}) + +      assert Config.from_binary(updated1.value) == [another_repo: [Pleroma.Repo]] +      assert Config.from_binary(updated2.value) == 777 +    end + +    test "full update if value is not keyword" do +      config = +        insert(:config, +          group: ":tesla", +          key: ":adapter", +          value: Config.to_binary(Tesla.Adapter.Hackney) +        ) + +      {:ok, _config} = +        Config.update_or_create(%{ +          group: config.group, +          key: config.key, +          value: Tesla.Adapter.Httpc +        }) + +      updated = Config.get_by_params(%{group: config.group, key: config.key}) + +      assert Config.from_binary(updated.value) == Tesla.Adapter.Httpc +    end    end    test "delete/1" do @@ -85,20 +171,50 @@ defmodule Pleroma.Web.AdminAPI.ConfigTest do        assert Config.from_binary(binary) == :atom      end +    test "ssl options" do +      binary = Config.transform([":tlsv1", ":tlsv1.1", ":tlsv1.2"]) +      assert binary == :erlang.term_to_binary([:tlsv1, :"tlsv1.1", :"tlsv1.2"]) +      assert Config.from_binary(binary) == [:tlsv1, :"tlsv1.1", :"tlsv1.2"] +    end +      test "pleroma module" do        binary = Config.transform("Pleroma.Bookmark")        assert binary == :erlang.term_to_binary(Pleroma.Bookmark)        assert Config.from_binary(binary) == Pleroma.Bookmark      end +    test "pleroma string" do +      binary = Config.transform("Pleroma") +      assert binary == :erlang.term_to_binary("Pleroma") +      assert Config.from_binary(binary) == "Pleroma" +    end +      test "phoenix module" do        binary = Config.transform("Phoenix.Socket.V1.JSONSerializer")        assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer)        assert Config.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer      end +    test "tesla module" do +      binary = Config.transform("Tesla.Adapter.Hackney") +      assert binary == :erlang.term_to_binary(Tesla.Adapter.Hackney) +      assert Config.from_binary(binary) == Tesla.Adapter.Hackney +    end + +    test "ExSyslogger module" do +      binary = Config.transform("ExSyslogger") +      assert binary == :erlang.term_to_binary(ExSyslogger) +      assert Config.from_binary(binary) == ExSyslogger +    end + +    test "Quack.Logger module" do +      binary = Config.transform("Quack.Logger") +      assert binary == :erlang.term_to_binary(Quack.Logger) +      assert Config.from_binary(binary) == Quack.Logger +    end +      test "sigil" do -      binary = Config.transform("~r/comp[lL][aA][iI][nN]er/") +      binary = Config.transform("~r[comp[lL][aA][iI][nN]er]")        assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/)        assert Config.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/      end @@ -109,10 +225,10 @@ defmodule Pleroma.Web.AdminAPI.ConfigTest do        assert Config.from_binary(binary) == ~r/https:\/\/example.com/      end -    test "link sigil with u modifier" do -      binary = Config.transform("~r/https:\/\/example.com/u") -      assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/u) -      assert Config.from_binary(binary) == ~r/https:\/\/example.com/u +    test "link sigil with um modifiers" do +      binary = Config.transform("~r/https:\/\/example.com/um") +      assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/um) +      assert Config.from_binary(binary) == ~r/https:\/\/example.com/um      end      test "link sigil with i modifier" do @@ -127,12 +243,48 @@ defmodule Pleroma.Web.AdminAPI.ConfigTest do        assert Config.from_binary(binary) == ~r/https:\/\/example.com/s      end +    test "raise if valid delimiter not found" do +      assert_raise ArgumentError, "valid delimiter for Regex expression not found", fn -> +        Config.transform("~r/https://[]{}<>\"'()|example.com/s") +      end +    end +      test "2 child tuple" do        binary = Config.transform(%{"tuple" => ["v1", ":v2"]})        assert binary == :erlang.term_to_binary({"v1", :v2})        assert Config.from_binary(binary) == {"v1", :v2}      end +    test "proxy tuple with localhost" do +      binary = +        Config.transform(%{ +          "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}] +        }) + +      assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, :localhost, 1234}}) +      assert Config.from_binary(binary) == {:proxy_url, {:socks5, :localhost, 1234}} +    end + +    test "proxy tuple with domain" do +      binary = +        Config.transform(%{ +          "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}] +        }) + +      assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, 'domain.com', 1234}}) +      assert Config.from_binary(binary) == {:proxy_url, {:socks5, 'domain.com', 1234}} +    end + +    test "proxy tuple with ip" do +      binary = +        Config.transform(%{ +          "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}] +        }) + +      assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}}) +      assert Config.from_binary(binary) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}} +    end +      test "tuple with n childs" do        binary =          Config.transform(%{ | 
