session-check 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01760d88d12d072557a3850b09592a39c0d402d18cdd5b4d48193d3c3780a15c
4
- data.tar.gz: 1809267c20cc72d9927cacf7521f1dd025d7b7861e0e10f68fc8579191cce167
3
+ metadata.gz: 75caa11e24f6f750c18ee096a9d39ba72c86713e74836d479885625f2d72d262
4
+ data.tar.gz: 6eaa656c8f9aac3a935483393aa4835e9286d6e96fe87446477c238ab575cd75
5
5
  SHA512:
6
- metadata.gz: e39eb03da722898d4a7d6e8c1618aceadbb643e53a84e549f23651919d5ddc30aab9cf7f3ba84cc8f2ded1950e963c8bf46245b64e0312d4883a8993f478ae83
7
- data.tar.gz: 70559131eee0435399dfc94002a6456924bcdb08a8401ed12037ce4098e247f25422457eb72099760697ccecb7f481d4da8866034d41eaad86b39a93d31446ee
6
+ metadata.gz: 5375698f650fb0fccf732a4a7c735e4e9248084a6b3d2f3126d49be384116cfb3b66751bbc549f137c6f6f3971a99d35dc2fbc641ce611136aff0718f073a67e
7
+ data.tar.gz: 9bc95912cb792257bd9449702a0092d29331b5be003b191061b2b7b8b3e62add21d1bef242513ac7f0b8409ef5a6db2bfc2752bd099bc25a04149b6d983b33bc
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # Session Check
1
+ Session Check
2
+ =========
3
+
4
+ [![Gem Version](https://img.shields.io/gem/v/session-check?color=green)](https://rubygems.org/gems/session-check)
5
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
2
6
 
3
7
  A gem that returns you to your application's sign in page when your Devise session expires.
4
8
 
@@ -72,8 +76,22 @@ server-side ping endpoint and the initial JS `should_session_check` value. All o
72
76
 
73
77
  If `session_active_proc` is not set the gem uses the default Devise behaviour, computing remaining session time from the Warden last-request timestamp.
74
78
 
79
+ # Development
80
+
81
+ The client-side JS lives in `app/assets/javascripts/session_check.js` as plain, dependency-free JS
82
+ so it can be unit tested in isolation. The `_session_check` partial only passes configuration in via
83
+ `window.SessionCheckConfig` and inlines this file's contents — no asset pipeline setup is required
84
+ by consuming applications.
85
+
86
+ JS unit tests (Jest + jsdom) live under `spec/javascript` and are scoped to this repo only —
87
+ `package.json`/`node_modules` are dev-only and excluded from the published gem. Run them with:
88
+
89
+ npm install
90
+ npm test
91
+
75
92
  # Changelog
76
93
 
94
+ Version 2.0.1 : Fix session-expiry check drifting in background/inactive tabs
77
95
  Version 2.0.0 : **Breaking change** — default Devise behaviour now correctly computes remaining session time from the Warden last-request timestamp rather than always returning the full timeout. `current_user` is no longer exposed to the session check partial. Added `session_active_proc` configuration option for non-Devise session support. Fixed setTimeout multiplier (5000 → 1000) so session checks fire at the correct interval. Bump your dependency to `>= 2.0.0`.
78
96
  Version 1.1.0 : Added optional nonce
79
97
  Version 0.2.1 : Added explicit reference to Devise (which is required)
@@ -0,0 +1,125 @@
1
+ /* eslint-disable no-var */
2
+ // This file is plain JS (no ERB) so it can be loaded directly in unit tests
3
+ // (see spec/javascript) as well as served as-is by the Rails asset pipeline.
4
+ //
5
+ // Configuration is supplied at runtime via a `window.SessionCheckConfig`
6
+ // object assigned by app/views/_session_check.html.erb, e.g.:
7
+ //
8
+ // window.SessionCheckConfig = {
9
+ // should_session_check: true,
10
+ // check_every_s: 30,
11
+ // session_time: 3600,
12
+ // logged_out_url: '/users/sign_in',
13
+ // reset_counter_on_ajax: true
14
+ // };
15
+ (function (global) {
16
+ 'use strict';
17
+
18
+ // `createSessionCheck` builds a fresh instance of the session-check
19
+ // behaviour. `deps` allows tests to inject fakes for jQuery, the clock and
20
+ // timer functions instead of relying on browser globals.
21
+ function createSessionCheck(config, deps) {
22
+ config = config || {};
23
+ deps = deps || {};
24
+
25
+ var $ = deps.$ || global.$;
26
+ var now = deps.now || function () {
27
+ return Date.now();
28
+ };
29
+ var setTimeoutFn = deps.setTimeout || global.setTimeout;
30
+ var documentRef = deps.document || global.document;
31
+ var locationRef = deps.location || global;
32
+
33
+ var check_every_s = config.check_every_s;
34
+ var session_time = config.session_time;
35
+ var check_every_ms = check_every_s * 1000;
36
+ var min_check_interval_ms = 5 * 1000; // don't re-check more than once per 5s
37
+ var session_expires_at = now() + session_time * 1000; // absolute timestamp, not a countdown
38
+ var last_check_at = now();
39
+
40
+ var SessionCheck = {
41
+ should_session_check: !!config.should_session_check
42
+ };
43
+
44
+ var force_sign_in = function () {
45
+ locationRef.location = config.logged_out_url;
46
+ };
47
+
48
+ var check_session_with_server = function () {
49
+ last_check_at = now();
50
+ $.get('/session_check/time_to_session_expiry')
51
+ .done(function (d) {
52
+ if (!d.session_exists) {
53
+ force_sign_in();
54
+ } else {
55
+ session_expires_at = now() + d.session_expires_in * 1000;
56
+ }
57
+ })
58
+ .fail(force_sign_in);
59
+ };
60
+
61
+ var session_check = function () {
62
+ if (SessionCheck.should_session_check && now() >= session_expires_at) {
63
+ check_session_with_server();
64
+ }
65
+ setTimeoutFn(session_check, check_every_ms);
66
+ };
67
+
68
+ var on_visibility_change = function () {
69
+ if (documentRef.visibilityState === 'visible' && SessionCheck.should_session_check) {
70
+ if (now() - last_check_at > min_check_interval_ms) {
71
+ check_session_with_server();
72
+ }
73
+ }
74
+ };
75
+
76
+ var on_ajax_complete = function () {
77
+ session_expires_at = now() + session_time * 1000;
78
+ last_check_at = now();
79
+ };
80
+
81
+ var start = function () {
82
+ setTimeoutFn(session_check, check_every_ms);
83
+
84
+ // Whenever the tab becomes visible again, go straight to the server
85
+ // for ground truth instead of trusting local timers/clock math.
86
+ // Debounced so rapid tab-switching doesn't spam the endpoint.
87
+ documentRef.addEventListener('visibilitychange', on_visibility_change);
88
+
89
+ if (config.reset_counter_on_ajax) {
90
+ $.ajaxSetup({
91
+ complete: on_ajax_complete
92
+ });
93
+ }
94
+ };
95
+
96
+ return {
97
+ SessionCheck: SessionCheck,
98
+ start: start,
99
+ // Exposed for unit testing only.
100
+ _internal: {
101
+ force_sign_in: force_sign_in,
102
+ check_session_with_server: check_session_with_server,
103
+ session_check: session_check,
104
+ on_visibility_change: on_visibility_change,
105
+ on_ajax_complete: on_ajax_complete,
106
+ get session_expires_at() {
107
+ return session_expires_at;
108
+ },
109
+ get last_check_at() {
110
+ return last_check_at;
111
+ }
112
+ }
113
+ };
114
+ }
115
+
116
+ if (typeof module !== 'undefined' && module.exports) {
117
+ module.exports = createSessionCheck;
118
+ }
119
+
120
+ if (typeof global.SessionCheckConfig !== 'undefined') {
121
+ var instance = createSessionCheck(global.SessionCheckConfig);
122
+ global.SessionCheck = instance.SessionCheck;
123
+ instance.start();
124
+ }
125
+ })(typeof window !== 'undefined' ? window : this);
@@ -1,35 +1,12 @@
1
1
  <script<% if local_assigns[:nonce] %> nonce="<%= nonce %>"<% end %>>
2
- var SessionCheck = {
3
- should_session_check: <%= session_active %>
4
- };
5
- (function () {
6
- var check_every_s = <%= check_every_s %>;
7
- var session_time_left = <%= session_time %>;
8
- var force_sign_in = function () {
9
- window.location = '<%= logged_out_url %>';
10
- };
11
- var session_check = function () {
12
- session_time_left = session_time_left - check_every_s;
13
- if (SessionCheck.should_session_check && session_time_left < 0) {
14
- $.get('/session_check/time_to_session_expiry')
15
- .done(function (d) {
16
- if (!d.session_exists) {
17
- force_sign_in();
18
- } else {
19
- session_time_left = d.session_expires_in;
20
- }
21
- })
22
- .fail(force_sign_in);
23
- }
24
- setTimeout(session_check, check_every_s * 1000);
25
- };
26
- setTimeout(session_check, check_every_s * 1000);
27
- <% if reset_counter_on_ajax %>
28
- $.ajaxSetup({
29
- complete: function (xhr) {
30
- session_time_left = <%= session_time %>;
31
- }
32
- });
33
- <% end %>
34
- }());
2
+ window.SessionCheckConfig = {
3
+ should_session_check: <%= session_active %>,
4
+ check_every_s: <%= check_every_s %>,
5
+ session_time: <%= session_time %>,
6
+ logged_out_url: <%= raw ERB::Util.json_escape(logged_out_url.to_json) %>,
7
+ reset_counter_on_ajax: <%= !!reset_counter_on_ajax %>
8
+ };
9
+ </script>
10
+ <script<% if local_assigns[:nonce] %> nonce="<%= nonce %>"<% end %>>
11
+ <%= raw File.read(Session::Check::Engine.root.join('app', 'assets', 'javascripts', 'session_check.js')) %>
35
12
  </script>
data/config/routes.rb CHANGED
@@ -1,5 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Draw directly into the host application's routes (rather than
4
+ # `Session::Check::Engine.routes.draw`) so the endpoint is auto-wired for any
5
+ # consuming app without requiring an explicit `mount Session::Check::Engine`,
6
+ # matching the README usage (`<%= session_check %>` only).
3
7
  Rails.application.routes.draw do
4
- get 'session_check/time_to_session_expiry', to: 'session/check/session_checks#time_to_session_expiry'
8
+ get 'session_check/time_to_session_expiry',
9
+ to: 'session/check/session_checks#time_to_session_expiry',
10
+ format: :json,
11
+ defaults: { format: :json }
5
12
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Session
4
4
  module Check
5
- VERSION = '2.0.0'
5
+ VERSION = '2.0.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: session-check
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Lascelles
@@ -128,6 +128,7 @@ extensions: []
128
128
  extra_rdoc_files: []
129
129
  files:
130
130
  - README.md
131
+ - app/assets/javascripts/session_check.js
131
132
  - app/controllers/session/check/session_checks_controller.rb
132
133
  - app/helpers/session/check/session_check_helper.rb
133
134
  - app/views/_session_check.html.erb