Skip to content

Commit d02d706

Browse files
leastbadgitbook-bot
authored andcommitted
GitBook: [master] 4 pages modified
1 parent b814e6c commit d02d706

File tree

4 files changed

+168
-155
lines changed

4 files changed

+168
-155
lines changed

authentication.md

+149-148
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,149 @@
1-
---
2-
description: Practice safe optimism
3-
---
4-
5-
# Authentication
6-
7-
If you're just trying to bootstrap a proof-of-concept application on your local workstation, you don't technically have to worry about giving ActionCable the ability to distinguish between multiple concurrent users. However, **the moment you deploy to a host with more than one person accessing your app, you'll find that you're sharing a session and seeing other people's updates**. That isn't what most developers have in mind.
8-
9-
## Encrypted Session Cookies
10-
11-
You can use your default Rails encrypted cookie-based sessions to isolate your users into their own sessions. This works great even if your application doesn't have a login system.
12-
13-
{% code title="app/controllers/application\_controller.rb" %}
14-
```ruby
15-
class ApplicationController < ActionController::Base
16-
before_action :set_action_cable_identifier
17-
18-
private
19-
20-
def set_action_cable_identifier
21-
cookies.encrypted[:session_id] = session.id.to_s
22-
end
23-
end
24-
```
25-
{% endcode %}
26-
27-
{% code title="app/channels/application\_cable/connection.rb" %}
28-
```ruby
29-
module ApplicationCable
30-
class Connection < ActionCable::Connection::Base
31-
identified_by :session_id
32-
33-
def connect
34-
self.session_id = cookies.encrypted[:session_id]
35-
end
36-
end
37-
end
38-
```
39-
{% endcode %}
40-
41-
We need to instruct ActionCable to stream updates on a per-session basis:
42-
43-
{% code title="app/channels/optimism\_channel.rb" %}
44-
```ruby
45-
class OptimismChannel < ApplicationCable::Channel
46-
def subscribed
47-
stream_for session_id
48-
end
49-
end
50-
```
51-
{% endcode %}
52-
53-
Finally, we need to give Optimism the ability to broadcast updates to the correct channel subscription. We will override Optimism's default "OptimismChannel" with a lambda that returns the subscription identifier. You might already have other values in your initializer, or it might not yet exist at all:
54-
55-
{% code title="config/initializers/optimism.rb" %}
56-
```ruby
57-
Optimism.configure do |config|
58-
config.channel_proc = ->(context) { OptimismChannel.broadcasting_for(context.session.id) }
59-
end
60-
```
61-
{% endcode %}
62-
63-
## User-based Authentication
64-
65-
Many Rails apps use the current\_user convention or more recently, the [Current](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html) object to provide a global user context. This gives access to the user scope from _almost_ all parts of your application.
66-
67-
{% code title="app/controllers/application\_controller.rb " %}
68-
```ruby
69-
class ApplicationController < ActionController::Base
70-
before_action :set_action_cable_identifier
71-
72-
private
73-
74-
def set_action_cable_identifier
75-
cookies.encrypted[:user_id] = current_user&.id
76-
end
77-
end
78-
```
79-
{% endcode %}
80-
81-
{% code title="app/channels/application\_cable/connection.rb " %}
82-
```ruby
83-
module ApplicationCable
84-
class Connection < ActionCable::Connection::Base
85-
identified_by :current_user
86-
87-
def connect
88-
user_id = cookies.encrypted[:user_id]
89-
return reject_unauthorized_connection if user_id.nil?
90-
user = User.find_by(id: user_id)
91-
return reject_unauthorized_connection if user.nil?
92-
self.current_user = user
93-
end
94-
end
95-
end
96-
```
97-
{% endcode %}
98-
99-
We need to instruct ActionCable to stream updates on a per-session basis:
100-
101-
{% code title="app/channels/optimism\_channel.rb" %}
102-
```ruby
103-
class OptimismChannel < ApplicationCable::Channel
104-
def subscribed
105-
stream_for current_user
106-
end
107-
end
108-
```
109-
{% endcode %}
110-
111-
Finally, we need to give Optimism the ability to broadcast updates to the correct channel subscription. We will override Optimism's default "OptimismChannel" with a lambda that returns the subscription identifier. You might already have other values in your initializer, or it might not yet exist at all:
112-
113-
{% code title="config/initializers/optimism.rb" %}
114-
```ruby
115-
Optimism.configure do |config|
116-
config.channel_proc = ->(context) { OptimismChannel.broadcasting_for(context.current_user) }
117-
end
118-
```
119-
{% endcode %}
120-
121-
## Devise-based Authentication
122-
123-
If you're using the versatile [Devise](https://github.com/plataformatec/devise) authentication library, your configuration is _identical_ to the User-Based Authentication above, **except** for how ActionCable looks up a user:
124-
125-
{% code title="app/channels/application\_cable/connection.rb" %}
126-
```ruby
127-
module ApplicationCable
128-
class Connection < ActionCable::Connection::Base
129-
identified_by :current_user
130-
131-
def connect
132-
self.current_user = find_verified_user
133-
end
134-
135-
protected
136-
137-
def find_verified_user
138-
if current_user = env["warden"].user
139-
current_user
140-
else
141-
reject_unauthorized_connection
142-
end
143-
end
144-
end
145-
end
146-
```
147-
{% endcode %}
148-
1+
---
2+
description: Practice safe optimism
3+
---
4+
5+
# Authentication
6+
7+
If you're just trying to bootstrap a proof-of-concept application on your local workstation, you don't technically have to worry about giving ActionCable the ability to distinguish between multiple concurrent users. However, **the moment you deploy to a host with more than one person accessing your app, you'll find that you're sharing a session and seeing other people's updates**. That isn't what most developers have in mind.
8+
9+
## Encrypted Session Cookies
10+
11+
You can use your default Rails encrypted cookie-based sessions to isolate your users into their own sessions. This works great even if your application doesn't have a login system.
12+
13+
{% code title="app/controllers/application\_controller.rb" %}
14+
```ruby
15+
class ApplicationController < ActionController::Base
16+
before_action :set_action_cable_identifier
17+
18+
private
19+
20+
def set_action_cable_identifier
21+
cookies.encrypted[:session_id] = session.id.to_s
22+
end
23+
end
24+
```
25+
{% endcode %}
26+
27+
{% code title="app/channels/application\_cable/connection.rb" %}
28+
```ruby
29+
module ApplicationCable
30+
class Connection < ActionCable::Connection::Base
31+
identified_by :session_id
32+
33+
def connect
34+
self.session_id = cookies.encrypted[:session_id]
35+
end
36+
end
37+
end
38+
```
39+
{% endcode %}
40+
41+
We need to instruct ActionCable to stream updates on a per-session basis:
42+
43+
{% code title="app/channels/optimism_channel.rb" %}
44+
```ruby
45+
class OptimismChannel < ApplicationCable::Channel
46+
def subscribed
47+
stream_for session_id
48+
end
49+
end
50+
```
51+
{% endcode %}
52+
53+
Finally, we need to give Optimism the ability to broadcast updates to the correct channel subscription. We will override Optimism's default "OptimismChannel" with a lambda that returns the subscription identifier. You might already have other values in your initializer, or it might not yet exist at all:
54+
55+
{% code title="config/initializers/optimism.rb" %}
56+
```ruby
57+
Optimism.configure do |config|
58+
config.channel = ->(context) { OptimismChannel.broadcasting_for(context.session.id) }
59+
end
60+
```
61+
{% endcode %}
62+
63+
## User-based Authentication
64+
65+
Many Rails apps use the current\_user convention or more recently, the [Current](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html) object to provide a global user context. This gives access to the user scope from _almost_ all parts of your application.
66+
67+
{% code title="app/controllers/application\_controller.rb " %}
68+
```ruby
69+
class ApplicationController < ActionController::Base
70+
before_action :set_action_cable_identifier
71+
72+
private
73+
74+
def set_action_cable_identifier
75+
cookies.encrypted[:user_id] = current_user&.id
76+
end
77+
end
78+
```
79+
{% endcode %}
80+
81+
{% code title="app/channels/application\_cable/connection.rb " %}
82+
```ruby
83+
module ApplicationCable
84+
class Connection < ActionCable::Connection::Base
85+
identified_by :current_user
86+
87+
def connect
88+
user_id = cookies.encrypted[:user_id]
89+
return reject_unauthorized_connection if user_id.nil?
90+
user = User.find_by(id: user_id)
91+
return reject_unauthorized_connection if user.nil?
92+
self.current_user = user
93+
end
94+
end
95+
end
96+
```
97+
{% endcode %}
98+
99+
We need to instruct ActionCable to stream updates on a per-session basis:
100+
101+
{% code title="app/channels/optimism_channel.rb" %}
102+
```ruby
103+
class OptimismChannel < ApplicationCable::Channel
104+
def subscribed
105+
stream_for current_user
106+
end
107+
end
108+
```
109+
{% endcode %}
110+
111+
Finally, we need to give Optimism the ability to broadcast updates to the correct channel subscription. We will override Optimism's default "OptimismChannel" with a lambda that returns the subscription identifier. You might already have other values in your initializer, or it might not yet exist at all:
112+
113+
{% code title="config/initializers/optimism.rb" %}
114+
```ruby
115+
Optimism.configure do |config|
116+
config.channel = ->(context) { OptimismChannel.broadcasting_for(context.current_user) }
117+
end
118+
```
119+
{% endcode %}
120+
121+
## Devise-based Authentication
122+
123+
If you're using the versatile [Devise](https://github.com/plataformatec/devise) authentication library, your configuration is *identical* to the User-Based Authentication above, **except** for how ActionCable looks up a user:
124+
125+
{% code title="app/channels/application\_cable/connection.rb" %}
126+
```ruby
127+
module ApplicationCable
128+
class Connection < ActionCable::Connection::Base
129+
identified_by :current_user
130+
131+
def connect
132+
self.current_user = find_verified_user
133+
end
134+
135+
protected
136+
137+
def find_verified_user
138+
if current_user = env["warden"].user
139+
current_user
140+
else
141+
reject_unauthorized_connection
142+
end
143+
end
144+
end
145+
end
146+
```
147+
{% endcode %}
148+
149+

