Merge branch 'develop' into feld-2168-media-preview-proxy

This commit is contained in:
Mark Felder 2020-08-25 11:57:23 -05:00
commit 479578b148
54 changed files with 1095 additions and 254 deletions

View file

@ -14,7 +14,7 @@ defmodule Mix.Pleroma do
:swoosh,
:timex
]
@cachex_children ["object", "user"]
@cachex_children ["object", "user", "scrubber"]
@doc "Common functions to be reused in mix tasks"
def start_pleroma do
Pleroma.Config.Holder.save_default()

View file

@ -15,7 +15,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
{options, [], []} = parse_global_opts(args)
url_or_path = options[:manifest] || default_manifest()
manifest = fetch_and_decode(url_or_path)
manifest = fetch_and_decode!(url_or_path)
Enum.each(manifest, fn {name, info} ->
to_print = [
@ -42,7 +42,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
url_or_path = options[:manifest] || default_manifest()
manifest = fetch_and_decode(url_or_path)
manifest = fetch_and_decode!(url_or_path)
for pack_name <- pack_names do
if Map.has_key?(manifest, pack_name) do
@ -92,7 +92,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
])
)
files = fetch_and_decode(files_loc)
files = fetch_and_decode!(files_loc)
IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
@ -243,9 +243,11 @@ defmodule Mix.Tasks.Pleroma.Emoji do
IO.puts("Emoji packs have been reloaded.")
end
defp fetch_and_decode(from) do
defp fetch_and_decode!(from) do
with {:ok, json} <- fetch(from) do
Jason.decode!(json)
else
{:error, error} -> raise "#{from} cannot be fetched. Error: #{error} occur."
end
end

View file

@ -0,0 +1,140 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Frontend do
use Mix.Task
import Mix.Pleroma
@shortdoc "Manages bundled Pleroma frontends"
@moduledoc File.read!("docs/administration/CLI_tasks/frontend.md")
def run(["install", "none" | _args]) do
shell_info("Skipping frontend installation because none was requested")
"none"
end
def run(["install", frontend | args]) do
log_level = Logger.level()
Logger.configure(level: :warn)
start_pleroma()
{options, [], []} =
OptionParser.parse(
args,
strict: [
ref: :string,
static_dir: :string,
build_url: :string,
build_dir: :string,
file: :string
]
)
instance_static_dir =
with nil <- options[:static_dir] do
Pleroma.Config.get!([:instance, :static_dir])
end
cmd_frontend_info = %{
"name" => frontend,
"ref" => options[:ref],
"build_url" => options[:build_url],
"build_dir" => options[:build_dir]
}
config_frontend_info = Pleroma.Config.get([:frontends, :available, frontend], %{})
frontend_info =
Map.merge(config_frontend_info, cmd_frontend_info, fn _key, config, cmd ->
# This only overrides things that are actually set
cmd || config
end)
ref = frontend_info["ref"]
unless ref do
raise "No ref given or configured"
end
dest =
Path.join([
instance_static_dir,
"frontends",
frontend,
ref
])
fe_label = "#{frontend} (#{ref})"
tmp_dir = Path.join(dest, "tmp")
with {_, :ok} <-
{:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, options[:file])},
shell_info("Installing #{fe_label} to #{dest}"),
:ok <- install_frontend(frontend_info, tmp_dir, dest) do
File.rm_rf!(tmp_dir)
shell_info("Frontend #{fe_label} installed to #{dest}")
Logger.configure(level: log_level)
else
{:download_or_unzip, _} ->
shell_info("Could not download or unzip the frontend")
_e ->
shell_info("Could not install the frontend")
end
end
defp download_or_unzip(frontend_info, temp_dir, file) do
if file do
with {:ok, zip} <- File.read(Path.expand(file)) do
unzip(zip, temp_dir)
end
else
download_build(frontend_info, temp_dir)
end
end
def unzip(zip, dest) do
with {:ok, unzipped} <- :zip.unzip(zip, [:memory]) do
File.rm_rf!(dest)
File.mkdir_p!(dest)
Enum.each(unzipped, fn {filename, data} ->
path = filename
new_file_path = Path.join(dest, path)
new_file_path
|> Path.dirname()
|> File.mkdir_p!()
File.write!(new_file_path, data)
end)
:ok
end
end
defp download_build(frontend_info, dest) do
shell_info("Downloading pre-built bundle for #{frontend_info["name"]}")
url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
with {:ok, %{status: 200, body: zip_body}} <-
Pleroma.HTTP.get(url, [], timeout: 120_000, recv_timeout: 120_000) do
unzip(zip_body, dest)
else
e -> {:error, e}
end
end
defp install_frontend(frontend_info, source, dest) do
from = frontend_info["build_dir"] || "dist"
File.mkdir_p!(dest)
File.cp_r!(Path.join([source, from]), dest)
:ok
end
end

