lux-fw 0.1.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.version +1 -0
- data/bin/cli/am +250 -0
- data/bin/cli/assets +37 -0
- data/bin/cli/console +50 -0
- data/bin/cli/dev +1 -0
- data/bin/cli/eval +15 -0
- data/bin/cli/exceptions +62 -0
- data/bin/cli/generate +82 -0
- data/bin/cli/get +5 -0
- data/bin/cli/nginx +28 -0
- data/bin/cli/production +1 -0
- data/bin/cli/routes +12 -0
- data/bin/cli/server +1 -0
- data/bin/cli/stat +1 -0
- data/bin/forever +65 -0
- data/bin/job_que +39 -0
- data/bin/lux +87 -0
- data/bin/txt/nginx.conf +29 -0
- data/bin/txt/siege-and-puma.txt +3 -0
- data/lib/common/base32.rb +47 -0
- data/lib/common/before_and_after.rb +71 -0
- data/lib/common/class_attributes.rb +66 -0
- data/lib/common/class_method_params.rb +94 -0
- data/lib/common/crypt.rb +66 -0
- data/lib/common/folder_model.rb +50 -0
- data/lib/common/generic_model.rb +62 -0
- data/lib/common/policy.rb +54 -0
- data/lib/common/string_base.rb +49 -0
- data/lib/common/url.rb +171 -0
- data/lib/lux/api/api.rb +150 -0
- data/lib/lux/api/lib/application_api.rb +19 -0
- data/lib/lux/api/lib/doc_builder.rb +18 -0
- data/lib/lux/api/lib/dsl.rb +73 -0
- data/lib/lux/api/lib/model_api.rb +145 -0
- data/lib/lux/api/lib/rescue.rb +18 -0
- data/lib/lux/cache/cache.rb +71 -0
- data/lib/lux/cache/lib/memcached.rb +3 -0
- data/lib/lux/cache/lib/null.rb +23 -0
- data/lib/lux/cache/lib/ram.rb +38 -0
- data/lib/lux/cell/cell.rb +260 -0
- data/lib/lux/config/config.rb +88 -0
- data/lib/lux/controller/controller.rb +185 -0
- data/lib/lux/controller/lib/nav.rb +77 -0
- data/lib/lux/controller/lib/plugs.rb +10 -0
- data/lib/lux/delayed_job/delayed_job.rb +44 -0
- data/lib/lux/delayed_job/lib/memory.rb +14 -0
- data/lib/lux/delayed_job/lib/nsq.rb +3 -0
- data/lib/lux/delayed_job/lib/postgre.rb +6 -0
- data/lib/lux/delayed_job/lib/redis.rb +19 -0
- data/lib/lux/error/error.rb +75 -0
- data/lib/lux/helper/helper.rb +109 -0
- data/lib/lux/html/html.rb +3 -0
- data/lib/lux/html/lib/form.rb +81 -0
- data/lib/lux/html/lib/input.rb +71 -0
- data/lib/lux/html/lib/input_types.rb +277 -0
- data/lib/lux/lux.rb +164 -0
- data/lib/lux/mailer/mailer.rb +73 -0
- data/lib/lux/page/lib/encrypt_params.rb +44 -0
- data/lib/lux/page/lib/flash.rb +49 -0
- data/lib/lux/page/lib/static_file.rb +97 -0
- data/lib/lux/page/page.rb +271 -0
- data/lib/lux/rescue_from/rescue_from.rb +61 -0
- data/lib/lux/template/template.rb +95 -0
- data/lib/lux-fw.rb +48 -0
- data/lib/overload/array.rb +52 -0
- data/lib/overload/blank.rb +62 -0
- data/lib/overload/date.rb +58 -0
- data/lib/overload/file.rb +14 -0
- data/lib/overload/hash.rb +86 -0
- data/lib/overload/hash_wia.rb +282 -0
- data/lib/overload/inflections.rb +199 -0
- data/lib/overload/integer.rb +19 -0
- data/lib/overload/module.rb +10 -0
- data/lib/overload/nil.rb +8 -0
- data/lib/overload/object.rb +77 -0
- data/lib/overload/string.rb +89 -0
- data/lib/overload/string_inflections.rb +7 -0
- data/lib/overload/struct.rb +5 -0
- data/lib/plugins/assets/assets_plug.rb +26 -0
- data/lib/plugins/assets/helper_module_adapter.rb +49 -0
- data/lib/plugins/assets/init.rb +4 -0
- data/lib/plugins/db_helpers/array_and_hstore.rb +64 -0
- data/lib/plugins/db_helpers/arrays_and_tags.rb +23 -0
- data/lib/plugins/db_helpers/before_save.rb +44 -0
- data/lib/plugins/db_helpers/cached_find_by.rb +45 -0
- data/lib/plugins/db_helpers/class_and_instance.rb +120 -0
- data/lib/plugins/db_helpers/dataset_plugin.rb +101 -0
- data/lib/plugins/db_helpers/filter_wrappers.rb +21 -0
- data/lib/plugins/db_helpers/link_plugin.rb +95 -0
- data/lib/plugins/db_helpers/localize_plugin.rb +57 -0
- data/lib/plugins/db_helpers/primary_keys.rb +36 -0
- data/lib/plugins/db_helpers/typero_attributes.rb +69 -0
- data/lib/plugins/db_logger/init.rb +18 -0
- data/lib/plugins/db_logger/lux_response_adapter.rb +9 -0
- data/lib/plugins/paginate/helper.rb +32 -0
- data/lib/plugins/paginate/sequel_adapter.rb +18 -0
- data/lib/vendor/mini_assets/mini_asset/base.rb +167 -0
- data/lib/vendor/mini_assets/mini_asset/css.rb +38 -0
- data/lib/vendor/mini_assets/mini_asset/js.rb +38 -0
- data/lib/vendor/mini_assets/mini_asset.rb +31 -0
- data/lib/vendor/oauth/lib/facebook.rb +35 -0
- data/lib/vendor/oauth/lib/github.rb +37 -0
- data/lib/vendor/oauth/lib/google.rb +41 -0
- data/lib/vendor/oauth/lib/linkedin.rb +41 -0
- data/lib/vendor/oauth/lib/stackexchange.rb +37 -0
- data/lib/vendor/oauth/lib/twitter.rb +41 -0
- data/lib/vendor/oauth/oauth.rb +46 -0
- 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
|
data/lib/lux/api/api.rb
ADDED
@@ -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('<','<').gsub('>','>').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,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
|