reference.md

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ else
2121
end
2222
```
2323

24+
25+
2426
## Form Builder Helpers
2527

2628
### container\_for\(attribute, \*\*options, &block\)
@@ -39,6 +41,8 @@ Call this helper to create a `div` that will wrap your input element along with
3941
<% end %>
4042
```
4143

44+
45+
4246
### container\_id\_for\(attribute\)
4347

4448
**attribute**: Symbol identifying the the model attribute to use
@@ -51,6 +55,8 @@ Returns the id required for a container to wrap your input elements and receive
5155
<blockquote id="<%= form.container_id_for :name %>"></blockquote>
5256
```
5357

58+
59+
5460
### error\_for\(attribute, \*\*options\)
5561

5662
**attribute**: Symbol identifying the the model attribute to use
@@ -64,6 +70,8 @@ Call this helper to create a `span` that you place adjacent to your your input e
6470
<%= form.error_for :name, class: "d-none text-danger small form-group" %>
6571
```
6672

73+
74+
6775
### error\_id\_for\(attribute\)
6876

6977
**attribute**: Symbol identifying the the model attribute to use
@@ -74,6 +82,8 @@ Returns the id required for a container to receive validation error text. Use it
7482
<blockquote id="<%= form.error_id_for :name %>"></blockquote>
7583
```
7684

85+
86+
7787
![](.gitbook/assets/master_plan.svg)
7888

7989
## Initializer
@@ -123,6 +133,8 @@ end
123133

124134
**submit\_selector**: This is the pattern from which Submit button id CSS selectors will be constructed. You probably shouldn't change this.
125135

136+
137+
126138
## Events
127139

128140
If you set the `emit_events` property to true in your initializer, Optimism will emit DOM events in response to validation errors. This can happen in addition to or instead of CSS and text updates. This is a great alternative for complicated integrations where you have legacy components which need to be notified of error conditions on the backend.

setup.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ description: Form validations in five minutes or it's free
44

55
# Setup
66

7-
## Setup
8-
97
Optimism has a relatively small number of dependencies, but it does assume that it's being run in a Rails project with ActionCable configured for the environments you intend to operate in. You can easily install Optimism to new and existing Rails projects.
108

119
```bash
@@ -20,7 +18,7 @@ The terminal commands above will ensure that Optimism is installed. It creates t
2018

