{"id":13878946,"url":"https://github.com/markets/sudo_rails","last_synced_at":"2025-04-09T20:13:01.745Z","repository":{"id":34845017,"uuid":"184481314","full_name":"markets/sudo_rails","owner":"markets","description":"🔒 Sudo mode for your Rails controllers","archived":false,"fork":false,"pushed_at":"2024-04-17T18:55:12.000Z","size":241,"stargazers_count":80,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-09T20:12:50.263Z","etag":null,"topics":["password-confirmation","rails","rails-engine","ruby","security","sudo"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/sudo_rails","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/markets.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":"support/images/cover.png","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-01T21:03:31.000Z","updated_at":"2024-04-24T06:08:38.000Z","dependencies_parsed_at":"2023-11-21T00:26:22.987Z","dependency_job_id":"85372df0-d9b8-4236-996a-5fa57f600f27","html_url":"https://github.com/markets/sudo_rails","commit_stats":{"total_commits":52,"total_committers":2,"mean_commits":26.0,"dds":"0.019230769230769273","last_synced_commit":"ac3df41a85b7eeb224981b78ea040cb53eacb63b"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markets%2Fsudo_rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markets%2Fsudo_rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markets%2Fsudo_rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markets%2Fsudo_rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markets","download_url":"https://codeload.github.com/markets/sudo_rails/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103872,"owners_count":21048245,"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":["password-confirmation","rails","rails-engine","ruby","security","sudo"],"created_at":"2024-08-06T08:02:05.020Z","updated_at":"2025-04-09T20:13:01.702Z","avatar_url":"https://github.com/markets.png","language":"Ruby","readme":"# Sudo Rails\n\n[![Gem](https://img.shields.io/gem/v/sudo_rails.svg?style=flat-square)](https://rubygems.org/gems/sudo_rails)\n[![Build Status](https://github.com/markets/sudo_rails/workflows/CI/badge.svg)](https://github.com/markets/sudo_rails/actions)\n[![Maintainability](https://api.codeclimate.com/v1/badges/322350adc7ab052beccb/maintainability)](https://codeclimate.com/github/markets/sudo_rails/maintainability)\n\n\u003e Sudo mode for your Rails controllers\n\n:lock: Protect any Rails action with a customizable password confirmation strategy.\n\n```ruby\nclass SecretController \u003c ApplicationController\n  sudo\nend\n```\n\n*Inspired by [Unix `sudo` command](https://en.wikipedia.org/wiki/Sudo) and [GitHub Sudo mode](https://help.github.com/en/articles/sudo-mode).*\n\n![](support/images/cover.png)\n\n## Installation\n\nAdd this line to your Gemfile and then execute `bundle install`:\n\n```ruby\ngem 'sudo_rails'\n```\n\n## Usage\n\nFrom now on, you have the `sudo` method available in your controllers, you can protect the whole controller or only some actions:\n\n```ruby\nclass SettingsController \u003c ApplicationController\n  sudo only: :sensible_settings\nend\n```\n\nUnder the hood, the `sudo` method delegates to a `before_action` callback, so you're able to pass the following options: `:only`, `:except`, `:if` and `:unless`.\n\nThe gem also provides a couple of controller helpers, useful to manually manage the `sudo` session status:\n\n- `reset_sudo_session!`: resets the current sudo session, if any.\n- `extend_sudo_session!`: marks the current session as a valid sudo session.\n\n### Configuration\n\nYou can use the `setup` method to configure and customize different things:\n\n```ruby\n# config/initializers/sudo_rails.rb\nSudoRails.setup do |config|\n  # On/off engine\n  config.enabled = true\n\n  # Sudo mode sessions duration, default is 30 minutes\n  config.sudo_session_duration = 10.minutes\n\n  # Confirmation page styling\n  config.custom_logo = '/images/logo_medium.png'\n  config.primary_color = '#1a7191'\n  config.background_color = '#1a1a1a'\n  config.layout = 'admin'\n\n  # Confirmation strategy implementation\n  config.confirm_strategy = -\u003e (context, password) {\n    user = context.current_user\n    user.valid_password?(password)\n  }\n\n  # Reset password link\n  config.reset_pass_link = '/users/password/new'\n\n  # Subscribe to different events\n  config.callbacks = {\n    invalid_sudo_session: -\u003e (context) {\n      user = context.current_user\n      AuthService.send_code(user)\n    },\n    invalid_confirmation: -\u003e (context) {\n      user = context.current_user\n      Rails.logger.warn(\"[SUDO_RAILS] invalid password for #{user.email}\")\n    }\n  }\nend\n```\n\nUse the provided `sudo_rails:config` generator to create a default config file under your *initializers* folder.\n\n### Sudo sessions\n\nUsing the `sudo_session_duration` option you are able to configure the `sudo` session duration (30 minutes by default).\n\nIf you set it to `nil`, your `sudo` session won't expire automatically and you will have to do it manually by using the `reset_sudo_session!` helper.\n\n### Styling\n\nUsing the `custom_logo`, `primary_color` and `background_color` options, you can customize the confirmation page. In case you want full control of the styles, you can use your own layout (and consequently your own styles too) using the `layout` option.\n\nSee some :camera: [examples here](support/images/examples/).\n\n\u003e ℹ️ If you are using your own layout, don't forget to render the flash messages in that layout. You can do something [like this](app/views/sudo_rails/_flash_alert.html.erb).\n\nYou can also override the view by calling the `sudo_rails:view` generator. This will create a copy of the view file at `app/views/sudo_rails/confirm_form.html.erb` which can be later modified as per your requirements.\n\n### Confirmation strategy\n\nYou should define how to validate the password using the `confirm_strategy` option. It must be a `lambda`, which will receive 2 arguments: the controller instance (`context`) and the password from the user.\n\nBy default, the gem ships with `Devise` and `Clearance` integration. Check it [here](lib/sudo_rails/integrations/).\n\n\u003e ℹ️ In order to autoload `Devise` or `Clearance` strategy properly, you should place the `sudo_rails` gem after them in the Gemfile.\n\nImplementation examples:\n\n```ruby\n# Devise implementation\nconfig.confirm_strategy = -\u003e (context, password) {\n  user = context.current_user\n  user.valid_password?(password)\n}\n\n# has_secure_password implementation\nconfig.confirm_strategy = -\u003e (context, password) {\n  user = context.current_user\n  user.authenticate(password)\n}\n\n# Another example, using ENV vars\nconfig.confirm_strategy = -\u003e (context, password) {\n  user = context.current_user\n  user.admin? \u0026\u0026 password == ENV['SUPER_SECRET_PASSWORD']\n}\n```\n\n### Callbacks\n\nYou can subscribe to different lifecycle events via the `callbacks` option. Each callback must be a `lambda`, which will receive 1 argument, the controller instance (`context`).\n\nYou can subscribe to the following events:\n\n- `:invalid_sudo_session`: fired when the confirmation page is rendered, because there is no valid sudo session. Be careful! If the page is re-submitted or the password is invalid, the confirmation page will be rendered again and this event will be fired again too.\n- `:new_sudo_session`: fired when a new sudo session is started.\n- `:invalid_confirmation`: fired when an invalid password is submitted.\n\nThis can be really useful for example for instrumentation or logging:\n\n```ruby\nconfig.callbacks = {\n  invalid_confirmation: -\u003e (context) {\n    user = context.current_user\n    request = context.request\n\n    Rails.logger.warn(\"[SUDO_RAILS] Invalid verification: #{user.email} - #{request.remote_ip}\")\n  }\n}\n```\n\nOr you can even implement custom workflows along with the `confirm_strategy` option. Like for example, using your 2FA system instead of the session password:\n\n```ruby\nconfig.callbacks = {\n  invalid_sudo_session: -\u003e (context) {\n    user = context.current_user\n    AuthService.send_code(user)\n  }\n}\n\nconfig.confirm_strategy = -\u003e (context, code) {\n  user = context.current_user\n  AuthService.validate_code(user, code)\n}\n```\n\n### I18n\n\n`sudo_rails` uses I18n by default. Take a look at our [locale file](config/locales/en.yml) to check all available messages.\n\n## Development\n\nAny kind of feedback, bug report, idea or enhancement are really appreciated.\n\nTo contribute, just fork the repo, hack on it and send a pull request. Don't forget to add tests for behaviour changes and run the test suite:\n\n    \u003e bundle exec rspec\n\n## License\n\nCopyright (c) Marc Anguera. SudoRails is released under the [MIT](LICENSE) License.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkets%2Fsudo_rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkets%2Fsudo_rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkets%2Fsudo_rails/lists"}