dynamic_configuration: false,
user_bio_length: 5000,
user_name_length: 100,
+ max_account_fields: 4,
external_user_synchronization: true
config :pleroma, :markup,
* `skip_thread_containment`: Skip filter out broken threads. The default is `false`.
* `limit_to_local_content`: Limit unauthenticated users to search for local statutes and users only. Possible values: `:unauthenticated`, `:all` and `false`. The default is `:unauthenticated`.
* `dynamic_configuration`: Allow transferring configuration to DB with the subsequent customization from Admin api.
+* `max_account_fields`: The maximum number of custom fields in the user profile (default: `4`)
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users.
field(:mascot, :map, default: nil)
field(:emoji, {:array, :map}, default: [])
field(:pleroma_settings_store, :map, default: %{})
+ field(:fields, {:array, :map}, default: [])
field(:notification_settings, :map,
default: %{
:background,
:show_role,
:skip_thread_containment,
+ :fields,
:pleroma_settings_store
])
+ |> validate_fields()
end
+ def validate_fields(changeset) do
+ limit = Pleroma.Config.get([:instance, :max_account_fields], 0)
+
+ changeset
+ |> validate_length(:fields, max: limit)
+ |> validate_change(:fields, fn :fields, fields ->
+ if Enum.all?(fields, &valid_field?/1) do
+ []
+ else
+ [fields: "invalid"]
+ end
+ end)
+ end
+
+ defp valid_field?(%{"name" => name, "value" => value}) do
+ is_binary(name) && is_binary(value)
+ end
+
+ defp valid_field?(_), do: false
+
@spec confirmation_changeset(Info.t(), keyword()) :: Changeset.t()
def confirmation_changeset(info, opts) do
need_confirmation? = Keyword.get(opts, :need_confirmation)
cast(info, params, [:muted_reblogs])
end
+ def fields(%{source_data: %{"attachment" => attachment}}) do
+ attachment
+ |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
+ |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
+ end
+
+ def fields(%{fields: fields}), do: fields
+
def follow_information_update(info, params) do
info
|> cast(params, [
end)
end)
|> add_if_present(params, "default_scope", :default_scope)
+ |> add_if_present(params, "fields", :fields, fn fields ->
+ fields =
+ Enum.map(fields, fn field ->
+ %{
+ "name" => Formatter.html_escape(field["name"], "text/plain"),
+ "value" => Formatter.html_escape(field["value"], "text/plain")
+ }
+ end)
+
+ {:ok, fields}
+ end)
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
end)
}
end)
- fields =
- (user.info.source_data["attachment"] || [])
- |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
- |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
+ fields = User.Info.fields(user.info)
+ fields_html = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
header: header,
header_static: header,
emojis: emojis,
- fields: fields,
+ fields: fields_html,
bot: bot,
source: %{
note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
sensitive: false,
+ fields: fields,
pleroma: %{}
},
assert user["display_name"] == name
assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = user["emojis"]
end
+
+ test "update fields", %{conn: conn} do
+ user = insert(:user)
+
+ fields = [
+ %{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
+ %{"name" => "link", "value" => "cofe.io"}
+ ]
+
+ account =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields})
+ |> json_response(200)
+
+ assert account["fields"] == [
+ %{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
+ %{"name" => "link", "value" => "<a href=\"http://cofe.io\">cofe.io</a>"}
+ ]
+
+ assert account["source"]["fields"] == [
+ %{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
+ %{"name" => "link", "value" => "cofe.io"}
+ ]
+
+ Pleroma.Config.put([:instance, :max_account_fields], 1)
+
+ fields = [
+ %{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
+ %{"name" => "link", "value" => "cofe.io"}
+ ]
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields})
+
+ assert %{"error" => "Invalid request"} == json_response(conn, 403)
+ end
end
end