{"id":16400985,"url":"https://github.com/moertel/forty","last_synced_at":"2025-10-26T15:31:02.255Z","repository":{"id":56847611,"uuid":"64134239","full_name":"moertel/forty","owner":"moertel","description":"Postgres ACL as code: manage users, groups and permissions","archived":false,"fork":false,"pushed_at":"2019-04-10T13:09:51.000Z","size":33,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-30T05:26:11.830Z","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/moertel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-07-25T12:55:09.000Z","updated_at":"2018-11-16T10:58:42.000Z","dependencies_parsed_at":"2022-09-09T06:22:45.027Z","dependency_job_id":null,"html_url":"https://github.com/moertel/forty","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moertel%2Fforty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moertel%2Fforty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moertel%2Fforty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moertel%2Fforty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moertel","download_url":"https://codeload.github.com/moertel/forty/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238357427,"owners_count":19458578,"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-10-11T05:29:09.137Z","updated_at":"2025-10-26T15:31:01.974Z","avatar_url":"https://github.com/moertel.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Forty\n\n[![Build Status](https://travis-ci.org/moertel/forty.svg?branch=master)](https://travis-ci.org/moertel/forty) [![Gem Version](https://badge.fury.io/rb/forty.svg)](https://badge.fury.io/rb/forty)\n\nDefine Postgres users, groups and their permissions as code and let Forty enforce this state in your Postgres database. Forty will create users/groups which are present in the configuration file but missing from the database, and will delete users/groups which are present in the database but missing from the configuration file. An extensive example can be found [here](example/acl.json).\n\n## Example\n\nIf you have Docker installed, you can run `docker-compose -f docker-compose_demo.yml up` on your machine to see an example in action. This will spin up a Postgres instance with the system user `postgres` and another admin user `demo_admin_user`. The file [`acl.json`](example/acl.json) specifies a few more users and groups (and their permissions) who are not yet present in the database. When calling Forty's `sync` method, the configuration will be synced to the database.\n\n## Usage\n\nTo configure Forty, simply require it in your script and configure the library as well as a Postgres database. You will need to specify a user for the Postgres database which has access to all realms that you want to manage. In case you want to allow it to delete users, Forty will reassign objects that are defined in `Forty.configuration.schemas` to the user defined as `Forty.configuration.master_username` and delete all other objects in \"unmanaged\" schemas.\n\n### Configuration\n\n```ruby\nrequire 'forty'\n\nForty.configure do |config|\n    config.master_username = 'postgres' # the root user; no permissions will be synced for this user\n    config.acl_file = 'acl.json'        # the file with users, groups and permissions\n    config.schemas = ['postgres']       # a list of schemas to be caught by wildcard identifiers in `acl.json`\nend\n\nForty.database do |db|\n    db.host = '127.0.0.1'\n    db.port = 5432\n    db.user = 'postgres'    # the user to be used to sync permissions. must have full access to everything!\n    db.password = 'secret'\n    db.database = 'postgres'\nend\n```\n\nIn case you want to send an email with credentials and connection details to a user:\n```ruby\nForty.mailer do |mail|\n  mail.smtp_address = 'someone@example.com' # sender address\n  mail.smtp_host = 'localhost'              # SMTP server address\n  mail.smtp_port = 587                      # SMTP server port\n  mail.smtp_username = 'someone'\n  mail.smtp_password = 'very_secret'\n  mail.smtp_authentication = :login         # refer to Ruby's mail gem for available options\n  mail.smtp_encryption = :tls               # refer to Ruby's mail gem for available options\n  mail.templates = { user_created: 'mail_template_user_created.erb' } # see example/mail_template_user_created.erb for available placeholders\n  mail.enabled = true                       # whether or not emails should be sent, defaults to false\nend\n```\n\n### Execution\n\nYou can either sync immediately by calling the command somewhere in your Ruby code:\n```ruby\n# ./some_ruby_script.rb\n\nrequire 'forty'\n\nForty.sync  # this starts the sync immediately\n```\n\nOr import Forty's Rake tasks and call it from elsewhere; especially useful if you want to run this in Docker:\n```ruby\n# Rakefile\n\nrequire 'forty/rake/task'\n```\nWhich will give you the following command:\n```\n$ rake acl:sync:all\n```\n\n### ACL File\n\nDefine users, groups and permissions in a JSON formatted file. (A more sophisticated example can be found [here](example/acl.json).)\n```json\n{\n    \"users\": {\n        \"some_readonly_user\": {\n            \"groups\": [\n                \"all_tables_readonly\"\n            ]\n        }\n    },\n    \"groups\": {\n        \"all_tables_readonly\": {\n            \"permissions\": [\n                {\n                    \"type\": \"table\",\n                    \"identifiers\": [\n                        \"*.*\"\n                    ],\n                    \"privileges\": [\n                        \"select\"\n                    ]\n                }\n            ]\n        }\n    }\n}\n```\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'forty'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install forty\n\n\n## Contributing\n\n1. Fork it ( https://github.com/moertel/forty/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoertel%2Fforty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoertel%2Fforty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoertel%2Fforty/lists"}