pleroma/test/web/admin_api/admin_api_controller_test.exs

785 lines
23 KiB
Elixir
Raw Normal View History

2018-12-23 15:11:29 -05:00
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
use Pleroma.Web.ConnCase
2019-02-10 16:57:38 -05:00
alias Pleroma.User
2019-04-06 09:25:19 -04:00
alias Pleroma.UserInviteToken
import Pleroma.Factory
describe "/api/pleroma/admin/user" do
test "Delete" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> delete("/api/pleroma/admin/user?nickname=#{user.nickname}")
assert json_response(conn, 200) == user.nickname
end
test "Create" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/user", %{
"nickname" => "lain",
"email" => "lain@example.org",
"password" => "test"
})
assert json_response(conn, 200) == "lain"
end
end
describe "/api/pleroma/admin/users/:nickname" do
test "Show", %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
conn
|> assign(:user, admin)
|> get("/api/pleroma/admin/users/#{user.nickname}")
expected = %{
"deactivated" => false,
"id" => to_string(user.id),
"local" => true,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"tags" => []
}
assert expected == json_response(conn, 200)
end
test "when the user doesn't exist", %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
user = build(:user)
conn =
conn
|> assign(:user, admin)
|> get("/api/pleroma/admin/users/#{user.nickname}")
assert "Not found" == json_response(conn, 404)
end
end
describe "/api/pleroma/admin/user/follow" do
test "allows to force-follow another user" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
follower = insert(:user)
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/user/follow", %{
"follower" => follower.nickname,
"followed" => user.nickname
})
2019-04-22 03:20:43 -04:00
user = User.get_cached_by_id(user.id)
follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, user)
end
end
describe "/api/pleroma/admin/user/unfollow" do
test "allows to force-unfollow another user" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
follower = insert(:user)
User.follow(follower, user)
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/user/unfollow", %{
"follower" => follower.nickname,
"followed" => user.nickname
})
2019-04-22 03:20:43 -04:00
user = User.get_cached_by_id(user.id)
follower = User.get_cached_by_id(follower.id)
refute User.following?(follower, user)
end
end
describe "PUT /api/pleroma/admin/users/tag" do
setup do
admin = insert(:user, info: %{is_admin: true})
user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y"]})
user3 = insert(:user, %{tags: ["unchanged"]})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
2018-12-06 12:13:07 -05:00
|> put(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
user2.nickname
}&tags[]=foo&tags[]=bar"
)
%{conn: conn, user1: user1, user2: user2, user3: user3}
end
2018-12-06 12:13:07 -05:00
test "it appends specified tags to users with specified nicknames", %{
conn: conn,
user1: user1,
user2: user2
} do
assert json_response(conn, :no_content)
2019-04-22 03:20:43 -04:00
assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
assert json_response(conn, :no_content)
2019-04-22 03:20:43 -04:00
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
end
describe "DELETE /api/pleroma/admin/users/tag" do
setup do
admin = insert(:user, info: %{is_admin: true})
user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y", "z"]})
user3 = insert(:user, %{tags: ["unchanged"]})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> delete(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
2018-12-06 12:13:07 -05:00
user2.nickname
}&tags[]=x&tags[]=z"
)
%{conn: conn, user1: user1, user2: user2, user3: user3}
end
2018-12-06 12:13:07 -05:00
test "it removes specified tags from users with specified nicknames", %{
conn: conn,
user1: user1,
user2: user2
} do
assert json_response(conn, :no_content)
2019-04-22 03:20:43 -04:00
assert User.get_cached_by_id(user1.id).tags == []
assert User.get_cached_by_id(user2.id).tags == ["y"]
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
assert json_response(conn, :no_content)
2019-04-22 03:20:43 -04:00
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
end
describe "/api/pleroma/admin/permission_group" do
test "GET is giving user_info" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/permission_group/#{admin.nickname}")
2018-12-01 03:03:16 -05:00
assert json_response(conn, 200) == %{
"is_admin" => true,
"is_moderator" => false
}
end
test "/:right POST, can add to a permission group" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/permission_group/#{user.nickname}/admin")
2018-12-01 03:03:16 -05:00
assert json_response(conn, 200) == %{
"is_admin" => true
}
end
test "/:right DELETE, can remove from a permission group" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
user = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> delete("/api/pleroma/admin/permission_group/#{user.nickname}/admin")
2018-12-01 03:03:16 -05:00
assert json_response(conn, 200) == %{
"is_admin" => false
}
end
end
describe "PUT /api/pleroma/admin/activation_status" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
conn =
conn
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
%{conn: conn}
end
test "deactivates the user", %{conn: conn} do
user = insert(:user)
conn =
conn
|> put("/api/pleroma/admin/activation_status/#{user.nickname}", %{status: false})
2019-04-22 03:20:43 -04:00
user = User.get_cached_by_id(user.id)
assert user.info.deactivated == true
assert json_response(conn, :no_content)
end
test "activates the user", %{conn: conn} do
user = insert(:user, info: %{deactivated: true})
conn =
conn
|> put("/api/pleroma/admin/activation_status/#{user.nickname}", %{status: true})
2019-04-22 03:20:43 -04:00
user = User.get_cached_by_id(user.id)
assert user.info.deactivated == false
assert json_response(conn, :no_content)
end
test "returns 403 when requested by a non-admin", %{conn: conn} do
user = insert(:user)
conn =
conn
|> assign(:user, user)
|> put("/api/pleroma/admin/activation_status/#{user.nickname}", %{status: false})
assert json_response(conn, :forbidden)
end
end
2018-12-14 05:52:04 -05:00
describe "POST /api/pleroma/admin/email_invite, with valid config" do
setup do
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
Pleroma.Config.put([:instance, :registrations_open], false)
Pleroma.Config.put([:instance, :invites_enabled], true)
on_exit(fn ->
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
:ok
end)
[user: insert(:user, info: %{is_admin: true})]
end
test "sends invitation and returns 204", %{conn: conn, user: user} do
recipient_email = "foo@bar.com"
recipient_name = "J. D."
conn =
conn
|> assign(:user, user)
|> post("/api/pleroma/admin/email_invite?email=#{recipient_email}&name=#{recipient_name}")
assert json_response(conn, :no_content)
2018-12-14 05:52:04 -05:00
token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
assert token_record
refute token_record.used
notify_email = Pleroma.Config.get([:instance, :notify_email])
instance_name = Pleroma.Config.get([:instance, :name])
email =
2019-04-13 03:55:42 -04:00
Pleroma.Emails.UserEmail.user_invitation_email(
2018-12-14 05:52:04 -05:00
user,
token_record,
recipient_email,
recipient_name
)
Swoosh.TestAssertions.assert_email_sent(
from: {instance_name, notify_email},
to: {recipient_name, recipient_email},
html_body: email.html_body
2018-12-14 05:52:04 -05:00
)
end
test "it returns 403 if requested by a non-admin", %{conn: conn} do
non_admin_user = insert(:user)
conn =
conn
|> assign(:user, non_admin_user)
|> post("/api/pleroma/admin/email_invite?email=foo@bar.com&name=JD")
assert json_response(conn, :forbidden)
end
end
describe "POST /api/pleroma/admin/email_invite, with invalid config" do
setup do
[user: insert(:user, info: %{is_admin: true})]
end
test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
Pleroma.Config.put([:instance, :registrations_open], false)
Pleroma.Config.put([:instance, :invites_enabled], false)
on_exit(fn ->
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
:ok
end)
conn =
conn
|> assign(:user, user)
|> post("/api/pleroma/admin/email_invite?email=foo@bar.com&name=JD")
assert json_response(conn, :internal_server_error)
end
test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
Pleroma.Config.put([:instance, :registrations_open], true)
Pleroma.Config.put([:instance, :invites_enabled], true)
on_exit(fn ->
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
:ok
end)
conn =
conn
|> assign(:user, user)
|> post("/api/pleroma/admin/email_invite?email=foo@bar.com&name=JD")
assert json_response(conn, :internal_server_error)
end
end
test "/api/pleroma/admin/invite_token" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/invite_token")
assert conn.status == 200
end
test "/api/pleroma/admin/password_reset" do
2018-12-01 03:03:16 -05:00
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/password_reset?nickname=#{user.nickname}")
assert conn.status == 200
end
2019-02-26 19:08:03 -05:00
2019-02-28 09:54:02 -05:00
describe "GET /api/pleroma/admin/users" do
test "renders users array for the first page" do
admin = insert(:user, info: %{is_admin: true})
2019-03-13 18:52:24 -04:00
user = insert(:user, local: false, tags: ["foo", "bar"])
2019-02-26 19:08:03 -05:00
2019-02-28 09:54:02 -05:00
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?page=1")
assert json_response(conn, 200) == %{
2019-03-02 09:21:18 -05:00
"count" => 2,
2019-02-28 09:54:02 -05:00
"page_size" => 50,
"users" => [
2019-03-01 12:23:19 -05:00
%{
"deactivated" => admin.info.deactivated,
"id" => admin.id,
2019-03-12 15:15:28 -04:00
"nickname" => admin.nickname,
2019-03-13 09:14:31 -04:00
"roles" => %{"admin" => true, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
2019-03-01 12:23:19 -05:00
},
2019-02-28 09:54:02 -05:00
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
2019-03-12 15:15:28 -04:00
"nickname" => user.nickname,
2019-03-13 09:14:31 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => false,
"tags" => ["foo", "bar"]
2019-02-28 09:54:02 -05:00
}
]
}
end
test "renders empty array for the second page" do
admin = insert(:user, info: %{is_admin: true})
2019-02-28 11:04:47 -05:00
insert(:user)
2019-02-28 09:54:02 -05:00
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?page=2")
assert json_response(conn, 200) == %{
2019-03-02 09:21:18 -05:00
"count" => 2,
2019-02-28 09:54:02 -05:00
"page_size" => 50,
"users" => []
}
end
2019-02-26 19:08:03 -05:00
2019-03-01 12:13:02 -05:00
test "regular search" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user, nickname: "bob")
2019-02-28 11:04:47 -05:00
2019-03-01 12:13:02 -05:00
conn =
build_conn()
|> assign(:user, admin)
2019-03-04 13:26:32 -05:00
|> get("/api/pleroma/admin/users?query=bo")
2019-03-01 12:13:02 -05:00
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
2019-03-12 15:15:28 -04:00
"nickname" => user.nickname,
2019-03-13 09:04:44 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
}
]
}
2019-03-01 12:13:02 -05:00
end
2019-03-02 09:21:18 -05:00
test "regular search with page size" do
2019-03-01 12:13:02 -05:00
admin = insert(:user, info: %{is_admin: true})
user = insert(:user, nickname: "aalice")
user2 = insert(:user, nickname: "alice")
2019-03-02 09:21:18 -05:00
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?query=a&page_size=1&page=1")
2019-03-02 09:21:18 -05:00
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 1,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
2019-03-12 15:15:28 -04:00
"nickname" => user.nickname,
2019-03-13 09:04:44 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
2019-03-02 09:21:18 -05:00
}
]
}
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?query=a&page_size=1&page=2")
2019-03-02 09:21:18 -05:00
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 1,
"users" => [
%{
"deactivated" => user2.info.deactivated,
"id" => user2.id,
2019-03-12 15:15:28 -04:00
"nickname" => user2.nickname,
2019-03-13 09:04:44 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
2019-03-02 09:21:18 -05:00
}
]
}
end
test "only local users" do
admin = insert(:user, info: %{is_admin: true}, nickname: "john")
user = insert(:user, nickname: "bob")
2019-03-01 12:13:02 -05:00
insert(:user, nickname: "bobb", local: false)
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?query=bo&filters=local")
2019-03-01 12:13:02 -05:00
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
2019-03-12 15:15:28 -04:00
"nickname" => user.nickname,
2019-03-13 09:04:44 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
}
]
}
2019-03-01 12:13:02 -05:00
end
2019-03-04 13:26:32 -05:00
test "only local users with no query" do
admin = insert(:user, info: %{is_admin: true}, nickname: "john")
user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false)
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?filters=local")
2019-03-04 13:26:32 -05:00
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 50,
"users" => [
2019-03-04 13:33:53 -05:00
%{
2019-03-04 13:26:32 -05:00
"deactivated" => user.info.deactivated,
"id" => user.id,
2019-03-12 15:15:28 -04:00
"nickname" => user.nickname,
2019-03-13 09:04:44 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
2019-03-17 06:29:28 -04:00
},
%{
"deactivated" => admin.info.deactivated,
"id" => admin.id,
"nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
"local" => true,
"tags" => []
2019-03-04 13:26:32 -05:00
}
]
}
end
test "it works with multiple filters" do
admin = insert(:user, nickname: "john", info: %{is_admin: true})
user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true})
insert(:user, nickname: "ken", local: true, info: %{deactivated: true})
insert(:user, nickname: "bobb", local: false, info: %{deactivated: false})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?filters=deactivated,external")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => user.local,
"tags" => []
}
]
}
end
2019-03-04 13:26:32 -05:00
end
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
assert json_response(conn, 200) ==
%{
"deactivated" => !user.info.deactivated,
"id" => user.id,
2019-03-12 15:15:28 -04:00
"nickname" => user.nickname,
2019-03-13 09:04:44 -04:00
"roles" => %{"admin" => false, "moderator" => false},
2019-03-13 18:52:24 -04:00
"local" => true,
"tags" => []
2019-03-04 13:26:32 -05:00
}
2019-02-28 11:04:47 -05:00
end
2019-04-06 09:25:19 -04:00
describe "GET /api/pleroma/admin/invite_token" do
test "without options" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/invite_token")
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
refute invite.expires_at
2019-04-06 09:25:19 -04:00
refute invite.max_use
assert invite.invite_type == "one_time"
end
test "with expires_at" do
2019-04-06 09:25:19 -04:00
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/invite_token", %{
"invite" => %{"expires_at" => Date.to_string(Date.utc_today())}
2019-04-06 09:25:19 -04:00
})
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
assert invite.expires_at == Date.utc_today()
2019-04-06 09:25:19 -04:00
refute invite.max_use
assert invite.invite_type == "date_limited"
end
test "with max_use" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/invite_token", %{
"invite" => %{"max_use" => 150}
})
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
refute invite.expires_at
2019-04-06 09:25:19 -04:00
assert invite.max_use == 150
assert invite.invite_type == "reusable"
end
test "with max use and expires_at" do
2019-04-06 09:25:19 -04:00
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/invite_token", %{
"invite" => %{"max_use" => 150, "expires_at" => Date.to_string(Date.utc_today())}
2019-04-06 09:25:19 -04:00
})
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
assert invite.expires_at == Date.utc_today()
2019-04-06 09:25:19 -04:00
assert invite.max_use == 150
assert invite.invite_type == "reusable_date_limited"
end
end
describe "GET /api/pleroma/admin/invites" do
2019-04-06 09:25:19 -04:00
test "no invites" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/invites")
2019-04-06 09:25:19 -04:00
assert json_response(conn, 200) == %{"invites" => []}
end
test "with invite" do
admin = insert(:user, info: %{is_admin: true})
{:ok, invite} = UserInviteToken.create_invite()
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/invites")
2019-04-06 09:25:19 -04:00
assert json_response(conn, 200) == %{
"invites" => [
%{
"expires_at" => nil,
2019-04-06 09:25:19 -04:00
"id" => invite.id,
"invite_type" => "one_time",
"max_use" => nil,
"token" => invite.token,
"used" => false,
"uses" => 0
}
]
}
end
end
describe "POST /api/pleroma/admin/revoke_invite" do
2019-04-06 09:25:19 -04:00
test "with token" do
admin = insert(:user, info: %{is_admin: true})
{:ok, invite} = UserInviteToken.create_invite()
conn =
build_conn()
|> assign(:user, admin)
|> post("/api/pleroma/admin/revoke_invite", %{"token" => invite.token})
2019-04-06 09:25:19 -04:00
assert json_response(conn, 200) == %{
"expires_at" => nil,
2019-04-06 09:25:19 -04:00
"id" => invite.id,
"invite_type" => "one_time",
"max_use" => nil,
"token" => invite.token,
"used" => true,
"uses" => 0
}
end
end
end