lux-fw 0.5.36 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/bin/README.md +26 -13
  4. data/bin/cli/benchmark.rb +18 -0
  5. data/bin/cli/cerb.rb +90 -0
  6. data/bin/cli/config.rb +4 -11
  7. data/bin/cli/console.rb +72 -30
  8. data/bin/cli/eval.rb +5 -27
  9. data/bin/cli/generate.rb +9 -11
  10. data/bin/cli/get.rb +14 -6
  11. data/bin/cli/memory.rb +12 -0
  12. data/bin/cli/new.rb +2 -0
  13. data/bin/cli/secrets.rb +3 -31
  14. data/bin/cli/server.rb +28 -9
  15. data/bin/cli/stats.rb +26 -20
  16. data/bin/cli/template.rb +10 -0
  17. data/bin/generate_doc +168 -0
  18. data/bin/lux +73 -10
  19. data/lib/README.md +18 -8
  20. data/lib/common/crypt.rb +60 -9
  21. data/lib/common/string_base.rb +54 -15
  22. data/lib/common/struct_opts.rb +30 -0
  23. data/lib/common/time_difference.rb +75 -0
  24. data/lib/loader.rb +41 -0
  25. data/lib/lux/application/README.md +67 -105
  26. data/lib/lux/application/application.rb +87 -329
  27. data/lib/lux/application/lib/magic_routes.rb +22 -0
  28. data/lib/lux/application/lib/nav.rb +218 -99
  29. data/lib/lux/application/lib/render.rb +47 -67
  30. data/lib/lux/application/lib/routes.rb +242 -0
  31. data/lib/lux/application/lib/shared.rb +47 -0
  32. data/lib/lux/application/lux_adapter.rb +6 -0
  33. data/lib/lux/application/lux_config.rb +26 -0
  34. data/lib/lux/cache/Find Results +24 -0
  35. data/lib/lux/cache/README.md +28 -35
  36. data/lib/lux/cache/cache.rb +78 -26
  37. data/lib/lux/cache/lib/memcached_server.rb +36 -0
  38. data/lib/lux/cache/lib/memory_server.rb +44 -0
  39. data/lib/lux/cache/lib/null_server.rb +33 -0
  40. data/lib/lux/cache/lib/sqlite_server.rb +62 -0
  41. data/lib/lux/cache/lux_adapter.rb +19 -0
  42. data/lib/lux/config/config.rb +93 -144
  43. data/lib/lux/config/lux_adapter.rb +27 -0
  44. data/lib/lux/controller/README.md +67 -12
  45. data/lib/lux/controller/controller.rb +237 -187
  46. data/lib/lux/current/README.md +29 -10
  47. data/lib/lux/current/current.rb +166 -77
  48. data/lib/lux/current/lib/current.rb +6 -0
  49. data/lib/lux/current/lib/encrypt_params.rb +38 -36
  50. data/lib/lux/current/lib/session.rb +86 -65
  51. data/lib/lux/current/lux_adapter.rb +5 -0
  52. data/lib/lux/environment/README.md +24 -0
  53. data/lib/lux/environment/environment.rb +91 -0
  54. data/lib/lux/environment/lux_adapter.rb +13 -0
  55. data/lib/lux/error/README.md +18 -19
  56. data/lib/lux/error/error.rb +207 -152
  57. data/lib/lux/error/lux_adapter.rb +9 -0
  58. data/lib/lux/logger/README.md +45 -0
  59. data/lib/lux/logger/lux_adapter.rb +27 -0
  60. data/lib/lux/lux.rb +72 -129
  61. data/lib/lux/mailer/README.md +12 -5
  62. data/lib/lux/mailer/lux_config.rb +4 -0
  63. data/lib/lux/mailer/mailer.rb +81 -59
  64. data/lib/lux/plugin/README.md +19 -0
  65. data/lib/lux/plugin/lux_adapter.rb +8 -0
  66. data/lib/lux/plugin/plugin.rb +65 -0
  67. data/lib/lux/render/README.md +100 -0
  68. data/lib/lux/render/render.rb +12 -0
  69. data/lib/lux/response/README.md +57 -1
  70. data/lib/lux/response/lib/file.rb +87 -65
  71. data/lib/lux/response/lib/flash.rb +49 -34
  72. data/lib/lux/response/lib/header.rb +34 -33
  73. data/lib/lux/response/response.rb +252 -164
  74. data/lib/lux/template/helper.rb +130 -0
  75. data/lib/lux/template/inline_render_proxy.rb +31 -0
  76. data/lib/lux/template/lux_adapter.rb +5 -0
  77. data/lib/lux/template/template.rb +127 -0
  78. data/lib/lux-fw.rb +15 -33
  79. data/lib/overload/array.rb +33 -7
  80. data/lib/overload/blank.rb +8 -3
  81. data/lib/overload/boolean.rb +46 -0
  82. data/lib/overload/class.rb +28 -0
  83. data/lib/overload/dir.rb +117 -7
  84. data/lib/overload/file.rb +40 -5
  85. data/lib/overload/float.rb +38 -3
  86. data/lib/overload/hash.rb +81 -91
  87. data/lib/overload/integer.rb +15 -0
  88. data/lib/overload/json.rb +26 -0
  89. data/lib/overload/nil.rb +4 -8
  90. data/lib/overload/object.rb +91 -24
  91. data/lib/overload/pathname.rb +11 -0
  92. data/lib/overload/raise_variants.rb +26 -36
  93. data/lib/overload/string.rb +100 -27
  94. data/lib/overload/thread_simple.rb +100 -0
  95. data/lib/overload/time.rb +60 -38
  96. data/tasks/loader.rb +20 -7
  97. metadata +170 -169
  98. data/bin/.DS_Store +0 -0
  99. data/bin/build_gem +0 -77
  100. data/bin/cli/dbconsole.rb +0 -8
  101. data/bin/cli/routes.rb +0 -90
  102. data/lib/.DS_Store +0 -0
  103. data/lib/common/.DS_Store +0 -0
  104. data/lib/common/class_attributes.rb +0 -51
  105. data/lib/common/class_callbacks.rb +0 -47
  106. data/lib/common/free_struct.rb +0 -42
  107. data/lib/common/hash_with_indifferent_access.rb +0 -74
  108. data/lib/common/html_tag_builder.rb +0 -91
  109. data/lib/common/method_attr.rb +0 -69
  110. data/lib/common/url.rb +0 -191
  111. data/lib/lux/.DS_Store +0 -0
  112. data/lib/lux/README.md +0 -10
  113. data/lib/lux/cache/.DS_Store +0 -0
  114. data/lib/lux/cache/lib/memory.rb +0 -36
  115. data/lib/lux/cache/lib/null.rb +0 -21
  116. data/lib/lux/config/README.md +0 -63
  117. data/lib/lux/config/lib/plugin.rb +0 -65
  118. data/lib/lux/config/lib/secrets.rb +0 -48
  119. data/lib/lux/current/.DS_Store +0 -0
  120. data/lib/lux/delayed_job/.DS_Store +0 -0
  121. data/lib/lux/delayed_job/README.md +0 -3
  122. data/lib/lux/delayed_job/delayed_job.rb +0 -51
  123. data/lib/lux/delayed_job/lib/memory.rb +0 -16
  124. data/lib/lux/delayed_job/lib/nsq.rb +0 -3
  125. data/lib/lux/delayed_job/lib/postgre.rb +0 -6
  126. data/lib/lux/delayed_job/lib/redis.rb +0 -19
  127. data/lib/lux/event_bus/README.md +0 -36
  128. data/lib/lux/event_bus/event_bus.rb +0 -27
  129. data/lib/lux/view/README.md +0 -85
  130. data/lib/lux/view/cell.rb +0 -102
  131. data/lib/lux/view/helper.rb +0 -120
  132. data/lib/lux/view/lib/cell_helpers.rb +0 -29
  133. data/lib/lux/view/view.rb +0 -95
  134. data/lib/overload/it.rb +0 -29
  135. data/plugins/api/README.md +0 -49
  136. data/plugins/api/api.rb +0 -153
  137. data/plugins/api/lib/attr.rb +0 -31
  138. data/plugins/api/lib/dsl.rb +0 -52
  139. data/plugins/api/lib/error.rb +0 -3
  140. data/plugins/api/lib/model_api.rb +0 -203
  141. data/plugins/api/lib/response.rb +0 -85
  142. data/plugins/db/.DS_Store +0 -0
  143. data/plugins/db/README.md +0 -29
  144. data/plugins/db/auto_migrate/auto_migrate.rb +0 -268
  145. data/plugins/db/auto_migrate/db.rake +0 -15
  146. data/plugins/db/helpers/array_search.rb +0 -27
  147. data/plugins/db/helpers/before_save_filters.rb +0 -32
  148. data/plugins/db/helpers/composite_primary_keys.rb +0 -36
  149. data/plugins/db/helpers/core.rb +0 -94
  150. data/plugins/db/helpers/dataset_methods.rb +0 -138
  151. data/plugins/db/helpers/enums_plugin.rb +0 -52
  152. data/plugins/db/helpers/find_precache.rb +0 -31
  153. data/plugins/db/helpers/link_objects.rb +0 -84
  154. data/plugins/db/helpers/schema_checks.rb +0 -83
  155. data/plugins/db/helpers/typero_adapter.rb +0 -71
  156. data/plugins/db/logger/config.rb +0 -22
  157. data/plugins/db/logger/lux_response_adapter.rb +0 -10
  158. data/plugins/db/paginate/helper.rb +0 -32
  159. data/plugins/db/paginate/sequel_adapter.rb +0 -23
  160. data/plugins/exceptions/exceptions.rake +0 -43
  161. data/plugins/exceptions/simple_exception.rb +0 -64
  162. data/plugins/favicon/favicon.rb +0 -10
  163. data/plugins/html/README.md +0 -3
  164. data/plugins/html/html_form.rb +0 -118
  165. data/plugins/html/html_input.rb +0 -98
  166. data/plugins/html/html_menu.rb +0 -79
  167. data/plugins/html/input_types.rb +0 -346
  168. data/plugins/js_widgets/README.md +0 -5
  169. data/plugins/js_widgets/js/html_tag.coffee +0 -42
  170. data/plugins/js_widgets/js/widgets.coffee +0 -161
  171. data/plugins/js_widgets/js_widgets.rb +0 -15
  172. data/plugins/oauth/lib/facebook.rb +0 -35
  173. data/plugins/oauth/lib/github.rb +0 -38
  174. data/plugins/oauth/lib/google.rb +0 -41
  175. data/plugins/oauth/lib/linkedin.rb +0 -41
  176. data/plugins/oauth/lib/stackexchange.rb +0 -41
  177. data/plugins/oauth/lib/twitter.rb +0 -38
  178. data/plugins/oauth/oauth.rb +0 -42
  179. data/plugins/policy/policy.rb +0 -53
  180. data/tasks/nginx.rake +0 -23
  181. /data/lib/lux/{view/lib → mailer}/helper_modules.rb +0 -0
