Skip to content

Commit

Permalink
[FEATURE] [MER 3007] Allow admin to generate reset password link for …
Browse files Browse the repository at this point in the history
…student

Mer 3007 generate reset password link
  • Loading branch information
darrensiegel committed Apr 10, 2024
2 parents 9fc122d + dbeecb6 commit a20b503
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
39 changes: 37 additions & 2 deletions lib/oli_web/controllers/pow.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
defmodule OliWeb.PowController do
use OliWeb, :controller

alias Oli.Repo
alias Oli.Accounts.User
alias Oli.Accounts.Author
alias Oli.Accounts.User
alias Pow.Phoenix.Controller
alias Pow.Phoenix.Routes, as: PowRoutes
alias PowResetPassword.Phoenix.ResetPasswordController
alias Oli.Repo

@secret_key_base Application.compile_env(:oli, OliWeb.Endpoint)[:secret_key_base]
@basic_conn_for_pow %Plug.Conn{
private: %{phoenix_router: OliWeb.Router, phoenix_endpoint: OliWeb.Endpoint, otp_app: :oli},
secret_key_base: @secret_key_base
}

@ttl :timer.minutes(24 * 60)
@cache_config {PowResetPassword.Store.ResetTokenCache, ttl: @ttl}

def create_user_password_reset_link(%{"id" => id}) do
%{email: email} = _user = Repo.get(User, id)
params = %{"user" => %{"email" => email}}

@basic_conn_for_pow
|> use_pow_config(:user)
|> put_reset_password_token_store_into_pow_config()
|> ResetPasswordController.process_create(params)
|> generate_password_reset_url()
end

def send_user_password_reset_link(conn, %{"id" => id}) do
user = Repo.get(User, id)
Expand Down Expand Up @@ -66,6 +89,18 @@ defmodule OliWeb.PowController do
|> redirect(to: Routes.live_path(conn, OliWeb.Users.AuthorsDetailView, author.id))
end

defp generate_password_reset_url({:ok, %{token: token, user: _user}, conn}) do
Controller.routes(conn, PowRoutes).url_for(conn, ResetPasswordController, :edit, [token])
end

defp put_reset_password_token_store_into_pow_config(conn) do
update_in(
conn,
[Access.key(:private), Access.key(:pow_config)],
&Keyword.put(&1, :reset_password_token_store, @cache_config)
)
end

defp resend_user_confirmation_email(conn, user) do
PowEmailConfirmation.Phoenix.ControllerCallbacks.send_confirmation_email(user, conn)
conn
Expand Down
36 changes: 36 additions & 0 deletions lib/oli_web/live/users/user_actions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule OliWeb.Users.Actions do
attr(:for_author, :boolean, default: false)
attr(:user, :any, required: true)
attr(:csrf_token, :any, required: true)
attr(:password_reset_link, :string, default: "")

def render(assigns) do
{resend, reset} =
Expand All @@ -26,6 +27,41 @@ defmodule OliWeb.Users.Actions do

~H"""
<div>
<div class="form-group">
<label for="reset_link_input">Generate Reset Password Link</label>
<div class="input-group" style="max-width: 100%;">
<input
readonly
type="text"
id="password-reset-link-1"
class="form-control"
aria-label="Password Reset Link Text Input"
value={@password_reset_link}
/>
<div class="input-group-append">
<button
id="copy-password-reset-link-button"
class="btn btn-outline-secondary"
data-clipboard-target="#password-reset-link-1"
phx-hook="CopyListener"
>
<i class="far fa-clipboard"></i> Copy
</button>
</div>
</div>
<p :if={@password_reset_link not in [nil, ""]} class="mb-1">
This link will expired in 24 hours.
</p>
<button
phx-click="generate_reset_password_link"
phx-value-id={@user.id}
class="btn btn-md btn-primary"
>
Generate
</button>
</div>
<form
id={"resend-confirmation-#{@user.id}"}
method="post"
Expand Down
15 changes: 13 additions & 2 deletions lib/oli_web/live/users/user_detail_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ defmodule OliWeb.Users.UsersDetailView do
user_lti_params: LtiParams.all_user_lti_params(user.id),
enrolled_sections: enrolled_sections,
disabled_edit: true,
user_name: user.name
user_name: user.name,
password_reset_link: ""
)}
end
end
Expand Down Expand Up @@ -205,7 +206,11 @@ defmodule OliWeb.Users.UsersDetailView do
</Group.render>
<Group.render label="Actions" description="Actions that can be taken for this user">
<%= if @user.independent_learner do %>
<Actions.render user={@user} csrf_token={@csrf_token} />
<Actions.render
user={@user}
csrf_token={@csrf_token}
password_reset_link={@password_reset_link}
/>
<% else %>
<div>No actions available</div>
<div class="text-secondary">LTI users are managed by their LMS</div>
Expand All @@ -225,6 +230,12 @@ defmodule OliWeb.Users.UsersDetailView do
{:noreply, socket}
end

def handle_event("generate_reset_password_link", params, socket) do
password_reset_link = OliWeb.PowController.create_user_password_reset_link(params)
socket = assign(socket, password_reset_link: password_reset_link)
{:noreply, socket}
end

def handle_event("show_confirm_email_modal", _, socket) do
modal_assigns = %{
user: socket.assigns.user
Expand Down

0 comments on commit a20b503

Please sign in to comment.