Merge branch 'develop' into kaniini/pleroma-bugfix/unlisted-statuses

This commit is contained in:
lain 2018-05-13 10:56:11 +02:00
commit 76722ea9c8
59 changed files with 472 additions and 194 deletions

View file

@ -26,3 +26,12 @@ config :comeonin, :pbkdf2_rounds, 1
config :pleroma, :websub, Pleroma.Web.WebsubMock config :pleroma, :websub, Pleroma.Web.WebsubMock
config :pleroma, :ostatus, Pleroma.Web.OStatusMock config :pleroma, :ostatus, Pleroma.Web.OStatusMock
config :pleroma, :httpoison, HTTPoisonMock config :pleroma, :httpoison, HTTPoisonMock
try do
import_config "test.secret.exs"
rescue
_ ->
IO.puts(
"You may want to create test.secret.exs to declare custom database connection parameters."
)
end

View file

@ -59,6 +59,16 @@ server {
} }
# stop removing lines here. # stop removing lines here.
add_header X-XSS-Protection "1; mode=block";
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy same-origin;
add_header X-Download-Options noopen;
# Uncomment this only after you get HTTPS working.
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";

View file

@ -13,4 +13,3 @@ Restart=on-failure
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
Alias=pleroma.service

View file

@ -39,15 +39,9 @@ sub vcl_recv {
return (hash); return (hash);
} }
# Hack to enable a Terms of Service page missing from Pleroma
if (req.url ~ "^/about/more$") {
set req.http.x-redir = "https://" + req.http.host + "/static/terms-of-service.html";
return (synth(750, ""));
}
# Strip headers that will affect caching from all other static content # Strip headers that will affect caching from all other static content
# This also permits caching of individual toots and AP Activities # This also permits caching of individual toots and AP Activities
if ((req.url ~ "^/(media|notice|objects|static)/") || if ((req.url ~ "^/(media|static)/") ||
(req.url ~ "(?i)\.(html|js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$")) (req.url ~ "(?i)\.(html|js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$"))
{ {
unset req.http.Cookie; unset req.http.Cookie;
@ -99,8 +93,7 @@ sub vcl_backend_response {
# Strip cache-restricting headers from Pleroma on static content that we want to cache # Strip cache-restricting headers from Pleroma on static content that we want to cache
# Also enable streaming of cached content to clients (no waiting for Varnish to complete backend fetch) # Also enable streaming of cached content to clients (no waiting for Varnish to complete backend fetch)
if ((bereq.url ~ "^/(notice|objects)/") || if (bereq.url ~ "(?i)\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$")
(bereq.url ~ "(?i)\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$"))
{ {
unset beresp.http.set-cookie; unset beresp.http.set-cookie;
unset beresp.http.Cache-Control; unset beresp.http.Cache-Control;

View file

@ -1,6 +1,5 @@
defmodule Mix.Tasks.FixApUsers do defmodule Mix.Tasks.FixApUsers do
use Mix.Task use Mix.Task
import Mix.Ecto
import Ecto.Query import Ecto.Query
alias Pleroma.{Repo, User} alias Pleroma.{Repo, User}

View file

@ -1,7 +1,6 @@
defmodule Mix.Tasks.GeneratePasswordReset do defmodule Mix.Tasks.GeneratePasswordReset do
use Mix.Task use Mix.Task
import Mix.Ecto alias Pleroma.User
alias Pleroma.{Repo, User}
@shortdoc "Generate password reset link for user" @shortdoc "Generate password reset link for user"
def run([nickname]) do def run([nickname]) do

View file

@ -1,6 +1,5 @@
defmodule Mix.Tasks.RegisterUser do defmodule Mix.Tasks.RegisterUser do
use Mix.Task use Mix.Task
import Mix.Ecto
alias Pleroma.{Repo, User} alias Pleroma.{Repo, User}
@shortdoc "Register user" @shortdoc "Register user"

View file

@ -1,7 +1,6 @@
defmodule Mix.Tasks.RmUser do defmodule Mix.Tasks.RmUser do
use Mix.Task use Mix.Task
import Mix.Ecto alias Pleroma.User
alias Pleroma.{User, Repo}
@shortdoc "Permanently delete a user" @shortdoc "Permanently delete a user"
def run([nickname]) do def run([nickname]) do

View file

@ -23,6 +23,18 @@ defmodule Pleroma.Application do
limit: 2500 limit: 2500
] ]
]), ]),
worker(
Cachex,
[
:idempotency_cache,
[
default_ttl: :timer.seconds(6 * 60 * 60),
ttl_interval: :timer.seconds(60),
limit: 2500
]
],
id: :cachex_idem
),
worker(Pleroma.Web.Federator, []), worker(Pleroma.Web.Federator, []),
worker(Pleroma.Gopher.Server, []), worker(Pleroma.Gopher.Server, []),
worker(Pleroma.Stats, []) worker(Pleroma.Stats, [])

View file

@ -65,12 +65,6 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
"#{type}#{name}\t#{selector}\t#{address}\t#{port}\r\n" "#{type}#{name}\t#{selector}\t#{address}\t#{port}\r\n"
end end
def response("") do
info("Welcome to #{Keyword.get(@instance, :name, "Pleroma")}!") <>
link("Public Timeline", "/main/public") <>
link("Federated Timeline", "/main/all") <> ".\r\n"
end
def render_activities(activities) do def render_activities(activities) do
activities activities
|> Enum.reverse() |> Enum.reverse()
@ -93,6 +87,12 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|> Enum.join("\r\n") |> Enum.join("\r\n")
end end
def response("") do
info("Welcome to #{Keyword.get(@instance, :name, "Pleroma")}!") <>
link("Public Timeline", "/main/public") <>
link("Federated Timeline", "/main/all") <> ".\r\n"
end
def response("/main/public") do def response("/main/public") do
posts = posts =
ActivityPub.fetch_public_activities(%{"type" => ["Create"], "local_only" => true}) ActivityPub.fetch_public_activities(%{"type" => ["Create"], "local_only" => true})