@@ -1,107 +1,196 @@
1
- # frozen_string_literal: true
1
+ module Lux
2
+ class Current
3
+ # set to true if user is admin and you want him to be able to clear caches in production
4
+ attr_accessor :can_clear_cache
5
+
6
+ attr_accessor :session, :locale, :error
7
+ attr_reader :request, :response, :nav, :var, :env, :params
8
+
9
+ def initialize env = nil, opts = {}
10
+ @env = env || '/mock'
11
+ @env = ::Rack::MockRequest.env_for(env) if env.is_a?(String)
12
+ @request = ::Rack::Request.new @env
13
+
14
+ # fix params if defined
15
+ if opts.keys.length > 0
16
+ opts = opts.to_hwia :params, :post, :method, :session, :cookies, :query_string
17
+
18
+ if opts[:post]
19
+ opts[:method] = 'POST'
20
+ opts[:params] = opts[:post]
21
+ end
22
+ end
23
+
24
+ # reset page cache
25
+ Thread.current[:lux] = self
2
26
 
3
- # we need this for command line
4
- Thread.current[:lux] ||= { cache: {} }
27
+ # overload request method
28
+ @request.env['REQUEST_METHOD'] = opts[:method].to_s.upcase if opts[:method]
5
29
 
6
- class Lux::Current
7
- # set to true if user is admin and you want him to be able to clear caches in production
8
- attr_accessor :can_clear_cache
30
+ # set cookies
31
+ @request.cookies.merge opts[:cookies] if opts[:cookies]
9
32
 
