File Coverage: lib/Yukki/Web/Router/Route/Match.pm

# File Coverage

File: | lib/Yukki/Web/Router/Route/Match.pm
Coverage: | 90.6%

line | stmt | bran | cond | sub | pod | time | code
--- | --- | --- | --- | --- | --- | --- | ---
1 |  |  |  |  |  |  | package Yukki::Web::Router::Route::Match;
2 |
3 | 1 1 |  |  | 1 |  | 5 2 | use v5.24;
4 | 1 1 1 |  |  | 1 |  | 3 2 2 | use utf8;
5 | 1 1 1 |  |  | 1 |  | 11 1 2 | use Moo;
6 |
7 |  |  |  |  |  |  | extends 'Path::Router::Route::Match';
8 |
9 | 1 1 1 |  |  | 1 |  | 175 1 40 | use List::Util qw( all any );
10 | 1 1 1 |  |  | 1 |  | 2 1 5 | use Yukki::Error qw( http_throw );
11 |
12 | 1 1 1 |  |  | 1 |  | 187 2 3 | use namespace::clean;
13 |
14 |  |  |  |  |  |  | # ABSTRACT: Matching with access controls
15 |
16 - 30 |  |
    =head1 DESCRIPTION

    This is a helper that include access control level checking.

    =head1 EXTENDS

    L<Path::Router::Route::Match>

    =head1 METHODS

    =head2 access_level

    Evaluates the access control list against a particular path.

    =cut
31 |
32 |  |  |  |  |  |  | sub access_level {
33 | 18 |  |  | 18 | 1 | 21 | my $self = shift;
34 |
35 | 18 |  |  |  |  | 36 | my $mapping = $self->mapping;
36 | 18 |  |  |  |  | 35 | my $acl = $self->route->acl;
37 |
38 | 18 |  |  |  |  | 29 | for my $rule (@$acl) {
39 | 24 |  |  |  |  | 36 | my ($access_level, $match) = @$rule;
40 |
41 |  |  |  |  |  |  | my $accepts = sub {
42 | 24 |  |  | 24 |  | 26 | my $key = shift;
43 |
44 | 24 | 50 100 50 |  |  |  | 62 | if (!ref $match->{$key}) {
45 | 0 |  |  |  |  | 0 | return $mapping->{$key} eq $match->{$key};
46 |  |  |  |  |  |  | }
47 |  |  |  |  |  |  | elsif (ref $match->{$key} eq 'CODE') {
48 | 3 |  |  |  |  | 5 | local $_ = $mapping->{$key};
49 | 3 |  |  |  |  | 14 | return $match->{$key}->($mapping->{$key});
50 |  |  |  |  |  |  | }
51 |  |  |  |  |  |  | elsif (ref $match->{$key} eq 'ARRAY') {
52 | 21 53 |  |  |  |  | 59 111 | return any { $mapping->{$key} eq $_ } $match->{$key}->@*;
53 |  |  |  |  |  |  | }
54 |  |  |  |  |  |  | else {
55 | 0 |  |  |  |  | 0 | die "unknown ACL authorization check type";
56 |  |  |  |  |  |  | }
57 | 24 |  |  |  |  | 56 | };
58 |
59 | 24 24 | 100 |  | 24 |  | 59 37 | if (all { $accepts->($_) } keys %$match) {
60 | 18 |  |  |  |  | 39 | return $access_level;
61 |  |  |  |  |  |  | }
62 |  |  |  |  |  |  | }
63 |
64 | 0 |  |  |  |  |  | http_throw("no ACL found to match " . $self->path);
65 |  |  |  |  |  |  | }
66 |
67 |  |  |  |  |  |  | 1;