forked from solisoft/fasty
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.moon
236 lines (208 loc) · 9.45 KB
/
app.moon
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
-- fasty CMS
sass = require 'sass'
lapis = require 'lapis'
stringy = require 'stringy'
shell = require 'resty.shell'
encoding = require 'lapis.util.encoding'
app_config = require "lapis.config"
config = app_config.get!
db_config = app_config.get("db_#{config._name}")
import aqls from require 'lib.aqls'
import write_cache, read_cache from require 'lib.cache'
import basic_auth, is_auth from require 'lib.basic_auth'
import after_dispatch from require 'lapis.nginx.context'
import write_content, read_file from require 'lib.service'
import uuid, check_valid_lang, define_content_type, table_deep_merge from require 'lib.utils'
import auth_arangodb, aql, list_databases from require 'lib.arango'
import trim, from_json, to_json, unescape, slugify from require 'lapis.util'
import dynamic_replace, dynamic_page, page_info, splat_to_table
load_page_by_slug, load_redirection, prepare_bindvars from require 'lib.concerns'
jwt = {}
global_data = {}
all_domains = nil
settings = {}
no_db = {}
sub_domain = ''
git_folder = {}
last_db_connect = os.time(os.date("!*t"))
app_config "development", -> measure_performance true
expire_at = () ->
'Expires: ' .. os.date('%a, %d %b %Y %H:%M:%S GMT', os.time() + 60*60*24*365)
--------------------------------------------------------------------------------
define_subdomain = ()=>
sub_domain = @req.headers['x-app'] or stringy.split(@req.headers.host, '.')[1]
--------------------------------------------------------------------------------
load_settings = ()=>
if (os.time(os.date("!*t")) - last_db_connect) > (config.db_ttl and config.db_ttl or 10) -- reconnect each 10 seconds
jwt[sub_domain] = nil
global_data[sub_domain] = nil
last_db_connect = os.time(os.date("!*t"))
unless global_data[sub_domain]
jwt[sub_domain] = auth_arangodb(sub_domain, db_config) if jwt[sub_domain] == nil or all_domains == nil
all_domains = list_databases! if all_domains == nil
if all_domains["db_#{sub_domain}"] == nil
no_db[sub_domain] = true
else
global_data[sub_domain] = aql("db_#{sub_domain}", aqls.settings)['result'][1]
global_data[sub_domain]['partials'] = {}
settings[sub_domain] = global_data[sub_domain].settings[1]
site_settings = from_json(settings[sub_domain].home)
git_folder[sub_domain] = site_settings['git_folder'] and site_settings['git_folder'] or "git/db_#{sub_domain}"
--------------------------------------------------------------------------------
lua_files = (path)=>
for file in lfs.dir(path) do
if file ~= "." and file ~= ".." then
f = path..'/'..file
attr = lfs.attributes (f)
if(type(attr) ~= "nil")
assert(type(attr) == "table")
if(attr.mode == "directory")
lua_files(@, f)
else
if stringy.split(file, ".")[2] == "lua"
path = stringy.split(f, ".")[1]\gsub("/", ".")
@include path
--------------------------------------------------------------------------------
class extends lapis.Application
@before_filter=>
start_time = os.clock!
define_subdomain(@)
after_dispatch ->
if config.measure_performance
print to_json(ngx.ctx.performance)
print to_json("#{(os.clock! - start_time) * 1000}ms")
handle_error: (err, trace)=>
if config._name == 'production' then
print(to_json(err) .. to_json(trace))
@err = err
display_error_page(@, 500)
else
super err, trace
@enable 'etlua'
@include 'applications.uploads'
@include 'applications.services'
@include 'applications.assets'
lua_files(@, "git/lua") if os.rename("git/lua", "git/lua")
layout: false -- we don't need a layout, it will be loaded dynamically
------------------------------------------------------------------------------
display_error_page = (status=500, headers={})=>
error_page = from_json(settings[sub_domain].home)["error_#{status}"]
if error_page ~= nil then
display_page(@, error_page, 404)
else
render: "error_#{status}" , status: status, headers: headers
------------------------------------------------------------------------------
display_page = (slug=nil, status=200)=>
db_name = "db_#{sub_domain}"
asset = ngx.location.capture("/#{git_folder[sub_domain]}/public/#{@req.parsed_url.path}")
html = ''
if asset.status == 200
content_type: define_content_type(@req.parsed_url.path), status: 200, asset.body, headers: { 'expires': expire_at! }
else
slug = @params.slug if slug == nil
slug = unescape(slug)
page_content_type = define_content_type(slug)
slug = slug\gsub(".pdf", "") if page_content_type == "application/pdf"
@params.lang = check_valid_lang(settings[sub_domain].langs, @params.lang)
@session.lang = @params.lang
used_lang = @params.lang
cache = read_cache(db_name, @req.parsed_url.path)
infos = page_info(git_folder[sub_domain], db_name, @params.slug, @params.lang)
if cache.status == 200
html = cache.body
else
redirection = load_redirection(db_name, @params)
current_page = load_page_by_slug(git_folder[sub_domain], db_name, slug, @params.lang)
if current_page == nil then
used_lang = stringy.split(settings[sub_domain].langs, ',')[1]
infos = page_info(git_folder[sub_domain], db_name, @params.slug, used_lang)
current_page = load_page_by_slug(git_folder[sub_domain], db_name, slug, used_lang)
if @params.splat and table.getn(stringy.split(@params.splat, '/')) % 2 == 1
@params.splat = "slug/#{@params.splat}"
if infos == nil
infos = { 'page': {}, 'folder': {} }
else
current_page.item = table_deep_merge(current_page.item, infos.page)
if infos.page.og_aql and infos.page.og_aql[@params.lang] and infos.page.og_aql[@params.lang] != ''
splat = {}
splat = splat_to_table(@params.splat) if @params.splat
bindvars = prepare_bindvars(splat, infos.page.og_aql[@params.lang], @params.lang)
@params.og_data = aql(db_name, infos.page.og_aql[@params.lang], bindvars)['result'][1]
if redirection == nil then
params_lang = @params.lang
@params.lang = used_lang
html = dynamic_page(db_name, current_page, @params, global_data[sub_domain])
@params.lang = params_lang
else
html = redirection
html = dynamic_replace(db_name, html, global_data[sub_domain], {}, @params)
if infos.page.ttl
write_cache(@req.parsed_url.path, html, db_name, infos.page.ttl)
basic_auth(@, settings[sub_domain], infos) -- check if website need a basic auth
if is_auth(@, settings[sub_domain], infos)
if html ~= 'null' and trim(html) != '' then
if page_content_type ~= "application/pdf" then
content_type: page_content_type, html, status: status
else -- convert html data to pdf
filename = "#{uuid!}.html"
write_content "print/#{filename}", html
shell.run "wkhtmltopdf print/#{filename} print/#{filename}.pdf"
pdf = read_file "print/#{filename}.pdf", "rb"
shell.run "rm print/#{filename}"
shell.run "rm print/#{filename}.pdf"
content_type: "application/pdf", pdf, status: status
else
display_error_page(@, 404)
else
status: 401, headers: { 'WWW-Authenticate': 'Basic realm=\"admin\"' }
------------------------------------------------------------------------------
[need_a_db: '/need_a_db']:=> render: true
------------------------------------------------------------------------------
[robots: '/robots.txt']:=>
if no_db[sub_domain] then redirect_to: 'need_a_db'
else
load_settings(@)
@params.lang = @session.lang
@params.all = '-'
@params.slug = 'robots'
display_page(@)
------------------------------------------------------------------------------
[root: '/(:lang)']:=>
if no_db[sub_domain] then redirect_to: 'need_a_db'
else
load_settings(@)
lang = @params.lang or stringy.split(settings[sub_domain].langs, ',')[1]
@session.lang = check_valid_lang(settings[sub_domain].langs, lang)
if @params.lang and @params.lang ~= @session.lang
@params.all = '-'
@params.slug = @params.lang
@params.lang = @session.lang
@session.lang = check_valid_lang(settings[sub_domain].langs, lang)
if @params.slug
display_page(@)
else
home = from_json(settings[sub_domain].home)
@params.lang = @session.lang
@params.all = home['all']
@params.slug = home['slug']
@params.splat = home['splat'] if home['splat']
if type(home['root_redirection']) == 'string'
redirect_to: home['root_redirection']
else
display_page(@)
------------------------------------------------------------------------------
[page_no_lang: '/:all/:slug']:=>
if no_db[sub_domain] then redirect_to: '/need_a_db'
else
load_settings(@)
@params.lang = check_valid_lang(settings[sub_domain].langs, @params.all)
unless @session.lang
@session.lang = stringy.split(settings[sub_domain].langs, ',')[1]
display_page(@)
------------------------------------------------------------------------------
[page: '/:lang/:all/:slug(/*)']:=>
if no_db[sub_domain] then redirect_to: '/need_a_db'
else
load_settings(@)
display_page(@)
--