10
- attr_accessor :session, :locale
11
- attr_reader :request, :response, :nav
33
+ prepare_params opts
12
34
 
13
- def initialize env=nil
14
- env ||= '/mock'
15
- env = ::Rack::MockRequest.env_for(env) if env.is_a?(String)
16
- request = ::Rack::Request.new env
35
+ # base vars
36
+ @files_in_use = []
37
+ @response = Lux::Response.new
38
+ @session = Lux::Current::Session.new @request
39
+ @nav = Lux::Application::Nav.new @request
40
+ @var = {}.to_hwia
17
41
 
18
- # reset page cache
19
- Thread.current[:lux] = { cache:{}, page: self }
42
+ opts[:session].or({}).each {|k,v| @session[k] = v }
43
+ end
44
+
45
+ def [] name
46
+ @var[name]
47
+ end
48
+
49
+ def []= name, val
50
+ @var[name] = val
51
+ end
52
+
53
+ # Full host with port
54
+ def host
55
+ "#{request.env['rack.url_scheme']}://#{request.host}:#{request.port}".sub(':80','')# rescue 'http://locahost:3000'
56
+ end
20
57
 
21
- @files_in_use = []
22
- @response = Lux::Response.new
23
- @request = request
24
- @session = Lux::Current::Session.new request
58
+ # Cache data in scope of current request
59
+ def cache key
60
+ root = @var[:cache] ||= {}
61
+ data = root[key] # it is array ref because we want to cache nil results too
25
62
 
26
- # remove empty paramsters in GET request
27
- if request.request_method == 'GET'
28
- for el in request.params.keys
29
- request.params.delete(el) if request.params[el].blank?
63
+ unless data
64
+ data = [yield]
65
+ root[key] = data
30
66
  end
67
+
68
+ data[0]
31
69
  end
32
70
 
33
- # indiferent access
34
- request.instance_variable_set(:@params, request.params.h_wia) if request.params.keys.length > 0
71
+ # Set Lux.current.can_clear_cache = true in production for admins
72
+ def no_cache? shallow_check = false
73
+ check = @request.env['HTTP_CACHE_CONTROL'].to_s.downcase == 'no-cache'
74
+
75
+ if check
76
+ if shallow_check || Lux.env.no_cache?
77
+ true
78
+ else
79
+ can_clear_cache ? true : false
80
+ end
81
+ else
82
+ false
83
+ end
84
+ end
35
85
 
36
- Lux::Current::EncryptParams.decrypt request.params
37
- ap request.params if request.post? && Lux.config(:log_to_stdout)
86
+ # Execute action once per page
87
+ def once id = nil
88
+ id ||= Digest::SHA1.hexdigest caller[0]
38
89
 
39
- @nav = Lux::Application::Nav.new request
40
- end
90
+ @once_hash ||= {}
91
+ return false if @once_hash[id]
92
+ @once_hash[id] = true
41
93
 
42
- def domain
43
- host = Lux.current.request.host.split('.')
44
- host_country = host.pop
45
- host_name = host.pop
46
- host_name ? "#{host_name}.#{host_country}" : host_country
47
- end
94
+ if block_given?
95
+ yield || true
96
+ else
97
+ true
98
+ end
99
+ end
48
100
 
49
- def host
50
- "#{request.env['rack.url_scheme']}://#{request.host}:#{request.port}".sub(':80','')# rescue 'http://locahost:3000'
51
- end
101
+ # Generete unique ID par page render
102
+ # current.uid => "uid_123_1668273316128"
103
+ # current.uid(true) => 123
104
+ def uid num_only = false
105
+ Thread.current[:lux][:uid_cnt] ||= 0
106
+ num = Thread.current[:lux][:uid_cnt] += 1
107
+ num_only ? num : "uid_#{num}_#{(Time.now.to_f*1000).to_i}"
108
+ end
52
109
 
53
- def var
54
- Thread.current[:lux][:var] ||= Hashie::Mash.new
55
- end
110
+ # Get or check current session secure token
111
+ def secure_token token = nil
112
+ generated = Crypt.sha1(self.ip)
113
+ token ? (generated == token) : generated
114
+ end
56
115
 
57
- # cache data in current page
58
- def cache key
59
- data = Thread.current[:lux][:cache][key]
60
- return data if data
61
- Thread.current[:lux][:cache][key] = yield
62
- end
116
+ def robot?
117
+ ua = request.env['HTTP_USER_AGENT'].to_s.downcase
118
+ ua.include?('wget/') || ua.include?('curl/')
119
+ end
63
120
 
