Merge branch 'develop' into admin-be
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Tue, 14 Jan 2020 11:52:00 +0000 (14:52 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Tue, 14 Jan 2020 11:52:00 +0000 (14:52 +0300)
1  2 
config/config.exs
config/description.exs
lib/pleroma/web/router.ex

diff --combined config/config.exs
index df677c2e052e2e6d38964d9f3c92468388bcd68a,d41abf09099447de593135de309f35840fb9038d..0a8f1465c9c6937f274ed1e16639ef0662e561e0
@@@ -108,10 -108,6 +108,6 @@@ config :pleroma, Pleroma.Uploaders.S3
    streaming_enabled: true,
    public_endpoint: "https://s3.amazonaws.com"
  
- config :pleroma, Pleroma.Uploaders.MDII,
-   cgi: "https://mdii.sakura.ne.jp/mdii-post.cgi",
-   files: "https://mdii.sakura.ne.jp"
  config :pleroma, :emoji,
    shortcode_globs: ["/emoji/custom/**/*.png"],
    pack_extensions: [".png", ".gif"],
@@@ -269,6 -265,7 +265,6 @@@ config :pleroma, :instance
    remote_post_retention_days: 90,
    skip_thread_containment: true,
    limit_to_local_content: :unauthenticated,
 -  dynamic_configuration: false,
    user_bio_length: 5000,
    user_name_length: 100,
    max_account_fields: 10,
@@@ -622,8 -619,6 +618,8 @@@ config :pleroma, :web_cache_ttl
  
  config :pleroma, :modules, runtime_dir: "instance/modules"
  
 +config :pleroma, configurable_from_database: false
 +
  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.
diff --combined config/description.exs
index 3c5febf0539915289fa089d599b5de4c18b4e683,1089fd86c5536cbd0b2e632b9d4a529cb9046030..5de9392d2c15e93dddd7a1b14ce999acbfbc4600
@@@ -23,17 -23,17 +23,17 @@@ config :pleroma, :config_description, 
          key: :uploader,
          type: :module,
          description: "Module which will be used for uploads",
 -        suggestions: [
 -          Generator.uploaders_list()
 -        ]
 +        suggestions: [Pleroma.Uploaders.Local, Pleroma.Uploaders.MDII, Pleroma.Uploaders.S3]
        },
        %{
          key: :filters,
          type: {:list, :module},
          description: "List of filter modules for uploads",
 -        suggestions: [
 -          Generator.filters_list()
 -        ]
 +        suggestions:
 +          Generator.list_modules_in_dir(
 +            "lib/pleroma/upload/filter",
 +            "Elixir.Pleroma.Upload.Filter."
 +          )
        },
        %{
          key: :link_name,
        %{
          key: :proxy_opts,
          type: :keyword,
 -        description: "Proxy options, see `Pleroma.ReverseProxy` documentation"
 +        description: "Options for Pleroma.ReverseProxy",
 +        suggestions: [
 +          redirect_on_failure: false,
 +          max_body_length: 25 * 1_048_576,
 +          http: [
 +            follow_redirect: true,
 +            pool: :media
 +          ]
 +        ],
 +        children: [
 +          %{
 +            key: :redirect_on_failure,
 +            type: :boolean,
 +            description:
 +              "Redirects the client to the real remote URL if there's any HTTP errors. " <>
 +                "Any error during body processing will not be redirected as the response is chunked"
 +          },
 +          %{
 +            key: :max_body_length,
 +            type: :integer,
 +            description:
 +              "limits the content length to be approximately the " <>
 +                "specified length. It is validated with the `content-length` header and also verified when proxying"
 +          },
 +          %{
 +            key: :http,
 +            type: :keyword,
 +            description: "HTTP options",
 +            children: [
 +              %{
 +                key: :adapter,
 +                type: :keyword,
 +                description: "Adapter specific options",
 +                children: [
 +                  %{
 +                    key: :ssl_options,
 +                    type: :keyword,
 +                    label: "SSL Options",
 +                    description: "SSL options for HTTP adapter",
 +                    children: [
 +                      %{
 +                        key: :versions,
 +                        type: {:list, :atom},
 +                        description: "List of TLS version to use",
 +                        suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2"]
 +                      }
 +                    ]
 +                  }
 +                ]
 +              },
 +              %{
 +                key: :proxy_url,
 +                label: "Proxy URL",
 +                type: [:string, :tuple],
 +                description: "Proxy URL",
 +                suggestions: ["127.0.0.1:8123", {:socks5, :localhost, 9050}]
 +              }
 +            ]
 +          }
 +        ]
        }
      ]
    },
          description: "List of actions for the mogrify command",
          suggestions: [
            "strip",
 -          ["strip", "auto-orient"],
 -          [{"implode", "1"}],
 -          ["strip", "auto-orient", {"implode", "1"}]
 +          "auto-orient",
 +          {"implode", "1"}
          ]
        }
      ]
            "Text to replace filenames in links. If no setting, {random}.extension will be used. You can get the original" <>
              " filename extension by using {extension}, for example custom-file-name.{extension}",
          suggestions: [
 -          "custom-file-name.{extension}",
 -          nil
 +          "custom-file-name.{extension}"
          ]
        }
      ]
            Swoosh.Adapters.AmazonSES,
            Swoosh.Adapters.Dyn,
            Swoosh.Adapters.SocketLabs,
 -          Swoosh.Adapters.Gmail
 +          Swoosh.Adapters.Gmail,
 +          Swoosh.Adapters.Local
          ]
        },
        %{
        %{
          group: {:subgroup, Swoosh.Adapters.SMTP},
          key: :ssl,
 +        label: "SSL",
          type: :boolean,
          description: "`Swoosh.Adapters.SMTP` adapter specific setting"
        },
        %{
          group: {:subgroup, Swoosh.Adapters.SMTP},
          key: :tls,
 +        label: "TLS",
          type: :atom,
          description: "`Swoosh.Adapters.SMTP` adapter specific setting",
          suggestions: [:always, :never, :if_available]
        %{
          group: {:subgroup, Swoosh.Adapters.SMTP},
          key: :no_mx_lookups,
 +        label: "No MX lookups",
          type: :boolean,
          description: "`Swoosh.Adapters.SMTP` adapter specific setting"
        },
        %{
          group: {:subgroup, Swoosh.Adapters.Sendgrid},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.Sendgrid` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.Mandrill},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.Mandrill` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.Mailgun},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.Mailgun` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.Mailjet},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.Mailjet` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.Postmark},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.Postmark` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.SparkPost},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.SparkPost` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.AmazonSES},
          key: :region,
 -        type: {:string},
 +        type: :string,
          description: "`Swoosh.Adapters.AmazonSES` adapter specific setting",
          suggestions: ["us-east-1", "us-east-2"]
        },
        %{
          group: {:subgroup, Swoosh.Adapters.Dyn},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.Dyn` adapter specific setting",
          suggestions: ["my-api-key"]
        %{
          group: {:subgroup, Swoosh.Adapters.SocketLabs},
          key: :api_key,
 +        label: "API key",
          type: :string,
          description: "`Swoosh.Adapters.SocketLabs` adapter specific setting"
        },
        }
      ]
    },
 +  %{
 +    group: :swoosh,
 +    type: :group,
 +    description: "`Swoosh.Adapters.Local` adapter specific settings",
 +    children: [
 +      %{
 +        group: {:subgroup, Swoosh.Adapters.Local},
 +        key: :serve_mailbox,
 +        type: :boolean,
 +        description: "Run the preview server together as part of your app"
 +      },
 +      %{
 +        group: {:subgroup, Swoosh.Adapters.Local},
 +        key: :preview_port,
 +        type: :integer,
 +        description: "The preview server port",
 +        suggestions: [4001]
 +      }
 +    ]
 +  },
    %{
      group: :pleroma,
      key: :uri_schemes,
          type: {:list, :string},
          description: "List of the scheme part that is considered valid to be an URL",
          suggestions: [
 -          [
 -            "https",
 -            "http",
 -            "dat",
 -            "dweb",
 -            "gopher",
 -            "ipfs",
 -            "ipns",
 -            "irc",
 -            "ircs",
 -            "magnet",
 -            "mailto",
 -            "mumble",
 -            "ssb",
 -            "xmpp"
 -          ]
 +          "https",
 +          "http",
 +          "dat",
 +          "dweb",
 +          "gopher",
 +          "ipfs",
 +          "ipns",
 +          "irc",
 +          "ircs",
 +          "magnet",
 +          "mailto",
 +          "mumble",
 +          "ssb",
 +          "xmpp"
          ]
        }
      ]
            5_000
          ]
        },
 +      %{
 +        key: :chat_limit,
 +        type: :integer,
 +        description: "Character limit of the instance chat messages",
 +        suggestions: [
 +          5_000
 +        ]
 +      },
        %{
          key: :remote_limit,
          type: :integer,
        },
        %{
          key: :federation_publisher_modules,
 -        type: [:list, :module],
 +        type: {:list, :module},
          description: "List of modules for federation publishing",
          suggestions: [
            Pleroma.Web.ActivityPub.Publisher
        },
        %{
          key: :rewrite_policy,
 -        type: {:list, :module},
 +        type: [:module, {:list, :module}],
          description: "A list of MRF policies enabled",
 -        suggestions: [
 -          Pleroma.Web.ActivityPub.MRF.NoOpPolicy,
 -          Generator.mrf_list()
 -        ]
 +        suggestions:
 +          Generator.list_modules_in_dir(
 +            "lib/pleroma/web/activity_pub/mrf",
 +            "Elixir.Pleroma.Web.ActivityPub.MRF."
 +          )
        },
        %{
          key: :public,
          type: {:list, :string},
          description: "MIME-type list of formats allowed to be posted (transformed into HTML)",
          suggestions: [
 -          [
 -            "text/plain",
 -            "text/html",
 -            "text/markdown",
 -            "text/bbcode"
 -          ]
 +          "text/plain",
 +          "text/html",
 +          "text/markdown",
 +          "text/bbcode"
          ]
        },
        %{
          key: :mrf_transparency,
 +        label: "MRF transparency",
          type: :boolean,
          description:
            "Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
        },
        %{
          key: :mrf_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"]
 +          "exclusion.com"
          ]
        },
        %{
          description:
            "A message that will be send to a newly registered users as a direct message",
          suggestions: [
 -          "Hi, @username! Welcome to the board!",
 -          nil
 +          "Hi, @username! Welcome on board!"
          ]
        },
        %{
          type: :string,
          description: "The nickname of the local user that sends the welcome message",
          suggestions: [
 -          "lain",
 -          nil
 +          "lain"
          ]
        },
        %{
            false
          ]
        },
 -      %{
 -        key: :dynamic_configuration,
 -        type: :boolean,
 -        description:
 -          "Allow transferring configuration to DB with the subsequent customization from Admin api. Defaults to `false`"
 -      },
        %{
          key: :max_account_fields,
          type: :integer,
          type: [:atom, :tuple, :module],
          description:
            "Where logs will be send, :console - send logs to stdout, {ExSyslogger, :ex_syslogger} - to syslog, Quack.Logger - to Slack.",
 -        suggestions: [[:console, {ExSyslogger, :ex_syslogger}, Quack.Logger]]
 +        suggestions: [:console, {ExSyslogger, :ex_syslogger}, Quack.Logger]
        }
      ]
    },
        %{
          key: :metadata,
          type: {:list, :atom},
 -        suggestions: [[:request_id]]
 +        suggestions: [:request_id]
        }
      ]
    },
        %{
          key: :metadata,
          type: {:list, :atom},
 -        suggestions: [[:request_id]]
 +        suggestions: [:request_id]
        }
      ]
    },
      group: :pleroma,
      key: :frontend_configurations,
      type: :group,
 -    description: "A keyword list that keeps the configuration data for any kind of frontend",
 +    description:
 +      "This form can be used to configure a keyword list that keeps the configuration data for any " <>
 +        "kind of frontend. By default, settings for pleroma_fe and masto_fe are configured. If you want to " <>
 +        "add your own configuration your settings need to be complete as they will override the defaults.",
      children: [
        %{
          key: :pleroma_fe,
 +        label: "Pleroma FE",
          type: :map,
          description: "Settings for Pleroma FE",
          suggestions: [
            },
            %{
              key: :redirectRootNoLogin,
 +            label: "Redirect root no login",
              type: :string,
              description:
                "relative URL which indicates where to redirect when a user isn't logged in",
            },
            %{
              key: :redirectRootLogin,
 +            label: "Redirect root login",
              type: :string,
              description:
                "relative URL which indicates where to redirect when a user is logged in",
            },
            %{
              key: :showInstanceSpecificPanel,
 +            label: "Show instance specific panel",
              type: :boolean,
              description: "Whenether to show the instance's specific panel"
            },
            %{
              key: :scopeOptionsEnabled,
 +            label: "Scope options enabled",
              type: :boolean,
              description: "Enable setting an notice visibility and subject/CW when posting"
            },
            %{
              key: :formattingOptionsEnabled,
 +            label: "Formatting options enabled",
              type: :boolean,
              description:
                "Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to :instance, allowed_post_formats"
            },
            %{
              key: :collapseMessageWithSubject,
 +            label: "Collapse message with subject",
              type: :boolean,
              description:
                "When a message has a subject(aka Content Warning), collapse it by default"
            },
            %{
              key: :hidePostStats,
 +            label: "Hide post stats",
              type: :boolean,
              description: "Hide notices statistics(repeats, favorites, ...)"
            },
            %{
              key: :hideUserStats,
 +            label: "Hide user stats",
              type: :boolean,
              description:
                "Hide profile statistics(posts, posts per day, followers, followings, ...)"
            },
            %{
              key: :scopeCopy,
 +            label: "Scope copy",
              type: :boolean,
              description: "Copy the scope (private/unlisted/public) in replies to posts by default"
            },
            %{
              key: :subjectLineBehavior,
 +            label: "Subject line behavior",
              type: :string,
              description: "Allows changing the default behaviour of subject lines in replies.
            `email`: Copy and preprend re:, as in email,
            },
            %{
              key: :alwaysShowSubjectInput,
 +            label: "Always show subject input",
              type: :boolean,
              description: "When set to false, auto-hide the subject field when it's empty"
            }
        },
        %{
          key: :masto_fe,
 +        label: "Masto FE",
          type: :map,
          description: "Settings for Masto FE",
          suggestions: [
          children: [
            %{
              key: :showInstanceSpecificPanel,
 +            label: "Show instance specific panel",
              type: :boolean,
              description: "Whenether to show the instance's specific panel"
            }
      children: [
        %{
          key: :mascots,
 -        type: :keyword,
 +        type: {:keyword, :map},
          description:
            "Keyword of mascots, each element MUST contain both a url and a mime_type key",
          suggestions: [
 -          [
 -            pleroma_fox_tan: %{
 -              url: "/images/pleroma-fox-tan-smol.png",
 -              mime_type: "image/png"
 -            },
 -            pleroma_fox_tan_shy: %{
 -              url: "/images/pleroma-fox-tan-shy.png",
 -              mime_type: "image/png"
 -            }
 -          ]
 +          pleroma_fox_tan: %{
 +            url: "/images/pleroma-fox-tan-smol.png",
 +            mime_type: "image/png"
 +          },
 +          pleroma_fox_tan_shy: %{
 +            url: "/images/pleroma-fox-tan-shy.png",
 +            mime_type: "image/png"
 +          }
          ]
        },
        %{
    %{
      group: :pleroma,
      key: :mrf_simple,
 +    label: "MRF simple",
      type: :group,
      description: "Message Rewrite Facility",
      children: [
        },
        %{
          key: :media_nsfw,
 +        label: "Media NSFW",
          type: {:list, :string},
          description: "List of instances to put medias as NSFW(sensitive) from",
          suggestions: ["example.com", "*.example.com"]
    %{
      group: :pleroma,
      key: :mrf_subchain,
 +    label: "MRF subchain",
      type: :group,
      description:
        "This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
    %{
      group: :pleroma,
      key: :mrf_rejectnonpublic,
 +    description:
 +      "MRF RejectNonPublic settings. RejectNonPublic drops posts with non-public visibility settings.",
 +    label: "MRF reject non public",
      type: :group,
      children: [
        %{
          key: :allow_followersonly,
 +        label: "Allow followers-only",
          type: :boolean,
          description: "whether to allow followers-only posts"
        },
    %{
      group: :pleroma,
      key: :mrf_hellthread,
 +    label: "MRF hellthread",
      type: :group,
      description: "Block messages with too much mentions",
      children: [
    %{
      group: :pleroma,
      key: :mrf_keyword,
 +    label: "MRF keyword",
      type: :group,
      description: "Reject or Word-Replace messages with a keyword or regex",
      children: [
        },
        %{
          key: :replace,
 -        type: [{:string, :string}, {:regex, :string}],
 +        type: [{:tuple, :string, :string}, {:tuple, :regex, :string}],
          description:
 -          "A list of patterns which result in message being removed from federated timelines (a.k.a unlisted), each pattern can be a string or a regular expression",
 +          "A list of tuples containing {pattern, replacement}, pattern can be a string or a regular expression.",
          suggestions: [{"foo", "bar"}, {~r/foo/iu, "bar"}]
        }
      ]
    %{
      group: :pleroma,
      key: :mrf_mention,
 +    label: "MRF mention",
      type: :group,
      description: "Block messages which mention a user",
      children: [
          key: :actors,
          type: {:list, :string},
          description: "A list of actors, for which to drop any posts mentioning",
 -        suggestions: [["actor1", "actor2"]]
 +        suggestions: ["actor1", "actor2"]
        }
      ]
    },
    %{
      group: :pleroma,
      key: :mrf_vocabulary,
 +    label: "MRF vocabulary",
      type: :group,
      description: "Filter messages which belong to certain activity vocabularies",
      children: [
          type: {:list, :string},
          description:
            "A list of ActivityStreams terms to accept. If empty, all supported messages are accepted",
 -        suggestions: [["Create", "Follow", "Mention", "Announce", "Like"]]
 +        suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
        },
        %{
          key: :reject,
          type: {:list, :string},
          description:
            "A list of ActivityStreams terms to reject. If empty, no messages are rejected",
 -        suggestions: [["Create", "Follow", "Mention", "Announce", "Like"]]
 +        suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
        }
      ]
    },
          key: :proxy_opts,
          type: :keyword,
          description: "Options for Pleroma.ReverseProxy",
 -        suggestions: [[max_body_length: 25 * 1_048_576, redirect_on_failure: false]]
 +        suggestions: [
 +          redirect_on_failure: false,
 +          max_body_length: 25 * 1_048_576,
 +          http: [
 +            follow_redirect: true,
 +            pool: :media
 +          ]
 +        ],
 +        children: [
 +          %{
 +            key: :redirect_on_failure,
 +            type: :boolean,
 +            description:
 +              "Redirects the client to the real remote URL if there's any HTTP errors. " <>
 +                "Any error during body processing will not be redirected as the response is chunked"
 +          },
 +          %{
 +            key: :max_body_length,
 +            type: :integer,
 +            description:
 +              "limits the content length to be approximately the " <>
 +                "specified length. It is validated with the `content-length` header and also verified when proxying"
 +          },
 +          %{
 +            key: :http,
 +            type: :keyword,
 +            description: "HTTP options",
 +            children: [
 +              %{
 +                key: :adapter,
 +                type: :keyword,
 +                description: "Adapter specific options",
 +                children: [
 +                  %{
 +                    key: :ssl_options,
 +                    type: :keyword,
 +                    label: "SSL Options",
 +                    description: "SSL options for HTTP adapter",
 +                    children: [
 +                      %{
 +                        key: :versions,
 +                        type: {:list, :atom},
 +                        description: "List of TLS version to use",
 +                        suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2"]
 +                      }
 +                    ]
 +                  }
 +                ]
 +              },
 +              %{
 +                key: :proxy_url,
 +                label: "Proxy URL",
 +                type: [:string, :tuple],
 +                description: "Proxy URL",
 +                suggestions: ["127.0.0.1:8123", {:socks5, :localhost, 9050}]
 +              }
 +            ]
 +          }
 +        ]
        },
        %{
          key: :whitelist,
      children: [
        %{
          key: :http,
 -        type: :keyword,
 +        label: "HTTP",
 +        type: {:keyword, :integer, :tuple},
          description: "http protocol configuration",
          suggestions: [
 -          [port: 8080, ip: {127, 0, 0, 1}]
 +          port: 8080,
 +          ip: {127, 0, 0, 1}
          ],
          children: [
            %{
              type: {:list, :tuple},
              description: "dispatch settings",
              suggestions: [
 -              [
 -                {:_,
 -                 [
 -                   {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
 -                   {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
 -                    {Phoenix.Transports.WebSocket,
 -                     {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, websocket_config}}},
 -                   {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
 -                 ]}
 -                # end copied from config.exs
 -              ]
 +              {:_,
 +               [
 +                 {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
 +                 {"/websocket", Phoenix.Endpoint.CowboyWebSocket,
 +                  {Phoenix.Transports.WebSocket,
 +                   {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, websocket_config}}},
 +                 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
 +               ]}
 +              # end copied from config.exs
              ]
            },
            %{
              key: :ip,
 +            label: "IP",
              type: :tuple,
              description: "ip",
              suggestions: [
        },
        %{
          key: :url,
 -        type: :keyword,
 +        label: "URL",
 +        type: {:keyword, :string, :integer},
          description: "configuration for generating urls",
          suggestions: [
 -          [host: "example.com", port: 2020, scheme: "https"]
 +          host: "example.com",
 +          port: 2020,
 +          scheme: "https"
          ],
          children: [
            %{
        %{
          key: :render_errors,
          type: :keyword,
 -        suggestions: [[view: Pleroma.Web.ErrorView, accepts: ~w(json)]],
 +        suggestions: [view: Pleroma.Web.ErrorView, accepts: ~w(json)],
          children: [
            %{
              key: :view,
        %{
          key: :pubsub,
          type: :keyword,
 -        suggestions: [[name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2]],
 +        suggestions: [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2],
          children: [
            %{
              key: :name,
        },
        %{
          key: :sts,
 +        label: "STS",
          type: :boolean,
          description: "Whether to additionally send a Strict-Transport-Security header"
        },
        %{
          key: :sts_max_age,
 +        label: "STS max age",
          type: :integer,
          description: "The maximum age for the Strict-Transport-Security header if sent",
          suggestions: [31_536_000]
        },
        %{
          key: :ct_max_age,
 +        label: "CT max age",
          type: :integer,
          description: "The maximum age for the Expect-CT header if sent",
          suggestions: [2_592_000]
        },
        %{
          key: :report_uri,
 +        label: "Report URI",
          type: :string,
          description: "Adds the specified url to report-uri and report-to group in CSP header",
          suggestions: ["https://example.com/report-uri"]
          key: :method,
          type: :module,
          description: "The method/service to use for captcha",
 -        suggestions: [Pleroma.Captcha.Kocaptcha]
 +        suggestions: [Pleroma.Captcha.Kocaptcha, Pleroma.Captcha.Native]
        },
        %{
          key: :seconds_valid,
        },
        %{
          key: :queues,
 -        type: :keyword,
 +        type: {:keyword, :integer},
          description:
            "Background jobs queues (keys: queues, values: max numbers of concurrent jobs)",
          suggestions: [
 -          [
 -            activity_expiration: 10,
 -            background: 5,
 -            federator_incoming: 50,
 -            federator_outgoing: 50,
 -            mailer: 10,
 -            scheduled_activities: 10,
 -            transmogrifier: 20,
 -            web_push: 50
 -          ]
 +          activity_expiration: 10,
 +          background: 5,
 +          federator_incoming: 50,
 +          federator_outgoing: 50,
 +          mailer: 10,
 +          scheduled_activities: 10,
 +          transmogrifier: 20,
 +          web_push: 50
          ],
          children: [
            %{
      children: [
        %{
          key: :retries,
 -        type: :keyword,
 +        type: {:keyword, :integer},
          description: "Max retry attempts for failed jobs, per `Oban` queue",
          suggestions: [
 -          [
 -            federator_incoming: 5,
 -            federator_outgoing: 5
 -          ]
 +          federator_incoming: 5,
 +          federator_outgoing: 5
          ]
        }
      ]
      group: :pleroma,
      key: Pleroma.Web.Metadata,
      type: :group,
 -    decsription: "Metadata-related settings",
 +    description: "Metadata-related settings",
      children: [
        %{
          key: :providers,
          type: {:list, :module},
          description: "List of metadata providers to enable",
          suggestions: [
 -          [
 -            Pleroma.Web.Metadata.Providers.OpenGraph,
 -            Pleroma.Web.Metadata.Providers.TwitterCard,
 -            Pleroma.Web.Metadata.Providers.RelMe
 -          ]
 +          Pleroma.Web.Metadata.Providers.OpenGraph,
 +          Pleroma.Web.Metadata.Providers.TwitterCard,
 +          Pleroma.Web.Metadata.Providers.RelMe,
 +          Pleroma.Web.Metadata.Providers.Feed
          ]
        },
        %{
          key: :unfurl_nsfw,
 +        label: "Unfurl NSFW",
          type: :boolean,
          description: "If set to true nsfw attachments will be shown in previews"
        }
      group: :pleroma,
      key: :rich_media,
      type: :group,
 +    description:
 +      "If enabled the instance will parse metadata from attached links to generate link previews.",
      children: [
        %{
          key: :enabled,
          type: :boolean,
 -        description:
 -          "if enabled the instance will parse metadata from attached links to generate link previews"
 +        description: "Enables/disables RichMedia."
        },
        %{
          key: :ignore_hosts,
          type: {:list, :string},
 -        description: "list of hosts which will be ignored by the metadata parser",
 -        suggestions: [["accounts.google.com", "xss.website"]]
 +        description: "List of hosts which will be ignored by the metadata parser.",
 +        suggestions: ["accounts.google.com", "xss.website"]
        },
        %{
          key: :ignore_tld,
 +        label: "Ignore TLD",
          type: {:list, :string},
 -        description: "list TLDs (top-level domains) which will ignore for parse metadata",
 -        suggestions: [["local", "localdomain", "lan"]]
 +        description: "List TLDs (top-level domains) which will ignore for parse metadata.",
 +        suggestions: ["local", "localdomain", "lan"]
        },
        %{
          key: :parsers,
          type: {:list, :module},
 -        description: "list of Rich Media parsers",
 +        description: "List of Rich Media parsers.",
          suggestions: [
 -          Generator.richmedia_parsers()
 +          Pleroma.Web.RichMedia.Parsers.MetaTagsParser,
 +          Pleroma.Web.RichMedia.Parsers.OEmbed,
 +          Pleroma.Web.RichMedia.Parsers.OGP,
 +          Pleroma.Web.RichMedia.Parsers.TwitterCard
          ]
        },
        %{
          key: :ttl_setters,
 +        label: "TTL setters",
          type: {:list, :module},
 -        description: "list of rich media ttl setters",
 +        description: "List of rich media ttl setters.",
          suggestions: [
 -          [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
 +          Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl
          ]
        }
      ]
        },
        %{
          key: :ssl,
 +        label: "SSL",
          type: :boolean,
          description: "true to use SSL, usually implies the port 636"
        },
        %{
          key: :sslopts,
 +        label: "SSL options",
          type: :keyword,
 -        description: "additional SSL options"
 +        description: "additional SSL options",
 +        suggestions: [cacertfile: "path/to/file/with/PEM/cacerts", verify: :verify_peer],
 +        children: [
 +          %{
 +            key: :cacertfile,
 +            type: :string,
 +            description: "Path to file with PEM encoded cacerts",
 +            suggestions: ["path/to/file/with/PEM/cacerts"]
 +          },
 +          %{
 +            key: :verify,
 +            type: :atom,
 +            description: "Type of cert verification",
 +            suggestions: [:verify_peer]
 +          }
 +        ]
        },
        %{
          key: :tls,
 +        label: "TLS",
          type: :boolean,
          description: "true to start TLS, usually implies the port 389"
        },
        %{
          key: :tlsopts,
 +        label: "TLS options",
          type: :keyword,
 -        description: "additional TLS options"
 +        description: "additional TLS options",
 +        suggestions: [cacertfile: "path/to/file/with/PEM/cacerts", verify: :verify_peer],
 +        children: [
 +          %{
 +            key: :cacertfile,
 +            type: :string,
 +            description: "Path to file with PEM encoded cacerts",
 +            suggestions: ["path/to/file/with/PEM/cacerts"]
 +          },
 +          %{
 +            key: :verify,
 +            type: :atom,
 +            description: "Type of cert verification",
 +            suggestions: [:verify_peer]
 +          }
 +        ]
        },
        %{
          key: :base,
        },
        %{
          key: :oauth_consumer_strategies,
 -        type: :string,
 +        type: {:list, :string},
          description:
            "the list of enabled OAuth consumer strategies; by default it's set by OAUTH_CONSUMER_STRATEGIES environment variable." <>
              " Each entry in this space-delimited string should be of format <strategy> or <strategy>:<dependency>" <>
            },
            %{
              key: :interval,
 -            type: :ininteger,
 +            type: :integer,
              description: "Minimum interval between digest emails to one user",
              suggestions: [7]
            },
      children: [
        %{
          key: :logo,
 -        type: [:string, nil],
 +        type: :string,
          description: "a path to a custom logo. Set it to nil to use the default Pleroma logo",
 -        suggestions: ["some/path/logo.png", nil]
 +        suggestions: ["some/path/logo.png"]
        },
        %{
          key: :styling,
          key: :shortcode_globs,
          type: {:list, :string},
          description: "Location of custom emoji files. * can be used as a wildcard",
 -        suggestions: [["/emoji/custom/**/*.png"]]
 +        suggestions: ["/emoji/custom/**/*.png"]
        },
        %{
          key: :pack_extensions,
          type: {:list, :string},
          description:
            "A list of file extensions for emojis, when no emoji.txt for a pack is present",
 -        suggestions: [[".png", ".gif"]]
 +        suggestions: [".png", ".gif"]
        },
        %{
          key: :groups,
 -        type: :keyword,
 +        type: {:keyword, :string, {:list, :string}},
          description:
            "Emojis are ordered in groups (tags). This is an array of key-value pairs where the key is the groupname" <>
              " and the value the location or array of locations. * can be used as a wildcard",
          suggestions: [
 -          [
 -            # Put groups that have higher priority than defaults here. Example in `docs/config/custom_emoji.md`
 -            Custom: ["/emoji/*.png", "/emoji/**/*.png"]
 -          ]
 +          # Put groups that have higher priority than defaults here. Example in `docs/config/custom_emoji.md`
 +          Custom: ["/emoji/*.png", "/emoji/**/*.png"]
          ]
        },
        %{
      group: :esshd,
      type: :group,
      description:
 -      "To enable simple command line interface accessible over ssh, add a setting like this to your configuration file",
 +      "Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <>
 +        "and generate host keys in your priv dir with ssh-keygen -m PEM -N \"\" -b 2048 -t rsa -f ssh_host_rsa_key",
      children: [
        %{
          key: :enabled,
            %{
              key: "application/xml",
              type: {:list, :string},
 -            suggestions: [["xml"]]
 +            suggestions: ["xml"]
            },
            %{
              key: "application/xrd+xml",
              type: {:list, :string},
 -            suggestions: [["xrd+xml"]]
 +            suggestions: ["xrd+xml"]
            },
            %{
              key: "application/jrd+json",
              type: {:list, :string},
 -            suggestions: [["jrd+json"]]
 +            suggestions: ["jrd+json"]
            },
            %{
              key: "application/activity+json",
              type: {:list, :string},
 -            suggestions: [["activity+json"]]
 +            suggestions: ["activity+json"]
            },
            %{
              key: "application/ld+json",
              type: {:list, :string},
 -            suggestions: [["activity+json"]]
 +            suggestions: ["activity+json"]
            }
          ]
        }
        }
      ]
    },
-   %{
-     group: :pleroma,
-     key: Pleroma.Uploaders.MDII,
-     description:
-       "Uploader for https://github.com/hakaba-hitoyo/minimal-digital-image-infrastructure",
-     type: :group,
-     children: [
-       %{
-         key: :cgi,
-         type: :string,
-         suggestions: ["https://mdii.sakura.ne.jp/mdii-post.cgi"]
-       },
-       %{
-         key: :files,
-         type: :string,
-         suggestions: ["https://mdii.sakura.ne.jp"]
-       }
-     ]
-   },
    %{
      group: :pleroma,
      key: :http,
      children: [
        %{
          key: :proxy_url,
 -        type: [:string, :atom, nil],
 -        suggestions: ["localhost:9020", {:socks5, :localhost, 3090}, nil]
 +        label: "Proxy URL",
 +        type: [:string, :tuple],
 +        description: "Proxy URL",
 +        suggestions: ["localhost:9020", {:socks5, :localhost, 3090}]
        },
        %{
          key: :send_user_agent,
          type: :boolean
        },
 +      %{
 +        key: :user_agent,
 +        type: [:string, :atom],
 +        desctiption:
 +          "what user agent should we use? (default: `:default`), must be string or `:default`",
 +        suggestions: ["Pleroma", :default]
 +      },
        %{
          key: :adapter,
          type: :keyword,
 -        suggestions: [
 -          [
 -            ssl_options: [
 -              # Workaround for remote server certificate chain issues
 -              partial_chain: &:hackney_connect.partial_chain/1,
 -              # We don't support TLS v1.3 yet
 -              versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
 +        description: "Adapter specific options",
 +        suggestions: [],
 +        children: [
 +          %{
 +            key: :ssl_options,
 +            type: :keyword,
 +            label: "SSL Options",
 +            description: "SSL options for HTTP adapter",
 +            children: [
 +              %{
 +                key: :versions,
 +                type: {:list, :atom},
 +                description: "List of TLS version to use",
 +                suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2"]
 +              }
              ]
 -          ]
 +          }
          ]
        }
      ]
        %{
          key: :scrub_policy,
          type: {:list, :module},
 -        suggestions: [[Pleroma.HTML.Transform.MediaProxy, Pleroma.HTML.Scrubber.Default]]
 +        suggestions: [Pleroma.HTML.Transform.MediaProxy, Pleroma.HTML.Scrubber.Default]
        }
      ]
    },
    %{
      group: :pleroma,
      key: :mrf_normalize_markup,
 +    label: "MRF normalize markup",
 +    description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
      type: :group,
      children: [
        %{
          key: :restricted_nicknames,
          type: {:list, :string},
          suggestions: [
 -          [
 -            ".well-known",
 -            "~",
 -            "about",
 -            "activities",
 -            "api",
 -            "auth",
 -            "check_password",
 -            "dev",
 -            "friend-requests",
 -            "inbox",
 -            "internal",
 -            "main",
 -            "media",
 -            "nodeinfo",
 -            "notice",
 -            "oauth",
 -            "objects",
 -            "ostatus_subscribe",
 -            "pleroma",
 -            "proxy",
 -            "push",
 -            "registration",
 -            "relay",
 -            "settings",
 -            "status",
 -            "tag",
 -            "user-search",
 -            "user_exists",
 -            "users",
 -            "web"
 -          ]
 +          ".well-known",
 +          "~",
 +          "about",
 +          "activities",
 +          "api",
 +          "auth",
 +          "check_password",
 +          "dev",
 +          "friend-requests",
 +          "inbox",
 +          "internal",
 +          "main",
 +          "media",
 +          "nodeinfo",
 +          "notice",
 +          "oauth",
 +          "objects",
 +          "ostatus_subscribe",
 +          "pleroma",
 +          "proxy",
 +          "push",
 +          "registration",
 +          "relay",
 +          "settings",
 +          "status",
 +          "tag",
 +          "user-search",
 +          "user_exists",
 +          "users",
 +          "web"
          ]
        }
      ]
        %{
          key: :methods,
          type: {:list, :string},
 -        suggestions: [["POST", "PUT", "DELETE", "GET", "PATCH", "OPTIONS"]]
 +        suggestions: ["POST", "PUT", "DELETE", "GET", "PATCH", "OPTIONS"]
        },
        %{
          key: :expose,
 -        type: :string,
 +        type: {:list, :string},
          suggestions: [
 -          [
 -            "Link",
 -            "X-RateLimit-Reset",
 -            "X-RateLimit-Limit",
 -            "X-RateLimit-Remaining",
 -            "X-Request-Id",
 -            "Idempotency-Key"
 -          ]
 +          "Link",
 +          "X-RateLimit-Reset",
 +          "X-RateLimit-Limit",
 +          "X-RateLimit-Remaining",
 +          "X-Request-Id",
 +          "Idempotency-Key"
          ]
        },
        %{
        %{
          key: :headers,
          type: {:list, :string},
 -        suggestions: [["Authorization", "Content-Type", "Idempotency-Key"]]
 +        suggestions: ["Authorization", "Content-Type", "Idempotency-Key"]
        }
      ]
    },
      key: Pleroma.Plugs.RemoteIp,
      type: :group,
      description: """
 -    **If your instance is not behind at least one reverse proxy, you should not enable this plug.**
 -
      `Pleroma.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.
 +    **If your instance is not behind at least one reverse proxy, you should not enable this plug.**
      """,
      children: [
        %{
          key: :enabled,
          type: :boolean,
 -        description: "Enable/disable the plug. Defaults to `false`.",
 -        suggestions: [true, false]
 +        description: "Enable/disable the plug. Defaults to `false`."
        },
        %{
          key: :headers,
          type: :integer,
          description:
            "activity pub routes (except question activities). Defaults to `nil` (no expiration).",
 -        suggestions: [30_000, nil]
 +        suggestions: [30_000]
        },
        %{
          key: :activity_pub_question,
          suggestions: [30_000]
        }
      ]
 +  },
 +  %{
 +    group: :pleroma,
 +    key: :static_fe,
 +    type: :group,
 +    description:
 +      "Render profiles and posts using server-generated HTML that is viewable without using JavaScript.",
 +    children: [
 +      %{
 +        key: :enabled,
 +        type: :boolean,
 +        description: "Enables the rendering of static HTML. Defaults to `false`."
 +      }
 +    ]
 +  },
 +  %{
 +    group: :pleroma,
 +    key: :feed,
 +    type: :group,
 +    description: "Configure feed rendering.",
 +    children: [
 +      %{
 +        key: :post_title,
 +        type: :map,
 +        description: "Configure title rendering.",
 +        children: [
 +          %{
 +            key: :max_length,
 +            type: :integer,
 +            description: "Maximum number of characters before truncating title.",
 +            suggestions: [100]
 +          },
 +          %{
 +            key: :omission,
 +            type: :string,
 +            description: "Replacement which will be used after truncating string.",
 +            suggestions: ["..."]
 +          }
 +        ]
 +      }
 +    ]
 +  },
 +  %{
 +    group: :pleroma,
 +    key: :mrf_object_age,
 +    type: :group,
 +    description: "Rejects or delists posts based on their age when received.",
 +    children: [
 +      %{
 +        key: :threshold,
 +        type: :integer,
 +        description: "Required age (in seconds) of a post before actions are taken.",
 +        suggestions: [172_800]
 +      },
 +      %{
 +        key: :actions,
 +        type: {:list, :atom},
 +        description:
 +          "A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
 +            "`:strip_followers` removes followers from the ActivityPub recipient list, ensuring they won't be delivered to home timelines; " <>
 +            "`:reject` rejects the message entirely",
 +        suggestions: [:delist, :strip_followers, :reject]
 +      }
 +    ]
 +  },
 +  %{
 +    group: :pleroma,
 +    key: :modules,
 +    type: :group,
 +    description: "Custom Runtime Modules.",
 +    children: [
 +      %{
 +        key: :runtime_dir,
 +        type: :string,
 +        description: "A path to custom Elixir modules (such as MRF policies)."
 +      }
 +    ]
 +  },
 +  %{
 +    group: :pleroma,
 +    type: :group,
 +    description: "Allow instance configuration from database.",
 +    children: [
 +      %{
 +        key: :configurable_from_database,
 +        type: :boolean,
 +        description:
 +          "Allow transferring configuration to DB with the subsequent customization from Admin api. Defaults to `false`"
 +      }
 +    ]
    }
  ]
index a182e90e7005df74db4384dc1d770a89f20110ea,9654ab8a3fe7402c358edc8654bffb9a7c6c487b..8cd7e021aa0ff658d6712416364941d1466a95f6
@@@ -195,7 -195,6 +195,7 @@@ defmodule Pleroma.Web.Router d
  
      get("/config", AdminAPIController, :config_show)
      post("/config", AdminAPIController, :config_update)
 +    get("/config/descriptions", AdminAPIController, :config_descriptions)
      get("/config/migrate_to_db", AdminAPIController, :migrate_to_db)
      get("/config/migrate_from_db", AdminAPIController, :migrate_from_db)
  
      pipe_through(:pleroma_html)
  
      post("/main/ostatus", UtilController, :remote_subscribe)
-     get("/ostatus_subscribe", UtilController, :remote_follow)
+     get("/ostatus_subscribe", RemoteFollowController, :follow)
  
-     post("/ostatus_subscribe", UtilController, :do_remote_follow)
+     post("/ostatus_subscribe", RemoteFollowController, :do_follow)
    end
  
    scope "/api/pleroma", Pleroma.Web.TwitterAPI do