Merge branch 'admin-create-users' into 'develop'
user creation admin api will create multiple users See merge request pleroma/pleroma!1170
This commit is contained in:
commit
90986667ce
|
@ -195,6 +195,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Configuration: Added `extra_cookie_attrs` for setting non-standard cookie attributes. Defaults to ["SameSite=Lax"] so that remote follows work.
|
- Configuration: Added `extra_cookie_attrs` for setting non-standard cookie attributes. Defaults to ["SameSite=Lax"] so that remote follows work.
|
||||||
- Timelines: Messages involving people you have blocked will be excluded from the timeline in all cases instead of just repeats.
|
- Timelines: Messages involving people you have blocked will be excluded from the timeline in all cases instead of just repeats.
|
||||||
- Admin API: Move the user related API to `api/pleroma/admin/users`
|
- Admin API: Move the user related API to `api/pleroma/admin/users`
|
||||||
|
- Admin API: `POST /api/pleroma/admin/users` will take list of users
|
||||||
- Pleroma API: Support for emoji tags in `/api/pleroma/emoji` resulting in a breaking API change
|
- Pleroma API: Support for emoji tags in `/api/pleroma/emoji` resulting in a breaking API change
|
||||||
- Mastodon API: Support for `exclude_types`, `limit` and `min_id` in `/api/v1/notifications`
|
- Mastodon API: Support for `exclude_types`, `limit` and `min_id` in `/api/v1/notifications`
|
||||||
- Mastodon API: Add `languages` and `registrations` to `/api/v1/instance`
|
- Mastodon API: Add `languages` and `registrations` to `/api/v1/instance`
|
||||||
|
|
|
@ -330,7 +330,13 @@ defp autofollow_users(user) do
|
||||||
@doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)"
|
@doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)"
|
||||||
def register(%Ecto.Changeset{} = changeset) do
|
def register(%Ecto.Changeset{} = changeset) do
|
||||||
with {:ok, user} <- Repo.insert(changeset),
|
with {:ok, user} <- Repo.insert(changeset),
|
||||||
{:ok, user} <- autofollow_users(user),
|
{:ok, user} <- post_register_action(user) do
|
||||||
|
{:ok, user}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_register_action(%User{} = user) do
|
||||||
|
with {:ok, user} <- autofollow_users(user),
|
||||||
{:ok, user} <- set_cache(user),
|
{:ok, user} <- set_cache(user),
|
||||||
{:ok, _} <- User.WelcomeMessage.post_welcome_message_to_user(user),
|
{:ok, _} <- User.WelcomeMessage.post_welcome_message_to_user(user),
|
||||||
{:ok, _} <- try_send_confirmation_email(user) do
|
{:ok, _} <- try_send_confirmation_email(user) do
|
||||||
|
|
|
@ -53,10 +53,9 @@ def user_unfollow(conn, %{"follower" => follower_nick, "followed" => followed_ni
|
||||||
|> json("ok")
|
|> json("ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_create(
|
def users_create(conn, %{"users" => users}) do
|
||||||
conn,
|
changesets =
|
||||||
%{"nickname" => nickname, "email" => email, "password" => password}
|
Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
|
||||||
) do
|
|
||||||
user_data = %{
|
user_data = %{
|
||||||
nickname: nickname,
|
nickname: nickname,
|
||||||
name: nickname,
|
name: nickname,
|
||||||
|
@ -66,11 +65,40 @@ def user_create(
|
||||||
bio: "."
|
bio: "."
|
||||||
}
|
}
|
||||||
|
|
||||||
changeset = User.register_changeset(%User{}, user_data, need_confirmation: false)
|
User.register_changeset(%User{}, user_data, need_confirmation: false)
|
||||||
{:ok, user} = User.register(changeset)
|
end)
|
||||||
|
|> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
|
||||||
|
Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
|
||||||
|
end)
|
||||||
|
|
||||||
|
case Pleroma.Repo.transaction(changesets) do
|
||||||
|
{:ok, users} ->
|
||||||
|
res =
|
||||||
|
users
|
||||||
|
|> Map.values()
|
||||||
|
|> Enum.map(fn user ->
|
||||||
|
{:ok, user} = User.post_register_action(user)
|
||||||
|
user
|
||||||
|
end)
|
||||||
|
|> Enum.map(&AccountView.render("created.json", %{user: &1}))
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> json(user.nickname)
|
|> json(res)
|
||||||
|
|
||||||
|
{:error, id, changeset, _} ->
|
||||||
|
res =
|
||||||
|
Enum.map(changesets.operations, fn
|
||||||
|
{current_id, {:changeset, _current_changeset, _}} when current_id == id ->
|
||||||
|
AccountView.render("create-error.json", %{changeset: changeset})
|
||||||
|
|
||||||
|
{_, {:changeset, current_changeset, _}} ->
|
||||||
|
AccountView.render("create-error.json", %{changeset: current_changeset})
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_status(:conflict)
|
||||||
|
|> json(res)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_show(conn, %{"nickname" => nickname}) do
|
def user_show(conn, %{"nickname" => nickname}) do
|
||||||
|
|
|
@ -52,4 +52,50 @@ def render("invites.json", %{invites: invites}) do
|
||||||
invites: render_many(invites, AccountView, "invite.json", as: :invite)
|
invites: render_many(invites, AccountView, "invite.json", as: :invite)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render("created.json", %{user: user}) do
|
||||||
|
%{
|
||||||
|
type: "success",
|
||||||
|
code: 200,
|
||||||
|
data: %{
|
||||||
|
nickname: user.nickname,
|
||||||
|
email: user.email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def render("create-error.json", %{changeset: %Ecto.Changeset{changes: changes, errors: errors}}) do
|
||||||
|
%{
|
||||||
|
type: "error",
|
||||||
|
code: 409,
|
||||||
|
error: parse_error(errors),
|
||||||
|
data: %{
|
||||||
|
nickname: Map.get(changes, :nickname),
|
||||||
|
email: Map.get(changes, :email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_error([]), do: ""
|
||||||
|
|
||||||
|
defp parse_error(errors) do
|
||||||
|
## when nickname is duplicate ap_id constraint error is raised
|
||||||
|
nickname_error = Keyword.get(errors, :nickname) || Keyword.get(errors, :ap_id)
|
||||||
|
email_error = Keyword.get(errors, :email)
|
||||||
|
password_error = Keyword.get(errors, :password)
|
||||||
|
|
||||||
|
cond do
|
||||||
|
nickname_error ->
|
||||||
|
"nickname #{elem(nickname_error, 0)}"
|
||||||
|
|
||||||
|
email_error ->
|
||||||
|
"email #{elem(email_error, 0)}"
|
||||||
|
|
||||||
|
password_error ->
|
||||||
|
"password #{elem(password_error, 0)}"
|
||||||
|
|
||||||
|
true ->
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -155,7 +155,7 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/users/unfollow", AdminAPIController, :user_unfollow)
|
post("/users/unfollow", AdminAPIController, :user_unfollow)
|
||||||
|
|
||||||
delete("/users", AdminAPIController, :user_delete)
|
delete("/users", AdminAPIController, :user_delete)
|
||||||
post("/users", AdminAPIController, :user_create)
|
post("/users", AdminAPIController, :users_create)
|
||||||
patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation)
|
patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation)
|
||||||
put("/users/tag", AdminAPIController, :tag_users)
|
put("/users/tag", AdminAPIController, :tag_users)
|
||||||
delete("/users/tag", AdminAPIController, :untag_users)
|
delete("/users/tag", AdminAPIController, :untag_users)
|
||||||
|
|
|
@ -35,12 +35,131 @@ test "Create" do
|
||||||
|> assign(:user, admin)
|
|> assign(:user, admin)
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|> post("/api/pleroma/admin/users", %{
|
|> post("/api/pleroma/admin/users", %{
|
||||||
|
"users" => [
|
||||||
|
%{
|
||||||
"nickname" => "lain",
|
"nickname" => "lain",
|
||||||
"email" => "lain@example.org",
|
"email" => "lain@example.org",
|
||||||
"password" => "test"
|
"password" => "test"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"nickname" => "lain2",
|
||||||
|
"email" => "lain2@example.org",
|
||||||
|
"password" => "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
assert json_response(conn, 200) == "lain"
|
response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
|
||||||
|
assert response == ["success", "success"]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Cannot create user with exisiting email" do
|
||||||
|
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/users", %{
|
||||||
|
"users" => [
|
||||||
|
%{
|
||||||
|
"nickname" => "lain",
|
||||||
|
"email" => user.email,
|
||||||
|
"password" => "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
assert json_response(conn, 409) == [
|
||||||
|
%{
|
||||||
|
"code" => 409,
|
||||||
|
"data" => %{
|
||||||
|
"email" => user.email,
|
||||||
|
"nickname" => "lain"
|
||||||
|
},
|
||||||
|
"error" => "email has already been taken",
|
||||||
|
"type" => "error"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Cannot create user with exisiting nickname" do
|
||||||
|
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/users", %{
|
||||||
|
"users" => [
|
||||||
|
%{
|
||||||
|
"nickname" => user.nickname,
|
||||||
|
"email" => "someuser@plerama.social",
|
||||||
|
"password" => "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
assert json_response(conn, 409) == [
|
||||||
|
%{
|
||||||
|
"code" => 409,
|
||||||
|
"data" => %{
|
||||||
|
"email" => "someuser@plerama.social",
|
||||||
|
"nickname" => user.nickname
|
||||||
|
},
|
||||||
|
"error" => "nickname has already been taken",
|
||||||
|
"type" => "error"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Multiple user creation works in transaction" do
|
||||||
|
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/users", %{
|
||||||
|
"users" => [
|
||||||
|
%{
|
||||||
|
"nickname" => "newuser",
|
||||||
|
"email" => "newuser@pleroma.social",
|
||||||
|
"password" => "test"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"nickname" => "lain",
|
||||||
|
"email" => user.email,
|
||||||
|
"password" => "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
assert json_response(conn, 409) == [
|
||||||
|
%{
|
||||||
|
"code" => 409,
|
||||||
|
"data" => %{
|
||||||
|
"email" => user.email,
|
||||||
|
"nickname" => "lain"
|
||||||
|
},
|
||||||
|
"error" => "email has already been taken",
|
||||||
|
"type" => "error"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"code" => 409,
|
||||||
|
"data" => %{
|
||||||
|
"email" => "newuser@pleroma.social",
|
||||||
|
"nickname" => "newuser"
|
||||||
|
},
|
||||||
|
"error" => "",
|
||||||
|
"type" => "error"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert User.get_by_nickname("newuser") === nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue