king_tokens 1.0.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/.document +3 -0
- data/.gitignore +20 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +87 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/coverage/index.html +112 -0
- data/coverage/lib-token_code_rb.html +290 -0
- data/coverage/lib-tokenizer_rb.html +344 -0
- data/init.rb +1 -0
- data/lib/king_tokens/token_code.rb +81 -0
- data/lib/king_tokens/tokenizer.rb +121 -0
- data/lib/king_tokens.rb +3 -0
- data/tasks/tokenizer_tasks.rake +4 -0
- data/test/schema.rb +14 -0
- data/test/test_helper.rb +17 -0
- data/test/tokenizer_test.rb +141 -0
- metadata +91 -0
data/.document
ADDED
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
= KingTokens
|
2
|
+
|
3
|
+
Tokens are a usefull way to give users access to an application. This can be for a limited time or just once.
|
4
|
+
Just think of password resets, changing email, protected rss feed urls, timed out private links, .. KingTokens are your easy way out in such cases
|
5
|
+
|
6
|
+
This plugin consists of two parts:
|
7
|
+
|
8
|
+
* an ActiveRecord model class TokenCode, which maps to the token table in the db
|
9
|
+
* a module Tokenizer mixed into ActiveRecord::Base, providing your models with the possibility to define tokens
|
10
|
+
|
11
|
+
KingTokens map polymorphic to other objects, through the can_has_tokens :a_tokens_name call
|
12
|
+
|
13
|
+
== Install
|
14
|
+
|
15
|
+
Get it as gem (hosted on gemcutter.org)
|
16
|
+
gem install king_tokens
|
17
|
+
|
18
|
+
Or download it from github and use it as rails plugin
|
19
|
+
|
20
|
+
setup your token db like defined in the test schema => test/schema.rb
|
21
|
+
|
22
|
+
== Example
|
23
|
+
|
24
|
+
Define a token on a model
|
25
|
+
class User
|
26
|
+
can_has_tokens :forgot_password
|
27
|
+
end
|
28
|
+
|
29
|
+
Set and get a user by token in a controller
|
30
|
+
class UsersController
|
31
|
+
# form with email so user can send himself a password reset link
|
32
|
+
def lost_password
|
33
|
+
if request.post?
|
34
|
+
#create users forgot_password_token
|
35
|
+
@user.set_forgot_password_token
|
36
|
+
.....
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Lookup user by lost_pass_code, send him to his password_edit page
|
41
|
+
# params[:code] contains the forgot_passwd token
|
42
|
+
def change_password
|
43
|
+
# identify by forgot_password_token in params[:code]
|
44
|
+
user = User.find_by_valid_token(:forgot_password, params[:code])
|
45
|
+
#expire token
|
46
|
+
user.get_forgot_password_token.use!
|
47
|
+
...
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
== Docs
|
52
|
+
|
53
|
+
To get a full understanding of the usage also read the tests. For QM you might check the coverage report in coverage/index.html
|
54
|
+
|
55
|
+
=== Token definition inside an ActiveRecord object:
|
56
|
+
|
57
|
+
Add a token with the name forgot_pasword to an object.
|
58
|
+
can_has_tokens :forgot_password
|
59
|
+
A token with the name change email valid for 3 days
|
60
|
+
can_has_tokens :change_email, {:days_valid => 3}
|
61
|
+
|
62
|
+
=== Instance methods added to the ActiveRecord object:
|
63
|
+
Set a new token and removing any existing one
|
64
|
+
user.set_forgot_password_token
|
65
|
+
Get the token string
|
66
|
+
user.forgot_password_token
|
67
|
+
Check if the user has such a token, returns boolean true
|
68
|
+
user.forgot_password_token?
|
69
|
+
Get the token object
|
70
|
+
user.get_forgot_password_token
|
71
|
+
Get the token object by name
|
72
|
+
user.token(:forgot_password)
|
73
|
+
Low level function to create a token with special options, overriding the ones set in the class definition
|
74
|
+
user.create_token(:token_name, :valid => 2.days.from_now)
|
75
|
+
|
76
|
+
|
77
|
+
=== Class methods
|
78
|
+
|
79
|
+
Find a user by a specific token which must be valid
|
80
|
+
User.find_by_valid_token(:token_name, 'a token string')
|
81
|
+
Find a user by specific token, without valid check
|
82
|
+
User.find_by_token(:forgot_password, 'a token string')
|
83
|
+
|
84
|
+
User.find_token
|
85
|
+
|
86
|
+
|
87
|
+
Copyright (c) 2008-2010 Michael Bumann, Georg Leciejewski released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "king_tokens"
|
10
|
+
gem.summary = %Q{Access tokens for any active record object}
|
11
|
+
gem.description = %Q{Tokens are a usefull way to give users access to an application. This can be for a limited time or just once. Just think of password resets, changing email, protected rss feed urls, timed out private links}
|
12
|
+
gem.email = "gl@salesking.eu"
|
13
|
+
gem.homepage = "http://github.com/schorsch/king_tokens"
|
14
|
+
gem.authors = ["Georg Leciejewski"]
|
15
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Default: run unit tests.'
|
24
|
+
task :default => :test
|
25
|
+
|
26
|
+
desc 'Test the tokenizer plugin.'
|
27
|
+
Rake::TestTask.new(:test) do |t|
|
28
|
+
t.libs << 'lib'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Generate documentation for the tokenizer plugin.'
|
34
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
35
|
+
rdoc.rdoc_dir = 'rdoc'
|
36
|
+
rdoc.title = 'KingTokens'
|
37
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
38
|
+
rdoc.rdoc_files.include('README')
|
39
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/coverage/index.html
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
|
3
|
+
<head>
|
4
|
+
<title>
|
5
|
+
C0 code coverage information
|
6
|
+
</title>
|
7
|
+
<style type='text/css'>
|
8
|
+
body { background-color: rgb(240, 240, 245); }
|
9
|
+
</style>
|
10
|
+
<style type='text/css'>
|
11
|
+
span.cross-ref-title { font-size: 140%; } span.cross-ref a {
|
12
|
+
text-decoration: none; } span.cross-ref { background-color:#f3f7fa;
|
13
|
+
border: 1px dashed #333; margin: 1em; padding: 0.5em; overflow: hidden; }
|
14
|
+
a.crossref-toggle { text-decoration: none; } span.marked0 {
|
15
|
+
background-color: rgb(185, 210, 200); display: block; } span.marked1 {
|
16
|
+
background-color: rgb(190, 215, 205); display: block; } span.inferred0 {
|
17
|
+
background-color: rgb(175, 200, 200); display: block; } span.inferred1 {
|
18
|
+
background-color: rgb(180, 205, 205); display: block; } span.uncovered0 {
|
19
|
+
background-color: rgb(225, 110, 110); display: block; } span.uncovered1 {
|
20
|
+
background-color: rgb(235, 120, 120); display: block; } span.overview {
|
21
|
+
border-bottom: 8px solid black; } div.overview { border-bottom: 8px solid
|
22
|
+
black; } body { font-family: verdana, arial, helvetica; } div.footer {
|
23
|
+
font-size: 68%; margin-top: 1.5em; } h1, h2, h3, h4, h5, h6 {
|
24
|
+
margin-bottom: 0.5em; } h5 { margin-top: 0.5em; } .hidden { display: none;
|
25
|
+
} div.separator { height: 10px; } /* Commented out for better readability,
|
26
|
+
esp. on IE */ /* table tr td, table tr th { font-size: 68%; } td.value
|
27
|
+
table tr td { font-size: 11px; } */ table.percent_graph { height: 12px;
|
28
|
+
border: #808080 1px solid; empty-cells: show; } table.percent_graph
|
29
|
+
td.covered { height: 10px; background: #00f000; } table.percent_graph
|
30
|
+
td.uncovered { height: 10px; background: #e00000; } table.percent_graph
|
31
|
+
td.NA { height: 10px; background: #eaeaea; } table.report {
|
32
|
+
border-collapse: collapse; width: 100%; } table.report td.heading {
|
33
|
+
background: #dcecff; border: #d0d0d0 1px solid; font-weight: bold;
|
34
|
+
text-align: center; } table.report td.heading:hover { background: #c0ffc0;
|
35
|
+
} table.report td.text { border: #d0d0d0 1px solid; } table.report
|
36
|
+
td.value, table.report td.lines_total, table.report td.lines_code {
|
37
|
+
text-align: right; border: #d0d0d0 1px solid; } table.report tr.light {
|
38
|
+
background-color: rgb(240, 240, 245); } table.report tr.dark {
|
39
|
+
background-color: rgb(230, 230, 235); }
|
40
|
+
</style>
|
41
|
+
<script type='text/javascript'>
|
42
|
+
// <![CDATA[ function toggleCode( id ) { if ( document.getElementById )
|
43
|
+
elem = document.getElementById( id ); else if ( document.all ) elem =
|
44
|
+
eval( "document.all." + id ); else return false; elemStyle = elem.style;
|
45
|
+
if ( elemStyle.display != "block" ) { elemStyle.display = "block" } else {
|
46
|
+
elemStyle.display = "none" } return true; } // Make cross-references
|
47
|
+
hidden by default document.writeln( "<style
|
48
|
+
type=\"text/css\">span.cross-ref { display: none }</style>" ) // ]]>
|
49
|
+
</script>
|
50
|
+
</head>
|
51
|
+
<body>
|
52
|
+
<h3>
|
53
|
+
C0 code coverage information
|
54
|
+
</h3>
|
55
|
+
<p>
|
56
|
+
Generated on Sun Dec 07 02:06:42 +0100 2008 with
|
57
|
+
<a href='http://eigenclass.org/hiki/rcov'>
|
58
|
+
rcov 0.8.1.2
|
59
|
+
</a>
|
60
|
+
</p>
|
61
|
+
<hr />
|
62
|
+
<table class='report'> <thead> <tr> <td class='heading'> Name </td> <td
|
63
|
+
class='heading'> Total lines </td> <td class='heading'> Lines of code </td>
|
64
|
+
<td class='heading'> Total coverage </td> <td class='heading'> Code coverage
|
65
|
+
</td> </tr> </thead> <tbody> <tr class='light'> <td> TOTAL </td> <td
|
66
|
+
class='lines_total'> <tt> 201 </tt> </td> <td class='lines_code'> <tt> 109
|
67
|
+
</tt> </td> <td> <table cellspacing='0' align='right' cellpadding='0'> <tr>
|
68
|
+
<td> <tt class='coverage_total'> 100.0% </tt> </td> <td> <table
|
69
|
+
class='percent_graph' cellspacing='0' width='100' cellpadding='0'> <tr> <td
|
70
|
+
class='covered' width='100' /> <td class='uncovered' width='0' /> </tr>
|
71
|
+
</table> </td> </tr> </table> </td> <td> <table cellspacing='0'
|
72
|
+
align='right' cellpadding='0'> <tr> <td> <tt class='coverage_code'> 100.0%
|
73
|
+
</tt> </td> <td> <table class='percent_graph' cellspacing='0'
|
74
|
+
width='100' cellpadding='0'> <tr> <td class='covered' width='100' /> <td
|
75
|
+
class='uncovered' width='0' /> </tr> </table> </td> </tr> </table> </td>
|
76
|
+
</tr> <tr class='dark'> <td> <a href='lib-token_code_rb.html'>
|
77
|
+
lib/token_code.rb </a> </td> <td class='lines_total'> <tt> 80 </tt> </td>
|
78
|
+
<td class='lines_code'> <tt> 46 </tt> </td> <td> <table cellspacing='0'
|
79
|
+
align='right' cellpadding='0'> <tr> <td> <tt class='coverage_total'> 100.0%
|
80
|
+
</tt> </td> <td> <table class='percent_graph' cellspacing='0'
|
81
|
+
width='100' cellpadding='0'> <tr> <td class='covered' width='100' /> <td
|
82
|
+
class='uncovered' width='0' /> </tr> </table> </td> </tr> </table> </td>
|
83
|
+
<td> <table cellspacing='0' align='right' cellpadding='0'> <tr> <td> <tt
|
84
|
+
class='coverage_code'> 100.0% </tt> </td> <td> <table
|
85
|
+
class='percent_graph' cellspacing='0' width='100' cellpadding='0'> <tr> <td
|
86
|
+
class='covered' width='100' /> <td class='uncovered' width='0' /> </tr>
|
87
|
+
</table> </td> </tr> </table> </td> </tr> <tr class='light'> <td> <a
|
88
|
+
href='lib-tokenizer_rb.html'> lib/tokenizer.rb </a> </td> <td
|
89
|
+
class='lines_total'> <tt> 121 </tt> </td> <td class='lines_code'> <tt> 63
|
90
|
+
</tt> </td> <td> <table cellspacing='0' align='right' cellpadding='0'> <tr>
|
91
|
+
<td> <tt class='coverage_total'> 100.0% </tt> </td> <td> <table
|
92
|
+
class='percent_graph' cellspacing='0' width='100' cellpadding='0'> <tr> <td
|
93
|
+
class='covered' width='100' /> <td class='uncovered' width='0' /> </tr>
|
94
|
+
</table> </td> </tr> </table> </td> <td> <table cellspacing='0'
|
95
|
+
align='right' cellpadding='0'> <tr> <td> <tt class='coverage_code'> 100.0%
|
96
|
+
</tt> </td> <td> <table class='percent_graph' cellspacing='0'
|
97
|
+
width='100' cellpadding='0'> <tr> <td class='covered' width='100' /> <td
|
98
|
+
class='uncovered' width='0' /> </tr> </table> </td> </tr> </table> </td>
|
99
|
+
</tr> </tbody> </table>
|
100
|
+
<hr />
|
101
|
+
<p> Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'> rcov
|
102
|
+
code coverage analysis tool for Ruby </a> version 0.8.1.2. </p>
|
103
|
+
<p>
|
104
|
+
<a href='http://validator.w3.org/check/referer'>
|
105
|
+
<img src='http://www.w3.org/Icons/valid-xhtml11' height='31' alt='Valid XHTML 1.1!' width='88' />
|
106
|
+
</a>
|
107
|
+
<a href='http://jigsaw.w3.org/css-validator/check/referer'>
|
108
|
+
<img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px' />
|
109
|
+
</a>
|
110
|
+
</p>
|
111
|
+
</body>
|
112
|
+
</html>
|
@@ -0,0 +1,290 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
|
3
|
+
<head>
|
4
|
+
<title>
|
5
|
+
lib/token_code.rb - C0 code coverage information
|
6
|
+
</title>
|
7
|
+
<style type='text/css'>
|
8
|
+
body { background-color: rgb(240, 240, 245); }
|
9
|
+
</style>
|
10
|
+
<style type='text/css'>
|
11
|
+
span.cross-ref-title { font-size: 140%; } span.cross-ref a {
|
12
|
+
text-decoration: none; } span.cross-ref { background-color:#f3f7fa;
|
13
|
+
border: 1px dashed #333; margin: 1em; padding: 0.5em; overflow: hidden; }
|
14
|
+
a.crossref-toggle { text-decoration: none; } span.marked0 {
|
15
|
+
background-color: rgb(185, 210, 200); display: block; } span.marked1 {
|
16
|
+
background-color: rgb(190, 215, 205); display: block; } span.inferred0 {
|
17
|
+
background-color: rgb(175, 200, 200); display: block; } span.inferred1 {
|
18
|
+
background-color: rgb(180, 205, 205); display: block; } span.uncovered0 {
|
19
|
+
background-color: rgb(225, 110, 110); display: block; } span.uncovered1 {
|
20
|
+
background-color: rgb(235, 120, 120); display: block; } span.overview {
|
21
|
+
border-bottom: 8px solid black; } div.overview { border-bottom: 8px solid
|
22
|
+
black; } body { font-family: verdana, arial, helvetica; } div.footer {
|
23
|
+
font-size: 68%; margin-top: 1.5em; } h1, h2, h3, h4, h5, h6 {
|
24
|
+
margin-bottom: 0.5em; } h5 { margin-top: 0.5em; } .hidden { display: none;
|
25
|
+
} div.separator { height: 10px; } /* Commented out for better readability,
|
26
|
+
esp. on IE */ /* table tr td, table tr th { font-size: 68%; } td.value
|
27
|
+
table tr td { font-size: 11px; } */ table.percent_graph { height: 12px;
|
28
|
+
border: #808080 1px solid; empty-cells: show; } table.percent_graph
|
29
|
+
td.covered { height: 10px; background: #00f000; } table.percent_graph
|
30
|
+
td.uncovered { height: 10px; background: #e00000; } table.percent_graph
|
31
|
+
td.NA { height: 10px; background: #eaeaea; } table.report {
|
32
|
+
border-collapse: collapse; width: 100%; } table.report td.heading {
|
33
|
+
background: #dcecff; border: #d0d0d0 1px solid; font-weight: bold;
|
34
|
+
text-align: center; } table.report td.heading:hover { background: #c0ffc0;
|
35
|
+
} table.report td.text { border: #d0d0d0 1px solid; } table.report
|
36
|
+
td.value, table.report td.lines_total, table.report td.lines_code {
|
37
|
+
text-align: right; border: #d0d0d0 1px solid; } table.report tr.light {
|
38
|
+
background-color: rgb(240, 240, 245); } table.report tr.dark {
|
39
|
+
background-color: rgb(230, 230, 235); }
|
40
|
+
</style>
|
41
|
+
<script type='text/javascript'>
|
42
|
+
// <![CDATA[ function toggleCode( id ) { if ( document.getElementById )
|
43
|
+
elem = document.getElementById( id ); else if ( document.all ) elem =
|
44
|
+
eval( "document.all." + id ); else return false; elemStyle = elem.style;
|
45
|
+
if ( elemStyle.display != "block" ) { elemStyle.display = "block" } else {
|
46
|
+
elemStyle.display = "none" } return true; } // Make cross-references
|
47
|
+
hidden by default document.writeln( "<style
|
48
|
+
type=\"text/css\">span.cross-ref { display: none }</style>" ) // ]]>
|
49
|
+
</script>
|
50
|
+
<style type='text/css'>
|
51
|
+
span.run0 { background-color: rgb(178, 204, 255); display: block; }
|
52
|
+
span.run1 { background-color: rgb(178, 206, 255); display: block; }
|
53
|
+
span.run2 { background-color: rgb(178, 209, 255); display: block; }
|
54
|
+
span.run3 { background-color: rgb(178, 211, 255); display: block; }
|
55
|
+
span.run4 { background-color: rgb(178, 214, 255); display: block; }
|
56
|
+
span.run5 { background-color: rgb(178, 218, 255); display: block; }
|
57
|
+
span.run6 { background-color: rgb(178, 220, 255); display: block; }
|
58
|
+
span.run7 { background-color: rgb(178, 223, 255); display: block; }
|
59
|
+
span.run8 { background-color: rgb(178, 225, 255); display: block; }
|
60
|
+
span.run9 { background-color: rgb(178, 228, 255); display: block; }
|
61
|
+
span.run10 { background-color: rgb(178, 232, 255); display: block; }
|
62
|
+
span.run11 { background-color: rgb(178, 234, 255); display: block; }
|
63
|
+
span.run12 { background-color: rgb(178, 237, 255); display: block; }
|
64
|
+
span.run13 { background-color: rgb(178, 239, 255); display: block; }
|
65
|
+
span.run14 { background-color: rgb(178, 242, 255); display: block; }
|
66
|
+
span.run15 { background-color: rgb(178, 246, 255); display: block; }
|
67
|
+
span.run16 { background-color: rgb(178, 248, 255); display: block; }
|
68
|
+
span.run17 { background-color: rgb(178, 251, 255); display: block; }
|
69
|
+
span.run18 { background-color: rgb(178, 253, 255); display: block; }
|
70
|
+
span.run19 { background-color: rgb(178, 255, 253); display: block; }
|
71
|
+
span.run20 { background-color: rgb(178, 255, 249); display: block; }
|
72
|
+
span.run21 { background-color: rgb(178, 255, 247); display: block; }
|
73
|
+
span.run22 { background-color: rgb(178, 255, 244); display: block; }
|
74
|
+
span.run23 { background-color: rgb(178, 255, 242); display: block; }
|
75
|
+
span.run24 { background-color: rgb(178, 255, 239); display: block; }
|
76
|
+
span.run25 { background-color: rgb(178, 255, 235); display: block; }
|
77
|
+
span.run26 { background-color: rgb(178, 255, 233); display: block; }
|
78
|
+
span.run27 { background-color: rgb(178, 255, 230); display: block; }
|
79
|
+
span.run28 { background-color: rgb(178, 255, 228); display: block; }
|
80
|
+
span.run29 { background-color: rgb(178, 255, 225); display: block; }
|
81
|
+
span.run30 { background-color: rgb(178, 255, 221); display: block; }
|
82
|
+
span.run31 { background-color: rgb(178, 255, 219); display: block; }
|
83
|
+
span.run32 { background-color: rgb(178, 255, 216); display: block; }
|
84
|
+
span.run33 { background-color: rgb(178, 255, 214); display: block; }
|
85
|
+
span.run34 { background-color: rgb(178, 255, 211); display: block; }
|
86
|
+
span.run35 { background-color: rgb(178, 255, 207); display: block; }
|
87
|
+
span.run36 { background-color: rgb(178, 255, 205); display: block; }
|
88
|
+
span.run37 { background-color: rgb(178, 255, 202); display: block; }
|
89
|
+
span.run38 { background-color: rgb(178, 255, 200); display: block; }
|
90
|
+
span.run39 { background-color: rgb(178, 255, 197); display: block; }
|
91
|
+
span.run40 { background-color: rgb(178, 255, 193); display: block; }
|
92
|
+
span.run41 { background-color: rgb(178, 255, 191); display: block; }
|
93
|
+
span.run42 { background-color: rgb(178, 255, 188); display: block; }
|
94
|
+
span.run43 { background-color: rgb(178, 255, 186); display: block; }
|
95
|
+
span.run44 { background-color: rgb(178, 255, 183); display: block; }
|
96
|
+
span.run45 { background-color: rgb(178, 255, 179); display: block; }
|
97
|
+
span.run46 { background-color: rgb(179, 255, 178); display: block; }
|
98
|
+
span.run47 { background-color: rgb(182, 255, 178); display: block; }
|
99
|
+
span.run48 { background-color: rgb(184, 255, 178); display: block; }
|
100
|
+
span.run49 { background-color: rgb(187, 255, 178); display: block; }
|
101
|
+
span.run50 { background-color: rgb(191, 255, 178); display: block; }
|
102
|
+
span.run51 { background-color: rgb(193, 255, 178); display: block; }
|
103
|
+
span.run52 { background-color: rgb(196, 255, 178); display: block; }
|
104
|
+
span.run53 { background-color: rgb(198, 255, 178); display: block; }
|
105
|
+
span.run54 { background-color: rgb(201, 255, 178); display: block; }
|
106
|
+
span.run55 { background-color: rgb(205, 255, 178); display: block; }
|
107
|
+
span.run56 { background-color: rgb(207, 255, 178); display: block; }
|
108
|
+
span.run57 { background-color: rgb(210, 255, 178); display: block; }
|
109
|
+
span.run58 { background-color: rgb(212, 255, 178); display: block; }
|
110
|
+
span.run59 { background-color: rgb(215, 255, 178); display: block; }
|
111
|
+
span.run60 { background-color: rgb(219, 255, 178); display: block; }
|
112
|
+
span.run61 { background-color: rgb(221, 255, 178); display: block; }
|
113
|
+
span.run62 { background-color: rgb(224, 255, 178); display: block; }
|
114
|
+
span.run63 { background-color: rgb(226, 255, 178); display: block; }
|
115
|
+
span.run64 { background-color: rgb(229, 255, 178); display: block; }
|
116
|
+
span.run65 { background-color: rgb(233, 255, 178); display: block; }
|
117
|
+
span.run66 { background-color: rgb(235, 255, 178); display: block; }
|
118
|
+
span.run67 { background-color: rgb(238, 255, 178); display: block; }
|
119
|
+
span.run68 { background-color: rgb(240, 255, 178); display: block; }
|
120
|
+
span.run69 { background-color: rgb(243, 255, 178); display: block; }
|
121
|
+
span.run70 { background-color: rgb(247, 255, 178); display: block; }
|
122
|
+
span.run71 { background-color: rgb(249, 255, 178); display: block; }
|
123
|
+
span.run72 { background-color: rgb(252, 255, 178); display: block; }
|
124
|
+
span.run73 { background-color: rgb(255, 255, 178); display: block; }
|
125
|
+
span.run74 { background-color: rgb(255, 252, 178); display: block; }
|
126
|
+
span.run75 { background-color: rgb(255, 248, 178); display: block; }
|
127
|
+
span.run76 { background-color: rgb(255, 246, 178); display: block; }
|
128
|
+
span.run77 { background-color: rgb(255, 243, 178); display: block; }
|
129
|
+
span.run78 { background-color: rgb(255, 240, 178); display: block; }
|
130
|
+
span.run79 { background-color: rgb(255, 238, 178); display: block; }
|
131
|
+
span.run80 { background-color: rgb(255, 234, 178); display: block; }
|
132
|
+
span.run81 { background-color: rgb(255, 232, 178); display: block; }
|
133
|
+
span.run82 { background-color: rgb(255, 229, 178); display: block; }
|
134
|
+
span.run83 { background-color: rgb(255, 226, 178); display: block; }
|
135
|
+
span.run84 { background-color: rgb(255, 224, 178); display: block; }
|
136
|
+
span.run85 { background-color: rgb(255, 220, 178); display: block; }
|
137
|
+
span.run86 { background-color: rgb(255, 218, 178); display: block; }
|
138
|
+
span.run87 { background-color: rgb(255, 215, 178); display: block; }
|
139
|
+
span.run88 { background-color: rgb(255, 212, 178); display: block; }
|
140
|
+
span.run89 { background-color: rgb(255, 210, 178); display: block; }
|
141
|
+
span.run90 { background-color: rgb(255, 206, 178); display: block; }
|
142
|
+
span.run91 { background-color: rgb(255, 204, 178); display: block; }
|
143
|
+
span.run92 { background-color: rgb(255, 201, 178); display: block; }
|
144
|
+
span.run93 { background-color: rgb(255, 198, 178); display: block; }
|
145
|
+
span.run94 { background-color: rgb(255, 196, 178); display: block; }
|
146
|
+
span.run95 { background-color: rgb(255, 192, 178); display: block; }
|
147
|
+
span.run96 { background-color: rgb(255, 189, 178); display: block; }
|
148
|
+
span.run97 { background-color: rgb(255, 187, 178); display: block; }
|
149
|
+
span.run98 { background-color: rgb(255, 184, 178); display: block; }
|
150
|
+
span.run99 { background-color: rgb(255, 182, 178); display: block; }
|
151
|
+
span.run100 { background-color: rgb(255, 178, 178); display: block; }
|
152
|
+
</style>
|
153
|
+
</head>
|
154
|
+
<body>
|
155
|
+
<h3>
|
156
|
+
C0 code coverage information
|
157
|
+
</h3>
|
158
|
+
<p>
|
159
|
+
Generated on Sun Dec 07 02:06:42 +0100 2008 with
|
160
|
+
<a href='http://eigenclass.org/hiki/rcov'>
|
161
|
+
rcov 0.8.1.2
|
162
|
+
</a>
|
163
|
+
</p>
|
164
|
+
<hr />
|
165
|
+
<pre><span class='marked0'>Code reported as executed by Ruby looks like
|
166
|
+
this... </span><span class='marked1'>and this: this line is also marked as
|
167
|
+
covered. </span><span class='inferred0'>Lines considered as run by rcov, but
|
168
|
+
not reported by Ruby, look like this, </span><span class='inferred1'>and
|
169
|
+
this: these lines were inferred by rcov (using simple heuristics).
|
170
|
+
</span><span class='uncovered0'>Finally, here's a line marked as not
|
171
|
+
executed. </span></pre>
|
172
|
+
<table class='report'> <thead> <tr> <td class='heading'> Name </td> <td
|
173
|
+
class='heading'> Total lines </td> <td class='heading'> Lines of code </td>
|
174
|
+
<td class='heading'> Total coverage </td> <td class='heading'> Code coverage
|
175
|
+
</td> </tr> </thead> <tbody> <tr class='light'> <td> <a
|
176
|
+
href='lib-token_code_rb.html'> lib/token_code.rb </a> </td> <td
|
177
|
+
class='lines_total'> <tt> 80 </tt> </td> <td class='lines_code'> <tt> 46
|
178
|
+
</tt> </td> <td> <table cellspacing='0' align='right' cellpadding='0'> <tr>
|
179
|
+
<td> <tt class='coverage_total'> 100.0% </tt> </td> <td> <table
|
180
|
+
class='percent_graph' cellspacing='0' width='100' cellpadding='0'> <tr> <td
|
181
|
+
class='covered' width='100' /> <td class='uncovered' width='0' /> </tr>
|
182
|
+
</table> </td> </tr> </table> </td> <td> <table cellspacing='0'
|
183
|
+
align='right' cellpadding='0'> <tr> <td> <tt class='coverage_code'> 100.0%
|
184
|
+
</tt> </td> <td> <table class='percent_graph' cellspacing='0'
|
185
|
+
width='100' cellpadding='0'> <tr> <td class='covered' width='100' /> <td
|
186
|
+
class='uncovered' width='0' /> </tr> </table> </td> </tr> </table> </td>
|
187
|
+
</tr> </tbody> </table><pre><span class="marked1"><a name="line1"></a> 1
|
188
|
+
require "digest/sha1" </span><span class="inferred0"><a
|
189
|
+
name="line2"></a> 2 </span><span class="inferred1"><a name="line3"></a> 3 #
|
190
|
+
Class to handle polymorphic tokens </span><span class="marked0"><a
|
191
|
+
name="line4"></a> 4 class TokenCode < ActiveRecord::Base </span><span
|
192
|
+
class="inferred1"><a name="line5"></a> 5 </span><span class="inferred0"><a
|
193
|
+
name="line6"></a> 6 # kick this stament if you dont uses uuids .. or better
|
194
|
+
we make a check?? </span><span class="inferred1"><a name="line7"></a> 7
|
195
|
+
</span><span class="marked0"><a name="line8"></a> 8 usesguid if
|
196
|
+
defined?(usesguid) </span><span class="inferred1"><a name="line9"></a> 9
|
197
|
+
</span><span class="marked0"><a name="line10"></a>10 belongs_to :object,
|
198
|
+
:polymorphic => true </span><span class="marked1"><a name="line11"></a>11
|
199
|
+
before_create :set_token </span><span class="inferred0"><a
|
200
|
+
name="line12"></a>12 </span><span class="marked1"><a name="line13"></a>13
|
201
|
+
validates_presence_of :name </span><span class="marked0"><a
|
202
|
+
name="line14"></a>14 validates_format_of :name, :with =>
|
203
|
+
/^[a-zA-Z0-9\_\-]+$/ </span><span class="marked1"><a name="line15"></a>15
|
204
|
+
validates_uniqueness_of :name, :scope => [:object_id, :object_type]
|
205
|
+
#second not really needed if uuid </span><span class="inferred0"><a
|
206
|
+
name="line16"></a>16 </span><span class="marked1"><a name="line17"></a>17
|
207
|
+
def to_s </span><span class="marked0"><a name="line18"></a>18 self.token
|
208
|
+
</span><span class="inferred1"><a name="line19"></a>19 end </span><span
|
209
|
+
class="inferred0"><a name="line20"></a>20 </span><span class="inferred1"><a
|
210
|
+
name="line21"></a>21 # Use a token for an object. </span><span
|
211
|
+
class="inferred0"><a name="line22"></a>22 # Sets the used_at field
|
212
|
+
</span><span class="marked1"><a name="line23"></a>23 def use! </span><span
|
213
|
+
class="marked0"><a name="line24"></a>24 update_attribute(:used_at,Time.now)
|
214
|
+
</span><span class="inferred1"><a name="line25"></a>25 end </span><span
|
215
|
+
class="inferred0"><a name="line26"></a>26 </span><span class="inferred1"><a
|
216
|
+
name="line27"></a>27 # Revoke the usage of a token by emptying its used_at
|
217
|
+
field </span><span class="marked0"><a name="line28"></a>28 def unuse!
|
218
|
+
</span><span class="marked1"><a name="line29"></a>29
|
219
|
+
update_attribute(:used_at,nil) </span><span class="inferred0"><a
|
220
|
+
name="line30"></a>30 end </span><span class="inferred1"><a
|
221
|
+
name="line31"></a>31 </span><span class="marked0"><a name="line32"></a>32
|
222
|
+
def used? </span><span class="marked1"><a name="line33"></a>33 !!
|
223
|
+
read_attribute(:used_at) </span><span class="inferred0"><a
|
224
|
+
name="line34"></a>34 end </span><span class="inferred1"><a
|
225
|
+
name="line35"></a>35 </span><span class="inferred0"><a name="line36"></a>36
|
226
|
+
# Check if the token has expired </span><span class="marked1"><a
|
227
|
+
name="line37"></a>37 def expired? </span><span class="marked0"><a
|
228
|
+
name="line38"></a>38 valid_until && valid_until < Time.now
|
229
|
+
</span><span class="inferred1"><a name="line39"></a>39 end </span><span
|
230
|
+
class="inferred0"><a name="line40"></a>40 </span><span class="inferred1"><a
|
231
|
+
name="line41"></a>41 # A token is valid to be used if: </span><span
|
232
|
+
class="inferred0"><a name="line42"></a>42 # - its has not been used
|
233
|
+
</span><span class="inferred1"><a name="line43"></a>43 # - its not expired
|
234
|
+
</span><span class="inferred0"><a name="line44"></a>44 # - its valid in
|
235
|
+
terms of AR validation </span><span class="marked1"><a name="line45"></a>45
|
236
|
+
def valid_for_use? </span><span class="marked0"><a name="line46"></a>46
|
237
|
+
valid? && !used? && !expired? </span><span
|
238
|
+
class="inferred1"><a name="line47"></a>47 end </span><span
|
239
|
+
class="inferred0"><a name="line48"></a>48 </span><span class="inferred1"><a
|
240
|
+
name="line49"></a>49 </span><span class="marked0"><a name="line50"></a>50
|
241
|
+
def self.delete_used </span><span class="marked1"><a name="line51"></a>51
|
242
|
+
delete_all "used_at IS NOT NULL" </span><span class="inferred0"><a
|
243
|
+
name="line52"></a>52 end </span><span class="inferred1"><a
|
244
|
+
name="line53"></a>53 </span><span class="marked0"><a name="line54"></a>54
|
245
|
+
def self.delete_expired </span><span class="marked1"><a name="line55"></a>55
|
246
|
+
delete_all ["valid_until IS NOT NULL AND valid_until < ? ",
|
247
|
+
Time.now] </span><span class="inferred0"><a name="line56"></a>56 end
|
248
|
+
</span><span class="inferred1"><a name="line57"></a>57 </span><span
|
249
|
+
class="marked0"><a name="line58"></a>58 private </span><span
|
250
|
+
class="inferred1"><a name="line59"></a>59 </span><span class="inferred0"><a
|
251
|
+
name="line60"></a>60 # Generate a token with a default length of 12.
|
252
|
+
</span><span class="inferred1"><a name="line61"></a>61 # Takes a block to
|
253
|
+
validate the token, which should return true/false </span><span
|
254
|
+
class="inferred0"><a name="line62"></a>62 # ==== Parameter </span><span
|
255
|
+
class="inferred1"><a name="line63"></a>63 # size<Integer>:: The length
|
256
|
+
of the token. Defaults to 40 </span><span class="inferred0"><a
|
257
|
+
name="line64"></a>64 # validity<Proc>:: A block to check the validity
|
258
|
+
of the token, see #set_token for usage </span><span class="marked1"><a
|
259
|
+
name="line65"></a>65 def generate_token(size = 40, &validity)
|
260
|
+
</span><span class="inferred0"><a name="line66"></a>66 begin </span><span
|
261
|
+
class="marked1"><a name="line67"></a>67 token = secure_digest(Time.now,
|
262
|
+
"#{self.object_type}#{self.object_id}", (1..10).map{ rand.to_s
|
263
|
+
}).first(size) </span><span class="marked0"><a name="line68"></a>68 end
|
264
|
+
while !validity.call(token) if block_given? </span><span class="marked1"><a
|
265
|
+
name="line69"></a>69 token </span><span class="inferred0"><a
|
266
|
+
name="line70"></a>70 end </span><span class="inferred1"><a
|
267
|
+
name="line71"></a>71 </span><span class="marked0"><a name="line72"></a>72
|
268
|
+
def secure_digest(*args) </span><span class="marked1"><a
|
269
|
+
name="line73"></a>73 Digest::SHA1.hexdigest(args.flatten.join('--'))
|
270
|
+
</span><span class="inferred0"><a name="line74"></a>74 end </span><span
|
271
|
+
class="inferred1"><a name="line75"></a>75 </span><span class="marked0"><a
|
272
|
+
name="line76"></a>76 def set_token </span><span class="marked1"><a
|
273
|
+
name="line77"></a>77 self.token = generate_token { |token|
|
274
|
+
TokenCode.find_by_token(token).nil? } </span><span class="inferred0"><a
|
275
|
+
name="line78"></a>78 end </span><span class="inferred1"><a
|
276
|
+
name="line79"></a>79 </span><span class="inferred0"><a name="line80"></a>80
|
277
|
+
end </span></pre>
|
278
|
+
<hr />
|
279
|
+
<p> Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'> rcov
|
280
|
+
code coverage analysis tool for Ruby </a> version 0.8.1.2. </p>
|
281
|
+
<p>
|
282
|
+
<a href='http://validator.w3.org/check/referer'>
|
283
|
+
<img src='http://www.w3.org/Icons/valid-xhtml10' height='31' alt='Valid XHTML 1.0!' width='88' />
|
284
|
+
</a>
|
285
|
+
<a href='http://jigsaw.w3.org/css-validator/check/referer'>
|
286
|
+
<img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px' />
|
287
|
+
</a>
|
288
|
+
</p>
|
289
|
+
</body>
|
290
|
+
</html>
|