Extract RSS Feed functionality from OStatus

This commit is contained in:
Sergey Suprunenko 2019-10-07 12:20:41 +00:00 committed by kaniini
parent 5c32e6ee91
commit 4b3f77a99f
17 changed files with 513 additions and 251 deletions

View File

@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Add `pleroma.unread_conversation_count` to the Account entity - Mastodon API: Add `pleroma.unread_conversation_count` to the Account entity
- OAuth: support for hierarchical permissions / [Mastodon 2.4.3 OAuth permissions](https://docs.joinmastodon.org/api/permissions/) - OAuth: support for hierarchical permissions / [Mastodon 2.4.3 OAuth permissions](https://docs.joinmastodon.org/api/permissions/)
- Authentication: Added rate limit for password-authorized actions / login existence checks - Authentication: Added rate limit for password-authorized actions / login existence checks
- Metadata Link: Atom syndication Feed
### Changed ### Changed
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7) - **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
@ -25,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`) - Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
- Admin API: Return link alongside with token on password reset - Admin API: Return link alongside with token on password reset
- MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities - MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities
- OStatus: Extract RSS functionality
### Fixed ### Fixed
- Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`) - Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)

View File

@ -409,7 +409,8 @@
providers: [ providers: [
Pleroma.Web.Metadata.Providers.OpenGraph, Pleroma.Web.Metadata.Providers.OpenGraph,
Pleroma.Web.Metadata.Providers.TwitterCard, Pleroma.Web.Metadata.Providers.TwitterCard,
Pleroma.Web.Metadata.Providers.RelMe Pleroma.Web.Metadata.Providers.RelMe,
Pleroma.Web.Metadata.Providers.Feed
], ],
unfurl_nsfw: false unfurl_nsfw: false

View File

