cpjk / canary

:hatching_chick: Elixir authorization and resource-loading library for Plug applications.
MIT License
473 stars 52 forks source link

Storing the authorizations in the database #30

Closed blasut closed 8 years ago

blasut commented 8 years ago

Hi, Is there an way to store the authorization rules in a permanent datastore, maybe using Ecto?

Updated the question to make it more clear.

cpjk commented 8 years ago

The title of the issue and your comment seem to say different things.

Do you mean the configuration (i.e. what you put in your config.exs), or do you mean the authorization rules (e.g. defimpl Canada.Can, for: User do ....)

blasut commented 8 years ago

Sorry, english is not my first language. To clarify i mean the authorization rules.

cpjk commented 8 years ago

No problem!

Since canary's authorization rules are specified as protocol implementations, they need to be present at compile-time. As such, while it would definitely be possible to persist the rules in a datastore, it would probably be complicated to read them back out and have them be useful without manual intervention.

Also, by specifying your rules in the source code, you can check them into version control any changes can be code-reviewed.

By reading rules from the datastore, you lose these benefits.

Can I ask what benefits you think might come from storing rules in a database?

blasut commented 8 years ago

Well, I imagine a scenario where a admin can register new users in the system.

The admin can set the authorization rules for users.

For example:

My first hope would be to let an admin user check specific authorization rules for each user and model. The next best thing would be to let the admin choose predefined roles, which should be viewable in a html page.

cpjk commented 8 years ago

OK, I see what you mean.

What I would do in this case is define permissions attributes on the user model, and authorize based on these attributes. Typically, this is implemented by creating a role model, where each role has associated permissions. You can easily give users roles and have well-defined permissions for each.

You can then define your Canada.Can implementation based on these user attributes.

For example, let's say you have an admin role. In this case, you could give a user the role so that their struct looked like this:

%User{roles: [%Role{name: "admin"}]}

and you could define a rule like this:

defimpl Canada.Can, for: User do
  def can?(%User{roles: user_roles}, :create, User) do
   # return true if the admin role is in user_roles
  end
end

In this way, everything is out in the open in version control and can be code-reviewed.

If you want to be able to give a user new permissions, just give them a role that has the associated permissions.

blasut commented 8 years ago

Thank you very much!

I'm currently evaluating different solutions for a project and elixir seems like a very good choice, but this question was a very big deal for the project.

cpjk commented 8 years ago

Happy to help!

I hope you find a solution that works for you, and hopefully Elixir is part of that solution :smile:

I'll close this issue now. In case you didn't know about it, https://elixir-lang.slack.com is a great place to ask other elixir questions.