]>
iEval git - gruntmaster-page.git/blob - lib/Plack/App/Gruntmaster.pm
8c8875db4586d0c6303c2f45bee810aee1897349
1 package Plack
::App
::Gruntmaster
;
6 use parent qw
/Plack::Component/;
7 no if $] >= 5.017011, warnings
=> 'experimental::smartmatch';
8 our $VERSION = '5999.000_001';
10 use Apache2
::Authen
::Passphrase qw
/pwcheck pwset/;
11 use CSS
::Minifier
::XS
;
12 use File
::Slurp qw
/read_file/;
13 use HTTP
::Negotiate qw
/choose/;
14 use JavaScript
::Minifier
::XS
;
16 use Gruntmaster
::Page
::Generic
;
22 my $r = Plack
::Request
->new($env);
23 my @handlers = @
{ $handlers{$r->method} // [] };
24 for my $handler (@handlers) {
25 my ($re, $obj) = @
$handler;
27 next unless @args = $r->path =~ m/^$re$/a;
28 return $obj->($env, map { $_ // '' } @args);
31 if ($r->method eq 'GET' || $r->method eq 'HEAD') {
32 my $article = $r->path eq '/' ?
'/index' : $r->path;
33 $article = substr $article, 1;
35 my @variants = grep { !/\.title$/ } <a
/$article.*>;
37 my $lang = choose
[ map { [$_, 1, 'text/html', undef, undef, $_, undef] } map { /\
.(.+)$/ } @variants ], $r->headers;
38 my $content = read_file
"a/$article.$lang";
39 my $title = read_file
"a/$article.$lang.title";
40 my $html = Gruntmaster
::Page
::Base
::header
($lang, $title) . $content . Gruntmaster
::Page
::Base
::footer
($lang);
41 return [200, ['Content-Type' => 'text/html', 'Content-Language' => $lang, 'Vary' => 'Accept-Language', 'X-Forever' => 1, 'Cache-Control' => 'max-age=300'], [$html] ]
45 [404, ['Content-Type' => 'text/plain'], ['Not found']]
48 sub get
{ push @
{$handlers{GET
}}, [ @_ ] }
49 sub post
{ push @
{$handlers{POST
}}, [ @_ ] }
50 sub db
{ $_[0]->{'gruntmaster.dbic'} }
51 sub reply
{ [200, ['Content-Type' => 'text/plain', 'Cache-Control' => 'no-cache'], [ @_ ] ] }
56 $pkg = "Gruntmaster::Page::$pkg";
57 eval "require $pkg" or die $@
;
59 my ($env, @args) = @_;
60 my $format = choose
$pkg->variants, Plack
::Request
->new($env)->headers;
61 $pkg->generate($format, $env, @args)
65 use constant CONTENT_TYPES
=> +{
67 cpp
=> 'text/x-c++src',
68 cs
=> 'text/x-csharp', # Used by GNOME. Not in mime.types.
69 java
=> 'text/x-java',
70 pas
=> 'text/x-pascal',
72 py
=> 'text/x-python',
74 use constant NOT_FOUND
=> [404, ['Content-Type' => 'text/plain'], ['Not found']];
75 use constant FORBIDDEN
=> [403, ['Content-Type' => 'text/plain'], ['Forbidden']];
78 my $word = qr
,(\w
+),a
;
79 my $number = qr
,(\d
+),a
;
81 get qr
,/css/$word\
.css
, => sub {
82 my ($env, $theme) = @_;
83 return [404, ['Content-Type' => 'text/plain'], [ 'Not found' ]] unless -e
"css/themes/$theme.css";
84 my $css = read_file
"css/themes/$theme.css";
85 $css .= read_file
$_ for <css
/*.css
>;
86 [200, ['Content-Type' => 'text/css', 'Cache-Control' => 'public, max-age=604800', 'X-Forever' => 1], [CSS
::Minifier
::XS
::minify
$css] ]
89 get qr
,/js\
.js
, => sub {
91 $js .= read_file
$_ for <js
/*.js
>;
92 [200, ['Content-Type' => 'application/javascript', 'Cache-Control' => 'public, max-age=604800', 'X-Forever' => 1], [JavaScript
::Minifier
::XS
::minify
$js] ]
95 get qr
,/log/src
/$number\
.$word, => sub {
96 my ($env, $job, $ext) = @_;
97 $job = db
($env)->job($job);
98 return NOT_FOUND
if $job->contest;
99 return FORBIDDEN
if !admin
&& ($job->private || $job->problem->private);
100 [200, ['Content-Type' => CONTENT_TYPES
->{$ext}, 'Cache-Control' => 'max-age=604800', 'X-Forever' => 1], [$job->source] ]
103 get qr
,/ct/$word/log/src
/$number\
.$word, => sub {
104 my ($env, $ct, $job, $ext) = @_;
105 $job = db
($env)->job($job);
106 $ct = db
($env)->contest($ct);
107 return NOT_FOUND
if $job->contest->id ne $ct->id;
108 return FORBIDDEN
if !admin
&& ($job->private || !$ct->is_finished);
109 [200, ['Content-Type' => CONTENT_TYPES
->{$ext}, 'Cache-Control' => 'max-age=604800', 'X-Forever' => 1], [$job->source] ]
112 get qr
,/ct/$word/log/st
, => sub {
114 $env->{'gruntmaster.contest'} = $ct;
115 old_handler
('St')->($env);
118 get qr
,/us/, => old_handler
'Us';
119 get qr
,/us/$word, => old_handler
'Us::Entry';
121 get qr
,/pb/, => old_handler
'Pb';
123 get qr
,/us/$word/pb/, => sub {
125 $env->{'gruntmaster.user'} = $us;
126 old_handler
('Pb')->($env);
129 get qr
,/ct/$word/pb/, => sub {
131 return FORBIDDEN
if !admin
&& db
($env)->contest($ct)->is_pending;
132 $env->{'gruntmaster.contest'} = $ct;
133 old_handler
('Pb')->($env);
136 get qr
,/pb/$word, => sub {
138 return NOT_FOUND
if !db
($env)->problem($pb)->is_in_archive;
139 return FORBIDDEN
if !admin
&& db
($env)->problem($pb)->private;
140 old_handler
('Pb::Entry')->(@_);
143 get qr
,/ct/$word/pb/$word, => sub{
144 my ($env, $ct, $pb) = @_;
145 return NOT_FOUND
if !db
($env)->contest_problems->find($ct, $pb);
146 return FORBIDDEN
if !admin
&& db
($env)->contest($ct)->is_pending;
147 $env->{'gruntmaster.contest'} = $ct;
148 old_handler
('Pb::Entry')->($env, $pb);
151 post qr
,/pb/$word/submit
, => sub {
153 return NOT_FOUND
if !db
($env)->problem($pb)->is_in_archive;
154 old_handler
('Submit')->($env, $pb);
157 post qr
,/ct/$word/pb/$word/submit
, => sub {
158 my ($env, $ct, $pb) = @_;
159 return NOT_FOUND
if !db
($env)->contest_problems->find($ct, $pb);
160 return FORBIDDEN
if !admin
&& db
($env)->contest($ct)->is_pending;
161 $env->{'gruntmaster.contest'} = $ct;
162 old_handler
('Submit')->($env, $pb);
165 get qr
,/log/(?
:page
-$number)?
, => sub {
166 my ($env, $page) = @_;
167 $env->{'gruntmaster.page'} = $page || -1;
168 old_handler
('Log')->($env)
171 get qr
,/ct/$word/log/(?
:page
-$number)?
, => sub {
172 my ($env, $ct, $page) = @_;
173 return FORBIDDEN
if !admin
&& db
($env)->contest($ct)->is_pending;
174 $env->{'gruntmaster.contest'} = $ct;
175 $env->{'gruntmaster.page'} = $page || -1;
176 old_handler
('Log')->($env)
179 get qr
,/pb/$word/log/(?
:page
-$number)?
, => sub {
180 my ($env, $pb, $page) = @_;
181 #return FORBIDDEN if !admin && db($pb)-> TODO
182 $env->{'gruntmaster.problem'} = $pb;
183 $env->{'gruntmaster.page'} = $page || -1;
184 old_handler
('Log')->($env)
187 get qr
,/us/$word/log/(?
:page
-$number)?
, => sub {
188 my ($env, $us, $page) = @_;
189 $env->{'gruntmaster.user'} = $us;
190 $env->{'gruntmaster.page'} = $page || -1;
191 old_handler
('Log')->($env);
194 get qr
,/log/$number, => sub{
195 my ($env, $job) = @_;
196 my $j = db
($env)->job($job);
197 return FORBIDDEN
if !admin
&& ($j->private || $j->problem->private || ($j->contest && !$j->contest->is_finished));
198 old_handler
('Log::Entry')->($env, $job);
201 get qr
,/ct/, => old_handler
'Ct';
203 get qr
,/ct/$word, => sub {
205 return FORBIDDEN
if !admin
&& db
($env)->contest($ct)->is_pending;
206 old_handler
('Ct::Entry')->($env, $ct);
209 post qr
,/action/passwd
, => sub {
211 my $r = Plack
::Request
->new($env);
212 my ($oldpass, $newpass, $confirm) = map {scalar $r->param($_)} 'password', 'new_password', 'confirm_new_password';
214 return reply
'Incorrect password' unless eval { pwcheck
$r->user, $oldpass; 1 };
215 return reply
'The two passwords do not match' unless $newpass eq $confirm;
217 pwset
$r->user, $newpass;
218 reply
'Password changed successfully';
221 post qr
,/action/register
, => old_handler
'Register';
This page took 0.077565 seconds and 4 git commands to generate.