session_countdown 0.1.0 → 0.2.0
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.
- data/README.html +191 -0
- data/README.rdoc +17 -15
- data/VERSION +1 -1
- data/lib/session_countdown.rb +6 -6
- data/session_countdown.gemspec +3 -2
- data/test/common/test_controller_test.rb +22 -4
- data/test/rails2x_root/test/functional/test_controller_test.rb +22 -4
- data/test/rails3x_root/test/functional/test_controller_test.rb +22 -4
- metadata +6 -4
data/README.html
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
|
2
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<title>RDoc Documentation</title>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<h2>File: README.rdoc</h2>
|
10
|
+
<table>
|
11
|
+
<tr><td>Path:</td><td>README.rdoc</td></tr>
|
12
|
+
<tr><td>Modified:</td><td>Fri Aug 06 06:53:51 -0400 2010</td></tr>
|
13
|
+
</table>
|
14
|
+
|
15
|
+
<h1>session_countdown</h1>
|
16
|
+
<p>
|
17
|
+
A Ruby on Rails plugin that puts a countdown timer on the session object.
|
18
|
+
</p>
|
19
|
+
<pre>
|
20
|
+
session.countdown_run(30.minutes)
|
21
|
+
session.countdown_running? # => true
|
22
|
+
session.countdown_expire
|
23
|
+
session.countdown_running? # => false
|
24
|
+
session.countdown_expired? # => true
|
25
|
+
session.countdown_restart
|
26
|
+
session.countdown_running? # => true
|
27
|
+
</pre>
|
28
|
+
<h3>But why?!?</h3>
|
29
|
+
<p>
|
30
|
+
Sometimes I need to build my own custom rails authentication systems rather
|
31
|
+
than use plugins such as Authlogic, Devise or restful_authentication.
|
32
|
+
</p>
|
33
|
+
<p>
|
34
|
+
There is always a "timer" in my custom authentication
|
35
|
+
contraptions, and there is always a session object lurking when I‘m
|
36
|
+
dealing with authentication stuff, so why not combine the two?
|
37
|
+
</p>
|
38
|
+
<h2>API</h2>
|
39
|
+
<p>
|
40
|
+
<em>Note that countdown_expire(), countdown_restart() and countdown_count()
|
41
|
+
will throw a NoCountdown exception if called on a non-existent countdown
|
42
|
+
timer.</em>
|
43
|
+
</p>
|
44
|
+
<p>
|
45
|
+
Start a countdown timer
|
46
|
+
</p>
|
47
|
+
<pre>
|
48
|
+
session.countdown_run(seconds, name = :default)
|
49
|
+
</pre>
|
50
|
+
<p>
|
51
|
+
<em>You can have multiple countdown timers if you name them. The default
|
52
|
+
countdown timer is named "default".</em>
|
53
|
+
</p>
|
54
|
+
<p>
|
55
|
+
Check if a countdown timer exists and is currently running
|
56
|
+
</p>
|
57
|
+
<pre>
|
58
|
+
session.countdown_running?(name = :default)
|
59
|
+
</pre>
|
60
|
+
<p>
|
61
|
+
Expire early (i.e. logout)
|
62
|
+
</p>
|
63
|
+
<pre>
|
64
|
+
session.countdown_expire(name = :default)
|
65
|
+
</pre>
|
66
|
+
<p>
|
67
|
+
Restart, using the duration supplied to countdown_run
|
68
|
+
</p>
|
69
|
+
<pre>
|
70
|
+
session.countdown_restart(name = :default)
|
71
|
+
</pre>
|
72
|
+
<p>
|
73
|
+
Check if expired
|
74
|
+
</p>
|
75
|
+
<pre>
|
76
|
+
session.countdown_expired?(name = :default)
|
77
|
+
</pre>
|
78
|
+
<p>
|
79
|
+
Remaining time in seconds
|
80
|
+
</p>
|
81
|
+
<pre>
|
82
|
+
session.countdown_count(name = :default)
|
83
|
+
</pre>
|
84
|
+
<p>
|
85
|
+
Understanding timer running, expired, and never started
|
86
|
+
</p>
|
87
|
+
<pre>
|
88
|
+
countdown_running? == true # timer running
|
89
|
+
countdown_expired? == true # timer expired
|
90
|
+
countdown_running? == false && countdown_expired? == false # never ran
|
91
|
+
</pre>
|
92
|
+
<h1>Synopsis</h1>
|
93
|
+
<h3>In application_controller.rb</h3>
|
94
|
+
<pre>
|
95
|
+
before_filter :authorize
|
96
|
+
|
97
|
+
def authorize
|
98
|
+
if session.countdown_running?
|
99
|
+
session.countdown_restart # extend user's login
|
100
|
+
else
|
101
|
+
# store attempted access before rudely redirected to login screen
|
102
|
+
session[:original_uri] = request.request_uri # rails3 use request.fullpath
|
103
|
+
if session.countdown_expired?
|
104
|
+
flash[:notice] = "Login Expired"
|
105
|
+
else
|
106
|
+
flash[:notice] = "Please login"
|
107
|
+
end
|
108
|
+
redirect_to :login
|
109
|
+
end
|
110
|
+
end
|
111
|
+
</pre>
|
112
|
+
<h3>In any controller</h3>
|
113
|
+
<pre>
|
114
|
+
def login
|
115
|
+
user = User.find_by_email(params[:email)
|
116
|
+
if user && user.password_matches?(params[:password])
|
117
|
+
session.countdown_run(1.hour)
|
118
|
+
redirect_to :controller => :private
|
119
|
+
else
|
120
|
+
flash.now[:notice] = "Sorry, email/password wrong"
|
121
|
+
render :index
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
def logout
|
127
|
+
session.countdown_expire
|
128
|
+
flash[:notice] = "You are now logged out"
|
129
|
+
redirect_to :index
|
130
|
+
end
|
131
|
+
</pre>
|
132
|
+
<h3>In user model</h3>
|
133
|
+
<pre>
|
134
|
+
def before_save
|
135
|
+
if self.password_changed?
|
136
|
+
self.salt = SecureRandom.hex(10)
|
137
|
+
self.password = Digest::MD5.hexdigest(self.salt + self.password)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def password_matches?(password_to_match)
|
142
|
+
self.password == Digest::MD5.hexdigest(self.salt + password_to_match)
|
143
|
+
end
|
144
|
+
</pre>
|
145
|
+
<h3>Note: Remember me</h3>
|
146
|
+
<p>
|
147
|
+
If you want an "remember me" feature you need to do two things.
|
148
|
+
</p>
|
149
|
+
<p>
|
150
|
+
Set timer for far future when user checks "remember me"
|
151
|
+
</p>
|
152
|
+
<pre>
|
153
|
+
session.countdown_run(1.year)
|
154
|
+
</pre>
|
155
|
+
<p>
|
156
|
+
Tell rails to serve up a persistent cookie instead of session cookie,
|
157
|
+
probably in application_controller.rb
|
158
|
+
</p>
|
159
|
+
<pre>
|
160
|
+
ActionController::Base.session_options[:expire_after] = 1.year
|
161
|
+
</pre>
|
162
|
+
<h3>Persistent vs session cookies</h3>
|
163
|
+
<p>
|
164
|
+
There are two types of browser cookies: ones with expiration dates and ones
|
165
|
+
without. When a cookie doesnt have an expiration date it‘s a
|
166
|
+
<em>session</em> cookie and will be deleted when the browser quits. If the
|
167
|
+
cookie has an expiration date it‘s a <em>persistent</em> cookie
|
168
|
+
(a.k.a. domain cookie) and will be valid until that date.
|
169
|
+
</p>
|
170
|
+
<p>
|
171
|
+
"Remember me" could work fine with only session cookies, provided
|
172
|
+
the user never quits the browser, but users expect "remember me"
|
173
|
+
to never expire their login <em>and</em> to persist across browser quits.
|
174
|
+
It also makes sense to set a far future expiration date or the cookie will
|
175
|
+
eventually expire before the login does.
|
176
|
+
</p>
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
|
184
|
+
<h2>Classes</h2>
|
185
|
+
</body>
|
186
|
+
</html>
|
187
|
+
Files: 1
|
188
|
+
Classes: 0
|
189
|
+
Modules: 0
|
190
|
+
Methods: 0
|
191
|
+
Elapsed: 0.048s
|
data/README.rdoc
CHANGED
@@ -26,11 +26,10 @@ authentication stuff, so why not combine the two?
|
|
26
26
|
== API
|
27
27
|
|
28
28
|
|
29
|
-
<i>Note that
|
30
|
-
|
29
|
+
<i>Note that countdown_expire(), countdown_restart() and
|
30
|
+
countdown_count() will throw a NoCountdown exception if called on a
|
31
31
|
non-existent countdown timer.</i>
|
32
32
|
|
33
|
-
|
34
33
|
Start a countdown timer
|
35
34
|
|
36
35
|
session.countdown_run(seconds, name = :default)
|
@@ -42,7 +41,7 @@ Check if a countdown timer exists and is currently running
|
|
42
41
|
|
43
42
|
session.countdown_running?(name = :default)
|
44
43
|
|
45
|
-
Expire early
|
44
|
+
Expire early (i.e. logout)
|
46
45
|
|
47
46
|
session.countdown_expire(name = :default)
|
48
47
|
|
@@ -54,17 +53,16 @@ Check if expired
|
|
54
53
|
|
55
54
|
session.countdown_expired?(name = :default)
|
56
55
|
|
57
|
-
<i>countdown_expired? is not the reverse of countdown_running?
|
58
|
-
because only works on an existing countdown, otherwise it will throw a
|
59
|
-
NoCountdown exception. Its use will reveal only if an existing
|
60
|
-
countdown is expired. The statement !countdown_running? can't tell
|
61
|
-
you if the countdown has expired because it will return true if there
|
62
|
-
was no countdown in the first place.</i>
|
63
|
-
|
64
56
|
Remaining time in seconds
|
65
57
|
|
66
58
|
session.countdown_count(name = :default)
|
67
59
|
|
60
|
+
Understanding timer running, expired, and never started
|
61
|
+
|
62
|
+
countdown_running? == true # timer running
|
63
|
+
countdown_expired? == true # timer expired
|
64
|
+
countdown_running? == false && countdown_expired? == false # never ran
|
65
|
+
|
68
66
|
|
69
67
|
= Synopsis
|
70
68
|
|
@@ -72,13 +70,17 @@ Remaining time in seconds
|
|
72
70
|
|
73
71
|
before_filter :authorize
|
74
72
|
|
75
|
-
|
76
73
|
def authorize
|
77
74
|
if session.countdown_running?
|
78
|
-
session.countdown_restart #
|
75
|
+
session.countdown_restart # extend user's login
|
79
76
|
else
|
80
|
-
|
81
|
-
|
77
|
+
# store attempted access before rudely redirected to login screen
|
78
|
+
session[:original_uri] = request.request_uri # rails3 use request.fullpath
|
79
|
+
if session.countdown_expired?
|
80
|
+
flash[:notice] = "Login Expired"
|
81
|
+
else
|
82
|
+
flash[:notice] = "Please login"
|
83
|
+
end
|
82
84
|
redirect_to :login
|
83
85
|
end
|
84
86
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/session_countdown.rb
CHANGED
@@ -17,9 +17,13 @@ module SessionCountdown
|
|
17
17
|
self[get_zero_key(name)] && self[get_zero_key(name)] > Time.now
|
18
18
|
end
|
19
19
|
|
20
|
+
def countdown_expired?(name = @@default_name)
|
21
|
+
self[get_zero_key(name)] && ! countdown_running?(name)
|
22
|
+
end
|
23
|
+
|
20
24
|
# sanity check for existing countdown for some methods
|
21
25
|
def method_missing(method, *args)
|
22
|
-
|
26
|
+
insist_countdown_exists(*args) # reason for this method_missing()
|
23
27
|
method = "_#{method}"
|
24
28
|
respond_to?(method) ? send(method, *args) : raise(NoMethodError)
|
25
29
|
end
|
@@ -30,10 +34,6 @@ module SessionCountdown
|
|
30
34
|
self[get_zero_key(name)] = Time.now
|
31
35
|
end
|
32
36
|
|
33
|
-
def _countdown_expired?(name = @@default_name)
|
34
|
-
! countdown_running?(name)
|
35
|
-
end
|
36
|
-
|
37
37
|
def _countdown_restart(name = @@default_name)
|
38
38
|
self[get_zero_key(name)] = Time.now + self[get_zero_delta_key(name)]
|
39
39
|
end
|
@@ -55,7 +55,7 @@ module SessionCountdown
|
|
55
55
|
"session_countdown:#{name}_delta"
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
58
|
+
def insist_countdown_exists(name = @@default_name)
|
59
59
|
unless self[get_zero_key(name)]
|
60
60
|
raise NoCountdown, "no session countdown named '#{name}'"
|
61
61
|
end
|
data/session_countdown.gemspec
CHANGED
@@ -5,15 +5,16 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{session_countdown}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kevin Swope"]
|
12
|
-
s.date = %q{2010-08-
|
12
|
+
s.date = %q{2010-08-06}
|
13
13
|
s.description = %q{A Ruby on Rails plugin that puts a countdown timer on the session object}
|
14
14
|
s.email = %q{gems-kevdev@snkmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
+
"README.html",
|
17
18
|
"README.rdoc"
|
18
19
|
]
|
19
20
|
s.files = [
|
@@ -7,6 +7,7 @@ class TestControllerTest < ActionController::TestCase
|
|
7
7
|
test "single default" do
|
8
8
|
|
9
9
|
assert ! session.countdown_running?
|
10
|
+
assert ! session.countdown_expired?
|
10
11
|
|
11
12
|
session.countdown_run(1.minute)
|
12
13
|
assert session.countdown_running?
|
@@ -23,6 +24,25 @@ class TestControllerTest < ActionController::TestCase
|
|
23
24
|
|
24
25
|
end
|
25
26
|
|
27
|
+
test "truth table test" do
|
28
|
+
|
29
|
+
# with no countdown started these conditions should be met
|
30
|
+
assert ! session.countdown_running?
|
31
|
+
assert ! session.countdown_expired?
|
32
|
+
|
33
|
+
# with countdown started
|
34
|
+
session.countdown_run(1.minute)
|
35
|
+
assert session.countdown_running?
|
36
|
+
assert ! session.countdown_expired?
|
37
|
+
|
38
|
+
# with countdown expired
|
39
|
+
session.countdown_expire
|
40
|
+
assert ! session.countdown_running?
|
41
|
+
assert session.countdown_expired?
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
26
46
|
|
27
47
|
test "mixed names" do
|
28
48
|
|
@@ -98,19 +118,17 @@ class TestControllerTest < ActionController::TestCase
|
|
98
118
|
|
99
119
|
test "unstable state" do
|
100
120
|
|
101
|
-
|
102
|
-
|
121
|
+
# restart, expire and count require an existing countdown, should
|
122
|
+
# throw exception if there isn't one
|
103
123
|
|
104
124
|
assert_raise(NoCountdown) { session.countdown_expire }
|
105
125
|
assert_raise(NoCountdown) { session.countdown_restart }
|
106
|
-
assert_raise(NoCountdown) { session.countdown_expired? }
|
107
126
|
assert_raise(NoCountdown) { session.countdown_count }
|
108
127
|
|
109
128
|
## try with named countdown
|
110
129
|
|
111
130
|
assert_raise(NoCountdown) { session.countdown_expire(:admin) }
|
112
131
|
assert_raise(NoCountdown) { session.countdown_restart(:admin) }
|
113
|
-
assert_raise(NoCountdown) { session.countdown_expired?(:admin) }
|
114
132
|
assert_raise(NoCountdown) { session.countdown_count(:admin) }
|
115
133
|
|
116
134
|
end
|
@@ -7,6 +7,7 @@ class TestControllerTest < ActionController::TestCase
|
|
7
7
|
test "single default" do
|
8
8
|
|
9
9
|
assert ! session.countdown_running?
|
10
|
+
assert ! session.countdown_expired?
|
10
11
|
|
11
12
|
session.countdown_run(1.minute)
|
12
13
|
assert session.countdown_running?
|
@@ -23,6 +24,25 @@ class TestControllerTest < ActionController::TestCase
|
|
23
24
|
|
24
25
|
end
|
25
26
|
|
27
|
+
test "truth table test" do
|
28
|
+
|
29
|
+
# with no countdown started these conditions should be met
|
30
|
+
assert ! session.countdown_running?
|
31
|
+
assert ! session.countdown_expired?
|
32
|
+
|
33
|
+
# with countdown started
|
34
|
+
session.countdown_run(1.minute)
|
35
|
+
assert session.countdown_running?
|
36
|
+
assert ! session.countdown_expired?
|
37
|
+
|
38
|
+
# with countdown expired
|
39
|
+
session.countdown_expire
|
40
|
+
assert ! session.countdown_running?
|
41
|
+
assert session.countdown_expired?
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
26
46
|
|
27
47
|
test "mixed names" do
|
28
48
|
|
@@ -98,19 +118,17 @@ class TestControllerTest < ActionController::TestCase
|
|
98
118
|
|
99
119
|
test "unstable state" do
|
100
120
|
|
101
|
-
|
102
|
-
|
121
|
+
# restart, expire and count require an existing countdown, should
|
122
|
+
# throw exception if there isn't one
|
103
123
|
|
104
124
|
assert_raise(NoCountdown) { session.countdown_expire }
|
105
125
|
assert_raise(NoCountdown) { session.countdown_restart }
|
106
|
-
assert_raise(NoCountdown) { session.countdown_expired? }
|
107
126
|
assert_raise(NoCountdown) { session.countdown_count }
|
108
127
|
|
109
128
|
## try with named countdown
|
110
129
|
|
111
130
|
assert_raise(NoCountdown) { session.countdown_expire(:admin) }
|
112
131
|
assert_raise(NoCountdown) { session.countdown_restart(:admin) }
|
113
|
-
assert_raise(NoCountdown) { session.countdown_expired?(:admin) }
|
114
132
|
assert_raise(NoCountdown) { session.countdown_count(:admin) }
|
115
133
|
|
116
134
|
end
|
@@ -7,6 +7,7 @@ class TestControllerTest < ActionController::TestCase
|
|
7
7
|
test "single default" do
|
8
8
|
|
9
9
|
assert ! session.countdown_running?
|
10
|
+
assert ! session.countdown_expired?
|
10
11
|
|
11
12
|
session.countdown_run(1.minute)
|
12
13
|
assert session.countdown_running?
|
@@ -23,6 +24,25 @@ class TestControllerTest < ActionController::TestCase
|
|
23
24
|
|
24
25
|
end
|
25
26
|
|
27
|
+
test "truth table test" do
|
28
|
+
|
29
|
+
# with no countdown started these conditions should be met
|
30
|
+
assert ! session.countdown_running?
|
31
|
+
assert ! session.countdown_expired?
|
32
|
+
|
33
|
+
# with countdown started
|
34
|
+
session.countdown_run(1.minute)
|
35
|
+
assert session.countdown_running?
|
36
|
+
assert ! session.countdown_expired?
|
37
|
+
|
38
|
+
# with countdown expired
|
39
|
+
session.countdown_expire
|
40
|
+
assert ! session.countdown_running?
|
41
|
+
assert session.countdown_expired?
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
26
46
|
|
27
47
|
test "mixed names" do
|
28
48
|
|
@@ -98,19 +118,17 @@ class TestControllerTest < ActionController::TestCase
|
|
98
118
|
|
99
119
|
test "unstable state" do
|
100
120
|
|
101
|
-
|
102
|
-
|
121
|
+
# restart, expire and count require an existing countdown, should
|
122
|
+
# throw exception if there isn't one
|
103
123
|
|
104
124
|
assert_raise(NoCountdown) { session.countdown_expire }
|
105
125
|
assert_raise(NoCountdown) { session.countdown_restart }
|
106
|
-
assert_raise(NoCountdown) { session.countdown_expired? }
|
107
126
|
assert_raise(NoCountdown) { session.countdown_count }
|
108
127
|
|
109
128
|
## try with named countdown
|
110
129
|
|
111
130
|
assert_raise(NoCountdown) { session.countdown_expire(:admin) }
|
112
131
|
assert_raise(NoCountdown) { session.countdown_restart(:admin) }
|
113
|
-
assert_raise(NoCountdown) { session.countdown_expired?(:admin) }
|
114
132
|
assert_raise(NoCountdown) { session.countdown_count(:admin) }
|
115
133
|
|
116
134
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: session_countdown
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kevin Swope
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-06 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -27,6 +27,7 @@ extensions: []
|
|
27
27
|
|
28
28
|
extra_rdoc_files:
|
29
29
|
- LICENSE
|
30
|
+
- README.html
|
30
31
|
- README.rdoc
|
31
32
|
files:
|
32
33
|
- .document
|
@@ -94,6 +95,7 @@ files:
|
|
94
95
|
- test/rails3x_root/script/rails
|
95
96
|
- test/rails3x_root/test/functional/test_controller_test.rb
|
96
97
|
- test/rails3x_root/test/test_helper.rb
|
98
|
+
- README.html
|
97
99
|
has_rdoc: true
|
98
100
|
homepage: http://github.com/kswope/session_countdown
|
99
101
|
licenses: []
|