Reputation: 131
I'm trying to stop ActionCable from continuously checking for users that are not logged into the server. I deleted all users in my test environment to check if this issue would persist, but it shows no sign of ending, even after I added a conditional statement to the JS file to check for the current_user's id. How can I finally bring an end to ActionCable attempting to connect users that don't exist or aren't logged in? Btw, I'm using JQuery3 and Rails 5.
Console Log
Started GET "/cable" for 127.0.0.1 at 2018-02-27 00:11:41 -0500
(1.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-02-27 00:11:42 -0500
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
User Load (2.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT $1 [["LIMIT", 1]]
An unauthorized connection attempt was rejected
Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-02-27 00:11:42 -0500
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-02-27 00:11:42 -0500
Started GET "/cable" for 127.0.0.1 at 2018-02-27 00:12:09 -0500
connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.username
end
protected
def find_verified_user
verified_user = User.find_by(id: cookies.signed['user.id'])
if verified_user && cookies.signed['user.expires_at'] > Time.now
verified_user
else
reject_unauthorized_connection
end
end
end
end
cable.js
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
chatroom.js
$(document).on('turbolinks:load', function () {
if ($("meta[name='current-user']").length > 0) {
(function () {
App.chatrooms = App.cable.subscriptions.create("ChatroomsChannel", {
connected: function () {
},
disconnected: function () {
},
received: function (data) {
var active_chatroom;
active_chatroom = $("[data-behavior='messages'][data-chatroom-id='" + data.chatroom_id + "']");
if (active_chatroom.length > 0) {
if (document.hidden) {
if ($(".strike").length === 0) {
active_chatroom.append("<div class='strike'><span>Unread Messages</span></div>");
}
if (Notification.permission === "granted") {
new Notification(data.username, {
body: data.body
});
}
} else {
App.last_read.update(data.chatroom_id);
}
return active_chatroom.append("<div class='media message'> <div class='media-body'> <h5 class='mt-0 message-username-pos'>" + data.username + "</h5> <p>" + data.body + "</p></div></div>");
} else {
return $("[data-behavior='chatroom-link'][data-chatroom-id='" + data.chatroom_id + "']").css("font-weight", "bold");
}
},
send_message: function (chatroom_id, message) {
return this.perform("send_message", {
chatroom_id: chatroom_id,
body: message
});
}
});
}).call(this);
}
});
last_read.js
$(document).on('turbolinks:load', function () {
if ($("meta[name='current-user']").length > 0) {
(function () {
App.last_read = App.cable.subscriptions.create("LastReadChannel", {
connected: function () {
},
disconnected: function () {
},
received: function (data) {
},
update: function (chatroom_id) {
return this.perform("update", {
chatroom_id: chatroom_id
});
}
});
}).call(this);
}
});
application.html.erb
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test App</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js' %>
<%= javascript_include_tag 'https://js.stripe.com/v3/' %>
<%= favicon_link_tag 'favicon.ico' %>
<% if user_signed_in? %>
<%= tag :meta, name: 'current-user', data: {id: current_user.id} %>
<% end %>
</head>
<body>
</body>
</html>
warden_hooks.rb
Warden::Manager.after_set_user do |user,auth,opts|
scope = opts[:scope]
auth.cookies.signed["#{scope}.id"] = user.id
auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
end
Warden::Manager.before_logout do |user, auth, opts|
scope = opts[:scope]
auth.cookies.signed["#{scope}.id"] = nil
auth.cookies.signed["#{scope}.expires_at"] = nil
end
Upvotes: 1
Views: 2217
Reputation: 131
To solve the problem of constant pinging by ActionCable, you must add a meta data checker inside of cable.js like below
$(document).on("turbolinks:load", function () {
if ($("meta[name='current-user']").length > 0) {
App.chatrooms = App.cable.subscriptions.create("ChatroomsChannel", {
...
});
} else if(App.chatrooms) {
App.chatrooms.unsubscribe();
delete App.chatrooms;
}
});
Upvotes: 1
Reputation: 3641
I am not sure that I understood your question. However connection is initiated here:
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
So if you don't want to connect you could add the check here.
Upvotes: 1