about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2017-06-25 16:54:30 +0200
committerGitHub <noreply@github.com>2017-06-25 16:54:30 +0200
commitf7301bd5b94d3033b5dbb9ff65dd1ed8ac825ce5 (patch)
treeddc52c8b89c84ee825d451cc50a6946d7d77b2bb /app
parent099a3b4eaccc37338eda9f45fc26991ea7115200 (diff)
Add overview of active sessions (#3929)
* Add overview of active sessions

* Better display of browser/platform name

* Improve how browser information is stored and displayed for sessions overview

* Fix test
Diffstat (limited to 'app')
-rw-r--r--app/controllers/auth/registrations_controller.rb5
-rw-r--r--app/helpers/settings_helper.rb12
-rw-r--r--app/javascript/styles/tables.scss12
-rw-r--r--app/models/session_activation.rb48
-rw-r--r--app/models/user.rb6
-rw-r--r--app/views/auth/registrations/_sessions.html.haml23
-rw-r--r--app/views/auth/registrations/edit.html.haml4
7 files changed, 93 insertions, 17 deletions
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index d385c08e1..60ace04d7 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -5,6 +5,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 
   before_action :check_enabled_registrations, only: [:new, :create]
   before_action :configure_sign_up_params, only: [:create]
+  before_action :set_sessions, only: [:edit, :update]
 
   def destroy
     not_found
@@ -41,4 +42,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
   def determine_layout
     %w(edit update).include?(action_name) ? 'admin' : 'auth'
   end
+
+  def set_sessions
+    @sessions = current_user.session_activations
+  end
 end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index 172ef33ca..847eff2e7 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -41,4 +41,16 @@ module SettingsHelper
   def hash_to_object(hash)
     HashObject.new(hash)
   end
+
+  def session_device_icon(session)
+    device = session.detection.device
+
+    if device.mobile?
+      'mobile'
+    elsif device.tablet?
+      'tablet'
+    else
+      'desktop'
+    end
+  end
 end
diff --git a/app/javascript/styles/tables.scss b/app/javascript/styles/tables.scss
index f7def8cf3..6e54c59c0 100644
--- a/app/javascript/styles/tables.scss
+++ b/app/javascript/styles/tables.scss
@@ -42,6 +42,18 @@
   strong {
     font-weight: 500;
   }
+
+  &.inline-table {
+    td,
+    th {
+      padding: 8px 0;
+    }
+
+    & > tbody > tr:nth-child(odd) > td,
+    & > tbody > tr:nth-child(odd) > th {
+      background: transparent;
+    }
+  }
 }
 
 samp {
diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb
index 71e9f023c..75339b5f7 100644
--- a/app/models/session_activation.rb
+++ b/app/models/session_activation.rb
@@ -8,31 +8,49 @@
 #  session_id :string           not null
 #  created_at :datetime         not null
 #  updated_at :datetime         not null
+#  user_agent :string           default(""), not null
+#  ip         :inet
 #
 
 class SessionActivation < ApplicationRecord
-  LIMIT = Rails.configuration.x.max_session_activations
-
-  def self.active?(id)
-    id && where(session_id: id).exists?
+  def detection
+    @detection ||= Browser.new(user_agent)
   end
 
-  def self.activate(id)
-    activation = create!(session_id: id)
-    purge_old
-    activation
+  def browser
+    detection.id
   end
 
-  def self.deactivate(id)
-    return unless id
-    where(session_id: id).destroy_all
+  def platform
+    detection.platform.id
   end
 
-  def self.purge_old
-    order('created_at desc').offset(LIMIT).destroy_all
+  before_save do
+    self.user_agent = '' if user_agent.nil?
   end
 
-  def self.exclusive(id)
-    where('session_id != ?', id).destroy_all
+  class << self
+    def active?(id)
+      id && where(session_id: id).exists?
+    end
+
+    def activate(options = {})
+      activation = create!(options)
+      purge_old
+      activation
+    end
+
+    def deactivate(id)
+      return unless id
+      where(session_id: id).destroy_all
+    end
+
+    def purge_old
+      order('created_at desc').offset(Rails.configuration.x.max_session_activations).destroy_all
+    end
+
+    def exclusive(id)
+      where('session_id != ?', id).destroy_all
+    end
   end
 end
diff --git a/app/models/user.rb b/app/models/user.rb
index fccf1089b..c31a0c644 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -91,8 +91,10 @@ class User < ApplicationRecord
     settings.auto_play_gif
   end
 
-  def activate_session
-    session_activations.activate(SecureRandom.hex).session_id
+  def activate_session(request)
+    session_activations.activate(session_id: SecureRandom.hex,
+                                 user_agent: request.user_agent,
+                                 ip: request.ip).session_id
   end
 
   def exclusive_session(id)
diff --git a/app/views/auth/registrations/_sessions.html.haml b/app/views/auth/registrations/_sessions.html.haml
new file mode 100644
index 000000000..11c0d4e31
--- /dev/null
+++ b/app/views/auth/registrations/_sessions.html.haml
@@ -0,0 +1,23 @@
+%h6= t 'sessions.title'
+%p.muted-hint= t 'sessions.explanation'
+
+%table.table.inline-table
+  %thead
+    %tr
+      %th= t 'sessions.browser'
+      %th= t 'sessions.ip'
+      %th= t 'sessions.activity'
+  %tbody
+    - @sessions.each do |session|
+      %tr
+        %td
+          %span{ title: session.user_agent }= fa_icon session_device_icon(session)
+          = ' '
+          = t 'sessions.description', browser: t("sessions.browsers.#{session.browser}"), platform: t("sessions.platforms.#{session.platform}")
+        %td
+          %samp= session.ip
+        %td
+          - if request.session['auth_id'] == session.session_id
+            = t 'sessions.current_session'
+          - else
+            %time.time-ago{ datetime: session.updated_at.iso8601, title: l(session.updated_at) }= l(session.updated_at)
diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml
index 38d4349cb..fbc8d017b 100644
--- a/app/views/auth/registrations/edit.html.haml
+++ b/app/views/auth/registrations/edit.html.haml
@@ -12,6 +12,10 @@
   .actions
     = f.button :button, t('generic.save_changes'), type: :submit
 
+%hr/
+
+= render 'sessions'
+
 - if open_deletion?
   %hr/