diff --git a/config/test.exs b/config/test.exs index 9cbf8c2747..3bb3ecb624 100644 --- a/config/test.exs +++ b/config/test.exs @@ -60,6 +60,8 @@ config :tesla, adapter: Tesla.Mock +config :tesla, Geospatial.HTTP, adapter: Tesla.Mock + config :pleroma, :rich_media, enabled: false, ignore_hosts: [], diff --git a/lib/pleroma/web/api_spec/operations/pleroma_event_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_event_operation.ex index ed88e2ee16..e685206ec1 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_event_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_event_operation.ex @@ -150,6 +150,7 @@ def authorize_participation_request_operation do parameters: [id_param(), participant_id_param()], responses: %{ 200 => event_response(), + 403 => Operation.response("Forbidden", "application/json", ApiError), 404 => Operation.response("Not Found", "application/json", ApiError) } } @@ -165,6 +166,7 @@ def reject_participation_request_operation do parameters: [id_param(), participant_id_param()], responses: %{ 200 => event_response(), + 403 => Operation.response("Forbidden", "application/json", ApiError), 404 => Operation.response("Not Found", "application/json", ApiError) } } diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex index 20e2e3467b..289663790e 100644 --- a/lib/pleroma/web/api_spec/operations/status_operation.ex +++ b/lib/pleroma/web/api_spec/operations/status_operation.ex @@ -487,7 +487,8 @@ def update_operation do responses: %{ 200 => status_response(), 403 => Operation.response("Forbidden", "application/json", ApiError), - 404 => Operation.response("Not Found", "application/json", ApiError) + 404 => Operation.response("Not Found", "application/json", ApiError), + 422 => Operation.response("Unprocessable Entity", "application/json", ApiError) } } end diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 6bba7d39a0..dbf450ec11 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -234,6 +234,7 @@ def update(%{assigns: %{user: user}, body_params: body_params} = conn, %{id: id} {_, true} <- {:is_create, activity.data["type"] == "Create"}, actor <- Activity.user_actor(activity), {_, true} <- {:own_status, actor.id == user.id}, + {_, true} <- {:not_event, activity.object.data["type"] != "Event"}, changes <- body_params |> Map.put(:generator, conn.assigns.application), {_, {:ok, _update_activity}} <- {:pipeline, CommonAPI.update(user, activity, changes)}, {_, %Activity{}} = {_, activity} <- {:refetched, Activity.get_by_id_with_object(id)} do @@ -245,6 +246,7 @@ def update(%{assigns: %{user: user}, body_params: body_params} = conn, %{id: id} ) else {:own_status, _} -> {:error, :forbidden} + {:not_event, _} -> {:error, :unprocessable_entity, "Use event update route"} {:pipeline, _} -> {:error, :internal_server_error} _ -> {:error, :not_found} end diff --git a/lib/pleroma/web/pleroma_api/controllers/event_controller.ex b/lib/pleroma/web/pleroma_api/controllers/event_controller.ex index 87ed2882fa..ee8de65f55 100644 --- a/lib/pleroma/web/pleroma_api/controllers/event_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/event_controller.ex @@ -70,6 +70,8 @@ defmodule Pleroma.Web.PleromaAPI.EventController do plug(Pleroma.Web.Plugs.SetApplicationPlug, [] when action in [:create, :update]) + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaEventOperation def create(%{assigns: %{user: user}, body_params: params} = conn, _) do @@ -231,10 +233,14 @@ def authorize_participation_request( } = conn, _ ) do - with {:ok, _} <- CommonAPI.accept_join_request(for_user, participant, ap_id) do + with actor <- Activity.user_actor(activity), + {_, true} <- {:own_event, actor.id == for_user.id}, + {:ok, _} <- CommonAPI.accept_join_request(for_user, participant, ap_id) do conn |> put_view(StatusView) |> try_render("show.json", activity: activity, for: for_user, as: :activity) + else + {:own_event, _} -> {:error, :forbidden} end end @@ -248,10 +254,14 @@ def reject_participation_request( } = conn, _ ) do - with {:ok, _} <- CommonAPI.reject_join_request(for_user, participant, ap_id) do + with actor <- Activity.user_actor(activity), + {_, true} <- {:own_event, actor.id == for_user.id}, + {:ok, _} <- CommonAPI.reject_join_request(for_user, participant, ap_id) do conn |> put_view(StatusView) |> try_render("show.json", activity: activity, for: for_user, as: :activity) + else + {:own_event, _} -> {:error, :forbidden} end end diff --git a/test/fixtures/tesla_mock/nominatim_search_results.json b/test/fixtures/tesla_mock/nominatim_search_results.json new file mode 100644 index 0000000000..60060c391f --- /dev/null +++ b/test/fixtures/tesla_mock/nominatim_search_results.json @@ -0,0 +1 @@ +{"type":"FeatureCollection","geocoding":{"version":"0.1.0","attribution":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","licence":"ODbL","query":"Benis"},"features":[{"type":"Feature","properties":{"geocoding":{"place_id":45392146,"osm_type":"node","osm_id":3726208425,"osm_key":"place","osm_value":"village","type":"city","label":"Benis, بخش مرکزی, Shabestar County, East Azerbaijan Province, Iran","name":"Benis","country":"Iran","state":"East Azerbaijan Province","county":"Shabestar County","city":"بخش مرکزی","admin":{"level4":"East Azerbaijan Province","level5":"Shabestar County","level6":"بخش مرکزی"}}},"geometry":{"type":"Point","coordinates":[45.7285348,38.212263]}},{"type":"Feature","properties":{"geocoding":{"place_id":298521494,"osm_type":"relation","osm_id":8841590,"osm_key":"boundary","osm_value":"administrative","type":"district","label":"Bénis, Castelsarrasin, Tarn-et-Garonne, Occitania, Metropolitan France, 82100, France","name":"Bénis","country":"France","postcode":"82100","state":"Occitania","county":"Tarn-et-Garonne","city":"Castelsarrasin","admin":{"level3":"Metropolitan France","level4":"Occitania","level6":"Tarn-et-Garonne","level7":"Castelsarrasin","level8":"Castelsarrasin","level10":"Bénis"}}},"geometry":{"type":"Point","coordinates":[1.1304739,44.0099561]}},{"type":"Feature","properties":{"geocoding":{"place_id":46542003,"osm_type":"node","osm_id":3839840986,"osm_key":"place","osm_value":"locality","type":"locality","label":"Beniš, Jablonov nad Turňou, District of Rožňava, Region of Košice, Eastern Slovakia, 049 43, Slovakia","name":"Beniš","country":"Slovakia","postcode":"049 43","state":"Region of Košice","county":"District of Rožňava","city":"Jablonov nad Turňou","district":"Jablonov nad Turňou","admin":{"level3":"Eastern Slovakia","level4":"Region of Košice","level8":"District of Rožňava","level9":"Jablonov nad Turňou","level10":"Jablonov nad Turňou"}}},"geometry":{"type":"Point","coordinates":[20.6856788,48.5855164]}},{"type":"Feature","properties":{"geocoding":{"place_id":49659169,"osm_type":"node","osm_id":4261667102,"osm_key":"shop","osm_value":"supermarket","type":"house","label":"Benis, Carrera 18, Centro, Comuna El Cafetero, Perímetro Urbano Armenia, Armenia, Capital, Quindío, 630004, Colombia","name":"Benis","country":"Colombia","postcode":"630004","state":"Quindío","county":"Capital","city":"Armenia","district":"Comuna El Cafetero","locality":"Centro","street":"Carrera 18","admin":{"level4":"Quindío","level5":"Capital","level6":"Armenia","level7":"Perímetro Urbano Armenia","level8":"Comuna El Cafetero"}}},"geometry":{"type":"Point","coordinates":[-75.6734958,4.5362242]}},{"type":"Feature","properties":{"geocoding":{"place_id":65944064,"osm_type":"node","osm_id":6087846386,"osm_key":"amenity","osm_value":"cafe","type":"house","label":"Bénis, شارع الحرية, الحدائق, معتمدية باب بحر, Tunis, 1017, Tunisia","name":"Bénis","country":"Tunisia","postcode":"1017","state":"Tunis","city":"Tunis","district":"الحدائق","street":"شارع الحرية","admin":{"level4":"Tunis","level5":"معتمدية باب بحر","level6":"الحدائق"}}},"geometry":{"type":"Point","coordinates":[10.1796633,36.8103671]}},{"type":"Feature","properties":{"geocoding":{"place_id":19666304,"osm_type":"node","osm_id":2250812267,"osm_key":"shop","osm_value":"bakery","type":"house","label":"Bénis, Rue du Fqih al Abbas, batiment hay dakhla, Houbous District, Mechouar, Pachalik de Méchouar de Casablanca, Prefecture of Casablanca, Casablanca-Settat, 20504, Morocco","name":"Bénis","country":"Morocco","postcode":"20504","state":"Casablanca-Settat","county":"Pachalik de Méchouar de Casablanca","city":"Mechouar","district":"Houbous District","locality":"batiment hay dakhla","street":"Rue du Fqih al Abbas","admin":{"level4":"Casablanca-Settat","level5":"Prefecture of Casablanca","level6":"Pachalik de Méchouar de Casablanca","level8":"Mechouar"}}},"geometry":{"type":"Point","coordinates":[-7.6054449,33.5779601]}}]} \ No newline at end of file diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 328e54c115..06c5c1dd82 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -2193,6 +2193,23 @@ test "it refuses to update when original post is not by the user", %{conn: conn} |> json_response_and_validate_schema(:forbidden) end + test "it refuses to update an event", %{conn: conn, user: user} do + {:ok, activity} = + CommonAPI.event(user, %{ + name: "I'm not a regular status", + status: "", + join_mode: "free", + start_time: DateTime.from_iso8601("2023-01-01T01:00:00.000Z") |> elem(1) + }) + + conn + |> put_req_header("content-type", "application/json") + |> put("/api/v1/statuses/#{activity.id}", %{ + "status" => "edited" + }) + |> json_response_and_validate_schema(:unprocessable_entity) + end + test "it returns 404 if the user cannot see the post", %{conn: conn} do another_user = insert(:user) diff --git a/test/pleroma/web/pleroma_api/controllers/event_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/event_controller_test.exs index 727710b768..58576c0282 100644 --- a/test/pleroma/web/pleroma_api/controllers/event_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/event_controller_test.exs @@ -16,7 +16,7 @@ defmodule Pleroma.Web.PleromaAPI.EventControllerTest do setup do user = insert(:user) %{user: user, conn: conn} = oauth_access(["write"], user: user) - [current_user: user, conn: conn] + [user: user, conn: conn] end test "creates an event", %{conn: conn} do @@ -87,10 +87,10 @@ test "GET /api/v1/pleroma/events/:id/participations" do setup do user = insert(:user) %{user: user, conn: conn} = oauth_access(["read"], user: user) - [current_user: user, conn: conn] + [user: user, conn: conn] end - test "show participation requests", %{conn: conn, current_user: user} do + test "show participation requests", %{conn: conn, user: user} do other_user = insert(:user) {:ok, activity} = @@ -141,7 +141,7 @@ test "don't display requests if not an author", %{conn: conn} do setup do user = insert(:user) %{user: user, conn: conn} = oauth_access(["write"], user: user) - [current_user: user, conn: conn] + [user: user, conn: conn] end test "joins an event", %{conn: conn} do @@ -167,7 +167,7 @@ test "joins an event", %{conn: conn} do } = Object.get_by_ap_id(activity.data["object"]) end - test "can't participate in your own event", %{conn: conn, current_user: user} do + test "can't participate in your own event", %{conn: conn, user: user} do {:ok, activity} = CommonAPI.event(user, %{ name: "test event", @@ -189,10 +189,10 @@ test "can't participate in your own event", %{conn: conn, current_user: user} do setup do user = insert(:user) %{user: user, conn: conn} = oauth_access(["write"], user: user) - [current_user: user, conn: conn] + [user: user, conn: conn] end - test "leaves an event", %{conn: conn, current_user: user} do + test "leaves an event", %{conn: conn, user: user} do other_user = insert(:user) {:ok, activity} = @@ -237,37 +237,66 @@ test "can't leave event you are not participating in", %{conn: conn} do end end - test "POST /api/v1/pleroma/events/:id/participation_requests/:participant_id/authorize" do - [user, %{ap_id: ap_id} = other_user] = insert_pair(:user) - %{user: user, conn: conn} = oauth_access(["write"], user: user) + describe "POST /api/v1/pleroma/events/:id/participation_requests/:participant_id/authorize" do + setup do + user = insert(:user) + %{user: user, conn: conn} = oauth_access(["write"], user: user) + [user: user, conn: conn] + end - {:ok, activity} = - CommonAPI.event(user, %{ - name: "test event", - status: "", - join_mode: "restricted", - start_time: DateTime.from_iso8601("2023-01-01T01:00:00.000Z") |> elem(1) - }) + test "accepts a participation request", %{user: user, conn: conn} do + %{ap_id: ap_id} = other_user = insert(:user) - CommonAPI.join(other_user, activity.id) + {:ok, activity} = + CommonAPI.event(user, %{ + name: "test event", + status: "", + join_mode: "restricted", + start_time: DateTime.from_iso8601("2023-01-01T01:00:00.000Z") |> elem(1) + }) - conn = - conn - |> post( - "/api/v1/pleroma/events/#{activity.id}/participation_requests/#{other_user.id}/authorize" - ) + CommonAPI.join(other_user, activity.id) - assert json_response_and_validate_schema(conn, 200) + conn = + conn + |> post( + "/api/v1/pleroma/events/#{activity.id}/participation_requests/#{other_user.id}/authorize" + ) - assert %{ - data: %{ - "participations" => [^ap_id], - "participation_count" => 1 - } - } = Object.get_by_ap_id(activity.data["object"]) + assert json_response_and_validate_schema(conn, 200) - assert %{data: %{"state" => "accept"}} = - Utils.get_existing_join(other_user.ap_id, activity.data["object"]) + assert %{ + data: %{ + "participations" => [^ap_id], + "participation_count" => 1 + } + } = Object.get_by_ap_id(activity.data["object"]) + + assert %{data: %{"state" => "accept"}} = + Utils.get_existing_join(other_user.ap_id, activity.data["object"]) + end + + test "it refuses to accept a request when event is not by the user", %{user: user, conn: conn} do + [second_user, third_user] = insert_pair(:user) + + {:ok, activity} = + CommonAPI.event(second_user, %{ + name: "test event", + status: "", + join_mode: "restricted", + start_time: DateTime.from_iso8601("2023-01-01T01:00:00.000Z") |> elem(1) + }) + + CommonAPI.join(third_user, activity.id) + + conn = + conn + |> post( + "/api/v1/pleroma/events/#{activity.id}/participation_requests/#{third_user.id}/authorize" + ) + + assert json_response_and_validate_schema(conn, :forbidden) + end end test "POST /api/v1/pleroma/events/:id/participation_requests/:participant_id/reject" do diff --git a/test/pleroma/web/pleroma_api/controllers/search_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/search_controller_test.exs new file mode 100644 index 0000000000..87a34508cb --- /dev/null +++ b/test/pleroma/web/pleroma_api/controllers/search_controller_test.exs @@ -0,0 +1,38 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.SearchControllerTest do + use Pleroma.Web.ConnCase + use Oban.Testing, repo: Pleroma.Repo + + import Pleroma.Factory + + test "GET /api/v1/pleroma/search/location" do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + user = insert(:user) + %{conn: conn} = oauth_access([], user: user) + + conn = + conn + |> get("/api/v1/pleroma/search/location?q=Benis") + + assert [result | _] = json_response_and_validate_schema(conn, 200) + + assert result == %{ + "country" => "Iran", + "description" => "Benis", + "geom" => %{"coordinates" => [45.7285348, 38.212263], "srid" => 4326}, + "locality" => "بخش مرکزی", + "origin_id" => "3726208425", + "origin_provider" => "nominatim", + "postal_code" => nil, + "region" => "East Azerbaijan Province", + "street" => " ", + "timezone" => nil, + "type" => "city", + "url" => nil + } + end +end diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 1679e18ef1..646e680b13 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1482,6 +1482,20 @@ def get("https://p.helene.moe/objects/fd5910ac-d9dc-412e-8d1d-914b203296c4", _, }} end + def get( + "https://nominatim.openstreetmap.org/search?format=geocodejson&q=Benis&limit=10&accept-language=en&addressdetails=1&namedetails=1", + _, + _, + _ + ) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/nominatim_search_results.json"), + headers: [{"content-type", "application/json"}] + }} + end + def get(url, query, body, headers) do {:error, "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"}