View file

@ -35,10 +35,16 @@ defmodule Mix.Tasks.Pleroma.Relay do
def run(["list"]) do
start_pleroma()
with {:ok, list} <- Relay.list(true) do
list |> Enum.each(&shell_info(&1))
with {:ok, list} <- Relay.list() do
Enum.each(list, &print_relay_url/1)
else
{:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
end
end
defp print_relay_url(%{followed_back: false} = relay) do
shell_info("#{relay.actor} - no Accept received (relay didn't follow back)")
end
defp print_relay_url(relay), do: shell_info(relay.actor)
end

View file

@ -107,25 +107,34 @@ defmodule Pleroma.Emails.UserEmail do
|> Enum.filter(&(&1.activity.data["type"] == "Create"))
|> Enum.map(fn notification ->
object = Pleroma.Object.normalize(notification.activity)
object = update_in(object.data["content"], &format_links/1)
%{
data: notification,
object: object,
from: User.get_by_ap_id(notification.activity.actor)
}
if not is_nil(object) do
object = update_in(object.data["content"], &format_links/1)
%{
data: notification,
object: object,
from: User.get_by_ap_id(notification.activity.actor)
}
end
end)
|> Enum.filter(& &1)
followers =
notifications
|> Enum.filter(&(&1.activity.data["type"] == "Follow"))
|> Enum.map(fn notification ->
%{
data: notification,
object: Pleroma.Object.normalize(notification.activity),
from: User.get_by_ap_id(notification.activity.actor)
}
from = User.get_by_ap_id(notification.activity.actor)
if not is_nil(from) do
%{
data: notification,
object: Pleroma.Object.normalize(notification.activity),
from: User.get_by_ap_id(notification.activity.actor)
}
end
end)
|> Enum.filter(& &1)
unless Enum.empty?(mentions) do
styling = Config.get([__MODULE__, :styling])

View file

@ -264,4 +264,12 @@ defmodule Pleroma.FollowingRelationship do
end
end)
end
@spec following_ap_ids(User.t()) :: [String.t()]
def following_ap_ids(%User{} = user) do
user
|> following_query()
|> select([r, u], u.ap_id)
|> Repo.all()
end
end

View file

@ -30,6 +30,7 @@ defmodule Pleroma.Plugs.FrontendStatic do
opts
|> Keyword.put(:from, "__unconfigured_frontend_static_plug")
|> Plug.Static.init()
|> Map.put(:frontend_type, opts[:frontend_type])
end
def call(conn, opts) do

View file

@ -56,6 +56,15 @@ defmodule Pleroma.Upload do
}
defstruct [:id, :name, :tempfile, :content_type, :path]
defp get_description(opts, upload) do
case {opts[:description], Pleroma.Config.get([Pleroma.Upload, :default_description])} do
{description, _} when is_binary(description) -> description
{_, :filename} -> upload.name
{_, str} when is_binary(str) -> str
_ -> ""
end
end
@spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()}
def store(upload, opts \\ []) do
opts = get_opts(opts)
@ -63,7 +72,7 @@ defmodule Pleroma.Upload do
with {:ok, upload} <- prepare_upload(upload, opts),
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
{:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload),
description = Map.get(opts, :description) || upload.name,
description = get_description(opts, upload),
{_, true} <-
{:description_limit,
String.length(description) <= Pleroma.Config.get([:instance, :description_limit])},

View file

