blob: 73b4561daad8c9ec645a8bf1ccdfb86660962ef4 [file] [log] [blame]
Akron0e1ed242018-10-11 13:22:00 +02001#!/usr/bin/env perl
2use Mojolicious::Lite;
3use Mojo::ByteStream 'b';
4use Mojo::Date;
5use Mojo::JSON qw/true false encode_json decode_json/;
6use strict;
7use warnings;
8use Mojo::JWT;
Akron6d49c1f2018-10-11 14:22:21 +02009use Mojo::File qw/path/;
10use Mojo::Util qw/slugify/;
Akron0e1ed242018-10-11 13:22:00 +020011
12# This is an API fake server with fixtures
13
14my $secret = 's3cr3t';
Akron6d49c1f2018-10-11 14:22:21 +020015my $fixture_path = path(Mojo::File->new(__FILE__)->dirname);
Akron0e1ed242018-10-11 13:22:00 +020016
17helper jwt_encode => sub {
18 shift;
19 return Mojo::JWT->new(
20 secret => $secret,
21 token_type => 'api_token',
22 expires => time + (3 * 34 * 60 * 60),
23 claims => { @_ }
24 );
25};
26
27helper jwt_decode => sub {
28 my ($c, $auth) = @_;
29 $auth =~ s/\s*api_token\s+//;
30 return Mojo::JWT->new(secret => $secret)->decode($auth);
31};
32
33
Akron6d49c1f2018-10-11 14:22:21 +020034# Load fixture responses
35helper 'load_response' => sub {
36 my $c = shift;
37 my $q_name = shift;
38 my $file = $fixture_path->child("response_$q_name.json");
39 unless (-f $file) {
40 return {
41 status => 500,
42 json => {
43 errors => [[0, 'Unable to load query response from ' . $file]]
44 }
45 }
46 };
47 my $response = $file->slurp;
48 return decode_json($response);
49};
50
51
Akron0e1ed242018-10-11 13:22:00 +020052# Base page
53get '/' => sub {
Akron6d49c1f2018-10-11 14:22:21 +020054 shift->render(text => 'Fake server available');
Akron0e1ed242018-10-11 13:22:00 +020055};
56
57# Search fixtures
58get '/search' => sub {
59 my $c = shift;
60 my $v = $c->validation;
61 $v->optional('q');
62 $v->optional('page');
63 $v->optional('ql');
64 $v->optional('count');
65 $v->optional('context');
66
67 # Response q=x&ql=cosmas3
68 if ($v->param('ql') && $v->param('ql') eq 'cosmas3') {
69 return $c->render(
70 status => 400,
71 json => {
72 "\@context" => "http://korap.ids-mannheim.de/ns/koral/0.3/context.jsonld",
73 "errors" => [[307,"cosmas3 is not a supported query language!"]]
74 });
75 };
76
Akron6d49c1f2018-10-11 14:22:21 +020077 if (!$v->param('q')) {
78 return $c->render(%{$c->load_response('no_query')});
Akron0e1ed242018-10-11 13:22:00 +020079 };
80
Akron6d49c1f2018-10-11 14:22:21 +020081 # Get response based on query parameter
82 my $response = $c->load_response(slugify($v->param('q')));
Akron0e1ed242018-10-11 13:22:00 +020083
84 # Check authentification
85 if (my $auth = $c->req->headers->header('Authorization')) {
86 if (my $jwt = $c->jwt_decode($auth)) {
Akron6d49c1f2018-10-11 14:22:21 +020087 $response->{json}->{meta}->{authorized} = $jwt->{username} if $jwt->{username};
Akron0e1ed242018-10-11 13:22:00 +020088 };
89 };
90
Akron6d49c1f2018-10-11 14:22:21 +020091 # Set page parameter
Akron0e1ed242018-10-11 13:22:00 +020092 if ($v->param('page')) {
Akron6d49c1f2018-10-11 14:22:21 +020093 $response->{json}->{meta}->{startIndex} = $v->param("startIndex");
Akron0e1ed242018-10-11 13:22:00 +020094 };
95
96
97 # Simple search fixture
Akron6d49c1f2018-10-11 14:22:21 +020098 return $c->render(%$response);
Akron0e1ed242018-10-11 13:22:00 +020099};
100
101
102
103############
104# Auth API #
105############
106
107# Request API token
108get '/auth/logout' => sub {
109 my $c = shift;
110
111 if (my $auth = $c->req->headers->header('Authorization')) {
112 if (my $jwt = $c->jwt_decode($auth)) {
113 my $user = $jwt->{username} if $jwt->{username};
114
115 $c->app->log->debug('Server-Logout: ' . $user);
116 return $c->render(json => { msg => [[0, 'Fine!']]});
117 };
118 };
119
120 return $c->render(status => 400, json => { error => [[0, 'No!']]});
121};
122
123
124# Request API token
125get '/auth/apiToken' => sub {
126 my $c = shift;
127
128 # Get auth header
129 my $auth = $c->req->headers->authorization;
130
131 # Authorization missing or not basic
132 if (!$auth || $auth !~ s/\s*Basic\s+//gi) {
133 return $c->render(
134 json => {
135 error => [[2, 'x']]
136 }
137 );
138 };
139
140 # Decode header
141 my ($username, $pwd) = @{b($auth)->b64_decode->split(':')->to_array};
142
143 # the password is 'pass'
144 if ($pwd) {
145
146 # the password is 'pass'
147 if ($pwd eq 'pass') {
148
149 # Render info with token
150 my $jwt = $c->jwt_encode(username => $username);
151
152 # Render in the Kustvakt fashion:
153 return $c->render(
154 format => 'html',
155 text => encode_json({
156 %{$jwt->claims},
157 expires => $jwt->expires,
158 token => $jwt->encode,
159 token_type => 'api_token'
160 })
161 );
162 };
163
164 return $c->render(
165 json => {
166 error => [[2004, undef]]
167 }
168 );
169 };
170
171 return $c->render(
172 json => {
173 error => [[2004, undef]]
174 }
175 );
176};
177
178app->start;
179
180
181__END__
182
183
184 # Temporary:
185 my $collection_query = {
186 '@type' => "koral:docGroup",
187 "operation" => "operation:or",
188 "operands" => [
189 {
190 '@type' => "koral:docGroup",
191 "operation" => "operation:and",
192 "operands" => [
193 {
194 '@type' => "koral:doc",
195 "key" => "title",
196 "match" => "match:eq",
197 "value" => "Der Birnbaum",
198 "type" => "type:string"
199 },
200 {
201 '@type' => "koral:doc",
202 "key" => "pubPlace",
203 "match" => "match:eq",
204 "value" => "Mannheim",
205 "type" => "type:string"
206 },
207 {
208 '@type' => "koral:docGroup",
209 "operation" => "operation:or",
210 "operands" => [
211 {
212 '@type' => "koral:doc",
213 "key" => "subTitle",
214 "match" => "match:eq",
215 "value" => "Aufzucht oder Pflege",
216 "type" => "type:string"
217 },
218 {
219 '@type' => "koral:doc",
220 "key" => "subTitle",
221 "match" => "match:eq",
222 "value" => "Gedichte",
223 "type" => "type:string"
224 }
225 ]
226 }
227 ]
228 },
229 {
230 '@type' => "koral:doc",
231 "key" => "pubDate",
232 "match" => "match:geq",
233 "value" => "2015-03-05",
234 "type" => "type:date"
235 }
236 ]
237 };