collections. Should speed up the queries because ecto doesn't have to parse the json.tags/v0.9.9
@@ -278,24 +278,30 @@ defmodule Pleroma.User do | |||
end | |||
end | |||
def get_followers(%User{id: id, follower_address: follower_address}) do | |||
q = | |||
from( | |||
u in User, | |||
where: fragment("? <@ ?", ^[follower_address], u.following), | |||
where: u.id != ^id | |||
) | |||
def get_followers_query(%User{id: id, follower_address: follower_address}) do | |||
from( | |||
u in User, | |||
where: fragment("? <@ ?", ^[follower_address], u.following), | |||
where: u.id != ^id | |||
) | |||
end | |||
def get_followers(user) do | |||
q = get_followers_query(user) | |||
{:ok, Repo.all(q)} | |||
end | |||
def get_friends(%User{id: id, following: following}) do | |||
q = | |||
from( | |||
u in User, | |||
where: u.follower_address in ^following, | |||
where: u.id != ^id | |||
) | |||
def get_friends_query(%User{id: id, following: following}) do | |||
from( | |||
u in User, | |||
where: u.follower_address in ^following, | |||
where: u.id != ^id | |||
) | |||
end | |||
def get_friends(user) do | |||
q = get_friends_query(user) | |||
{:ok, Repo.all(q)} | |||
end | |||
@@ -3,9 +3,11 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
alias Pleroma.Web.Salmon | |||
alias Pleroma.Web.WebFinger | |||
alias Pleroma.User | |||
alias Pleroma.Repo | |||
alias Pleroma.Web.ActivityPub.ActivityPub | |||
alias Pleroma.Web.ActivityPub.Transmogrifier | |||
alias Pleroma.Web.ActivityPub.Utils | |||
import Ecto.Query | |||
def render("user.json", %{user: user}) do | |||
{:ok, user} = WebFinger.ensure_keys_present(user) | |||
@@ -45,10 +47,11 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
|> Map.merge(Utils.make_json_ld_header()) | |||
end | |||
def collection(collection, iri, page) do | |||
def collection(collection, iri, page, total \\ nil) do | |||
offset = (page - 1) * 10 | |||
items = Enum.slice(collection, offset, 10) | |||
items = Enum.map(items, fn user -> user.ap_id end) | |||
total = total || length(collection) | |||
map = %{ | |||
"id" => "#{iri}?page=#{page}", | |||
@@ -64,14 +67,18 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
end | |||
def render("following.json", %{user: user, page: page}) do | |||
{:ok, following} = User.get_friends(user) | |||
query = User.get_friends_query(user) | |||
query = from(user in query, select: [:ap_id]) | |||
following = Repo.all(query) | |||
collection(following, "#{user.ap_id}/following", page) | |||
|> Map.merge(Utils.make_json_ld_header()) | |||
end | |||
def render("following.json", %{user: user}) do | |||
{:ok, following} = User.get_friends(user) | |||
query = User.get_friends_query(user) | |||
query = from(user in query, select: [:ap_id]) | |||
following = Repo.all(query) | |||
%{ | |||
"id" => "#{user.ap_id}/following", | |||
@@ -83,14 +90,18 @@ defmodule Pleroma.Web.ActivityPub.UserView do | |||
end | |||
def render("followers.json", %{user: user, page: page}) do | |||
{:ok, followers} = User.get_followers(user) | |||
query = User.get_followers_query(user) | |||
query = from(user in query, select: [:ap_id]) | |||
followers = Repo.all(query) | |||
collection(followers, "#{user.ap_id}/followers", page) | |||
|> Map.merge(Utils.make_json_ld_header()) | |||
end | |||
def render("followers.json", %{user: user}) do | |||
{:ok, followers} = User.get_followers(user) | |||
query = User.get_followers_query(user) | |||
query = from(user in query, select: [:ap_id]) | |||
followers = Repo.all(query) | |||
%{ | |||
"id" => "#{user.ap_id}/followers", | |||
@@ -49,4 +49,87 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
assert Activity.get_by_ap_id(data["id"]) | |||
end | |||
end | |||
describe "/users/:nickname/followers" do | |||
test "it returns the followers in a collection", %{conn: conn} do | |||
user = insert(:user) | |||
user_two = insert(:user) | |||
User.follow(user, user_two) | |||
result = | |||
conn | |||
|> get("/users/#{user_two.nickname}/followers") | |||
|> json_response(200) | |||
assert result["first"]["orderedItems"] == [user.ap_id] | |||
end | |||
test "it works for more than 10 users", %{conn: conn} do | |||
user = insert(:user) | |||
Enum.each(1..15, fn _ -> | |||
other_user = insert(:user) | |||
User.follow(other_user, user) | |||
end) | |||
result = | |||
conn | |||
|> get("/users/#{user.nickname}/followers") | |||
|> json_response(200) | |||
assert length(result["first"]["orderedItems"]) == 10 | |||
assert result["first"]["totalItems"] == 15 | |||
assert result["totalItems"] == 15 | |||
result = | |||
conn | |||
|> get("/users/#{user.nickname}/followers?page=2") | |||
|> json_response(200) | |||
assert length(result["orderedItems"]) == 5 | |||
assert result["totalItems"] == 15 | |||
end | |||
end | |||
describe "/users/:nickname/following" do | |||
test "it returns the following in a collection", %{conn: conn} do | |||
user = insert(:user) | |||
user_two = insert(:user) | |||
User.follow(user, user_two) | |||
result = | |||
conn | |||
|> get("/users/#{user.nickname}/following") | |||
|> json_response(200) | |||
assert result["first"]["orderedItems"] == [user_two.ap_id] | |||
end | |||
test "it works for more than 10 users", %{conn: conn} do | |||
user = insert(:user) | |||
Enum.each(1..15, fn _ -> | |||
user = Repo.get(User, user.id) | |||
other_user = insert(:user) | |||
User.follow(user, other_user) | |||
end) | |||
result = | |||
conn | |||
|> get("/users/#{user.nickname}/following") | |||
|> json_response(200) | |||
assert length(result["first"]["orderedItems"]) == 10 | |||
assert result["first"]["totalItems"] == 15 | |||
assert result["totalItems"] == 15 | |||
result = | |||
conn | |||
|> get("/users/#{user.nickname}/following?page=2") | |||
|> json_response(200) | |||
assert length(result["orderedItems"]) == 5 | |||
assert result["totalItems"] == 15 | |||
end | |||
end | |||
end |