Merge branch 'feature/list-users' into 'master'

Add ability to list users

See merge request framasoft/mobilizon!83
This commit is contained in:
Thomas Citharel 2019-03-05 12:19:40 +01:00
commit bacd1bfb02
7 changed files with 185 additions and 13 deletions

View file

@ -266,8 +266,21 @@ defmodule Mobilizon.Actors do
[%Mobilizon.Actors.User{}] [%Mobilizon.Actors.User{}]
""" """
def list_users do def list_users(page \\ nil, limit \\ nil, sort \\ nil, direction \\ nil) do
Repo.all(User) Repo.all(
User
|> paginate(page, limit)
|> sort(sort, direction)
)
end
def count_users() do
Repo.one(
from(
u in User,
select: count(u.id)
)
)
end end
def insert_or_update_actor(data, preload \\ false) do def insert_or_update_actor(data, preload \\ false) do
@ -300,15 +313,6 @@ defmodule Mobilizon.Actors do
# update_and_set_cache(cs) # update_and_set_cache(cs)
# end # end
def count_users() do
Repo.one(
from(
u in User,
select: count(u.id)
)
)
end
@doc """ @doc """
Gets a single user. Gets a single user.

View file

@ -19,6 +19,16 @@ defmodule Mobilizon.Ecto do
) )
end end
@doc """
Add sort to the query
"""
def sort(query, sort, direction) do
from(
query,
order_by: [{^direction, ^sort}]
)
end
def increment_slug(slug) do def increment_slug(slug) do
case List.pop_at(String.split(slug, "-"), -1) do case List.pop_at(String.split(slug, "-"), -1) do
{nil, _} -> {nil, _} ->

View file

@ -24,6 +24,20 @@ defmodule MobilizonWeb.Resolvers.User do
{:error, "You need to be logged-in to view current user"} {:error, "You need to be logged-in to view current user"}
end end
@doc """
List instance users
"""
def list_and_count_users(
_parent,
%{page: page, limit: limit, sort: sort, direction: direction},
_resolution
) do
total = Task.async(&Actors.count_users/0)
elements = Task.async(fn -> Actors.list_users(page, limit, sort, direction) end)
{:ok, %{total: Task.await(total), elements: Task.await(elements)}}
end
@doc """ @doc """
Login an user. Returns a token and the user Login an user. Returns a token and the user
""" """

View file

@ -0,0 +1,12 @@
defmodule MobilizonWeb.Schema.SortType do
@moduledoc """
Allows sorting a collection of elements
"""
use Absinthe.Schema.Notation
@desc "Available sort directions"
enum :sort_direction do
value(:asc)
value(:desc)
end
end

View file

@ -6,6 +6,8 @@ defmodule MobilizonWeb.Schema.UserType do
alias MobilizonWeb.Resolvers.User alias MobilizonWeb.Resolvers.User
import MobilizonWeb.Schema.Utils import MobilizonWeb.Schema.Utils
import_types(MobilizonWeb.Schema.SortType)
@desc "A local user of Mobilizon" @desc "A local user of Mobilizon"
object :user do object :user do
field(:id, non_null(:id), description: "The user's ID") field(:id, non_null(:id), description: "The user's ID")
@ -36,6 +38,17 @@ defmodule MobilizonWeb.Schema.UserType do
) )
end end
@desc "Users list"
object :users do
field(:total, non_null(:integer), description: "Total elements")
field(:elements, non_null(list_of(:user)), description: "User elements")
end
@desc "The list of possible options for the event's status"
enum :sortable_user_field do
value(:id)
end
object :user_queries do object :user_queries do
@desc "Get an user" @desc "Get an user"
field :user, :user do field :user, :user do
@ -47,6 +60,17 @@ defmodule MobilizonWeb.Schema.UserType do
field :logged_user, :user do field :logged_user, :user do
resolve(&User.get_current_user/3) resolve(&User.get_current_user/3)
end end
@desc "List instance users"
field :users, :users do
arg(:page, :integer, default_value: 1)
arg(:limit, :integer, default_value: 10)
arg(:sort, :sortable_user_field, default_value: :id)
arg(:direction, :sort_direction, default_value: :desc)
resolve(&User.list_and_count_users/3)
end
end end
object :user_mutations do object :user_mutations do

View file

@ -274,7 +274,7 @@ defmodule Mobilizon.ActorsTest do
test "list_users/0 returns all users" do test "list_users/0 returns all users" do
user = insert(:user) user = insert(:user)
users = Actors.list_users() users = Actors.list_users(nil, nil, :id, :desc)
assert [user.id] == users |> Enum.map(& &1.id) assert [user.id] == users |> Enum.map(& &1.id)
end end

View file

@ -72,6 +72,114 @@ defmodule MobilizonWeb.Resolvers.UserResolverTest do
end end
end end
describe "Resolver: List users" do
test "list_users/3 returns a list of users", context do
insert(:user, email: "riri@example.com")
insert(:user, email: "fifi@example.com")
insert(:user, email: "loulou@example.com")
query = """
{
users {
total,
elements {
email
}
}
}
"""
res =
context.conn
|> get("/api", AbsintheHelpers.query_skeleton(query, "user"))
assert json_response(res, 200)["errors"] == nil
assert json_response(res, 200)["data"]["users"]["total"] == 3
assert json_response(res, 200)["data"]["users"]["elements"] |> length == 3
assert json_response(res, 200)["data"]["users"]["elements"]
|> Enum.map(& &1["email"]) == [
"loulou@example.com",
"fifi@example.com",
"riri@example.com"
]
query = """
{
users(page: 2, limit: 1) {
total,
elements {
email
}
}
}
"""
res =
context.conn
|> get("/api", AbsintheHelpers.query_skeleton(query, "user"))
assert json_response(res, 200)["errors"] == nil
assert json_response(res, 200)["data"]["users"]["total"] == 3
assert json_response(res, 200)["data"]["users"]["elements"] |> length == 1
assert json_response(res, 200)["data"]["users"]["elements"] |> Enum.map(& &1["email"]) == [
"fifi@example.com"
]
query = """
{
users(page: 3, limit: 1, sort: ID, direction: DESC) {
total,
elements {
email
}
}
}
"""
res =
context.conn
|> get("/api", AbsintheHelpers.query_skeleton(query, "user"))
assert json_response(res, 200)["errors"] == nil
assert json_response(res, 200)["data"]["users"]["total"] == 3
assert json_response(res, 200)["data"]["users"]["elements"] |> length == 1
assert json_response(res, 200)["data"]["users"]["elements"] |> Enum.map(& &1["email"]) == [
"riri@example.com"
]
end
test "get_current_user/3 returns the current logged-in user", context do
user = insert(:user)
query = """
{
loggedUser {
id
}
}
"""
res =
context.conn
|> get("/api", AbsintheHelpers.query_skeleton(query, "logged_user"))
assert json_response(res, 200)["data"]["loggedUser"] == nil
assert hd(json_response(res, 200)["errors"])["message"] ==
"You need to be logged-in to view current user"
res =
context.conn
|> auth_conn(user)
|> get("/api", AbsintheHelpers.query_skeleton(query, "logged_user"))
assert json_response(res, 200)["data"]["loggedUser"]["id"] == to_string(user.id)
end
end
describe "Resolver: Create an user & actor" do describe "Resolver: Create an user & actor" do
@user_creation %{ @user_creation %{
email: "test@demo.tld", email: "test@demo.tld",