rubko 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/bin/rubko-deploy +40 -0
- data/bin/rubko-init +6 -0
- data/lib/rubko/app.rb +79 -0
- data/lib/rubko/asset/fileStream.rb +18 -0
- data/lib/rubko/asset/gzipStream.rb +26 -0
- data/lib/rubko/asset.rb +71 -0
- data/lib/rubko/base.rb +123 -0
- data/lib/rubko/controller.rb +17 -0
- data/lib/rubko/model.rb +5 -0
- data/lib/rubko/plugin.rb +7 -0
- data/lib/rubko/plugins/cookie.rb +45 -0
- data/lib/rubko/plugins/db.rb +389 -0
- data/lib/rubko/plugins/facebook.rb +50 -0
- data/lib/rubko/plugins/log.rb +49 -0
- data/lib/rubko/plugins/session.rb +88 -0
- data/lib/rubko/plugins/storage/db.rb +6 -0
- data/lib/rubko/plugins/storage/disk.rb +50 -0
- data/lib/rubko/plugins/storage/memory.rb +60 -0
- data/lib/rubko/plugins/url.rb +91 -0
- data/lib/rubko/socket.rb +23 -0
- data/lib/rubko/storage.rb +27 -0
- data/lib/rubko.rb +32 -0
- data/rubko.gemspec +22 -0
- data/stamp/.gitignore +3 -0
- data/stamp/config/db.rb +8 -0
- data/stamp/config/facebook.rb +8 -0
- data/stamp/config/session.rb +7 -0
- data/stamp/config/url.rb +7 -0
- data/stamp/config.ru +38 -0
- data/stamp/controllers/error404.rb +19 -0
- data/stamp/controllers/files.rb +20 -0
- data/stamp/controllers/welcome.rb +6 -0
- data/stamp/models/user.rb +14 -0
- data/stamp/public/css/.private/default.sass +31 -0
- data/stamp/public/img/favicon.png +0 -0
- data/stamp/public/js/jquery/iframize.js +25 -0
- data/stamp/public/js/jquery/translate.js +112 -0
- data/stamp/public/js/merge.sh +10 -0
- data/stamp/tarok.yml +17 -0
- data/stamp/views/welcome.haml +11 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 507cef7351098c01960413739e54b19d74ea872d
|
4
|
+
data.tar.gz: b6476fac467d2265b8777620e77b9557fc16e19f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 926e843d6848ceb3dccb87affd87b1c57998a8d38822517e2cbc02ef077cdde55fb2944d62741c7b67e04388cc2fcf6deea4b5fe59626fa47cf5ca33ce0ca19d
|
7
|
+
data.tar.gz: 35f3021ce7bae47895be95216f0358314dd93a5c47b972d94540aa0df94dfdfac662a1768f610c67a5ed37007fbf4f3342cc81650192dfa134be946c0905d032
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/bin/rubko-deploy
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# settings
|
4
|
+
|
5
|
+
ssh = true
|
6
|
+
host = 'hetzner:54321'
|
7
|
+
user = 'root'
|
8
|
+
remote = '/srv/http/' + File.basename(Dir.getwd)
|
9
|
+
|
10
|
+
exclude = [
|
11
|
+
'log.txt',
|
12
|
+
#'config/db.rb',
|
13
|
+
'.deploy.rb',
|
14
|
+
'.dev/',
|
15
|
+
'.run/',
|
16
|
+
'.repo/',
|
17
|
+
'.gitignore',
|
18
|
+
'.git/'
|
19
|
+
]
|
20
|
+
|
21
|
+
# program
|
22
|
+
|
23
|
+
require 'io/console'
|
24
|
+
print 'Password: ';
|
25
|
+
pass = STDIN.noecho(&:gets).strip
|
26
|
+
puts
|
27
|
+
|
28
|
+
protocol = ssh ? 'sftp' : 'ftp'
|
29
|
+
|
30
|
+
commands = [
|
31
|
+
'set ftp:list-options -a',
|
32
|
+
"open #{protocol}://#{user}:#{pass}@#{host}",
|
33
|
+
'lcd ./',
|
34
|
+
"cd #{remote}",
|
35
|
+
'mirror -L --reverse --only-newer --verbose ' + exclude.map { |el|
|
36
|
+
'--exclude-glob ' + el
|
37
|
+
}.join(' ')
|
38
|
+
]
|
39
|
+
|
40
|
+
system 'lftp', '-c', commands.join(';')
|
data/bin/rubko-init
ADDED
data/lib/rubko/app.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rubko/base'
|
2
|
+
require 'rubko/asset/gzipStream'
|
3
|
+
|
4
|
+
class Rubko::App
|
5
|
+
include Rubko::Base
|
6
|
+
|
7
|
+
def initialize(env, shared = nil)
|
8
|
+
@status = 200
|
9
|
+
@headers = {'Connection' => 'Keep-Alive', 'Date' => Time.now.httpdate}
|
10
|
+
@mime = 'text/html'
|
11
|
+
@body = ''
|
12
|
+
|
13
|
+
@shared = shared
|
14
|
+
@finalizers = []
|
15
|
+
|
16
|
+
@env = env
|
17
|
+
params = Rack::Utils.parse_nested_query @env['rack.input'].read
|
18
|
+
@params = Hash[ params.map { |k, v|
|
19
|
+
[ k.to_sym, v ]
|
20
|
+
} ]
|
21
|
+
|
22
|
+
super()
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor :status, :headers, :mime, :body
|
26
|
+
attr_reader :env, :params, :shared, :finalizers
|
27
|
+
|
28
|
+
def init(path)
|
29
|
+
url.path = path
|
30
|
+
request( *url.newPath )
|
31
|
+
end
|
32
|
+
|
33
|
+
def request(name = :welcome, action = nil, *path)
|
34
|
+
controller = loadController(name) || loadController(:error404)
|
35
|
+
|
36
|
+
calls = [ action ? "_#{action}" : 'index' ]
|
37
|
+
calls << calls.first + '_' + url.method
|
38
|
+
|
39
|
+
calls.map! { |call|
|
40
|
+
if controller.respond_to? call
|
41
|
+
@body = controller.__send__ call, *path
|
42
|
+
true
|
43
|
+
end
|
44
|
+
}
|
45
|
+
if calls.compact.empty?
|
46
|
+
@body = controller.other action, *path
|
47
|
+
end
|
48
|
+
|
49
|
+
# finalize request
|
50
|
+
finalizers.reverse_each(&:finalize)
|
51
|
+
@headers['Content-Type'] = "#{mime}; charset=utf-8" unless @status == 304
|
52
|
+
|
53
|
+
# make sure body responds to :each
|
54
|
+
@body = @body.to_s if Integer === @body
|
55
|
+
@body = [@body] if String === @body
|
56
|
+
@body = [] unless @body.respond_to? :each
|
57
|
+
|
58
|
+
# compress
|
59
|
+
if controller.compressible?
|
60
|
+
headers['Content-Encoding'] = 'gzip'
|
61
|
+
@body = Rubko::Asset::GzipStream.new @body
|
62
|
+
end
|
63
|
+
|
64
|
+
# add Content-Length header
|
65
|
+
if @body.respond_to? :bytesize
|
66
|
+
headers['Content-Length'] = @body.bytesize.to_s
|
67
|
+
elsif Array === @body
|
68
|
+
headers['Content-Length'] = @body.reduce(0) { |sum, x|
|
69
|
+
sum + x.bytesize
|
70
|
+
}.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
[@status, @headers, @body]
|
74
|
+
end
|
75
|
+
|
76
|
+
def production?
|
77
|
+
ENV['RACK_ENV'] == 'production'
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Rubko::Asset::FileStream
|
2
|
+
def initialize(path, chunk = 32)
|
3
|
+
@path = path
|
4
|
+
@chunk = 1024*chunk
|
5
|
+
end
|
6
|
+
|
7
|
+
def each
|
8
|
+
File.open(@path, 'rb') { |f|
|
9
|
+
while part = f.read(@chunk)
|
10
|
+
yield part
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def bytesize
|
16
|
+
File.size @path
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubko/controller'
|
2
|
+
require 'zlib'
|
3
|
+
|
4
|
+
class Rubko::Asset < Rubko::Controller
|
5
|
+
class GzipStream
|
6
|
+
def initialize(body, mtime = Time.now)
|
7
|
+
@body = body
|
8
|
+
@gzip = Zlib::GzipWriter.new self
|
9
|
+
@gzip.mtime = mtime
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
@writer = block
|
14
|
+
@body.each { |part|
|
15
|
+
@gzip.write part
|
16
|
+
@gzip.flush
|
17
|
+
}
|
18
|
+
ensure
|
19
|
+
@gzip.close
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(data)
|
23
|
+
@writer.call data
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/rubko/asset.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rubko/controller'
|
2
|
+
|
3
|
+
# in case we want to serve files and get notified on hits
|
4
|
+
class Rubko::Asset < Rubko::Controller
|
5
|
+
|
6
|
+
def init
|
7
|
+
@dir = 'public'
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :dir
|
11
|
+
|
12
|
+
def hit(*path)
|
13
|
+
puts "File #{path*'/'} hit." unless production?
|
14
|
+
end
|
15
|
+
|
16
|
+
def cache(*path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def miss(*path)
|
20
|
+
puts "File #{path*'/'} not found (404)."
|
21
|
+
loadController(:error404).other( *path )
|
22
|
+
end
|
23
|
+
|
24
|
+
private :hit, :cache, :miss
|
25
|
+
|
26
|
+
def compressible?
|
27
|
+
super && @mime != 'application/octet-stream' &&
|
28
|
+
['application', 'text'].any? { |type|
|
29
|
+
@mime.start_with? type+'/'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :mime, :modified
|
34
|
+
|
35
|
+
def index
|
36
|
+
other
|
37
|
+
end
|
38
|
+
|
39
|
+
def other(*path)
|
40
|
+
# protect private files
|
41
|
+
if path.include?('..') || path.include?('.private') && production?
|
42
|
+
return miss(*path)
|
43
|
+
end
|
44
|
+
|
45
|
+
path.shift if path[0] =~ /^\d*$/
|
46
|
+
path = "#{@dir}/#{path * '/'}"
|
47
|
+
@mime = Rack::Mime.mime_type File.extname(path)
|
48
|
+
if File.file? path
|
49
|
+
self.mime = @mime
|
50
|
+
headers['Cache-Control'] = 'public'
|
51
|
+
headers['Vary'] = 'Accept-Encoding'
|
52
|
+
|
53
|
+
@modified = File.mtime path
|
54
|
+
since = (Time.httpdate(env['HTTP_IF_MODIFIED_SINCE']).to_i rescue 0)
|
55
|
+
headers['Last-Modified'] = @modified.httpdate
|
56
|
+
headers['Expires'] = (DateTime.now >> 12).httpdate
|
57
|
+
|
58
|
+
if @modified.to_i <= since
|
59
|
+
cache( *path )
|
60
|
+
self.status = 304
|
61
|
+
''
|
62
|
+
else
|
63
|
+
hit( *path )
|
64
|
+
require 'rubko/asset/fileStream'
|
65
|
+
FileStream.new path
|
66
|
+
end
|
67
|
+
else
|
68
|
+
miss( *path )
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/rubko/base.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Rubko
|
5
|
+
module Base
|
6
|
+
def initialize(parent = nil)
|
7
|
+
@parent = parent
|
8
|
+
finalizers << self if @parent
|
9
|
+
@plugins = {}
|
10
|
+
puts "#{self.class} initialized." unless production?
|
11
|
+
end
|
12
|
+
|
13
|
+
def init(*) end
|
14
|
+
def finalize(*) end
|
15
|
+
|
16
|
+
attr_accessor :parent
|
17
|
+
|
18
|
+
def loadFile(name)
|
19
|
+
require(name) || true
|
20
|
+
rescue LoadError
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def camelize(array)
|
25
|
+
array.map { |x|
|
26
|
+
x.to_s.downcase.capitalize
|
27
|
+
}.join
|
28
|
+
end
|
29
|
+
def uncamelize(str)
|
30
|
+
str.to_s.split(/(?=[A-Z])/).map(&:downcase)
|
31
|
+
end
|
32
|
+
|
33
|
+
def load(what, name, *args)
|
34
|
+
Kernel.const_get(camelize [*[*name].reverse, what]).
|
35
|
+
new(self).tap { |x| x.init(*args) }
|
36
|
+
end
|
37
|
+
private :load
|
38
|
+
|
39
|
+
def loadPlugin(name, *args)
|
40
|
+
require 'rubko/plugin'
|
41
|
+
|
42
|
+
process = -> search, range, proc=nil {
|
43
|
+
p = Dir[search].sort_by { |x|
|
44
|
+
x.split('/').size
|
45
|
+
}.first
|
46
|
+
if p
|
47
|
+
loadFile p
|
48
|
+
p[range].split '/'
|
49
|
+
else
|
50
|
+
proc.call if proc
|
51
|
+
end
|
52
|
+
}
|
53
|
+
|
54
|
+
path = uncamelize(name).reverse * '/'
|
55
|
+
name = process.call "./plugins/**/#{path}.rb", 10..-4, -> {
|
56
|
+
d = __dir__
|
57
|
+
process.call "#{d}/plugins/**/#{path}.rb", (d.size+9)..-4
|
58
|
+
}
|
59
|
+
return false unless name
|
60
|
+
|
61
|
+
loadFile "./config/#{name * '/'}.rb"
|
62
|
+
load :plugin, name, *args
|
63
|
+
end
|
64
|
+
|
65
|
+
def loadController(name, *args)
|
66
|
+
require 'rubko/controller'
|
67
|
+
return false unless loadFile "./controllers/#{name}.rb"
|
68
|
+
load :controller, name, *args
|
69
|
+
end
|
70
|
+
|
71
|
+
def loadModel(name, *args)
|
72
|
+
require 'rubko/model'
|
73
|
+
return false unless loadFile "./models/#{name}.rb"
|
74
|
+
load :model, name, *args
|
75
|
+
end
|
76
|
+
|
77
|
+
def loadView(*name)
|
78
|
+
if production?
|
79
|
+
template = memory[:views, name]
|
80
|
+
end
|
81
|
+
unless template
|
82
|
+
fileName = 'views/'+name.join('/')+'.erb'
|
83
|
+
if File.exists? fileName
|
84
|
+
require 'erb'
|
85
|
+
template = ERB.new File.read(fileName)
|
86
|
+
else
|
87
|
+
fileName = 'views/'+name.join('/')+'.haml'
|
88
|
+
return unless File.exists? fileName
|
89
|
+
require 'haml'
|
90
|
+
template = Haml::Engine.new File.read(fileName), ugly: true, remove_whitespace: true
|
91
|
+
end
|
92
|
+
memory[:views, name] = template if production?
|
93
|
+
puts "Template #{name * '/'} initialized."
|
94
|
+
end
|
95
|
+
|
96
|
+
case template.class.to_s
|
97
|
+
when 'ERB'
|
98
|
+
template.result binding
|
99
|
+
when 'Haml::Engine'
|
100
|
+
template.render binding
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def method_missing(name, *args)
|
105
|
+
if @plugins && @plugins[name]
|
106
|
+
@plugins[name]
|
107
|
+
elsif parent
|
108
|
+
parent.__send__ name, *args
|
109
|
+
else
|
110
|
+
@plugins[name] = loadPlugin(name) || super
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def httpGet(url)
|
115
|
+
require 'net/http'
|
116
|
+
Net::HTTP.get_response(URI.parse url).body
|
117
|
+
end
|
118
|
+
|
119
|
+
def jsonParse(resource)
|
120
|
+
JSON.parse resource, symbolize_names: true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubko/base'
|
2
|
+
|
3
|
+
class Rubko::Controller
|
4
|
+
include Rubko::Base
|
5
|
+
|
6
|
+
def index
|
7
|
+
'It works. Please create the index() method.'
|
8
|
+
end
|
9
|
+
|
10
|
+
def other(name, *args)
|
11
|
+
loadController('error404').other name, args
|
12
|
+
end
|
13
|
+
|
14
|
+
def compressible?
|
15
|
+
env['HTTP_ACCEPT_ENCODING'].to_s.split(',').map(&:strip).include? 'gzip'
|
16
|
+
end
|
17
|
+
end
|
data/lib/rubko/model.rb
ADDED
data/lib/rubko/plugin.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
class CookiePlugin < Rubko::Plugin
|
2
|
+
def init
|
3
|
+
@domain = nil
|
4
|
+
@path = url.base
|
5
|
+
@httpOnly = true
|
6
|
+
@secure = false
|
7
|
+
|
8
|
+
@maxAge = 30*24*60*60
|
9
|
+
@expires = nil
|
10
|
+
config
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :domain, :path, :httpOnly, :secure, :maxAge, :expires
|
14
|
+
|
15
|
+
def cookies
|
16
|
+
return @cookies if @cookies
|
17
|
+
return @cookies = {} unless env['HTTP_COOKIE']
|
18
|
+
|
19
|
+
@cookies = Rack::Utils.parse_query(env['HTTP_COOKIE'], ';,').
|
20
|
+
inject({}) { |h, (k,v)|
|
21
|
+
h.tap { |x|
|
22
|
+
x[k.to_sym] = (Array === v) ? v.first : v
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
private :cookies
|
27
|
+
|
28
|
+
def ip
|
29
|
+
Rack::Request.new(env).ip.encode 'UTF-8'
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key = nil)
|
33
|
+
key.nil? ? cookies : cookies[key]
|
34
|
+
end
|
35
|
+
|
36
|
+
def []=(key, val)
|
37
|
+
if val.nil?
|
38
|
+
Rack::Utils.delete_cookie_header! headers, key, domain: domain, path: path
|
39
|
+
else
|
40
|
+
Rack::Utils.set_cookie_header! headers, key, value: val, domain: domain, path: path,
|
41
|
+
httponly: httpOnly, secure: secure, max_age: maxAge.to_s, expires: expires
|
42
|
+
end
|
43
|
+
val
|
44
|
+
end
|
45
|
+
end
|