diff --git a/app/models/concerns/pubsubable.rb b/app/models/concerns/pubsubable.rb index 7da99ea14..bbdef5100 100644 --- a/app/models/concerns/pubsubable.rb +++ b/app/models/concerns/pubsubable.rb @@ -6,6 +6,16 @@ module Pubsubable included do # Used by the actionCable/PubSub Service we use for real time communications has_secure_token :pubsub_token + before_save :rotate_pubsub_token + end + + def rotate_pubsub_token + # ATM we are only rotating the token if the user is changing their password + return unless is_a?(User) + + # Using the class method to avoid the extra Save + # TODO: Should we do this on signin ? + self.pubsub_token = self.class.generate_unique_secure_token if will_save_change_to_encrypted_password? end def pubsub_token diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 7bae381ac..f38b3db0b 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -34,6 +34,22 @@ RSpec.describe User do it { expect(user.pubsub_token).not_to be_nil } it { expect(user.saved_changes.keys).not_to eq('pubsub_token') } + + context 'rotates the pubsub_token' do + it 'changes the pubsub_token when password changes' do + pubsub_token = user.pubsub_token + user.password = Faker::Internet.password(special_characters: true) + user.save! + expect(user.pubsub_token).not_to eq(pubsub_token) + end + + it 'will not change pubsub_token when other attributes change' do + pubsub_token = user.pubsub_token + user.name = Faker::Name.name + user.save! + expect(user.pubsub_token).to eq(pubsub_token) + end + end end describe 'hmac_identifier' do