View file

@ -91,7 +91,8 @@ defmodule Pleroma.Notification do
# TODO move to sql, too. # TODO move to sql, too.
def create_notification(%Activity{} = activity, %User{} = user) do def create_notification(%Activity{} = activity, %User{} = user) do
unless User.blocks?(user, %{ap_id: activity.data["actor"]}) do unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or
user.ap_id == activity.data["actor"] do
notification = %Notification{user_id: user.id, activity: activity} notification = %Notification{user_id: user.id, activity: activity}
{:ok, notification} = Repo.insert(notification) {:ok, notification} = Repo.insert(notification)
Pleroma.Web.Streamer.stream("user", notification) Pleroma.Web.Streamer.stream("user", notification)

View file

@ -7,11 +7,11 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
options options
end end
def call(%{assigns: %{valid_signature: true}} = conn, opts) do def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
conn conn
end end
def call(conn, opts) do def call(conn, _opts) do
user = conn.params["actor"] user = conn.params["actor"]
Logger.debug("Checking sig for #{user}") Logger.debug("Checking sig for #{user}")
[signature | _] = get_req_header(conn, "signature") [signature | _] = get_req_header(conn, "signature")

View file

@ -1,6 +1,6 @@
defmodule Pleroma.Stats do defmodule Pleroma.Stats do
import Ecto.Query import Ecto.Query
alias Pleroma.{User, Repo, Activity} alias Pleroma.{User, Repo}
def start_link do def start_link do
agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__) agent = Agent.start_link(fn -> {[], %{}} end, name: __MODULE__)

View file

@ -1,6 +1,6 @@
defmodule Pleroma.Web.ActivityPub.ActivityPub do defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.{Activity, Repo, Object, Upload, User, Notification} alias Pleroma.{Activity, Repo, Object, Upload, User, Notification}
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.{Transmogrifier, MRF}
alias Pleroma.Web.WebFinger alias Pleroma.Web.WebFinger
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
alias Pleroma.Web.OStatus alias Pleroma.Web.OStatus
@ -11,7 +11,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
@httpoison Application.get_env(:pleroma, :httpoison) @httpoison Application.get_env(:pleroma, :httpoison)
@instance Application.get_env(:pleroma, :instance) @instance Application.get_env(:pleroma, :instance)
@rewrite_policy Keyword.get(@instance, :rewrite_policy)
def get_recipients(data) do def get_recipients(data) do
(data["to"] || []) ++ (data["cc"] || []) (data["to"] || []) ++ (data["cc"] || [])
@ -20,8 +19,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def insert(map, local \\ true) when is_map(map) do def insert(map, local \\ true) when is_map(map) do
with nil <- Activity.get_by_ap_id(map["id"]), with nil <- Activity.get_by_ap_id(map["id"]),
map <- lazy_put_activity_defaults(map), map <- lazy_put_activity_defaults(map),
:ok <- insert_full_object(map), {:ok, map} <- MRF.filter(map),
{:ok, map} <- @rewrite_policy.filter(map) do :ok <- insert_full_object(map) do
{:ok, activity} = {:ok, activity} =
Repo.insert(%Activity{ Repo.insert(%Activity{
data: map, data: map,
@ -66,7 +65,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
), ),
{:ok, activity} <- insert(create_data, local), {:ok, activity} <- insert(create_data, local),
:ok <- maybe_federate(activity), :ok <- maybe_federate(activity),
{:ok, actor} <- User.increase_note_count(actor) do {:ok, _actor} <- User.increase_note_count(actor) do
{:ok, activity} {:ok, activity}
end end
end end
@ -177,7 +176,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
Repo.delete_all(Activity.all_non_create_by_object_ap_id_q(id)), Repo.delete_all(Activity.all_non_create_by_object_ap_id_q(id)),
{:ok, activity} <- insert(data, local), {:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity), :ok <- maybe_federate(activity),
{:ok, actor} <- User.decrease_note_count(user) do {:ok, _actor} <- User.decrease_note_count(user) do
{:ok, activity} {:ok, activity}
end end
end end
@ -236,7 +235,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_tag(query, _), do: query defp restrict_tag(query, _), do: query
defp restrict_recipients(query, [], user), do: query defp restrict_recipients(query, [], _user), do: query
defp restrict_recipients(query, recipients, nil) do defp restrict_recipients(query, recipients, nil) do
from(activity in query, where: fragment("? && ?", ^recipients, activity.recipients)) from(activity in query, where: fragment("? && ?", ^recipients, activity.recipients))
@ -313,7 +312,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
blocks = info["blocks"] || [] blocks = info["blocks"] || []
from(activity in query,
from(
activity in query,
where: fragment("not (? = ANY(?))", activity.actor, ^blocks), where: fragment("not (? = ANY(?))", activity.actor, ^blocks),
where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks) where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks)
) )
@ -405,7 +406,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end end
def make_user_from_ap_id(ap_id) do def make_user_from_ap_id(ap_id) do
if user = User.get_by_ap_id(ap_id) do if _user = User.get_by_ap_id(ap_id) do
Transmogrifier.upgrade_user_from_ap_id(ap_id) Transmogrifier.upgrade_user_from_ap_id(ap_id)
else else
with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do
@ -501,7 +502,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
object = %Object{} -> object = %Object{} ->
{:ok, object} {:ok, object}
e -> _e ->
Logger.info("Couldn't get object via AP, trying out OStatus fetching...") Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
case OStatus.fetch_activity_from_url(id) do case OStatus.fetch_activity_from_url(id) do

View file

@ -1,7 +1,7 @@
defmodule Pleroma.Web.ActivityPub.ActivityPubController do defmodule Pleroma.Web.ActivityPub.ActivityPubController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
alias Pleroma.{User, Repo, Object, Activity} alias Pleroma.{User, Object}
alias Pleroma.Web.ActivityPub.{ObjectView, UserView, Transmogrifier} alias Pleroma.Web.ActivityPub.{ObjectView, UserView}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.Federator alias Pleroma.Web.Federator

View file

@ -0,0 +1,24 @@
defmodule Pleroma.Web.ActivityPub.MRF do
@callback filter(Map.t()) :: {:ok | :reject, Map.t()}
def filter(object) do
get_policies()
|> Enum.reduce({:ok, object}, fn
policy, {:ok, object} ->
policy.filter(object)
_, error ->
error
end)
end
def get_policies() do
Application.get_env(:pleroma, :instance, [])
|> Keyword.get(:rewrite_policy, [])
|> get_policies()
end
defp get_policies(policy) when is_atom(policy), do: [policy]
defp get_policies(policies) when is_list(policies), do: policies
defp get_policies(_), do: []
end

View file

@ -1,6 +1,8 @@
defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
require Logger require Logger
@behaviour Pleroma.Web.ActivityPub.MRF
@impl true
def filter(object) do def filter(object) do
Logger.info("REJECTING #{inspect(object)}") Logger.info("REJECTING #{inspect(object)}")
{:reject, object} {:reject, object}

View file

@ -1,4 +1,7 @@
defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
@behaviour Pleroma.Web.ActivityPub.MRF
@impl true
def filter(object) do def filter(object) do
{:ok, object} {:ok, object}
end end

View file

@ -1,5 +1,6 @@
defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
alias Pleroma.User alias Pleroma.User
@behaviour Pleroma.Web.ActivityPub.MRF
@mrf_policy Application.get_env(:pleroma, :mrf_simple) @mrf_policy Application.get_env(:pleroma, :mrf_simple)
@ -17,9 +18,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if actor_info.host in @media_removal do if actor_info.host in @media_removal do
child_object = Map.delete(object["object"], "attachment") child_object = Map.delete(object["object"], "attachment")
object = Map.put(object, "object", child_object) object = Map.put(object, "object", child_object)
{:ok, object}
else
{:ok, object}
end end
{:ok, object}
end end
@media_nsfw Keyword.get(@mrf_policy, :media_nsfw) @media_nsfw Keyword.get(@mrf_policy, :media_nsfw)
@ -32,9 +34,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
child_object = Map.put(child_object, "tags", tags) child_object = Map.put(child_object, "tags", tags)
child_object = Map.put(child_object, "sensitive", true) child_object = Map.put(child_object, "sensitive", true)
object = Map.put(object, "object", child_object) object = Map.put(object, "object", child_object)
{:ok, object}
else
{:ok, object}
end end
{:ok, object}
end end
@ftl_removal Keyword.get(@mrf_policy, :federated_timeline_removal) @ftl_removal Keyword.get(@mrf_policy, :federated_timeline_removal)
@ -43,24 +46,31 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
user = User.get_by_ap_id(object["actor"]) user = User.get_by_ap_id(object["actor"])
# flip to/cc relationship to make the post unlisted # flip to/cc relationship to make the post unlisted
if "https://www.w3.org/ns/activitystreams#Public" in object["to"] and object =
user.follower_address in object["cc"] do if "https://www.w3.org/ns/activitystreams#Public" in object["to"] and
to = user.follower_address in object["cc"] do
List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++ to =
[user.follower_address] List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++
[user.follower_address]
cc = cc =
List.delete(object["cc"], user.follower_address) ++ List.delete(object["cc"], user.follower_address) ++
["https://www.w3.org/ns/activitystreams#Public"] ["https://www.w3.org/ns/activitystreams#Public"]
object = Map.put(object, "to", to) object
object = Map.put(object, "cc", cc) |> Map.put("to", to)
end |> Map.put("cc", cc)
else
object
end
{:ok, object}
else
{:ok, object}
end end
{:ok, object}
end end
@impl true
def filter(object) do def filter(object) do
actor_info = URI.parse(object["actor"]) actor_info = URI.parse(object["actor"])
@ -70,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
{:ok, object} <- check_ftl_removal(actor_info, object) do {:ok, object} <- check_ftl_removal(actor_info, object) do
{:ok, object} {:ok, object}
else else
e -> {:reject, nil} _e -> {:reject, nil}
end end
end end
end end

View file

