logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma
commit: 6af164f27b5a285fb1b1c8790a86db061c8fc28a
parent: a17b2613795b24162e953dd457b411dddc0c902e
Author: Roger Braun <rbraun@Bobble.local>
Date:   Thu, 19 Oct 2017 17:37:24 +0200

Add password reset.

Diffstat:

Alib/pleroma/PasswordResetToken.ex44++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/user.ex19+++++++++++++++++++
Mlib/pleroma/web/router.ex10++++++++++
Alib/pleroma/web/templates/twitter_api/util/invalid_token.html.eex1+
Alib/pleroma/web/templates/twitter_api/util/password_reset.html.eex12++++++++++++
Alib/pleroma/web/templates/twitter_api/util/password_reset_failed.html.eex1+
Alib/pleroma/web/templates/twitter_api/util/password_reset_success.html.eex1+
Mlib/pleroma/web/twitter_api/controllers/util_controller.ex22++++++++++++++++++++++
Alib/pleroma/web/twitter_api/views/util_view.ex4++++
Apriv/repo/migrations/20171019141706_create_password_reset_tokens.exs13+++++++++++++
10 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/lib/pleroma/PasswordResetToken.ex b/lib/pleroma/PasswordResetToken.ex @@ -0,0 +1,44 @@ +defmodule Pleroma.PasswordResetToken do + use Ecto.Schema + + import Ecto.{Changeset, Query} + + alias Pleroma.{User, PasswordResetToken, Repo} + + schema "password_reset_tokens" do + belongs_to :user, User + field :token, :string + field :used, :boolean, default: false + + timestamps() + end + + def create_token(%User{} = user) do + token = :crypto.strong_rand_bytes(32) |> Base.url_encode64 + + token = %PasswordResetToken{ + user_id: user.id, + used: false, + token: token + } + + Repo.insert(token) + end + + def used_changeset(struct) do + changeset = struct + |> cast(%{}, []) + |> put_change(:used, true) + end + + def reset_password(token, data) do + with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}), + %User{} = user <- Repo.get(User, token.user_id), + {:ok, user} <- User.reset_password(user, data), + {:ok, token} <- Repo.update(used_changeset(token)) do + {:ok, token} + else + _e -> {:error, token} + end + end +end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex @@ -97,6 +97,25 @@ defmodule Pleroma.User do |> validate_length(:name, min: 1, max: 100) end + def password_update_changeset(struct, params) do + changeset = struct + |> cast(params, [:password, :password_confirmation]) + |> validate_required([:password, :password_confirmation]) + |> validate_confirmation(:password) + + if changeset.valid? do + hashed = Pbkdf2.hashpwsalt(changeset.changes[:password]) + changeset + |> put_change(:password_hash, hashed) + else + changeset + end + end + + def reset_password(user, data) do + Repo.update(password_update_changeset(user, data)) + end + def register_changeset(struct, params \\ %{}) do changeset = struct |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex @@ -33,6 +33,16 @@ defmodule Pleroma.Web.Router do plug :accepts, ["html", "json"] end + pipeline :password_reset do + plug :accepts, ["html"] + end + + scope "/api/pleroma", Pleroma.Web.TwitterAPI do + pipe_through :password_reset + get "/password_reset/:token", UtilController, :show_password_reset + post "/password_reset", UtilController, :password_reset + end + scope "/oauth", Pleroma.Web.OAuth do get "/authorize", OAuthController, :authorize post "/authorize", OAuthController, :create_authorization diff --git a/lib/pleroma/web/templates/twitter_api/util/invalid_token.html.eex b/lib/pleroma/web/templates/twitter_api/util/invalid_token.html.eex @@ -0,0 +1 @@ +<h2>Invalid Token</h2> diff --git a/lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex b/lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex @@ -0,0 +1,12 @@ +<h2>Password Reset for <%= @user.nickname %></h2> +<%= form_for @conn, util_path(@conn, :password_reset), [as: "data"], fn f -> %> +<%= label f, :password, "Password" %> +<%= password_input f, :password %> +<br> + +<%= label f, :password_confirmation, "Confirmation" %> +<%= password_input f, :password_confirmation %> +<br> +<%= hidden_input f, :token, value: @token.token %> +<%= submit "Reset" %> +<% end %> diff --git a/lib/pleroma/web/templates/twitter_api/util/password_reset_failed.html.eex b/lib/pleroma/web/templates/twitter_api/util/password_reset_failed.html.eex @@ -0,0 +1 @@ +<h2>Password reset failed</h2> diff --git a/lib/pleroma/web/templates/twitter_api/util/password_reset_success.html.eex b/lib/pleroma/web/templates/twitter_api/util/password_reset_success.html.eex @@ -0,0 +1 @@ +<h2>Password changed!</h2> diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -2,6 +2,28 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do use Pleroma.Web, :controller alias Pleroma.Web + alias Pleroma.{Repo, PasswordResetToken, User} + + def show_password_reset(conn, %{"token" => token}) do + with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}), + %User{} = user <- Repo.get(User, token.user_id) do + render conn, "password_reset.html", %{ + token: token, + user: user + } + else + _e -> render conn, "invalid_token.html" + end + end + + def password_reset(conn, %{"data" => data}) do + with {:ok, _} <- PasswordResetToken.reset_password(data["token"], data) do + render conn, "password_reset_success.html" + else + _e -> render conn, "password_reset_failed.html" + end + end + def help_test(conn, _params) do json(conn, "ok") end diff --git a/lib/pleroma/web/twitter_api/views/util_view.ex b/lib/pleroma/web/twitter_api/views/util_view.ex @@ -0,0 +1,4 @@ +defmodule Pleroma.Web.TwitterAPI.UtilView do + use Pleroma.Web, :view + import Phoenix.HTML.Form +end diff --git a/priv/repo/migrations/20171019141706_create_password_reset_tokens.exs b/priv/repo/migrations/20171019141706_create_password_reset_tokens.exs @@ -0,0 +1,13 @@ +defmodule Pleroma.Repo.Migrations.CreatePasswordResetTokens do + use Ecto.Migration + + def change do + create table(:password_reset_tokens) do + add :token, :string + add :user_id, references(:users) + add :used, :boolean, default: false + + timestamps() + end + end +end