|
Lines 33-42
my $schema = Koha::Database->new->schema;
Link Here
|
| 33 |
my $t = Test::Mojo->new('Koha::REST::V1'); |
33 |
my $t = Test::Mojo->new('Koha::REST::V1'); |
| 34 |
|
34 |
|
| 35 |
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); |
35 |
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); |
|
|
36 |
t::lib::Mocks::mock_config( 'api_secret_passphrase', 'test' ); |
| 36 |
|
37 |
|
| 37 |
subtest 'add() tests' => sub { |
38 |
subtest 'add() tests' => sub { |
| 38 |
|
39 |
|
| 39 |
plan tests => 7; |
40 |
plan tests => 13; |
| 40 |
|
41 |
|
| 41 |
$schema->storage->txn_begin; |
42 |
$schema->storage->txn_begin; |
| 42 |
|
43 |
|
|
Lines 57-68
subtest 'add() tests' => sub {
Link Here
|
| 57 |
} |
58 |
} |
| 58 |
}; |
59 |
}; |
| 59 |
|
60 |
|
| 60 |
# Anonymous request should work (browsers send these without auth) |
61 |
# Anonymous request requires token |
| 61 |
$t->post_ok( '/api/v1/public/csp-reports' => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
62 |
$t->post_ok( '/api/v1/public/csp-reports' => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
|
|
63 |
->status_is( 400, 'CSP report denied (400)' ) |
| 64 |
->content_like( qr/Missing property.*\/token"/, '...because of a missing token' ); |
| 65 |
|
| 66 |
# Anonymous request requires valid token |
| 67 |
$t->post_ok( '/api/v1/public/csp-reports?token=invalid' => { 'Content-Type' => 'application/csp-report' } => json => |
| 68 |
$csp_report )->status_is( 401, 'CSP report denied (401)' ) |
| 69 |
->json_is( '/error', 'Invalid token.', '...because of an invalid token' ); |
| 70 |
|
| 71 |
# Anonymous request should work (browsers send these without auth) |
| 72 |
$t->post_ok( '/api/v1/public/csp-reports?token=' |
| 73 |
. csp_token() => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
| 62 |
->status_is( 204, 'CSP report accepted' ); |
74 |
->status_is( 204, 'CSP report accepted' ); |
| 63 |
|
75 |
|
| 64 |
# Test with application/json content type (also valid) |
76 |
# Test with application/json content type (also valid) |
| 65 |
$t->post_ok( '/api/v1/public/csp-reports' => { 'Content-Type' => 'application/json' } => json => $csp_report ) |
77 |
$t->post_ok( '/api/v1/public/csp-reports?token=' |
|
|
78 |
. csp_token() => { 'Content-Type' => 'application/json' } => json => $csp_report ) |
| 66 |
->status_is( 204, 'CSP report accepted with application/json content type' ); |
79 |
->status_is( 204, 'CSP report accepted with application/json content type' ); |
| 67 |
|
80 |
|
| 68 |
# Test with minimal report |
81 |
# Test with minimal report |
|
Lines 74-80
subtest 'add() tests' => sub {
Link Here
|
| 74 |
} |
87 |
} |
| 75 |
}; |
88 |
}; |
| 76 |
|
89 |
|
| 77 |
$t->post_ok( '/api/v1/public/csp-reports' => json => $minimal_report ) |
90 |
$t->post_ok( '/api/v1/public/csp-reports?token=' . csp_token() => json => $minimal_report ) |
| 78 |
->status_is( 204, 'Minimal CSP report accepted' ); |
91 |
->status_is( 204, 'Minimal CSP report accepted' ); |
| 79 |
|
92 |
|
| 80 |
subtest 'make sure log entries are being written' => sub { |
93 |
subtest 'make sure log entries are being written' => sub { |
|
Lines 114-121
subtest 'add() tests' => sub {
Link Here
|
| 114 |
is( $appender->buffer, '', 'Nothing in log buffer yet' ); |
127 |
is( $appender->buffer, '', 'Nothing in log buffer yet' ); |
| 115 |
is( $appenderplack->buffer, '', 'Nothing in plack log buffer yet' ); |
128 |
is( $appenderplack->buffer, '', 'Nothing in plack log buffer yet' ); |
| 116 |
|
129 |
|
| 117 |
$t->post_ok( |
130 |
$t->post_ok( '/api/v1/public/csp-reports?token=' |
| 118 |
'/api/v1/public/csp-reports' => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
131 |
. csp_token() => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
| 119 |
->status_is( 204, 'CSP report accepted' ); |
132 |
->status_is( 204, 'CSP report accepted' ); |
| 120 |
|
133 |
|
| 121 |
my $expected_log_entry = sprintf( |
134 |
my $expected_log_entry = sprintf( |
|
Lines 137-144
subtest 'add() tests' => sub {
Link Here
|
| 137 |
$appender->clear(); |
150 |
$appender->clear(); |
| 138 |
|
151 |
|
| 139 |
$ENV{'plack.is.enabled.for.this.test'} = 1; # tricking C4::Context->psgi_env |
152 |
$ENV{'plack.is.enabled.for.this.test'} = 1; # tricking C4::Context->psgi_env |
| 140 |
$t->post_ok( |
153 |
$t->post_ok( '/api/v1/public/csp-reports?token=' |
| 141 |
'/api/v1/public/csp-reports' => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
154 |
. csp_token() => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
| 142 |
->status_is( 204, 'CSP report accepted' ); |
155 |
->status_is( 204, 'CSP report accepted' ); |
| 143 |
like( |
156 |
like( |
| 144 |
$appenderplack->buffer, qr/$expected_log_entry/ |
157 |
$appenderplack->buffer, qr/$expected_log_entry/ |
|
Lines 157-164
log4perl.appender.API.utf8=1
Link Here
|
| 157 |
HERE |
170 |
HERE |
| 158 |
); |
171 |
); |
| 159 |
$appender = Log::Log4perl->appenders()->{API}; |
172 |
$appender = Log::Log4perl->appenders()->{API}; |
| 160 |
$t->post_ok( |
173 |
$t->post_ok( '/api/v1/public/csp-reports?token=' |
| 161 |
'/api/v1/public/csp-reports' => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
174 |
. csp_token() => { 'Content-Type' => 'application/csp-report' } => json => $csp_report ) |
| 162 |
->status_is( 204, 'CSP report returns 204 even when no CSP loggers are defined' ); |
175 |
->status_is( 204, 'CSP report returns 204 even when no CSP loggers are defined' ); |
| 163 |
is( $appender->buffer, '', 'Nothing in the only defined log buffer, because it is unrelated to CSP' ); |
176 |
is( $appender->buffer, '', 'Nothing in the only defined log buffer, because it is unrelated to CSP' ); |
| 164 |
|
177 |
|
|
Lines 167-170
HERE
Link Here
|
| 167 |
$schema->storage->txn_rollback; |
180 |
$schema->storage->txn_rollback; |
| 168 |
}; |
181 |
}; |
| 169 |
|
182 |
|
|
|
183 |
sub csp_token { |
| 184 |
my $time = time(); |
| 185 |
return Mojo::JWT->new( |
| 186 |
claims => { |
| 187 |
type => 'csp-violation', |
| 188 |
timestamp => $time, |
| 189 |
}, |
| 190 |
expires => $time + 15, # the endpoint is valid for 15 seconds |
| 191 |
secret => Digest::MD5::md5_base64( |
| 192 |
Encode::encode( 'UTF-8', C4::Context->config('api_secret_passphrase') || 'unsafe' ) |
| 193 |
) |
| 194 |
)->encode; |
| 195 |
} |
| 196 |
|
| 170 |
1; |
197 |
1; |
| 171 |
- |
|
|