@ -72,9 +72,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Enum.reduce(%{}, fn data, mapping -> |> Enum.reduce(%{}, fn data, mapping ->
name = data["name"] name = data["name"]
if String.starts_with?(name, ":") do name =
name = name |> String.slice(1..-2) if String.starts_with?(name, ":") do
end name |> String.slice(1..-2)
else
name
end
mapping |> Map.put(name, data["icon"]["url"]) mapping |> Map.put(name, data["icon"]["url"])
end) end)
@ -143,12 +146,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
def handle_incoming( def handle_incoming(
%{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = _data
) do ) do
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- {:ok, object} <-
get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
{:ok, activity, object} <- ActivityPub.like(actor, object, id, false) do {:ok, activity, _object} <- ActivityPub.like(actor, object, id, false) do
{:ok, activity} {:ok, activity}
else else
_e -> :error _e -> :error
@ -156,12 +159,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end end
def handle_incoming( def handle_incoming(
%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data %{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = _data
) do ) do
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- {:ok, object} <-
get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
{:ok, activity, object} <- ActivityPub.announce(actor, object, id, false) do {:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false) do
{:ok, activity} {:ok, activity}
else else
_e -> :error _e -> :error
@ -202,7 +205,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# TODO: Make secure. # TODO: Make secure.
def handle_incoming( def handle_incoming(
%{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data
) do ) do
object_id = object_id =
case object_id do case object_id do
@ -210,13 +213,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
id -> id id -> id
end end
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), with %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- {:ok, object} <-
get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
{:ok, activity} <- ActivityPub.delete(object, false) do {:ok, activity} <- ActivityPub.delete(object, false) do
{:ok, activity} {:ok, activity}
else else
e -> :error _e -> :error
end end
end end
@ -254,10 +257,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> set_reply_to_uri |> set_reply_to_uri
end end
@doc # @doc
""" # """
internal -> Mastodon # internal -> Mastodon
""" # """
def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
object = object =
@ -272,7 +275,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, data} {:ok, data}
end end
def prepare_outgoing(%{"type" => type} = data) do def prepare_outgoing(%{"type" => _type} = data) do
data = data =
data data
|> maybe_fix_object_url |> maybe_fix_object_url
@ -286,7 +289,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
case ActivityPub.fetch_object_from_id(data["object"]) do case ActivityPub.fetch_object_from_id(data["object"]) do
{:ok, relative_object} -> {:ok, relative_object} ->
if relative_object.data["external_url"] do if relative_object.data["external_url"] do
data = _data =
data data
|> Map.put("object", relative_object.data["external_url"]) |> Map.put("object", relative_object.data["external_url"])
else else

View file

@ -47,25 +47,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Utils.make_json_ld_header())
end end
def collection(collection, iri, page, total \\ nil) do
offset = (page - 1) * 10
items = Enum.slice(collection, offset, 10)
items = Enum.map(items, fn user -> user.ap_id end)
total = total || length(collection)
map = %{
"id" => "#{iri}?page=#{page}",
"type" => "OrderedCollectionPage",
"partOf" => iri,
"totalItems" => length(collection),
"orderedItems" => items
}
if offset < length(collection) do
Map.put(map, "next", "#{iri}?page=#{page + 1}")
end
end
def render("following.json", %{user: user, page: page}) do def render("following.json", %{user: user, page: page}) do
query = User.get_friends_query(user) query = User.get_friends_query(user)
query = from(user in query, select: [:ap_id]) query = from(user in query, select: [:ap_id])
@ -123,9 +104,12 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"limit" => "10" "limit" => "10"
} }
if max_qid != nil do params =
params = Map.put(params, "max_id", max_qid) if max_qid != nil do
end Map.put(params, "max_id", max_qid)
else
params
end
activities = ActivityPub.fetch_public_activities(params) activities = ActivityPub.fetch_public_activities(params)
min_id = Enum.at(activities, 0).id min_id = Enum.at(activities, 0).id
@ -162,4 +146,23 @@ defmodule Pleroma.Web.ActivityPub.UserView do
page |> Map.merge(Utils.make_json_ld_header()) page |> Map.merge(Utils.make_json_ld_header())
end end
end end
def collection(collection, iri, page, total \\ nil) do
offset = (page - 1) * 10
items = Enum.slice(collection, offset, 10)
items = Enum.map(items, fn user -> user.ap_id end)
total = total || length(collection)
map = %{
"id" => "#{iri}?page=#{page}",
"type" => "OrderedCollectionPage",
"partOf" => iri,
"totalItems" => total,
"orderedItems" => items
}
if offset < total do
Map.put(map, "next", "#{iri}?page=#{page + 1}")
end
end
end end

View file

@ -1,7 +1,6 @@
defmodule Pleroma.Web.UserSocket do defmodule Pleroma.Web.UserSocket do
use Phoenix.Socket use Phoenix.Socket
alias Pleroma.User alias Pleroma.User
alias Comeonin.Pbkdf2
## Channels ## Channels
# channel "room:*", Pleroma.Web.RoomChannel # channel "room:*", Pleroma.Web.RoomChannel

View file

@ -1,5 +1,5 @@
defmodule Pleroma.Web.CommonAPI do defmodule Pleroma.Web.CommonAPI do
alias Pleroma.{Repo, Activity, Object, User} alias Pleroma.{Repo, Activity, Object}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Formatter alias Pleroma.Formatter

View file

@ -1,5 +1,5 @@
defmodule Pleroma.Web.CommonAPI.Utils do defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.{Repo, Object, Formatter, User, Activity} alias Pleroma.{Repo, Object, Formatter, Activity}
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Calendar.Strftime alias Calendar.Strftime
@ -49,7 +49,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
{[user.follower_address | to], cc} {[user.follower_address | to], cc}
end end
def to_for_user_and_mentions(user, mentions, inReplyTo, "direct") do def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do
mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
if inReplyTo do if inReplyTo do
@ -69,7 +69,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
def make_context(%Activity{data: %{"context" => context}}), do: context def make_context(%Activity{data: %{"context" => context}}), do: context
def make_context(_), do: Utils.generate_context_id() def make_context(_), do: Utils.generate_context_id()
def maybe_add_attachments(text, attachments, _no_links = true), do: text def maybe_add_attachments(text, _attachments, _no_links = true), do: text
def maybe_add_attachments(text, attachments, _no_links) do def maybe_add_attachments(text, attachments, _no_links) do
add_attachments(text, attachments) add_attachments(text, attachments)

View file

