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 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? # =&gt; true
22
+ session.countdown_expire
23
+ session.countdown_running? # =&gt; false
24
+ session.countdown_expired? # =&gt; true
25
+ session.countdown_restart
26
+ session.countdown_running? # =&gt; 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 &quot;timer&quot; in my custom authentication
35
+ contraptions, and there is always a session object lurking when I&#8216;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 &quot;default&quot;.</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 &amp;&amp; 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] = &quot;Login Expired&quot;
105
+ else
106
+ flash[:notice] = &quot;Please login&quot;
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 &amp;&amp; user.password_matches?(params[:password])
117
+ session.countdown_run(1.hour)
118
+ redirect_to :controller =&gt; :private
119
+ else
120
+ flash.now[:notice] = &quot;Sorry, email/password wrong&quot;
121
+ render :index
122
+ end
123
+
124
+ end
125
+
126
+ def logout
127
+ session.countdown_expire
128
+ flash[:notice] = &quot;You are now logged out&quot;
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 &quot;remember me&quot; feature you need to do two things.
148
+ </p>
149
+ <p>
150
+ Set timer for far future when user checks &quot;remember me&quot;
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&#8216;s a
166
+ <em>session</em> cookie and will be deleted when the browser quits. If the
167
+ cookie has an expiration date it&#8216;s a <em>persistent</em> cookie
168
+ (a.k.a. domain cookie) and will be valid until that date.
169
+ </p>
170
+ <p>
171
+ &quot;Remember me&quot; could work fine with only session cookies, provided
172
+ the user never quits the browser, but users expect &quot;remember me&quot;
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 except for countdown_run() and countdown_running?() all
30
- the public methods will throw a NoCountdown exception if called on a
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 # give user more time
75
+ session.countdown_restart # extend user's login
79
76
  else
80
- session[:original_uri] = request.request_uri
81
- flash[:notice] = session.countdown_expired? ? "Login Expired" : "Please login"
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
1
+ 0.2.0
@@ -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
- check_countdown_exists(*args) # reason for this method_missing()
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 check_countdown_exists(name = @@default_name)
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
@@ -5,15 +5,16 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{session_countdown}
8
- s.version = "0.1.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-05}
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
- ## all public methods except countdown_run and countdown_running?
102
- ## require an existing countdown
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
- ## all public methods except countdown_run and countdown_running?
102
- ## require an existing countdown
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
- ## all public methods except countdown_run and countdown_running?
102
- ## require an existing countdown
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: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.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-05 00:00:00 -04:00
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: []