2 use Mojo::Base 'Mojolicious';
3 use Mojo::Util qw(dumper);
8 use constant CONFIG_FILE => '/etc/newslash/newslash.conf';
10 # This method will run once at server start
15 # first, check existence of /etc/newslash.conf
16 if ($app->mode eq 'production' && -e CONFIG_FILE) {
17 $app->plugin('Newslash::Plugin::YAMLConfig', file => CONFIG_FILE);
20 #$app->plugin('JSONConfig');
21 $app->plugin('Newslash::Plugin::YAMLConfig');
23 # TODO: load/save configs with database
26 if ($app->config->{Log} && $app->config->{Log}->{system_log}) {
27 # check log is writable
28 my $pathname = $app->config->{Log}->{system_log};
31 $app->log->debug("logs will be outputed to $pathname ...");
32 $app->log(Mojo::Log->new);
33 $app->log->path($pathname);
36 $app->log->error("cannot write system log to file: $pathname");
40 if (open(my $fh, ">", $pathname)) {
42 $app->log->debug("logs will be outputed to $pathname ...");
43 $app->log(Mojo::Log->new);
44 $app->log->path($pathname);
47 $app->log->error("cannot create system log file: $pathname");
53 if ($app->config->{Log} && $app->config->{Log}->{level}) {
54 my $loglv = $app->config->{Log}->{level};
55 if (grep { $loglv eq $_ } qw(debug info warn error fatal)) {
56 $app->log->level($loglv);
59 $app->log->warn('invalid log level given in config file');
63 ############################################################
67 ############################################################
69 # when "test" mode, output debug logs.
70 $app->log->level('debug') if $app->mode eq 'test';
73 $app->plugin('Newslash::Plugin::AccessLog::Debug', $app->config->{Log} || {});
74 $app->plugin('Newslash::Plugin::AccessLog::LocalFile', $app->config->{Log} || {});
76 # secret key for hasing
77 $app->secrets([$app->config->{System}->{secret_key},]);
80 #$app->config->{_Plugins} = {};
83 if ($app->config->{BasicAuth} && $app->config->{BasicAuth}->{enable}) {
84 $app->plugin('Newslash::Plugin::BasicAuth');
87 # use TimeLimitedCache ($app->cache)
88 $app->plugin('Newslash::Plugin::TimeLimitedCache');
90 # use KeyValue Store ($app->kvs)
91 $app->plugin('Newslash::Plugin::KeyValueStore');
94 my $model_opts = $app->config;
95 $model_opts->{Logger} = $app->log;
96 $app->helper(model => Newslash::Model::loader($model_opts));
97 Newslash::Model::startup($model_opts, $app);
99 # use Model Cache ($app->model_cache)
100 $app->plugin('Newslash::Plugin::ModelCache');
102 # use Template::Toolkit 2 render
103 $app->plugin('Newslash::Plugin::TT2Renderer');
106 $app->plugin('Newslash::Plugin::CustomBoxes');
108 # use Analytics helper
109 $app->plugin('Newslash::Plugin::GoogleAnalytics');
111 # user AntiCsrf ($app->anti_csrf)
112 if ($app->mode ne 'test') {
113 # when test mode, disable AntiCsrf.
114 $app->plugin('Newslash::Plugin::AntiCsrf');
118 #$app->plugin('Newslash::Plugin::CSSCompile');
120 # quasi-static content
121 $app->plugin('Newslash::Plugin::QuasiStaticContent');
124 $app->plugin('Newslash::Plugin::JavaScriptLoader');
127 $app->plugin('Newslash::Plugin::UserAuth');
130 $app->plugin('Newslash::Plugin::AccessControl');
133 if ($app->mode ne 'test') {
134 $app->plugin('Newslash::Plugin::ReCaptcha');
137 # set canocal (for test.srad.jp)
138 $app->plugin('Newslash::Plugin::Canonical');
141 $app->plugin('Newslash::Plugin::Hsts');
144 $app->plugin('Newslash::Plugin::EventQue');
147 $app->plugin('Newslash::Plugin::Statics');
149 ############################################################
151 # Generate site-global used javascript file
153 ############################################################
154 my $templ_name = "common/siteconfig.js";
155 my $mod_reasons = $app->model('moderations')->reasons();
156 my $topics = $app->model('tags')->get_topics;
157 my @acl2_types = $app->model('users')->acl2_types;
159 for my $topic (@$topics) {
160 my $lc_keyword = lc($topic->{keyword});
161 my $lc_textname = lc($topic->{textname});
162 $keywords->{$lc_keyword} = {keyword => $topic->{keyword},
163 textname => $topic->{textname},
164 image => $topic->{image}};
165 if ($lc_keyword ne $lc_textname) {
166 $keywords->{$lc_textname} = $keywords->{$lc_keyword};
170 moderate_reasons => $mod_reasons,
172 acl2_types => \@acl2_types,
174 my $siteconfig = $app->tt2renderer->render($templ_name, $vars);
175 $app->static_content->add_content("js/siteconfig.js", $siteconfig, "text/javascript; charset=utf-8");
177 ############################################################
181 ############################################################
183 my $r = $app->routes;
186 $r->get('/')->to('timeline#stories');
187 $r->get('/recent')->to('timeline#recent');
188 $r->get('/popular')->to('timeline#popular');
189 $r->get('/comments')->to('timeline#comments');
190 $r->get('/journals')->to('timeline#journals');
191 $r->get('/submissions')->to('timeline#submissions');
192 $r->get('/polls')->to('timeline#polls');
195 $r->get('/banned')->to('index#banned', noindex => 1);
198 $r->get('/login')->to('login#login');
199 $r->post('/login')->to('login#login');
200 $r->get('/logout')->to('login#logout');
203 $r->get('/my/newuser')->to('login#newuser');
204 $r->post('/my/newuser')->to('login#newuser', captcha_check => 1);
207 $r->get('/story/:sid/' => [sid => qr|\d\d/\d\d/\d\d/\d+|])
208 ->to('story#single');
211 $r->get('/comment/:cid/')->to('comment#single');
214 $r->get('/journal/new')->to('journal#create', seclev => 1);
215 $r->get('/journal/:id/')->to('journal#single');
218 $r->get('/submission/new')->to('submission#create');
219 $r->get('/submission/:id/')->to('submission#single');
220 #$r->post('/submission')->to('submission#create');
223 $r->get('/poll/:qid')->to('poll#single');
224 $r->get('/vote/:qid')->to('poll#vote');
225 $r->get('/polls')->to('poll#index');
226 $r->post('/vote/:qid')->to('poll#vote_post', csrf_check_id => 'vote');
229 $r->get('/story/:year/:month/:day/')->to('archive#story');
230 $r->get('/story/:year/:month/')->to('archive#story');
231 $r->get('/story/')->to('archive#story');
233 $r->get('/journal/:year/:month/:day/')->to('archive#journal');
234 $r->get('/journal/:year/:month/')->to('archive#journal');
235 $r->get('/journal/')->to('archive#journal');
237 $r->get('/submission/:year/:month/:day/')->to('archive#submission');
238 $r->get('/submission/:year/:month/')->to('archive#submission');
239 $r->get('/submission/')->to('archive#submission');
241 $r->get('/poll/:year/:month/')->to('archive#poll');
242 $r->get('/poll/')->to('archive#poll');
245 $r->get('/my/settings')->to('user#settings', seclev => 1);
246 $r->get('/my/sidebar')->to('user#sidebar', seclev => 1);
247 $r->get('/my/messages')->to('my#messages', seclev => 1);
248 $r->get('/my/')->to('user#home', seclev => 1);
251 # pages under /admin needs seclev equal or greater than 10000;
252 my $admin = $r->under('/admin' => sub { my $c = shift; $c->stash(seclev => 10000); return 1; });
254 $admin->get('/firehose/:id/')->to('admin-firehose#single');
255 $admin->get('/submissions')->to('admin-submissions#index');
257 $admin->get('/css')->to('admin-css#edit');
258 $admin->get('/story/edit')->to('admin-story#edit');
260 $admin->get('/users')->to('admin-users#index');
262 $admin->get('/default-sidebar')->to('admin-sidebar#defaults');
264 $admin->get('/sidebar')->to('admin-sidebar#index');
265 $admin->get('/feed')->to('admin-feed#index');
266 $admin->get('/blocking')->to('admin-blocking#index');
268 $admin->get('/repository')->to('admin-repository#index');
271 # pages under /api/v1/admin needs seclev equal or greater than 10000;
272 my $admin_api = $r->under('/api/v1/admin' => sub { my $c = shift; $c->stash(seclev => 10000); return 1; });
273 $admin_api->get('/feed')->to('API::Admin::Feed#get');
274 $admin_api->post('/feed')->to('API::Admin::Feed#post');
275 $admin_api->get('/blocking')->to('API::Admin::Blocking#get');
276 $admin_api->post('/blocking')->to('API::Admin::Blocking#post');
278 $admin_api->get('/repository/export')->to('API::Admin::Repository#export');
279 $admin_api->get('/repository/import')->to('API::Admin::Repository#import');
281 $admin_api->post('/sidebar')->to('API::Admin::Sidebar#post');
282 $admin_api->get('/sidebar')->to('API::Admin::Sidebar#get');
285 my $api = $r->under('/api/v1');
286 $api->post('/login')->to('API::Login#login');
288 $api->get('/sidebar/item')->to('API::SidebarItem#get', seclev => 1);
290 $api->get('/comment')->to('API::Comment#get');
291 $api->post('/comment')->to('API::Comment#post', captcha_check => 1, csrf_check_id => 'comment');
293 $api->get('/user')->to('API::User#get');
294 $api->post('/user')->to('API::User#post', seclev => 1);
296 $api->get('/journal')->to('API::Journal#get');
297 $api->post('/journal')->to('API::Journal#post', seclev => 1, csrf_check_id => 'journal');
299 $api->get('/submission')->to('API::Submission#get');
300 $api->get('/submissions')->to('API::Submission#list');
301 $api->post('/submission')->to('API::Submission#post', captcha_check => 1, csrf_check_id => 'submission');
303 $api->get('/story')->to('API::Story#get');
304 $api->post('/story')->to('API::Story#post');
306 $api->get('/poll')->to('API::Poll#get');
307 $api->post('/poll')->to('API::Poll#post');
308 $api->post('/vote')->to('API::Poll#vote', csrf_check_id => 'vote');
310 $api->get('/moderation')->to('API::Moderation#get');
311 $api->post('/moderation')->to('API::Moderation#post', seclev => 1, csrf_check_id => 'moderation');
313 $api->get('/metamoderation')->to('API::Metamoderation#get');
314 $api->post('/metamoderation')->to('API::Metamoderation#post', seclev => 1, csrf_check_id => 'moderation');
316 $api->post('/relation')->to('API::Relation#post', seclev => 1, csrf_check_id => 'relation');
318 $api->get('/token')->to('API::Token#get');
321 # warning: these pathes uses regexp matching, so must write in tail of route definitions.
322 my $user = $r->under('/:nickname');
323 $user->get('/' => [nickname => qr/~.*/])->to('user#home');
324 $user->get('/journals' => [nickname => qr/~.*/])->to('user#journals');
325 $user->get('/journal' => [nickname => qr/~.*/])->to('user#journals'); # for compatibility
326 $user->get('/comments' => [nickname => qr/~.*/])->to('user#comments');
327 $user->get('/submissions' => [nickname => qr/~.*/])->to('user#submissions');
328 $user->get('/friends' => [nickname => qr/~.*/])->to('user#friends');
329 $user->get('/foes' => [nickname => qr/~.*/])->to('user#foes');
330 $user->get('/fans' => [nickname => qr/~.*/])->to('user#fans');
331 $user->get('/freaks' => [nickname => qr/~.*/])->to('user#freaks');
332 #$user->get('/achievements' => [nickname => qr/~.*/])->to('user#achievements');
333 #$r->get('/:user_name/journal' => [user_name => qr/~.*/])->to('journal#user_journals');