@ -14,6 +14,10 @@ defmodule Pleroma.Web.Federator do
@federating Keyword.get(@instance, :federating) @federating Keyword.get(@instance, :federating)
@max_jobs 20 @max_jobs 20
def init(args) do
{:ok, args}
end
def start_link do def start_link do
spawn(fn -> spawn(fn ->
# 1 minute # 1 minute
@ -89,12 +93,12 @@ defmodule Pleroma.Web.Federator do
with {:ok, _user} <- ap_enabled_actor(params["actor"]), with {:ok, _user} <- ap_enabled_actor(params["actor"]),
nil <- Activity.get_by_ap_id(params["id"]), nil <- Activity.get_by_ap_id(params["id"]),
{:ok, activity} <- Transmogrifier.handle_incoming(params) do {:ok, _activity} <- Transmogrifier.handle_incoming(params) do
else else
%Activity{} -> %Activity{} ->
Logger.info("Already had #{params["id"]}") Logger.info("Already had #{params["id"]}")
e -> _e ->
# Just drop those for now # Just drop those for now
Logger.info("Unhandled activity") Logger.info("Unhandled activity")
Logger.info(Poison.encode!(params, pretty: 2)) Logger.info(Poison.encode!(params, pretty: 2))
@ -154,7 +158,7 @@ defmodule Pleroma.Web.Federator do
end end
end end
def handle_cast({:enqueue, type, payload, priority}, state) def handle_cast({:enqueue, type, payload, _priority}, state)
when type in [:incoming_doc, :incoming_ap_doc] do when type in [:incoming_doc, :incoming_ap_doc] do
%{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}} = state %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}} = state
i_queue = enqueue_sorted(i_queue, {type, payload}, 1) i_queue = enqueue_sorted(i_queue, {type, payload}, 1)
@ -162,7 +166,7 @@ defmodule Pleroma.Web.Federator do
{:noreply, %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}}} {:noreply, %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}}}
end end
def handle_cast({:enqueue, type, payload, priority}, state) do def handle_cast({:enqueue, type, payload, _priority}, state) do
%{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}} = state %{in: {i_running_jobs, i_queue}, out: {o_running_jobs, o_queue}} = state
o_queue = enqueue_sorted(o_queue, {type, payload}, 1) o_queue = enqueue_sorted(o_queue, {type, payload}, 1)
{o_running_jobs, o_queue} = maybe_start_job(o_running_jobs, o_queue) {o_running_jobs, o_queue} = maybe_start_job(o_running_jobs, o_queue)

View file

@ -45,7 +45,7 @@ defmodule Pleroma.Web.HTTPSignatures do
end end
end end
else else
e -> _e ->
Logger.debug("Could not public key!") Logger.debug("Could not public key!")
false false
end end

View file

@ -112,7 +112,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
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: %{
streaming_api: String.replace(Web.base_url(), ["http", "https"], "wss") streaming_api: String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws")
}, },
stats: Stats.get_stats(), stats: Stats.get_stats(),
thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg", thumbnail: Web.base_url() <> "/instance/thumbnail.jpeg",
@ -212,14 +212,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("actor_id", ap_id) |> Map.put("actor_id", ap_id)
|> Map.put("whole_db", true) |> Map.put("whole_db", true)
if params["pinned"] == "true" do activities =
# Since Pleroma has no "pinned" posts feature, we'll just set an empty list here if params["pinned"] == "true" do
activities = [] # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here
else []
activities = else
ActivityPub.fetch_public_activities(params) ActivityPub.fetch_public_activities(params)
|> Enum.reverse() |> Enum.reverse()
end end
conn conn
|> add_link_headers(:user_statuses, activities, params["id"]) |> add_link_headers(:user_statuses, activities, params["id"])
@ -275,7 +275,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("in_reply_to_status_id", params["in_reply_to_id"]) |> Map.put("in_reply_to_status_id", params["in_reply_to_id"])
|> Map.put("no_attachment_links", true) |> Map.put("no_attachment_links", true)
{:ok, activity} = CommonAPI.post(user, params) idempotency_key =
case get_req_header(conn, "idempotency-key") do
[key] -> key
_ -> Ecto.UUID.generate()
end
{:ok, activity} =
Cachex.get!(
:idempotency_cache,
idempotency_key,
fallback: fn _ -> CommonAPI.post(user, params) end
)
render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
end end

View file

@ -82,19 +82,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
} }
end end
def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do
id = activity.data["object"]["inReplyTo"]
replied_to_activities[activity.data["object"]["inReplyTo"]]
end
def get_reply_to(%{data: %{"object" => object}}, _) do
if object["inReplyTo"] && object["inReplyTo"] != "" do
Activity.get_create_activity_by_object_ap_id(object["inReplyTo"])
else
nil
end
end
def render("status.json", %{activity: %{data: %{"object" => object}} = activity} = opts) do def render("status.json", %{activity: %{data: %{"object" => object}} = activity} = opts) do
user = User.get_cached_by_ap_id(activity.data["actor"]) user = User.get_cached_by_ap_id(activity.data["actor"])
@ -164,19 +151,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
} }
end end
def get_visibility(object) do
public = "https://www.w3.org/ns/activitystreams#Public"
to = object["to"] || []
cc = object["cc"] || []
cond do
public in to -> "public"
public in cc -> "unlisted"
Enum.any?(to, &String.contains?(&1, "/followers")) -> "private"
true -> "direct"
end
end
def render("attachment.json", %{attachment: attachment}) do def render("attachment.json", %{attachment: attachment}) do
[%{"mediaType" => media_type, "href" => href} | _] = attachment["url"] [%{"mediaType" => media_type, "href" => href} | _] = attachment["url"]
@ -199,4 +173,30 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
type: type type: type
} }
end end
def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do
_id = activity.data["object"]["inReplyTo"]
replied_to_activities[activity.data["object"]["inReplyTo"]]
end
def get_reply_to(%{data: %{"object" => object}}, _) do
if object["inReplyTo"] && object["inReplyTo"] != "" do
Activity.get_create_activity_by_object_ap_id(object["inReplyTo"])
else
nil
end
end
def get_visibility(object) do
public = "https://www.w3.org/ns/activitystreams#Public"
to = object["to"] || []
cc = object["cc"] || []
cond do
public in to -> "public"
public in cc -> "unlisted"
Enum.any?(to, &String.contains?(&1, "/followers")) -> "private"
true -> "direct"
end
end
end end

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,62 @@
defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
use Pleroma.Web, :controller
alias Pleroma.Stats
alias Pleroma.Web
@instance Application.get_env(:pleroma, :instance)
def schemas(conn, _params) do
response = %{
links: [
%{
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0",
href: Web.base_url() <> "/nodeinfo/2.0.json"
}
]
}
json(conn, response)
end
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
def nodeinfo(conn, %{"version" => "2.0"}) do
stats = Stats.get_stats()
response = %{
version: "2.0",
software: %{
name: "pleroma",
version: Keyword.get(@instance, :version)
},
protocols: ["ostatus", "activitypub"],
services: %{
inbound: [],
outbound: []
},
openRegistrations: Keyword.get(@instance, :registrations_open),
usage: %{
users: %{
total: stats.user_count || 0
},
localPosts: stats.status_count || 0
},
metadata: %{
nodeName: Keyword.get(@instance, :name)
}
}
conn
|> put_resp_header(
"content-type",
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
)
|> json(response)
end
def nodeinfo(conn, _) do
conn
|> put_status(404)
|> json(%{error: "Nodeinfo schema version not handled"})
end
end

