strelka 0.0.1.pre.244 → 0.0.1.pre.252
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.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
|
)
|