{"id":13879135,"url":"https://github.com/mfinelli/ruolo","last_synced_at":"2025-10-29T18:10:12.813Z","repository":{"id":56893864,"uuid":"204334298","full_name":"mfinelli/ruolo","owner":"mfinelli","description":"A library to keep your static role-based access control policies in sync with your database","archived":false,"fork":false,"pushed_at":"2023-01-25T20:46:24.000Z","size":121,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-24T08:32:41.099Z","etag":null,"topics":["authorization","role-based-access-control","ruby","rubygem","sequel"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/ruolo","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mfinelli.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-25T18:31:32.000Z","updated_at":"2023-01-29T07:51:45.000Z","dependencies_parsed_at":"2023-02-14T11:16:01.454Z","dependency_job_id":null,"html_url":"https://github.com/mfinelli/ruolo","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfinelli%2Fruolo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfinelli%2Fruolo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfinelli%2Fruolo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfinelli%2Fruolo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mfinelli","download_url":"https://codeload.github.com/mfinelli/ruolo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227614637,"owners_count":17793949,"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":["authorization","role-based-access-control","ruby","rubygem","sequel"],"created_at":"2024-08-06T08:02:10.894Z","updated_at":"2025-10-29T18:10:07.754Z","avatar_url":"https://github.com/mfinelli.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Ruolo\n\n[![RubyGems](https://img.shields.io/gem/v/ruolo.svg)](https://rubygems.org/gems/ruolo)\n![Build Status](https://github.com/mfinelli/ruolo/workflows/CI/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/mfinelli/ruolo/badge.svg?branch=master)](https://coveralls.io/github/mfinelli/ruolo?branch=master)\n[![Inline docs](http://inch-ci.org/github/mfinelli/ruolo.svg?branch=master)](http://inch-ci.org/github/mfinelli/ruolo)\n\nA library for generating and keeping your static role-based access-control\npolicies in sync with your database using the\n[sequel](https://github.com/jeremyevans/sequel) gem.\n\nYou're an application developer and know all of the permissions and roles that\nyou want to create - you want to create them in code and have them persist to\nthe database (and stay in sync should you add/change/remove something). This\nis what `ruolo` can help with: define your RBAC policies using a DSL and run\nthe sync on application start up. You're responsible for both the authentication\nand authorization of users after that, `ruolo` is completely unopinionated.\n\n## Usage\n\n### Require\n\nInclude the gem in your gemfile:\n\n```ruby\ngem 'ruolo', require: false\n```\n\nNotice the `require: false` which is necessary so it doesn't automatically get\nincluded if you do something like `Bundler.require`. Make sure that you have a\ndatabase connection and _then_ require the gem and configure it.\n\n### Migrations\n\nYou'll need to run the following database migration to setup your schema, fill\nin the `users` table with your own details:\n\n```ruby\nSequel.migration do\n  change do\n    create_table :users do\n      primary_key :id, type: :Bignum\n\n      column :email, String, null: false, size: 190, unique: true\n      column :password, String, null: false, size: 60, fixed: true\n\n      column :first_name, String, null: false\n      column :last_name, String, null: false\n\n      column :created_at, DateTime, null: false\n      column :updated_at, DateTime, null: false\n\n      constraint(:valid_email, email: /@/)\n    end\n\n    create_table :roles do\n      primary_key :id, type: :Bignum\n\n      column :name, String, null: false, size: 150, unique: true\n\n      column :created_at, DateTime, null: false\n      column :updated_at, DateTime, null: false\n\n      constraint(:valid_name, name: /^[A-Z]([A-Z0-9]*[-._]?)*$/)\n    end\n\n    create_table :permissions do\n      primary_key :id, type: :Bignum\n\n      column :name, String, null: false, size: 150, unique: true\n\n      column :created_at, DateTime, null: false\n      column :updated_at, DateTime, null: false\n\n      constraint(:valid_name, name: /^[A-Z]([A-Z0-9]*[-._]?)*$/)\n    end\n\n    create_table :users_roles do\n      foreign_key :user_id, :users, null: false, type: :Bignum,\n        on_update: :cascade, on_delete: :cascade\n      foreign_key :role_id, :roles, null: false, type: :Bignum,\n        on_update: :cascade, on_delete: :cascade\n      primary_key %i[user_id role_id]\n      index %i[role_id user_id]\n    end\n\n    create_table :roles_permissions do\n      foreign_key :role_id, :roles, null: false, type: :Bignum,\n        on_update: :cascade, on_delete: :cascade\n      foreign_key :permission_id, :permissions, null: false, type: :Bignum,\n        on_update: :cascade, on_delete: :cascade\n      primary_key %i[role_id permission_id]\n      index %i[permission_id role_id]\n    end\n  end\nend\n```\n\n### User Class\n\nYou'll need to set your `User` class to use the correct association class, and\nconfigure `ruolo` to use the correct user class (you can also include the\nruolo user module for the `permission?` mixin helper):\n\n```ruby\nRuolo.configure do |c|\n  c.user_class = 'YourApp::User'\nend\n\nmodule YourApp\n  class User \u003c Sequel::Model\n    include Ruolo::Models::User\n    plugin :timestamps, update_on_create: true\n    many_to_many :roles, join_table: :users_roles, class: 'Ruolo::Models::Role'\n  end\nend\n```\n\n### Policy\n\nTo create your static permissions and roles create a yaml file with the\nfollowing format, the permission list is derived from the permissions that are\ndefined for the roles:\n\n```yaml\n---\nroles:\n  POST_ADMIN:\n    - CREATE_POST\n    - DELETE_POST\n  POST_CREATOR:\n    - CREATE_POST\n```\n\n### Sync\n\nAfter adding the migrations, configuring ruolo and your custom user class, and\ndefining your RBAC policy, run the sync during your application startup:\n\n```ruby\nrequire 'sequel'\nrequire 'ruolo'\n\nDB = Sequel.connect('...')\n\nRuolo.configure do |config|\n  config.connection = DB\nend\n\nRuolo.synchronize!('./path/to/policy.yml')\n```\n\n## Gem Development\n\nTo hack on the gem you'll need PostgreSQL installed and running, then create a\nuser and database:\n\n```shell\n$ createuser ruolo\n$ createdb ruolo\n```\n\nThen you can ensure everything was created correctly:\n\n```shell\n$ psql -U ruolo\n```\n\nYou can use the `bin/console` command which will load in dependencies, and\nmigrate the database on load. It also provides the helper methods `reset_db!`\nand `migrate_db!` if you want to run those operations manually after the code\nhas loaded.\n\n```shell\n$ bundle exec bin/console\n```\n\n## License\n\n```\nCopyright 2019-2023 Mario Finelli\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmfinelli%2Fruolo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmfinelli%2Fruolo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmfinelli%2Fruolo/lists"}