view Lib/IMPL/Security/AbstractContext.pm @ 359:833e663796c4

TTView: added view variable to pass rendering context between controls TTView: display function renamed to display_for WebResource: resources now marked with roles for searching a desired resource by a role in the resource chain
author sergey
date Mon, 25 Nov 2013 02:19:31 +0400
parents fe725fad2d90
children
line wrap: on
line source

package IMPL::Security::AbstractContext;
use strict;
use warnings;

use IMPL::Const qw(:prop);

use IMPL::require {
    Role => 'IMPL::Security::Role',
    Principal => 'IMPL::Security::Principal',
    Exception => 'IMPL::Exception',
    NotImplementedException => '-IMPL::NotImplementedException'
};

use parent qw(IMPL::Class::Meta);

__PACKAGE__->static_accessor_clone(abstractProps => [
    principal => PROP_RW,
    rolesAssigned => PROP_RW | PROP_LIST,
    auth => PROP_RW,
    authority => PROP_RW
]);

my $current; # current session if any

sub Impersonate {
    my ($this,$code,@args) = @_;
    
    my $old = $current;
    $current = $this;
    my $result;
    my $e;
    
    {
        local $@;
        eval {
            $result = $code->(@args);
        };
        $e = $@;
    }
    $current = $old;
    if($e) {
        die $e;
    } else {
        return $result;
    }
}

sub Apply {
    my ($this) = @_;
    
    $current = $this;
}

sub isTrusted {
    my ($this) = @_;
    
    if (my $auth = $this->auth) {
        return $auth->isTrusted;
    } else {
        return 0;
    }
}

sub isNobody {
    return (shift->principal == Principal->nobody ? 1 : 0);
}

sub Satisfy {
    my ($this,@roles) = @_;
    
    my $roleEffective = Role->new ( _effective => scalar $this->rolesAssigned );
    
    return $roleEffective->Satisfy(@roles);
}

sub current {
    $current;
}

1;

__END__

=pod

=head1 NAME

C<abstract IMPL::Security::Context> - контекст безопасности.

=head1 SINOPSYS

=begin code

package MyApp::Model::Session;
use strict;

use IMPL::delare {
    base => [
        'MyApp::Model::BaseDBO' => '@_',
        'IMPL::Security::AbstractContext' => undef
    ],
    props {
        IMPL::Security::AbstractContext->abstractProps,
        qouta => PROP_GET
    }
}

package main;

$app->model->GetSession('546a54df4')->Impersonate(sub{
    # do something
});

=end code

=head1 DESCRIPTION

Код приложения, которое выполняется 

Являет собой контекст безопасности, описывает пользователя и привелегии, так же
у программы есть текущий контекст безопасности, по умолчанию он C<nobody>.

=head1 MEMBERS

=head2 C<[get] principal>

Идентификатор пользователя, владельца контекста.

=head2 C<[get,set] rolesAssigned>

Явно назначенные роли. Если список пуст, то считается, что используются роли
пользователя по-умолчанию.

=head2 C<[get] auth>

Объект асторизации C<IMPL::Security::Auth>, использованный при создании текущего контекста.

=head2 C<[get] authority>

Модуль безопасности, породивший данный контекст. Модуль безопасности, отвечающий
за создание контекста безопасности должен реализовывать метод
C<CreateContext($user,$auth,$roles)>

=head2 C<[get] isTrusted>

Возвращает значение является ли контекст доверенным, тоесть клиент
аутентифицирован и сессия установлена. Если C<false> значит, что сессия была
начата, однако не установлена до конца.

=head2 C<Impersonate($code)>

Делает контекст текущим и выполняет в нем функцию по ссылке C<$code>. По окончании
выполнения, контекст восстанавливается в предыдущий (не зависимо от того, что
с ним происходило во время выполнения C<$code>).

=head2 C<Apply()>

Заменяет текущий контекст на себя, но до конца действия метода C<Impersonate>, если
таковой был вызван.

=head2 C<Satisfy(@roles)>

Проверяет наличие необходимых ролей у контекста. Данный метод позволяет
абстрагироваться от механизмов связи контекста и ролей. Возвращает истинное
значение если список необходимых ролей у пользователя имеется.

=cut