X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser.ex;h=1dad30e876f6265d5835e7604ded15aea50ca3a8;hb=90661e20cf91b2b1e95fdee73f2e95aa18c1be65;hp=1dcb68470d92adda90ad42a3f86652037e2dc932;hpb=1452b2823fbd858f2b818c35ca1faedb0d222690;p=akkoma diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 1dcb68470..1dad30e87 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -68,7 +68,8 @@ defmodule Pleroma.User do following_count: length(user.following) - oneself, note_count: user.info["note_count"] || 0, follower_count: user.info["follower_count"] || 0, - locked: user.info["locked"] || false + locked: user.info["locked"] || false, + default_scope: user.info["default_scope"] || "public" } end @@ -77,7 +78,7 @@ defmodule Pleroma.User do changes = %User{} |> cast(params, [:bio, :name, :ap_id, :nickname, :info, :avatar]) - |> validate_required([:name, :ap_id, :nickname]) + |> validate_required([:name, :ap_id]) |> unique_constraint(:nickname) |> validate_format(:nickname, @email_regex) |> validate_length(:bio, max: 5000) @@ -169,6 +170,9 @@ defmodule Pleroma.User do end def maybe_direct_follow(%User{} = follower, %User{info: info} = followed) do + user_config = Application.get_env(:pleroma, :user) + deny_follow_blocked = Keyword.get(user_config, :deny_follow_blocked) + user_info = user_info(followed) should_direct_follow = @@ -178,7 +182,8 @@ defmodule Pleroma.User do false # if the users are blocking each other, we shouldn't even be here, but check for it anyway - User.blocks?(follower, followed) == true or User.blocks?(followed, follower) == true -> + deny_follow_blocked and + (User.blocks?(follower, followed) or User.blocks?(followed, follower)) -> false # if OStatus, then there is no three-way handshake to follow @@ -206,13 +211,16 @@ defmodule Pleroma.User do end def follow(%User{} = follower, %User{info: info} = followed) do + user_config = Application.get_env(:pleroma, :user) + deny_follow_blocked = Keyword.get(user_config, :deny_follow_blocked) + ap_followers = followed.follower_address cond do following?(follower, followed) or info["deactivated"] -> {:error, "Could not follow user: #{followed.nickname} is already on your list."} - blocks?(followed, follower) -> + deny_follow_blocked and blocks?(followed, follower) -> {:error, "Could not follow user: #{followed.nickname} blocked you."} true -> @@ -364,19 +372,22 @@ defmodule Pleroma.User do def get_follow_requests_query(%User{} = user) do from( a in Activity, - where: fragment( - "? ->> 'type' = 'Follow'", - a.data - ), - where: fragment( - "? ->> 'state' = 'pending'", - a.data - ), - where: fragment( - "? @> ?", - a.data, - ^%{"object" => user.ap_id} - ) + where: + fragment( + "? ->> 'type' = 'Follow'", + a.data + ), + where: + fragment( + "? ->> 'state' = 'pending'", + a.data + ), + where: + fragment( + "? @> ?", + a.data, + ^%{"object" => user.ap_id} + ) ) end @@ -385,9 +396,10 @@ defmodule Pleroma.User do reqs = Repo.all(q) users = - Enum.map(reqs, fn (req) -> req.actor end) - |> Enum.uniq - |> Enum.map(fn (ap_id) -> get_by_ap_id(ap_id) end) + Enum.map(reqs, fn req -> req.actor end) + |> Enum.uniq() + |> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end) + |> Enum.filter(fn u -> !following?(u, user) end) {:ok, users} end @@ -446,13 +458,34 @@ defmodule Pleroma.User do update_and_set_cache(cs) end + def get_notified_from_activity_query(to) do + from( + u in User, + where: u.ap_id in ^to, + where: u.local == true + ) + end + + def get_notified_from_activity(%Activity{recipients: to, data: %{"type" => "Announce"} = data}) do + object = Object.normalize(data["object"]) + actor = User.get_cached_by_ap_id(data["actor"]) + + # ensure that the actor who published the announced object appears only once + to = + if actor.nickname != nil do + to ++ [object.data["actor"]] + else + to + end + |> Enum.uniq() + + query = get_notified_from_activity_query(to) + + Repo.all(query) + end + def get_notified_from_activity(%Activity{recipients: to}) do - query = - from( - u in User, - where: u.ap_id in ^to, - where: u.local == true - ) + query = get_notified_from_activity_query(to) Repo.all(query) end @@ -489,7 +522,8 @@ defmodule Pleroma.User do u.nickname, u.name ) - } + }, + where: not is_nil(u.nickname) ) q = @@ -502,15 +536,33 @@ defmodule Pleroma.User do Repo.all(q) end - def block(user, %{ap_id: ap_id}) do - blocks = user.info["blocks"] || [] + def block(blocker, %User{ap_id: ap_id} = blocked) do + # sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213) + blocker = + if following?(blocker, blocked) do + {:ok, blocker, _} = unfollow(blocker, blocked) + blocker + else + blocker + end + + if following?(blocked, blocker) do + unfollow(blocked, blocker) + end + + blocks = blocker.info["blocks"] || [] new_blocks = Enum.uniq([ap_id | blocks]) - new_info = Map.put(user.info, "blocks", new_blocks) + new_info = Map.put(blocker.info, "blocks", new_blocks) - cs = User.info_changeset(user, %{info: new_info}) + cs = User.info_changeset(blocker, %{info: new_info}) update_and_set_cache(cs) end + # helper to handle the block given only an actor's AP id + def block(blocker, %{ap_id: ap_id}) do + block(blocker, User.get_by_ap_id(ap_id)) + end + def unblock(user, %{ap_id: ap_id}) do blocks = user.info["blocks"] || [] new_blocks = List.delete(blocks, ap_id) @@ -550,7 +602,19 @@ defmodule Pleroma.User do end def local_user_query() do - from(u in User, where: u.local == true) + from( + u in User, + where: u.local == true, + where: not is_nil(u.nickname) + ) + end + + def moderator_user_query() do + from( + u in User, + where: u.local == true, + where: fragment("?->'is_moderator' @> 'true'", u.info) + ) end def deactivate(%User{} = user) do @@ -579,7 +643,7 @@ defmodule Pleroma.User do |> Enum.each(fn activity -> case activity.data["type"] do "Create" -> - ActivityPub.delete(Object.get_by_ap_id(activity.data["object"]["id"])) + ActivityPub.delete(Object.normalize(activity.data["object"])) # TODO: Do something with likes, follows, repeats. _ -> @@ -609,6 +673,25 @@ defmodule Pleroma.User do end end + def get_or_create_instance_user do + relay_uri = "#{Pleroma.Web.Endpoint.url()}/relay" + + if user = get_by_ap_id(relay_uri) do + user + else + changes = + %User{} + |> cast(%{}, [:ap_id, :nickname, :local]) + |> put_change(:ap_id, relay_uri) + |> put_change(:nickname, nil) + |> put_change(:local, true) + |> put_change(:follower_address, relay_uri <> "/followers") + + {:ok, user} = Repo.insert(changes) + user + end + end + # AP style def public_key_from_info(%{ "source_data" => %{"publicKey" => %{"publicKeyPem" => public_key_pem}}