diff --git a/friends/lib/friends/accounts/user.ex b/friends/lib/friends/accounts/user.ex index 9f85586..db2af5a 100644 --- a/friends/lib/friends/accounts/user.ex +++ b/friends/lib/friends/accounts/user.ex @@ -2,6 +2,8 @@ defmodule Friends.Accounts.User do use Ecto.Schema import Ecto.Changeset + @repo Friends.Repo + schema "users" do field :email, :string field :password, :string, virtual: true, redact: true @@ -13,6 +15,15 @@ defmodule Friends.Accounts.User do has_one :profile, Friends.Friend end + def load_profile(%Friends.Accounts.User{profile: %Ecto.Association.NotLoaded{}} = model) do + model + |> @repo.preload(:profile) + end + + def load_profile(nil) do + %{profile: nil} + end + @doc """ A user changeset for registration. diff --git a/friends/lib/friends/friend.ex b/friends/lib/friends/friend.ex index d2b4f48..27a26f8 100644 --- a/friends/lib/friends/friend.ex +++ b/friends/lib/friends/friend.ex @@ -35,20 +35,26 @@ defmodule Friends.Friend do def changeset(friend, params \\ %{}) do friend - |> Ecto.Changeset.cast(params, [:name, :born, :nickname, :email, :phone, :slug]) + |> Ecto.Changeset.cast(params, [:name, :born, :nickname, :email, :phone, :slug, :user_id]) |> Ecto.Changeset.validate_required([:name, :email, :phone, :born]) |> Ecto.Changeset.validate_format(:name, ~r/\w+\ \w+/) - |> Ecto.Changeset.validate_format(:email, Regex.compile!("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")) - |> Ecto.Changeset.validate_format(:phone, Regex.compile!("^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$")) + |> Ecto.Changeset.validate_format( + :email, + Regex.compile!("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$") + ) + |> Ecto.Changeset.validate_format( + :phone, + Regex.compile!("^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$") + ) |> Ecto.Changeset.unique_constraint(:name) + |> Ecto.Changeset.unique_constraint(:email) end def all() do - preloads = [:relationships, :reverse_relationships] + preloads = [:relationships, :reverse_relationships, :user] @repo.all(from(f in Friends.Friend, preload: ^preloads)) end - def new(params \\ %{}) do %Friend{id: "new"} |> struct(params) @@ -62,6 +68,7 @@ defmodule Friends.Friend do ) ) end + def get_by_id(id) do @repo.one( from(f in Friend, @@ -71,49 +78,61 @@ defmodule Friends.Friend do ) end + def get_by_email(email) do + @repo.one( + from(f in Friend, + where: f.email == ^email, + preload: [:relationships, :reverse_relationships] + ) + ) + end + def create_or_update(params) do case params.id do "new" -> - %Friend{} |> Friend.changeset(%{params | id: nil}) - |> Map.put(:action, :insert) - |> @repo.insert! - _number -> - Friend.get_by_id(params.id |> String.to_integer) - |> Friend.changeset(params) - |> Map.put(:action, :update) - |> @repo.update! + %Friend{} + |> Friend.changeset(%{params | id: nil}) + |> Map.put(:action, :insert) + |> @repo.insert! + + _number -> + Friend.get_by_id(params.id |> String.to_integer()) + |> Friend.changeset(params) + |> Map.put(:action, :update) + |> @repo.update! end end def get_relationships(friend) do friend - |> relations - |> Enum.map(&(relation(friend, &1))) + |> relations + |> Enum.map(&relation(friend, &1)) end def get_events(friend) do friend - |> get_relationships - |> Enum.map(&(&1.events)) - |> List.flatten + |> get_relationships + |> Enum.map(& &1.events) + |> List.flatten() end def age(friend) do # Age in years - Date.diff(Date.utc_today,friend.born) |> div(365) + Date.diff(Date.utc_today(), friend.born) |> div(365) end # TODO: Refactor def create_birth_event(friend) do - if is_nil @repo.all( - from(e in Friends.Event, - where: e.name == "born" - )) |> List.flatten do + if is_nil( + @repo.all( + from(e in Friends.Event, + where: e.name == "born" + ) + ) + |> List.flatten() + ) do else "find" end end - - - end diff --git a/friends/lib/friends_web/controllers/page_controller.ex b/friends/lib/friends_web/controllers/page_controller.ex index 7401d19..be9f39e 100644 --- a/friends/lib/friends_web/controllers/page_controller.ex +++ b/friends/lib/friends_web/controllers/page_controller.ex @@ -1,16 +1,63 @@ defmodule FriendsWeb.PageController do use FriendsWeb, :controller - alias Friends.{Friend, Relationship} - import Helpers + alias Friends.{Friend, Repo, Accounts.User} + + import Helpers.Names + + plug :assign_profile def index(conn, _params) do - - new_friend = Friend.new |> Friend.changeset + new_friend = Friend.new() |> Friend.changeset() conn |> assign(:new_friend, new_friend) - |> assign(:all_friends, Friend.all) - |> assign(:users, Friends.Accounts.User |> Friends.Repo.all) + |> assign(:all_friends, Friend.all()) + |> assign(:users, User |> Repo.all()) |> render("index.html") end + + defp assign_profile(conn, _opts) do + current_user = conn.assigns.current_user + + case current_user do + nil -> + # No logged in user, and no profile + conn + + user -> + case user.profile do + nil -> + # Logged in user, but no profile + # Is there a profile with the same email? + try_profile = user.email |> Friends.Friend.get_by_email() + + case try_profile do + nil -> + # If not, we need to make a new profile + conn + |> redirect(to: Routes.profile_form_path(conn, :new)) + + # If so, link 'em and be done with it + friend -> + friend + |> Friends.Friend.changeset(%{ + user_id: user.id + }) + |> Friends.Repo.update!() + + conn + |> put_flash( + :info, + "Welcome to the app, #{friend |> first_name()}!" + ) + |> redirect(to: Routes.friend_path(conn, :index)) + end + + _profile -> + # Logged in user, and linked profile + conn + |> redirect(to: Routes.friend_path(conn, :index)) + end + end + end end diff --git a/friends/lib/friends_web/controllers/user_auth.ex b/friends/lib/friends_web/controllers/user_auth.ex index 30eb900..742a75c 100644 --- a/friends/lib/friends_web/controllers/user_auth.ex +++ b/friends/lib/friends_web/controllers/user_auth.ex @@ -91,7 +91,13 @@ defmodule FriendsWeb.UserAuth do def fetch_current_user(conn, _opts) do {user_token, conn} = ensure_user_token(conn) user = user_token && Accounts.get_user_by_session_token(user_token) - assign(conn, :current_user, user) + + assign( + conn, + :current_user, + user + |> Friends.Repo.preload(:profile) + ) end defp ensure_user_token(conn) do diff --git a/friends/lib/friends_web/controllers/user_profile_controller.ex b/friends/lib/friends_web/controllers/user_profile_controller.ex new file mode 100644 index 0000000..9bd9695 --- /dev/null +++ b/friends/lib/friends_web/controllers/user_profile_controller.ex @@ -0,0 +1,32 @@ +defmodule FriendsWeb.UserProfileController do + use FriendsWeb, :controller + + alias Friends.Accounts + alias FriendsWeb.Router.Helpers, as: Routes + + plug :assign_profile + + + + @doc """ + Checks if the user has linked a profile yet, + and redirects to the profile creation flow + if not. + """ + def main(conn) do + conn + |> put_flash(:info, "test") + end + + defp assign_profile(conn, _opts) do + user = conn.assigns.current_user + + msg = case user.profile do + nil -> "No profile!" + profile -> "Yes profile! #{profile.name}" + end + + conn + |> put_flash(:info, msg) + end +end diff --git a/friends/lib/friends_web/router.ex b/friends/lib/friends_web/router.ex index 5727e62..ef62b00 100644 --- a/friends/lib/friends_web/router.ex +++ b/friends/lib/friends_web/router.ex @@ -23,8 +23,8 @@ defmodule FriendsWeb.Router do get "/", PageController, :index get "/friends", FriendController, :index - live "/friend/:slug", FriendsLive.Show - + live "/friend/:slug", FriendLive.Show + live "/friend/:slug/edit", FriendLive.Edit end # Other scopes may use custom stacks. @@ -65,6 +65,7 @@ defmodule FriendsWeb.Router do scope "/", FriendsWeb do pipe_through [:browser, :redirect_if_user_is_authenticated] + # Requires the user NOT be authenticated: get "/users/register", UserRegistrationController, :new post "/users/register", UserRegistrationController, :create @@ -78,6 +79,9 @@ defmodule FriendsWeb.Router do scope "/", FriendsWeb do pipe_through [:browser, :require_authenticated_user] + # Requires the user DO be authenticated: + + live "/profile/new", ProfileLive.Form, :new get "/users/settings", UserSettingsController, :edit put "/users/settings", UserSettingsController, :update diff --git a/friends/lib/friends_web/templates/layout/live.html.heex b/friends/lib/friends_web/templates/layout/live.html.heex index 9bb672b..432ac4a 100644 --- a/friends/lib/friends_web/templates/layout/live.html.heex +++ b/friends/lib/friends_web/templates/layout/live.html.heex @@ -3,27 +3,8 @@
You have made a user account, but we don't yet have a profile for you.
+ +