Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restricting access #7

Merged
merged 8 commits into from Feb 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 0 additions & 9 deletions lib/prater/auth/auth.ex
Expand Up @@ -2,15 +2,6 @@ defmodule Prater.Auth do
alias Prater.Repo
alias Prater.Auth.User

def current_user(conn) do
user_id = Plug.Conn.get_session(conn, :current_user_id)
if user_id, do: Repo.get(User, user_id)
end

def user_signed_in?(conn) do
!!current_user(conn)
end

def sign_in(email, password) do
user = Repo.get_by(User, email: email)

Expand Down
5 changes: 5 additions & 0 deletions lib/prater/auth/authorizer.ex
@@ -0,0 +1,5 @@
defmodule Prater.Auth.Authorizer do
def can_manage?(user, room) do
user && user.id == room.user_id
end
end
1 change: 1 addition & 0 deletions lib/prater/auth/user.ex
Expand Up @@ -10,6 +10,7 @@ defmodule Prater.Auth.User do
field :username, :string
field :password, :string, virtual: true
field :password_confirmation, :string, virtual: true
has_many :rooms, Prater.Conversation.Room

timestamps()
end
Expand Down
5 changes: 3 additions & 2 deletions lib/prater/conversation/conversation.ex
Expand Up @@ -8,8 +8,9 @@ defmodule Prater.Conversation do

def get_room!(id), do: Repo.get!(Room, id)

def create_room(attrs \\ %{}) do
%Room{}
def create_room(user, attrs \\ %{}) do
user
|> Ecto.build_assoc(:rooms)
|> Room.changeset(attrs)
|> Repo.insert()
end
Expand Down
1 change: 1 addition & 0 deletions lib/prater/conversation/room.ex
Expand Up @@ -8,6 +8,7 @@ defmodule Prater.Conversation.Room do
field :description, :string
field :name, :string
field :topic, :string
belongs_to :user, Prater.Auth.User

timestamps()
end
Expand Down
20 changes: 19 additions & 1 deletion lib/prater_web/controllers/room_controller.ex
Expand Up @@ -3,6 +3,10 @@ defmodule PraterWeb.RoomController do

alias Prater.Conversation
alias Prater.Conversation.Room
alias Prater.Auth.Authorizer

plug PraterWeb.Plugs.AuthenticateUser when action not in [:index]
plug :authorize_user when action in [:edit, :update, :delete]

def index(conn, _params) do
rooms = Conversation.list_rooms()
Expand All @@ -15,7 +19,7 @@ defmodule PraterWeb.RoomController do
end

def create(conn, %{"room" => room_params}) do
case Conversation.create_room(room_params) do
case Conversation.create_room(conn.assigns.current_user, room_params) do
{:ok, room} ->
conn
|> put_flash(:info, "Room created successfully.")
Expand Down Expand Up @@ -58,4 +62,18 @@ defmodule PraterWeb.RoomController do
|> put_flash(:info, "Room deleted successfully.")
|> redirect(to: room_path(conn, :index))
end

defp authorize_user(conn, _params) do
%{params: %{"id" => room_id}} = conn
room = Conversation.get_room!(room_id)

if Authorizer.can_manage?(conn.assigns.current_user, room) do
conn
else
conn
|> put_flash(:error, "You are not authorized to access that page")
|> redirect(to: room_path(conn, :index))
|> halt()
end
end
end
20 changes: 20 additions & 0 deletions lib/prater_web/plugs/authenticate_user.ex
@@ -0,0 +1,20 @@
defmodule PraterWeb.Plugs.AuthenticateUser do
import Plug.Conn
import Phoenix.Controller

alias PraterWeb.Router.Helpers

def init(_params) do
end

def call(conn, _params) do
if conn.assigns.user_signed_in? do
conn
else
conn
|> put_flash(:error, "You need to sign in or sign up before continuing.")
|> redirect(to: Helpers.session_path(conn, :new))
|> halt()
end
end
end
24 changes: 24 additions & 0 deletions lib/prater_web/plugs/set_current_user.ex
@@ -0,0 +1,24 @@
defmodule PraterWeb.Plugs.SetCurrentUser do
import Plug.Conn

alias Prater.Repo
alias Prater.Auth.User

def init(_params) do
end

def call(conn, _params) do
user_id = Plug.Conn.get_session(conn, :current_user_id)

cond do
current_user = user_id && Repo.get(User, user_id) ->
conn
|> assign(:current_user, current_user)
|> assign(:user_signed_in?, true)
true ->
conn
|> assign(:current_user, nil)
|> assign(:user_signed_in?, false)
end
end
end
1 change: 1 addition & 0 deletions lib/prater_web/router.ex
Expand Up @@ -7,6 +7,7 @@ defmodule PraterWeb.Router do
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug PraterWeb.Plugs.SetCurrentUser
end

pipeline :api do
Expand Down
4 changes: 2 additions & 2 deletions lib/prater_web/templates/layout/app.html.eex
Expand Up @@ -17,9 +17,9 @@
<h5 class="my-0 mr-md-auto font-weight-normal">
<a href="/" class="navbar-brand text-dark"><strong>Prater</strong></a>
</h5>
<%= if Prater.Auth.user_signed_in?(@conn) do %>
<%= if @user_signed_in? do %>
<nav class="my-2 my-md-0 mr-md-3">
Signed in as: <strong><%= Prater.Auth.current_user(@conn).username %></strong>
Signed in as: <strong><%= @current_user.username %></strong>
</nav>
<%= link "Sign Out", to: session_path(@conn, :delete), method: :delete, class: "btn btn-outline-primary" %>
<% else %>
Expand Down
10 changes: 6 additions & 4 deletions lib/prater_web/templates/room/show.html.eex
@@ -1,8 +1,10 @@
<h2><%= @room.name %></h2>

<div>
<%= link "Edit", to: room_path(@conn, :edit, @room.id), class: "btn btn-default" %>
<%= link "Delete", to: room_path(@conn, :delete, @room), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger" %>
</div>
<%= if Prater.Auth.Authorizer.can_manage?(@current_user, @room) do %>
<div>
<%= link "Edit", to: room_path(@conn, :edit, @room.id), class: "btn btn-default" %>
<%= link "Delete", to: room_path(@conn, :delete, @room), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger" %>
</div>
<% end %>

<div><%= @room.description %></div>
9 changes: 9 additions & 0 deletions priv/repo/migrations/20180225104638_add_user_id_to_rooms.exs
@@ -0,0 +1,9 @@
defmodule Prater.Repo.Migrations.AddUserIdToRooms do
use Ecto.Migration

def change do
alter table(:rooms) do
add :user_id, references(:users)
end
end
end