Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop

This commit is contained in:
sadposter 2019-07-24 12:45:16 +01:00
commit d6dbcc03ea
14 changed files with 204 additions and 59 deletions

View file

@ -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 - 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 - NodeInfo: Return `skipThreadContainment` in `metadata` for the `skip_thread_containment` option
- Mastodon API: Unsubscribe followers when they unfollow a user - Mastodon API: Unsubscribe followers when they unfollow a user
- AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses)
### Fixed ### Fixed
- Not being able to pin unlisted posts - Not being able to pin unlisted posts
@ -23,6 +24,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 - 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 - 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: 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. - ActivityPub S2S: sharedInbox usage has been mostly aligned with the rules in the AP specification.
### Added ### Added
@ -53,6 +55,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Twitter API: added rate limit for `/api/account/password_reset` endpoint. - Twitter API: added rate limit for `/api/account/password_reset` endpoint.
- ActivityPub: Add an internal service actor for fetching ActivityPub objects. - ActivityPub: Add an internal service actor for fetching ActivityPub objects.
- ActivityPub: Optional signing of ActivityPub object fetches. - ActivityPub: Optional signing of ActivityPub object fetches.
- Admin API: Endpoint for fetching latest user's statuses
### Changed ### Changed
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text - Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text

View file

@ -187,6 +187,19 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
- On failure: `Not found` - On failure: `Not found`
- On success: JSON of the user - 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`)
- *optional* `godmode`: `true`/`false` allows to see private statuses
- Response:
- On failure: `Not found`
- On success: JSON array of user's latest statuses
## `/api/pleroma/admin/relay` ## `/api/pleroma/admin/relay`
### Follow a Relay ### Follow a Relay

View file

@ -1,35 +1,12 @@
# Small customizations # 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). ## Theme
# 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
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. 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 ## Message Visibility
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
To enable message visibility options when posting like in the Mastodon frontend, set To enable message visibility options when posting like in the Mastodon frontend, set
`scope_options_enabled` to `true` in `config/dev.secret.exs`. `scope_options_enabled` to `true` in `config/dev.secret.exs`.

View file

@ -7,7 +7,13 @@ config :pleroma, :instance,
static_dir: "instance/static/", 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/`.
Or, if you want to manage your custom file in git repository, basically remove the `instance/` entry from `.gitignore`.
## robots.txt ## robots.txt
@ -18,3 +24,46 @@ If you want to generate a restrictive `robots.txt`, you can run the following mi
``` ```
mix pleroma.robots_txt disallow_all mix pleroma.robots_txt disallow_all
``` ```
## Thumbnail
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)
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 `instance/static/`, and then changing `background` in `config/prod.secret.exs` accordingly.
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, You can change the logo of your instance by uploading it to `instance/static/`.
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 `instance/static/static/terms-of-service.html`.

View file

@ -631,17 +631,28 @@ def fetch_user_activities(user, reading_user, params \\ %{}) do
|> Map.put("pinned_activity_ids", user.info.pinned_activities) |> Map.put("pinned_activity_ids", user.info.pinned_activities)
recipients = recipients =
if reading_user do user_activities_recipients(%{
["https://www.w3.org/ns/activitystreams#Public"] ++ "godmode" => params["godmode"],
[reading_user.ap_id | reading_user.following] "reading_user" => reading_user
else })
["https://www.w3.org/ns/activitystreams#Public"]
end
fetch_activities(recipients, params) fetch_activities(recipients, params)
|> Enum.reverse() |> Enum.reverse()
end 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" => ""}), do: query
defp restrict_since(query, %{"since_id" => since_id}) do defp restrict_since(query, %{"since_id" => since_id}) do

View file

@ -82,6 +82,25 @@ def user_show(conn, %{"nickname" => nickname}) do
end end
end 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,
"godmode" => godmode
})
conn
|> json(StatusView.render("index.json", %{activities: activities, as: :activity}))
else
_ -> {:error, :not_found}
end
end
def user_toggle_activation(conn, %{"nickname" => nickname}) do def user_toggle_activation(conn, %{"nickname" => nickname}) do
user = User.get_cached_by_nickname(nickname) user = User.get_cached_by_nickname(nickname)

View file

@ -82,6 +82,7 @@ defp parse_url(url) do
html html
|> maybe_parse() |> maybe_parse()
|> Map.put(:url, url)
|> clean_parsed_data() |> clean_parsed_data()
|> check_parsed_data() |> check_parsed_data()
rescue rescue

View file

@ -154,22 +154,12 @@ defmodule Pleroma.Web.Router do
post("/users/follow", AdminAPIController, :user_follow) post("/users/follow", AdminAPIController, :user_follow)
post("/users/unfollow", AdminAPIController, :user_unfollow) 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) delete("/users", AdminAPIController, :user_delete)
post("/users", AdminAPIController, :user_create) post("/users", AdminAPIController, :user_create)
patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation) patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation)
put("/users/tag", AdminAPIController, :tag_users) put("/users/tag", AdminAPIController, :tag_users)
delete("/users/tag", AdminAPIController, :untag_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", AdminAPIController, :right_get)
get("/users/:nickname/permission_group/: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) post("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_add)
@ -190,13 +180,11 @@ defmodule Pleroma.Web.Router do
post("/users/revoke_invite", AdminAPIController, :revoke_invite) post("/users/revoke_invite", AdminAPIController, :revoke_invite)
post("/users/email_invite", AdminAPIController, :email_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/:nickname/password_reset", AdminAPIController, :get_password_reset)
get("/users", AdminAPIController, :list_users) get("/users", AdminAPIController, :list_users)
get("/users/:nickname", AdminAPIController, :user_show) get("/users/:nickname", AdminAPIController, :user_show)
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
get("/reports", AdminAPIController, :list_reports) get("/reports", AdminAPIController, :list_reports)
get("/reports/:id", AdminAPIController, :report_show) get("/reports/:id", AdminAPIController, :report_show)

View file

@ -234,10 +234,15 @@ defp should_send?(%User{} = user, %Activity{} = item) do
blocks = user.info.blocks || [] blocks = user.info.blocks || []
mutes = user.info.mutes || [] mutes = user.info.mutes || []
reblog_mutes = user.info.muted_reblogs || [] reblog_mutes = user.info.muted_reblogs || []
domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.info.domain_blocks)
with parent when not is_nil(parent) <- Object.normalize(item), 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, reblog_mutes], &(item.actor not in &1)),
true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)), true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)),
%{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 <- thread_containment(item, user) do
true true
else else

View file

@ -118,6 +118,7 @@ def direct_note_activity_factory do
def note_activity_factory(attrs \\ %{}) do def note_activity_factory(attrs \\ %{}) do
user = attrs[:user] || insert(:user) user = attrs[:user] || insert(:user)
note = attrs[:note] || insert(:note, user: user) note = attrs[:note] || insert(:note, user: user)
data_attrs = attrs[:data_attrs] || %{} data_attrs = attrs[:data_attrs] || %{}
attrs = Map.drop(attrs, [:user, :note, :data_attrs]) attrs = Map.drop(attrs, [:user, :note, :data_attrs])

View file

@ -1915,6 +1915,63 @@ test "queues key as atom", %{conn: conn} do
} }
end end
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
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 end
# Needed for testing # Needed for testing

View file

@ -2815,11 +2815,11 @@ test "returns rich-media card", %{conn: conn, user: user} do
card_data = %{ card_data = %{
"image" => "http://ia.media-imdb.com/images/rock.jpg", "image" => "http://ia.media-imdb.com/images/rock.jpg",
"provider_name" => "www.imdb.com", "provider_name" => "example.com",
"provider_url" => "http://www.imdb.com", "provider_url" => "https://example.com",
"title" => "The Rock", "title" => "The Rock",
"type" => "link", "type" => "link",
"url" => "http://www.imdb.com/title/tt0117500/", "url" => "https://example.com/ogp",
"description" => "description" =>
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
"pleroma" => %{ "pleroma" => %{
@ -2827,7 +2827,7 @@ test "returns rich-media card", %{conn: conn, user: user} do
"image" => "http://ia.media-imdb.com/images/rock.jpg", "image" => "http://ia.media-imdb.com/images/rock.jpg",
"title" => "The Rock", "title" => "The Rock",
"type" => "video.movie", "type" => "video.movie",
"url" => "http://www.imdb.com/title/tt0117500/", "url" => "https://example.com/ogp",
"description" => "description" =>
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer." "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", "title" => "Pleroma",
"description" => "", "description" => "",
"image" => nil, "image" => nil,
"provider_name" => "pleroma.social", "provider_name" => "example.com",
"provider_url" => "https://pleroma.social", "provider_url" => "https://example.com",
"url" => "https://pleroma.social/", "url" => "https://example.com/ogp-missing-data",
"pleroma" => %{ "pleroma" => %{
"opengraph" => %{ "opengraph" => %{
"title" => "Pleroma", "title" => "Pleroma",
"type" => "website", "type" => "website",
"url" => "https://pleroma.social/" "url" => "https://example.com/ogp-missing-data"
} }
} }
} }

View file

@ -59,7 +59,8 @@ test "returns error when no metadata present" do
test "doesn't just add a title" do test "doesn't just add a title" do
assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/non-ogp") == 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 end
test "parses ogp" do test "parses ogp" do
@ -71,7 +72,7 @@ test "parses ogp" do
description: description:
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
type: "video.movie", type: "video.movie",
url: "http://www.imdb.com/title/tt0117500/" url: "http://example.com/ogp"
}} }}
end end
@ -84,7 +85,7 @@ test "falls back to <title> when ogp:title is missing" do
description: description:
"Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
type: "video.movie", type: "video.movie",
url: "http://www.imdb.com/title/tt0117500/" url: "http://example.com/ogp-missing-title"
}} }}
end end
@ -96,7 +97,8 @@ test "parses twitter card" do
site: "@flickr", site: "@flickr",
image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg", image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg",
title: "Small Island Developing States Photo Submission", 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 end
@ -120,7 +122,7 @@ test "parses OEmbed" do
thumbnail_width: 150, thumbnail_width: 150,
title: "Bacon Lollys", title: "Bacon Lollys",
type: "photo", type: "photo",
url: "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg", url: "http://example.com/oembed",
version: "1.0", version: "1.0",
web_page: "https://www.flickr.com/photos/bees/2362225867/", web_page: "https://www.flickr.com/photos/bees/2362225867/",
web_page_short_url: "https://flic.kr/p/4AK2sc", web_page_short_url: "https://flic.kr/p/4AK2sc",

View file

@ -103,6 +103,25 @@ test "it doesn't send notify to the 'user:notification' stream when a thread is
Streamer.stream("user:notification", notif) Streamer.stream("user:notification", notif)
Task.await(task) Task.await(task)
end 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, 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
end end
test "it sends to public" do test "it sends to public" do