Hello everyone! None of the provided authorization libraries worked for me in a way that I needed (I need granular permissions per Role, User, Entity) therefore I created small library for ACL permissions.
Initially I was doing the code inside my project but then I created library from it. I would love to hear any suggestions/thoughts about that. Initially I went with existing libraries like authorize
or canary
but as I need many actions to be performed I ended up with ~20 custom can?
methods just for 1 schema and it was almost impossible to build admin panel for it to manage those permissions.
https://github.com/MilosMosovsky/terminator
https://hex.pm/packages/terminator
What terminator includes?
Database based permission system
When you are building large app with many actions and each action needs to have different permissions + you need some admin panel to manage those permissions existing libraries are just not enough.
Role based permissions
With existing libraries it was really hard to introduce 5 custom roles with different permissions (e.g. admin can done everything, editor can edit post description, super_editor can delete posts, writer can write new posts and registered user can view them. Terminator allows me to create as much roles as I need with assigned permissions to them
Compatibility with ecto projects
I already had existing project without any permissions therefore it was crucial to have something which I can plug-in with several lines without modyfing existing code. Performer
which is main actor in terminator can be plugged to any existing schema (I have it plugged to Account
schema)
Easy to read DSL
When I tried to create permission with existing libraries after a while I felt like a compiler in my head. You have to read extensively through multiple can?
implementations and pattern match them in head to see easily which permission
you are modifying. I created easily readable DSL:
permissions do
has_ability(:delete)
has_role(:admin)
end
as_authorized do
"I can safely proceed"
end
Full code coverage
As I understand how ACL is crucial for app I am maintaining 100% code coverage and keep library āover-testedā
Future ideas
-
I am using
ueberauth
,absinthe
in my app, I want to do easy plugs to load performer from plugs (session) or absinthe context. -
Currently I have WIP version for
field
based authorization in GraphQL (e.g. you have user shape but only admins and owner of an account can queryemail
field, you can solve it with multiple shaped queries but I created middleware on the top of terminator which protects resulting shape and returnsnil
on particular field) this allows you to have only 1 query
query { account { id, email } }
and terminator protectsemail
field in resolver.
As I am originally react developer I realize that code is probably not perfect but I would love to hear any suggestions/ideas and try-outs! Thank you!