culpa 2.0.1 → 2.1.1
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.
- checksums.yaml +4 -4
- data/bin/culpa +4 -0
- data/lib/culpa.rb +29 -14
- data/lib/culpa/action.rb +3 -2
- data/lib/culpa/brickchain_helpers.rb +11 -7
- data/lib/culpa/envelope.rb +1 -3
- data/lib/culpa/session.rb +27 -0
- data/lib/culpa/session_drivers/in_memory.rb +66 -0
- data/lib/culpa/test_helpers.rb +7 -1
- data/lib/culpa/version.rb +1 -1
- data/templates/culpa/Gemfile +4 -2
- data/templates/culpa/config.yml +10 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03c0b8f371e586acd616e7bb39cef52ee97f5d47
|
4
|
+
data.tar.gz: 4ea587fdcbf158a2d3a4c9287fb05ae356b6df3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e6036bf3ab63c1cdbf1ecd5fb4b4661b25d44c13f369e496ff1cccea831697b4bc4394a6598eb52e711efde67f7cbabd6642c740053319313d9951eb66ec863
|
7
|
+
data.tar.gz: c9de6db1d777c3c79f4bdf9acac33495393dd3b3a4a3981df80df8d38e2b393920e1e411d21a82c66ab00e5f698d3f0e9c84202838913e6ac66f943bda45887c
|
data/bin/culpa
CHANGED
@@ -34,6 +34,10 @@ def create_project(project_path)
|
|
34
34
|
config_rackup_path = File.join(File.dirname(__FILE__), '../templates/culpa/config.ru')
|
35
35
|
FileUtils.cp config_rackup_path, "#{project_path}/config.ru"
|
36
36
|
|
37
|
+
puts '==> Copying standard config.yml'
|
38
|
+
config_yml_path = File.join(File.dirname(__FILE__), '../templates/culpa/config.yml')
|
39
|
+
FileUtils.cp config_yml_path, "#{project_path}/config/config.yml"
|
40
|
+
|
37
41
|
puts '==> Copying Dockerfile'
|
38
42
|
dockerfile_rackup_path = File.join(File.dirname(__FILE__), '../templates/culpa/Dockerfile')
|
39
43
|
FileUtils.cp dockerfile_rackup_path, "#{project_path}/Dockerfile"
|
data/lib/culpa.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative 'culpa/path_parser'
|
|
8
8
|
require_relative 'culpa/routes_builder'
|
9
9
|
require_relative 'culpa/brickchain_helpers'
|
10
10
|
require_relative 'culpa/version'
|
11
|
+
require_relative 'culpa/session'
|
11
12
|
|
12
13
|
ACTIONS_PATH ||= './actions/*.rb'.freeze
|
13
14
|
MODELS_PATH ||= './models/*.rb'.freeze
|
@@ -52,6 +53,8 @@ module Culpa
|
|
52
53
|
bc_path = options[:brickchains] || './config/brickchains.rb'
|
53
54
|
route_builder = RoutesBuilder.new(File.read(bc_path))
|
54
55
|
@router = route_builder.result
|
56
|
+
# Loads configuration file
|
57
|
+
@configuration = YAML.load_file(options[:config] || './config/config.yml')
|
55
58
|
PathParser.create_route_cache(@router, route_builder.prefix || '')
|
56
59
|
# Setting static file directory
|
57
60
|
@public_folder = options[:public] || route_builder.public_folder || './public'
|
@@ -92,9 +95,17 @@ module Culpa
|
|
92
95
|
else
|
93
96
|
request[:input] = env['rack.input']
|
94
97
|
end
|
95
|
-
# Extract vars from path, take route decision and go !
|
98
|
+
# Extract vars from path, creates session object, take route decision and go !
|
99
|
+
session_id = env.has_key?('HTTP_X_SESSION_ID') ? env['HTTP_X_SESSION_ID'] : nil
|
100
|
+
session_obj = if @configuration.has_key? 'session'
|
101
|
+
Session.new(@configuration['session']['driver'],
|
102
|
+
@configuration['session']['configuration'],
|
103
|
+
session_id)
|
104
|
+
else
|
105
|
+
Session.new('InMemory', {'duration' => 600}, session_id)
|
106
|
+
end
|
96
107
|
method_name, f_request = PathParser.extract_vars(env['PATH_INFO'], request)
|
97
|
-
call_brickchain method_name, f_request
|
108
|
+
call_brickchain method_name, f_request, session_obj
|
98
109
|
rescue UnpredictableSubCallError, MultiJson::ParseError
|
99
110
|
# The sub_call wasn't predictacle, or the body wans't correct JSON.
|
100
111
|
# In both cases, it is a bad_request.
|
@@ -127,7 +138,7 @@ module Culpa
|
|
127
138
|
|
128
139
|
##
|
129
140
|
# Call a brickchain using the method_name associated to it
|
130
|
-
def call_brickchain(router_method_name, options)
|
141
|
+
def call_brickchain(router_method_name, options, session_obj)
|
131
142
|
# Loading the router method
|
132
143
|
raise RouteNotFoundError unless @router.key? router_method_name
|
133
144
|
route = @router[router_method_name]
|
@@ -137,34 +148,38 @@ module Culpa
|
|
137
148
|
request = EnvelopeRequest.new(options)
|
138
149
|
# Execute before blocks in the brickchain
|
139
150
|
route[:before].each do |before_block|
|
140
|
-
BrickchainExecutor.new(envelope, request).instance_eval(&before_block)
|
151
|
+
BrickchainExecutor.new(envelope, request, session_obj).instance_eval(&before_block)
|
141
152
|
end if route.key? :before
|
142
153
|
# Execute the brickchain itself
|
143
154
|
if route.key? :block
|
144
|
-
BrickchainExecutor.new(envelope, request).instance_eval(&route[:block])
|
155
|
+
BrickchainExecutor.new(envelope, request, session_obj).instance_eval(&route[:block])
|
145
156
|
else
|
146
|
-
ch = CallHolder.new(route[:brick_name], envelope, request)
|
157
|
+
ch = CallHolder.new(route[:brick_name], envelope, request, session_obj)
|
147
158
|
ch.from(route[:class_name])
|
148
159
|
end
|
149
160
|
# If we come to this point, the brickchain haven't raised the RenderNow.
|
150
161
|
# It means there is a problem with the brickchain since it has a path
|
151
162
|
# that didn't render.
|
163
|
+
session_obj.close
|
152
164
|
raise NoRenderCalled
|
153
165
|
rescue Action::RenderNow => renderer
|
154
|
-
return do_render(renderer.to_render)
|
166
|
+
return do_render(renderer.to_render, session_obj)
|
155
167
|
end
|
156
168
|
|
157
169
|
##
|
158
170
|
# Method called after a correct Action::RenderNow have been raised
|
159
|
-
def do_render(to_render)
|
171
|
+
def do_render(to_render, session_obj)
|
160
172
|
body = case to_render[:format]
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
173
|
+
when :json
|
174
|
+
[::MultiJson.dump(to_render[:object], pretty: ENV['RACK_ENV'] == 'development')]
|
175
|
+
when :string
|
176
|
+
[to_render[:object]]
|
177
|
+
when :file_from_path, :file_from_io
|
178
|
+
to_render[:object]
|
179
|
+
when :status
|
180
|
+
[]
|
167
181
|
end
|
182
|
+
session_obj.close
|
168
183
|
[to_render[:status], to_render[:headers], body]
|
169
184
|
end
|
170
185
|
|
data/lib/culpa/action.rb
CHANGED
@@ -17,7 +17,7 @@ class Action
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
attr_reader :e, :r
|
20
|
+
attr_reader :e, :r, :session
|
21
21
|
|
22
22
|
class RenderNow < StandardError
|
23
23
|
attr_reader :to_render
|
@@ -26,9 +26,10 @@ class Action
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def initialize(envelope, request)
|
29
|
+
def initialize(envelope, request, session)
|
30
30
|
@e = envelope
|
31
31
|
@r = request
|
32
|
+
@session = session
|
32
33
|
end
|
33
34
|
|
34
35
|
def method_missing(sym)
|
@@ -2,6 +2,7 @@ module Culpa
|
|
2
2
|
|
3
3
|
class BrickchainExecutor
|
4
4
|
attr_reader :envelope
|
5
|
+
attr_reader :session
|
5
6
|
|
6
7
|
@@injected_keywords = {}
|
7
8
|
|
@@ -9,13 +10,14 @@ module Culpa
|
|
9
10
|
@@injected_keywords[keyword] = call
|
10
11
|
end
|
11
12
|
|
12
|
-
def initialize(envelope, request)
|
13
|
+
def initialize(envelope, request, session)
|
13
14
|
@envelope = envelope
|
14
15
|
@request = request
|
16
|
+
@session = session
|
15
17
|
end
|
16
18
|
|
17
19
|
def async(&blk)
|
18
|
-
asb = AsyncBrickchain.new(@envelope, @request)
|
20
|
+
asb = AsyncBrickchain.new(@envelope, @request, @session)
|
19
21
|
asb.instance_eval(&blk)
|
20
22
|
asb.chs.each { |call_holder| call_holder.thread.join }
|
21
23
|
end
|
@@ -29,7 +31,7 @@ module Culpa
|
|
29
31
|
method = @@injected_keywords[sym]
|
30
32
|
instance_exec args, &method
|
31
33
|
else
|
32
|
-
CallHolder.new(sym.to_s, @envelope, @request)
|
34
|
+
CallHolder.new(sym.to_s, @envelope, @request, @session)
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
@@ -38,14 +40,15 @@ module Culpa
|
|
38
40
|
attr_reader :envelope
|
39
41
|
attr_reader :chs
|
40
42
|
|
41
|
-
def initialize(envelope, request)
|
43
|
+
def initialize(envelope, request, session)
|
42
44
|
@envelope = envelope
|
43
45
|
@request = request
|
46
|
+
@session = session
|
44
47
|
@chs = []
|
45
48
|
end
|
46
49
|
|
47
50
|
def method_missing(sym)
|
48
|
-
@chs << CallHolder.new(sym.to_s, @envelope, @request, true)
|
51
|
+
@chs << CallHolder.new(sym.to_s, @envelope, @request, @session, true)
|
49
52
|
@chs.last
|
50
53
|
end
|
51
54
|
end
|
@@ -53,10 +56,11 @@ module Culpa
|
|
53
56
|
class CallHolder
|
54
57
|
attr_reader :thread
|
55
58
|
|
56
|
-
def initialize(brickname, envelope, request, async = false)
|
59
|
+
def initialize(brickname, envelope, request, session, async = false)
|
57
60
|
@brickname = brickname
|
58
61
|
@envelope = envelope
|
59
62
|
@request = request
|
63
|
+
@session = session
|
60
64
|
@async = async
|
61
65
|
end
|
62
66
|
|
@@ -76,7 +80,7 @@ module Culpa
|
|
76
80
|
|
77
81
|
def get_action(name)
|
78
82
|
action_name = name.split('_').map(&:capitalize).join
|
79
|
-
Actions.const_get(action_name).new(@envelope, @request)
|
83
|
+
Actions.const_get(action_name).new(@envelope, @request, @session)
|
80
84
|
end
|
81
85
|
|
82
86
|
end
|
data/lib/culpa/envelope.rb
CHANGED
@@ -29,9 +29,7 @@ module Culpa
|
|
29
29
|
def ==(other_envelope)
|
30
30
|
return false unless other_envelope.is_a? Envelope
|
31
31
|
return false unless other_envelope.instance_variables.count == instance_variables.count
|
32
|
-
instance_variables.select do |iv|
|
33
|
-
iv != :@semaphore
|
34
|
-
end.each do |iv|
|
32
|
+
instance_variables.select{ |iv| iv != :@semaphore }.each do |iv|
|
35
33
|
return false unless instance_variable_get(iv) == other_envelope.instance_variable_get(iv)
|
36
34
|
end
|
37
35
|
true
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'session_drivers/in_memory'
|
2
|
+
|
3
|
+
# This is the decorator class against Session drivers
|
4
|
+
class Session
|
5
|
+
|
6
|
+
def initialize(backend, options, session_id)
|
7
|
+
@backend = Culpa::SessionDrivers.const_get(backend).new(options, session_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
def close
|
11
|
+
@backend.close if @backend.respond_to? :close
|
12
|
+
end
|
13
|
+
|
14
|
+
def id
|
15
|
+
@backend.session_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_keys?(*keys)
|
19
|
+
keys.each { |key| return false unless @backend.has_key?(key) }
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(sym, *args, &blk)
|
24
|
+
@backend.send(sym, *args, &blk)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Culpa::SessionDrivers
|
4
|
+
|
5
|
+
class InMemory
|
6
|
+
|
7
|
+
attr_reader :session_id
|
8
|
+
|
9
|
+
@@persist = {}
|
10
|
+
|
11
|
+
def initialize(options, session_id)
|
12
|
+
@options = options
|
13
|
+
@session_id = session_id || SecureRandom.hex
|
14
|
+
generate_session_struct unless session_exists?
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear!
|
18
|
+
@@persist.delete(@session_id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def [](k)
|
22
|
+
return nil unless is_valid?
|
23
|
+
session_prologation
|
24
|
+
@@persist[@session_id][:data][k]
|
25
|
+
end
|
26
|
+
|
27
|
+
def []=(k,v)
|
28
|
+
session_prologation
|
29
|
+
@@persist[@session_id][:data][k] = v
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_key?(key)
|
33
|
+
return false unless is_valid?
|
34
|
+
@@persist[@session_id][:data].has_key? key
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge!(new_hash)
|
38
|
+
@@persist[@session_id][:data].merge!(new_hash)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def session_exists?
|
44
|
+
@@persist.has_key?(@session_id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_session_struct
|
48
|
+
unless @@persist.has_key?(@session_id)
|
49
|
+
@@persist[@session_id] = {}
|
50
|
+
@@persist[@session_id][:data] = {}
|
51
|
+
@@persist[@session_id][:expire] = Time.new.to_i + @options['duration']
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_valid?
|
56
|
+
@@persist.has_key?(@session_id) and \
|
57
|
+
@@persist[@session_id][:expire] > Time.new.to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def session_prologation
|
61
|
+
@@persist[@session_id][:expire] = Time.new.to_i + @options['duration']
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/culpa/test_helpers.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative 'envelope'
|
2
2
|
require_relative 'action'
|
3
|
+
require_relative 'session'
|
3
4
|
require 'rspec/expectations'
|
4
5
|
|
5
6
|
module CulpaHelpers
|
@@ -22,6 +23,7 @@ module CulpaHelpers
|
|
22
23
|
|
23
24
|
def initialize(brick_name)
|
24
25
|
@brick_name = brick_name.to_s
|
26
|
+
@session = Session.new('InMemory', {'duration' => 600}, nil)
|
25
27
|
@from_done = false
|
26
28
|
end
|
27
29
|
|
@@ -31,6 +33,10 @@ module CulpaHelpers
|
|
31
33
|
self
|
32
34
|
end
|
33
35
|
|
36
|
+
def with_session(hash)
|
37
|
+
@session.merge!(hash)
|
38
|
+
end
|
39
|
+
|
34
40
|
def with(opts)
|
35
41
|
opts[:envelope] ||= {}
|
36
42
|
@envelope = Culpa::Envelope.new(opts[:envelope])
|
@@ -44,7 +50,7 @@ module CulpaHelpers
|
|
44
50
|
return @call_cache if @call_done
|
45
51
|
@envelope ||= Culpa::Envelope.new({})
|
46
52
|
@params ||= Culpa::EnvelopeRequest.new({})
|
47
|
-
@action_const.new(@envelope, @params).send(@brick_name)
|
53
|
+
@action_const.new(@envelope, @params, @session).send(@brick_name)
|
48
54
|
@call_done = true
|
49
55
|
return @call_cache = { to_render: nil, envelope: @envelope }
|
50
56
|
rescue Action::RenderNow => renderer
|
data/lib/culpa/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
CULPA_VERSION = '2.
|
1
|
+
CULPA_VERSION = '2.1.1'.freeze
|
data/templates/culpa/Gemfile
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
# The MEA framework
|
4
|
-
gem 'culpa', '~> 2.
|
4
|
+
gem 'culpa', '~> 2.1'
|
5
5
|
# Coliseum extension to describe JSON in an elegent way
|
6
|
-
gem 'culpa-coliseum', '~> 2.
|
6
|
+
gem 'culpa-coliseum', '~> 2.1'
|
7
|
+
# If you want to use Redis as a backend for sessions, uncomment :
|
8
|
+
# gem 'culpa-redis', '~> 2.1'
|
7
9
|
|
8
10
|
# Use rspec to test your project.
|
9
11
|
gem 'rspec', '~> 3.4'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: culpa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jérémy SEBAN
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -84,11 +84,14 @@ files:
|
|
84
84
|
- lib/culpa/renderers/json.rb
|
85
85
|
- lib/culpa/renderers/status.rb
|
86
86
|
- lib/culpa/routes_builder.rb
|
87
|
+
- lib/culpa/session.rb
|
88
|
+
- lib/culpa/session_drivers/in_memory.rb
|
87
89
|
- lib/culpa/test_helpers.rb
|
88
90
|
- lib/culpa/version.rb
|
89
91
|
- templates/culpa/Dockerfile
|
90
92
|
- templates/culpa/Gemfile
|
91
93
|
- templates/culpa/config.ru
|
94
|
+
- templates/culpa/config.yml
|
92
95
|
- templates/culpa/generators/action.tmpl
|
93
96
|
- templates/culpa/index.html
|
94
97
|
- templates/culpa/logo.png
|