Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> How do I do that in Phoenix ?

Assuming you have a `current_user` stored in assigns, I implement basic role access as:

    def edit(conn, param) when conn.assigns.current_user.role == :admin do
      ...
    end
If that's too long:

    defguard is_granted(conn, role) when conn.assigns.current_user.role == role

    def edit(conn, param) when is_granted(conn, :admin) do
      ...
    end
It also works on LiveViews with guards on handle_event.

---

The other way of doing authorization, which IIRC is similar to voters in Symfony, I typically implement with protocols:

    defprotocol Authz do
      def can?(resource, action, user)
    end
Then in my Post schema:

    defmodule MyApp.Blog.Post do
      schema "posts" do
        # ...
      end

      defimpl Authz do
        def can?(post, :view, user) do
          post.public or can?(post, :edit, user)
        end

        def can?(post, :edit, user) do
          post.owner_id == user.id
        end
      end
    end
You may encapsulate in a controller helper like this, although you cannot use it in guards:

    def can?(conn, resource, action) do
      Authz.can?(resource, action, conn.assigns.current_user)
    end
Now you can call it to check against any resource whatsoever. If you don't implement it for a resource or for an action, it will crash as expected.

I find it requires less boilerplate than the Voter approach in Symfony (but it has been quite some time since I last checked it). No additional abstractions either. The only downside is that it doesn't work annotation/@decorator style (but if you really want it, it should be doable).

---

However, my favorite way of doing authz is by scoping the queries. Typically all of my context functions receive either the org, the user, or a "session" data structure with both which I use as the starting point of my queries. Then I complement with Authz.can? style when that's not enough.



That's sensible ways of doing things obviously. The can? approach is very similar to the Canada lib IIRC. I'll probably try some of those.

But the best non-business code I like is the one I don't have to code, commit and maintain.

You don't need voters for the example I wrote earlier though, in fact I don't remember the last time I had to write one.

But I think it's more a functional vs OO discussion and we know how those goes ;)


I can see how #[IsGranted(role)] would work without voters but how would #[IsGranted(post, view)] work without voters? Would it dispatch to the post object? If so, then it is pretty much the same as protocols, yeah.

Follow up question: do you think the above would be helpful as a short-guide on Phoenix?


Yes you're probably right about the voter, I've probably mixed it up with the automatic parameter conversion for routing.

I've done too much Phoenix lately I forgot the rest ;)

About the guide I don't know, maybe a blog post yeah, but there is libs that do all that, maybe there's even too many of them. They are fine but lack the cohesiveness you get with something integrated in a framework.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: