My permission system requires 3 inputs, how would I design this in elixir?

Ok so in just 1 day I have almost ported my Rails API over to Phoenix, thanks everyone!

So in rails I have a class where I take in a few models as inputs, and based on those models I created my authorization class that I use in my controllers.

class PermissionService
  attr_access :model1, :model2, :model3
  def initialize(model1, model2, model3)
    ...
  end

  def can_do_this?()
    model1.prop1 && model3.prop5
  end

  def can_do_that?()
  end
end

So far in Phoenix I created a custom Plug that I can in my API pipeline, I get the api token from the request and I load etc. using Ecto.

How would I design a module?? to mimick my PermissionService I have in ruby.

You can port that code in a relatively straightforward manner. However, there are probably more idiomatic approaches but it’s hard to suggest them without knowing more concrete details of your use-case. The code below definitely smells more OO than functional.

defmodule MyPermissionService do
  defstruct [:model1, :model2, :model3]

  def new(model1, model2, model3) do
    %__MODULE__{model1: model1, model2: model2, model3: model3}
  end

  def can_do_this?(%__MODULE__{} = service) do
    %__MODULE__{model1: model1, model3: model3} = service
    model1.prop1 && model3.prop5
  end

  ...
end
1 Like

I would do it with plugs in controller:

def YourController do
  plug :can_do_this when action in [:actions_can_do_this]
  plug :can_do_that when action in [:actions_can_do_that]

  # function plug can_do_this
  defp can_do_this(conn, _) do
  end

  # function plug can_do_that
  defp can_do_that(conn, _) do
  end
end

Of course we can extract those function plugs into its own module.

1 Like

I would suggest not to carbon copy your rails/ruby code, think for second how can you model this functionally for example I could create a module that implements the functions to check some permission it could be any module instead of taking 1,2,3 models

defmodule PermissionService do
  def can_do_x(list_of_some_model) when is_list(list_of_some_model) do
  end

  def can_do_x(some_model) do 
  end

  def can_do_y(some_model) do
  end
end

not only you can extend this example to accept arbitrary models you can also use it as plugs if you like with minor changes

Note: possible improvements you can create behavior which is implemented by your permission models

3 Likes

Its very fine grained access.

Like say it is forum software:

can access post, can create forum, can reply to post

Update

Thanks for your suggestions, I think I will make it more functional, and also create plugs where it makes sense as sometimes I want the request execution to redirect or halt, and at other times it will be a simple message to the UI or a specific JSON response.

1 Like

Hey @salman, I have read your post and I had similar requirements as you (Blog system not forum system as in your case, but context are almost same). I have struggled with dirty rules definition and I recently created library

Maybe you could take a look to it and let me know any suggestions/if it fits in your context and what can I improve to fit it :slight_smile:

3 Likes

I went the custom route at this time, I’ll check your lib out though thanks.
I wanted something very specific to my needs because I didn’t want to wrestle with another library.
I tend to like full-control when it comes to a permission system (authorization) :slight_smile:

1 Like