session_countdown 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|