This commit is contained in:
Hakaba Hitoyo 2018-07-19 17:42:00 +09:00
commit cc9c062b55
16 changed files with 159 additions and 29 deletions

View File

@ -52,6 +52,7 @@ config :pleroma, :instance,
version: version, version: version,
name: "Pleroma", name: "Pleroma",
email: "example@example.com", email: "example@example.com",
description: "A Pleroma instance, an alternative fediverse server",
limit: 5000, limit: 5000,
upload_limit: 16_000_000, upload_limit: 16_000_000,
registrations_open: true, registrations_open: true,
@ -60,6 +61,19 @@ config :pleroma, :instance,
public: true, public: true,
quarantined_instances: [] quarantined_instances: []
config :pleroma, :fe,
theme: "pleroma-dark",
logo: "/static/logo.png",
background: "/static/aurora_borealis.jpg",
redirect_root_no_login: "/main/all",
redirect_root_login: "/main/friends",
show_instance_panel: true,
show_who_to_follow_panel: false,
who_to_follow_provider:
"https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-osa-api.cgi?{{host}}+{{user}}",
who_to_follow_link: "https://vinayaka.distsn.org/?{{host}}+{{user}}",
scope_options_enabled: false
config :pleroma, :activitypub, config :pleroma, :activitypub,
accept_blocks: true, accept_blocks: true,
unfollow_blocked: true, unfollow_blocked: true,

View File

