2018-12-23 21:04:54 +01:00
# Pleroma: A lightweight social networking server
2020-03-03 23:44:49 +01:00
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
2018-12-23 21:04:54 +01:00
# SPDX-License-Identifier: AGPL-3.0-only
2018-05-10 18:34:09 +02:00
defmodule Pleroma.Web.ActivityPub.MRF do
2020-11-10 17:18:53 +01:00
require Logger
2020-12-16 17:51:48 +01:00
@behaviour Pleroma.Web.ActivityPub.MRF.PipelineFiltering
2020-11-11 08:10:57 +01:00
@mrf_config_descriptions [
%{
group : :pleroma ,
key : :mrf ,
tab : :mrf ,
label : " MRF " ,
type : :group ,
description : " General MRF settings " ,
children : [
%{
key : :policies ,
type : [ :module , { :list , :module } ] ,
description :
" A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name. " ,
suggestions : { :list_behaviour_implementations , Pleroma.Web.ActivityPub.MRF }
} ,
%{
key : :transparency ,
label : " MRF transparency " ,
type : :boolean ,
description :
" Make the content of your Message Rewrite Facility settings public (via nodeinfo) "
} ,
%{
key : :transparency_exclusions ,
label : " MRF transparency exclusions " ,
type : { :list , :string } ,
description :
" Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value. " ,
suggestions : [
" exclusion.com "
]
}
]
}
]
2020-11-10 17:18:53 +01:00
@default_description %{
label : " " ,
2020-11-11 08:10:57 +01:00
description : " "
2020-11-10 17:18:53 +01:00
}
@required_description_keys [ :key , :related_policy ]
2018-05-10 18:51:58 +02:00
@callback filter ( Map . t ( ) ) :: { :ok | :reject , Map . t ( ) }
2020-11-10 17:18:53 +01:00
@callback describe ( ) :: { :ok | :error , Map . t ( ) }
@callback config_description ( ) :: %{
optional ( :children ) = > [ map ( ) ] ,
key : atom ( ) ,
related_policy : String . t ( ) ,
label : String . t ( ) ,
description : String . t ( )
}
@optional_callbacks config_description : 0
2018-05-10 18:34:09 +02:00
2020-09-12 12:05:36 +02:00
def filter ( policies , %{ } = message ) do
2019-06-02 11:44:42 +02:00
policies
2020-09-12 12:05:36 +02:00
|> Enum . reduce ( { :ok , message } , fn
policy , { :ok , message } -> policy . filter ( message )
2020-02-11 10:53:24 +01:00
_ , error -> error
2018-05-10 18:34:09 +02:00
end )
end
2019-06-02 11:44:42 +02:00
def filter ( %{ } = object ) , do : get_policies ( ) |> filter ( object )
2020-12-16 17:51:48 +01:00
@impl true
2020-09-12 12:05:36 +02:00
def pipeline_filter ( %{ } = message , meta ) do
object = meta [ :object_data ]
ap_id = message [ " object " ]
if object && ap_id do
with { :ok , message } <- filter ( Map . put ( message , " object " , object ) ) do
meta = Keyword . put ( meta , :object_data , message [ " object " ] )
{ :ok , Map . put ( message , " object " , ap_id ) , meta }
else
{ err , message } -> { err , message , meta }
end
else
{ err , message } = filter ( message )
{ err , message , meta }
end
end
2019-03-05 04:18:43 +01:00
def get_policies do
2020-03-21 07:47:05 +01:00
Pleroma.Config . get ( [ :mrf , :policies ] , [ ] ) |> get_policies ( )
2018-05-10 18:34:09 +02:00
end
2018-05-10 18:51:58 +02:00
defp get_policies ( policy ) when is_atom ( policy ) , do : [ policy ]
defp get_policies ( policies ) when is_list ( policies ) , do : policies
defp get_policies ( _ ) , do : [ ]
2019-07-22 16:33:58 +02:00
@spec subdomains_regex ( [ String . t ( ) ] ) :: [ Regex . t ( ) ]
def subdomains_regex ( domains ) when is_list ( domains ) do
2019-08-10 23:18:26 +02:00
for domain <- domains , do : ~r( ^ #{ String . replace ( domain , " *. " , " (.* \\ .)* " ) } $ )i
2019-07-22 16:33:58 +02:00
end
@spec subdomain_match? ( [ Regex . t ( ) ] , String . t ( ) ) :: boolean ( )
def subdomain_match? ( domains , host ) do
Enum . any? ( domains , fn domain -> Regex . match? ( domain , host ) end )
end
2019-08-13 23:26:24 +02:00
def describe ( policies ) do
2019-08-13 23:52:54 +02:00
{ :ok , policy_configs } =
policies
|> Enum . reduce ( { :ok , %{ } } , fn
policy , { :ok , data } ->
{ :ok , policy_data } = policy . describe ( )
{ :ok , Map . merge ( data , policy_data ) }
2019-08-13 23:26:24 +02:00
2019-08-13 23:52:54 +02:00
_ , error ->
error
end )
mrf_policies =
get_policies ( )
|> Enum . map ( fn policy -> to_string ( policy ) |> String . split ( " . " ) |> List . last ( ) end )
2020-03-21 07:47:05 +01:00
exclusions = Pleroma.Config . get ( [ :mrf , :transparency_exclusions ] )
2019-08-13 23:52:54 +02:00
base =
%{
mrf_policies : mrf_policies ,
2019-08-14 00:36:24 +02:00
exclusions : length ( exclusions ) > 0
2019-08-13 23:52:54 +02:00
}
|> Map . merge ( policy_configs )
{ :ok , base }
2019-08-13 23:26:24 +02:00
end
2019-08-14 00:36:24 +02:00
def describe , do : get_policies ( ) |> describe ( )
2020-11-10 17:18:53 +01:00
def config_descriptions do
Pleroma.Web.ActivityPub.MRF
|> Pleroma.Docs.Generator . list_behaviour_implementations ( )
|> config_descriptions ( )
end
def config_descriptions ( policies ) do
2020-11-11 08:10:57 +01:00
Enum . reduce ( policies , @mrf_config_descriptions , fn policy , acc ->
2020-11-10 17:18:53 +01:00
if function_exported? ( policy , :config_description , 0 ) do
description =
@default_description
|> Map . merge ( policy . config_description )
|> Map . put ( :group , :pleroma )
|> Map . put ( :tab , :mrf )
|> Map . put ( :type , :group )
if Enum . all? ( @required_description_keys , & Map . has_key? ( description , &1 ) ) do
[ description | acc ]
else
Logger . warn (
" #{ policy } config description doesn't have one or all required keys #{
inspect ( @required_description_keys )
} "
)
acc
end
else
2020-11-11 16:49:15 +01:00
Logger . debug (
2020-11-10 17:18:53 +01:00
" #{ policy } is excluded from config descriptions, because does not implement `config_description/0` method. "
)
acc
end
end )
end
2018-05-10 18:34:09 +02:00
end