@ -475,6 +475,7 @@ config :pleroma, :workers,
* Pleroma.Web.Metadata.Providers.OpenGraph * Pleroma.Web.Metadata.Providers.OpenGraph
* Pleroma.Web.Metadata.Providers.TwitterCard * Pleroma.Web.Metadata.Providers.TwitterCard
* Pleroma.Web.Metadata.Providers.RelMe - add links from user bio with rel=me into the `<header>` as `<link rel=me>` * Pleroma.Web.Metadata.Providers.RelMe - add links from user bio with rel=me into the `<header>` as `<link rel=me>`
* Pleroma.Web.Metadata.Providers.Feed - add a link to a user's Atom feed into the `<header>` as `<link rel=alternate>`
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews * `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews
## :rich_media ## :rich_media

View File

@ -17,7 +17,7 @@ defp instance_notify_email do
end end
defp user_url(user) do defp user_url(user) do
Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.id) Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, user.id)
end end
def report(to, reporter, account, statuses, comment) do def report(to, reporter, account, statuses, comment) do

View File

@ -0,0 +1,63 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Feed.FeedController do
use Pleroma.Web, :controller
alias Fallback.RedirectController
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.ActivityPubController
plug(Pleroma.Plugs.SetFormatPlug when action in [:feed_redirect])
action_fallback(:errors)
def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
RedirectController.redirector_with_meta(conn, %{user: user})
end
end
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
when format in ["json", "activity+json"] do
ActivityPubController.call(conn, :user)
end
def feed_redirect(conn, %{"nickname" => nickname}) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
redirect(conn, external: "#{feed_url(conn, :feed, user.nickname)}.atom")
end
end
def feed(conn, %{"nickname" => nickname} = params) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
query_params =
params
|> Map.take(["max_id"])
|> Map.put("type", ["Create"])
|> Map.put("whole_db", true)
|> Map.put("actor_id", user.ap_id)
activities =
query_params
|> ActivityPub.fetch_public_activities()
|> Enum.reverse()
conn
|> put_resp_content_type("application/atom+xml")
|> render("feed.xml", user: user, activities: activities)
end
end
def errors(conn, {:error, :not_found}) do
render_error(conn, :not_found, "Not found")
end
def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
def errors(conn, _) do
render_error(conn, :internal_server_error, "Something went wrong")
end
end

View File

@ -0,0 +1,77 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Feed.FeedView do
use Phoenix.HTML
use Pleroma.Web, :view
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.MediaProxy
require Pleroma.Constants
def most_recent_update(activities, user) do
(List.first(activities) || user).updated_at
|> NaiveDateTime.to_iso8601()
end
def logo(user) do
user
|> User.avatar_url()
|> MediaProxy.url()
end
def last_activity(activities) do
List.last(activities)
end
def activity_object(activity) do
Object.normalize(activity)
end
def activity_object_data(activity) do
activity
|> activity_object()
|> Map.get(:data)
end
def activity_content(activity) do
content = activity_object_data(activity)["content"]
content
|> String.replace(~r/[\n\r]/, "")
|> escape()
end
def activity_context(activity) do
activity.data["context"]
end
def attachment_href(attachment) do
attachment["url"]
|> hd()
|> Map.get("href")
end
def attachment_type(attachment) do
attachment["url"]
|> hd()
|> Map.get("mediaType")
end
def get_href(id) do
with %Object{data: %{"external_url" => external_url}} <- Object.get_cached_by_ap_id(id) do
external_url
else
_e -> id
end
end
def escape(html) do
html
|> html_escape()
|> safe_to_string()
end
end

View File

@ -0,0 +1,23 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Metadata.Providers.Feed do
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Metadata.Providers.Provider
alias Pleroma.Web.Router.Helpers
@behaviour Provider
@impl Provider
def build_tags(%{user: user}) do
[
{:link,
[
rel: "alternate",
type: "application/atom+xml",
href: Helpers.feed_path(Endpoint, :feed, user.nickname) <> ".atom"
], []}
]
end
end

View File

@ -9,16 +9,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPubController
alias Pleroma.Web.ActivityPub.ObjectView alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
alias Pleroma.Web.Metadata.PlayerView alias Pleroma.Web.Metadata.PlayerView
alias Pleroma.Web.OStatus
alias Pleroma.Web.OStatus.ActivityRepresenter alias Pleroma.Web.OStatus.ActivityRepresenter
alias Pleroma.Web.OStatus.FeedRepresenter
alias Pleroma.Web.Router alias Pleroma.Web.Router
alias Pleroma.Web.XML alias Pleroma.Web.XML
@ -31,49 +28,11 @@ defmodule Pleroma.Web.OStatus.OStatusController do
plug( plug(
Pleroma.Plugs.SetFormatPlug Pleroma.Plugs.SetFormatPlug
when action in [:feed_redirect, :object, :activity, :notice] when action in [:object, :activity, :notice]
) )
action_fallback(:errors) action_fallback(:errors)
def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
RedirectController.redirector_with_meta(conn, %{user: user})
end
end
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
when format in ["json", "activity+json"] do
ActivityPubController.call(conn, :user)
end
def feed_redirect(conn, %{"nickname" => nickname}) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
redirect(conn, external: OStatus.feed_path(user))
end
end
def feed(conn, %{"nickname" => nickname} = params) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
activities =
params
|> Map.take(["max_id"])
|> Map.merge(%{"whole_db" => true, "actor_id" => user.ap_id})
|> ActivityPub.fetch_public_activities()
|> Enum.reverse()
response =
user
|> FeedRepresenter.to_simple_form(activities, [user])
|> :xmerl.export_simple(:xmerl_xml)
|> to_string
conn
|> put_resp_content_type("application/atom+xml")
|> send_resp(200, response)
end
end
defp decode_or_retry(body) do defp decode_or_retry(body) do
with {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body), with {:ok, magic_key} <- Pleroma.Web.Salmon.fetch_magic_key(body),
{:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do {:ok, doc} <- Pleroma.Web.Salmon.decode_and_validate(magic_key, body) do

View File

@ -495,8 +495,9 @@ defmodule Pleroma.Web.Router do
get("/activities/:uuid", OStatus.OStatusController, :activity) get("/activities/:uuid", OStatus.OStatusController, :activity)
get("/notice/:id", OStatus.OStatusController, :notice) get("/notice/:id", OStatus.OStatusController, :notice)
get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player) get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player)
get("/users/:nickname/feed", OStatus.OStatusController, :feed)
get("/users/:nickname", OStatus.OStatusController, :feed_redirect) get("/users/:nickname/feed", Feed.FeedController, :feed)
get("/users/:nickname", Feed.FeedController, :feed_redirect)
post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming) post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming)
post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request) post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request)

View File

@ -0,0 +1,48 @@
<entry>
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<id><%= @data["id"] %></id>
<title><%= "New note by #{@user.nickname}" %></title>
<content type="html"><%= activity_content(@activity) %></content>
<published><%= @data["published"] %></published>
<updated><%= @data["published"] %></updated>
<ostatus:conversation ref="<%= activity_context(@activity) %>"><%= activity_context(@activity) %></ostatus:conversation>
<link ref="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
<%= if @data["summary"] do %>
<summary><%= @data["summary"] %></summary>
<% end %>
<%= if @activity.local do %>
<link type="application/atom+xml" href='<%= @data["id"] %>' rel="self"/>
<link type="text/html" href='<%= @data["id"] %>' rel="alternate"/>
<% else %>
<link type="text/html" href='<%= @data["external_url"] %>' rel="alternate"/>
<% end %>
<%= for tag <- @data["tag"] || [] do %>
<category term="<%= tag %>"></category>
<% end %>
<%= for attachment <- @data["attachment"] || [] do %>
<link rel="enclosure" href="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>"/>
<% end %>
<%= if @data["inReplyTo"] do %>
<thr:in-reply-to ref='<%= @data["inReplyTo"] %>' href='<%= get_href(@data["inReplyTo"]) %>'/>
<% end %>
<%= for id <- @activity.recipients do %>
<%= if id == Pleroma.Constants.as_public() do %>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
<% else %>
<%= unless Regex.match?(~r/^#{Pleroma.Web.base_url()}.+followers$/, id) do %>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="<%= id %>"/>
<% end %>
<% end %>
<% end %>
<%= for {emoji, file} <- @data["emoji"] || %{} do %>
<link name="<%= emoji %>" rel="emoji" href="<%= file %>"/>
<% end %>
</entry>

View File

@ -0,0 +1,17 @@
<author>
<id><%= @user.ap_id %></id>
<activity:object>http://activitystrea.ms/schema/1.0/person</activity:object>
<uri><%= @user.ap_id %></uri>
<poco:preferredUsername><%= @user.nickname %></poco:preferredUsername>
<poco:displayName><%= @user.name %></poco:displayName>
<poco:note><%= escape(@user.bio) %></poco:note>
<summary><%= escape(@user.bio) %></summary>
<name><%= @user.nickname %></name>
<link rel="avatar" href="<%= User.avatar_url(@user) %>"/>
<%= if User.banner_url(@user) do %>
<link rel="header" href="<%= User.banner_url(@user) %>"/>
<% end %>
<%= if @user.local do %>
<ap_enabled>true</ap_enabled>
<% end %>
</author>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<feed
xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:activity="http://activitystrea.ms/spec/1.0/"
xmlns:poco="http://portablecontacts.net/spec/1.0"
xmlns:ostatus="http://ostatus.org/schema/1.0">
<id><%= feed_url(@conn, :feed, @user.nickname) <> ".atom" %></id>
<title><%= @user.nickname <> "'s timeline" %></title>
<updated><%= most_recent_update(@activities, @user) %></updated>
<logo><%= logo(@user) %></logo>
<link rel="hub" href="<%= websub_url(@conn, :websub_subscription_request, @user.nickname) %>"/>
<link rel="salmon" href="<%= o_status_url(@conn, :salmon_incoming, @user.nickname) %>"/>
<link rel="self" href="<%= '#{feed_url(@conn, :feed, @user.nickname)}.atom' %>" type="application/atom+xml"/>
<%= render @view_module, "_author.xml", assigns %>
<%= if last_activity(@activities) do %>
<link rel="next" href="<%= '#{feed_url(@conn, :feed, @user.nickname)}.atom?max_id=#{last_activity(@activities).id}' %>" type="application/atom+xml"/>
<% end %>
<%= for activity <- @activities do %>
<%= render @view_module, "_activity.xml", Map.merge(assigns, %{activity: activity, data: activity_object_data(activity)}) %>
<% end %>
</feed>

View File

@ -19,8 +19,8 @@ test "build report email" do
AdminEmail.report(to_user, reporter, account, [%{name: "Test", id: "12"}], "Test comment") AdminEmail.report(to_user, reporter, account, [%{name: "Test", id: "12"}], "Test comment")
status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, "12") status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, "12")
reporter_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, reporter.id) reporter_url = Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, reporter.id)
account_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, account.id) account_url = Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, account.id)
assert res.to == [{to_user.name, to_user.email}] assert res.to == [{to_user.name, to_user.email}]
assert res.from == {config[:name], config[:notify_email]} assert res.from == {config[:name], config[:notify_email]}

View File

@ -515,7 +515,7 @@ test "returns an ap_id for a user" do
user = insert(:user) user = insert(:user)
assert User.ap_id(user) == assert User.ap_id(user) ==
Pleroma.Web.Router.Helpers.o_status_url( Pleroma.Web.Router.Helpers.feed_url(
Pleroma.Web.Endpoint, Pleroma.Web.Endpoint,
:feed_redirect, :feed_redirect,
user.nickname user.nickname
@ -526,7 +526,7 @@ test "returns an ap_followers link for a user" do
user = insert(:user) user = insert(:user)
assert User.ap_followers(user) == assert User.ap_followers(user) ==
Pleroma.Web.Router.Helpers.o_status_url( Pleroma.Web.Router.Helpers.feed_url(
Pleroma.Web.Endpoint, Pleroma.Web.Endpoint,
:feed_redirect, :feed_redirect,
user.nickname user.nickname

View File

@ -0,0 +1,227 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Feed.FeedControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
alias Pleroma.Object
alias Pleroma.User
test "gets a feed", %{conn: conn} do
activity = insert(:note_activity)
note =
insert(:note,
data: %{
"attachment" => [
%{
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}]
}
],
"inReplyTo" => activity.data["id"]
}
)
note_activity = insert(:note_activity, note: note)
object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
conn =
conn
|> put_req_header("content-type", "application/atom+xml")
|> get("/users/#{user.nickname}/feed.atom")
assert response(conn, 200) =~ object.data["content"]
end
test "returns 404 for a missing feed", %{conn: conn} do
conn =
conn
|> put_req_header("content-type", "application/atom+xml")
|> get("/users/nonexisting/feed.atom")
assert response(conn, 404)
end
describe "feed_redirect" do
test "undefined format. it redirects to feed", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> put_req_header("accept", "application/xml")
|> get("/users/#{user.nickname}")
|> response(302)
assert response ==
"<html><body>You are being <a href=\"#{Pleroma.Web.base_url()}/users/#{
user.nickname
}/feed.atom\">redirected</a>.</body></html>"
end
test "undefined format. it returns error when user not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/xml")
|> get("/users/jimm")
|> response(404)
assert response == ~S({"error":"Not found"})
end
test "activity+json format. it redirects on actual feed of user", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> put_req_header("accept", "application/activity+json")
|> get("/users/#{user.nickname}")
|> json_response(200)
assert response["endpoints"] == %{
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
"sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
"uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
}
assert response["@context"] == [
"https://www.w3.org/ns/activitystreams",
"http://localhost:4001/schemas/litepub-0.1.jsonld",
%{"@language" => "und"}
]
assert Map.take(response, [
"followers",
"following",
"id",
"inbox",
"manuallyApprovesFollowers",
"name",
"outbox",
"preferredUsername",
"summary",
"tag",
"type",
"url"
]) == %{
"followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
"following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
"id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
"inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
"manuallyApprovesFollowers" => false,
"name" => user.name,
"outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
"preferredUsername" => user.nickname,
"summary" => user.bio,
"tag" => [],
"type" => "Person",
"url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
}
end
test "activity+json format. it returns error whe use not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/activity+json")
|> get("/users/jimm")
|> json_response(404)
assert response == "Not found"
end
test "json format. it redirects on actual feed of user", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> put_req_header("accept", "application/json")
|> get("/users/#{user.nickname}")
|> json_response(200)
assert response["endpoints"] == %{
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
"sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
"uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
}
assert response["@context"] == [
"https://www.w3.org/ns/activitystreams",
"http://localhost:4001/schemas/litepub-0.1.jsonld",
%{"@language" => "und"}
]
assert Map.take(response, [
"followers",
"following",
"id",
"inbox",
"manuallyApprovesFollowers",
"name",
"outbox",
"preferredUsername",
"summary",
"tag",
"type",
"url"
]) == %{
"followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
"following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
"id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
"inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
"manuallyApprovesFollowers" => false,
"name" => user.name,
"outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
"preferredUsername" => user.nickname,
"summary" => user.bio,
"tag" => [],
"type" => "Person",
"url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
}
end
test "json format. it returns error whe use not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/json")
|> get("/users/jimm")
|> json_response(404)
assert response == "Not found"
end
test "html format. it redirects on actual feed of user", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> get("/users/#{user.nickname}")
|> response(200)
assert response ==
Fallback.RedirectController.redirector_with_meta(
conn,
%{user: user}
).resp_body
end
test "html format. it returns error when user not found", %{conn: conn} do
response =
conn
|> get("/users/jimm")
|> json_response(404)
assert response == %{"error" => "Not found"}
end
end
end

View File

@ -0,0 +1,18 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Metadata.Providers.FeedTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.Metadata.Providers.Feed
test "it renders a link to user's atom feed" do
user = insert(:user, nickname: "lain")
assert Feed.build_tags(%{user: user}) == [
{:link,
[rel: "alternate", type: "application/atom+xml", href: "/users/lain/feed.atom"], []}
]
end
end

View File

@ -72,28 +72,6 @@ test "decodes a salmon with a changed magic key", %{conn: conn} do
end end
end end
test "gets a feed", %{conn: conn} do
note_activity = insert(:note_activity)
object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
conn =
conn
|> put_req_header("content-type", "application/atom+xml")
|> get("/users/#{user.nickname}/feed.atom")
assert response(conn, 200) =~ object.data["content"]
end
test "returns 404 for a missing feed", %{conn: conn} do
conn =
conn
|> put_req_header("content-type", "application/atom+xml")
|> get("/users/nonexisting/feed.atom")
assert response(conn, 404)
end
describe "GET object/2" do describe "GET object/2" do
test "gets an object", %{conn: conn} do test "gets an object", %{conn: conn} do
note_activity = insert(:note_activity) note_activity = insert(:note_activity)
@ -355,185 +333,6 @@ test "404s a nonexisting notice", %{conn: conn} do
end end
end end
describe "feed_redirect" do
test "undefined format. it redirects to feed", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> put_req_header("accept", "application/xml")
|> get("/users/#{user.nickname}")
|> response(302)
assert response ==
"<html><body>You are being <a href=\"#{Pleroma.Web.base_url()}/users/#{
user.nickname
}/feed.atom\">redirected</a>.</body></html>"
end
test "undefined format. it returns error when user not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/xml")
|> get("/users/jimm")
|> response(404)
assert response == ~S({"error":"Not found"})
end
test "activity+json format. it redirects on actual feed of user", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> put_req_header("accept", "application/activity+json")
|> get("/users/#{user.nickname}")
|> json_response(200)
assert response["endpoints"] == %{
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
"sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
"uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
}
assert response["@context"] == [
"https://www.w3.org/ns/activitystreams",
"http://localhost:4001/schemas/litepub-0.1.jsonld",
%{"@language" => "und"}
]
assert Map.take(response, [
"followers",
"following",
"id",
"inbox",
"manuallyApprovesFollowers",
"name",
"outbox",
"preferredUsername",
"summary",
"tag",
"type",
"url"
]) == %{
"followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
"following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
"id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
"inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
"manuallyApprovesFollowers" => false,
"name" => user.name,
"outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
"preferredUsername" => user.nickname,
"summary" => user.bio,
"tag" => [],
"type" => "Person",
"url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
}
end
test "activity+json format. it returns error whe use not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/activity+json")
|> get("/users/jimm")
|> json_response(404)
assert response == "Not found"
end
test "json format. it redirects on actual feed of user", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> put_req_header("accept", "application/json")
|> get("/users/#{user.nickname}")
|> json_response(200)
assert response["endpoints"] == %{
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
"sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
"uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
}
assert response["@context"] == [
"https://www.w3.org/ns/activitystreams",
"http://localhost:4001/schemas/litepub-0.1.jsonld",
%{"@language" => "und"}
]
assert Map.take(response, [
"followers",
"following",
"id",
"inbox",
"manuallyApprovesFollowers",
"name",
"outbox",
"preferredUsername",
"summary",
"tag",
"type",
"url"
]) == %{
"followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
"following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
"id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
"inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
"manuallyApprovesFollowers" => false,
"name" => user.name,
"outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
"preferredUsername" => user.nickname,
"summary" => user.bio,
"tag" => [],
"type" => "Person",
"url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
}
end
test "json format. it returns error whe use not found", %{conn: conn} do
response =
conn
|> put_req_header("accept", "application/json")
|> get("/users/jimm")
|> json_response(404)
assert response == "Not found"
end
test "html format. it redirects on actual feed of user", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
response =
conn
|> get("/users/#{user.nickname}")
|> response(200)
assert response ==
Fallback.RedirectController.redirector_with_meta(
conn,
%{user: user}
).resp_body
end
test "html format. it returns error when user not found", %{conn: conn} do
response =
conn
|> get("/users/jimm")
|> json_response(404)
assert response == %{"error" => "Not found"}
end
end
describe "GET /notice/:id/embed_player" do describe "GET /notice/:id/embed_player" do
test "render embed player", %{conn: conn} do test "render embed player", %{conn: conn} do
note_activity = insert(:note_activity) note_activity = insert(:note_activity)