View file

@ -11,7 +11,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
field(:valid_until, :naive_datetime) field(:valid_until, :naive_datetime)
field(:used, :boolean, default: false) field(:used, :boolean, default: false)
belongs_to(:user, Pleroma.User) belongs_to(:user, Pleroma.User)
belongs_to(:app, Pleroma.App) belongs_to(:app, App)
timestamps() timestamps()
end end

View file

@ -9,7 +9,7 @@ defmodule Pleroma.Web.OAuth.Token do
field(:refresh_token, :string) field(:refresh_token, :string)
field(:valid_until, :naive_datetime) field(:valid_until, :naive_datetime)
belongs_to(:user, Pleroma.User) belongs_to(:user, Pleroma.User)
belongs_to(:app, Pleroma.App) belongs_to(:app, App)
timestamps() timestamps()
end end

View file

@ -1,7 +1,6 @@
defmodule Pleroma.Web.OStatus.ActivityRepresenter do defmodule Pleroma.Web.OStatus.ActivityRepresenter do
alias Pleroma.{Activity, User, Object} alias Pleroma.{Activity, User, Object}
alias Pleroma.Web.OStatus.UserRepresenter alias Pleroma.Web.OStatus.UserRepresenter
alias Pleroma.Formatter
require Logger require Logger
defp get_href(id) do defp get_href(id) do

View file

@ -1,7 +1,7 @@
defmodule Pleroma.Web.OStatus.NoteHandler do defmodule Pleroma.Web.OStatus.NoteHandler do
require Logger require Logger
alias Pleroma.Web.{XML, OStatus} alias Pleroma.Web.{XML, OStatus}
alias Pleroma.{Object, User, Activity} alias Pleroma.{Object, Activity}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI

View file

@ -8,7 +8,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do
alias Pleroma.Web.XML alias Pleroma.Web.XML
alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPubController
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
import Ecto.Query
def feed_redirect(conn, %{"nickname" => nickname} = params) do def feed_redirect(conn, %{"nickname" => nickname} = params) do
user = User.get_cached_by_nickname(nickname) user = User.get_cached_by_nickname(nickname)

View file

@ -295,6 +295,11 @@ defmodule Pleroma.Web.Router do
get("/host-meta", WebFinger.WebFingerController, :host_meta) get("/host-meta", WebFinger.WebFingerController, :host_meta)
get("/webfinger", WebFinger.WebFingerController, :webfinger) get("/webfinger", WebFinger.WebFingerController, :webfinger)
get("/nodeinfo", Nodeinfo.NodeinfoController, :schemas)
end
scope "/nodeinfo", Pleroma.Web do
get("/:version", Nodeinfo.NodeinfoController, :nodeinfo)
end end
end end

View file

@ -3,6 +3,10 @@ defmodule Pleroma.Web.Streamer do
require Logger require Logger
alias Pleroma.{User, Notification} alias Pleroma.{User, Notification}
def init(args) do
{:ok, args}
end
def start_link do def start_link do
spawn(fn -> spawn(fn ->
# 30 seconds # 30 seconds
@ -110,20 +114,26 @@ defmodule Pleroma.Web.Streamer do
def push_to_socket(topics, topic, item) do def push_to_socket(topics, topic, item) do
Enum.each(topics[topic] || [], fn socket -> Enum.each(topics[topic] || [], fn socket ->
json = # Get the current user so we have up-to-date blocks etc.
%{ user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
event: "update", blocks = user.info["blocks"] || []
payload:
Pleroma.Web.MastodonAPI.StatusView.render(
"status.json",
activity: item,
for: socket.assigns[:user]
)
|> Jason.encode!()
}
|> Jason.encode!()
send(socket.transport_pid, {:text, json}) unless item.actor in blocks do
json =
%{
event: "update",
payload:
Pleroma.Web.MastodonAPI.StatusView.render(
"status.json",
activity: item,
for: user
)
|> Jason.encode!()
}
|> Jason.encode!()
send(socket.transport_pid, {:text, json})
end
end) end)
end end

View file

@ -92,7 +92,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
with %User{} = user <- User.get_cached_by_nickname(username), with %User{} = user <- User.get_cached_by_nickname(username),
true <- Pbkdf2.checkpw(password, user.password_hash), true <- Pbkdf2.checkpw(password, user.password_hash),
%User{} = followed <- Repo.get(User, id), %User{} = _followed <- Repo.get(User, id),
{:ok, follower} <- User.follow(user, followee), {:ok, follower} <- User.follow(user, followee),
{:ok, _activity} <- ActivityPub.follow(follower, followee) do {:ok, _activity} <- ActivityPub.follow(follower, followee) do
conn conn

View file

@ -1,7 +1,6 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
alias Pleroma.{User, Activity, Repo, Object} alias Pleroma.{User, Activity, Repo, Object}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
alias Pleroma.Web.TwitterAPI.UserView alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.{OStatus, CommonAPI} alias Pleroma.Web.{OStatus, CommonAPI}
import Ecto.Query import Ecto.Query
@ -184,7 +183,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
defp parse_int(_, default), do: default defp parse_int(_, default), do: default
def search(user, %{"q" => query} = params) do def search(_user, %{"q" => query} = params) do
limit = parse_int(params["rpp"], 20) limit = parse_int(params["rpp"], 20)
page = parse_int(params["page"], 1) page = parse_int(params["page"], 1)
offset = (page - 1) * limit offset = (page - 1) * limit
@ -206,7 +205,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
order_by: [desc: :inserted_at] order_by: [desc: :inserted_at]
) )
activities = Repo.all(q) _activities = Repo.all(q)
end end
defp make_date do defp make_date do

