Local copy of Pleroma, an ActivityPub server software. Contains modifications running live on fedi.underscore.world
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

info.ex 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.User.Info do
  5. use Ecto.Schema
  6. import Ecto.Changeset
  7. alias Pleroma.User.Info
  8. @type t :: %__MODULE__{}
  9. embedded_schema do
  10. field(:banner, :map, default: %{})
  11. field(:background, :map, default: %{})
  12. field(:source_data, :map, default: %{})
  13. field(:note_count, :integer, default: 0)
  14. field(:follower_count, :integer, default: 0)
  15. # Should be filled in only for remote users
  16. field(:following_count, :integer, default: nil)
  17. field(:locked, :boolean, default: false)
  18. field(:confirmation_pending, :boolean, default: false)
  19. field(:confirmation_token, :string, default: nil)
  20. field(:default_scope, :string, default: "public")
  21. field(:blocks, {:array, :string}, default: [])
  22. field(:domain_blocks, {:array, :string}, default: [])
  23. field(:mutes, {:array, :string}, default: [])
  24. field(:muted_reblogs, {:array, :string}, default: [])
  25. field(:muted_notifications, {:array, :string}, default: [])
  26. field(:subscribers, {:array, :string}, default: [])
  27. field(:deactivated, :boolean, default: false)
  28. field(:no_rich_text, :boolean, default: false)
  29. field(:ap_enabled, :boolean, default: false)
  30. field(:is_moderator, :boolean, default: false)
  31. field(:is_admin, :boolean, default: false)
  32. field(:show_role, :boolean, default: true)
  33. field(:keys, :string, default: nil)
  34. field(:settings, :map, default: nil)
  35. field(:magic_key, :string, default: nil)
  36. field(:uri, :string, default: nil)
  37. field(:topic, :string, default: nil)
  38. field(:hub, :string, default: nil)
  39. field(:salmon, :string, default: nil)
  40. field(:hide_followers, :boolean, default: false)
  41. field(:hide_follows, :boolean, default: false)
  42. field(:hide_favorites, :boolean, default: true)
  43. field(:pinned_activities, {:array, :string}, default: [])
  44. field(:email_notifications, :map, default: %{"digest" => false})
  45. field(:mascot, :map, default: nil)
  46. field(:emoji, {:array, :map}, default: [])
  47. field(:pleroma_settings_store, :map, default: %{})
  48. field(:notification_settings, :map,
  49. default: %{
  50. "followers" => true,
  51. "follows" => true,
  52. "non_follows" => true,
  53. "non_followers" => true
  54. }
  55. )
  56. field(:skip_thread_containment, :boolean, default: false)
  57. # Found in the wild
  58. # ap_id -> Where is this used?
  59. # bio -> Where is this used?
  60. # avatar -> Where is this used?
  61. # fqn -> Where is this used?
  62. # host -> Where is this used?
  63. # subject _> Where is this used?
  64. end
  65. def set_activation_status(info, deactivated) do
  66. params = %{deactivated: deactivated}
  67. info
  68. |> cast(params, [:deactivated])
  69. |> validate_required([:deactivated])
  70. end
  71. def update_notification_settings(info, settings) do
  72. settings =
  73. settings
  74. |> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end)
  75. |> Map.new()
  76. notification_settings =
  77. info.notification_settings
  78. |> Map.merge(settings)
  79. |> Map.take(["followers", "follows", "non_follows", "non_followers"])
  80. params = %{notification_settings: notification_settings}
  81. info
  82. |> cast(params, [:notification_settings])
  83. |> validate_required([:notification_settings])
  84. end
  85. @doc """
  86. Update email notifications in the given User.Info struct.
  87. Examples:
  88. iex> update_email_notifications(%Pleroma.User.Info{email_notifications: %{"digest" => false}}, %{"digest" => true})
  89. %Pleroma.User.Info{email_notifications: %{"digest" => true}}
  90. """
  91. @spec update_email_notifications(t(), map()) :: Ecto.Changeset.t()
  92. def update_email_notifications(info, settings) do
  93. email_notifications =
  94. info.email_notifications
  95. |> Map.merge(settings)
  96. |> Map.take(["digest"])
  97. params = %{email_notifications: email_notifications}
  98. fields = [:email_notifications]
  99. info
  100. |> cast(params, fields)
  101. |> validate_required(fields)
  102. end
  103. def add_to_note_count(info, number) do
  104. set_note_count(info, info.note_count + number)
  105. end
  106. def set_note_count(info, number) do
  107. params = %{note_count: Enum.max([0, number])}
  108. info
  109. |> cast(params, [:note_count])
  110. |> validate_required([:note_count])
  111. end
  112. def set_follower_count(info, number) do
  113. params = %{follower_count: Enum.max([0, number])}
  114. info
  115. |> cast(params, [:follower_count])
  116. |> validate_required([:follower_count])
  117. end
  118. def set_mutes(info, mutes) do
  119. params = %{mutes: mutes}
  120. info
  121. |> cast(params, [:mutes])
  122. |> validate_required([:mutes])
  123. end
  124. @spec set_notification_mutes(Changeset.t(), [String.t()], boolean()) :: Changeset.t()
  125. def set_notification_mutes(changeset, muted_notifications, notifications?) do
  126. if notifications? do
  127. put_change(changeset, :muted_notifications, muted_notifications)
  128. |> validate_required([:muted_notifications])
  129. else
  130. changeset
  131. end
  132. end
  133. def set_blocks(info, blocks) do
  134. params = %{blocks: blocks}
  135. info
  136. |> cast(params, [:blocks])
  137. |> validate_required([:blocks])
  138. end
  139. def set_subscribers(info, subscribers) do
  140. params = %{subscribers: subscribers}
  141. info
  142. |> cast(params, [:subscribers])
  143. |> validate_required([:subscribers])
  144. end
  145. @spec add_to_mutes(Info.t(), String.t()) :: Changeset.t()
  146. def add_to_mutes(info, muted) do
  147. set_mutes(info, Enum.uniq([muted | info.mutes]))
  148. end
  149. @spec add_to_muted_notifications(Changeset.t(), Info.t(), String.t(), boolean()) ::
  150. Changeset.t()
  151. def add_to_muted_notifications(changeset, info, muted, notifications?) do
  152. set_notification_mutes(
  153. changeset,
  154. Enum.uniq([muted | info.muted_notifications]),
  155. notifications?
  156. )
  157. end
  158. @spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t()
  159. def remove_from_mutes(info, muted) do
  160. set_mutes(info, List.delete(info.mutes, muted))
  161. end
  162. @spec remove_from_muted_notifications(Changeset.t(), Info.t(), String.t()) :: Changeset.t()
  163. def remove_from_muted_notifications(changeset, info, muted) do
  164. set_notification_mutes(changeset, List.delete(info.muted_notifications, muted), true)
  165. end
  166. def add_to_block(info, blocked) do
  167. set_blocks(info, Enum.uniq([blocked | info.blocks]))
  168. end
  169. def remove_from_block(info, blocked) do
  170. set_blocks(info, List.delete(info.blocks, blocked))
  171. end
  172. def add_to_subscribers(info, subscribed) do
  173. set_subscribers(info, Enum.uniq([subscribed | info.subscribers]))
  174. end
  175. def remove_from_subscribers(info, subscribed) do
  176. set_subscribers(info, List.delete(info.subscribers, subscribed))
  177. end
  178. def set_domain_blocks(info, domain_blocks) do
  179. params = %{domain_blocks: domain_blocks}
  180. info
  181. |> cast(params, [:domain_blocks])
  182. |> validate_required([:domain_blocks])
  183. end
  184. def add_to_domain_block(info, domain_blocked) do
  185. set_domain_blocks(info, Enum.uniq([domain_blocked | info.domain_blocks]))
  186. end
  187. def remove_from_domain_block(info, domain_blocked) do
  188. set_domain_blocks(info, List.delete(info.domain_blocks, domain_blocked))
  189. end
  190. def set_keys(info, keys) do
  191. params = %{keys: keys}
  192. info
  193. |> cast(params, [:keys])
  194. |> validate_required([:keys])
  195. end
  196. def remote_user_creation(info, params) do
  197. info
  198. |> cast(params, [
  199. :ap_enabled,
  200. :source_data,
  201. :banner,
  202. :locked,
  203. :magic_key,
  204. :uri,
  205. :hub,
  206. :topic,
  207. :salmon,
  208. :hide_followers,
  209. :hide_follows,
  210. :follower_count,
  211. :following_count
  212. ])
  213. end
  214. def user_upgrade(info, params) do
  215. info
  216. |> cast(params, [
  217. :ap_enabled,
  218. :source_data,
  219. :banner,
  220. :locked,
  221. :magic_key,
  222. :follower_count,
  223. :following_count,
  224. :hide_follows,
  225. :hide_followers
  226. ])
  227. end
  228. def profile_update(info, params) do
  229. info
  230. |> cast(params, [
  231. :locked,
  232. :no_rich_text,
  233. :default_scope,
  234. :banner,
  235. :hide_follows,
  236. :hide_followers,
  237. :hide_favorites,
  238. :background,
  239. :show_role,
  240. :skip_thread_containment,
  241. :pleroma_settings_store
  242. ])
  243. end
  244. @spec confirmation_changeset(Info.t(), keyword()) :: Changeset.t()
  245. def confirmation_changeset(info, opts) do
  246. need_confirmation? = Keyword.get(opts, :need_confirmation)
  247. params =
  248. if need_confirmation? do
  249. %{
  250. confirmation_pending: true,
  251. confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
  252. }
  253. else
  254. %{
  255. confirmation_pending: false,
  256. confirmation_token: nil
  257. }
  258. end
  259. cast(info, params, [:confirmation_pending, :confirmation_token])
  260. end
  261. def mastodon_settings_update(info, settings) do
  262. params = %{settings: settings}
  263. info
  264. |> cast(params, [:settings])
  265. |> validate_required([:settings])
  266. end
  267. def mascot_update(info, url) do
  268. params = %{mascot: url}
  269. info
  270. |> cast(params, [:mascot])
  271. |> validate_required([:mascot])
  272. end
  273. def set_source_data(info, source_data) do
  274. params = %{source_data: source_data}
  275. info
  276. |> cast(params, [:source_data])
  277. |> validate_required([:source_data])
  278. end
  279. def admin_api_update(info, params) do
  280. info
  281. |> cast(params, [
  282. :is_moderator,
  283. :is_admin,
  284. :show_role
  285. ])
  286. end
  287. def add_pinnned_activity(info, %Pleroma.Activity{id: id}) do
  288. if id not in info.pinned_activities do
  289. max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0)
  290. params = %{pinned_activities: info.pinned_activities ++ [id]}
  291. info
  292. |> cast(params, [:pinned_activities])
  293. |> validate_length(:pinned_activities,
  294. max: max_pinned_statuses,
  295. message: "You have already pinned the maximum number of statuses"
  296. )
  297. else
  298. change(info)
  299. end
  300. end
  301. def remove_pinnned_activity(info, %Pleroma.Activity{id: id}) do
  302. params = %{pinned_activities: List.delete(info.pinned_activities, id)}
  303. cast(info, params, [:pinned_activities])
  304. end
  305. def roles(%Info{is_moderator: is_moderator, is_admin: is_admin}) do
  306. %{
  307. admin: is_admin,
  308. moderator: is_moderator
  309. }
  310. end
  311. def add_reblog_mute(info, ap_id) do
  312. params = %{muted_reblogs: info.muted_reblogs ++ [ap_id]}
  313. cast(info, params, [:muted_reblogs])
  314. end
  315. def remove_reblog_mute(info, ap_id) do
  316. params = %{muted_reblogs: List.delete(info.muted_reblogs, ap_id)}
  317. cast(info, params, [:muted_reblogs])
  318. end
  319. def follow_information_update(info, params) do
  320. info
  321. |> cast(params, [
  322. :hide_followers,
  323. :hide_follows,
  324. :follower_count,
  325. :following_count
  326. ])
  327. end
  328. end