lux-fw 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.version +1 -0
  3. data/bin/cli/am +250 -0
  4. data/bin/cli/assets +37 -0
  5. data/bin/cli/console +50 -0
  6. data/bin/cli/dev +1 -0
  7. data/bin/cli/eval +15 -0
  8. data/bin/cli/exceptions +62 -0
  9. data/bin/cli/generate +82 -0
  10. data/bin/cli/get +5 -0
  11. data/bin/cli/nginx +28 -0
  12. data/bin/cli/production +1 -0
  13. data/bin/cli/routes +12 -0
  14. data/bin/cli/server +1 -0
  15. data/bin/cli/stat +1 -0
  16. data/bin/forever +65 -0
  17. data/bin/job_que +39 -0
  18. data/bin/lux +87 -0
  19. data/bin/txt/nginx.conf +29 -0
  20. data/bin/txt/siege-and-puma.txt +3 -0
  21. data/lib/common/base32.rb +47 -0
  22. data/lib/common/before_and_after.rb +71 -0
  23. data/lib/common/class_attributes.rb +66 -0
  24. data/lib/common/class_method_params.rb +94 -0
  25. data/lib/common/crypt.rb +66 -0
  26. data/lib/common/folder_model.rb +50 -0
  27. data/lib/common/generic_model.rb +62 -0
  28. data/lib/common/policy.rb +54 -0
  29. data/lib/common/string_base.rb +49 -0
  30. data/lib/common/url.rb +171 -0
  31. data/lib/lux/api/api.rb +150 -0
  32. data/lib/lux/api/lib/application_api.rb +19 -0
  33. data/lib/lux/api/lib/doc_builder.rb +18 -0
  34. data/lib/lux/api/lib/dsl.rb +73 -0
  35. data/lib/lux/api/lib/model_api.rb +145 -0
  36. data/lib/lux/api/lib/rescue.rb +18 -0
  37. data/lib/lux/cache/cache.rb +71 -0
  38. data/lib/lux/cache/lib/memcached.rb +3 -0
  39. data/lib/lux/cache/lib/null.rb +23 -0
  40. data/lib/lux/cache/lib/ram.rb +38 -0
  41. data/lib/lux/cell/cell.rb +260 -0
  42. data/lib/lux/config/config.rb +88 -0
  43. data/lib/lux/controller/controller.rb +185 -0
  44. data/lib/lux/controller/lib/nav.rb +77 -0
  45. data/lib/lux/controller/lib/plugs.rb +10 -0
  46. data/lib/lux/delayed_job/delayed_job.rb +44 -0
  47. data/lib/lux/delayed_job/lib/memory.rb +14 -0
  48. data/lib/lux/delayed_job/lib/nsq.rb +3 -0
  49. data/lib/lux/delayed_job/lib/postgre.rb +6 -0
  50. data/lib/lux/delayed_job/lib/redis.rb +19 -0
  51. data/lib/lux/error/error.rb +75 -0
  52. data/lib/lux/helper/helper.rb +109 -0
  53. data/lib/lux/html/html.rb +3 -0
  54. data/lib/lux/html/lib/form.rb +81 -0
  55. data/lib/lux/html/lib/input.rb +71 -0
  56. data/lib/lux/html/lib/input_types.rb +277 -0
  57. data/lib/lux/lux.rb +164 -0
  58. data/lib/lux/mailer/mailer.rb +73 -0
  59. data/lib/lux/page/lib/encrypt_params.rb +44 -0
  60. data/lib/lux/page/lib/flash.rb +49 -0
  61. data/lib/lux/page/lib/static_file.rb +97 -0
  62. data/lib/lux/page/page.rb +271 -0
  63. data/lib/lux/rescue_from/rescue_from.rb +61 -0
  64. data/lib/lux/template/template.rb +95 -0
  65. data/lib/lux-fw.rb +48 -0
  66. data/lib/overload/array.rb +52 -0
  67. data/lib/overload/blank.rb +62 -0
  68. data/lib/overload/date.rb +58 -0
  69. data/lib/overload/file.rb +14 -0
  70. data/lib/overload/hash.rb +86 -0
  71. data/lib/overload/hash_wia.rb +282 -0
  72. data/lib/overload/inflections.rb +199 -0
  73. data/lib/overload/integer.rb +19 -0
  74. data/lib/overload/module.rb +10 -0
  75. data/lib/overload/nil.rb +8 -0
  76. data/lib/overload/object.rb +77 -0
  77. data/lib/overload/string.rb +89 -0
  78. data/lib/overload/string_inflections.rb +7 -0
  79. data/lib/overload/struct.rb +5 -0
  80. data/lib/plugins/assets/assets_plug.rb +26 -0
  81. data/lib/plugins/assets/helper_module_adapter.rb +49 -0
  82. data/lib/plugins/assets/init.rb +4 -0
  83. data/lib/plugins/db_helpers/array_and_hstore.rb +64 -0
  84. data/lib/plugins/db_helpers/arrays_and_tags.rb +23 -0
  85. data/lib/plugins/db_helpers/before_save.rb +44 -0
  86. data/lib/plugins/db_helpers/cached_find_by.rb +45 -0
  87. data/lib/plugins/db_helpers/class_and_instance.rb +120 -0
  88. data/lib/plugins/db_helpers/dataset_plugin.rb +101 -0
  89. data/lib/plugins/db_helpers/filter_wrappers.rb +21 -0
  90. data/lib/plugins/db_helpers/link_plugin.rb +95 -0
  91. data/lib/plugins/db_helpers/localize_plugin.rb +57 -0
  92. data/lib/plugins/db_helpers/primary_keys.rb +36 -0
  93. data/lib/plugins/db_helpers/typero_attributes.rb +69 -0
  94. data/lib/plugins/db_logger/init.rb +18 -0
  95. data/lib/plugins/db_logger/lux_response_adapter.rb +9 -0
  96. data/lib/plugins/paginate/helper.rb +32 -0
  97. data/lib/plugins/paginate/sequel_adapter.rb +18 -0
  98. data/lib/vendor/mini_assets/mini_asset/base.rb +167 -0
  99. data/lib/vendor/mini_assets/mini_asset/css.rb +38 -0
  100. data/lib/vendor/mini_assets/mini_asset/js.rb +38 -0
  101. data/lib/vendor/mini_assets/mini_asset.rb +31 -0
  102. data/lib/vendor/oauth/lib/facebook.rb +35 -0
  103. data/lib/vendor/oauth/lib/github.rb +37 -0
  104. data/lib/vendor/oauth/lib/google.rb +41 -0
  105. data/lib/vendor/oauth/lib/linkedin.rb +41 -0
  106. data/lib/vendor/oauth/lib/stackexchange.rb +37 -0
  107. data/lib/vendor/oauth/lib/twitter.rb +41 -0
  108. data/lib/vendor/oauth/oauth.rb +46 -0
  109. metadata +334 -0