64
- # set current.can_clear_cache = true in production for admins
65
- def no_cache?
66
- @can_clear_cache = true if Lux.dev?
67
- @can_clear_cache && @request.env['HTTP_CACHE_CONTROL'].to_s.downcase == 'no-cache' ? true : false
68
- end
121
+ # Add to list of files in use
122
+ def files_in_use file = nil
123
+ return @files_in_use unless file
124
+ return unless file.class == String
69
125
 
70
- def redirect *args
71
- response.redirect *args
72
- end
126
+ file = file.sub './', ''
73
127
 
74
- # execute action once per page
75
- def once id=nil, data=nil, &block
76
- id ||= Digest::SHA1.hexdigest caller[0] if block
128
+ if @files_in_use.include?(file)
129
+ true
130
+ else
131
+ @files_in_use.push file
132
+ yield(file) if block_given?
133
+ false
134
+ end
135
+ end
77
136
 
78
- @once_hash ||= {}
79
- return if @once_hash[id]
80
- @once_hash[id] = true
137
+ # Thread.new but copies env to a thread
138
+ def delay *args
139
+ if block_given?
140
+ lux_env = self.dup
141
+ Thread.new do
142
+ begin
143
+ Thread.current[:lux] = lux_env
144
+ Timeout::timeout(Lux.config.delay_timeout) do
145
+ yield *args
146
+ end
147
+ rescue => e
148
+ Lux.error.log e
149
+ Lux.log ['Lux.current.delay error: %s' % e.message, e.backtrace].join($/)
150
+ end
151
+ end
152
+ else
153
+ raise ArgumentError, 'Block not given'
154
+ end
155
+ end
81
156
 
82
- block_given? ? yield : data
83
- end
157
+ def ip
158
+ request.env['HTTP_CF_CONNECTING_IP'] || # will not work with cloudflare if removed
159
+ request.env['HTTP_X_FORWARDED_FOR'] ||
160
+ request.env['REMOTE_ADDR'] ||
161
+ '127.0.0.1'
162
+ end
84
163
 
85
- def uid
86
- Thread.current[:uid_cnt] ||= 0
87
- "uid-#{Thread.current[:uid_cnt]+=1}"
88
- end
164
+ def encrypt data, opts={}
165
+ opts[:password] ||= self.ip
166
+ opts[:ttl] ||= 10.minutes
167
+ Crypt.encrypt(data, opts)
168
+ end
89
169
 
90
- def files_in_use file=nil
91
- if block_given?
92
- return yield(file) unless @files_in_use.include?(file)
170
+ def decrypt token, opts={}
171
+ opts[:password] ||= self.ip
172
+ Crypt.decrypt(token, opts)
93
173
  end
94
174
 
95
- return @files_in_use unless file
96
- return unless Lux.config(:log_to_stdout)
175
+ # Crypt.encrypt('secret', ttl:1.hour, password:'pa$$w0rd')
176
+ private
177
+
178
+ def prepare_params opts
179
+ # patch params to support indiferent access 😈
180
+ # request.instance_variable_set(:@params, request.params.to_hwia) if request.params.keys.length > 0
97
181
 
98
- file = file.sub './', ''
182
+ # merge qs if present
183
+ @params = (@request.params.dup || {}).to_hwia
184
+ @params.merge! opts[:query_string] if opts[:query_string]
185
+
186
+ # remove empty parametars in GET request
187
+ if request.request_method == 'GET'
188
+ for el in @params.keys
189
+ @params.delete(el) if @params[el].blank?
190
+ end
191
+ end
99
192
 
100
- if @files_in_use.include?(file)
101
- true
102
- else
103
- @files_in_use.push file
104
- false
193
+ Lux::Current::EncryptParams.decrypt @params
105
194
  end
106
195
  end
107
196
  end
@@ -0,0 +1,6 @@
1
+ class Current
2
+ def self.method_missing mame, *args
3
+ eval "def Current.#{mame} *list; Lux.current.#{mame} *list; end"
4
+ Current.send mame, *args
5
+ end
6
+ end
@@ -1,44 +1,46 @@
1
1
  # used for encrypting and decrypting data in forms
2
2
 