@ -19,7 +19,7 @@ defmodule Pleroma.Upload do
end end
%{ %{
"type" => "Image", "type" => "Document",
"url" => [ "url" => [
%{ %{
"type" => "Link", "type" => "Link",

View File

@ -13,6 +13,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
require Logger require Logger
def get_actor(%{"actor" => actor}) when is_binary(actor) do
actor
end
def get_actor(%{"actor" => actor}) when is_list(actor) do
Enum.at(actor, 0)
end
def get_actor(%{"actor" => actor_list}) do
Enum.find(actor_list, fn %{"type" => type} -> type == "Person" end)
|> Map.get("id")
end
@doc """ @doc """
Modifies an incoming AP object (mastodon format) to our internal format. Modifies an incoming AP object (mastodon format) to our internal format.
""" """
@ -28,16 +41,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
def fix_actor(%{"attributedTo" => actor} = object) do def fix_actor(%{"attributedTo" => actor} = object) do
# attributedTo can be a list in the case of peertube or plume
actor =
if is_list(actor) do
Enum.at(actor, 0)
else
actor
end
object object
|> Map.put("actor", actor) |> Map.put("actor", get_actor(%{"actor" => actor}))
end end
def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object) def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
@ -137,12 +142,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# - emoji # - emoji
def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data) def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data)
when objtype in ["Article", "Note"] do when objtype in ["Article", "Note"] do
actor = get_actor(data)
data = Map.put(data, "actor", actor)
with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]), with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]),
%User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do %User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do
# prefer the activity's actor instead of attributedTo object = fix_object(data["object"])
object =
fix_object(data["object"])
|> Map.put("actor", data["actor"])
params = %{ params = %{
to: data["to"], to: data["to"],

View File

@ -1,6 +1,6 @@
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
alias Pleroma.{Repo, Activity, User, Notification, Stats} alias Pleroma.{Repo, Object, Activity, User, Notification, Stats}
alias Pleroma.Web alias Pleroma.Web
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView} alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -127,7 +127,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
response = %{ response = %{
uri: Web.base_url(), uri: Web.base_url(),
title: Keyword.get(@instance, :name), title: Keyword.get(@instance, :name),
description: "A Pleroma instance, an alternative fediverse server", description: Keyword.get(@instance, :description),
version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})", version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})",
email: Keyword.get(@instance, :email), email: Keyword.get(@instance, :email),
urls: %{ urls: %{
@ -430,16 +430,43 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
render(conn, AccountView, "relationships.json", %{user: user, targets: targets}) render(conn, AccountView, "relationships.json", %{user: user, targets: targets})
end end
def upload(%{assigns: %{user: _}} = conn, %{"file" => file}) do def update_media(%{assigns: %{user: _}} = conn, data) do
with {:ok, object} <- ActivityPub.upload(file) do with %Object{} = object <- Repo.get(Object, data["id"]),
true <- is_binary(data["description"]),
description <- data["description"] do
new_data = %{object.data | "name" => description}
change = Object.change(object, %{data: new_data})
{:ok, media_obj} = Repo.update(change)
data = data =
object.data new_data
|> Map.put("id", object.id) |> Map.put("id", object.id)
render(conn, StatusView, "attachment.json", %{attachment: data}) render(conn, StatusView, "attachment.json", %{attachment: data})
end end
end end
def upload(%{assigns: %{user: _}} = conn, %{"file" => file} = data) do
with {:ok, object} <- ActivityPub.upload(file) do
objdata =
if Map.has_key?(data, "description") do
Map.put(object.data, "name", data["description"])
else
object.data
end
change = Object.change(object, %{data: objdata})
{:ok, object} = Repo.update(change)
objdata =
objdata
|> Map.put("id", object.id)
render(conn, StatusView, "attachment.json", %{attachment: objdata})
end
end
def favourited_by(conn, %{"id" => id}) do def favourited_by(conn, %{"id" => id}) do
with %Activity{data: %{"object" => %{"likes" => likes}}} <- Repo.get(Activity, id) do with %Activity{data: %{"object" => %{"likes" => likes}}} <- Repo.get(Activity, id) do
q = from(u in User, where: u.ap_id in ^likes) q = from(u in User, where: u.ap_id in ^likes)

View File

@ -169,7 +169,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
remote_url: href, remote_url: href,
preview_url: MediaProxy.url(href), preview_url: MediaProxy.url(href),
text_url: href, text_url: href,
type: type type: type,
description: attachment["name"]
} }
end end

View File

@ -44,7 +44,9 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
}, },
metadata: %{ metadata: %{
nodeName: Keyword.get(instance, :name), nodeName: Keyword.get(instance, :name),
nodeDescription: Keyword.get(instance, :description),
mediaProxy: Keyword.get(media_proxy, :enabled), mediaProxy: Keyword.get(media_proxy, :enabled),
private: !Keyword.get(instance, :public, true),
suggestions: %{ suggestions: %{
enabled: Keyword.get(suggestions, :enabled, false), enabled: Keyword.get(suggestions, :enabled, false),
thirdPartyEngine: Keyword.get(suggestions, :third_party_engine, ""), thirdPartyEngine: Keyword.get(suggestions, :third_party_engine, ""),

View File

@ -6,6 +6,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Web.{OStatus, Federator} alias Pleroma.Web.{OStatus, Federator}
alias Pleroma.Web.XML alias Pleroma.Web.XML
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPubController
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -90,7 +91,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
case get_format(conn) do case get_format(conn) do
"html" -> redirect(conn, to: "/notice/#{activity.id}") "html" -> redirect(conn, to: "/notice/#{activity.id}")
_ -> represent_activity(conn, activity, user) _ -> represent_activity(conn, nil, activity, user)
end end
else else
{:public?, false} -> {:public?, false} ->
@ -110,9 +111,9 @@ defmodule Pleroma.Web.OStatus.OStatusController do
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
{_, true} <- {:public?, ActivityPub.is_public?(activity)}, {_, true} <- {:public?, ActivityPub.is_public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
case get_format(conn) do case format = get_format(conn) do
"html" -> redirect(conn, to: "/notice/#{activity.id}") "html" -> redirect(conn, to: "/notice/#{activity.id}")
_ -> represent_activity(conn, activity, user) _ -> represent_activity(conn, format, activity, user)
end end
else else
{:public?, false} -> {:public?, false} ->
@ -130,14 +131,14 @@ defmodule Pleroma.Web.OStatus.OStatusController do
with {_, %Activity{} = activity} <- {:activity, Repo.get(Activity, id)}, with {_, %Activity{} = activity} <- {:activity, Repo.get(Activity, id)},
{_, true} <- {:public?, ActivityPub.is_public?(activity)}, {_, true} <- {:public?, ActivityPub.is_public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
case get_format(conn) do case format = get_format(conn) do
"html" -> "html" ->
conn conn
|> put_resp_content_type("text/html") |> put_resp_content_type("text/html")
|> send_file(200, "priv/static/index.html") |> send_file(200, "priv/static/index.html")
_ -> _ ->
represent_activity(conn, activity, user) represent_activity(conn, format, activity, user)
end end
else else
{:public?, false} -> {:public?, false} ->
@ -151,7 +152,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do
end end
end end
defp represent_activity(conn, activity, user) do defp represent_activity(conn, "activity+json", activity, user) do
conn
|> put_resp_header("content-type", "application/activity+json")
|> json(ObjectView.render("object.json", %{object: activity}))
end
defp represent_activity(conn, _, activity, user) do
response = response =
activity activity
|> ActivityRepresenter.to_simple_form(user, true) |> ActivityRepresenter.to_simple_form(user, true)

View File

@ -127,6 +127,7 @@ defmodule Pleroma.Web.Router do
get("/notifications/:id", MastodonAPIController, :get_notification) get("/notifications/:id", MastodonAPIController, :get_notification)
post("/media", MastodonAPIController, :upload) post("/media", MastodonAPIController, :upload)
put("/media/:id", MastodonAPIController, :update_media)
get("/lists", MastodonAPIController, :get_lists) get("/lists", MastodonAPIController, :get_lists)
get("/lists/:id", MastodonAPIController, :get_list) get("/lists/:id", MastodonAPIController, :get_list)

View File

@ -126,6 +126,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end end
@instance Application.get_env(:pleroma, :instance) @instance Application.get_env(:pleroma, :instance)
@instance_fe Application.get_env(:pleroma, :fe)
@instance_chat Application.get_env(:pleroma, :chat)
def config(conn, _params) do def config(conn, _params) do
case get_format(conn) do case get_format(conn) do
"xml" -> "xml" ->
@ -148,9 +150,24 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
json(conn, %{ json(conn, %{
site: %{ site: %{
name: Keyword.get(@instance, :name), name: Keyword.get(@instance, :name),
description: Keyword.get(@instance, :description),
server: Web.base_url(), server: Web.base_url(),
textlimit: to_string(Keyword.get(@instance, :limit)), textlimit: to_string(Keyword.get(@instance, :limit)),
closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1") closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1"),
private: if(Keyword.get(@instance, :public, true), do: "0", else: "1"),
pleromafe: %{
theme: Keyword.get(@instance_fe, :theme),
background: Keyword.get(@instance_fe, :background),
logo: Keyword.get(@instance_fe, :logo),
redirectRootNoLogin: Keyword.get(@instance_fe, :redirect_root_no_login),
redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login),
chatDisabled: !Keyword.get(@instance_chat, :enabled),
showInstanceSpecificPanel: Keyword.get(@instance_fe, :show_instance_panel),
showWhoToFollowPanel: Keyword.get(@instance_fe, :show_who_to_follow_panel),
scopeOptionsEnabled: Keyword.get(@instance_fe, :scope_options_enabled),
whoToFollowProvider: Keyword.get(@instance_fe, :who_to_follow_provider),
whoToFollowLink: Keyword.get(@instance_fe, :who_to_follow_link)
}
} }
}) })
end end

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"Emoji":"toot:Emoji","Hashtag":"as:Hashtag","atomUri":"ostatus:atomUri","conversation":"ostatus:conversation","featured":"toot:featured","focalPoint":{"@container":"@list","@id":"toot:focalPoint"},"inReplyToAtomUri":"ostatus:inReplyToAtomUri","manuallyApprovesFollowers":"as:manuallyApprovesFollowers","movedTo":"as:movedTo","ostatus":"http://ostatus.org#","sensitive":"as:sensitive","toot":"http://joinmastodon.org/ns#"}],"endpoints":{"oauthAuthorizationEndpoint":null,"oauthTokenEndpoint":null,"provideClientKey":null,"proxyUrl":null,"sharedInbox":"https://baptiste.gelez.xyz/inbox/","signClientKey":null},"followers":null,"following":null,"id":"https://baptiste.gelez.xyz/@/BaptisteGelez","inbox":"https://baptiste.gelez.xyz/@/BaptisteGelez/inbox","liked":null,"likes":null,"name":"Baptiste Gelez","outbox":"https://baptiste.gelez.xyz/@/BaptisteGelez/outbox","preferredUsername":"BaptisteGelez","publicKey":{"id":"https://baptiste.gelez.xyz/@/BaptisteGelez#main-key","owner":"https://baptiste.gelez.xyz/@/BaptisteGelez","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA56vPlCAyxZDDy8hNiT1p\n0cdFKnUK/51LiP4nTAxGf5Eb8NmsB2ftDgiDWZfg3LiHkjNcfTDpmN0aZyRxnTg9\nZ4JiQagfynVEbMkcOQhO64OFZpB47GpLtxrb49IcUes/p4ngp/Wkp+arYZSpoSs6\n3I995mZp3ZJ78pNQf1/lV0VIdDe6SqvRj1GmBDXXcecxF0O7rN/WYNO7Jag4i/XA\nU1ToDAMeUFeijRioSNoD3CHkMIu7AN+gqAWzZ21H/ZUvmfxh3WqQi/MDNcUhhA+0\nXv7/dv4S20EGnHadtE7OrBC1IwiHEuRM41zZq0ze9cKpoXg3VK2fiSNrCHlYrA18\n2wIDAQAB\n-----END PUBLIC KEY-----\n"},"shares":null,"source":null,"streams":null,"summary":"Main Plume developer","type":"Person","uploadMedia":null,"url":"https://baptiste.gelez.xyz/@/BaptisteGelez"}

View File

@ -736,6 +736,22 @@ defmodule HTTPoisonMock do
}} }}
end end
def get("https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json")
}}
end
def get("https://baptiste.gelez.xyz/@/BaptisteGelez", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json")
}}
end
def get(url, body, headers) do def get(url, body, headers) do
{:error, {:error,
"Not implemented the mock response for get #{inspect(url)}, #{inspect(body)}, #{ "Not implemented the mock response for get #{inspect(url)}, #{inspect(body)}, #{

View File

@ -476,6 +476,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end end
end end
test "it can fetch plume articles" do
{:ok, object} =
ActivityPub.fetch_object_from_id(
"https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"
)
assert object
end
describe "update" do describe "update" do
test "it creates an update activity with the new user data" do test "it creates an update activity with the new user data" do
user = insert(:user) user = insert(:user)

View File

@ -736,16 +736,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
filename: "an_image.jpg" filename: "an_image.jpg"
} }
desc = "Description of the image"
user = insert(:user) user = insert(:user)
conn = conn =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> post("/api/v1/media", %{"file" => file}) |> post("/api/v1/media", %{"file" => file, "description" => desc})
assert media = json_response(conn, 200) assert media = json_response(conn, 200)
assert media["type"] == "image" assert media["type"] == "image"
assert media["description"] == desc
end end
test "hashtag timeline", %{conn: conn} do test "hashtag timeline", %{conn: conn} do

View File

@ -102,7 +102,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
url: "someurl", url: "someurl",
remote_url: "someurl", remote_url: "someurl",
preview_url: "someurl", preview_url: "someurl",
text_url: "someurl" text_url: "someurl",
description: nil
} }
assert expected == StatusView.render("attachment.json", %{attachment: object}) assert expected == StatusView.render("attachment.json", %{attachment: object})

View File

@ -155,6 +155,31 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
assert response(conn, 200) assert response(conn, 200)
end end
test "gets a notice in AS2 format", %{conn: conn} do
note_activity = insert(:note_activity)
url = "/notice/#{note_activity.id}"
conn =
conn
|> put_req_header("accept", "application/activity+json")
|> get(url)
assert json_response(conn, 200)
end
test "gets an activity in AS2 format", %{conn: conn} do
note_activity = insert(:note_activity)
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
url = "/activities/#{uuid}"
conn =
conn
|> put_req_header("accept", "application/activity+json")
|> get(url)
assert json_response(conn, 200)
end
test "404s a private notice", %{conn: conn} do test "404s a private notice", %{conn: conn} do
note_activity = insert(:direct_note_activity) note_activity = insert(:direct_note_activity)
url = "/notice/#{note_activity.id}" url = "/notice/#{note_activity.id}"