Skip to content

Commit

Permalink
add Rails authentication scaffold guide
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianthedev committed Nov 22, 2024
1 parent 3eef685 commit 9c93837
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 26 deletions.
27 changes: 23 additions & 4 deletions docs/3.0/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,23 @@ With Avo, you have the flexibility to build apps either with or without authenti
3. You can assign [lightweight roles](#user-roles) to your users.
4. Any authentication strategy or gem of your choice can be utilized.

:::info Rails 8 authentication scaffold
In essence, the [authentication scaffold](https://github.com/rails/rails/pull/52328) that Rails 8 comes with is custom authentication so we need to do a few things to ensure it's working.

Please follow [this guide](./guides/rails-authentication-scaffold) to enable it.
:::

## Customize the `current_user` method

Avo will not assume your authentication provider (the `current_user` method returns `nil`). That means that you have to tell Avo who the `current_user` is.

### Using devise
<Option name="Rails authentication scaffold">

Please follow [this guide](./guides/rails-authentication-scaffold) to Rails' authentication scaffold.

</Option>

<Option name="Devise">

For [devise](https://github.com/heartcombo/devise), you should set it to `current_user`.

Expand All @@ -26,8 +38,9 @@ Avo.configure do |config|
config.current_user_method = :current_user
end
```
</Option>

### Use a different authenticator
<Option name="Other methods">

Using another authentication provider, you may customize the `current_user` method to something else.

Expand All @@ -49,6 +62,8 @@ Avo.configure do |config|
end
```

</Option>

## Customize the sign-out link

If your app responds to `destroy_user_session_path`, a sign-out menu item will be added on the bottom sidebar (when you click the three dots). If your app does not respond to this method, the link will be hidden unless you provide a custom sign-out path. There are two ways to customize the sign-out path.
Expand Down Expand Up @@ -138,7 +153,7 @@ Avo roles are very lightweight and that's for a reason. Building with roles in m

There are two extra roles that you can give to a user, besides the regular user. These roles can be assigned with a check on the `current_user` object.

### 1. Admin user
<Option name="1. Admin user">

The check that Avo will do to figure that out is to run the `is_admin?` method on the [`current_user`](#customize-the-current-user-method) object.

Expand All @@ -150,7 +165,9 @@ You can do that check yourself using the `Avo::Current.user_is_admin?`.

Avo doesn't use this setting momentarily but might in the future.

### 2. Developer user
</Option>

<Option name="2. Developer user">

There might be cases where you want to signal that a user is a developer. The developer will be able to see extra things like long backtrace messages in errors.

Expand All @@ -167,6 +184,8 @@ Ex: on record save, you might call an API which by some reason errors out. Inste

<Image src="/assets/img/3_0/authentication/backtrace.png" alt="Backtrace alert" width="1602" height="780" />

</Option>

### Customize the methods that check for roles

You may customize the methods that Avo uses to assign roles in the initializer.
Expand Down
7 changes: 7 additions & 0 deletions docs/3.0/common/application_controller_eject_notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:::info
If you don't have the `app/controllers/avo/application_controller.rb` file present in your app, you can eject it using this command:

```bash
rails generate avo:eject --controller application_controller
```
:::
27 changes: 5 additions & 22 deletions docs/3.0/guides/multi-language-urls.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,16 @@ Implementing multi-language URLs is a common use-case. Using a route scope block

## 1. Mount Avo within a `:locale` scope

<!-- @include: ./../common/mount_avo_under_locale_scope_common.md-->
<!-- @include: ./../common/mount_avo_under_locale_scope_common.md -->

## 2. Apply the `locale` Scope

To properly handle localization within Avo, you'll need to ensure the `locale` parameter is respected throughout the request.
To properly handle localization within Avo, you'll need to ensure the `locale` parameter is respected throughout the request which we'll do by overriding the `set_avo_locale` method in your `Avo::ApplicationController` as follows:

:::info
If you've already ejected the `Avo::ApplicationController`, you can skip the ejection step below.
:::
<!-- @include: ./../common/application_controller_eject_notice.md -->

### Eject the `Avo::ApplicationController`

Run the following command to eject the `Avo::ApplicationController`:

```bash
rails generate avo:eject --controller application_controller
```

This command generates a customizable version of the `Avo::ApplicationController`, allowing you to override default behaviors.

### Override the `set_avo_locale` method

Next, override the `set_avo_locale` method to ensure that the `locale` parameter is applied throughout the request lifecycle. Update your controller as follows:

```ruby{5-7}
```ruby{4-6}
# app/controllers/avo/application_controller.rb
module Avo
class ApplicationController < BaseApplicationController
def set_avo_locale(&action)
Expand All @@ -44,4 +27,4 @@ module Avo
end
```

This implementation uses `I18n.with_locale` to set the desired locale for the duration of the request, ensuring consistent localization behavior across Avo's interface.
This implementation uses `I18n.with_locale` to set the desired locale for the duration of the request, ensuring consistent localization behavior across Avo's interface and that it won't impact the other non-Avo parts of your app.
53 changes: 53 additions & 0 deletions docs/3.0/guides/rails-authentication-scaffold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Authentication using Rails' scaffold

In essence, the [authentication scaffold](https://github.com/rails/rails/pull/52328) that Rails 8 comes with is custom authentication so we need to do a few things to ensure it's working properly with Avo.

## 1. Set the current user

The scaffold uses the `Current.user` thread-safe global to hold the current authenticated user so we need to tell Avo how to fetch them.

```ruby
# config/initializers/avo.rb
Avo.configure do |config|
# other pieces of configuration

# tell Avo how to find the current authenticated user.
config.current_user_method do
Current.user
end
end
```

## 2. Set the sign out link

The scaffold uses the `SessionsController` to sign out the user so the link should be `sessions_path`. We need to add that to Avo as well.

```ruby
# config/initializers/avo.rb
Avo.configure do |config|
# other pieces of configuration

# tell Avo how to sign out the authenticated user.
config.sign_out_path_name = :session_path
end
```

## 3. Ensure only authenticated users are allowed on Avo

Now, here comes the part which might seem unfamiliar but it's actually pretty standard.

The scaffold adds the `Authentication` concern to your `ApplicationController` which is great. We will add it to Avo's `ApplicationController` and also add the `before_action`, but instead of just appending it wil will prepend it so we can ensure it will be fired as soon as possible in the request lifecycle.

```ruby{4,7}
# app/controllers/avo/application_controller.rb
module Avo
class ApplicationController < BaseApplicationController
include Authentication
# we are prepending the action to ensure it will be fired very early on in the request lifecycle
prepend_before_action :require_authentication
end
end
```

<!-- @include: ./../common/application_controller_eject_notice.md -->

0 comments on commit 9c93837

Please sign in to comment.