strelka 0.0.1.pre.244 → 0.0.1.pre.252
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/ChangeLog +57 -3
- data/Manifest.txt +3 -4
- data/Rakefile +1 -1
- data/bin/strelka +4 -7
- data/examples/.env +4 -0
- data/examples/Procfile +8 -0
- data/examples/apps/auth-demo +3 -5
- data/examples/apps/auth-demo2 +10 -9
- data/{data/strelka → examples}/apps/hello-world +1 -2
- data/examples/apps/sessions-demo +2 -2
- data/examples/config.yml +12 -1
- data/examples/gen-config.rb +5 -6
- data/examples/templates/auth-form.tmpl +4 -0
- data/examples/templates/auth-success.tmpl +3 -1
- data/lib/strelka.rb +15 -21
- data/lib/strelka/app.rb +53 -31
- data/lib/strelka/app/auth.rb +260 -132
- data/lib/strelka/app/sessions.rb +25 -31
- data/lib/strelka/authprovider/basic.rb +33 -9
- data/lib/strelka/authprovider/hostaccess.rb +1 -1
- data/lib/strelka/constants.rb +0 -11
- data/lib/strelka/cookie.rb +17 -1
- data/lib/strelka/httpresponse/negotiation.rb +1 -1
- data/lib/strelka/session/db.rb +49 -25
- data/lib/strelka/session/default.rb +39 -19
- data/spec/lib/helpers.rb +3 -24
- data/spec/strelka/app/auth_spec.rb +461 -177
- data/spec/strelka/app/sessions_spec.rb +7 -26
- data/spec/strelka/app_spec.rb +3 -3
- data/spec/strelka/authprovider/basic_spec.rb +4 -4
- data/spec/strelka/httprequest/session_spec.rb +1 -1
- data/spec/strelka/httpresponse/session_spec.rb +1 -1
- data/spec/strelka/session/db_spec.rb +6 -1
- data/spec/strelka/session/default_spec.rb +3 -3
- metadata +7 -8
- metadata.gz.sig +2 -2
- data/examples/apps/ws-echo +0 -17
- data/lib/strelka/logging.rb +0 -301
- data/spec/strelka/logging_spec.rb +0 -74
data/lib/strelka/app/sessions.rb
CHANGED
@@ -64,16 +64,18 @@ require 'strelka/httpresponse/session'
|
|
64
64
|
# # it uses
|
65
65
|
# sessions:
|
66
66
|
# session_class: default
|
67
|
-
#
|
67
|
+
#
|
68
|
+
# defaultsession:
|
68
69
|
# cookie_name: acme-session
|
69
70
|
#
|
70
|
-
# #
|
71
|
+
# # Use the database-backed session type and point it
|
71
72
|
# # at a database
|
72
73
|
# sessions:
|
73
|
-
# session_class:
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
74
|
+
# session_class: db
|
75
|
+
#
|
76
|
+
# dbsession:
|
77
|
+
# connect: "postgres://pg.example.com/db01"
|
78
|
+
# table_name: sessions
|
77
79
|
#
|
78
80
|
# The +type+ value will be used to look up the class (see Strelka::Session
|
79
81
|
# for more information about how this works), and the +options+ section
|
@@ -97,15 +99,6 @@ module Strelka::App::Sessions
|
|
97
99
|
run_after :templating, :filters, :parameters
|
98
100
|
|
99
101
|
|
100
|
-
# Default options to pass to the session object
|
101
|
-
DEFAULT_OPTIONS = {}
|
102
|
-
|
103
|
-
|
104
|
-
##
|
105
|
-
# What session class to use (Class object)
|
106
|
-
singleton_attr_writer :session_class
|
107
|
-
|
108
|
-
|
109
102
|
# Class methods and instance variables to add to classes with sessions.
|
110
103
|
module ClassMethods # :nodoc:
|
111
104
|
|
@@ -132,33 +125,34 @@ module Strelka::App::Sessions
|
|
132
125
|
end # module ClassMethods
|
133
126
|
|
134
127
|
|
128
|
+
# Default options to pass to the session object
|
129
|
+
CONFIG_DEFAULTS = {
|
130
|
+
session_class: 'default',
|
131
|
+
}
|
132
|
+
|
135
133
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
##
|
135
|
+
# What session class to use (String, Symbol, or Class); passed to
|
136
|
+
# Strelka::Session.create.
|
137
|
+
singleton_attr_reader :session_class
|
140
138
|
|
141
139
|
|
142
140
|
### Configurability API -- set up session type and options with values from
|
143
141
|
### the +config+.
|
144
142
|
def self::configure( config=nil )
|
145
|
-
options = DEFAULT_OPTIONS.dup
|
146
|
-
|
147
143
|
# Figure out which session class is going to be used, or choose a default one
|
148
144
|
if config
|
149
|
-
self.session_class =
|
150
|
-
config.key?( :session_class )
|
151
|
-
if config[:options]
|
152
|
-
options.merge!( config[:options] ) do |key, oldval, newval|
|
153
|
-
oldval.merge( newval )
|
154
|
-
end
|
155
|
-
end
|
145
|
+
self.session_class = config[:session_class]
|
156
146
|
else
|
157
|
-
self.session_class =
|
147
|
+
self.session_class = CONFIG_DEFAULTS[:session_class]
|
158
148
|
end
|
159
149
|
|
160
|
-
|
161
|
-
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
### Get the configured session class (Strelka::Session subclass)
|
154
|
+
def self::session_class=( newclass )
|
155
|
+
@session_class = Strelka::Session.get_subclass( newclass )
|
162
156
|
end
|
163
157
|
|
164
158
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
# vim: set nosta noet ts=4 sw=4:
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'openssl'
|
5
5
|
require 'configurability'
|
6
6
|
|
7
7
|
require 'strelka' unless defined?( Strelka )
|
@@ -31,17 +31,26 @@ require 'strelka/mixins'
|
|
31
31
|
# kmurgen: "MZj9+VhZ8C9+aJhmwp+kWBL76Vs="
|
32
32
|
#
|
33
33
|
class Strelka::AuthProvider::Basic < Strelka::AuthProvider
|
34
|
-
extend
|
35
|
-
Configurability,
|
34
|
+
extend Configurability,
|
36
35
|
Strelka::MethodUtilities
|
37
36
|
include Strelka::Constants
|
38
37
|
|
39
38
|
# Configurability API - set the section of the config
|
40
|
-
config_key :
|
39
|
+
config_key :basicauth
|
41
40
|
|
41
|
+
# Configurability API -- configuration defaults
|
42
|
+
CONFIG_DEFAULTS = {
|
43
|
+
realm: nil,
|
44
|
+
users: {},
|
45
|
+
}
|
46
|
+
|
47
|
+
# The amount of work to do while encrypting -- higher number == more work == less suceptable
|
48
|
+
# to brute-force attacks
|
49
|
+
ENCRYPT_ITERATIONS = 20_000
|
50
|
+
|
51
|
+
# The Digest class to use when encrypting passwords
|
52
|
+
DIGEST_CLASS = OpenSSL::Digest::SHA256
|
42
53
|
|
43
|
-
@users = nil
|
44
|
-
@realm = nil
|
45
54
|
|
46
55
|
##
|
47
56
|
# The Hash of users and their SHA1+Base64'ed passwords
|
@@ -54,11 +63,12 @@ class Strelka::AuthProvider::Basic < Strelka::AuthProvider
|
|
54
63
|
|
55
64
|
### Configurability API -- configure the auth provider instance.
|
56
65
|
def self::configure( config=nil )
|
57
|
-
if config
|
66
|
+
if config && config[:realm]
|
58
67
|
self.log.debug "Configuring Basic authprovider: %p" % [ config ]
|
59
|
-
self.realm = config[
|
60
|
-
self.users = config[
|
68
|
+
self.realm = config[:realm]
|
69
|
+
self.users = config[:users]
|
61
70
|
else
|
71
|
+
self.log.warn "No 'basicauth' config section; using the (empty) defaults"
|
62
72
|
self.realm = nil
|
63
73
|
self.users = {}
|
64
74
|
end
|
@@ -132,4 +142,18 @@ class Strelka::AuthProvider::Basic < Strelka::AuthProvider
|
|
132
142
|
finish_with( HTTP::AUTH_REQUIRED, "Requires authentication.", www_authenticate: header )
|
133
143
|
end
|
134
144
|
|
145
|
+
|
146
|
+
### (undocumented)
|
147
|
+
def encrypt( pass, salt=nil )
|
148
|
+
salt ||= OpenSSL::Random.random_bytes( 16 ) #store this with the generated value
|
149
|
+
iter = ENCRYPT_ITERATIONS
|
150
|
+
digest = DIGEST_CLASS.new
|
151
|
+
len = digest.digest_length
|
152
|
+
|
153
|
+
value = OpenSSL::PKCS5.pbkdf2_hmac( pass, salt, iter, len, digest )
|
154
|
+
|
155
|
+
return [ value, salt ].join( ':' )
|
156
|
+
end
|
157
|
+
|
158
|
+
|
135
159
|
end # class Strelka::AuthProvider::Basic
|
data/lib/strelka/constants.rb
CHANGED
@@ -11,17 +11,6 @@ module Strelka::Constants
|
|
11
11
|
# Import Mongrel2's constants, too
|
12
12
|
include Mongrel2::Constants
|
13
13
|
|
14
|
-
# The data directory in the project if that exists, otherwise the gem datadir
|
15
|
-
DEFAULT_DATADIR = if ENV['STRELKA_DATADIR']
|
16
|
-
Pathname( ENV['STRELKA_DATADIR'] )
|
17
|
-
elsif File.directory?( 'data/strelka' )
|
18
|
-
Pathname( 'data/strelka' )
|
19
|
-
elsif path = Gem.datadir('strelka')
|
20
|
-
Pathname( path )
|
21
|
-
else
|
22
|
-
raise ScriptError, "can't find the data directory!"
|
23
|
-
end
|
24
|
-
|
25
14
|
# Extend Mongrel2's HTTP constants collection
|
26
15
|
module HTTP
|
27
16
|
include Mongrel2::Constants::HTTP
|
data/lib/strelka/cookie.rb
CHANGED
@@ -155,7 +155,23 @@ class Strelka::Cookie
|
|
155
155
|
#################################################################
|
156
156
|
|
157
157
|
### Create a new Strelka::Cookie object with the specified +name+ and
|
158
|
-
### +values+.
|
158
|
+
### +values+. Valid options are:
|
159
|
+
###
|
160
|
+
### [\version]
|
161
|
+
### The cookie version. 0 (the default) is fine for most uses
|
162
|
+
### [\domain]
|
163
|
+
### The domain the cookie belongs to.
|
164
|
+
### [\path]
|
165
|
+
### The path the cookie applies to.
|
166
|
+
### [\secure]
|
167
|
+
### The cookie's 'secure' flag.
|
168
|
+
### [\expires]
|
169
|
+
### The cookie's expiration (a Time object). See expires= for valid
|
170
|
+
### values.
|
171
|
+
### [\max_age]
|
172
|
+
### The lifetime of the cookie, in seconds.
|
173
|
+
### [\comment]
|
174
|
+
### Cookie comment; see #comment= for details.
|
159
175
|
def initialize( name, values, options={} )
|
160
176
|
values = [ values ] unless values.is_a?( Array )
|
161
177
|
@name = name
|
@@ -334,7 +334,7 @@ module Strelka::HTTPResponse::Negotiation
|
|
334
334
|
STRINGIFIERS.key?( mimetype ) && !new_body.is_a?( String )
|
335
335
|
|
336
336
|
self.body = new_body
|
337
|
-
self.content_type = mimetype
|
337
|
+
self.content_type = mimetype.dup # :TODO: Why is this frozen?
|
338
338
|
self.status ||= HTTP::OK
|
339
339
|
|
340
340
|
return true
|
data/lib/strelka/session/db.rb
CHANGED
@@ -15,29 +15,43 @@ require 'strelka/session/default'
|
|
15
15
|
# any database that Sequel supports. It defaults to non-persistent, in memory Sqlite.
|
16
16
|
#
|
17
17
|
class Strelka::Session::Db < Strelka::Session::Default
|
18
|
-
extend
|
18
|
+
extend Configurability,
|
19
19
|
Forwardable,
|
20
20
|
Strelka::MethodUtilities
|
21
21
|
|
22
|
-
# Loggability API -- set up logging under the 'strelka' log host
|
23
|
-
log_to :strelka
|
24
22
|
|
23
|
+
##
|
24
|
+
# Configurability API -- use the 'dbsession' section of the config
|
25
|
+
config_key :dbsession
|
26
|
+
|
27
|
+
|
28
|
+
# Configuration defaults
|
29
|
+
CONFIG_DEFAULTS = {
|
30
|
+
connect: nil,
|
31
|
+
table_name: 'sessions',
|
32
|
+
cookie_name: 'strelka-session',
|
33
|
+
cookie_options: {
|
34
|
+
expires: "+1d",
|
35
|
+
}
|
36
|
+
}
|
25
37
|
|
26
38
|
# Class-instance variables
|
27
39
|
@table_name = :sessions
|
28
40
|
@db = nil
|
29
41
|
@dataset = nil
|
30
|
-
|
31
|
-
:name => 'strelka-session'
|
32
|
-
}
|
42
|
+
|
33
43
|
|
34
44
|
##
|
35
45
|
# The Sequel dataset connection
|
36
|
-
|
46
|
+
singleton_attr_accessor :db
|
37
47
|
|
38
48
|
##
|
39
49
|
# The Sequel dataset for the sessions table
|
40
|
-
|
50
|
+
singleton_attr_accessor :dataset
|
51
|
+
|
52
|
+
##
|
53
|
+
# The name of the table to use for storing sessions
|
54
|
+
singleton_attr_accessor :table_name
|
41
55
|
|
42
56
|
##
|
43
57
|
# The configured session cookie parameters
|
@@ -51,21 +65,31 @@ class Strelka::Session::Db < Strelka::Session::Default
|
|
51
65
|
### Configure the session class with the given +options+, which should be a
|
52
66
|
### Hash or an object that has a Hash-like interface.
|
53
67
|
###
|
54
|
-
### Valid options:
|
55
|
-
###
|
56
|
-
###
|
57
|
-
###
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
+
### Valid options (in addition to those ):
|
69
|
+
###
|
70
|
+
### [cookie_name]::
|
71
|
+
### The name of the cookie to use for the session ID
|
72
|
+
### [cookie_options]::
|
73
|
+
### Options to pass to Strelka::Cookie's constructor.
|
74
|
+
### [connect]::
|
75
|
+
### The Sequel connection string; if nil, an in-memory DB will be used.
|
76
|
+
### [table_name]::
|
77
|
+
### The name of the sessions table. Defaults to 'sessions'.
|
78
|
+
def self::configure( options=nil )
|
79
|
+
super
|
80
|
+
|
81
|
+
if options
|
82
|
+
self.table_name = options[:table_name]
|
83
|
+
self.db = options[ :connect ].nil? ?
|
84
|
+
Mongrel2::Config.in_memory_db :
|
85
|
+
Sequel.connect( options[:connect] )
|
86
|
+
else
|
87
|
+
self.table_name = CONFIG_DEFAULTS[:table_name]
|
88
|
+
self.db = Mongrel2::Config.in_memory_db
|
89
|
+
end
|
68
90
|
|
91
|
+
self.db.logger = Loggability[ Mongrel2 ].proxy_for( self.db )
|
92
|
+
self.db.sql_log_level = :debug
|
69
93
|
self.initialize_sessions_table
|
70
94
|
end
|
71
95
|
|
@@ -74,12 +98,12 @@ class Strelka::Session::Db < Strelka::Session::Default
|
|
74
98
|
### attribute to a Sequel dataset on the configured DB table.
|
75
99
|
###
|
76
100
|
def self::initialize_sessions_table
|
77
|
-
if self.db.table_exists?(
|
101
|
+
if self.db.table_exists?( self.table_name )
|
78
102
|
self.log.debug "Using existing sessions table for %p" % [ db ]
|
79
103
|
|
80
104
|
else
|
81
105
|
self.log.debug "Creating new sessions table for %p" % [ db ]
|
82
|
-
self.db.create_table(
|
106
|
+
self.db.create_table( self.table_name ) do
|
83
107
|
text :session_id, :index => true
|
84
108
|
text :session
|
85
109
|
timestamp :created
|
@@ -88,7 +112,7 @@ class Strelka::Session::Db < Strelka::Session::Default
|
|
88
112
|
end
|
89
113
|
end
|
90
114
|
|
91
|
-
|
115
|
+
self.dataset = self.db[ self.table_name.to_sym ]
|
92
116
|
end
|
93
117
|
|
94
118
|
|
@@ -12,45 +12,64 @@ require 'strelka/session'
|
|
12
12
|
require 'strelka/mixins'
|
13
13
|
|
14
14
|
# Default session class -- simple in-memory, cookie-based base-bones session.
|
15
|
-
#
|
16
|
-
# == Hash Interface
|
17
|
-
#
|
18
|
-
# The following methods are delegated to the inner Hash via the #namespaced_hash method:
|
19
|
-
# #[], #[]=, #delete, #key?
|
20
15
|
class Strelka::Session::Default < Strelka::Session
|
21
|
-
extend
|
16
|
+
extend Configurability,
|
22
17
|
Forwardable,
|
23
18
|
Strelka::MethodUtilities,
|
24
19
|
Strelka::Delegation
|
25
20
|
include Strelka::DataUtilities
|
26
21
|
|
22
|
+
|
23
|
+
##
|
24
|
+
# Configurability API -- use the 'defaultsession' section of the config
|
25
|
+
config_key :defaultsession
|
26
|
+
|
27
27
|
# Default configuration
|
28
|
-
|
29
|
-
:
|
28
|
+
CONFIG_DEFAULTS = {
|
29
|
+
cookie_name: 'strelka-session',
|
30
|
+
cookie_options: {
|
31
|
+
expires: "+1d",
|
32
|
+
}
|
30
33
|
}.freeze
|
31
34
|
|
32
35
|
|
33
36
|
# Class-instance variables
|
34
|
-
@
|
35
|
-
@
|
37
|
+
@sessions = {}
|
38
|
+
@cookie_name = CONFIG_DEFAULTS[:cookie_name]
|
39
|
+
@cookie_options = {}
|
36
40
|
|
37
41
|
##
|
38
42
|
# In-memory session store
|
39
43
|
singleton_attr_reader :sessions
|
40
44
|
|
41
45
|
##
|
42
|
-
# The
|
46
|
+
# The name of the session cookie
|
47
|
+
singleton_attr_accessor :cookie_name
|
48
|
+
|
49
|
+
##
|
50
|
+
# Session cookie options; see {Strelka::Cookie}[rdoc-ref://Strelka::Cookie.new]
|
51
|
+
# for available options.
|
43
52
|
singleton_attr_accessor :cookie_options
|
44
53
|
|
45
54
|
|
46
55
|
### Configure the session class with the given +options+, which should be a
|
47
|
-
### Hash or an object that has a Hash-like interface.
|
48
|
-
###
|
49
|
-
|
50
|
-
|
51
|
-
|
56
|
+
### Hash or an object that has a Hash-like interface.
|
57
|
+
###
|
58
|
+
### Valid keys:
|
59
|
+
###
|
60
|
+
### [\cookie_name]
|
61
|
+
### The name of the cookie that will be used for persisting the session key.
|
62
|
+
### [\cookie_options]
|
63
|
+
### A hash of options for the session cookie; see
|
64
|
+
### {Strelka::Cookie}[rdoc-ref://Strelka::Cookie.new]
|
65
|
+
### for available options.
|
66
|
+
def self::configure( config=nil )
|
67
|
+
if config
|
68
|
+
self.cookie_name = config[:cookie_name]
|
69
|
+
self.cookie_options = config[:cookie_options]
|
52
70
|
else
|
53
|
-
self.
|
71
|
+
self.cookie_name = CONFIG_DEFAULTS[:cookie_name]
|
72
|
+
self.cookie_options = CONFIG_DEFAULTS[:cookie_options].dup
|
54
73
|
end
|
55
74
|
end
|
56
75
|
|
@@ -77,7 +96,7 @@ class Strelka::Session::Default < Strelka::Session
|
|
77
96
|
### Try to fetch a session ID from the specified +request+, returning +nil+
|
78
97
|
### if there isn't one.
|
79
98
|
def self::get_existing_session_id( request )
|
80
|
-
cookie = request.cookies[ self.
|
99
|
+
cookie = request.cookies[ self.cookie_name ] or return nil
|
81
100
|
|
82
101
|
if cookie.value =~ /^([[:xdigit:]]+)$/i
|
83
102
|
return $1.untaint
|
@@ -141,6 +160,7 @@ class Strelka::Session::Default < Strelka::Session
|
|
141
160
|
# to the application.
|
142
161
|
attr_reader :namespace
|
143
162
|
|
163
|
+
##
|
144
164
|
# Delegate Hash methods to whichever Hash is the current namespace
|
145
165
|
def_method_delegators :namespaced_hash, :[], :[]=, :delete, :key?
|
146
166
|
|
@@ -160,7 +180,7 @@ class Strelka::Session::Default < Strelka::Session
|
|
160
180
|
self.log.debug "Adding session cookie to the request."
|
161
181
|
|
162
182
|
session_cookie = Strelka::Cookie.new(
|
163
|
-
self.class.
|
183
|
+
self.class.cookie_name,
|
164
184
|
self.session_id,
|
165
185
|
self.class.cookie_options
|
166
186
|
)
|