OSDN Git Service

implement blocking related API
[newslash/newslash.git] / src / newslash_web / lib / Newslash / Web.pm
1 package Newslash::Web;
2 use Mojo::Base 'Mojolicious';
3 use Mojo::Util qw(dumper);
4
5 use Newslash::Model;
6
7 use constant CONFIG_FILE => '/etc/newslash/newslash.conf';
8
9 # This method will run once at server start
10 sub startup {
11     my $app = shift;
12
13     # load config file
14     # first, check existence of /etc/newslash.conf
15     if ($app->mode eq 'production' && -e CONFIG_FILE) {
16         $app->plugin('Newslash::Plugin::YAMLConfig', file => CONFIG_FILE);
17     }
18     else {
19         #$app->plugin('JSONConfig');
20         $app->plugin('Newslash::Plugin::YAMLConfig');
21     }
22     # TODO: load/save configs with database
23
24     # set log level
25     if ($app->config->{Log} && $app->config->{Log}->{level}) {
26         my $loglv = $app->config->{Log}->{level};
27         if (grep { $loglv eq $_ } qw(debug info warn error fatal)) {
28             $app->log->level($loglv);
29         }
30         else {
31             $app->log->warn('invalid log level given in config file');
32         }
33     }
34
35     ############################################################
36     #
37     # Plugin Settings
38     #
39     ############################################################
40
41     # when "test" mode, output debug logs.
42     $app->log->level('debug') if $app->mode eq 'test';
43
44     # enable logging
45     $app->plugin('Newslash::Plugin::AccessLog::Debug', $app->config->{Log} || {});
46     $app->plugin('Newslash::Plugin::AccessLog::LocalFile', $app->config->{Log} || {});
47
48     # secret key for hasing
49     $app->secrets([$app->config->{System}->{secret_key},]);
50
51     # stash for plugins
52     #$app->config->{_Plugins} = {};
53
54     # use BasicAuth?
55     if ($app->config->{BasicAuth} && $app->config->{BasicAuth}->{enable}) {
56         $app->plugin('Newslash::Plugin::BasicAuth');
57     }
58
59     # use TimeLimitedCache ($app->cache)
60     $app->plugin('Newslash::Plugin::TimeLimitedCache');
61
62     # use KeyValue Store ($app->kvs)
63     $app->plugin('Newslash::Plugin::KeyValueStore');
64
65     # add Model Loader
66     my $model_opts = $app->config;
67     $model_opts->{Logger} = $app->log;
68     $app->helper(model => Newslash::Model::loader($model_opts));
69     Newslash::Model::startup($model_opts, $app);
70
71     # use Model Cache ($app->model_cache)
72     $app->plugin('Newslash::Plugin::ModelCache');
73
74     # use Template::Toolkit 2 render
75     $app->plugin('Newslash::Plugin::TT2Renderer');
76
77     # user AntiCsrf ($app->anti_csrf)
78     if ($app->mode ne 'test') {
79         # when test mode, disable AntiCsrf.
80         $app->plugin('Newslash::Plugin::AntiCsrf');
81     }
82
83     # compile CSS
84     #$app->plugin('Newslash::Plugin::CSSCompile');
85
86     # quasi-static content
87     $app->plugin('Newslash::Plugin::QuasiStaticContent');
88
89     # user authorization
90     $app->plugin('Newslash::Plugin::UserAuth');
91
92     # access control
93     $app->plugin('Newslash::Plugin::AccessControl');
94
95     # ReCaptcha control
96     if ($app->mode ne 'test') {
97         $app->plugin('Newslash::Plugin::ReCaptcha');
98     }
99
100     # Event Que
101     $app->plugin('Newslash::Plugin::EventQue');
102
103
104     ############################################################
105     #
106     # Generate site-global used javascript file
107     #
108     ############################################################
109     my $templ_name = "common/siteconfig.js";
110     my $mod_reasons = $app->model('moderations')->reasons();
111     my $topics = $app->model('tags')->get_topics;
112     my @acl2_types = $app->model('users')->acl2_types;
113     my $keywords = {};
114     for my $topic (@$topics) {
115         my $lc_keyword = lc($topic->{keyword});
116         my $lc_textname = lc($topic->{textname});
117         $keywords->{$lc_keyword} = {keyword => $topic->{keyword},
118                                     textname => $topic->{textname},
119                                     image => $topic->{image}};
120         if ($lc_keyword ne $lc_textname) {
121             $keywords->{$lc_textname} = $keywords->{$lc_keyword};
122         }
123     }
124     my $vars = {
125                 moderate_reasons => $mod_reasons,
126                 topics => $keywords,
127                 acl2_types => \@acl2_types,
128                };
129     my $siteconfig = $app->tt2renderer->render($templ_name, $vars);
130     $app->static_content->add_content("js/siteconfig.js", $siteconfig, "text/javascript; charset=utf-8");
131
132     ############################################################
133     #
134     # Routing Settings
135     #
136     ############################################################
137
138     my $r = $app->routes;
139
140     # index page
141     $r->get('/')->to('index#root');
142     $r->get('/recent')->to('timeline#recent');
143     $r->get('/journals')->to('index#journals');
144     $r->get('/submissions')->to('index#submissions');
145
146     # comment
147     $r->get('/comments')->to('comment#index');
148
149     # Banned page
150     $r->get('/banned')->to('index#banned', noindex => 1);
151
152     # Login / Logout
153     $r->get('/login')->to('login#login');
154     $r->post('/login')->to('login#login');
155     $r->get('/logout')->to('login#logout');
156
157     # User Register
158     $r->get('/my/newuser')->to('login#newuser');
159     $r->post('/my/newuser')->to('login#newuser', captcha_check => 1);
160
161     # story page
162     $r->get('/story/:sid/' => [sid => qr|\d\d/\d\d/\d\d/\d+|])
163       ->to('story#story');
164
165     # journal page
166     $r->get('/journal/new')->to('journal#create', seclev => 1);
167     $r->get('/journal/:id/')->to('journal#journal');
168
169     # submission page
170     $r->get('/submission/new')->to('submission#create');
171     $r->get('/submission/:id/')->to('submission#submission');
172     #$r->post('/submission')->to('submission#create');
173
174     # polls page
175     $r->get('/poll/:qid')->to('poll#single');
176     $r->get('/vote/:qid')->to('poll#vote');
177     $r->get('/polls')->to('poll#index');
178     $r->post('/vote/:qid')->to('poll#post', csrf_check_id => 'vote');
179
180     # archive page
181     $r->get('/story/:year/:month/:day/')->to('archive#story');
182     $r->get('/story/:year/:month/')->to('archive#story');
183     $r->get('/story/:year/')->to('archive#story');
184     $r->get('/story/')->to('archive#story');
185     $r->get('/journal/:year/:month/:day/')->to('archive#journal');
186     $r->get('/journal/:year/:month/')->to('archive#journal');
187     $r->get('/journal/:year/')->to('archive#journal');
188     $r->get('/journal/')->to('archive#journal');
189
190     $r->get('/journal/:year/:month/:day/' => [year => qr/[0-9]{2}/,
191                                             month => qr/[0-9]{2}/,
192                                               day => qr/[0-9]{2}/])->to('archive#journal');
193
194     $r->get('/comment/:year/:month/:day/' => [year => qr/[0-9]{2}/,
195                                             month => qr/[0-9]{2}/,
196                                             day => qr/[0-9]{2}/])->to('archive#comment');
197
198     $r->get('/submission/:year/:month/:day/' => [year => qr/[0-9]{2}/,
199                                             month => qr/[0-9]{2}/,
200                                             day => qr/[0-9]{2}/])->to('archive#submission');
201
202
203     # my page
204     $r->get('/my/settings')->to('user#settings', seclev => 1);
205     $r->get('/my/sidebar')->to('user#sidebar', seclev => 1);
206     $r->get('/my/messages')->to('my#messages', seclev => 1);
207     $r->get('/my/')->to('user#home', seclev => 1);
208
209     # Admin
210     # pages under /admin needs seclev equal or greater than 10000;
211     my $admin = $r->under('/admin' => sub { my $c = shift; $c->stash(seclev => 10000); return 1; });
212
213     $admin->get('/submissions')->to('admin-submissions#index');
214     $admin->get('/submissions/list')->to('admin-submissions#list');
215
216     $admin->get('/css')->to('admin-css#edit');
217     $admin->get('/story/edit')->to('admin-story#edit');
218
219     $admin->get('/users')->to('admin-users#index');
220
221     $admin->get('/default-sidebar')->to('admin-sidebar#defaults');
222
223     $admin->get('/sidebar')->to('admin-sidebar#index');
224     $admin->post('/sidebar/update')->to('admin-sidebar#update');
225     $admin->post('/sidebar/delete')->to('admin-sidebar#delete');
226     $admin->any(['GET', 'POST'] => '/sidebar/list')->to('admin-sidebar#list');
227     $admin->post('/sidebar/get')->to('admin-sidebar#get');
228
229     $admin->get('/feed')->to('admin-feed#index');
230     $admin->get('/blocking')->to('admin-blocking#index');
231
232     $admin->get('/repository')->to('admin-repository#index');
233
234     # Admin API
235     # pages under /api/v1/admin needs seclev equal or greater than 10000;
236     my $admin_api = $r->under('/api/v1/admin' => sub { my $c = shift; $c->stash(seclev => 10000); return 1; });
237     $admin_api->get('/feed')->to('API::Admin::Feed#get');
238     $admin_api->post('/feed')->to('API::Admin::Feed#post');
239     $admin_api->get('/blocking')->to('API::Admin::Blocking#get');
240     $admin_api->post('/blocking')->to('API::Admin::Blocking#post');
241
242     $admin_api->get('/repository/export')->to('API::Admin::Repository#export');
243     $admin_api->get('/repository/import')->to('API::Admin::Repository#import');
244
245     # API
246     my $api = $r->under('/api/v1');
247     $api->get('/sidebars')->to('admin-sidebar#list');
248
249     $api->post('/login')->to('API::Login#login');
250
251     $api->get('/comment')->to('API::Comment#get');
252     $api->post('/comment')->to('API::Comment#post', captcha_check => 1, csrf_check_id => 'comment');
253
254     $api->get('/user')->to('API::User#get');
255     $api->post('/user')->to('API::User#post', seclev => 1);
256
257     $api->get('/journal')->to('API::Journal#get');
258     $api->post('/journal')->to('API::Journal#post', seclev => 1, csrf_check_id => 'journal');
259
260     $api->get('/submission')->to('API::Submission#get');
261     $api->post('/submission')->to('API::Submission#post', captcha_check => 1, csrf_check_id => 'submission');
262
263     $api->get('/story')->to('API::Story#get');
264     $api->post('/story')->to('API::Story#post');
265
266     $api->get('/poll')->to('API::Poll#get');
267     $api->post('/poll')->to('API::Poll#post');
268     $api->post('/vote')->to('API::Poll#vote', csrf_check_id => 'vote');
269
270     $api->get('/moderation')->to('API::Moderation#get');
271     $api->post('/moderation')->to('API::Moderation#post', seclev => 1, csrf_check_id => 'moderation');
272
273     $api->get('/metamoderation')->to('API::Metamoderation#get');
274     $api->post('/metamoderation')->to('API::Metamoderation#post', seclev => 1, csrf_check_id => 'moderation');
275
276     $api->post('/relation')->to('API::Relation#post', seclev => 1, csrf_check_id => 'relation');
277
278     $api->get('/token')->to('API::Token#get');
279
280     # user page
281     # warning: these pathes uses regexp matching, so must write in tail of route definitions.
282     my $user = $r->under('/:nickname');
283     $user->get('/'             => [nickname => qr/~.*/])->to('user#home');
284     $user->get('/journals'     => [nickname => qr/~.*/])->to('user#journals');
285     $user->get('/comments'     => [nickname => qr/~.*/])->to('user#comments');
286     $user->get('/submissions'  => [nickname => qr/~.*/])->to('user#submissions');
287     $user->get('/friends'      => [nickname => qr/~.*/])->to('user#friends');
288     $user->get('/foes'         => [nickname => qr/~.*/])->to('user#foes');
289     $user->get('/fans'         => [nickname => qr/~.*/])->to('user#fans');
290     $user->get('/freaks'       => [nickname => qr/~.*/])->to('user#freaks');
291     $user->get('/achievements' => [nickname => qr/~.*/])->to('user#achievements');
292     #$r->get('/:user_name/journal' => [user_name => qr/~.*/])->to('journal#user_journals');
293
294 }
295
296 1;