diff options
Diffstat (limited to 'test/web/pleroma_api/controllers')
6 files changed, 1015 insertions, 397 deletions
| diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs index d17026a6b..103997c31 100644 --- a/test/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/web/pleroma_api/controllers/account_controller_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do @@ -27,14 +27,32 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        [user: user]      end -    clear_config([:instance, :account_activation_required]) do -      Config.put([:instance, :account_activation_required], true) -    end +    setup do: clear_config([:instance, :account_activation_required], true)      test "resend account confirmation email", %{conn: conn, user: user} do        conn +      |> put_req_header("content-type", "application/json")        |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}") -      |> json_response(:no_content) +      |> json_response_and_validate_schema(:no_content) + +      ObanHelpers.perform_all() + +      email = Pleroma.Emails.UserEmail.account_confirmation_email(user) +      notify_email = Config.get([:instance, :notify_email]) +      instance_name = Config.get([:instance, :name]) + +      assert_email_sent( +        from: {instance_name, notify_email}, +        to: {user.name, user.email}, +        html_body: email.html_body +      ) +    end + +    test "resend account confirmation email (with nickname)", %{conn: conn, user: user} do +      conn +      |> put_req_header("content-type", "application/json") +      |> post("/api/v1/pleroma/accounts/confirmation_resend?nickname=#{user.nickname}") +      |> json_response_and_validate_schema(:no_content)        ObanHelpers.perform_all() @@ -56,7 +74,10 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      test "user avatar can be set", %{user: user, conn: conn} do        avatar_image = File.read!("test/fixtures/avatar_data_uri") -      conn = patch(conn, "/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image}) +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})        user = refresh_record(user) @@ -72,17 +93,20 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do                 ]               } = user.avatar -      assert %{"url" => _} = json_response(conn, 200) +      assert %{"url" => _} = json_response_and_validate_schema(conn, 200)      end      test "user avatar can be reset", %{user: user, conn: conn} do -      conn = patch(conn, "/api/v1/pleroma/accounts/update_avatar", %{img: ""}) +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})        user = User.get_cached_by_id(user.id)        assert user.avatar == nil -      assert %{"url" => nil} = json_response(conn, 200) +      assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)      end    end @@ -90,21 +114,27 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      setup do: oauth_access(["write:accounts"])      test "can set profile banner", %{user: user, conn: conn} do -      conn = patch(conn, "/api/v1/pleroma/accounts/update_banner", %{"banner" => @image}) +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})        user = refresh_record(user)        assert user.banner["type"] == "Image" -      assert %{"url" => _} = json_response(conn, 200) +      assert %{"url" => _} = json_response_and_validate_schema(conn, 200)      end      test "can reset profile banner", %{user: user, conn: conn} do -      conn = patch(conn, "/api/v1/pleroma/accounts/update_banner", %{"banner" => ""}) +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})        user = refresh_record(user)        assert user.banner == %{} -      assert %{"url" => nil} = json_response(conn, 200) +      assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)      end    end @@ -112,19 +142,26 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      setup do: oauth_access(["write:accounts"])      test "background image can be set", %{user: user, conn: conn} do -      conn = patch(conn, "/api/v1/pleroma/accounts/update_background", %{"img" => @image}) +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})        user = refresh_record(user)        assert user.background["type"] == "Image" -      assert %{"url" => _} = json_response(conn, 200) +      # assert %{"url" => _} = json_response(conn, 200) +      assert %{"url" => _} = json_response_and_validate_schema(conn, 200)      end      test "background image can be reset", %{user: user, conn: conn} do -      conn = patch(conn, "/api/v1/pleroma/accounts/update_background", %{"img" => ""}) +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})        user = refresh_record(user)        assert user.background == %{} -      assert %{"url" => nil} = json_response(conn, 200) +      assert %{"url" => nil} = json_response_and_validate_schema(conn, 200)      end    end @@ -140,12 +177,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        user: user      } do        [activity | _] = insert_pair(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        response =          conn          |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") -        |> json_response(:ok) +        |> json_response_and_validate_schema(:ok)        [like] = response @@ -153,15 +190,18 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        assert like["id"] == activity.id      end -    test "does not return favorites for specified user_id when user is not logged in", %{ +    test "returns favorites for specified user_id when requester is not logged in", %{        user: user      } do        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id) -      build_conn() -      |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") -      |> json_response(403) +      response = +        build_conn() +        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") +        |> json_response_and_validate_schema(200) + +      assert length(response) == 1      end      test "returns favorited DM only when user is logged in and he is one of recipients", %{ @@ -170,11 +210,11 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      } do        {:ok, direct} =          CommonAPI.post(current_user, %{ -          "status" => "Hi @#{user.nickname}!", -          "visibility" => "direct" +          status: "Hi @#{user.nickname}!", +          visibility: "direct"          }) -      CommonAPI.favorite(direct.id, user) +      CommonAPI.favorite(user, direct.id)        for u <- [user, current_user] do          response = @@ -182,14 +222,17 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do            |> assign(:user, u)            |> assign(:token, insert(:oauth_token, user: u, scopes: ["read:favourites"]))            |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") -          |> json_response(:ok) +          |> json_response_and_validate_schema(:ok)          assert length(response) == 1        end -      build_conn() -      |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") -      |> json_response(403) +      response = +        build_conn() +        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") +        |> json_response_and_validate_schema(200) + +      assert length(response) == 0      end      test "does not return others' favorited DM when user is not one of recipients", %{ @@ -200,16 +243,16 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        {:ok, direct} =          CommonAPI.post(user_two, %{ -          "status" => "Hi @#{user.nickname}!", -          "visibility" => "direct" +          status: "Hi @#{user.nickname}!", +          visibility: "direct"          }) -      CommonAPI.favorite(direct.id, user) +      CommonAPI.favorite(user, direct.id)        response =          conn          |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") -        |> json_response(:ok) +        |> json_response_and_validate_schema(:ok)        assert Enum.empty?(response)      end @@ -221,7 +264,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        activities = insert_list(10, :note_activity)        Enum.each(activities, fn activity -> -        CommonAPI.favorite(activity.id, user) +        CommonAPI.favorite(user, activity.id)        end)        third_activity = Enum.at(activities, 2) @@ -229,11 +272,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        response =          conn -        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{ -          since_id: third_activity.id, -          max_id: seventh_activity.id -        }) -        |> json_response(:ok) +        |> get( +          "/api/v1/pleroma/accounts/#{user.id}/favourites?since_id=#{third_activity.id}&max_id=#{ +            seventh_activity.id +          }" +        ) +        |> json_response_and_validate_schema(:ok)        assert length(response) == 3        refute third_activity in response @@ -247,13 +291,13 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        7        |> insert_list(:note_activity)        |> Enum.each(fn activity -> -        CommonAPI.favorite(activity.id, user) +        CommonAPI.favorite(user, activity.id)        end)        response =          conn -        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"}) -        |> json_response(:ok) +        |> get("/api/v1/pleroma/accounts/#{user.id}/favourites?limit=3") +        |> json_response_and_validate_schema(:ok)        assert length(response) == 3      end @@ -265,7 +309,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        response =          conn          |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") -        |> json_response(:ok) +        |> json_response_and_validate_schema(:ok)        assert Enum.empty?(response)      end @@ -273,28 +317,28 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do      test "returns 404 error when specified user is not exist", %{conn: conn} do        conn = get(conn, "/api/v1/pleroma/accounts/test/favourites") -      assert json_response(conn, 404) == %{"error" => "Record not found"} +      assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}      end      test "returns 403 error when user has hidden own favorites", %{conn: conn} do        user = insert(:user, hide_favorites: true)        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") -      assert json_response(conn, 403) == %{"error" => "Can't get favorites"} +      assert json_response_and_validate_schema(conn, 403) == %{"error" => "Can't get favorites"}      end      test "hides favorites for new users by default", %{conn: conn} do        user = insert(:user)        activity = insert(:note_activity) -      CommonAPI.favorite(activity.id, user) +      CommonAPI.favorite(user, activity.id)        assert user.hide_favorites        conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") -      assert json_response(conn, 403) == %{"error" => "Can't get favorites"} +      assert json_response_and_validate_schema(conn, 403) == %{"error" => "Can't get favorites"}      end    end @@ -308,11 +352,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do          |> assign(:user, user)          |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe") -      assert %{"id" => _id, "subscribing" => true} = json_response(ret_conn, 200) +      assert %{"id" => _id, "subscribing" => true} = +               json_response_and_validate_schema(ret_conn, 200)        conn = post(conn, "/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe") -      assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200) +      assert %{"id" => _id, "subscribing" => false} = json_response_and_validate_schema(conn, 200)      end    end @@ -322,7 +367,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        conn = post(conn, "/api/v1/pleroma/accounts/target_id/subscribe") -      assert %{"error" => "Record not found"} = json_response(conn, 404) +      assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404)      end    end @@ -332,7 +377,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do        conn = post(conn, "/api/v1/pleroma/accounts/target_id/unsubscribe") -      assert %{"error" => "Record not found"} = json_response(conn, 404) +      assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404)      end    end  end diff --git a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs index 6f1ea78ec..d343256fe 100644 --- a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do @@ -8,216 +8,298 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do    import Tesla.Mock    import Pleroma.Factory -  @emoji_dir_path Path.join( -                    Pleroma.Config.get!([:instance, :static_dir]), -                    "emoji" -                  ) +  @emoji_path Path.join( +                Pleroma.Config.get!([:instance, :static_dir]), +                "emoji" +              ) +  setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) + +  setup do +    admin = insert(:user, is_admin: true) +    token = insert(:oauth_admin_token, user: admin) -  clear_config([:auth, :enforce_oauth_admin_scope_usage]) do -    Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], false) +    admin_conn = +      build_conn() +      |> assign(:user, admin) +      |> assign(:token, token) + +    Pleroma.Emoji.reload() +    {:ok, %{admin_conn: admin_conn}}    end -  test "shared & non-shared pack information in list_packs is ok" do -    conn = build_conn() -    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200) +  test "GET /api/pleroma/emoji/packs", %{conn: conn} do +    resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200) -    assert Map.has_key?(resp, "test_pack") +    shared = resp["test_pack"] +    assert shared["files"] == %{"blank" => "blank.png"} +    assert Map.has_key?(shared["pack"], "download-sha256") +    assert shared["pack"]["can-download"] +    assert shared["pack"]["share-files"] -    pack = resp["test_pack"] +    non_shared = resp["test_pack_nonshared"] +    assert non_shared["pack"]["share-files"] == false +    assert non_shared["pack"]["can-download"] == false +  end -    assert Map.has_key?(pack["pack"], "download-sha256") -    assert pack["pack"]["can-download"] +  describe "GET /api/pleroma/emoji/packs/remote" do +    test "shareable instance", %{admin_conn: admin_conn, conn: conn} do +      resp = +        conn +        |> get("/api/pleroma/emoji/packs") +        |> json_response(200) -    assert pack["files"] == %{"blank" => "blank.png"} +      mock(fn +        %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> +          json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) -    # Non-shared pack +        %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> +          json(%{metadata: %{features: ["shareable_emoji_packs"]}}) -    assert Map.has_key?(resp, "test_pack_nonshared") +        %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} -> +          json(resp) +      end) -    pack = resp["test_pack_nonshared"] +      assert admin_conn +             |> get("/api/pleroma/emoji/packs/remote", %{ +               url: "https://example.com" +             }) +             |> json_response(200) == resp +    end -    refute pack["pack"]["shared"] -    refute pack["pack"]["can-download"] -  end +    test "non shareable instance", %{admin_conn: admin_conn} do +      mock(fn +        %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> +          json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) -  test "listing remote packs" do -    admin = insert(:user, is_admin: true) -    %{conn: conn} = oauth_access(["admin:write"], user: admin) +        %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> +          json(%{metadata: %{features: []}}) +      end) -    resp = -      build_conn() -      |> get(emoji_api_path(conn, :list_packs)) -      |> json_response(200) +      assert admin_conn +             |> get("/api/pleroma/emoji/packs/remote", %{url: "https://example.com"}) +             |> json_response(500) == %{ +               "error" => "The requested instance does not support sharing emoji packs" +             } +    end +  end -    mock(fn -      %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> -        json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) +  describe "GET /api/pleroma/emoji/packs/:name/archive" do +    test "download shared pack", %{conn: conn} do +      resp = +        conn +        |> get("/api/pleroma/emoji/packs/test_pack/archive") +        |> response(200) -      %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> -        json(%{metadata: %{features: ["shareable_emoji_packs"]}}) +      {:ok, arch} = :zip.unzip(resp, [:memory]) -      %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} -> -        json(resp) -    end) +      assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end) +      assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end) +    end + +    test "non existing pack", %{conn: conn} do +      assert conn +             |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive") +             |> json_response(:not_found) == %{ +               "error" => "Pack test_pack_for_import does not exist" +             } +    end -    assert conn -           |> post(emoji_api_path(conn, :list_from), %{instance_address: "https://example.com"}) -           |> json_response(200) == resp +    test "non downloadable pack", %{conn: conn} do +      assert conn +             |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive") +             |> json_response(:forbidden) == %{ +               "error" => +                 "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing" +             } +    end    end -  test "downloading a shared pack from download_shared" do -    conn = build_conn() +  describe "POST /api/pleroma/emoji/packs/download" do +    test "shared pack from remote and non shared from fallback-src", %{ +      admin_conn: admin_conn, +      conn: conn +    } do +      mock(fn +        %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> +          json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) -    resp = -      conn -      |> get(emoji_api_path(conn, :download_shared, "test_pack")) -      |> response(200) +        %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> +          json(%{metadata: %{features: ["shareable_emoji_packs"]}}) -    {:ok, arch} = :zip.unzip(resp, [:memory]) +        %{ +          method: :get, +          url: "https://example.com/api/pleroma/emoji/packs/test_pack" +        } -> +          conn +          |> get("/api/pleroma/emoji/packs/test_pack") +          |> json_response(200) +          |> json() -    assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end) -    assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end) -  end +        %{ +          method: :get, +          url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive" +        } -> +          conn +          |> get("/api/pleroma/emoji/packs/test_pack/archive") +          |> response(200) +          |> text() -  test "downloading shared & unshared packs from another instance via download_from, deleting them" do -    on_exit(fn -> -      File.rm_rf!("#{@emoji_dir_path}/test_pack2") -      File.rm_rf!("#{@emoji_dir_path}/test_pack_nonshared2") -    end) +        %{ +          method: :get, +          url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared" +        } -> +          conn +          |> get("/api/pleroma/emoji/packs/test_pack_nonshared") +          |> json_response(200) +          |> json() -    mock(fn -      %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} -> -        json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]}) +        %{ +          method: :get, +          url: "https://nonshared-pack" +        } -> +          text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip")) +      end) -      %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} -> -        json(%{metadata: %{features: []}}) +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/download", %{ +               url: "https://example.com", +               name: "test_pack", +               as: "test_pack2" +             }) +             |> json_response(200) == "ok" -      %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> -        json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) +      assert File.exists?("#{@emoji_path}/test_pack2/pack.json") +      assert File.exists?("#{@emoji_path}/test_pack2/blank.png") -      %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> -        json(%{metadata: %{features: ["shareable_emoji_packs"]}}) +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/test_pack2") +             |> json_response(200) == "ok" -      %{ -        method: :get, -        url: "https://example.com/api/pleroma/emoji/packs/list" -      } -> -        conn = build_conn() +      refute File.exists?("#{@emoji_path}/test_pack2") -        conn -        |> get(emoji_api_path(conn, :list_packs)) -        |> json_response(200) -        |> json() +      assert admin_conn +             |> post( +               "/api/pleroma/emoji/packs/download", +               %{ +                 url: "https://example.com", +                 name: "test_pack_nonshared", +                 as: "test_pack_nonshared2" +               } +             ) +             |> json_response(200) == "ok" -      %{ -        method: :get, -        url: "https://example.com/api/pleroma/emoji/packs/download_shared/test_pack" -      } -> -        conn = build_conn() +      assert File.exists?("#{@emoji_path}/test_pack_nonshared2/pack.json") +      assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png") -        conn -        |> get(emoji_api_path(conn, :download_shared, "test_pack")) -        |> response(200) -        |> text() +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/test_pack_nonshared2") +             |> json_response(200) == "ok" -      %{ -        method: :get, -        url: "https://nonshared-pack" -      } -> -        text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip")) -    end) +      refute File.exists?("#{@emoji_path}/test_pack_nonshared2") +    end -    admin = insert(:user, is_admin: true) +    test "nonshareable instance", %{admin_conn: admin_conn} do +      mock(fn +        %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} -> +          json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]}) -    conn = -      build_conn() -      |> assign(:user, admin) -      |> assign(:token, insert(:oauth_admin_token, user: admin, scopes: ["admin:write"])) - -    assert (conn -            |> put_req_header("content-type", "application/json") -            |> post( -              emoji_api_path( -                conn, -                :download_from -              ), -              %{ -                instance_address: "https://old-instance", -                pack_name: "test_pack", -                as: "test_pack2" -              } -              |> Jason.encode!() -            ) -            |> json_response(500))["error"] =~ "does not support" - -    assert conn -           |> put_req_header("content-type", "application/json") -           |> post( -             emoji_api_path( -               conn, -               :download_from -             ), -             %{ -               instance_address: "https://example.com", -               pack_name: "test_pack", -               as: "test_pack2" +        %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} -> +          json(%{metadata: %{features: []}}) +      end) + +      assert admin_conn +             |> post( +               "/api/pleroma/emoji/packs/download", +               %{ +                 url: "https://old-instance", +                 name: "test_pack", +                 as: "test_pack2" +               } +             ) +             |> json_response(500) == %{ +               "error" => "The requested instance does not support sharing emoji packs"               } -             |> Jason.encode!() -           ) -           |> json_response(200) == "ok" - -    assert File.exists?("#{@emoji_dir_path}/test_pack2/pack.json") -    assert File.exists?("#{@emoji_dir_path}/test_pack2/blank.png") - -    assert conn -           |> delete(emoji_api_path(conn, :delete, "test_pack2")) -           |> json_response(200) == "ok" - -    refute File.exists?("#{@emoji_dir_path}/test_pack2") - -    # non-shared, downloaded from the fallback URL - -    assert conn -           |> put_req_header("content-type", "application/json") -           |> post( -             emoji_api_path( -               conn, -               :download_from -             ), -             %{ -               instance_address: "https://example.com", -               pack_name: "test_pack_nonshared", -               as: "test_pack_nonshared2" +    end + +    test "checksum fail", %{admin_conn: admin_conn} do +      mock(fn +        %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> +          json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) + +        %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> +          json(%{metadata: %{features: ["shareable_emoji_packs"]}}) + +        %{ +          method: :get, +          url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha" +        } -> +          %Tesla.Env{ +            status: 200, +            body: Pleroma.Emoji.Pack.load_pack("pack_bad_sha") |> Jason.encode!() +          } + +        %{ +          method: :get, +          url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/archive" +        } -> +          %Tesla.Env{ +            status: 200, +            body: File.read!("test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip") +          } +      end) + +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/download", %{ +               url: "https://example.com", +               name: "pack_bad_sha", +               as: "pack_bad_sha2" +             }) +             |> json_response(:internal_server_error) == %{ +               "error" => "SHA256 for the pack doesn't match the one sent by the server"               } -             |> Jason.encode!() -           ) -           |> json_response(200) == "ok" +    end + +    test "other error", %{admin_conn: admin_conn} do +      mock(fn +        %{method: :get, url: "https://example.com/.well-known/nodeinfo"} -> +          json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]}) -    assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/pack.json") -    assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/blank.png") +        %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> +          json(%{metadata: %{features: ["shareable_emoji_packs"]}}) -    assert conn -           |> delete(emoji_api_path(conn, :delete, "test_pack_nonshared2")) -           |> json_response(200) == "ok" +        %{ +          method: :get, +          url: "https://example.com/api/pleroma/emoji/packs/test_pack" +        } -> +          %Tesla.Env{ +            status: 200, +            body: Pleroma.Emoji.Pack.load_pack("test_pack") |> Jason.encode!() +          } +      end) -    refute File.exists?("#{@emoji_dir_path}/test_pack_nonshared2") +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/download", %{ +               url: "https://example.com", +               name: "test_pack", +               as: "test_pack2" +             }) +             |> json_response(:internal_server_error) == %{ +               "error" => +                 "The pack was not set as shared and there is no fallback src to download from" +             } +    end    end -  describe "updating pack metadata" do +  describe "PATCH /api/pleroma/emoji/packs/:name" do      setup do -      pack_file = "#{@emoji_dir_path}/test_pack/pack.json" +      pack_file = "#{@emoji_path}/test_pack/pack.json"        original_content = File.read!(pack_file)        on_exit(fn ->          File.write!(pack_file, original_content)        end) -      admin = insert(:user, is_admin: true) -      %{conn: conn} = oauth_access(["admin:write"], user: admin) -        {:ok, -       admin: admin, -       conn: conn,         pack_file: pack_file,         new_data: %{           "license" => "Test license changed", @@ -228,15 +310,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do      end      test "for a pack without a fallback source", ctx do -      conn = ctx[:conn] - -      assert conn -             |> post( -               emoji_api_path(conn, :update_metadata, "test_pack"), -               %{ -                 "new_data" => ctx[:new_data] -               } -             ) +      assert ctx[:admin_conn] +             |> patch("/api/pleroma/emoji/packs/test_pack", %{"metadata" => ctx[:new_data]})               |> json_response(200) == ctx[:new_data]        assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data] @@ -248,7 +323,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do            method: :get,            url: "https://nonshared-pack"          } -> -          text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip")) +          text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))        end)        new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack") @@ -260,15 +335,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do            "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"          ) -      conn = ctx[:conn] - -      assert conn -             |> post( -               emoji_api_path(conn, :update_metadata, "test_pack"), -               %{ -                 "new_data" => new_data -               } -             ) +      assert ctx[:admin_conn] +             |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})               |> json_response(200) == new_data_with_sha        assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha @@ -286,181 +354,377 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do        new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack") -      conn = ctx[:conn] - -      assert (conn -              |> post( -                emoji_api_path(conn, :update_metadata, "test_pack"), -                %{ -                  "new_data" => new_data -                } -              ) -              |> json_response(:bad_request))["error"] =~ "does not have all" +      assert ctx[:admin_conn] +             |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data}) +             |> json_response(:bad_request) == %{ +               "error" => "The fallback archive does not have all files specified in pack.json" +             }      end    end -  test "updating pack files" do -    pack_file = "#{@emoji_dir_path}/test_pack/pack.json" -    original_content = File.read!(pack_file) +  describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do +    setup do +      pack_file = "#{@emoji_path}/test_pack/pack.json" +      original_content = File.read!(pack_file) -    on_exit(fn -> -      File.write!(pack_file, original_content) +      on_exit(fn -> +        File.write!(pack_file, original_content) +      end) -      File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png") -      File.rm_rf!("#{@emoji_dir_path}/test_pack/dir") -      File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2") -    end) +      :ok +    end -    admin = insert(:user, is_admin: true) -    %{conn: conn} = oauth_access(["admin:write"], user: admin) - -    same_name = %{ -      "action" => "add", -      "shortcode" => "blank", -      "filename" => "dir/blank.png", -      "file" => %Plug.Upload{ -        filename: "blank.png", -        path: "#{@emoji_dir_path}/test_pack/blank.png" -      } -    } - -    different_name = %{same_name | "shortcode" => "blank_2"} - -    assert (conn -            |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name) -            |> json_response(:conflict))["error"] =~ "already exists" - -    assert conn -           |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name) -           |> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"} - -    assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png") - -    assert conn -           |> post(emoji_api_path(conn, :update_file, "test_pack"), %{ -             "action" => "update", -             "shortcode" => "blank_2", -             "new_shortcode" => "blank_3", -             "new_filename" => "dir_2/blank_3.png" -           }) -           |> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"} - -    refute File.exists?("#{@emoji_dir_path}/test_pack/dir/") -    assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png") - -    assert conn -           |> post(emoji_api_path(conn, :update_file, "test_pack"), %{ -             "action" => "remove", -             "shortcode" => "blank_3" -           }) -           |> json_response(200) == %{"blank" => "blank.png"} - -    refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/") - -    mock(fn -      %{ -        method: :get, -        url: "https://test-blank/blank_url.png" -      } -> -        text(File.read!("#{@emoji_dir_path}/test_pack/blank.png")) -    end) +    test "create shortcode exists", %{admin_conn: admin_conn} do +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response(:conflict) == %{ +               "error" => "An emoji with the \"blank\" shortcode already exists" +             } +    end -    # The name should be inferred from the URL ending -    from_url = %{ -      "action" => "add", -      "shortcode" => "blank_url", -      "file" => "https://test-blank/blank_url.png" -    } +    test "don't rewrite old emoji", %{admin_conn: admin_conn} do +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end) -    assert conn -           |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url) -           |> json_response(200) == %{ -             "blank" => "blank.png", -             "blank_url" => "blank_url.png" -           } +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank2", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response(200) == %{"blank" => "blank.png", "blank2" => "dir/blank.png"} + +      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") + +      assert admin_conn +             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank", +               new_shortcode: "blank2", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response(:conflict) == %{ +               "error" => +                 "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option" +             } +    end + +    test "rewrite old emoji with force option", %{admin_conn: admin_conn} do +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end) -    assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png") +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank2", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response(200) == %{"blank" => "blank.png", "blank2" => "dir/blank.png"} + +      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") + +      assert admin_conn +             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank2", +               new_shortcode: "blank3", +               new_filename: "dir_2/blank_3.png", +               force: true +             }) +             |> json_response(200) == %{ +               "blank" => "blank.png", +               "blank3" => "dir_2/blank_3.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") +    end + +    test "with empty filename", %{admin_conn: admin_conn} do +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank2", +               filename: "", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response(:bad_request) == %{ +               "error" => "pack name, shortcode or filename cannot be empty" +             } +    end + +    test "add file with not loaded pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/not_loaded/files", %{ +               shortcode: "blank2", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response(:bad_request) == %{ +               "error" => "pack \"not_loaded\" is not found" +             } +    end + +    test "remove file with not loaded pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/not_loaded/files", %{shortcode: "blank3"}) +             |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"} +    end + +    test "remove file with empty shortcode", %{admin_conn: admin_conn} do +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/not_loaded/files", %{shortcode: ""}) +             |> json_response(:bad_request) == %{ +               "error" => "pack name or shortcode cannot be empty" +             } +    end -    assert conn -           |> post(emoji_api_path(conn, :update_file, "test_pack"), %{ -             "action" => "remove", -             "shortcode" => "blank_url" -           }) -           |> json_response(200) == %{"blank" => "blank.png"} +    test "update file with not loaded pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> patch("/api/pleroma/emoji/packs/not_loaded/files", %{ +               shortcode: "blank4", +               new_shortcode: "blank3", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"} +    end + +    test "new with shortcode as file with update", %{admin_conn: admin_conn} do +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank4", +               filename: "dir/blank.png", +               file: %Plug.Upload{ +                 filename: "blank.png", +                 path: "#{@emoji_path}/test_pack/blank.png" +               } +             }) +             |> json_response(200) == %{"blank" => "blank.png", "blank4" => "dir/blank.png"} -    refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png") +      assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png") + +      assert admin_conn +             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank4", +               new_shortcode: "blank3", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response(200) == %{"blank3" => "dir_2/blank_3.png", "blank" => "blank.png"} + +      refute File.exists?("#{@emoji_path}/test_pack/dir/") +      assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") + +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/test_pack/files", %{shortcode: "blank3"}) +             |> json_response(200) == %{"blank" => "blank.png"} + +      refute File.exists?("#{@emoji_path}/test_pack/dir_2/") + +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end) +    end + +    test "new with shortcode from url", %{admin_conn: admin_conn} do +      mock(fn +        %{ +          method: :get, +          url: "https://test-blank/blank_url.png" +        } -> +          text(File.read!("#{@emoji_path}/test_pack/blank.png")) +      end) + +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank_url", +               file: "https://test-blank/blank_url.png" +             }) +             |> json_response(200) == %{ +               "blank_url" => "blank_url.png", +               "blank" => "blank.png" +             } + +      assert File.exists?("#{@emoji_path}/test_pack/blank_url.png") + +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end) +    end + +    test "new without shortcode", %{admin_conn: admin_conn} do +      on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end) + +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_pack/files", %{ +               file: %Plug.Upload{ +                 filename: "shortcode.png", +                 path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png" +               } +             }) +             |> json_response(200) == %{"shortcode" => "shortcode.png", "blank" => "blank.png"} +    end + +    test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/test_pack/files", %{shortcode: "blank2"}) +             |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"} +    end + +    test "update non existing emoji", %{admin_conn: admin_conn} do +      assert admin_conn +             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank2", +               new_shortcode: "blank3", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"} +    end + +    test "update with empty shortcode", %{admin_conn: admin_conn} do +      assert admin_conn +             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{ +               shortcode: "blank", +               new_filename: "dir_2/blank_3.png" +             }) +             |> json_response(:bad_request) == %{ +               "error" => "new_shortcode or new_filename cannot be empty" +             } +    end    end -  test "creating and deleting a pack" do -    on_exit(fn -> -      File.rm_rf!("#{@emoji_dir_path}/test_created") -    end) +  describe "POST/DELETE /api/pleroma/emoji/packs/:name" do +    test "creating and deleting a pack", %{admin_conn: admin_conn} do +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_created") +             |> json_response(200) == "ok" -    admin = insert(:user, is_admin: true) -    %{conn: conn} = oauth_access(["admin:write"], user: admin) - -    assert conn -           |> put_req_header("content-type", "application/json") -           |> put( -             emoji_api_path( -               conn, -               :create, -               "test_created" -             ) -           ) -           |> json_response(200) == "ok" +      assert File.exists?("#{@emoji_path}/test_created/pack.json") -    assert File.exists?("#{@emoji_dir_path}/test_created/pack.json") +      assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{ +               "pack" => %{}, +               "files" => %{} +             } -    assert Jason.decode!(File.read!("#{@emoji_dir_path}/test_created/pack.json")) == %{ -             "pack" => %{}, -             "files" => %{} -           } +      assert admin_conn +             |> delete("/api/pleroma/emoji/packs/test_created") +             |> json_response(200) == "ok" + +      refute File.exists?("#{@emoji_path}/test_created/pack.json") +    end + +    test "if pack exists", %{admin_conn: admin_conn} do +      path = Path.join(@emoji_path, "test_created") +      File.mkdir(path) +      pack_file = Jason.encode!(%{files: %{}, pack: %{}}) +      File.write!(Path.join(path, "pack.json"), pack_file) + +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/test_created") +             |> json_response(:conflict) == %{ +               "error" => "A pack named \"test_created\" already exists" +             } -    assert conn -           |> delete(emoji_api_path(conn, :delete, "test_created")) -           |> json_response(200) == "ok" +      on_exit(fn -> File.rm_rf(path) end) +    end + +    test "with empty name", %{admin_conn: admin_conn} do +      assert admin_conn +             |> post("/api/pleroma/emoji/packs/ ") +             |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"} +    end +  end + +  test "deleting nonexisting pack", %{admin_conn: admin_conn} do +    assert admin_conn +           |> delete("/api/pleroma/emoji/packs/non_existing") +           |> json_response(:not_found) == %{"error" => "Pack non_existing does not exist"} +  end -    refute File.exists?("#{@emoji_dir_path}/test_created/pack.json") +  test "deleting with empty name", %{admin_conn: admin_conn} do +    assert admin_conn +           |> delete("/api/pleroma/emoji/packs/ ") +           |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}    end -  test "filesystem import" do +  test "filesystem import", %{admin_conn: admin_conn, conn: conn} do      on_exit(fn -> -      File.rm!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt") -      File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json") +      File.rm!("#{@emoji_path}/test_pack_for_import/emoji.txt") +      File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")      end) -    conn = build_conn() -    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200) +    resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)      refute Map.has_key?(resp, "test_pack_for_import") -    admin = insert(:user, is_admin: true) -    %{conn: conn} = oauth_access(["admin:write"], user: admin) - -    assert conn -           |> post(emoji_api_path(conn, :import_from_fs)) +    assert admin_conn +           |> get("/api/pleroma/emoji/packs/import")             |> json_response(200) == ["test_pack_for_import"] -    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200) +    resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)      assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"} -    File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json") -    refute File.exists?("#{@emoji_dir_path}/test_pack_for_import/pack.json") +    File.rm!("#{@emoji_path}/test_pack_for_import/pack.json") +    refute File.exists?("#{@emoji_path}/test_pack_for_import/pack.json") -    emoji_txt_content = "blank, blank.png, Fun\n\nblank2, blank.png" +    emoji_txt_content = """ +    blank, blank.png, Fun +    blank2, blank.png +    foo, /emoji/test_pack_for_import/blank.png +    bar +    """ -    File.write!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt", emoji_txt_content) +    File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content) -    assert conn -           |> post(emoji_api_path(conn, :import_from_fs)) +    assert admin_conn +           |> get("/api/pleroma/emoji/packs/import")             |> json_response(200) == ["test_pack_for_import"] -    resp = build_conn() |> get(emoji_api_path(conn, :list_packs)) |> json_response(200) +    resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)      assert resp["test_pack_for_import"]["files"] == %{               "blank" => "blank.png", -             "blank2" => "blank.png" +             "blank2" => "blank.png", +             "foo" => "blank.png"             }    end + +  describe "GET /api/pleroma/emoji/packs/:name" do +    test "shows pack.json", %{conn: conn} do +      assert %{ +               "files" => %{"blank" => "blank.png"}, +               "pack" => %{ +                 "can-download" => true, +                 "description" => "Test description", +                 "download-sha256" => _, +                 "homepage" => "https://pleroma.social", +                 "license" => "Test license", +                 "share-files" => true +               } +             } = +               conn +               |> get("/api/pleroma/emoji/packs/test_pack") +               |> json_response(200) +    end + +    test "non existing pack", %{conn: conn} do +      assert conn +             |> get("/api/pleroma/emoji/packs/non_existing") +             |> json_response(:not_found) == %{"error" => "Pack non_existing does not exist"} +    end + +    test "error name", %{conn: conn} do +      assert conn +             |> get("/api/pleroma/emoji/packs/ ") +             |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"} +    end +  end  end diff --git a/test/web/pleroma_api/controllers/mascot_controller_test.exs b/test/web/pleroma_api/controllers/mascot_controller_test.exs index 40c33e609..617831b02 100644 --- a/test/web/pleroma_api/controllers/mascot_controller_test.exs +++ b/test/web/pleroma_api/controllers/mascot_controller_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs index 36868db38..cfd1dbd24 100644 --- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs @@ -1,14 +1,16 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do +  use Oban.Testing, repo: Pleroma.Repo    use Pleroma.Web.ConnCase    alias Pleroma.Conversation.Participation    alias Pleroma.Notification    alias Pleroma.Object    alias Pleroma.Repo +  alias Pleroma.Tests.ObanHelpers    alias Pleroma.User    alias Pleroma.Web.CommonAPI @@ -18,7 +20,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      user = insert(:user)      other_user = insert(:user) -    {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"}) +    {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})      result =        conn @@ -40,8 +42,10 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      user = insert(:user)      other_user = insert(:user) -    {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"}) -    {:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "☕") +    {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) +    {:ok, _reaction_activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕") + +    ObanHelpers.perform_all()      result =        conn @@ -52,7 +56,9 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      assert %{"id" => id} = json_response(result, 200)      assert to_string(activity.id) == id -    object = Object.normalize(activity) +    ObanHelpers.perform_all() + +    object = Object.get_by_ap_id(activity.data["object"])      assert object.data["reaction_count"] == 0    end @@ -62,7 +68,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      other_user = insert(:user)      doomed_user = insert(:user) -    {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"}) +    {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})      result =        conn @@ -71,8 +77,8 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      assert result == [] -    {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅") -    {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, doomed_user, "🎅") +    {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅") +    {:ok, _} = CommonAPI.react_with_emoji(activity.id, doomed_user, "🎅")      User.perform(:delete, doomed_user) @@ -96,12 +102,38 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do               result    end +  test "GET /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) + +    result = +      conn +      |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions/🎅") +      |> json_response(200) + +    assert result == [] + +    {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅") +    {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕") + +    result = +      conn +      |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions/🎅") +      |> json_response(200) + +    [%{"name" => "🎅", "count" => 1, "accounts" => [represented_user], "me" => false}] = result + +    assert represented_user["id"] == other_user.id +  end +    test "/api/v1/pleroma/conversations/:id" do      user = insert(:user)      %{user: other_user, conn: conn} = oauth_access(["read:statuses"])      {:ok, _activity} = -      CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"}) +      CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}!", visibility: "direct"})      [participation] = Participation.for_user(other_user) @@ -119,18 +151,18 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      third_user = insert(:user)      {:ok, _activity} = -      CommonAPI.post(user, %{"status" => "Hi @#{third_user.nickname}!", "visibility" => "direct"}) +      CommonAPI.post(user, %{status: "Hi @#{third_user.nickname}!", visibility: "direct"})      {:ok, activity} = -      CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"}) +      CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}!", visibility: "direct"})      [participation] = Participation.for_user(other_user)      {:ok, activity_two} =        CommonAPI.post(other_user, %{ -        "status" => "Hi!", -        "in_reply_to_status_id" => activity.id, -        "in_reply_to_conversation_id" => participation.id +        status: "Hi!", +        in_reply_to_status_id: activity.id, +        in_reply_to_conversation_id: participation.id        })      result = @@ -143,13 +175,30 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      id_one = activity.id      id_two = activity_two.id      assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result + +    {:ok, %{id: id_three}} = +      CommonAPI.post(other_user, %{ +        status: "Bye!", +        in_reply_to_status_id: activity.id, +        in_reply_to_conversation_id: participation.id +      }) + +    assert [%{"id" => ^id_two}, %{"id" => ^id_three}] = +             conn +             |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?limit=2") +             |> json_response(:ok) + +    assert [%{"id" => ^id_three}] = +             conn +             |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?min_id=#{id_two}") +             |> json_response(:ok)    end    test "PATCH /api/v1/pleroma/conversations/:id" do      %{user: user, conn: conn} = oauth_access(["write:conversations"])      other_user = insert(:user) -    {:ok, _activity} = CommonAPI.post(user, %{"status" => "Hi", "visibility" => "direct"}) +    {:ok, _activity} = CommonAPI.post(user, %{status: "Hi", visibility: "direct"})      [participation] = Participation.for_user(user) @@ -177,13 +226,13 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do    test "POST /api/v1/pleroma/conversations/read" do      user = insert(:user) -    %{user: other_user, conn: conn} = oauth_access(["write:notifications"]) +    %{user: other_user, conn: conn} = oauth_access(["write:conversations"])      {:ok, _activity} = -      CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}", "visibility" => "direct"}) +      CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}", visibility: "direct"})      {:ok, _activity} = -      CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}", "visibility" => "direct"}) +      CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}", visibility: "direct"})      [participation2, participation1] = Participation.for_user(other_user)      assert Participation.get(participation2.id).read == false @@ -206,8 +255,8 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      test "it marks a single notification as read", %{user: user1, conn: conn} do        user2 = insert(:user) -      {:ok, activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"}) -      {:ok, activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"}) +      {:ok, activity1} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"}) +      {:ok, activity2} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})        {:ok, [notification1]} = Notification.create_notifications(activity1)        {:ok, [notification2]} = Notification.create_notifications(activity2) @@ -223,9 +272,9 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      test "it marks multiple notifications as read", %{user: user1, conn: conn} do        user2 = insert(:user) -      {:ok, _activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"}) -      {:ok, _activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"}) -      {:ok, _activity3} = CommonAPI.post(user2, %{"status" => "HIE @#{user1.nickname}"}) +      {:ok, _activity1} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"}) +      {:ok, _activity2} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"}) +      {:ok, _activity3} = CommonAPI.post(user2, %{status: "HIE @#{user1.nickname}"})        [notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3}) diff --git a/test/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/web/pleroma_api/controllers/scrobble_controller_test.exs index 2242610f1..1b945040c 100644 --- a/test/web/pleroma_api/controllers/scrobble_controller_test.exs +++ b/test/web/pleroma_api/controllers/scrobble_controller_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do diff --git a/test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs b/test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs new file mode 100644 index 000000000..d23d08a00 --- /dev/null +++ b/test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs @@ -0,0 +1,260 @@ +defmodule Pleroma.Web.PleromaAPI.TwoFactorAuthenticationControllerTest do +  use Pleroma.Web.ConnCase + +  import Pleroma.Factory +  alias Pleroma.MFA.Settings +  alias Pleroma.MFA.TOTP + +  describe "GET /api/pleroma/accounts/mfa/settings" do +    test "returns user mfa settings for new user", %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read", "follow"]) +      token2 = insert(:oauth_token, scopes: ["write"]) + +      assert conn +             |> put_req_header("authorization", "Bearer #{token.token}") +             |> get("/api/pleroma/accounts/mfa") +             |> json_response(:ok) == %{ +               "settings" => %{"enabled" => false, "totp" => false} +             } + +      assert conn +             |> put_req_header("authorization", "Bearer #{token2.token}") +             |> get("/api/pleroma/accounts/mfa") +             |> json_response(403) == %{ +               "error" => "Insufficient permissions: read:security." +             } +    end + +    test "returns user mfa settings with enabled totp", %{conn: conn} do +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{ +            enabled: true, +            totp: %Settings.TOTP{secret: "XXX", delivery_type: "app", confirmed: true} +          } +        ) + +      token = insert(:oauth_token, scopes: ["read", "follow"], user: user) + +      assert conn +             |> put_req_header("authorization", "Bearer #{token.token}") +             |> get("/api/pleroma/accounts/mfa") +             |> json_response(:ok) == %{ +               "settings" => %{"enabled" => true, "totp" => true} +             } +    end +  end + +  describe "GET /api/pleroma/accounts/mfa/backup_codes" do +    test "returns backup codes", %{conn: conn} do +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{ +            backup_codes: ["1", "2", "3"], +            totp: %Settings.TOTP{secret: "secret"} +          } +        ) + +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) +      token2 = insert(:oauth_token, scopes: ["read"]) + +      response = +        conn +        |> put_req_header("authorization", "Bearer #{token.token}") +        |> get("/api/pleroma/accounts/mfa/backup_codes") +        |> json_response(:ok) + +      assert [<<_::bytes-size(6)>>, <<_::bytes-size(6)>>] = response["codes"] +      user = refresh_record(user) +      mfa_settings = user.multi_factor_authentication_settings +      assert mfa_settings.totp.secret == "secret" +      refute mfa_settings.backup_codes == ["1", "2", "3"] +      refute mfa_settings.backup_codes == [] + +      assert conn +             |> put_req_header("authorization", "Bearer #{token2.token}") +             |> get("/api/pleroma/accounts/mfa/backup_codes") +             |> json_response(403) == %{ +               "error" => "Insufficient permissions: write:security." +             } +    end +  end + +  describe "GET /api/pleroma/accounts/mfa/setup/totp" do +    test "return errors when method is invalid", %{conn: conn} do +      user = insert(:user) +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) + +      response = +        conn +        |> put_req_header("authorization", "Bearer #{token.token}") +        |> get("/api/pleroma/accounts/mfa/setup/torf") +        |> json_response(400) + +      assert response == %{"error" => "undefined method"} +    end + +    test "returns key and provisioning_uri", %{conn: conn} do +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{backup_codes: ["1", "2", "3"]} +        ) + +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) +      token2 = insert(:oauth_token, scopes: ["read"]) + +      response = +        conn +        |> put_req_header("authorization", "Bearer #{token.token}") +        |> get("/api/pleroma/accounts/mfa/setup/totp") +        |> json_response(:ok) + +      user = refresh_record(user) +      mfa_settings = user.multi_factor_authentication_settings +      secret = mfa_settings.totp.secret +      refute mfa_settings.enabled +      assert mfa_settings.backup_codes == ["1", "2", "3"] + +      assert response == %{ +               "key" => secret, +               "provisioning_uri" => TOTP.provisioning_uri(secret, "#{user.email}") +             } + +      assert conn +             |> put_req_header("authorization", "Bearer #{token2.token}") +             |> get("/api/pleroma/accounts/mfa/setup/totp") +             |> json_response(403) == %{ +               "error" => "Insufficient permissions: write:security." +             } +    end +  end + +  describe "GET /api/pleroma/accounts/mfa/confirm/totp" do +    test "returns success result", %{conn: conn} do +      secret = TOTP.generate_secret() +      code = TOTP.generate_token(secret) + +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{ +            backup_codes: ["1", "2", "3"], +            totp: %Settings.TOTP{secret: secret} +          } +        ) + +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) +      token2 = insert(:oauth_token, scopes: ["read"]) + +      assert conn +             |> put_req_header("authorization", "Bearer #{token.token}") +             |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code}) +             |> json_response(:ok) + +      settings = refresh_record(user).multi_factor_authentication_settings +      assert settings.enabled +      assert settings.totp.secret == secret +      assert settings.totp.confirmed +      assert settings.backup_codes == ["1", "2", "3"] + +      assert conn +             |> put_req_header("authorization", "Bearer #{token2.token}") +             |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code}) +             |> json_response(403) == %{ +               "error" => "Insufficient permissions: write:security." +             } +    end + +    test "returns error if password incorrect", %{conn: conn} do +      secret = TOTP.generate_secret() +      code = TOTP.generate_token(secret) + +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{ +            backup_codes: ["1", "2", "3"], +            totp: %Settings.TOTP{secret: secret} +          } +        ) + +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) + +      response = +        conn +        |> put_req_header("authorization", "Bearer #{token.token}") +        |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "xxx", code: code}) +        |> json_response(422) + +      settings = refresh_record(user).multi_factor_authentication_settings +      refute settings.enabled +      refute settings.totp.confirmed +      assert settings.backup_codes == ["1", "2", "3"] +      assert response == %{"error" => "Invalid password."} +    end + +    test "returns error if code incorrect", %{conn: conn} do +      secret = TOTP.generate_secret() + +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{ +            backup_codes: ["1", "2", "3"], +            totp: %Settings.TOTP{secret: secret} +          } +        ) + +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) +      token2 = insert(:oauth_token, scopes: ["read"]) + +      response = +        conn +        |> put_req_header("authorization", "Bearer #{token.token}") +        |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"}) +        |> json_response(422) + +      settings = refresh_record(user).multi_factor_authentication_settings +      refute settings.enabled +      refute settings.totp.confirmed +      assert settings.backup_codes == ["1", "2", "3"] +      assert response == %{"error" => "invalid_token"} + +      assert conn +             |> put_req_header("authorization", "Bearer #{token2.token}") +             |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"}) +             |> json_response(403) == %{ +               "error" => "Insufficient permissions: write:security." +             } +    end +  end + +  describe "DELETE /api/pleroma/accounts/mfa/totp" do +    test "returns success result", %{conn: conn} do +      user = +        insert(:user, +          multi_factor_authentication_settings: %Settings{ +            backup_codes: ["1", "2", "3"], +            totp: %Settings.TOTP{secret: "secret"} +          } +        ) + +      token = insert(:oauth_token, scopes: ["write", "follow"], user: user) +      token2 = insert(:oauth_token, scopes: ["read"]) + +      assert conn +             |> put_req_header("authorization", "Bearer #{token.token}") +             |> delete("/api/pleroma/accounts/mfa/totp", %{password: "test"}) +             |> json_response(:ok) + +      settings = refresh_record(user).multi_factor_authentication_settings +      refute settings.enabled +      assert settings.totp.secret == nil +      refute settings.totp.confirmed + +      assert conn +             |> put_req_header("authorization", "Bearer #{token2.token}") +             |> delete("/api/pleroma/accounts/mfa/totp", %{password: "test"}) +             |> json_response(403) == %{ +               "error" => "Insufficient permissions: write:security." +             } +    end +  end +end | 