3
- module Lux::Current::EncryptParams
4
- extend self
5
-
6
- @cnt = 0
7
-
8
- # encrypt_param('dux', 'foo')
9
- # <OpenStruct name="_data_1", value="eyJ0eXAiOiJKV1QiLCJhbGciOi..."
10
- def encrypt name, value
11
- base = name.include?('[') ? name.split(/[\[\]]/).first(2).join('::') : name
12
- base += '#%s' % value
13
-
14
- OpenStruct.new(name: "_data_#{@cnt+=1}", value: Crypt.encrypt(base))
15
- end
3
+ module Lux
4
+ class Current
5
+ module EncryptParams
6
+ extend self
7
+
8
+ # encrypt_param('dux', 'foo')
9
+ # <OpenStruct name="_data_1", value="eyJ0eXAiOiJKV1QiLCJhbGciOi..."
10
+ def encrypt name, value
11
+ base = name.include?('[') ? name.split(/[\[\]]/).first(2).join('::') : name
12
+ base += '#%s' % value
13
+
14
+ OpenStruct.new(name: "_data_#{Lux.current.uid}", value: Crypt.encrypt(base))
15
+ end
16
16
 
17
- def hidden_input name, value
18
- data = encrypt name, value
17
+ def hidden_input name, value
18
+ data = encrypt name, value
19
19
 
20
- %[<input type="hidden" name="#{data.name}" value="#{data.value}" />]
21
- end
20
+ %[<input type="hidden" name="#{data.name}" value="#{data.value}" />]
21
+ end
22
22
 
23
- # decrypts params starting with _data_
24
- def decrypt hash
25
- for key in hash.keys
26
- next unless key.starts_with?('_data_')
27
- data = Crypt.decrypt(hash.delete(key))
28
- data, value = data.split('#', 2)
29
- data = data.split('::')
30
-
31
- if data[1]
32
- hash[data[0]] ||= {}
33
- hash[data[0]][data[1]] = value
34
- else
35
- hash[data[0]] = value
23
+ # decrypts params starting with _data_
24
+ def decrypt hash
25
+ for key in hash.keys
26
+ next unless key.starts_with?('_data_')
27
+ data = Crypt.decrypt(hash.delete(key))
28
+ data, value = data.split('#', 2)
29
+ data = data.split('::')
30
+
31
+ if data[1]
32
+ hash[data[0]] ||= {}
33
+ hash[data[0]][data[1]] = value
34
+ else
35
+ hash[data[0]] = value
36
+ end
37
+ end
38
+
39
+ hash
40
+ rescue
41
+ Lux.log ' Lux::Current::EncryptParams decrypt error'.red
42
+ {}
36
43
  end
37
44
  end
38
-
39
- hash
40
- rescue
41
- Lux.log ' Lux::Current::EncryptParams decrypt error'.red
42
- {}
43
45
  end
44
- end
46
+ end
@@ -1,72 +1,93 @@
1
1
  # vars
2
2
  # Lux.config.session_cookie_name
3
3
  # Lux.config.session_cookie_max_age
4
- # Lux.config.session_cookie_domain
5
4
 
