{"id":13427677,"url":"https://github.com/be9/acl9","last_synced_at":"2025-03-16T00:31:52.475Z","repository":{"id":474967,"uuid":"100181","full_name":"be9/acl9","owner":"be9","description":"Yet another role-based authorization system for Rails","archived":false,"fork":false,"pushed_at":"2024-01-04T06:19:55.000Z","size":283,"stargazers_count":854,"open_issues_count":8,"forks_count":118,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-04-14T07:14:10.760Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/be9.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2009-01-03T12:14:52.000Z","updated_at":"2024-04-30T18:52:05.163Z","dependencies_parsed_at":"2024-01-05T21:58:27.832Z","dependency_job_id":null,"html_url":"https://github.com/be9/acl9","commit_stats":{"total_commits":173,"total_committers":28,"mean_commits":6.178571428571429,"dds":0.630057803468208,"last_synced_commit":"da5e390e349e31ec6e063c505a9147b4ada89e72"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/be9%2Facl9","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/be9%2Facl9/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/be9%2Facl9/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/be9%2Facl9/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/be9","download_url":"https://codeload.github.com/be9/acl9/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221631809,"owners_count":16855012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T01:00:36.691Z","updated_at":"2024-10-27T05:30:18.774Z","avatar_url":"https://github.com/be9.png","language":"Ruby","readme":"# acl9\n\n[![Travis-CI](https://travis-ci.org/be9/acl9.svg?branch=master)](https://travis-ci.org/be9/acl9)\n\nAcl9 is a role-based authorization system that provides a concise DSL for\nsecuring your Rails application.\n\nAccess control is pointless if you're not sure you've done it right.  The\nfundamental goal of acl9 is to ensure that your rules are easy to understand and\neasy to test - in other words acl9 makes it easy to ensure you've got your\npermissions correct.\n\n## Installation\n\nAcl9 is [Semantically Versioned](http://semver.org/), so just add this to your\n`Gemfile` (note that you need 3.2 for Rails 6+ support):\n\n```ruby\ngem 'acl9', '~\u003e 3.2'\n```\n\nYou will need Ruby \u003e 2.0\n\n### Rails 4 - stick with 2.x\n\n```ruby\ngem 'acl9', '~\u003e 2.0'\n```\n\n### Rails \u003c 4 - upgrade Rails!\n\nWe dropped support for Rails \u003c 4 in the 1.x releases, so if you're still using\nRails 2.x or 3.x then you'll want this:\n\n```ruby\ngem 'acl9', '~\u003e 0.12'\n```\n\n## Getting Started\n\nThe simplest way to demonstrate this is with some examples.\n\n### Access Control\n\nYou declare the access control directly in your controller, so it's visible and\nobvious for any developer looking at the controller:\n\n```ruby\nclass Admin::SchoolsController \u003c ApplicationController\n  access_control do\n    allow :support, :of =\u003e School\n    allow :admins, :managers, :teachers, :of =\u003e :school\n    deny :teachers, :only =\u003e :destroy\n\n    action :index do\n      allow anonymous, logged_in\n    end\n\n    allow logged_in, :only =\u003e :show\n    deny :students\n  end\n\n  def index\n    # ...\n  end\n\n  # ...\nend\n```\n\nYou can see more about all this stuff in the wiki under [Access Control\nSubsystem](//github.com/be9/acl9/wiki/Access-Control-Subsystem)\n\n### Roles\n\nThe other side of acl9 is where you give and remove roles to and from a user. As\nyou're looking through these examples refer back to the [Access\nControl](#access-control) example and you should be able to see which access\ncontrol rule each role corresponds to.\n\nLet's say we want to create an admin of a given school, not a global admin, just\nthe admin for a particular school:\n\n```ruby\nuser.has_role! :admin, school\nuser.has_role! :admin, of: school\n```\n\nThen let's say we have some support people in our organization who are dedicated\nto supporting all the schools. We could do two things, either we could come up\nwith a new role name like `:school_support` or we can use the fact that we can\nassign roles to any object, including a class, and do this:\n\n```ruby\nuser.has_role! :support, School\nuser.has_role! :support, for: School\n```\n\nYou can see the `allow` line in our `access_control` block that this corresponds\nwith. If we had used `:school_support` instead then that line would have to be:\n`allow :school_support`\n\nNow, when a support person leaves that team, we need to remove that role:\n\n```ruby\nuser.has_no_role! :support, School\nuser.has_no_role! :support, at: School\n```\n\nYou can see more about all this stuff in the wiki under [Role\nSubsystem](//github.com/be9/acl9/wiki/Role-Subsystem)\n\n## Database Setup\n\nAs mentioned in [Role Subsystem](//github.com/be9/acl9/wiki/Role-Subsystem) you\ndon't have to use these, if your role system is very simple all you need is a\n`has_role?` method in your subject model that returns a boolean and the Access\nControl part of Acl9 will work from that.\n\nHowever, most commonly, the roles and role assignments are stored in two new\ntables that you create specifically for Acl9. There's a rails generator for\ncreating the migrations, role model and updating the subject model and\noptionally any number of object models.\n\nYou can view the USAGE for this generator by running the following in your app\ndirectory:\n\n```sh\nbin/rails g acl9:setup -h\n```\n\n## Configuration\n\nThere are five configurable settings. These all have sensible defaults which can\nbe easily overridden in `config/initializers/acl9.rb`\n\nYou can also override each of the `:default_*` settings (dropping the \"default_\"\nprefix) in your models/controllers - see below for more detail:\n\n### :default_role_class_name\n\nSet to `'Role'` and can be overridden in your \"user\" model, [see the wiki for more](//github.com/be9/acl9/wiki/Role-Subsystem#custom-class-names).\n \n### :default_association_name\n\nSet to `:role_objects` and can be overridden in\nyour \"user\" model, [see the wiki for more](//github.com/be9/acl9/wiki/Role-Subsystem#subject-model).\nWe chose a name for this association that was unlikely to conflict with\nexisting models but a lot of people override this to be just `:roles`\n\n### :default_subject_class_name\n\nSet to `'User'` and can be overridden in your\n\"role\" model, [see the wiki for more](//github.com/be9/acl9/wiki/Role-Subsystem#custom-class-names).\n\n### :default_subject_method\n\nSet to `:current_user` and can be overridden in\nyour controllers, [see the wiki for more](//github.com/be9/acl9/wiki/Access-Control-Subsystem#subject_method).\n\n### :default_join_table_name\n\nThis is set to `nil` by default, which will mean it will use the Rails method of\ncalculating the join table name for a `has_and_belongs_to_many` (eg.\n`users_roles`). Remember that if you override this value, either do it before\nyou run `rails g acl9:setup` or be sure to update your migration or database.\n\n### :normalize_role_names\n\nSet to `true` (see \"Upgrade Notes\" below if you're upgrading) and can only be\nchanged by setting it in `Acl9.config`. When true this causes Acl9 to normalize\nyour role names, normalization is `.to_s.underscore.singularize`. This is done\non both the setter and getter.\n\n### :protect_global_roles\n\nSet to `true` (see \"Upgrade Notes\" below if you're upgrading) and can only be\nchanged by merging into `Acl9.config`.  This setting changes how global roles\n(ie. roles with no object) are treated.\n\nSay we set a role like so:\n\n```ruby\nuser.has_role! :admin, school\n```\n\nWhen `:protect_global_roles` is `true` (as is the default) then `user.has_role?\n:admin` is `false`. Ie. changing the role on a specific instance doesn't impact\nthe global role (hence the name).\n\nWhen `:protect_global_roles` is `false` then `user.has_role? :admin` is `true`.\nIe. setting a role on a specific instance makes that person a global one of\nthose roles.\n\nBasically these are just two different ways of working with roles, if you're\nprotecting your global roles then you can use them as sort of a superuser\nversion of a given role. So you can have an admin of a school **and** a global\nadmin with different privileges.\n\nIf you don't protect your global roles then you can use them as a catch-all for\nany specific roles, so then the admins of schools, classrooms and students can\nall be granted a privilege by allowing the global `:admin` role.\n\n### Example\n\n```ruby\n# config/initializers/acl9.rb\nAcl9.config.default_association_name = :roles\n\n# or...\nAcl9.configure do |c|\n  c.default_association_name = :roles\nend\n```\n\n### Reset Defaults\n\nOn the off chance that you ever need to reset the config back to its default you\ncan use:\n\n```ruby\nAcl9.config.reset!\n```\n\n## Upgrade Notes\n\n### Acl9 now protects global roles by default\n\nPlease, PLEASE, **PLEASE** note. If you're upgrading from the `0.x` series of acl9\nthen there's an important change in one of the defaults for `1.x`. We flipped\nthe default value of `:protect_global_roles` from `false` to `true`.\n\nSay you had a role on an object:\n\n```ruby\nuser.has_role! :manager, department\n```\n\nWe all know that this means:\n\n```ruby\nuser.has_role? :manager, department    # =\u003e true\nuser.has_role? :manager, in: department    # =\u003e true\n```\n\nWith `:protect_global_roles` set to `false`, as it was in `0.x` then the above\nrole would mean that the global `:manager` role would also be `true`.\n\nIe. this is how `0.x` behaved:\n\n```ruby\nuser.has_role? :manager      # =\u003e true\n```\n\nNow in `1.x` we default `:protect_global_roles` to `true` which means that the\nglobal `:manager` role is protected, ie:\n\n```ruby\nuser.has_role? :manager      # =\u003e false\n```\n\nIn words, in 1.x just because you're the `:manager` of a `department` that\ndoesn't make you a global `:manager` (anymore).\n\n### Acl9 now normalizes role names by default\n\nSo basically we downcase, underscore, and singularize your role names, so:\n\n```ruby\nuser.has_role! 'FooBars'\n\nuser.has_role? 'FooBars'     # =\u003e true\nuser.has_role? :foo_bar      # =\u003e true\n\nuser.has_role! :foo_bar      # =\u003e nil, because it was already set above\n```\n\nIf you're upgrading then you will want to do something like this:\n\n```ruby\nRole.all.each do |role|\n  role.update! name: role.name.underscore.singularize\nend\n```\n\n**Then check for any duplicates** and resolve those manually.\n\n### Acl9 now raises ArgumentError on bad args to `allow`/`deny`\n\nIn 2.x and above we now try to help the developer by raising ArgumentError if\nthey mess up with the options they pass to `allow`/`deny`, this prevents people\ndoing things that they think are going to work but actually aren't like:\n\n```ruby\n  allow all, actions: [ :index, :show ]    # \u003c---- BROKEN!!\n```\n\n## Community\n\n**Gitter:** [Join the gitter chat here](https://gitter.im/be9/acl9)\n\n**docs:** Rdocs are available [here](http://rdoc.info/projects/be9/acl9).\n\n**StackOverflow:** Go ask (or answer) a question [on\nStackOverflow](http://stackoverflow.com/questions/tagged/acl9)\n\n**Mailing list:** We have an old skule mailing list as well [acl9-discuss\ngroup](http://groups.google.com/group/acl9-discuss)\n\n**Contributing:** Last but not least, check out the [Contributing\nGuide](./CONTRIBUTING.md) if you want to get even more involved\n\n## Acknowledgements\n\n[All these people are awesome!](//github.com/be9/acl9/graphs/contributors) as are all the\npeople who have raised or investigated issues.\n","funding_links":[],"categories":["User","Security","Ruby","Authorization"],"sub_categories":["Authorization","Rails Authorization"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbe9%2Facl9","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbe9%2Facl9","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbe9%2Facl9/lists"}