View file

@ -347,7 +347,8 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
def update_profile(%{assigns: %{user: user}} = conn, params) do def update_profile(%{assigns: %{user: user}} = conn, params) do
params = params =
if bio = params["description"] do if bio = params["description"] do
Map.put(params, "bio", bio) bio_brs = Regex.replace(~r/\r?\n/, bio, "<br>")
Map.put(params, "bio", bio_brs)
else else
params params
end end

View file

@ -31,7 +31,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
end end
defp collect_context_ids(activities) do defp collect_context_ids(activities) do
contexts = _contexts =
activities activities
|> Enum.reject(& &1.data["context_id"]) |> Enum.reject(& &1.data["context_id"])
|> Enum.map(fn %{data: data} -> |> Enum.map(fn %{data: data} ->

View file

@ -2,7 +2,6 @@ defmodule Pleroma.Web.TwitterAPI.NotificationView do
use Pleroma.Web, :view use Pleroma.Web, :view
alias Pleroma.{Notification, User} alias Pleroma.{Notification, User}
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MediaProxy
alias Pleroma.Web.TwitterAPI.UserView alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.TwitterAPI.ActivityView alias Pleroma.Web.TwitterAPI.ActivityView

View file

@ -1,7 +1,7 @@
defmodule Pleroma.Web.WebFinger do defmodule Pleroma.Web.WebFinger do
@httpoison Application.get_env(:pleroma, :httpoison) @httpoison Application.get_env(:pleroma, :httpoison)
alias Pleroma.{Repo, User, XmlBuilder} alias Pleroma.{User, XmlBuilder}
alias Pleroma.Web alias Pleroma.Web
alias Pleroma.Web.{XML, Salmon, OStatus} alias Pleroma.Web.{XML, Salmon, OStatus}
require Jason require Jason
@ -239,13 +239,14 @@ defmodule Pleroma.Web.WebFinger do
URI.parse(account).host URI.parse(account).host
end end
case find_lrdd_template(domain) do address =
{:ok, template} -> case find_lrdd_template(domain) do
address = String.replace(template, "{uri}", URI.encode(account)) {:ok, template} ->
String.replace(template, "{uri}", URI.encode(account))
_ -> _ ->
address = "http://#{domain}/.well-known/webfinger?resource=acct:#{account}" "http://#{domain}/.well-known/webfinger?resource=acct:#{account}"
end end
with response <- with response <-
@httpoison.get( @httpoison.get(

View file

@ -14,7 +14,7 @@ defmodule Pleroma.Web.XML do
if res == "", do: nil, else: res if res == "", do: nil, else: res
catch catch
e -> _e ->
Logger.debug("Couldn't find xpath #{xpath} in XML doc") Logger.debug("Couldn't find xpath #{xpath} in XML doc")
nil nil
end end

View file

@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.6c8da1b0ace79ad8881a0e5e716ec818.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.cdeff2a56af285544b89.js></script><script type=text/javascript src=/static/js/vendor.ef2aee0b2db579c3a86a.js></script><script type=text/javascript src=/static/js/app.408cea515c3032097a51.js></script></body></html> <!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.6c8da1b0ace79ad8881a0e5e716ec818.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.38e369a50eccc2857845.js></script><script type=text/javascript src=/static/js/vendor.ef2aee0b2db579c3a86a.js></script><script type=text/javascript src=/static/js/app.af121efa5ff89725b4c6.js></script></body></html>

View file

@ -2,7 +2,8 @@
"theme": "pleroma-dark", "theme": "pleroma-dark",
"background": "/static/aurora_borealis.jpg", "background": "/static/aurora_borealis.jpg",
"logo": "/static/logo.png", "logo": "/static/logo.png",
"defaultPath": "/main/all", "redirectRootNoLogin": "/main/all",
"redirectRootLogin": "/main/friends",
"chatDisabled": false, "chatDisabled": false,
"showInstanceSpecificPanel": true "showInstanceSpecificPanel": false
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
!function(e){function t(a){if(r[a])return r[a].exports;var n=r[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a=window.webpackJsonp;window.webpackJsonp=function(o,c){for(var p,l,s=0,f=[];s<o.length;s++)l=o[s],n[l]&&f.push.apply(f,n[l]),n[l]=0;for(p in c)Object.prototype.hasOwnProperty.call(c,p)&&(e[p]=c[p]);for(a&&a(o,c);f.length;)f.shift().call(null,t);if(c[0])return r[0]=0,t(0)};var r={},n={0:0};t.e=function(e,a){if(0===n[e])return a.call(null,t);if(void 0!==n[e])n[e].push(a);else{n[e]=[a];var r=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.src=t.p+"static/js/"+e+"."+{1:"ef2aee0b2db579c3a86a",2:"af121efa5ff89725b4c6"}[e]+".js",r.appendChild(o)}},t.m=e,t.c=r,t.p="/"}([]);
//# sourceMappingURL=manifest.38e369a50eccc2857845.js.map

View file

@ -1,2 +0,0 @@
!function(e){function t(a){if(r[a])return r[a].exports;var n=r[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,l,s=0,i=[];s<c.length;s++)l=c[s],n[l]&&i.push.apply(i,n[l]),n[l]=0;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&(e[p]=o[p]);for(a&&a(c,o);i.length;)i.shift().call(null,t);if(o[0])return r[0]=0,t(0)};var r={},n={0:0};t.e=function(e,a){if(0===n[e])return a.call(null,t);if(void 0!==n[e])n[e].push(a);else{n[e]=[a];var r=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.src=t.p+"static/js/"+e+"."+{1:"ef2aee0b2db579c3a86a",2:"408cea515c3032097a51"}[e]+".js",r.appendChild(c)}},t.m=e,t.c=r,t.p="/"}([]);
//# sourceMappingURL=manifest.cdeff2a56af285544b89.js.map

View file

@ -33,6 +33,13 @@ defmodule Pleroma.NotificationTest do
assert nil == Notification.create_notification(activity, user) assert nil == Notification.create_notification(activity, user)
end end
test "it doesn't create a notification for user if he is the activity author" do
activity = insert(:note_activity)
author = User.get_by_ap_id(activity.data["actor"])
assert nil == Notification.create_notification(activity, author)
end
end end
describe "get notification" do describe "get notification" do

View file

@ -26,7 +26,7 @@ defmodule Pleroma.Builders.ActivityBuilder do
end end
def insert_list(times, data \\ %{}, opts \\ %{}) do def insert_list(times, data \\ %{}, opts \\ %{}) do
Enum.map(1..times, fn n -> Enum.map(1..times, fn _n ->
{:ok, activity} = insert(data, opts) {:ok, activity} = insert(data, opts)
activity activity
end) end)

View file

@ -367,7 +367,7 @@ defmodule HTTPoisonMock do
def post( def post(
"https://social.heldscal.la/main/push/hub", "https://social.heldscal.la/main/push/hub",
{:form, data}, {:form, _data},
"Content-type": "application/x-www-form-urlencoded" "Content-type": "application/x-www-form-urlencoded"
) do ) do
{:ok, {:ok,
@ -711,11 +711,11 @@ defmodule HTTPoisonMock do
}"} }"}
end end
def post(url, body, headers) do def post(url, _body, _headers) do
{:error, "Not implemented the mock response for post #{inspect(url)}"} {:error, "Not implemented the mock response for post #{inspect(url)}"}
end end
def post(url, body, headers, options) do def post(url, _body, _headers, _options) do
{:error, "Not implemented the mock response for post #{inspect(url)}"} {:error, "Not implemented the mock response for post #{inspect(url)}"}
end end
end end

View file

@ -63,7 +63,42 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
test "posting a status", %{conn: conn} do test "posting a status", %{conn: conn} do
user = insert(:user) user = insert(:user)
conn = idempotency_key = "Pikachu rocks!"
conn_one =
conn
|> assign(:user, user)
|> put_req_header("idempotency-key", idempotency_key)
|> post("/api/v1/statuses", %{
"status" => "cofe",
"spoiler_text" => "2hu",
"sensitive" => "false"
})
{:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
# Six hours
assert ttl > :timer.seconds(6 * 60 * 60 - 1)
assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
json_response(conn_one, 200)
assert Repo.get(Activity, id)
conn_two =
conn
|> assign(:user, user)
|> put_req_header("idempotency-key", idempotency_key)
|> post("/api/v1/statuses", %{
"status" => "cofe",
"spoiler_text" => "2hu",
"sensitive" => "false"
})
assert %{"id" => second_id} = json_response(conn_two, 200)
assert id == second_id
conn_three =
conn conn
|> assign(:user, user) |> assign(:user, user)
|> post("/api/v1/statuses", %{ |> post("/api/v1/statuses", %{
@ -72,10 +107,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
"sensitive" => "false" "sensitive" => "false"
}) })
assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = assert %{"id" => third_id} = json_response(conn_three, 200)
json_response(conn, 200)
assert Repo.get(Activity, id) refute id == third_id
end end
test "posting a sensitive status", %{conn: conn} do test "posting a sensitive status", %{conn: conn} do

View file

@ -0,0 +1,63 @@
defmodule Pleroma.Web.StreamerTest do
use Pleroma.DataCase
alias Pleroma.Web.Streamer
alias Pleroma.User
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
test "it sends to public" do
user = insert(:user)
other_user = insert(:user)
task =
Task.async(fn ->
assert_receive {:text, _}, 4_000
end)
fake_socket = %{
transport_pid: task.pid,
assigns: %{
user: user
}
}
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "Test"})
topics = %{
"public" => [fake_socket]
}
Streamer.push_to_socket(topics, "public", activity)
Task.await(task)
end
test "it doesn't send to blocked users" do
user = insert(:user)
blocked_user = insert(:user)
{:ok, user} = User.block(user, blocked_user)
task =
Task.async(fn ->
refute_receive {:text, _}, 1_000
end)
fake_socket = %{
transport_pid: task.pid,
assigns: %{
user: user
}
}
{:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"})
topics = %{
"public" => [fake_socket]
}
Streamer.push_to_socket(topics, "public", activity)
Task.await(task)
end
end

View file

@ -257,8 +257,10 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end end
test "with credentials", %{conn: conn, user: current_user} do test "with credentials", %{conn: conn, user: current_user} do
other_user = insert(:user)
{:ok, activity} = {:ok, activity} =
ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user}) ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
conn = conn =
conn conn
@ -784,4 +786,18 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
assert status["id"] == activity.id assert status["id"] == activity.id
end end
end end
test "Convert newlines to <br> in bio", %{conn: conn} do
user = insert(:user)
conn =
conn
|> assign(:user, user)
|> post("/api/account/update_profile.json", %{
"description" => "Hello,\r\nWorld! I\n am a test."
})
user = Repo.get!(User, user.id)
assert user.bio == "Hello,<br>World! I<br> am a test."
end
end end