-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from daveminer/settings-role
Settings role
- Loading branch information
Showing
13 changed files
with
370 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
defmodule Basket.ClubMember do | ||
@moduledoc false | ||
|
||
use Ecto.Schema | ||
import Ecto.Changeset | ||
|
||
alias Basket.{Club, User} | ||
|
||
schema "club_members" do | ||
belongs_to :user, User | ||
belongs_to :club, Club | ||
end | ||
|
||
@doc false | ||
def changeset(club_member, attrs) do | ||
club_member | ||
|> cast(attrs, [:user_id, :club_id]) | ||
|> validate_required([:user_id, :club_id]) | ||
|> foreign_key_constraint(:user_id) | ||
|> foreign_key_constraint(:club_id) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
defmodule Basket.ClubOfficer do | ||
@moduledoc false | ||
|
||
use Ecto.Schema | ||
import Ecto.Changeset | ||
|
||
alias Basket.{Club, User} | ||
|
||
schema "club_officers" do | ||
belongs_to :user, User | ||
belongs_to :club, Club | ||
end | ||
|
||
@doc false | ||
def changeset(club_member, attrs) do | ||
club_member | ||
|> cast(attrs, [:user_id, :club_id]) | ||
|> validate_required([:user_id, :club_id]) | ||
|> foreign_key_constraint(:user_id) | ||
|> foreign_key_constraint(:club_id) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 44 additions & 45 deletions
89
lib/basket_web/controllers/pow/session_html/new.html.heex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,56 @@ | ||
<div class="mx-auto max-w-sm"> | ||
<div class="w-screen h-screen"> | ||
<.header class="text-center mb-3"> | ||
Welcome to Basket! | ||
</.header> | ||
|
||
<img src={~p"/images/stock_basket.webp"} width="216" class="mx-auto block" /> | ||
|
||
<.simple_form :let={f} for={@changeset} as={:user} action={@action} phx-update="ignore"> | ||
<.error :if={@changeset.action}> | ||
Oops, something went wrong! Please check the errors below. | ||
</.error> | ||
<.input | ||
field={f[Pow.Ecto.Schema.user_id_field(@changeset)]} | ||
type={(Pow.Ecto.Schema.user_id_field(@changeset) == :email && "email") || "text"} | ||
label={Phoenix.Naming.humanize(Pow.Ecto.Schema.user_id_field(@changeset))} | ||
required | ||
/> | ||
<.input field={f[:password]} type="password" label="Password" value={nil} required /> | ||
|
||
<:actions | ||
:let={f} | ||
:if={ | ||
Pow.Plug.extension_enabled?(@conn, PowPersistentSession) || | ||
Pow.Plug.extension_enabled?(@conn, PowResetPassword) | ||
} | ||
> | ||
<div class="mx-auto w-1/2"> | ||
<.simple_form :let={f} for={@changeset} as={:user} action={@action} phx-update="ignore"> | ||
<.error :if={@changeset.action}> | ||
Oops, something went wrong! Please check the errors below. | ||
</.error> | ||
<.input | ||
:if={Pow.Plug.extension_enabled?(@conn, PowPersistentSession)} | ||
field={f[:persistent_session]} | ||
type="checkbox" | ||
label="Keep me logged in" | ||
field={f[Pow.Ecto.Schema.user_id_field(@changeset)]} | ||
type={(Pow.Ecto.Schema.user_id_field(@changeset) == :email && "email") || "text"} | ||
label={Phoenix.Naming.humanize(Pow.Ecto.Schema.user_id_field(@changeset))} | ||
required | ||
/> | ||
<.link | ||
:if={Pow.Plug.extension_enabled?(@conn, PowResetPassword)} | ||
href={ | ||
Pow.Phoenix.Routes.path_for( | ||
@conn, | ||
PowResetPassword.Phoenix.ResetPasswordController, | ||
:new | ||
) | ||
<.input field={f[:password]} type="password" label="Password" value={nil} required /> | ||
|
||
<:actions | ||
:let={f} | ||
:if={ | ||
Pow.Plug.extension_enabled?(@conn, PowPersistentSession) || | ||
Pow.Plug.extension_enabled?(@conn, PowResetPassword) | ||
} | ||
class="text-sm font-semibold" | ||
> | ||
Forgot your password? | ||
</.link> | ||
</:actions> | ||
<.input | ||
:if={Pow.Plug.extension_enabled?(@conn, PowPersistentSession)} | ||
field={f[:persistent_session]} | ||
type="checkbox" | ||
label="Keep me logged in" | ||
/> | ||
<.link | ||
:if={Pow.Plug.extension_enabled?(@conn, PowResetPassword)} | ||
href={ | ||
Pow.Phoenix.Routes.path_for( | ||
@conn, | ||
PowResetPassword.Phoenix.ResetPasswordController, | ||
:new | ||
) | ||
} | ||
class="text-sm font-semibold" | ||
> | ||
Forgot your password? | ||
</.link> | ||
</:actions> | ||
|
||
<:actions> | ||
<.button | ||
phx-disable-with="Signing in..." | ||
class="w-full text-black bg-gray-300 hover:bg-gray-400" | ||
> | ||
Sign in <span aria-hidden="true">→</span> | ||
</.button> | ||
</:actions> | ||
</.simple_form> | ||
<:actions> | ||
<.button phx-disable-with="Signing in..." class="w-full"> | ||
Sign in <span aria-hidden="true">→</span> | ||
</.button> | ||
</:actions> | ||
</.simple_form> | ||
</div> | ||
</div> |
82 changes: 82 additions & 0 deletions
82
lib/basket_web/controllers/pow_invitation/invitation_controller.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
defmodule BasketWeb.PowInvitation.InvitationController do | ||
use BasketWeb, :controller | ||
|
||
import Phoenix.VerifiedRoutes | ||
|
||
alias Basket.Repo | ||
alias Pow.{Config, Plug} | ||
|
||
plug :load_user when action in [:create] | ||
|
||
@doc """ | ||
This custom PowInvitation controller allows for a custom redirect after invitation and | ||
creation of a club membership for the new user, based on the inviting user's office. | ||
This controller assumes the inviting user only has one office. | ||
""" | ||
def create(%{assigns: %{current_user: invited_by}} = conn, %{"user" => user_params}) do | ||
case create_user(conn, user_params) do | ||
{:ok, user, conn} -> | ||
url = path(conn, BasketWeb.Router, ~p"/invitations/#{user.invitation_token}/edit") | ||
email = PowInvitation.Phoenix.Mailer.invitation(conn, user, invited_by, url) | ||
Pow.Phoenix.Mailer.deliver(conn, email) | ||
|
||
conn | ||
|> put_flash(:info, "Invitation sent successfully.") | ||
|> redirect(to: path(conn, BasketWeb.Router, ~p"/settings")) | ||
|
||
{:error, changeset, conn} -> | ||
error_message = format_changeset_errors(changeset) | ||
|
||
conn | ||
|> put_flash(:error, error_message) | ||
|> redirect(to: path(conn, BasketWeb.Router, ~p"/settings")) | ||
end | ||
end | ||
|
||
defp create_user(conn, user_params) do | ||
config = Plug.fetch_config(conn) | ||
|
||
user = | ||
conn | ||
|> Plug.current_user() | ||
|> Repo.preload(:offices) | ||
|
||
user_mod = Config.user!(config) | ||
|
||
user_params = | ||
Map.put(user_params, :email, user_params["email"]) | ||
|> Map.delete("email") | ||
|
||
user_mod | ||
|> struct() | ||
|> user_mod.invite_changeset(user, user_params) | ||
|> Ecto.Changeset.put_assoc(:clubs, [hd(user.offices)]) | ||
|> Repo.insert() | ||
|> case do | ||
{:ok, user} -> {:ok, user, conn} | ||
{:error, changeset} -> {:error, changeset, conn} | ||
end | ||
end | ||
|
||
defp format_changeset_errors(changeset) do | ||
Enum.map_join(changeset.errors, ", ", fn | ||
{:email, {"has already been taken", _}} -> | ||
"That email address has already been invited." | ||
|
||
{field, {message, _}} -> | ||
"#{humanize(field)} #{message}" | ||
end) | ||
end | ||
|
||
defp humanize(field) do | ||
field | ||
|> to_string() | ||
|> String.replace("_", " ") | ||
|> String.capitalize() | ||
end | ||
|
||
defp load_user(conn, _opts) do | ||
user = Pow.Plug.current_user(conn) | ||
assign(conn, :current_user, user) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.