@ -247,6 +247,13 @@ defmodule Pleroma.User do
end
end
defdelegate following_count(user), to: FollowingRelationship
defdelegate following(user), to: FollowingRelationship
defdelegate following?(follower, followed), to: FollowingRelationship
defdelegate following_ap_ids(user), to: FollowingRelationship
defdelegate get_follow_requests(user), to: FollowingRelationship
defdelegate search(query, opts \\ []), to: User.Search
@doc """
Dumps Flake Id to SQL-compatible format (16-byte UUID).
E.g. "9pQtDGXuq4p3VlcJEm" -> <<0, 0, 1, 110, 179, 218, 42, 92, 213, 41, 44, 227, 95, 213, 0, 0>>
@ -372,8 +379,6 @@ defmodule Pleroma.User do
from(u in query, where: u.deactivated != ^true)
end
defdelegate following_count(user), to: FollowingRelationship
defp truncate_fields_param(params) do
if Map.has_key?(params, :fields) do
Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
@ -868,8 +873,6 @@ defmodule Pleroma.User do
set_cache(follower)
end
defdelegate following(user), to: FollowingRelationship
def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do
deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
@ -923,8 +926,6 @@ defmodule Pleroma.User do
end
end
defdelegate following?(follower, followed), to: FollowingRelationship
@doc "Returns follow state as Pleroma.FollowingRelationship.State value"
def get_follow_state(%User{} = follower, %User{} = following) do
following_relationship = FollowingRelationship.get(follower, following)
@ -1189,8 +1190,6 @@ defmodule Pleroma.User do
|> Repo.all()
end
defdelegate get_follow_requests(user), to: FollowingRelationship
def increase_note_count(%User{} = user) do
User
|> where(id: ^user.id)
@ -2163,8 +2162,6 @@ defmodule Pleroma.User do
|> Repo.all()
end
defdelegate search(query, opts \\ []), to: User.Search
defp put_password_hash(
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
) do

View file

@ -85,7 +85,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp increase_replies_count_if_reply(_create_data), do: :noop
@object_types ["ChatMessage", "Question", "Answer"]
@object_types ~w[ChatMessage Question Answer Audio Event]
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
def persist(%{"type" => type} = object, meta) when type in @object_types do
with {:ok, object} <- Object.create(object) do
@ -1344,9 +1344,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
def maybe_handle_clashing_nickname(data) do
nickname = data[:nickname]
with %User{} = old_user <- User.get_by_nickname(nickname),
with nickname when is_binary(nickname) <- data[:nickname],
%User{} = old_user <- User.get_by_nickname(nickname),
{_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do
Logger.info(
"Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{
@ -1360,7 +1359,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
else
{:ap_id_comparison, true} ->
Logger.info(
"Found an old user for #{nickname}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
"Found an old user for #{data[:nickname]}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
)
_ ->

View file

@ -215,7 +215,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
to =
cond do
actor.ap_id == Relay.relay_ap_id() ->
actor.ap_id == Relay.ap_id() ->
[actor.follower_address]
public? ->

View file

@ -23,6 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
@ -43,6 +44,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
end
end
def validate(%{"type" => "Event"} = object, meta) do
with {:ok, object} <-
object
|> EventValidator.cast_and_validate()
|> Ecto.Changeset.apply_action(:insert) do
object = stringify_keys(object)
{:ok, object, meta}
end
end
def validate(%{"type" => "Follow"} = object, meta) do
with {:ok, object} <-
object
@ -187,7 +198,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
%{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity,
meta
)
when objtype in ~w[Question Answer Audio] do
when objtype in ~w[Question Answer Audio Event] do
with {:ok, object_data} <- cast_and_apply(object),
meta = Keyword.put(meta, :object_data, object_data |> stringify_keys),
{:ok, create_activity} <-
@ -225,6 +236,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
AudioValidator.cast_and_apply(object)
end
def cast_and_apply(%{"type" => "Event"} = object) do
EventValidator.cast_and_apply(object)
end
def cast_and_apply(o), do: {:error, {:validator_not_set, o}}
# is_struct/1 isn't present in Elixir 1.8.x

View file

@ -41,34 +41,34 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
end
def fix_media_type(data) do
data =
data
|> Map.put_new("mediaType", data["mimeType"])
data = Map.put_new(data, "mediaType", data["mimeType"])
if MIME.valid?(data["mediaType"]) do
data
else
data
|> Map.put("mediaType", "application/octet-stream")
Map.put(data, "mediaType", "application/octet-stream")
end
end
def fix_url(data) do
case data["url"] do
url when is_binary(url) ->
data
|> Map.put(
"url",
[
%{
"href" => url,
"type" => "Link",
"mediaType" => data["mediaType"]
}
]
)
defp handle_href(href, mediaType) do
[
%{
"href" => href,
"type" => "Link",
"mediaType" => mediaType
}
]
end
_ ->
defp fix_url(data) do
cond do
is_binary(data["url"]) ->
Map.put(data, "url", handle_href(data["url"], data["mediaType"]))
is_binary(data["href"]) and data["url"] == nil ->
Map.put(data, "url", handle_href(data["href"], data["mediaType"]))
true ->
data
end
end

View file

@ -41,7 +41,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, :string)
field(:uri, ObjectValidators.Uri)
field(:url, ObjectValidators.Uri)
# short identifier for PleromaFE to group statuses by context
field(:context_id, :integer)
@ -66,10 +66,24 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
|> changeset(data)
end
defp fix_url(%{"url" => url} = data) when is_list(url) do
attachment =
Enum.find(url, fn x -> is_map(x) and String.starts_with?(x["mimeType"], "audio/") end)
link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
data
|> Map.put("attachment", [attachment])
|> Map.put("url", link_element["href"])
end
defp fix_url(data), do: data
defp fix(data) do
data
|> CommonFixes.fix_defaults()
|> CommonFixes.fix_attribution()
|> fix_url()
end
def changeset(struct, data) do
@ -83,7 +97,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Audio"])
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|> validate_required([:id, :actor, :attributedTo, :type, :context, :attachment])
|> CommonValidations.validate_any_presence([:cc, :to])
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|> CommonValidations.validate_actor_presence()

View file

@ -61,9 +61,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
end
end
defp fix_addressing(data, meta) do
if object = meta[:object_data] do
data
|> Map.put_new("to", object["to"] || [])
|> Map.put_new("cc", object["cc"] || [])
else
data
end
end
defp fix(data, meta) do
data
|> fix_context(meta)
|> fix_addressing(meta)
end
def validate_data(cng, meta \\ []) do

View file

@ -0,0 +1,96 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do
use Ecto.Schema
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
import Ecto.Changeset
@primary_key false
@derive Jason.Encoder
# Extends from NoteValidator
embedded_schema do
field(:id, ObjectValidators.ObjectID, primary_key: true)
field(:to, ObjectValidators.Recipients, default: [])
field(:cc, ObjectValidators.Recipients, default: [])
field(:bto, ObjectValidators.Recipients, default: [])
field(:bcc, ObjectValidators.Recipients, default: [])
# TODO: Write type
field(:tag, {:array, :map}, default: [])
field(:type, :string)
field(:name, :string)
field(:summary, :string)
field(:content, :string)
field(:context, :string)
# short identifier for PleromaFE to group statuses by context
field(:context_id, :integer)
# TODO: Remove actor on objects
field(:actor, ObjectValidators.ObjectID)
field(:attributedTo, ObjectValidators.ObjectID)
field(:published, ObjectValidators.DateTime)
# TODO: Write type
field(:emoji, :map, default: %{})
field(:sensitive, :boolean, default: false)
embeds_many(:attachment, AttachmentValidator)
field(:replies_count, :integer, default: 0)
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
field(:url, ObjectValidators.Uri)
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
end
def cast_and_apply(data) do
data
|> cast_data
|> apply_action(:insert)
end
def cast_and_validate(data) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> changeset(data)
end
defp fix(data) do
data
|> CommonFixes.fix_defaults()
|> CommonFixes.fix_attribution()
end
def changeset(struct, data) do
data = fix(data)
struct
|> cast(data, __schema__(:fields) -- [:attachment])
|> cast_embed(:attachment)
end
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Event"])
|> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id])
|> CommonValidations.validate_any_presence([:cc, :to])
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|> CommonValidations.validate_actor_presence()
|> CommonValidations.validate_host_match()
end
end

View file

@ -20,11 +20,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
# TODO: Write type
field(:tag, {:array, :map}, default: [])
field(:type, :string)
field(:name, :string)
field(:summary, :string)
field(:content, :string)
field(:context, :string)
# short identifier for PleromaFE to group statuses by context
field(:context_id, :integer)
field(:actor, ObjectValidators.ObjectID)
field(:attributedTo, ObjectValidators.ObjectID)
field(:summary, :string)
field(:published, ObjectValidators.DateTime)
# TODO: Write type
field(:emoji, :map, default: %{})
@ -35,13 +41,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
field(:uri, ObjectValidators.Uri)
field(:url, ObjectValidators.Uri)
field(:likes, {:array, :string}, default: [])
field(:announcements, {:array, :string}, default: [])
# see if needed
field(:context_id, :string)
end
def cast_and_validate(data) do

View file

@ -43,7 +43,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
field(:uri, ObjectValidators.Uri)
field(:url, ObjectValidators.Uri)
# short identifier for PleromaFE to group statuses by context
field(:context_id, :integer)

View file

@ -10,19 +10,13 @@ defmodule Pleroma.Web.ActivityPub.Relay do
alias Pleroma.Web.CommonAPI
require Logger
@relay_nickname "relay"
@nickname "relay"
def get_actor do
actor =
relay_ap_id()
|> User.get_or_create_service_actor_by_ap_id(@relay_nickname)
@spec ap_id() :: String.t()
def ap_id, do: "#{Pleroma.Web.Endpoint.url()}/#{@nickname}"
actor
end
def relay_ap_id do
"#{Pleroma.Web.Endpoint.url()}/relay"
end
@spec get_actor() :: User.t() | nil
def get_actor, do: User.get_or_create_service_actor_by_ap_id(ap_id(), @nickname)
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
def follow(target_instance) do
@ -61,34 +55,38 @@ defmodule Pleroma.Web.ActivityPub.Relay do
def publish(_), do: {:error, "Not implemented"}
@spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()}
def list(with_not_accepted \\ false) do
@spec list() :: {:ok, [%{actor: String.t(), followed_back: boolean()}]} | {:error, any()}
def list do
with %User{} = user <- get_actor() do
accepted =
user
|> User.following()
|> Enum.map(fn entry -> URI.parse(entry).host end)
|> following()
|> Enum.map(fn actor -> %{actor: actor, followed_back: true} end)
without_accept =
user
|> Pleroma.Activity.following_requests_for_actor()
|> Enum.map(fn activity -> %{actor: activity.data["object"], followed_back: false} end)
|> Enum.uniq()
list =
if with_not_accepted do
without_accept =
user
|> Pleroma.Activity.following_requests_for_actor()
|> Enum.map(fn a -> URI.parse(a.data["object"]).host <> " (no Accept received)" end)
|> Enum.uniq()
accepted ++ without_accept
else
accepted
end
{:ok, list}
{:ok, accepted ++ without_accept}
else
error -> format_error(error)
end
end
@spec following() :: [String.t()]
def following do
get_actor()
|> following()
end
defp following(user) do
user
|> User.following_ap_ids()
|> Enum.uniq()
end
defp format_error({:error, error}), do: format_error(error)
defp format_error(error) do

View file

@ -341,7 +341,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end
def handle_object_creation(%{"type" => objtype} = object, meta)
when objtype in ~w[Audio Question] do
when objtype in ~w[Audio Question Event] do
with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
{:ok, object, meta}
end

View file

@ -276,13 +276,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
Map.put(object, "url", url["href"])
end
def fix_url(%{"type" => object_type, "url" => url} = object)
when object_type in ["Video", "Audio"] and is_list(url) do
def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do
attachment =
Enum.find(url, fn x ->
media_type = x["mediaType"] || x["mimeType"] || ""
is_map(x) and String.starts_with?(media_type, ["audio/", "video/"])
is_map(x) and String.starts_with?(media_type, "video/")
end)
link_element =
@ -461,7 +460,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Create", "object" => %{"type" => objtype} = object} = data,
options
)
when objtype in ~w{Article Event Note Video Page} do
when objtype in ~w{Article Note Video Page} do
actor = Containment.get_actor(data)
with nil <- Activity.get_create_by_object_ap_id(object["id"]),
@ -555,7 +554,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Create", "object" => %{"type" => objtype}} = data,
_options
)
when objtype in ~w{Question Answer ChatMessage Audio} do
when objtype in ~w{Question Answer ChatMessage Audio Event} do
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
{:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}

View file

@ -39,7 +39,7 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
target: target
})
json(conn, target)
json(conn, %{actor: target, followed_back: target in Relay.following()})
else
_ ->
conn

View file

@ -79,7 +79,8 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
"confirmation_pending" => user.confirmation_pending,
"approval_pending" => user.approval_pending,
"url" => user.uri || user.ap_id,
"registration_reason" => user.registration_reason
"registration_reason" => user.registration_reason,
"actor_type" => user.actor_type
}
end

View file

@ -27,8 +27,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
properties: %{
relays: %Schema{
type: :array,
items: %Schema{type: :string},
example: ["lain.com", "mstdn.io"]
items: relay()
}
}
})
@ -43,19 +42,9 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
operationId: "AdminAPI.RelayController.follow",
security: [%{"oAuth" => ["write:follows"]}],
parameters: admin_api_params(),
requestBody:
request_body("Parameters", %Schema{
type: :object,
properties: %{
relay_url: %Schema{type: :string, format: :uri}
}
}),
requestBody: request_body("Parameters", relay_url()),
responses: %{
200 =>
Operation.response("Status", "application/json", %Schema{
type: :string,
example: "http://mastodon.example.org/users/admin"
})
200 => Operation.response("Status", "application/json", relay())
}
}
end
@ -67,13 +56,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
operationId: "AdminAPI.RelayController.unfollow",
security: [%{"oAuth" => ["write:follows"]}],
parameters: admin_api_params(),
requestBody:
request_body("Parameters", %Schema{
type: :object,
properties: %{
relay_url: %Schema{type: :string, format: :uri}
}
}),
requestBody: request_body("Parameters", relay_url()),
responses: %{
200 =>
Operation.response("Status", "application/json", %Schema{
@ -83,4 +66,29 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
}
}
end
defp relay do
%Schema{
type: :object,
properties: %{
actor: %Schema{
type: :string,
example: "https://example.com/relay"
},
followed_back: %Schema{
type: :boolean,
description: "Is relay followed back by this actor?"
}
}
}
end
defp relay_url do
%Schema{
type: :object,
properties: %{
relay_url: %Schema{type: :string, format: :uri}
}
}
end
end

View file

@ -39,6 +39,18 @@ defmodule Pleroma.Web.Endpoint do
}
)
plug(Plug.Static.IndexHtml, at: "/pleroma/admin/")
plug(Pleroma.Plugs.FrontendStatic,
at: "/pleroma/admin",
frontend_type: :admin,
gzip: true,
cache_control_for_etags: @static_cache_control,
headers: %{
"cache-control" => @static_cache_control
}
)
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phoenix.digest
@ -56,8 +68,6 @@ defmodule Pleroma.Web.Endpoint do
}
)
plug(Plug.Static.IndexHtml, at: "/pleroma/admin/")
plug(Plug.Static,
at: "/pleroma/admin/",
from: {:pleroma, "priv/static/adminfe/"}

View file

@ -474,23 +474,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
end
def render_content(%{data: %{"type" => object_type}} = object)
when object_type in ["Video", "Event", "Audio"] do
with name when not is_nil(name) and name != "" <- object.data["name"] do
"<p><a href=\"#{object.data["id"]}\">#{name}</a></p>#{object.data["content"]}"
else
_ -> object.data["content"] || ""
end
end
def render_content(%{data: %{"name" => name}} = object) when not is_nil(name) and name != "" do
url = object.data["url"] || object.data["id"]
def render_content(%{data: %{"type" => object_type}} = object)
when object_type in ["Article", "Page"] do
with summary when not is_nil(summary) and summary != "" <- object.data["name"],
url when is_bitstring(url) <- object.data["url"] do
"<p><a href=\"#{url}\">#{summary}</a></p>#{object.data["content"]}"
else
_ -> object.data["content"] || ""
end
"<p><a href=\"#{url}\">#{name}</a></p>#{object.data["content"]}"
end
def render_content(object), do: object.data["content"] || ""