6
- class Lux::Current::Session
7
- def initialize request
8
- # how long will session last if BROWSER or IP change
9
- Lux.config.session_forced_validity ||= 10.minutes.to_i
10
-
11
- # name of the session cookie
12
- @cookie_name = Lux.config.session_cookie_name ||= 'lux_' + Crypt.sha1(Lux.config.secret)[0,4].downcase
13
- @request = request
14
- @session = JSON.parse(Crypt.decrypt(request.cookies[@cookie_name] || '{}')) rescue {}
15
-
16
- security_check
17
- end
18
-
19
- def [] key
20
- @session[key.to_s.downcase]
21
- end
22
-
23
- def []= key, value
24
- @session[key.to_s.downcase] = value
25
- end
26
-
27
- def delete key
28
- @session.delete key.to_s.downcase
29
- end
30
-
31
- def generate_cookie
32
- encrypted = Crypt.encrypt(@session.to_json)
33
-
34
- if @request.cookies[@cookie_name] != encrypted
35
- cookie = []
36
- cookie.push [@cookie_name, encrypted].join('=')
37
- cookie.push 'Max-Age=%s' % (Lux.config.session_cookie_max_age || 1.week.to_i)
38
- cookie.push "Path=/"
39
- cookie.push "Domain=#{Lux.config.session_cookie_domain}" if Lux.config.session_cookie_domain
40
- cookie.push "secure" if Lux.config.host.include?('https:')
41
- cookie.push "HttpOnly"
42
-
43
- cookie.join('; ')
44
- else
45
- nil
5
+ # IMPORTANT - it is probably not a bug!
6
+ # If you have issues with cookies and sessions, try annonymous window and check info on set headers
7
+ # sometimes there is a bug there and cookie will not be set because of http https issues
8
+
9
+ module Lux
10
+ class Current
11
+ class Session
12
+ attr_reader :hash, :cookie_name
13
+
14
+ def initialize request
15
+ # how long will session last if BROWSER or IP change
16
+ Lux.config[:session_forced_validity] ||= 10.minutes.to_i
17
+ Lux.config[:session_cookie_max_age] ||= 1.week.to_i
18
+
19
+ # name of the session cookie
20
+ @cookie_name = Lux.config[:session_cookie_name] ||= 'lux_' + Crypt.sha1(Lux.config.secret)[0,4].downcase
21
+ @request = request
22
+ @hash = JSON.parse(Crypt.decrypt(request.cookies[@cookie_name] || '{}')) rescue {}
23
+
24
+ security_check
25
+ end
26
+
27
+ def [] key
28
+ @hash[key.to_s.downcase]
29
+ end
30
+
31
+ def []= key, value
32
+ @hash[key.to_s.downcase] = value
33
+ end
34
+
35
+ def delete key
36
+ @hash.delete key.to_s.downcase
37
+ end
38
+
39
+ def generate_cookie
40
+ encrypted = Crypt.encrypt(@hash.to_json)
41
+
42
+ if @request.cookies[@cookie_name] != encrypted
43
+ cookie_domain = Lux.current.var[:lux_cookie_domain] || Lux.current.nav.domain
44
+
45
+ cookie = []
46
+ cookie.push [@cookie_name, encrypted].join('=')
47
+ cookie.push 'Max-Age=%s' % (Lux.config.session_cookie_max_age)
48
+ cookie.push "Path=/"
49
+ cookie.push "Domain=#{cookie_domain}"
50
+ cookie.push "secure" if Lux.current.request.url.start_with?('https:')
51
+ cookie.push "HttpOnly"
52
+ cookie.push "SameSite=Lax"
53
+
54
+ cookie.join('; ')
55
+ else
56
+ nil
57
+ end
58
+ end
59
+
60
+ def merge! hash={}
61
+ @hash.keys.each { |k| self[k] = @hash[k] }
62
+ end
63
+
64
+ def keys
65
+ @hash.keys
66
+ end
67
+
68
+ def to_h
69
+ @hash
70
+ end
71
+
72
+ private
73
+
74
+ def security_check
75
+ key = '_c'
76
+ ip = Lux.current.ip.split('.').first(3).join('.') # only 3 first numbers of IP
77
+ check = Crypt.sha1(ip+@request.env['HTTP_USER_AGENT'].to_s)[0, 5]
78
+
79
+ # force type array
80
+ @hash.delete(key) unless @hash[key].class == Array
81
+
82
+ # allow 10 mins delay for IP change
83
+ if @hash[key] && (@hash[key][0] != check && @hash[key][1].to_i < Time.now.to_i - Lux.config.session_forced_validity)
84
+ @hash = {}
85
+ end
86
+
87
+ # add new time stamp to every request
88
+ @hash[key] = [check, Time.now.to_i]
89
+ end
46
90
  end
47
91
  end
92
+ end
48
93
 
