Add ability to set a default post expiry (#321)
[akkoma] / lib / pleroma / user.ex
index d6628363218f6a0626b367f1f5931fd9f86a3e0c..b0ab9d0cd6ada61835b7bad09019524b9edee2ef 100644 (file)
@@ -151,6 +151,7 @@ defmodule Pleroma.User do
     field(:is_suggested, :boolean, default: false)
     field(:last_status_at, :naive_datetime)
     field(:language, :string)
+    field(:status_ttl_days, :integer, default: nil)
 
     embeds_one(
       :notification_settings,
@@ -165,6 +166,8 @@ defmodule Pleroma.User do
     has_many(:outgoing_relationships, UserRelationship, foreign_key: :source_id)
     has_many(:incoming_relationships, UserRelationship, foreign_key: :target_id)
 
+    has_many(:frontend_profiles, Pleroma.Akkoma.FrontendSettingsProfile)
+
     for {relationship_type,
          [
            {outgoing_relation, outgoing_relation_target},
@@ -514,7 +517,8 @@ defmodule Pleroma.User do
         :pleroma_settings_store,
         :is_discoverable,
         :actor_type,
-        :disclose_client
+        :disclose_client,
+        :status_ttl_days
       ]
     )
     |> unique_constraint(:nickname)
@@ -522,6 +526,7 @@ defmodule Pleroma.User do
     |> validate_length(:bio, max: bio_limit)
     |> validate_length(:name, min: 1, max: name_limit)
     |> validate_inclusion(:actor_type, ["Person", "Service"])
+    |> validate_number(:status_ttl_days, greater_than: 0)
     |> put_fields()
     |> put_emoji()
     |> put_change_if_present(:bio, &{:ok, parse_bio(&1, struct)})
@@ -660,6 +665,32 @@ defmodule Pleroma.User do
   @spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
   def force_password_reset(user), do: update_password_reset_pending(user, true)
 
+  # Used to auto-register LDAP accounts which won't have a password hash stored locally
+  def register_changeset_ldap(struct, params = %{password: password})
+      when is_nil(password) do
+    params =
+      if Map.has_key?(params, :email) do
+        Map.put_new(params, :email, params[:email])
+      else
+        params
+      end
+
+    struct
+    |> cast(params, [
+      :name,
+      :nickname,
+      :email
+    ])
+    |> validate_required([:name, :nickname])
+    |> unique_constraint(:nickname)
+    |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
+    |> validate_format(:nickname, local_nickname_regex())
+    |> put_ap_id()
+    |> unique_constraint(:ap_id)
+    |> put_following_and_follower_and_featured_address()
+    |> put_private_key()
+  end
+
   def register_changeset(struct, params \\ %{}, opts \\ []) do
     bio_limit = Config.get([:instance, :user_bio_length], 5000)
     name_limit = Config.get([:instance, :user_name_length], 100)
@@ -718,6 +749,7 @@ defmodule Pleroma.User do
     |> put_ap_id()
     |> unique_constraint(:ap_id)
     |> put_following_and_follower_and_featured_address()
+    |> put_private_key()
   end
 
   def maybe_validate_required_email(changeset, true), do: changeset
@@ -730,12 +762,12 @@ defmodule Pleroma.User do
     end
   end
 
-  defp put_ap_id(changeset) do
+  def put_ap_id(changeset) do
     ap_id = ap_id(%User{nickname: get_field(changeset, :nickname)})
     put_change(changeset, :ap_id, ap_id)
   end
 
-  defp put_following_and_follower_and_featured_address(changeset) do
+  def put_following_and_follower_and_featured_address(changeset) do
     user = %User{nickname: get_field(changeset, :nickname)}
     followers = ap_followers(user)
     following = ap_following(user)
@@ -747,6 +779,11 @@ defmodule Pleroma.User do
     |> put_change(:featured_address, featured)
   end
 
+  defp put_private_key(changeset) do
+    {:ok, pem} = Keys.generate_rsa_pem()
+    put_change(changeset, :keys, pem)
+  end
+
   defp autofollow_users(user) do
     candidates = Config.get([:instance, :autofollowed_nicknames])
 
@@ -1448,13 +1485,19 @@ defmodule Pleroma.User do
         blocker
       end
 
-    # clear any requested follows as well
+    # clear any requested follows from both sides as well
     blocked =
       case CommonAPI.reject_follow_request(blocked, blocker) do
         {:ok, %User{} = updated_blocked} -> updated_blocked
         nil -> blocked
       end
 
+    blocker =
+      case CommonAPI.reject_follow_request(blocker, blocked) do
+        {:ok, %User{} = updated_blocker} -> updated_blocker
+        nil -> blocker
+      end
+
     unsubscribe(blocked, blocker)
 
     unfollowing_blocked = Config.get([:activitypub, :unfollow_blocked], true)
@@ -1870,7 +1913,8 @@ defmodule Pleroma.User do
       {%User{} = user, _} ->
         {:ok, user}
 
-      _ ->
+      e ->
+        Logger.error("Could not fetch user, #{inspect(e)}")
         {:error, :not_found}
     end
   end
@@ -1917,6 +1961,7 @@ defmodule Pleroma.User do
       follower_address: uri <> "/followers"
     }
     |> change
+    |> put_private_key()
     |> unique_constraint(:nickname)
     |> Repo.insert()
     |> set_cache()
@@ -1949,7 +1994,8 @@ defmodule Pleroma.User do
 
   @doc "Gets or fetch a user by uri or nickname."
   @spec get_or_fetch(String.t()) :: {:ok, User.t()} | {:error, String.t()}
-  def get_or_fetch("http" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
+  def get_or_fetch("http://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
+  def get_or_fetch("https://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
   def get_or_fetch(nickname), do: get_or_fetch_by_nickname(nickname)
 
   # wait a period of time and return newest version of the User structs
@@ -2035,7 +2081,7 @@ defmodule Pleroma.User do
     |> Enum.map(&String.downcase/1)
   end
 
-  defp local_nickname_regex do
+  def local_nickname_regex do
     if Config.get([:instance, :extended_nickname_format]) do
       @extended_local_nickname_regex
     else
@@ -2182,17 +2228,6 @@ defmodule Pleroma.User do
     }
   end
 
-  def ensure_keys_present(%{keys: keys} = user) when not is_nil(keys), do: {:ok, user}
-
-  def ensure_keys_present(%User{} = user) do
-    with {:ok, pem} <- Keys.generate_rsa_pem() do
-      user
-      |> cast(%{keys: pem}, [:keys])
-      |> validate_required([:keys])
-      |> update_and_set_cache()
-    end
-  end
-
   def get_ap_ids_by_nicknames(nicknames) do
     from(u in User,
       where: u.nickname in ^nicknames,