File Coverage

File:lib/OpenAPI/Dispatcher.pm
Coverage:83.6%

linestmtbrancondsubpodtimecode
1package OpenAPI::Dispatcher;
2
3
22
22
22
190
66
177
use strict;
4
22
22
22
241
74
169
use warnings;
5
6#use Smart::Comments;
7
22
22
22
299
88
280
use Data::UUID;
8
22
22
22
324
81
263
use OpenAPI::Limits;
9
22
22
22
306
109
343
use OpenAPI::Cache;
10
22
22
22
345
112
246
use OpenAPI;
11
22
22
22
291
74
299
use OpenAPI::Config;
12
13our $InitFatal;
14
15# XXX Excpetion not caputred...when database 'test' not created.
16my %Dispatcher = (
17    model => [
18        qw< model_list model model_column model_row >
19    ],
20    view => [
21        qw< view_list view view_param view_exec >
22    ],
23    action => [
24        qw< action_list action action_param action_exec >
25    ],
26    admin => [
27        qw< admin admin_op >
28    ],
29    role => [
30        qw< role_list role access_rule_column access_rule >
31    ],
32    login => [
33        qw< login login_user login_user_password >
34    ],
35    captcha => [
36        qw< captcha_list captcha_column captcha_value >
37    ],
38    version => [ qw< version > ],
39);
40
41my $url_prefix = $ENV{OPENAPI_URL_PREFIX};
42if ($url_prefix) {
43    $url_prefix =~ s{^/+|/+$}{}g;
44}
45
46sub init {
47
22
0
133
    $CGI::POST_MAX = $POST_LEN_LIMIT; # max 100 K posts
48
22
96
    $CGI::DISABLE_UPLOADS = 1; # no uploads
49
22
206
    OpenAPI::Config->init;
50
22
406
    my $backend = $OpenAPI::Config{'backend.type'};
51
22
95
    eval {
52
22
316
        $OpenAPI::Cache = OpenAPI::Cache->new;
53
22
227
        OpenAPI->connect($backend);
54    };
55
22
247
    if ($@) {
56
0
0
        $InitFatal = $@;
57    }
58}
59
60sub process_request {
61
602
0
4114
    my ($class, $cgi) = @_;
62
602
4459
    my $url = $ENV{REQUEST_URI};
63    ### $url
64
602
3752
    $url =~ s/\?.*//g;
65    #my $url = $cgi->url(-absolute=>1,-path_info=>1);
66
602
5389
    $url =~ s{^/+}{}g;
67    ### Old URL: $url
68    ### URL Prefox: $url_prefix
69
70
602
3538
    $url =~ s{^\Q$url_prefix\E/+}{}g if $url_prefix; ### New URL: $url
71
72
602
5644
    my $openapi = OpenAPI->new($cgi);
73
602
3795
    if ($InitFatal) {
74
0
0
        $openapi->fatal($InitFatal);
75
0
0
        return;
76    }
77
78
602
2431
    eval {
79
602
4720
        $openapi->init(\$url);
80    };
81
602
3708
    if ($@) {
82        ### Exception in new: $@
83
5
40
        $openapi->fatal($@);
84
5
236
        return;
85    }
86
87    #$url =~ s/\/+$//g;
88    #print "page: ", url_param("page"), "\n";
89    #warn "Hello!";
90    #print "charset: ", url_param("charset"), "\n";
91
92
597
7143
    my @bits = split /\//, $url, 5;
93
94
597
3947
    if (!@bits) {
95        ### Unknown URL: $url
96
0
0
        $openapi->fatal("Unknown URL: $url");
97
0
0
        return;
98    }
99
100
597
2234
6
2941
10022
52
    map { s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; } @bits;
101    ## @bits
102
103
597
3897
    my $fst = shift @bits;
104
597
4054
    if ($fst ne '=') {
105
0
0
        $openapi->fatal("URLs must be led by '=': $url");
106
0
0
        return;
107    }
108
109
597
3755
    my $http_meth = $openapi->{'_http_method'};
110
597
3024
    if (!$http_meth) {
111
0
0
        $openapi->fatal("HTTP method not detected.");
112
0
0
        return;
113    }
114    ### $http_meth
115
116    # XXX hacks...
117
597
5679
    my $cookies = CGI::Cookie->fetch;
118
597
5548
    my ($session_from_cookie, $captcha_from_cookie, $response_from_cookie);
119
597
1764
    my $session;
120
597
3489
    if ($cookies) {
121
558
3125
        my $cookie = $cookies->{session};
122
558
1419
        if ($cookie) {
123
548
11059
            $openapi->{_session_from_cookie} =
124                $session_from_cookie = $cookie->value;
125        }
126
558
23014
        $cookie = $cookies->{captcha};
127
558
2875
        if ($cookie) {
128
41
860
            $openapi->{_captcha_from_cookie} =
129                $captcha_from_cookie = $cookie->value;
130            #$OpenAPI::Cache->remove($captcha_from_cookie);
131        }
132
558
2132
        if ($cookie = $cookies->{last_response}) {
133
503
10847
            $response_from_cookie = $cookie->value;
134        }
135    }
136
137
597
28254
    if ($http_meth eq 'GET' and @bits >= 2 and $bits[0] eq 'last' and $bits[1] eq 'response') {
138
5
42
        $openapi->{_bin_data} = $response_from_cookie . "\n";
139
5
37
        $openapi->response;
140
5
76
        return;
141    }
142
143
592
2930
    my ($account, $role);
144
592
10256
    if ($bits[0] and $bits[0] !~ /^(?:login|captcha|version)$/) {
145
539
2636
        eval {
146            # XXX this part is lame...
147
539
4166
            my $user = $cgi->url_param('user');
148
539
3191
            if (defined $user) {
149                #$OpenAPI::Cache->remove($uuid);
150
43
309
                my $captcha = $cgi->url_param('captcha');
151                ### URL param capture: $captcha
152
43
384
                my $res = $openapi->login($user, {
153                    password => scalar($cgi->url_param('password')),
154                    captcha => $captcha,
155                });
156
30
280
                $account = $res->{account};
157
30
243
                $role = $res->{role};
158                # XXX login as $account.$role...
159                # XXX if account is anonymous, then create a session
160                # XXX else check password, if correct, create a session
161            } else {
162
496
6998
                my $session = $openapi->{_session} || $session_from_cookie;
163
496
2618
                if ($session) {
164
490
4533
                    my $user = $OpenAPI::Cache->get($session);
165                    ### User from cookie: $user
166
490
7892
                    if ($user) {
167
490
4901
                        ($account, $role) = split /\./, $user, 2;
168                    }
169                    ### $account
170                    ### $role
171                }
172            }
173
174            # this part is lame?
175
526
3386
            if (!$account) {
176
6
22
                die "Login required.\n";
177            }
178
520
4280
            if (!$openapi->has_user($account)) {
179                ### Found user: $user
180
0
0
                die "Account \"$account\" does not exist.\n";
181            }
182
520
14018
            $openapi->set_user($account);
183
184
520
3362
            $role ||= 'Admin';
185
520
5093
            if (!$openapi->has_role($role)) {
186                ### Found user: $user
187
0
0
                die "Role \"$role\" does not exist.\n";
188            }
189
520
27620
            $openapi->set_role($role);
190        };
191
539
3918
        if ($@) {
192
19
170
            $openapi->fatal($@);
193
19
1229
            return;
194        }
195    }
196
197    # XXX check ACL rules...
198
573
11804
    if ($bits[0] and $bits[0] !~ /^(?:login|captcha|version)$/) {
199
520
5792
        my $res = $openapi->current_user_can($http_meth => \@bits);
200
520
4546
        if (!$res) {
201
22
291
            $openapi->fatal("Permission denied for the \"$role\" role.");
202
22
1298
            return;
203        }
204    } else {
205    }
206
207
551
5514
    my $category = $Dispatcher{$bits[0]};
208
551
3082
    if ($category) {
209
551
4801
        my $object = $category->[$#bits];
210        ### $object
211
551
3532
        if (!defined $object) {
212
0
0
            $openapi->fatal("Unknown URL level: $url");
213
0
0
            return;
214        }
215
551
3894
        my $meth = $http_meth . '_' . $object;
216
551
2998
        $meth =~ s/\./_/g;
217
551
8795
        if (!$openapi->can($meth)) {
218
0
0
            $object =~ s/_/ /g;
219
0
0
            $openapi->fatal("HTTP $http_meth method not supported for $object.");
220
0
0
            return;
221        }
222
551
2108
        my $data;
223
551
2138
        eval {
224
551
3778
            if ($bits[0] eq 'model') {
225
311
3451
                $openapi->global_model_check(\@bits, $http_meth);
226            }
227
228
529
7395
            $data = $openapi->$meth(\@bits);
229        };
230
551
9545
        if ($@) {
231
113
1075
            $openapi->fatal($@);
232
113
7245
            return;
233        }
234
438
4434
        $openapi->data($data);
235
438
3370
        $openapi->response();
236    } else {
237
0
        $openapi->fatal("Unknown URL catagory: $bits[0]");
238    }
239}
240
2411;