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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f32f675f29fa3dabc13a81c5862761de1452734a
4
- data.tar.gz: 53d2dc0997562fb55f6eb4a1723fb805caf84ceb
3
+ metadata.gz: 03c0b8f371e586acd616e7bb39cef52ee97f5d47
4
+ data.tar.gz: 4ea587fdcbf158a2d3a4c9287fb05ae356b6df3a
5
5
  SHA512:
6
- metadata.gz: 974d73a51e9ac4b4ebc8f905dd341bc6968f606fdd8c58e949f2b44aa91d4173f5e8ab237ff1efb2b6bd4f67bbdd05dfe578d18442eda0ef0ad343ea2f9147c0
7
- data.tar.gz: 71c74d3e04522db35ac7ece51b8a9a612660935b0901730988f5dd793c6d336692d7f659579325a1f7a46fbf2ee53ed21af3b31f4604d9be616bd4812dd428c3
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"
@@ -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
- when :json
162
- [::MultiJson.dump(to_render[:object], pretty: ENV['RACK_ENV'] == 'development')]
163
- when :file_from_path, :file_from_io
164
- to_render[:object]
165
- when :status
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
 
@@ -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
@@ -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
@@ -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
@@ -1 +1 @@
1
- CULPA_VERSION = '2.0.1'.freeze
1
+ CULPA_VERSION = '2.1.1'.freeze
@@ -1,9 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # The MEA framework
4
- gem 'culpa', '~> 2.0'
4
+ gem 'culpa', '~> 2.1'
5
5
  # Coliseum extension to describe JSON in an elegent way
6
- gem 'culpa-coliseum', '~> 2.0'
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'
@@ -0,0 +1,10 @@
1
+ # This is the main configuration file of Culpa
2
+ # Check the guides at http://culpaframework.org/guides.html for more information
3
+
4
+ production:
5
+ log_level: WARN
6
+
7
+ session:
8
+ driver: InMemory
9
+ configuration:
10
+ duration: 600
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.0.1
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: 2016-12-27 00:00:00.000000000 Z
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