data/lib/common/url.rb ADDED
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ # u = Url.new('https://www.YouTube.com/watch?t=1260&v=cOFSX6nezEY')
4
+ # u.delete :t
5
+ # u.hash '160s'
6
+ # u.to_s -> 'https://com.youtube.www/watch?v=cOFSX6nezEY#160s'
7
+
8
+ require 'cgi'
9
+
10
+ class Url
11
+
12
+ attr_accessor :proto, :host, :port
13
+
14
+ class << self
15
+ def current
16
+ new Lux.page.request.url
17
+ end
18
+
19
+ def force_locale loc
20
+ u = current
21
+ u.locale loc
22
+ u.relative
23
+ end
24
+
25
+ def subdomain name, in_path=nil
26
+ b = current.subdomain(name)
27
+ b.path in_path if in_path
28
+ b.url
29
+ end
30
+
31
+ def qs name, value=nil
32
+ current.qs(name, value).relative
33
+ end
34
+
35
+ # for search
36
+ # Url.prepare_qs(:q) -> /foo?bar=1&q=
37
+ def prepare_qs name
38
+ url = current.qs(name).relative
39
+ url += url.index('?') ? '&' : '?'
40
+ "#{url}#{name}="
41
+ end
42
+
43
+ def escape str=nil
44
+ CGI::escape(str.to_s)
45
+ end
46
+
47
+ def unescape str=nil
48
+ CGI::unescape(str.to_s)
49
+ end
50
+ end
51
+
52
+ ###
53
+
54
+ def initialize url
55
+ if url =~ /:/
56
+ @elms = url.split '/', 4
57
+ else
58
+ @elms = [url]
59
+ @elms.unshift '',''
60
+ end
61
+
62
+ domain_and_port = @elms[2].split(':')
63
+ @domain_parts = domain_and_port[0].to_s.split('.').reverse.map(&:downcase)
64
+
65
+ @qs = {}
66
+ path_with_qs = @elms[3].to_s.split(/\?|#/)
67
+ path_with_qs[1].split('&').map do |el|
68
+ parts = el.split('=')
69
+ @qs[parts[0]] = Url.unescape parts[1]
70
+ end if path_with_qs[1]
71
+
72
+ @path = path_with_qs[0] || '/'
73
+ @proto = @elms[0].split(':').first.downcase
74
+ @port = domain_and_port[1] ? domain_and_port[1].to_i : 80
75
+ end
76
+
77
+ def domain what=nil
78
+ if what
79
+ @host = what
80
+ return self
81
+ end
82
+
83
+ @domain_parts.slice(0,2).reverse.join '.'
84
+ end
85
+
86
+ def subdomain name
87
+ if name
88
+ @domain_parts[2] = name
89
+ return self
90
+ end
91
+ @domain_parts.drop(2).reverse.join('.').or nil
92
+ end
93
+
94
+ def subdomain= name
95
+ @domain_parts[2] = name
96
+ end
97
+
98
+ def host
99
+ @domain_parts.reverse.join '.'
100
+ end
101
+
102
+ def host_with_port
103
+ %[#{proto}://#{host}#{port == 80 ? '' : ":#{port}"}]
104
+ end
105
+
106
+ def query
107
+ @query
108
+ end
109
+
110
+ def path val=nil
111
+ return '/'+@path+(@namespace ? ":#{@namespace}" : '') unless val
112
+
113
+ @path = val.sub(/^\//,'')
114
+ self
115
+ end
116
+
117
+ def delete *keys
118
+ keys.map{ |key| @qs.delete(key.to_s) }
119
+ self
120
+ end
121
+
122
+ def hash val
123
+ @hash = "##{val}"
124
+ end
125
+
126
+ def qs name, value=nil
127
+ if value
128
+ @qs[name.to_s] = value
129
+ elsif name
130
+ @qs.delete(name.to_s)
131
+ end
132
+ self
133
+ end
134
+
135
+ def namespace data
136
+ @namespace = data.to_s
137
+ self
138
+ end
139
+
140
+ def locale what
141
+ elms = @path.split('/')
142
+ if elms[0] && Locale.all.index(elms[0].to_s)
143
+ elms[0] = what
144
+ else
145
+ elms.unshift what
146
+ end
147
+ @path = elms.join('/')
148
+ self
149
+ end
150
+
151
+ def qs_val
152
+ ret = []
153
+ if @qs.keys.length > 0
154
+ ret.push '?' + @qs.keys.sort.map{ |key| "#{key}=#{Url.escape(@qs[key].to_s)}" }.join('&')
155
+ end
156
+ ret.join('')
157
+ end
158
+
159
+ def url
160
+ [host_with_port, path, qs_val, @hash].join('')
161
+ end
162
+
163
+ def relative
164
+ [path, qs_val, @hash].join('').sub('//','/')
165
+ end
166
+
167
+ def to_s
168
+ domain.length > 0 ? url : local_url
169
+ end
170
+
171
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ # 2xx - Success 4xx / 5xx - Error 3xx - Redirection
4
+ # 200 OK 400 Bad Request 301 Moved
5
+ # 201 Created 401 Unauthorized 302 Found
6
+ # 203 Partial Information 402 Payment Required 304 Not Modified
7
+ # 204 No response 403 Forbidden
8
+ # 404 Not Found
9
+ # 500 Internal Server Error
10
+ # 503 Service Unavailable
11
+
12
+ class Lux::Api
13
+
14
+ BeforeAndAfter.define self, :before, :after
15
+
16
+ Lux::RescueFrom.define(self)
17
+
18
+ class << self
19
+ # public mount method for router
20
+ def call path
21
+ return 'Unsupported API call' if !path[1] || path[3]
22
+
23
+ opts = Lux.page.params # Lux.page.request.post? ? Rack::Utils.parse_nested_query(Lux.page.request.body.read).h : Lux.page.params
24
+
25
+ if path[2]
26
+ opts[:_id] = path[1]
27
+ path[1] = path[2]
28
+ end
29
+
30
+ Lux.page.body run(path[0], path[1], opts)
31
+ end
32
+
33
+ # public method for running actions on global class
34
+ # use as Lux::Api.run 'users', 'show', { email:'rejotl@gmail.com' }
35
+ # safe create api class and fix params
36
+ def run klass, action, params={}
37
+ params.delete_if{ |el| [:captures, :splat].index(el.to_sym) }
38
+
39
+ action = action.to_s.sub(/[^\w_]/,'')
40
+
41
+ class_name = klass.to_s.classify
42
+
43
+ if params[class_name.underscore]
44
+ begin
45
+ params.merge! params.delete(class_name.underscore)
46
+ rescue
47
+ error "#{$!.message}. Domain value is probably not hash, invalid parameter #{class_name.underscore}"
48
+ end
49
+ end
50
+
51
+ for k,v in params
52
+ params[k] = params[k].gsub('<','&lt;').gsub('>','&gt;').gsub(/\A^\s+|\s+\z/,'') if v.kind_of?(String)
53
+ end
54
+
55
+ begin
56
+ klass = (klass.singularize.camelize+'Api').constantize
57
+ rescue
58
+ return Lux.page.body({ error:"API #{klass} not found" })
59
+ end
60
+
61
+ klass.new.call(action.to_sym, params)
62
+ end
63
+
64
+ end
65
+
66
+ def call(action, params={})
67
+ @@rescue_from_ivar.call do
68
+ rescued_call(action, params)
69
+ BeforeAndAfter.execute(self, :after)
70
+ end
71
+
72
+ @response
73
+ end
74
+
75
+ # internal method for running actions
76
+ # UserApi.new.call(:login, { email:'', pass:'' })
77
+ def rescued_call(action, params={})
78
+ raise ForbidenError, "Protected action call" if [:call, :rescued_call, :params, :error].index action
79
+ raise NotFoundError, "Action #{action} not found in #{self.class.to_s}" unless respond_to? action
80
+
81
+ @response = {}
82
+ @message = nil
83
+ @params = params
84
+ @class_name = self.class.to_s.sub(/Api$/,'')
85
+
86
+ # load default object
87
+ if @params[:_id]
88
+ eval "@object = @#{@class_name.underscore} = #{@class_name}[@params[:_id].to_i]"
89
+ @params.delete(:_id)
90
+ @response[:path] = @object.path rescue nil if @object
91
+ end
92
+
93
+ # execte api call and verify params if possible
94
+ BeforeAndAfter.execute(self, :before)
95
+
96
+ return unless check_params_and_mock_instance_variables action
97
+
98
+ api_data = send(action)
99
+ format_response!(api_data)
100
+ end
101
+
102
+ def params
103
+ @params
104
+ end
105
+
106
+ def error(what)
107
+ raise StandardError, what
108
+ end
109
+
110
+ def format_response!(api_data=nil)
111
+ if api_data
112
+ # api_data = instance_eval(&res) if api_data.kind_of?(Proc)
113
+ api_data = api_data.all.map{ |el| el.attributes } if api_data.class.name == 'ActiveRecord::Relation'
114
+
115
+ # sequel array of objects returned
116
+ if api_data.kind_of?(Array) && api_data[0] && api_data[0].respond_to?(:columns)
117
+ api_data = api_data.map(&:to_h)
118
+ end
119
+
120
+ # object given
121
+ if api_data.respond_to?(:attributes)
122
+ @response[:path] = api_data.path if api_data.id && api_data.respond_to?(:path)
123
+ api_data = api_data.attributes.reject{ |f| ['updated_by', 'updated_at', 'created_by', 'created_at'].index(f) }
124
+ end
125
+
126
+ @response[:data] = api_data
127
+ @response[:message] = @message.to_s unless @message.nil?
128
+ # @response[:message] = api_data if !@message && api_data.kind_of?(String)
129
+
130
+ # if we define _redirect then we will be redirected to exact page
131
+ # useful for file uploads
132
+ if @params[:_redirect]
133
+ if @response[:error]
134
+ Lux.page.flash.error @response[:error]
135
+ elsif @response[:message]
136
+ Lux.page.flash.info @response[:message]
137
+ end
138
+ Lux.page.redirect(@params[:_redirect])
139
+ end
140
+ end
141
+
142
+ ap @response if Lux.config.debug_api_response
143
+ end
144
+
145
+ def message(what)
146
+ @message = what
147
+ end
148
+
149
+ end
150
+
@@ -0,0 +1,19 @@
1
+ class ApplicationApi < Lux::Api
2
+
3
+ # called at the end of response
4
+ def decorate_response!(data=nil)
5
+ @response = data if data
6
+ if Lux.page
7
+ @response[:ip] = Lux.page.request.ip
8
+ @response[:user] = Lux.page.var.user ? Lux.page.var.user.email : nil
9
+ @response[:http_status] = Lux.page.status(200)
10
+ @response[:error] ||= 'Bad request' if Lux.page.status != 200
11
+ end
12
+ @response
13
+ end
14
+
15
+ def after
16
+ decorate_response!
17
+ end
18
+
19
+ end
@@ -0,0 +1,18 @@
1
+ class Lux::Api
2
+ class << self
3
+ # list all availabe actions in a class
4
+ def actions
5
+ instance_level_actions = UserApi.instance_methods - Object.instance_methods - [:sinatra, :instance_run, :params]
6
+ @@actions[self.to_s].keys + instance_level_actions
7
+ end
8
+
9
+ # get details about action
10
+ def action_details(name)
11
+ @@actions[self.to_s][name] ||= {}
12
+ details = @@actions[self.to_s][name].reject { |key| [:proc].index(key) }
13
+ details[:name] ||= "#{name.to_s} action"
14
+ details[:action] ||= name
15
+ details.h
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,73 @@
1
+ class Lux::Api
2
+
3
+ # name 'Show user data'
4
+ # param :email, type: :email, req: false
5
+ # param :pass
6
+ # def show
7
+ # @user = User.where(email:@_email).first
8
+ # @user.slice(:id, :name, :avatar, :email)
9
+ # end
10
+
11
+ class << self
12
+ @@actions ||= {}
13
+
14
+ def method_added(m)
15
+ ClassMethodParams.add_method self, m
16
+ end
17
+
18
+ # helper for standard definition of parametars
19
+ # param :o_id
20
+ # param :o_id, Integer
21
+ # param :o_id, Integer, req: false
22
+ # param :o_id, req: false
23
+ def param(field, type=String, opts={})
24
+ opts = type.is_a?(Hash) ? type : opts.merge(type: type)
25
+ opts[:name] = field
26
+ opts[:req] = opts[:req].class.name == 'FalseClass' ? false : true
27
+ opts[:type] ||= String
28
+
29
+ ClassMethodParams.add_param self, :param, opts
30
+ end
31
+
32
+ # helper for standard definition of name
33
+ def name(name)
34
+ ClassMethodParams.add_param self, :name, name
35
+ end
36
+
37
+ # helper for standard definition of description
38
+ def description(data)
39
+ ClassMethodParams.add_param self, :description, name
40
+ end
41
+ end
42
+
43
+ ###
44
+
45
+ def check_params_and_mock_instance_variables action
46
+ opts = ClassMethodParams.params self.class, action
47
+
48
+ if opts && opts[:param]
49
+ local = opts[:param].inject({}) { |h, el| o=el.dup; h[o.delete(:name)] = o; h }
50
+
51
+ rules = Typero.new local
52
+ errors = rules.validate(@params)
53
+
54
+ if errors.keys.length > 0
55
+ raise ArgumentError.new(errors.values.to_sentence) unless Lux.page
56
+
57
+ Lux.page.status(400)
58
+ @response[:error] = errors.values.to_sentence
59
+ @response[:errors] = errors
60
+ return false
61
+ end
62
+
63
+ # define local prefixed @_ variables
64
+ for key in local.keys.map(&:to_s)
65
+ value = params[key]
66
+ eval "@_#{key.downcase.gsub(/[^\w]/,'_')} = value" if key.length < 15 && value.present? && key =~ /^[\w]+$/
67
+ end
68
+ end
69
+
70
+ true
71
+ end
72
+
73
+ end
@@ -0,0 +1,145 @@
1
+ class ModelApi < ApplicationApi
2
+
3
+ class << self
4
+ def toggle_ids name
5
+ self.class_eval %[
6
+ param :#{name}_id, Integer
7
+ def toggle_#{name}
8
+ message toggle!(@object, :#{name}_ids, @_#{name}_id) ? 'added' : 'removed'
9
+ end
10
+ ]
11
+ end
12
+ end
13
+
14
+ # toggles value in postgre array field
15
+ def toggle!(object, field, value)
16
+ object[field] ||= []
17
+
18
+ if object[field].include?(value)
19
+ object[field] -= [value]
20
+ object.save
21
+ false
22
+ else
23
+ object[field] += [value]
24
+ object.save
25
+ true
26
+ end
27
+ end
28
+
29
+ ###
30
+
31
+ def index
32
+ raise 'No index method defiend'
33
+ end
34
+
35
+ def show
36
+ error "Object not found" unless @object
37
+
38
+ can? :read, @object
39
+ @object.attributes
40
+ end
41
+
42
+ def create
43
+ @object = @class_name.constantize.new
44
+
45
+ @last = @class_name.constantize.my.last rescue @class_name.constantize.last
46
+ if @last && @last[:name].present? && @last[:name] == @params[:name]
47
+ error "#{@class_name} is same as last one created."
48
+ end
49
+
50
+ for k,v in @params
51
+ @object.send("#{k}=", v) if @object.respond_to?(k.to_sym)
52
+ end
53
+
54
+ can? :create, @object
55
+ @object.save if @object.valid?
56
+ return if report_errros_if_any @object
57
+
58
+ if @object.id
59
+ @message = "#{@class_name.capitalize} created"
60
+ else
61
+ error 'object not created, error unknown'
62
+ end
63
+
64
+ @response[:path] = (@object.path rescue nil)
65
+
66
+ @object.attributes
67
+ end
68
+
69
+ def update
70
+ error "Object not found" unless @object
71
+
72
+ for k,v in @params
73
+ @object.send("#{k}=", v) if @object.respond_to?(k.to_sym)
74
+ end
75
+
76
+ can? :update, @object
77
+ @object.save if @object.valid?
78
+ report_errros_if_any @object
79
+ @message = "#{@class_name} updated"
80
+ @response[:path] = (@object.path rescue nil)
81
+ @object.attributes
82
+ end
83
+
84
+ # if you put active boolean field to objects, then they will be unactivated on destroy
85
+ def destroy
86
+ error "Object not found" unless @object
87
+ can? :delete, @object
88
+
89
+ if @object.respond_to?(:is_active)
90
+ @object.update is_active: false
91
+ @message = 'Object deleted (exists in trashcan)'
92
+ elsif @object.respond_to?(:active)
93
+ @object.update active: false
94
+ @message = 'Object deleted (exists in trashcan)'
95
+ else
96
+ @object.destroy
97
+ @message = "#{@object.class.name} deleted"
98
+ end
99
+ report_errros_if_any @object
100
+ @object.attributes
101
+ end
102
+
103
+ def undelete
104
+ error "Object not found" unless @object
105
+ can? :create, @object
106
+
107
+ if @object.respond_to?(:is_active)
108
+ @object.update :is_active=>true
109
+ elsif @object.respond_to?(:active)
110
+ @object.update :active=>true
111
+ else
112
+ error "No is_active, can't undelete"
113
+ end
114
+
115
+ @message = 'Object raised from the dead.'
116
+ end
117
+
118
+ def report_errros_if_any(obj)
119
+ @response[:object] = obj.class.to_s.tableize.singularize
120
+ @response[:objects] = obj.class.to_s.tableize
121
+
122
+ if obj.errors.count > 0
123
+ @response[:error] = ''
124
+ @response[:errors] = {}
125
+ for k,v in obj.errors
126
+ desc = v.join(', ')
127
+ desc = "#{k} #{desc}" if desc.starts_with?('is ')
128
+ @response[:errors][k] = desc
129
+ @response[:error] += ', ' unless @response[:error].blank?
130
+ @response[:error] += desc
131
+ end
132
+ Lux.page.status(400)
133
+ return true
134
+ end
135
+ false
136
+ end
137
+
138
+ def can?(action, object)
139
+ ModelPolicy.can?(action: action, model: object, user: Lux.page.var.user) do |err|
140
+ msg = 'No %s permission for %s' % [action.to_s.sub('?',''), Lux.page.var.user ? Lux.page.var.user.email : :guests]
141
+ msg += ' on %s' % object.class.name if object
142
+ error msg
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,18 @@
1
+ Lux::Api.class_eval do
2
+
3
+ rescue_from(:default) do |msg|
4
+ Lux.page.status $!.class
5
+
6
+ data = { error:msg }
7
+
8
+ if Lux.dev? && $!.class != StandardError
9
+ data[:backtrace] = $!.backtrace.reject{ |el| el.index('/gems/') }.map{ |el| el.sub(Lux.root.to_s, '') }
10
+ ap data[:backtrace]
11
+ end
12
+
13
+ ApplicationApi.new.decorate_response!(data)
14
+
15
+ Lux.page.body data
16
+ end
17
+
18
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lux::Cache
4
+ extend self
5
+
6
+ def server= obj
7
+ @@server = obj
8
+ end
9
+
10
+ # cache data in current thread
11
+ def thread key
12
+ data = Lux.thread[:cache][key]
13
+ return data if data
14
+ Lux.thread[:cache][key] = yield
15
+ end
16
+
17
+ def read key
18
+ return nil if (Lux.page.no_cache? rescue false)
19
+ @@server.get(key)
20
+ end
21
+ alias :get :read
22
+
23
+ def read_multi *args
24
+ @@server.get_multi(*args)
25
+ end
26
+ alias :get_multi :read_multi
27
+
28
+ def write key, data, ttl=nil
29
+ ttl = ttl.to_i if ttl
30
+ @@server.set(key, data, ttl)
31
+ end
32
+ alias :set :write
33
+
34
+ def delete key, data=nil
35
+ @@server.delete(key)
36
+ end
37
+
38
+ def fetch key, ttl=nil, log=true
39
+ ttl = ttl.to_i if ttl
40
+ @@server.delete key if Lux.page && Lux.page.no_cache?
41
+
42
+ Lux.log " Cache.fetch.get #{key} (ttl: #{ttl.or(:nil)})" if log
43
+ data = @@server.fetch key, ttl do
44
+ data = yield
45
+ Lux.log " Cache.fetch.SET #{key} len:#{data.to_s.length}" if log
46
+ data
47
+ end
48
+
49
+ data
50
+ end
51
+
52
+ def is_available?
53
+ set('lux-test', 9)
54
+ get('lux-test') == 9
55
+ end
56
+
57
+ def generate_key *data
58
+ keys = []
59
+ for el in [data].flatten
60
+ if el.respond_to?(:updated_at)
61
+ keys.push el.updated_at
62
+ elsif el.respond_to?(:created_at)
63
+ keys.push el.created_at
64
+ else
65
+ keys.push el.to_s
66
+ end
67
+ end
68
+ key = keys.join('-')
69
+ key.length < 30 ? key : Crypt.md5(key)
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ # use this in app config
2
+ # Lux.config.cache = Dalli::Client.new('localhost:11211', { :namespace=>Digest::MD5.hexdigest(__FILE__)[0,4], :compress => true, :expires_in => 1.hour })
3
+ # directly connect memcached
@@ -0,0 +1,23 @@
1
+ module Lux::Cache::NullCache
2
+ extend self
3
+
4
+ def set(key, data, ttl=nil)
5
+ data
6
+ end
7
+
8
+ def get(key)
9
+ nil
10
+ end
11
+
12
+ def fetch(key, ttl=nil)
13
+ yield
14
+ end
15
+
16
+ def delete(key)
17
+ nil
18
+ end
19
+
20
+ def get_multi(*args)
21
+ {}
22
+ end
23
+ end