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/bin/lux
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if File.exists?('lux-fw.gemspec')
|
4
|
+
puts 'Cant run in lux folder'
|
5
|
+
exit
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'colorize'
|
9
|
+
require 'optparse'
|
10
|
+
require 'awesome_print'
|
11
|
+
require 'dotenv'
|
12
|
+
|
13
|
+
module LuxCli
|
14
|
+
extend self
|
15
|
+
|
16
|
+
def run what
|
17
|
+
puts what.green
|
18
|
+
system what
|
19
|
+
end
|
20
|
+
|
21
|
+
def die text
|
22
|
+
puts text.red
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Dotenv.load
|
28
|
+
|
29
|
+
@port = 3000
|
30
|
+
lux_root = File.expand_path '../..', __FILE__
|
31
|
+
|
32
|
+
puts 'Lux (%s, v%s)' % [lux_root, File.read('%s/.version' % lux_root)] unless ARGV[0]
|
33
|
+
|
34
|
+
ARGV.options do |opts|
|
35
|
+
opts.on("-e", "--environment=val", "RACK_ENV enviroment", String) do |v|
|
36
|
+
v = 'production' if v[0,1] == 'p'
|
37
|
+
v = 'development' if v[0,1] == 'd'
|
38
|
+
ENV['RACK_ENV'] = v if v
|
39
|
+
end
|
40
|
+
opts.on("-p", "--port=val", "port (3000)", String) do |v|
|
41
|
+
@port = v.to_i
|
42
|
+
end
|
43
|
+
end.parse!
|
44
|
+
|
45
|
+
commands = {}
|
46
|
+
commands['am'] = 'auto migrate'
|
47
|
+
commands['assets'] = 'precompile assets and genereate mainifest.json'
|
48
|
+
commands['console'] = 'Lux console'
|
49
|
+
commands['dev'] = 'dev on port 3000 with hot reload on code change'
|
50
|
+
commands['eval'] = 'eval code or file'
|
51
|
+
commands['exceptions'] = 'show stored exceptions, last created first'
|
52
|
+
commands['generate'] = 'generates models and views based on templates'
|
53
|
+
commands['get'] = 'get local URL'
|
54
|
+
# commands['job_que'] = 'process job que with loaded enviroment'
|
55
|
+
commands['nginx'] = 'parse and install config/nginx.conf'
|
56
|
+
commands['production'] = 'run puma in production mode'
|
57
|
+
commands['routes'] = 'list routes'
|
58
|
+
commands['server'] = 'run puma development server'
|
59
|
+
commands['stat'] = 'goaccess stat to public/goaccess.html'
|
60
|
+
|
61
|
+
command = ARGV.shift
|
62
|
+
|
63
|
+
if command
|
64
|
+
for c in commands
|
65
|
+
command = c[0] if c[0] if c[0].start_with?(command)
|
66
|
+
end
|
67
|
+
|
68
|
+
if commands[command]
|
69
|
+
path = '%s/bin/cli/%s' % [lux_root, command]
|
70
|
+
load path
|
71
|
+
else
|
72
|
+
LuxCli.die "Can't find command [%s]" % command
|
73
|
+
end
|
74
|
+
else
|
75
|
+
puts "\nCommands:"
|
76
|
+
for c in commands
|
77
|
+
# puts " #{c[0].sub(/(\w)/,'[\\1]').ljust(15)} # #{c[1]}"
|
78
|
+
puts " #{c[0].ljust(15)} # #{c[1]}"
|
79
|
+
end
|
80
|
+
|
81
|
+
puts "\nExamples:"
|
82
|
+
puts ' lux c # lux console'
|
83
|
+
puts ' lux g user # lux generate user users'
|
84
|
+
puts ''
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
data/bin/txt/nginx.conf
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
worker_processes 1;
|
2
|
+
|
3
|
+
events {
|
4
|
+
worker_connections 1024;
|
5
|
+
}
|
6
|
+
|
7
|
+
server {
|
8
|
+
listen 80; #default deferred;
|
9
|
+
server_name .color-mont.com;
|
10
|
+
root /home/deployer/apps/app/public;
|
11
|
+
error_log /home/deployer/apps/app/log/nginx-error.log;
|
12
|
+
|
13
|
+
passenger_enabled on;
|
14
|
+
passenger_friendly_error_pages on;
|
15
|
+
|
16
|
+
location = /favicon.ico {
|
17
|
+
log_not_found off;
|
18
|
+
access_log off;
|
19
|
+
}
|
20
|
+
|
21
|
+
location ^~ /assets/ {
|
22
|
+
gzip_static on;
|
23
|
+
expires max;
|
24
|
+
add_header Cache-Control public;
|
25
|
+
}
|
26
|
+
|
27
|
+
client_max_body_size 1G;
|
28
|
+
keepalive_timeout 20;
|
29
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Base32
|
4
|
+
|
5
|
+
class Chunk
|
6
|
+
def initialize(bytes)
|
7
|
+
@table = "abcdefghijklmnopqrstuvwxyz234567"
|
8
|
+
@bytes = bytes
|
9
|
+
end
|
10
|
+
|
11
|
+
def decode
|
12
|
+
bytes = @bytes.take_while {|c| c != 61} # strip padding
|
13
|
+
n = (bytes.length * 5.0 / 8.0).floor
|
14
|
+
p = bytes.length < 8 ? 5 - (n * 8) % 5 : 0
|
15
|
+
c = bytes.inject(0) {|m,o| (m << 5) + @table.index(o.chr)} >> p
|
16
|
+
(0..n-1).to_a.reverse.collect {|i| ((c >> i * 8) & 0xff).chr} # bla
|
17
|
+
end
|
18
|
+
|
19
|
+
def encode
|
20
|
+
n = (@bytes.length * 8.0 / 5.0).ceil
|
21
|
+
p = n < 8 ? 5 - (@bytes.length * 8) % 5 : 0
|
22
|
+
c = @bytes.inject(0) {|m,o| (m << 8) + o} << p
|
23
|
+
[(0..n-1).to_a.reverse.collect {|i| @table[(c >> i * 5) & 0x1f].chr},
|
24
|
+
("=" * (8-n))]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def chunks(str, size)
|
30
|
+
result = []
|
31
|
+
bytes = str.bytes
|
32
|
+
while bytes.any? do
|
33
|
+
result << Chunk.new(bytes.take(size))
|
34
|
+
bytes = bytes.drop(size)
|
35
|
+
end
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
def encode(str)
|
40
|
+
chunks(str, 5).collect(&:encode).flatten.join.sub(/=+$/,'')
|
41
|
+
end
|
42
|
+
|
43
|
+
def decode(str)
|
44
|
+
chunks(str, 8).collect(&:decode).flatten.join
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# in some class
|
4
|
+
# def self.before(proc=nil, &block)
|
5
|
+
# BeforeAndAfter.add(self, caller[0], :before, proc || block)
|
6
|
+
# end
|
7
|
+
# or
|
8
|
+
# BeforeAndAfter.define self, :before, :after
|
9
|
+
#
|
10
|
+
# then to execute
|
11
|
+
# instance_object = SomeClass.new
|
12
|
+
# BeforeAndAfter.execute(instance_object, :before)
|
13
|
+
# or
|
14
|
+
# before do
|
15
|
+
# ...
|
16
|
+
# end
|
17
|
+
# or
|
18
|
+
# def before
|
19
|
+
# super
|
20
|
+
# ...
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# logic is very simple, keep all pointers to all blocks in one class, resolve and execute as needed
|
24
|
+
# we keep methods and ponters in different hashes to allow hot reload while development
|
25
|
+
|
26
|
+
module BeforeAndAfter
|
27
|
+
extend self
|
28
|
+
|
29
|
+
@@methods = {}
|
30
|
+
@@pointers = {}
|
31
|
+
|
32
|
+
def add(klass, unique_id, action, method)
|
33
|
+
key = Crypt.md5(unique_id)
|
34
|
+
@@pointers[key] = method
|
35
|
+
@@methods[klass.to_s] ||= {}
|
36
|
+
@@methods[klass.to_s][action] ||= []
|
37
|
+
@@methods[klass.to_s][action].push(key) unless @@methods[klass.to_s][action].index(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute(instance_object, action)
|
41
|
+
instance_object.send(action)
|
42
|
+
|
43
|
+
# execute for self and parent
|
44
|
+
for name in instance_object.class.ancestors.reverse.map(&:to_s)
|
45
|
+
next if name == 'Object'
|
46
|
+
|
47
|
+
if @@methods[name] && @@methods[name][action]
|
48
|
+
for el in @@methods[name][action].map { |o| @@pointers[o] }
|
49
|
+
if el.kind_of?(Symbol)
|
50
|
+
instance_object.send(el)
|
51
|
+
else
|
52
|
+
instance_object.instance_exec &el
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def define(klass, *args)
|
60
|
+
for action in args
|
61
|
+
klass.class_eval %[
|
62
|
+
def #{action}
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.#{action}(proc=nil, opts={}, &block)
|
66
|
+
BeforeAndAfter.add(self, caller[0], :#{action}, proc || block)
|
67
|
+
end
|
68
|
+
]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# ClassAttributes.define klass, :layout, 'default_value_optional'
|
4
|
+
# klass.layout -> get value
|
5
|
+
# klass.layout = value -> set value
|
6
|
+
|
7
|
+
# class A
|
8
|
+
# ClassAttributes.define self, :layout, 'default'
|
9
|
+
# end
|
10
|
+
# class B < A
|
11
|
+
# layout 'l B'
|
12
|
+
# end
|
13
|
+
# class C < B
|
14
|
+
# end
|
15
|
+
# puts A.layout # default
|
16
|
+
# puts B.layout # l B
|
17
|
+
# puts C.layout # l B
|
18
|
+
|
19
|
+
# class User
|
20
|
+
# ClassAttributes.define_in_current_thread self, :current
|
21
|
+
# end
|
22
|
+
|
23
|
+
# User.current = User.first
|
24
|
+
|
25
|
+
module ClassAttributes
|
26
|
+
extend self
|
27
|
+
|
28
|
+
CA_DEFAULTS = {}
|
29
|
+
|
30
|
+
# defines class variable
|
31
|
+
def define klass, name, default=nil, &block
|
32
|
+
raise ArgumentError, 'name must be symbol' unless name.class == Symbol
|
33
|
+
|
34
|
+
default ||= block if block
|
35
|
+
|
36
|
+
::ClassAttributes::CA_DEFAULTS[name] = { 'Object'=>default }
|
37
|
+
|
38
|
+
klass.class.send(:define_method, name) do |*args|
|
39
|
+
root = ::ClassAttributes::CA_DEFAULTS[name]
|
40
|
+
|
41
|
+
# set and return if argument defined
|
42
|
+
return root[self.to_s] = args[0] if args.length > 0
|
43
|
+
|
44
|
+
# find value and return
|
45
|
+
self.ancestors.map(&:to_s).each do |el|
|
46
|
+
value = root[el]
|
47
|
+
if value || el == 'Object'
|
48
|
+
value = self.instance_exec(&value) if value.is_a?(Proc)
|
49
|
+
return value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# defines class variable in current lux thread
|
56
|
+
def current klass, name
|
57
|
+
klass.class.send(:define_method, name) do |*args|
|
58
|
+
Thread.current[:lux]['%s-%s' % [klass, name]]
|
59
|
+
end
|
60
|
+
|
61
|
+
klass.class.send(:define_method, '%s=' % name) do |value|
|
62
|
+
Thread.current[:lux] ||= {}
|
63
|
+
Thread.current[:lux]['%s-%s' % [klass, name]] = value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# allows adding of params to methods
|
4
|
+
# used in Lux::Api
|
5
|
+
#
|
6
|
+
# param :model_id, type: :integer
|
7
|
+
# param :age, max: 120
|
8
|
+
# def show
|
9
|
+
# end
|
10
|
+
|
11
|
+
# class ModelApi
|
12
|
+
# class << self
|
13
|
+
# def param *args
|
14
|
+
# ClassMethodParams.add_param self, args
|
15
|
+
# end
|
16
|
+
|
17
|
+
# def method_added(m)
|
18
|
+
# ClassMethodParams.add_method self, m
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
|
22
|
+
# ###
|
23
|
+
|
24
|
+
# param :id
|
25
|
+
# param :user_id, Integer
|
26
|
+
# param :model_id, type: :integer
|
27
|
+
# param :age, max: 120
|
28
|
+
# def show
|
29
|
+
|
30
|
+
# end
|
31
|
+
|
32
|
+
# end
|
33
|
+
|
34
|
+
# class UserApi < ModelApi
|
35
|
+
|
36
|
+
# param :name
|
37
|
+
# def edit
|
38
|
+
|
39
|
+
# end
|
40
|
+
|
41
|
+
# end
|
42
|
+
|
43
|
+
# ap ClassMethodParams.params
|
44
|
+
# ap ClassMethodParams.params UserApi, :show
|
45
|
+
# ap ClassMethodParams.all UserApi
|
46
|
+
|
47
|
+
module ClassMethodParams
|
48
|
+
extend self
|
49
|
+
|
50
|
+
@params = {}
|
51
|
+
@cache = {}
|
52
|
+
|
53
|
+
def add_param klass, param, args
|
54
|
+
@cache[klass.to_s] ||= {}
|
55
|
+
@cache[klass.to_s][param] ||= []
|
56
|
+
@cache[klass.to_s][param].push args
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_method klass, m
|
60
|
+
k = klass.to_s
|
61
|
+
@params[k] ||= {}
|
62
|
+
@params[k][m] = @cache[k] ? @cache[k].dup : {}
|
63
|
+
@cache = {}
|
64
|
+
end
|
65
|
+
|
66
|
+
def all_params
|
67
|
+
@params
|
68
|
+
end
|
69
|
+
|
70
|
+
# return all params method in a class
|
71
|
+
def params klass, m
|
72
|
+
return @params unless m
|
73
|
+
|
74
|
+
klass.ancestors.map(&:to_s).each do |klass|
|
75
|
+
return if klass == 'Object'
|
76
|
+
data = @params[klass]
|
77
|
+
return data[m] if data && data[m]
|
78
|
+
end
|
79
|
+
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
# return all methos and all parameters for all methods in a class
|
84
|
+
def all klass
|
85
|
+
data = {}
|
86
|
+
all_methods = klass.instance_methods - Object.instance_methods
|
87
|
+
all_methods.each do |m|
|
88
|
+
data[m] = ClassMethodParams.params(klass, m)
|
89
|
+
end
|
90
|
+
data
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
data/lib/common/crypt.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @author: Dino Reic
|
4
|
+
# @description:
|
5
|
+
# module for easy and convenient access to frequently used crypt operations
|
6
|
+
|
7
|
+
require 'openssl'
|
8
|
+
require 'base64'
|
9
|
+
require 'digest/md5'
|
10
|
+
require 'securerandom'
|
11
|
+
|
12
|
+
module Crypt
|
13
|
+
extend self
|
14
|
+
|
15
|
+
ALGORITHM = 'HS512'
|
16
|
+
|
17
|
+
def secret
|
18
|
+
Lux.env('SECRET')
|
19
|
+
end
|
20
|
+
|
21
|
+
def base64(str)
|
22
|
+
Base64.urlsafe_encode64(str)
|
23
|
+
end
|
24
|
+
|
25
|
+
def uid
|
26
|
+
SecureRandom.hex
|
27
|
+
end
|
28
|
+
|
29
|
+
def sha1(str)
|
30
|
+
Digest::SHA1.hexdigest(str.to_s + secret)
|
31
|
+
end
|
32
|
+
|
33
|
+
def md5(str)
|
34
|
+
Digest::MD5.hexdigest(str.to_s + secret)
|
35
|
+
end
|
36
|
+
|
37
|
+
def bc(str)
|
38
|
+
BCrypt::Password.create(str + secret)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Crypt.encrypt('secret')
|
42
|
+
# Crypt.encrypt('secret', ttl:1.hour, password:'pa$$w0rd')
|
43
|
+
def encrypt(data, opts={})
|
44
|
+
diff = opts.keys - [:ttl, :password]
|
45
|
+
raise 'Unallowed key(s) found %s' % diff.join(', ') if diff.length > 0
|
46
|
+
|
47
|
+
payload = { data:data }
|
48
|
+
payload[:ttl] = Time.now.to_i + opts[:ttl] if opts[:ttl]
|
49
|
+
hmac_secret = "#{secret}#{opts.delete(:password)}"
|
50
|
+
JWT.encode payload, hmac_secret, ALGORITHM
|
51
|
+
end
|
52
|
+
|
53
|
+
# Crypt.decrypt('secret')
|
54
|
+
# Crypt.decrypt('secret', password:'pa$$w0rd')
|
55
|
+
def decrypt(token, opts={})
|
56
|
+
diff = opts.keys - [:password]
|
57
|
+
raise 'Unallowed key(s) found %s' % diff.join(', ') if diff.length > 0
|
58
|
+
|
59
|
+
hmac_secret = "#{secret}#{opts.delete(:password)}"
|
60
|
+
token_data = JWT.decode token, hmac_secret, true, { :algorithm => ALGORITHM }
|
61
|
+
data = token_data[0]
|
62
|
+
raise "Crpted data expired before #{Time.now.to_i - data['ttl']} seconds" if data['ttl'] && data['ttl'] < Time.now.to_i
|
63
|
+
data['data']
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FolderModel
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def find(key)
|
7
|
+
new(key)
|
8
|
+
end
|
9
|
+
|
10
|
+
def all
|
11
|
+
Dir["db/#{self.to_s.tableize}/*.json"].map{|file| new file.split('/').last.sub('.json') }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
###
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
@data[key]
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(key, value)
|
22
|
+
@data[key] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(name, *args)
|
26
|
+
func = name.to_s.split('=')[0].to_sym
|
27
|
+
|
28
|
+
if name.to_s.index('=')
|
29
|
+
@data[func] = args[0]
|
30
|
+
else
|
31
|
+
# raise "Field #{name} not found"
|
32
|
+
@data[func]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def save
|
37
|
+
@storage.write JSON.pretty_generate(@data)
|
38
|
+
@data
|
39
|
+
end
|
40
|
+
alias :save! :save
|
41
|
+
|
42
|
+
def initialize(key)
|
43
|
+
@key = key
|
44
|
+
@storage = Pathname.new("db/#{self.class.to_s.tableize}/#{key}.json")
|
45
|
+
@data = JSON.parse @storage.read
|
46
|
+
@data = @data.h
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# class FooBar < GenericModel
|
4
|
+
#
|
5
|
+
# values [1, 'LinkedIn'],
|
6
|
+
# [2, 'Facebook'],
|
7
|
+
# [3, 'Twitter'],
|
8
|
+
# [4, 'Google'],
|
9
|
+
# [5, 'Email'],
|
10
|
+
# [6, 'Mobile']
|
11
|
+
#
|
12
|
+
# def ico
|
13
|
+
# %{<img src="/images/type/#{code}.png" style="width:16px; height:16px; vertical-align:middle; " />}
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# end
|
17
|
+
|
18
|
+
class GenericModel
|
19
|
+
|
20
|
+
@@values = {}
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def values(vals)
|
24
|
+
@@values[self.to_s] = []
|
25
|
+
vals.map { |el| add_value(el) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_value(val)
|
29
|
+
o = new(val)
|
30
|
+
for key in val.keys
|
31
|
+
eval %[def o.#{key}; @_vals[:#{key}]; end]
|
32
|
+
end
|
33
|
+
@@values[self.to_s].push(o)
|
34
|
+
end
|
35
|
+
|
36
|
+
def find(id)
|
37
|
+
for el in all
|
38
|
+
return el if el.id == id
|
39
|
+
end
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def all
|
44
|
+
@@values[self.to_s]
|
45
|
+
end
|
46
|
+
|
47
|
+
def where(opts)
|
48
|
+
@@values[self.to_s].select{ |el| el[opts.keys[0]] == opts.values[0] }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
###
|
53
|
+
|
54
|
+
def initialize(vals)
|
55
|
+
@_vals = vals
|
56
|
+
end
|
57
|
+
|
58
|
+
def [](key)
|
59
|
+
@_vals[key]
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# base caller
|
4
|
+
# UserPolicy.new(model: @model, user: User.current).can?(:update) -> can current user update @user
|
5
|
+
# ApplicationPolicy.new(user: Lux.page.var.user).can?(:admin_login?) -> can current user login to admin
|
6
|
+
|
7
|
+
# block will capture error message and be triggered only if error is present
|
8
|
+
# ApplicationPolicy.can?(:login) { |msg| http_error 401, "Err: #{msg}".red; return 'no access' }
|
9
|
+
|
10
|
+
class Policy
|
11
|
+
|
12
|
+
def initialize hash
|
13
|
+
for k, v in hash
|
14
|
+
instance_variable_set "@#{k}", v
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# pass block if you want to handle errors yourself
|
19
|
+
# return true if false if block is passed
|
20
|
+
def can? action, &block
|
21
|
+
@action = action.to_s.sub('?','') + '?'
|
22
|
+
@action = @action.to_sym
|
23
|
+
|
24
|
+
# pre check
|
25
|
+
raise RuntimeError, 'Method name not allowed' if %w(can).index(@action)
|
26
|
+
raise NoMethodError, %[Policy check "#{action}" not found in #{self.class}] unless respond_to?(@action)
|
27
|
+
|
28
|
+
call &block
|
29
|
+
end
|
30
|
+
|
31
|
+
# call has to be isolated because specific of error handling
|
32
|
+
def call &block
|
33
|
+
return true if before(@action)
|
34
|
+
return true if send(@action)
|
35
|
+
raise UnauthorizedError, 'Access disabled in policy'
|
36
|
+
rescue UnauthorizedError
|
37
|
+
error = $!.message
|
38
|
+
error += " - #{self.class}.#{@action}" if Lux.config(:show_server_errors)
|
39
|
+
raise UnauthorizedError, error unless block
|
40
|
+
block.call(error)
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
###
|
45
|
+
|
46
|
+
def before action
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
def error message
|
51
|
+
raise UnauthorizedError, message
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StringBase
|
4
|
+
extend self
|
5
|
+
|
6
|
+
KEYS = 'bcdghjklmnpqrstvwxyz'
|
7
|
+
MULTIPLIER = 99
|
8
|
+
|
9
|
+
def encode value
|
10
|
+
value = value * MULTIPLIER
|
11
|
+
ring = Hash[KEYS.chars.map.with_index.to_a.map(&:reverse)]
|
12
|
+
base = KEYS.length
|
13
|
+
result = []
|
14
|
+
until value == 0
|
15
|
+
result << ring[ value % base ]
|
16
|
+
value /= base
|
17
|
+
end
|
18
|
+
result.reverse.join
|
19
|
+
end
|
20
|
+
|
21
|
+
def decode string
|
22
|
+
ring = Hash[KEYS.chars.map.with_index.to_a]
|
23
|
+
base = KEYS.length
|
24
|
+
ret = string.reverse.chars.map.with_index.inject(0) do |sum,(char,i)|
|
25
|
+
sum + ring[char] * (base**i)
|
26
|
+
end
|
27
|
+
raise 'Invalid decode base' if ret%MULTIPLIER>0
|
28
|
+
ret/MULTIPLIER
|
29
|
+
end
|
30
|
+
|
31
|
+
# extract ID from url
|
32
|
+
def extract(url_part)
|
33
|
+
id_str = url_part.split('-').last
|
34
|
+
return nil unless id_str
|
35
|
+
StringBase.decode(id_str) rescue nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Integer
|
40
|
+
def string_id
|
41
|
+
StringBase.encode self
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class String
|
46
|
+
def string_id
|
47
|
+
StringBase.decode self
|
48
|
+
end
|
49
|
+
end
|