2119
![](.gitbook/assets/setup.svg)
2220

23-
## Authentication
21+
# Authentication
2422

2523
{% hint style="info" %}
2624
If you're just experimenting with Optimism or trying to bootstrap a proof-of-concept application on your local workstation, you can actually skip this section until you're planning to deploy.
@@ -30,11 +28,11 @@ Out of the box, ActionCable doesn't give Optimism the ability to distinguish bet
3028

3129
**If you deploy to a host with more than one person accessing your app, you'll find that you're sharing a session and seeing other people's updates.** That isn't what most developers have in mind!
3230

33-
When the time comes, it's easy to configure your application to support authenticating users by their Rails session or current\_user scope. Just check out the Authentication page and choose your own adventure.
31+
When the time comes, it's easy to configure your application to support authenticating users by their Rails session or current_user scope. Just check out the Authentication page and choose your own adventure.
3432

3533
{% page-ref page="authentication.md" %}
3634

37-
## Logging
35+
# Logging
3836

3937
In the default _debug_ log level, ActionCable emits particularly verbose log messages. You can optionally discard everything but exceptions by switching to the _warn_ log level, as is common in development environments:
4038

@@ -45,7 +43,7 @@ config.log_level = :warn
4543
```
4644
{% endcode %}
4745

48-
## Troubleshooting
46+
# Troubleshooting
4947

5048
{% hint style="info" %}
5149
If _something_ goes wrong, it's often because of the **spring** gem. You can test this by temporarily setting the `DISABLE_SPRING=1` environment variable and restarting your server.
@@ -57,3 +55,5 @@ To remove **spring** forever, here is the process we recommend:
5755
3. `bin/spring binstub -remove -all`
5856
{% endhint %}
5957

58+
59+

0 commit comments

Comments
 (0)