CallBackery

 view release on metacpan or  search on metacpan

lib/CallBackery/Controller/RpcService.pm  view on Meta::CPAN

target plugin opts into anonymous access (C<mayAnonymous>). The plugin
instantiation is wrapped in C<eval>, because instantiating a plugin as an
unauthenticated user commonly dies (plugins read user rights/config); such a
death resolves to "not anonymous" here and must never escape as a generic
code 9999 error.

=item *

Otherwise the method requires authentication the user does not have: if the
user's session has merely expired, C<die> a C<RPC_SESSION_EXPIRED> (code 7)
exception; otherwise C<return 0> for the ordinary login-required path.

=back

=cut

my %allow = (
    getBaseConfig => 1,
    login => 1,
    logout => 1,
    ping => 1,
    getUserConfig => 2,
    getPluginConfig => 3,
    validatePluginData => 3,
    processPluginData => 3,
    getPluginData => 3,
    getSessionCookie => 2
);

has config => sub ($self) {
    $self->app->config;
}, weak => 1;

has user => sub ($self) {
    my $obj = $self->app->userObject->new(app=>$self->app,controller=>$self,log=>$self->log);
    return $obj;
};

has pluginMap => sub ($self) {
    my $map = $self->config->cfgHash->{PLUGIN};
    return $map;
}, weak => 1;


sub allow_rpc_access ($self,$method) {
    if (not $self->req->method eq 'POST') {
        # sorry we do not allow GET requests
        $self->log->error("refused ".$self->req->method." request");
        return 0;
    }
    if (not exists $allow{$method}){
        return 0;
    }
    for ($allow{$method}){
        /1/ && return 1;                                 # public method
        return 1 if ($self->user->isUserAuthenticated); # forces cookieConf (sets sessionExpired)
        /3/ && do {
            # Level-3: allowed only for plugins that opt into anonymous access.
            # Guard the instantiation: for an unauthenticated user it commonly
            # dies (plugins read user rights/config); that death must resolve to
            # "not anonymous" here, never escape as a generic code-9999 popup.
            my $plugin = $self->rpcParams->[0];
            my $anon = eval {
                $self->config->instantiatePlugin($plugin,$self->user)->mayAnonymous
            };
            return 1 if $anon;
        };
        # Method needs auth and the user is not authenticated. If a session was
        # present and merely expired, signal that distinctly (code 7 -> reload);
        # otherwise fall through to code 6 (login dialog).
        die mkerror(RPC_SESSION_EXPIRED,
            trm('Your session has expired. Please reload to log in.'))
            if $self->user->sessionExpired;
        last;
    }
    return 0;
};

has passMatch => sub ($self) {
    qr{(?i)(?:password|_pass)};
};

sub perMethodCleaner ($self,$method=undef) {
    $method or return;
    return {
        login => sub {
            my $data = shift;
            if (ref $data eq 'ARRAY'){
               $data->[1] = 'xxx';
            }
            return;
        }
    }->{$method};
};

sub dataCleaner ($self,$data,$method=undef) {
    if (my $perMethodCleaner = $self->perMethodCleaner($method)){
        return $perMethodCleaner->($data);
    }

    my $match = $self->passMatch;
    my $type = ref $data;
    for ($type) {
        /ARRAY/ && do {
            $self->dataCleaner($_) for @$data;
        };
        /HASH/ && do {
            for my $key (keys %$data) {
                my $value = $data->{$key};
                if ($key =~ /$match/){
                    $data->{$key} = 'xxx';
                }
                elsif (ref $value){
                    $self->dataCleaner($value);
                }
            }
        }
    }
}

=head2 logRpcCall



( run in 1.520 second using v1.01-cache-2.11-cpan-364913b4093 )