How I can restrict some function/routes only for authenticated user?
In django, I can do this easily by putting a decorator on top of function. Like this one :
@login_required
def post_new(request):
# do stuff here... only for logged in user
I’m using openmaize lib to do my auth job, and its docs doesnt cover any of this issue.
Second question, how I can restrict some functions so that only the author (assuming this is some kind of blogging app) that can only edit his own post? In Ruby maybe something like this (CMIIW) :
def edit
if @post.user_id != current_user.id
flash[:notice] = 'Access denied as you are not owner of this Post'
redirect_to root_path
end
end
Thank you in advance for any help you can provide
Cheers!
One way is to use plugs and pipelines. You define a pipeline on your router (possibly :login_required). Inside that pipeline, you add a plug that verifies the authentication mechanism and bail (with 401 or redirects) if no session or authorization header provided.
Edit to add: after that, you can use the pipeline on your scope. For example:
pipeline :login_required do
# your plugs
end
scope "/", MyApp do
pipe_through [:browser]
# public routes
end
scope "/", MyApp do
pipe_through [:browser, :login_required]
# protected routes.
# yes, you can have multiple scopes with the same route.
end
You can see as an example guardian’s docs on using pipelines. I don’t know if guardian plays well with openmaize though. Basically you need something along the lines of Guardian.Plug.VerifySession or Guardian.Plug.VerifyHeader (depends on your authentication mechanism) and Guardian.Plug.EnsureAuthenticated.
For the second one, I think it would be quite straightforward if the user_id is in the post body and you have your current_user detail on session or token. If the POSTed data does not contain user_id, you might need to fetch the post from the DB first.
This solved my first issue
Thank you so much @cassiogodinho!
This solved my 2nd issue! Thanks for the clue. This is how I do it (I dont know if this is the best way or not, but it works for me. If you know a better way, please let me know) :
def edit(conn, %{"id" => id}) do
note = Repo.get!(Note, id)
current_user = conn.assigns.current_user
if current_user.id != current_user.id do
conn
|> put_flash(:error, "Cannot edit!.")
|> redirect(to: note_path(conn, :index))
else
changeset = Note.changeset(note)
render(conn, "edit.html", note: note, changeset: changeset)
end
end
The plug :id_check when action in [:edit, :update, :delete] was supposed to solve the second issue because this is what the plug is doing.
def id_check(%Plug.Conn{params: %{"id" => id}, assigns: %{current_user:
%{id: current_id}}} = conn, _opts) do
if id == to_string(current_id), do: conn,
else: auth_error conn, "You are not authorized to view this page", user_path(conn, :index)
end