Browse Source

Add email change endpoint

tags/v1.1.4
Egor Kislitsyn 4 years ago
parent
commit
25d8216804
7 changed files with 174 additions and 1 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +10
    -1
      docs/api/pleroma_api.md
  3. +9
    -0
      lib/pleroma/user.ex
  4. +1
    -0
      lib/pleroma/web/router.ex
  5. +19
    -0
      lib/pleroma/web/twitter_api/controllers/util_controller.ex
  6. +27
    -0
      test/user_test.exs
  7. +107
    -0
      test/web/twitter_api/util_controller_test.exs

+ 1
- 0
CHANGELOG.md View File

@@ -105,6 +105,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- ActivityPub: Optional signing of ActivityPub object fetches.
- Admin API: Endpoint for fetching latest user's statuses
- Pleroma API: Add `/api/v1/pleroma/accounts/confirmation_resend?email=<email>` for resending account confirmation.
- Pleroma API: Email change endpoint.
- Relays: Added a task to list relay subscriptions.
- Mix Tasks: `mix pleroma.database fix_likes_collections`
- Federation: Remove `likes` from objects.


+ 10
- 1
docs/api/pleroma_api.md View File

@@ -252,7 +252,7 @@ See [Admin-API](Admin-API.md)
* Params:
* `email`: email of that needs to be verified
* Authentication: not required
* Response: 204 No Content
* Response: 204 No Content

## `/api/v1/pleroma/mascot`
### Gets user mascot image
@@ -321,6 +321,15 @@ See [Admin-API](Admin-API.md)
}
```

## `/api/pleroma/change_email`
### Change account email
* Method `POST`
* Authentication: required
* Params:
* `password`: user's password
* `email`: new email
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise

# Pleroma Conversations

Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:


+ 9
- 0
lib/pleroma/user.ex View File

@@ -1624,4 +1624,13 @@ defmodule Pleroma.User do
def is_internal_user?(%User{nickname: nil}), do: true
def is_internal_user?(%User{local: true, nickname: "internal." <> _}), do: true
def is_internal_user?(_), do: false

def change_email(user, email) do
user
|> cast(%{email: email}, [:email])
|> validate_required([:email])
|> unique_constraint(:email)
|> validate_format(:email, @email_regex)
|> update_and_set_cache()
end
end

+ 1
- 0
lib/pleroma/web/router.ex View File

@@ -224,6 +224,7 @@ defmodule Pleroma.Web.Router do
scope [] do
pipe_through(:oauth_write)

post("/change_email", UtilController, :change_email)
post("/change_password", UtilController, :change_password)
post("/delete_account", UtilController, :delete_account)
put("/notification_settings", UtilController, :update_notificaton_settings)


+ 19
- 0
lib/pleroma/web/twitter_api/controllers/util_controller.ex View File

@@ -314,6 +314,25 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end

def change_email(%{assigns: %{user: user}} = conn, params) do
case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
{:ok, user} ->
with {:ok, _user} <- User.change_email(user, params["email"]) do
json(conn, %{status: "success"})
else
{:error, changeset} ->
{_, {error, _}} = Enum.at(changeset.errors, 0)
json(conn, %{error: "Email #{error}."})

_ ->
json(conn, %{error: "Unable to change email."})
end

{:error, msg} ->
json(conn, %{error: msg})
end
end

def delete_account(%{assigns: %{user: user}} = conn, params) do
case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
{:ok, user} ->


+ 27
- 0
test/user_test.exs View File

@@ -1614,4 +1614,31 @@ defmodule Pleroma.UserTest do
assert User.user_info(other_user).following_count == 152
end
end

describe "change_email/2" do
setup do
[user: insert(:user)]
end

test "blank email returns error", %{user: user} do
assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
end

test "non unique email returns error", %{user: user} do
%{email: email} = insert(:user)

assert {:error, %{errors: [email: {"has already been taken", _}]}} =
User.change_email(user, email)
end

test "invalid email returns error", %{user: user} do
assert {:error, %{errors: [email: {"has invalid format", _}]}} =
User.change_email(user, "cofe")
end

test "changes email", %{user: user} do
assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
end
end
end

+ 107
- 0
test/web/twitter_api/util_controller_test.exs View File

@@ -662,4 +662,111 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
assert called(Pleroma.Captcha.new())
end
end

defp with_credentials(conn, username, password) do
header_content = "Basic " <> Base.encode64("#{username}:#{password}")
put_req_header(conn, "authorization", header_content)
end

defp valid_user(_context) do
user = insert(:user)
[user: user]
end

describe "POST /api/pleroma/change_email" do
setup [:valid_user]

test "without credentials", %{conn: conn} do
conn = post(conn, "/api/pleroma/change_email")
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end

test "with credentials and invalid password", %{conn: conn, user: current_user} do
conn =
conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/pleroma/change_email", %{
"password" => "hi",
"email" => "test@test.com"
})

assert json_response(conn, 200) == %{"error" => "Invalid password."}
end

test "with credentials, valid password and invalid email", %{
conn: conn,
user: current_user
} do
conn =
conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/pleroma/change_email", %{
"password" => "test",
"email" => "foobar"
})

assert json_response(conn, 200) == %{"error" => "Email has invalid format."}
end

test "with credentials, valid password and no email", %{
conn: conn,
user: current_user
} do
conn =
conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/pleroma/change_email", %{
"password" => "test"
})

assert json_response(conn, 200) == %{"error" => "Email can't be blank."}
end

test "with credentials, valid password and blank email", %{
conn: conn,
user: current_user
} do
conn =
conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/pleroma/change_email", %{
"password" => "test",
"email" => ""
})

assert json_response(conn, 200) == %{"error" => "Email can't be blank."}
end

test "with credentials, valid password and non unique email", %{
conn: conn,
user: current_user
} do
user = insert(:user)

conn =
conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/pleroma/change_email", %{
"password" => "test",
"email" => user.email
})

assert json_response(conn, 200) == %{"error" => "Email has already been taken."}
end

test "with credentials, valid password and valid email", %{
conn: conn,
user: current_user
} do
conn =
conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/pleroma/change_email", %{
"password" => "test",
"email" => "cofe@foobar.com"
})

assert json_response(conn, 200) == %{"status" => "success"}
end
end
end

Loading…
Cancel
Save