From a9459ff98f0af590931ef279c2bc7efb0cceac5a Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Sun, 14 Jul 2019 00:37:19 +0300 Subject: [PATCH 01/12] Admin API: Endpoint for fetching latest user's statuses --- CHANGELOG.md | 1 + docs/api/admin_api.md | 12 +++++++ .../web/admin_api/admin_api_controller.ex | 16 +++++++++ lib/pleroma/web/router.ex | 1 + test/support/factory.ex | 5 ++- .../admin_api/admin_api_controller_test.exs | 33 +++++++++++++++++++ 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 942733ab6..86cbaeff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Configuration: `federation_incoming_replies_max_depth` option - Added synchronization of following/followers counters for external users - Configuration: `enabled` option for `Pleroma.Emails.Mailer`, defaulting to `false`. - Mastodon API: Add support for categories for custom emojis by reusing the group feature. +- Admin API: Endpoint for fetching latest user's statuses ### Changed - Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text diff --git a/docs/api/admin_api.md b/docs/api/admin_api.md index c429da822..3880af218 100644 --- a/docs/api/admin_api.md +++ b/docs/api/admin_api.md @@ -187,6 +187,18 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - On failure: `Not found` - On success: JSON of the user +## `/api/pleroma/admin/users/:nickname_or_id/statuses` + +### Retrive user's latest statuses + +- Method: `GET` +- Params: + - `nickname` or `id` + - *optional* `page_size`: number of statuses to return (default is `20`) +- Response: + - On failure: `Not found` + - On success: JSON array of user's latest statuses + ## `/api/pleroma/admin/relay` ### Follow a Relay diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 4a0bf4823..64ad7e8e2 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -82,6 +82,22 @@ def user_show(conn, %{"nickname" => nickname}) do end end + def list_user_statuses(conn, %{"nickname" => nickname} = params) do + with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do + {_, page_size} = page_params(params) + + activities = + ActivityPub.fetch_user_activities(user, nil, %{ + "limit" => page_size + }) + + conn + |> json(StatusView.render("index.json", %{activities: activities, as: :activity})) + else + _ -> {:error, :not_found} + end + end + def user_toggle_activation(conn, %{"nickname" => nickname}) do user = User.get_cached_by_nickname(nickname) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d53fa8a35..9315302c8 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -197,6 +197,7 @@ defmodule Pleroma.Web.Router do get("/users", AdminAPIController, :list_users) get("/users/:nickname", AdminAPIController, :user_show) + get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) get("/reports", AdminAPIController, :list_reports) get("/reports/:id", AdminAPIController, :report_show) diff --git a/test/support/factory.ex b/test/support/factory.ex index 531eb81e4..807b34545 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -118,7 +118,10 @@ def direct_note_activity_factory do def note_activity_factory(attrs \\ %{}) do user = attrs[:user] || insert(:user) note = attrs[:note] || insert(:note, user: user) + published = attrs[:published] || DateTime.utc_now() |> DateTime.to_iso8601() attrs = Map.drop(attrs, [:user, :note]) + require IEx + IEx.pry() data = %{ "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(), @@ -126,7 +129,7 @@ def note_activity_factory(attrs \\ %{}) do "actor" => note.data["actor"], "to" => note.data["to"], "object" => note.data["id"], - "published" => DateTime.utc_now() |> DateTime.to_iso8601(), + "published" => published, "context" => note.data["context"] } diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 1b71cbff3..9d4b3d74b 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -1863,6 +1863,39 @@ test "dispatch setting", %{conn: conn} do } end end + + describe "GET /api/pleroma/admin/users/:nickname/statuses" do + setup do + admin = insert(:user, info: %{is_admin: true}) + user = insert(:user) + + date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() + date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!() + date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!() + + insert(:note_activity, user: user, published: date1) + insert(:note_activity, user: user, published: date2) + insert(:note_activity, user: user, published: date3) + + conn = + build_conn() + |> assign(:user, admin) + + {:ok, conn: conn, user: user} + end + + test "renders user's statuses", %{conn: conn, user: user} do + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses") + + assert json_response(conn, 200) |> length() == 3 + end + + test "renders user's statuses with a limit", %{conn: conn, user: user} do + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2") + + assert json_response(conn, 200) |> length() == 2 + end + end end # Needed for testing From 63924ee712a4a40b902990a4af1f16cbdd49175b Mon Sep 17 00:00:00 2001 From: aries Date: Mon, 22 Jul 2019 18:46:32 +0900 Subject: [PATCH 02/12] Fix static_dir docs --- docs/config/small_customizations.md | 29 ++----------------- docs/config/static_dir.md | 44 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/docs/config/small_customizations.md b/docs/config/small_customizations.md index 09e8d6041..f91657a4c 100644 --- a/docs/config/small_customizations.md +++ b/docs/config/small_customizations.md @@ -1,35 +1,12 @@ # Small customizations -Replace `dev.secret.exs` with `prod.secret.exs` according to your setup. -# Thumbnail +See also static_dir.md for visual settings. -Replace `priv/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html). - -# Instance-specific panel - -![instance-specific panel demo](/uploads/296b19ec806b130e0b49b16bfe29ce8a/image.png) - -To show the instance specific panel, set `show_instance_panel` to `true` in `config/dev.secret.exs`. You can modify its content by editing `priv/static/instance/panel.html`. - -# Background - -You can change the background of your Pleroma instance by uploading it to `priv/static/static`, and then changing `"background"` in `config/dev.secret.exs` accordingly. - -# Logo - -![logo modification demo](/uploads/c70b14de60fa74245e7f0dcfa695ebff/image.png) - -If you want to give a brand to your instance, look no further. You can change the logo of your instance by uploading it to `priv/static/static`, and then changing `logo` in `config/dev.secret.exs` accordingly. - -# Theme +## Theme All users of your instance will be able to change the theme they use by going to the settings (the cog in the top-right hand corner). However, if you wish to change the default theme, you can do so by editing `theme` in `config/dev.secret.exs` accordingly. -# Terms of Service - -Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `priv/static/static/terms-of-service.html`. - -# Message Visibility +## Message Visibility To enable message visibility options when posting like in the Mastodon frontend, set `scope_options_enabled` to `true` in `config/dev.secret.exs`. diff --git a/docs/config/static_dir.md b/docs/config/static_dir.md index 0cc52b99a..0da1e6c9f 100644 --- a/docs/config/static_dir.md +++ b/docs/config/static_dir.md @@ -18,3 +18,47 @@ If you want to generate a restrictive `robots.txt`, you can run the following mi ``` mix pleroma.robots_txt disallow_all ``` + +# Small customizations + +You can directly overwrite files in `priv/static`, but you can also use`instance/static`. + +Since `priv` is tracked by git, it is recommended to put panel.html or thumbnail.jpeg and more under the `instance` directory if you do not use your own pleroma git repository. + +For example, `instance/static/instance/panel.html` + +This is when static_dir is the default. + +## Thumbnail + +Replace `priv/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html). + +Or put your file on `instance/static/instance/thumbnail.jpeg` when static_dir is default. + +## Instance-specific panel + +![instance-specific panel demo](/uploads/296b19ec806b130e0b49b16bfe29ce8a/image.png) + +To show the instance specific panel, set `show_instance_panel` to `true` in `config/dev.secret.exs`. You can modify its content by editing `priv/static/instance/panel.html`. + +Or put your file on `instance/static/instance/panel.html` when static_dir is default. + +## Background + +You can change the background of your Pleroma instance by uploading it to `priv/static/static`, and then changing `"background"` in `config/dev.secret.exs` accordingly. + +Or put your file on `instance/static/static/background.jpg` when static_dir is default. + +## Logo + +![logo modification demo](/uploads/c70b14de60fa74245e7f0dcfa695ebff/image.png) + +If you want to give a brand to your instance, look no further. You can change the logo of your instance by uploading it to `priv/static/static`, and then changing `logo` in `config/dev.secret.exs` accordingly. + +Or put your file on `instance/static/static/logo.png` when static_dir is default. + +## Terms of Service + +Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `priv/static/static/terms-of-service.html`. + +Or put your file on `instance/static/static/terms-of-service.html` when static_dir is default. From 1e7d68e8bf4777013e76fbf732cf81b6f1644320 Mon Sep 17 00:00:00 2001 From: Aries Date: Tue, 23 Jul 2019 09:55:58 +0900 Subject: [PATCH 03/12] Fix the sentence and add the setting example --- docs/config/static_dir.md | 51 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/docs/config/static_dir.md b/docs/config/static_dir.md index 0da1e6c9f..1326a5a17 100644 --- a/docs/config/static_dir.md +++ b/docs/config/static_dir.md @@ -7,7 +7,11 @@ config :pleroma, :instance, static_dir: "instance/static/", ``` -You can overwrite this value in your configuration to use a different static instance directory. +For example, edit `instance/static/instance/panel.html` . + +Alternatively, you can overwrite this value in your configuration to use a different static instance directory. + +This document is written assuming `instance/static/`. ## robots.txt @@ -19,46 +23,45 @@ If you want to generate a restrictive `robots.txt`, you can run the following mi mix pleroma.robots_txt disallow_all ``` -# Small customizations - -You can directly overwrite files in `priv/static`, but you can also use`instance/static`. - -Since `priv` is tracked by git, it is recommended to put panel.html or thumbnail.jpeg and more under the `instance` directory if you do not use your own pleroma git repository. - -For example, `instance/static/instance/panel.html` - -This is when static_dir is the default. - ## Thumbnail -Replace `priv/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html). - -Or put your file on `instance/static/instance/thumbnail.jpeg` when static_dir is default. +Put on `instance/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html). ## Instance-specific panel ![instance-specific panel demo](/uploads/296b19ec806b130e0b49b16bfe29ce8a/image.png) -To show the instance specific panel, set `show_instance_panel` to `true` in `config/dev.secret.exs`. You can modify its content by editing `priv/static/instance/panel.html`. - -Or put your file on `instance/static/instance/panel.html` when static_dir is default. +Create and Edit your file on `instance/static/instance/panel.html`. ## Background -You can change the background of your Pleroma instance by uploading it to `priv/static/static`, and then changing `"background"` in `config/dev.secret.exs` accordingly. +You can change the background of your Pleroma instance by uploading it to `instance/static/`, and then changing `background` in `config/prod.secret.exs` accordingly. -Or put your file on `instance/static/static/background.jpg` when static_dir is default. +If you put `instance/static/images/background.jpg` + +``` +config :pleroma, :frontend_configurations, + pleroma_fe: %{ + background: "/images/background.jpg" + } +``` ## Logo ![logo modification demo](/uploads/c70b14de60fa74245e7f0dcfa695ebff/image.png) -If you want to give a brand to your instance, look no further. You can change the logo of your instance by uploading it to `priv/static/static`, and then changing `logo` in `config/dev.secret.exs` accordingly. +If you want to give a brand to your instance, You can change the logo of your instance by uploading it to `instance/static/`. -Or put your file on `instance/static/static/logo.png` when static_dir is default. +Alternatively, you can specify the path with config. +If you put `instance/static/static/mylogo-file.png` + +``` +config :pleroma, :frontend_configurations, + pleroma_fe: %{ + logo: "/static/mylogo-file.png" + } +``` ## Terms of Service -Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `priv/static/static/terms-of-service.html`. - -Or put your file on `instance/static/static/terms-of-service.html` when static_dir is default. +Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `instance/static/static/terms-of-service.html`. From 14ab2fd0f43f0f8338f685d2ea599479e1e103bf Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Tue, 23 Jul 2019 12:30:37 +0300 Subject: [PATCH 04/12] remove pry --- test/support/factory.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/support/factory.ex b/test/support/factory.ex index 807b34545..d02bd9212 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -120,8 +120,6 @@ def note_activity_factory(attrs \\ %{}) do note = attrs[:note] || insert(:note, user: user) published = attrs[:published] || DateTime.utc_now() |> DateTime.to_iso8601() attrs = Map.drop(attrs, [:user, :note]) - require IEx - IEx.pry() data = %{ "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(), From 90be91b0e091dabd6db36dff92b13ce9dc251c5c Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 22 Jul 2019 13:41:56 +0200 Subject: [PATCH 05/12] Router: Remove deprecated AdminAPI endpoints --- lib/pleroma/web/router.ex | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a33b5ddd7..d230788d0 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -154,22 +154,12 @@ defmodule Pleroma.Web.Router do post("/users/follow", AdminAPIController, :user_follow) post("/users/unfollow", AdminAPIController, :user_unfollow) - # TODO: to be removed at version 1.0 - delete("/user", AdminAPIController, :user_delete) - post("/user", AdminAPIController, :user_create) - delete("/users", AdminAPIController, :user_delete) post("/users", AdminAPIController, :user_create) patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation) put("/users/tag", AdminAPIController, :tag_users) delete("/users/tag", AdminAPIController, :untag_users) - # TODO: to be removed at version 1.0 - get("/permission_group/:nickname", AdminAPIController, :right_get) - get("/permission_group/:nickname/:permission_group", AdminAPIController, :right_get) - post("/permission_group/:nickname/:permission_group", AdminAPIController, :right_add) - delete("/permission_group/:nickname/:permission_group", AdminAPIController, :right_delete) - get("/users/:nickname/permission_group", AdminAPIController, :right_get) get("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_get) post("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_add) @@ -190,9 +180,6 @@ defmodule Pleroma.Web.Router do post("/users/revoke_invite", AdminAPIController, :revoke_invite) post("/users/email_invite", AdminAPIController, :email_invite) - # TODO: to be removed at version 1.0 - get("/password_reset", AdminAPIController, :get_password_reset) - get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset) get("/users", AdminAPIController, :list_users) From 0afaf9664030956567bdc3dba745b9bbc326bad5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 23 Jul 2019 19:49:36 +0000 Subject: [PATCH 06/12] update mix.lock --- mix.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mix.lock b/mix.lock index 45142ba8f..5f20878d3 100644 --- a/mix.lock +++ b/mix.lock @@ -56,22 +56,22 @@ "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "hexpm"}, - "phoenix": {:hex, :phoenix, "1.4.8", "c72dc3adeb49c70eb963a0ea24f7a064ec1588e651e84e1b7ad5ed8253c0b4a2", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, + "phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, "phoenix_html": {:hex, :phoenix_html, "2.13.1", "fa8f034b5328e2dfa0e4131b5569379003f34bc1fafdaa84985b0b9d2f12e68b", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"}, "pleroma_job_queue": {:hex, :pleroma_job_queue, "0.2.0", "879e660aa1cebe8dc6f0aaaa6aa48b4875e89cd961d4a585fd128e0773b31a18", [:mix], [], "hexpm"}, "plug": {:hex, :plug, "1.8.2", "0bcce1daa420f189a6491f3940cc77ea7fb1919761175c9c3b59800d897440fc", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"}, - "plug_cowboy": {:hex, :plug_cowboy, "2.0.2", "6055f16868cc4882b24b6e1d63d2bada94fb4978413377a3b32ac16c18dffba2", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"}, "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"}, "postgrex": {:hex, :postgrex, "0.14.3", "5754dee2fdf6e9e508cbf49ab138df964278700b764177e8f3871e658b345a1e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, - "prometheus": {:hex, :prometheus, "4.2.2", "a830e77b79dc6d28183f4db050a7cac926a6c58f1872f9ef94a35cd989aceef8", [:mix, :rebar3], [], "hexpm"}, + "prometheus": {:hex, :prometheus, "4.4.1", "1e96073b3ed7788053768fea779cbc896ddc3bdd9ba60687f2ad50b252ac87d6", [:mix, :rebar3], [], "hexpm"}, "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.1", "6c768ea9654de871e5b32fab2eac348467b3021604ebebbcbd8bcbe806a65ed5", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"}, "prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"}, - "prometheus_phoenix": {:hex, :prometheus_phoenix, "1.2.1", "964a74dfbc055f781d3a75631e06ce3816a2913976d1df7830283aa3118a797a", [:mix], [{:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"}, + "prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"}, "prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"}, "prometheus_process_collector": {:hex, :prometheus_process_collector, "1.4.0", "6dbd39e3165b9ef1c94a7a820e9ffe08479f949dcdd431ed4aaea7b250eebfde", [:rebar3], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"}, "quack": {:hex, :quack, "0.1.1", "cca7b4da1a233757fdb44b3334fce80c94785b3ad5a602053b7a002b5a8967bf", [:mix], [{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm"}, From 03471151d6089e318abaf5265d42ffedf7a5b902 Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Wed, 24 Jul 2019 01:50:09 +0300 Subject: [PATCH 07/12] AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses) --- CHANGELOG.md | 1 + docs/api/admin_api.md | 1 + lib/pleroma/web/activity_pub/activity_pub.ex | 23 +++++++++++++----- .../web/admin_api/admin_api_controller.ex | 5 +++- .../admin_api/admin_api_controller_test.exs | 24 +++++++++++++++++++ 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a0f2cdc9..6c9381b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Federation: Return 403 errors when trying to request pages from a user's follower/following collections if they have `hide_followers`/`hide_follows` set - NodeInfo: Return `skipThreadContainment` in `metadata` for the `skip_thread_containment` option - Mastodon API: Unsubscribe followers when they unfollow a user +- AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses) ### Fixed - Not being able to pin unlisted posts diff --git a/docs/api/admin_api.md b/docs/api/admin_api.md index 3880af218..98968c1a6 100644 --- a/docs/api/admin_api.md +++ b/docs/api/admin_api.md @@ -195,6 +195,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - Params: - `nickname` or `id` - *optional* `page_size`: number of statuses to return (default is `20`) + - *optional* `godmode`: `true`/`false` – allows to see private statuses - Response: - On failure: `Not found` - On success: JSON array of user's latest statuses diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 31397b09f..a42c50875 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -631,17 +631,28 @@ def fetch_user_activities(user, reading_user, params \\ %{}) do |> Map.put("pinned_activity_ids", user.info.pinned_activities) recipients = - if reading_user do - ["https://www.w3.org/ns/activitystreams#Public"] ++ - [reading_user.ap_id | reading_user.following] - else - ["https://www.w3.org/ns/activitystreams#Public"] - end + user_activities_recipients(%{ + "godmode" => params["godmode"], + "reading_user" => reading_user + }) fetch_activities(recipients, params) |> Enum.reverse() end + defp user_activities_recipients(%{"godmode" => true}) do + [] + end + + defp user_activities_recipients(%{"reading_user" => reading_user}) do + if reading_user do + ["https://www.w3.org/ns/activitystreams#Public"] ++ + [reading_user.ap_id | reading_user.following] + else + ["https://www.w3.org/ns/activitystreams#Public"] + end + end + defp restrict_since(query, %{"since_id" => ""}), do: query defp restrict_since(query, %{"since_id" => since_id}) do diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 64ad7e8e2..5c64bb81b 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -83,12 +83,15 @@ def user_show(conn, %{"nickname" => nickname}) do end def list_user_statuses(conn, %{"nickname" => nickname} = params) do + godmode = params["godmode"] == "true" || params["godmode"] == true + with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do {_, page_size} = page_params(params) activities = ActivityPub.fetch_user_activities(user, nil, %{ - "limit" => page_size + "limit" => page_size, + "godmode" => godmode }) conn diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 25e062878..20d5268a2 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -1934,6 +1934,30 @@ test "renders user's statuses with a limit", %{conn: conn, user: user} do assert json_response(conn, 200) |> length() == 2 end + + test "doesn't return private statuses by default", %{conn: conn, user: user} do + {:ok, _private_status} = + CommonAPI.post(user, %{"status" => "private", "visibility" => "private"}) + + {:ok, _public_status} = + CommonAPI.post(user, %{"status" => "public", "visibility" => "public"}) + + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses") + + assert json_response(conn, 200) |> length() == 4 + end + + test "returns private statuses with godmode on", %{conn: conn, user: user} do + {:ok, _private_status} = + CommonAPI.post(user, %{"status" => "private", "visibility" => "private"}) + + {:ok, _public_status} = + CommonAPI.post(user, %{"status" => "public", "visibility" => "public"}) + + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true") + + assert json_response(conn, 200) |> length() == 5 + end end end From d3bdb8e7049ebda19593d064b308b40ddb6ab4d1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 23 Jul 2019 22:58:31 +0000 Subject: [PATCH 08/12] rich media: parser: splice the given URL into the result --- CHANGELOG.md | 1 + lib/pleroma/web/rich_media/parser.ex | 1 + .../mastodon_api_controller_test.exs | 16 ++++++++-------- test/web/rich_media/parser_test.exs | 12 +++++++----- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4043b1edf..7c2b1d151 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - ActivityPub C2S: follower/following collection pages being inaccessible even when authentifucated if `hide_followers`/ `hide_follows` was set - Existing user id not being preserved on insert conflict - Rich Media: Parser failing when no TTL can be found by image TTL setters +- Rich Media: The crawled URL is now spliced into the rich media data. - ActivityPub S2S: sharedInbox usage has been mostly aligned with the rules in the AP specification. ### Added diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index 185156375..f5f9e358c 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -82,6 +82,7 @@ defp parse_url(url) do html |> maybe_parse() + |> Map.put(:url, url) |> clean_parsed_data() |> check_parsed_data() rescue diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index bc3213e0c..ce2e44499 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -2815,11 +2815,11 @@ test "returns rich-media card", %{conn: conn, user: user} do card_data = %{ "image" => "http://ia.media-imdb.com/images/rock.jpg", - "provider_name" => "www.imdb.com", - "provider_url" => "http://www.imdb.com", + "provider_name" => "example.com", + "provider_url" => "https://example.com", "title" => "The Rock", "type" => "link", - "url" => "http://www.imdb.com/title/tt0117500/", + "url" => "https://example.com/ogp", "description" => "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", "pleroma" => %{ @@ -2827,7 +2827,7 @@ test "returns rich-media card", %{conn: conn, user: user} do "image" => "http://ia.media-imdb.com/images/rock.jpg", "title" => "The Rock", "type" => "video.movie", - "url" => "http://www.imdb.com/title/tt0117500/", + "url" => "https://example.com/ogp", "description" => "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer." } @@ -2868,14 +2868,14 @@ test "replaces missing description with an empty string", %{conn: conn, user: us "title" => "Pleroma", "description" => "", "image" => nil, - "provider_name" => "pleroma.social", - "provider_url" => "https://pleroma.social", - "url" => "https://pleroma.social/", + "provider_name" => "example.com", + "provider_url" => "https://example.com", + "url" => "https://example.com/ogp-missing-data", "pleroma" => %{ "opengraph" => %{ "title" => "Pleroma", "type" => "website", - "url" => "https://pleroma.social/" + "url" => "https://example.com/ogp-missing-data" } } } diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs index 19c19e895..b75bdf96f 100644 --- a/test/web/rich_media/parser_test.exs +++ b/test/web/rich_media/parser_test.exs @@ -59,7 +59,8 @@ test "returns error when no metadata present" do test "doesn't just add a title" do assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/non-ogp") == - {:error, "Found metadata was invalid or incomplete: %{}"} + {:error, + "Found metadata was invalid or incomplete: %{url: \"http://example.com/non-ogp\"}"} end test "parses ogp" do @@ -71,7 +72,7 @@ test "parses ogp" do description: "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", type: "video.movie", - url: "http://www.imdb.com/title/tt0117500/" + url: "http://example.com/ogp" }} end @@ -84,7 +85,7 @@ test "falls back to when ogp:title is missing" do description: "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", type: "video.movie", - url: "http://www.imdb.com/title/tt0117500/" + url: "http://example.com/ogp-missing-title" }} end @@ -96,7 +97,8 @@ test "parses twitter card" do site: "@flickr", image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg", title: "Small Island Developing States Photo Submission", - description: "View the album on Flickr." + description: "View the album on Flickr.", + url: "http://example.com/twitter-card" }} end @@ -120,7 +122,7 @@ test "parses OEmbed" do thumbnail_width: 150, title: "Bacon Lollys", type: "photo", - url: "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg", + url: "http://example.com/oembed", version: "1.0", web_page: "https://www.flickr.com/photos/bees/2362225867/", web_page_short_url: "https://flic.kr/p/4AK2sc", From 9638da43e9f189e1ac46ab8857dd37f907c4d347 Mon Sep 17 00:00:00 2001 From: aries <aries@asterism.xyz> Date: Wed, 24 Jul 2019 01:50:56 +0000 Subject: [PATCH 09/12] Add text about gitignore --- docs/config/static_dir.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/config/static_dir.md b/docs/config/static_dir.md index 1326a5a17..5fb38c3de 100644 --- a/docs/config/static_dir.md +++ b/docs/config/static_dir.md @@ -13,6 +13,8 @@ Alternatively, you can overwrite this value in your configuration to use a diffe This document is written assuming `instance/static/`. +Or, if you want to manage your custom file in git repository, basically remove the `instance/` entry from `.gitignore`. + ## robots.txt By default, the `robots.txt` that ships in `priv/static/` is permissive. It allows well-behaved search engines to index all of your instance's URIs. From 4af4f6166bd04b5a302856034fdda94dd61045ed Mon Sep 17 00:00:00 2001 From: Sadposter <hannah+pleroma@coffee-and-dreams.uk> Date: Wed, 24 Jul 2019 11:09:06 +0100 Subject: [PATCH 10/12] honour domain blocks on streaming notifications --- lib/pleroma/web/streamer.ex | 3 +++ test/web/streamer_test.exs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 86e2dc4dd..d233d2a41 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -234,10 +234,13 @@ defp should_send?(%User{} = user, %Activity{} = item) do blocks = user.info.blocks || [] mutes = user.info.mutes || [] reblog_mutes = user.info.muted_reblogs || [] + domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.info.domain_blocks) + %{host: host} = URI.parse(parent.data["actor"]) with parent when not is_nil(parent) <- Object.normalize(item), true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), + false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host), true <- thread_containment(item, user) do true else diff --git a/test/web/streamer_test.exs b/test/web/streamer_test.exs index 8f56e7486..95d5e5d58 100644 --- a/test/web/streamer_test.exs +++ b/test/web/streamer_test.exs @@ -103,6 +103,24 @@ test "it doesn't send notify to the 'user:notification' stream when a thread is Streamer.stream("user:notification", notif) Task.await(task) end + + test "it doesn't send notify to the 'user:notification' stream' when a domain is blocked", %{ + user: user + } do + user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"}) + task = Task.async(fn -> refute_receive {:text, _}, 4_000 end) + + Streamer.add_socket( + "user:notification", + %{transport_pid: task.pid, assigns: %{user: user}} + ) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) + {:ok, user} = User.block_domain(user, "hecking-lewd-place.com") + {:ok, notif, _} = CommonAPI.favorite(activity.id, user2) + Streamer.stream("user:notification", notif) + Task.await(task) + end end test "it sends to public" do From 48bd3be9cb9b378dfde78e769e2f00ed77129ab9 Mon Sep 17 00:00:00 2001 From: Sadposter <hannah+pleroma@coffee-and-dreams.uk> Date: Wed, 24 Jul 2019 11:11:33 +0100 Subject: [PATCH 11/12] move domain block check to with block --- lib/pleroma/web/streamer.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index d233d2a41..e4259e869 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -235,11 +235,11 @@ defp should_send?(%User{} = user, %Activity{} = item) do mutes = user.info.mutes || [] reblog_mutes = user.info.muted_reblogs || [] domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.info.domain_blocks) - %{host: host} = URI.parse(parent.data["actor"]) with parent when not is_nil(parent) <- Object.normalize(item), true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), + %{host: host} <- URI.parse(parent.data["actor"]), false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host), true <- thread_containment(item, user) do true From f5d574f4ed9aa997a47d03f02adeb701d96f6789 Mon Sep 17 00:00:00 2001 From: sadposter <hannah+pleroma@coffee-and-dreams.uk> Date: Wed, 24 Jul 2019 11:35:16 +0100 Subject: [PATCH 12/12] check both item and parent domain blocks --- lib/pleroma/web/streamer.ex | 6 ++++-- test/web/streamer_test.exs | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index e4259e869..9ee331030 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -239,8 +239,10 @@ defp should_send?(%User{} = user, %Activity{} = item) do with parent when not is_nil(parent) <- Object.normalize(item), true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), - %{host: host} <- URI.parse(parent.data["actor"]), - false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host), + %{host: item_host} <- URI.parse(item.actor), + %{host: parent_host} <- URI.parse(parent.data["actor"]), + false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, item_host), + false <- Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, parent_host), true <- thread_containment(item, user) do true else diff --git a/test/web/streamer_test.exs b/test/web/streamer_test.exs index 95d5e5d58..d47b37efb 100644 --- a/test/web/streamer_test.exs +++ b/test/web/streamer_test.exs @@ -115,9 +115,10 @@ test "it doesn't send notify to the 'user:notification' stream' when a domain is %{transport_pid: task.pid, assigns: %{user: user}} ) - {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) {:ok, user} = User.block_domain(user, "hecking-lewd-place.com") + {:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"}) {:ok, notif, _} = CommonAPI.favorite(activity.id, user2) + Streamer.stream("user:notification", notif) Task.await(task) end