49
- def merge! hash={}
50
- hash.keys.each { |k| self[k] = hash[k] }
51
- end
52
-
53
- def hash
54
- @session.dup
55
- end
56
-
57
- private
58
-
59
- def security_check
60
- key = '_c'
61
- check = Crypt.sha1(@request.ip.to_s+@request.env['HTTP_USER_AGENT'].to_s)[0, 5]
62
-
63
- # force type array
64
- @session.delete(key) unless @session[key].class == Array
65
-
66
- # allow 10 mins delay for IP change
67
- @session = {} if @session[key] && (@session[key][0] != check && @session[key][1].to_i < Time.now.to_i - Lux.config.session_forced_validity)
68
-
69
- # add new time stamp to every request
70
- @session[key] = [check, Time.now.to_i]
71
- end
72
- end
@@ -0,0 +1,5 @@
1
+ module Lux
2
+ def current
3
+ Thread.current[:lux] ||= Lux::Current.new('/mock')
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ ## Lux.env (Lux::Environment)
2
+
3
+ Module provides access to environment settings.
4
+
5
+ ```ruby
6
+ Lux.env.development? # true in development and test
7
+ Lux.env.production? # true in production and log
8
+ Lux.env.test? # true for test
9
+ Lux.env.log? # true for log
10
+ Lux.env.rake? # true if run in rake
11
+ Lux.env.cli? # true if not run under web server
12
+
13
+ # aliases
14
+ Lux.env.dev? # Lux.env.development?
15
+ Lux.env.prod? # Lux.env.production?
16
+ ```
17
+
18
+ Lux provides only 4 environent modes that are set via `ENV['RACK_ENV']` settings -
19
+ `development`, `production`, `test` and `log`.
20
+ * `test` and `log` are special modes
21
+ * `test`: will retun true to `Lux.env.test?` and `Lux.env.develoment?`
22
+ * `log`: Production mode with output logging. It will retun true for
23
+ `Lux.env.log?` and `Lux.env.production?` or `Lux.env.prod?`.
24
+ This mode is activated if you run server with `bundle exec lux ss`
@@ -0,0 +1,91 @@
1
+ module Lux
2
+ class Environment
3
+ ENVS ||= %w(development production test)
4
+
5
+ def initialize env_name
6
+ if env_name.empty?
7
+ raise ArgumentError.new('RACK_ENV is not defined') # never default to "development", because it could be loaded as default in production
8
+ elsif !ENVS.include?(env_name)
9
+ raise ArgumentError.new('Unsupported environemt: %s (supported are %s)' % [env_name, ENVS])
10
+ end
11
+
12
+ @env_name = env_name
13
+ end
14
+
15
+ def development?
16
+ @env_name != 'production'
17
+ end
18
+ alias :dev? development?
19
+
20
+ def production?
21
+ @env_name == 'production'
22
+ end
23
+ alias :prod? :production?
24
+
25
+ def test?
26
+ $0.end_with?('/rspec') || @env_name == 'test'
27
+ end
28
+
29
+ def rake?
30
+ $0.end_with?('/rake')
31
+ end
32
+
33
+ def live?
34
+ value = ENV['LUX_LIVE'] || Lux.die('ENV LUX_LIVE not defined')
35
+ value == 'true'
36
+ end
37
+
38
+ def local?
39
+ !live?
40
+ end
41
+
42
+ def web?
43
+ if @env_web.nil?
44
+ list = ObjectSpace.each_object(Class).map(&:to_s)
45
+ @env_web = list.include?('#<Class:Rack::Server>') || list.include?('Puma::Launcher')
46
+ end
47
+
48
+ @env_web
49
+ end
50
+
51
+ def cli?
52
+ !web?
53
+ end
54
+
55
+ def cache?
56
+ !no_cache?
57
+ end
58
+
59
+ def no_cache?
60
+ @no_cache = ENV['LUX_ENV'].include?('c') if @no_cache.nil?
61
+ @no_cache
62
+ end
63
+
64
+ def show_errors?
65
+ @show_errors = ENV['LUX_ENV'].include?('e') if @show_errors.nil?
66
+ @show_errors
67
+ end
68
+
69
+ def reload_code?
70
+ @reload_code = ENV['LUX_ENV'].include?('r') if @reload_code.nil?
71
+ @reload_code
72
+ end
73
+
74
+ def screen_log?
75
+ @screen_log = ENV['LUX_ENV'].include?('l') if @screen_log.nil?
76
+ @screen_log
77
+ end
78
+
79
+ ###
80
+
81
+ # Lux.env == :dev
82
+ def == what
83
+ return true if what.to_s == @env_name
84
+ send '%s?' % what
85
+ end
86
+
87
+ def to_s
88
+ production? ? 'production' : 'development'
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,13 @@
1
+ # Lux.env.to_s # 'development'
2
+ # Lux.env == :dev # true
3
+ # Lux.env == :development # true
4
+ # Lux.env.development? # true
5
+ # Lux.env.dev? # true
6
+
7
+ module Lux
8
+ def env test=nil
9
+ @env_base ||= Lux::Environment.new ENV.fetch('RACK_ENV')
10
+
11
+ test ? @env_base == test : @env_base
12
+ end
13
+ end