Merge branch 'feature/custom-runtime-modules' into 'develop'
Add support for custom modules at runtime Closes #1448 See merge request pleroma/pleroma!2039
This commit is contained in:
commit
c51e93978e
|
@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Deprecated `User.Info` embedded schema (fields moved to `User`)
|
||||
- Store status data inside Flag activity
|
||||
- Deprecated (reorganized as `UserRelationship` entity) User fields with user AP IDs (`blocks`, `mutes`, `muted_reblogs`, `muted_notifications`, `subscribers`).
|
||||
- Logger: default log level changed from `warn` to `info`.
|
||||
<details>
|
||||
<summary>API Changes</summary>
|
||||
|
||||
|
@ -51,6 +52,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Support for `X-Forwarded-For` and similar HTTP headers which used by reverse proxies to pass a real user IP address to the backend. Must not be enabled unless your instance is behind at least one reverse proxy (such as Nginx, Apache HTTPD or Varnish Cache).
|
||||
- MRF: New module which handles incoming posts based on their age. By default, all incoming posts that are older than 2 days will be unlisted and not shown to their followers.
|
||||
- User notification settings: Add `privacy_option` option.
|
||||
- Support for custom Elixir modules (such as MRF policies)
|
||||
- User settings: Add _This account is a_ option.
|
||||
- OAuth: admin scopes support (relevant setting: `[:auth, :enforce_oauth_admin_scope_usage]`).
|
||||
<details>
|
||||
|
|
|
@ -621,6 +621,8 @@
|
|||
activity_pub: nil,
|
||||
activity_pub_question: 30_000
|
||||
|
||||
config :pleroma, :modules, runtime_dir: "instance/modules"
|
||||
|
||||
config :swarm, node_blacklist: [~r/myhtml_.*$/]
|
||||
# Import environment specific config. This must remain at the bottom
|
||||
# of this file so it overrides the configuration defined above.
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
config :phoenix, serve_endpoints: true
|
||||
|
||||
# Do not print debug messages in production
|
||||
config :logger, :console, level: :warn
|
||||
config :logger, :ex_syslogger, level: :warn
|
||||
config :logger, :console, level: :info
|
||||
config :logger, :ex_syslogger, level: :info
|
||||
|
||||
# ## SSL Support
|
||||
#
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
|
||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
|
||||
config :pleroma, :modules, runtime_dir: "/var/lib/pleroma/modules"
|
||||
|
||||
config_path = System.get_env("PLEROMA_CONFIG_PATH") || "/etc/pleroma/config.exs"
|
||||
|
||||
|
|
|
@ -95,6 +95,8 @@
|
|||
|
||||
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
||||
|
||||
config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
|
||||
|
||||
if File.exists?("./config/test.secret.exs") do
|
||||
import_config "test.secret.exs"
|
||||
else
|
||||
|
|
|
@ -836,3 +836,7 @@ config :auto_linker,
|
|||
rel: "ugc"
|
||||
]
|
||||
```
|
||||
|
||||
## Custom Runtime Modules (`:modules`)
|
||||
|
||||
* `runtime_dir`: A path to custom Elixir modules (such as MRF policies).
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.Application do
|
||||
import Cachex.Spec
|
||||
use Application
|
||||
require Logger
|
||||
|
||||
@name Mix.Project.config()[:name]
|
||||
@version Mix.Project.config()[:version]
|
||||
|
@ -33,6 +34,7 @@ def start(_type, _args) do
|
|||
Pleroma.HTML.compile_scrubbers()
|
||||
Pleroma.Config.DeprecationWarnings.warn()
|
||||
setup_instrumenters()
|
||||
load_custom_modules()
|
||||
|
||||
# Define workers and child supervisors to be supervised
|
||||
children =
|
||||
|
@ -68,6 +70,28 @@ def start(_type, _args) do
|
|||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
|
||||
def load_custom_modules do
|
||||
dir = Pleroma.Config.get([:modules, :runtime_dir])
|
||||
|
||||
if dir && File.exists?(dir) do
|
||||
dir
|
||||
|> Pleroma.Utils.compile_dir()
|
||||
|> case do
|
||||
{:error, _errors, _warnings} ->
|
||||
raise "Invalid custom modules"
|
||||
|
||||
{:ok, modules, _warnings} ->
|
||||
if @env != :test do
|
||||
Enum.each(modules, fn mod ->
|
||||
Logger.info("Custom module loaded: #{inspect(mod)}")
|
||||
end)
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp setup_instrumenters do
|
||||
require Prometheus.Registry
|
||||
|
||||
|
|
|
@ -10,9 +10,7 @@ def compile_scrubbers do
|
|||
dir = Path.join(:code.priv_dir(:pleroma), "scrubbers")
|
||||
|
||||
dir
|
||||
|> File.ls!()
|
||||
|> Enum.map(&Path.join(dir, &1))
|
||||
|> Kernel.ParallelCompiler.compile()
|
||||
|> Pleroma.Utils.compile_dir()
|
||||
|> case do
|
||||
{:error, _errors, _warnings} ->
|
||||
raise "Compiling scrubbers failed"
|
||||
|
|
|
@ -154,7 +154,7 @@ defp maybe_date_fetch(headers, date) do
|
|||
end
|
||||
|
||||
def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
|
||||
Logger.info("Fetching object #{id} via AP")
|
||||
Logger.debug("Fetching object #{id} via AP")
|
||||
|
||||
date = Pleroma.Signature.signed_date()
|
||||
|
||||
|
|
12
lib/pleroma/utils.ex
Normal file
12
lib/pleroma/utils.ex
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Utils do
|
||||
def compile_dir(dir) when is_binary(dir) do
|
||||
dir
|
||||
|> File.ls!()
|
||||
|> Enum.map(&Path.join(dir, &1))
|
||||
|> Kernel.ParallelCompiler.compile()
|
||||
end
|
||||
end
|
|
@ -257,7 +257,7 @@ def inbox(%{assigns: %{valid_signature: true}} = conn, params) do
|
|||
|
||||
# only accept relayed Creates
|
||||
def inbox(conn, %{"type" => "Create"} = params) do
|
||||
Logger.info(
|
||||
Logger.debug(
|
||||
"Signature missing or not from author, relayed Create message, fetching object from source"
|
||||
)
|
||||
|
||||
|
@ -270,11 +270,11 @@ def inbox(conn, params) do
|
|||
headers = Enum.into(conn.req_headers, %{})
|
||||
|
||||
if String.contains?(headers["signature"], params["actor"]) do
|
||||
Logger.info(
|
||||
Logger.debug(
|
||||
"Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
|
||||
)
|
||||
|
||||
Logger.info(inspect(conn.req_headers))
|
||||
Logger.debug(inspect(conn.req_headers))
|
||||
end
|
||||
|
||||
json(conn, dgettext("errors", "error"))
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(object) do
|
||||
Logger.info("REJECTING #{inspect(object)}")
|
||||
Logger.debug("REJECTING #{inspect(object)}")
|
||||
{:reject, object}
|
||||
end
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
|
|||
]
|
||||
|
||||
def perform(:prefetch, url) do
|
||||
Logger.info("Prefetching #{inspect(url)}")
|
||||
Logger.debug("Prefetching #{inspect(url)}")
|
||||
|
||||
url
|
||||
|> MediaProxy.url()
|
||||
|
|
|
@ -48,7 +48,7 @@ def is_representable?(%Activity{} = activity) do
|
|||
* `id`: the ActivityStreams URI of the message
|
||||
"""
|
||||
def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
|
||||
Logger.info("Federating #{id} to #{inbox}")
|
||||
Logger.debug("Federating #{id} to #{inbox}")
|
||||
%{host: host, path: path} = URI.parse(inbox)
|
||||
|
||||
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
|
||||
|
@ -228,7 +228,7 @@ def publish(%User{} = actor, %Activity{} = activity) do
|
|||
public = is_public?(activity)
|
||||
|
||||
if public && Config.get([:instance, :allow_relay]) do
|
||||
Logger.info(fn -> "Relaying #{activity.data["id"]} out" end)
|
||||
Logger.debug(fn -> "Relaying #{activity.data["id"]} out" end)
|
||||
Relay.publish(activity)
|
||||
end
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ defmodule Pleroma.Web.Endpoint do
|
|||
|
||||
plug(Pleroma.Plugs.TrailingFormatPlug)
|
||||
plug(Plug.RequestId)
|
||||
plug(Plug.Logger)
|
||||
plug(Plug.Logger, log: :debug)
|
||||
|
||||
plug(Pleroma.Plugs.Parsers)
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ def perform(:publish, activity) do
|
|||
end
|
||||
|
||||
def perform(:incoming_ap_doc, params) do
|
||||
Logger.info("Handling incoming AP activity")
|
||||
Logger.debug("Handling incoming AP activity")
|
||||
|
||||
params = Utils.normalize_params(params)
|
||||
|
||||
|
@ -71,13 +71,13 @@ def perform(:incoming_ap_doc, params) do
|
|||
{:ok, activity}
|
||||
else
|
||||
%Activity{} ->
|
||||
Logger.info("Already had #{params["id"]}")
|
||||
Logger.debug("Already had #{params["id"]}")
|
||||
:error
|
||||
|
||||
_e ->
|
||||
# Just drop those for now
|
||||
Logger.info("Unhandled activity")
|
||||
Logger.info(Jason.encode!(params, pretty: true))
|
||||
Logger.debug("Unhandled activity")
|
||||
Logger.debug(Jason.encode!(params, pretty: true))
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,7 +47,7 @@ def publish(%User{} = user, %Activity{} = activity) do
|
|||
Config.get([:instance, :federation_publisher_modules])
|
||||
|> Enum.each(fn module ->
|
||||
if module.is_representable?(activity) do
|
||||
Logger.info("Publishing #{activity.data["id"]} using #{inspect(module)}")
|
||||
Logger.debug("Publishing #{activity.data["id"]} using #{inspect(module)}")
|
||||
module.publish(user, activity)
|
||||
end
|
||||
end)
|
||||
|
|
9
test/fixtures/modules/runtime_module.ex
vendored
Normal file
9
test/fixtures/modules/runtime_module.ex
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule RuntimeModule do
|
||||
@moduledoc """
|
||||
This is a dummy module to test custom runtime modules.
|
||||
"""
|
||||
end
|
11
test/runtime_test.exs
Normal file
11
test/runtime_test.exs
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.RuntimeTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
test "it loads custom runtime modules" do
|
||||
assert Code.ensure_compiled?(RuntimeModule)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue