Browse Source

Merge branch 'master' into ru_translation_password

tags/2.0.6
miramir 10 years ago
parent
commit
03953e863f
  1. 1
      build/controllers/DevController.php
  2. 1
      build/controllers/ReleaseController.php
  3. 94
      docs/guide-pt-BR/concept-components.md
  4. 752
      docs/guide-pt-BR/runtime-routing.md
  5. 4
      docs/guide-ru/README.md
  6. 368
      docs/guide-ru/images/rbac-access-check-1.graphml
  7. BIN
      docs/guide-ru/images/rbac-access-check-1.png
  8. 368
      docs/guide-ru/images/rbac-access-check-2.graphml
  9. BIN
      docs/guide-ru/images/rbac-access-check-2.png
  10. 368
      docs/guide-ru/images/rbac-access-check-3.graphml
  11. BIN
      docs/guide-ru/images/rbac-access-check-3.png
  12. 312
      docs/guide-ru/images/rbac-hierarchy-1.graphml
  13. BIN
      docs/guide-ru/images/rbac-hierarchy-1.png
  14. 368
      docs/guide-ru/images/rbac-hierarchy-2.graphml
  15. BIN
      docs/guide-ru/images/rbac-hierarchy-2.png
  16. 518
      docs/guide-ru/security-authorization.md
  17. 179
      docs/guide-ru/security-best-practices.md
  18. 2
      docs/guide/db-active-record.md
  19. 92
      docs/guide/security-authorization.md
  20. 5
      docs/guide/security-best-practices.md
  21. 2
      docs/guide/structure-entry-scripts.md
  22. 11
      docs/guide/tutorial-core-validators.md
  23. 5
      docs/internals-pt-BR/translation-workflow.md
  24. 2
      docs/internals/translation-status.md
  25. 2
      framework/BaseYii.php
  26. 8
      framework/CHANGELOG.md
  27. 1
      framework/classes.php
  28. 2
      framework/db/BaseActiveRecord.php
  29. 2
      framework/db/Schema.php
  30. 17
      framework/messages/uk/yii.php
  31. 18
      framework/validators/DateValidator.php

1
build/controllers/DevController.php

@ -29,6 +29,7 @@ class DevController extends Controller
public $apps = [
'basic' => 'git@github.com:yiisoft/yii2-app-basic.git',
'advanced' => 'git@github.com:yiisoft/yii2-app-advanced.git',
'benchmark' => 'git@github.com:yiisoft/yii2-app-benchmark.git',
];
public $extensions = [

1
build/controllers/ReleaseController.php

@ -67,7 +67,6 @@ class ReleaseController extends Controller
{
$headline = "\n$version under development\n";
$headline .= str_repeat('-', strlen($headline) - 2) . "\n\n";
$headline .= "- no changes in this release.\n";
foreach($this->getChangelogs() as $file) {
$lines = explode("\n", file_get_contents($file));
$hl = [

94
docs/guide-pt-BR/concept-components.md

@ -0,0 +1,94 @@
Componentes
===========
Componente é a parte principal na construção de aplicações Yii. Componentes são instâncias de [[yii\base\Component]],
Ou uma classe extendida. As três características principais que os Componentes fornecem a outras classes são:
* [Propriedades](concept-properties.md)
* [Eventos](concept-events.md)
* [Behaviors (Comportamentos)](concept-behaviors.md)
Separadamente e combinadas, essas características fazem com que as classes no Yii sejam muito mais customizáveis e fáceis de usar. Por Exemplo,
O include [[yii\jui\DatePicker|date picker widget]], um componete de interface do usuário, pode ser usado na [view (visão)](structure-view.md)
Para gerar um `date picker` interativo:
```php
use yii\jui\DatePicker;
echo DatePicker::widget([
'language' => 'ru',
'name' => 'country',
'clientOptions' => [
'dateFormat' => 'yy-mm-dd',
],
]);
```
Os widgets são facilmente escritos porque a classe estende de [[yii\base\Component]].
Enquanto componenetese são muito poderosos, eles são um pouco mais pesados do que um objeto normal, devido ao fato de que é preciso
Memória e CPU extra para dar suporte a [evento](concept-events.md) e [comportamento](concept-behaviors.md) funcionalidade em particular.
Se o seu componente não precisa dessas duas características, você pode considerar extender a sua classe de componente de [[yii\base\Object]] em vez de [[yii\base\Component]]. Se o fizer, fará com que seus componentes sejam tão eficientes como objetos normais do PHP,
Mas com um suporte adcional para [propriedades](concept-properties.md).
Ao extender sua classe de [[yii\base\Component]] ou [[yii\base\Object]], é recomendado que você siga estas convenções:
- Se você sobrescrever o construtor, declare um parâmetro `$config` como último parâmetro do construtor, e em seguida passe este parâmetro para o construtor pai.
- Sempre chame o construtor pai *no final* do seu construtor reescrito.
- Se você sobrescrever o método [[yii\base\Object::init()]],certifique-se de chamar a implementação pai do `init` *no início* do seu método `init`.
Por Exemplo:
```php
<?php
namespace yii\components\MyClass;
use yii\base\Object;
class MyClass extends Object
{
public $prop1;
public $prop2;
public function __construct($param1, $param2, $config = [])
{
// ... initialization before configuration is applied
parent::__construct($config);
}
public function init()
{
parent::init();
// ... initialization after configuration is applied
}
}
```
Seguindo essas orientações fará com que seus componentes sejam [configuraveis](concept-configurations.md) quando forem criados. Por Exemplo:
```php
$component = new MyClass(1, 2, ['prop1' => 3, 'prop2' => 4]);
// alternatively
$component = \Yii::createObject([
'class' => MyClass::className(),
'prop1' => 3,
'prop2' => 4,
], [1, 2]);
```
> informação: Embora a forma de chamar [[Yii::createObject()]] pareça ser mais complicada, ela é mais poderosa porque ela é
> aplicada no topo de um [recipiente
de injeção de dependência](concept-di-container.md).
A Classe [[yii\base\Object]] inpõe o seguinte cilo de vida do objeto:
1. Pré-inicialização dentro do construtor. Você pode definir valores de propriedade padrão aqui.
2. Configuração de objeto via `$config`. A configuração pode sobrescrever o valor padrão configurado dentro do construtor.
3. Pós-inicialização dentro do [[yii\base\Object::init()|init()]]. Você pode sobrescrever este método para executar checagens e normalização das propriedades.
4. Chamadas de método de objeto.
Os três primeiros passos acontecem dentro do construtor do objeto. Isto significa que uma vez que você instancia a classe (Isto é, um objeto), esse objeto foi inicializado adequadamente.

752
docs/guide-pt-BR/runtime-routing.md

@ -0,0 +1,752 @@
Roteamento e Criação de URL
===========================
Quando uma aplicação Yii começa a processar uma URL requerida, o primeiro passo
necessário é obter a rota pela análise da URL. A rota é usada para instanciar o
[controlador (controller) da ação](structure-controllers.md) correspondente para
manipular a requisição. Todo este processo é chamado de *roteamento*.
O processo inverso do roteamento é chamada de *criação de URL*, onde é criado uma
URL a partir de uma determinada rota e seus parâmetros. Quando a URL criada for
exigida em outro momento, o processo de roteamento pode resolve-la de volta para
a rota original e seus parâmetros.
O ponto central responsável pelo roteamento e pela criação de URL é o
[[yii\web\UrlManager|gerenciador de URL]], na qual é registrado como o
[componente da aplicação](structure-application-components.md) `urlManager`. O
[[yii\web\UrlManager|gerenciador de URL]] fornece o método
[[yii\web\UrlManager::parseRequest()|parseRequest()]] para analisar um requisição
de entrada a fim de obter uma rota e seus parâmetros associados; e o método
[[yii\web\UrlManager::createUrl()|createUrl()]] para criar uma URL a partir de
uma rota e seus parâmetros associados.
Ao configurar o componente `urlManager` na configuração da aplicação, poderá
fazer com que sua aplicação reconheça de forma arbitrária diversos formatos de
URL sem modificar o código existente da aplicação. Por exemplo, você pode usar o
código a seguir para criar uma URL a partir da ação `post/view`:
```php
use yii\helpers\Url;
// Url::to() chama UrlManager::createUrl() para criar uma URL
$url = Url::to(['post/view', 'id' => 100]);
```
Dependendo da configuração da propriedade `urlManager`, a URL criada pode ser
parecida com um dos formatos a seguir (ou até mesmo com outro formato). E se a
URL criada for requerida, ainda será analisada a fim de obter a rota e os valores
dos parâmetros originais.
```
/index.php?r=post/view&id=100
/index.php/post/100
/posts/100
```
## Formatos de URL <span id="url-formats"></span>
O [[yii\web\UrlManager|gerenciador de URL]] suporta dois formatos de URL: o
formato de URL padrão e o formato de URL amigável (pretty URL).
O formato de URL padrão usa um parâmetro chamado `r` para representar a rota e
os demais parâmetros representam os parâmetros associados a rota. Por exemplo, a
URL `/index.php?r=post/view&id=100` representa a rota `post/view` e o parâmetro
`id` com o valor 100. O formato de URL padrão não exige qualquer tipo de
configuração no [[yii\web\UrlManager|gerenciador de URL]] e trabalha em qualquer
servidor Web.
O formato de URL amigável (pretty URL) usa um caminho adicional após o nome do
script de entrada para representar a rota e seus parâmetros. Por exemplo, o
caminho adicional na URL `/index.php/post/100` é `/post/100`, onde pode
representar, em uma adequada [[yii\web\UrlManager::rules|regra de URL]], a rota
`post/view` e o parâmetro `id` com o valor 100. Para usar o formato de URL
amigável (pretty URL), você precisará escrever um conjunto de
[[yii\web\UrlManager::rules|regras de URLs]] de acordo com a necessidade sobre
como as URLs devem parecer.
Você pode alterar entre os dois formatos de URLs, alternando a propriedade
[[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] do
[[yii\web\UrlManager|gerenciador de URL]] sem alterar qualquer código na aplicação.
## Roteamento <span id="routing"></span>
O roteamento envolve duas etapas. Na primeira etapa, a requisição de entrada é
transformada em uma rota e seus parâmetros. Na segunda etapa, a
[ação do controller (controlador)](structure-controllers.md) correspondente a
rota analisada será criada para processar a requisição.
Ao utilizar o formato de URL padrão, a análise de uma requisição para obter uma
rota é tão simples como pegar o valor via `GET` do parâmetro `r`.
Ao utilizar o formato de URL amigável (pretty URL), o
[[yii\web\UrlManager|gerenciado de URL]] examinará as
[[yii\web\UrlManager::rules|regras de URLs]] registradas para encontrar alguma
correspondência que poderá resolver a requisição em uma rota. Se tal regra não
for encontrada, uma exceção [[yii\web\NotFoundHttpException]] será lançada.
Uma vez que a requisição analisada apresentar uma rota, é hora de criar a ação
do controller (controlador) identificado pela rota.
A rota é dividida em várias partes pelo separador barra (“/”). Por exemplo, a
rota `site/index` será dividida em duas partes: `site` e `index`. Cada parte é
um ID que pode referenciar a um módulo, um controller (controlador) ou uma ação.
A partir da primeira parte da rota, a aplicação executará as seguintes etapas para
criar o módulo (se existir), o controller (controlador) e a ação:
1. Define a aplicação como o módulo atual.
2. Verifica se o [[yii\base\Module::controllerMap|mapa do controller (controlador)]]
do módulo contém o ID atual. Caso exista, um objeto do controller (controlador)
será criado de acordo com a configuração do controller (controlador) encontrado
no mapa e a etapa 3 e 4 não serão executadas.
3. Verifica se o ID referência a um módulo listado na propriedade
[[yii\base\Module::modules|modules]] do módulo atual. Caso exista, um módulo
será criado de acordo com as configurações encontradas na lista e a etapa 2
será executada como etapa seguinte do processo, no âmbito de usar o contexto
do módulo recém-criado.
4. Trata o ID como um ID do controller (controlador) e cria um objeto do controller
(controlador). Siga para a próxima etapa, como parte restante do processo.
5. O controller (controlador) procura o ID atual em seu
[[yii\base\Controller::actions()|mapa de ações]]. Caso exista, será criado uma
ação de acordo com a configuração encontrada no mapa. Caso contrário, o
controller (controlador) tentará criar uma ação inline que é definida por um
método da ação correspondente ao ID atual.
Nas etapas acima, se ocorrer qualquer erro, uma exceção [[yii\web\NotFoundHttpException]]
será lançada, indicando a falha no processo de roteamento.
### Rota Padrão <span id="default-route"></span>
Quando uma requisição analisada apresentar uma rota vazia, a assim chamada
*rota padrão* será usada em seu lugar. A rota padrão é `site/index` é utilizada
como padrão, que referencia a ação `index` do controller (controlador) `site`.
Você pode personalizar esta configuração pela propriedade
[[yii\web\Application::defaultRoute|defaultRoute]] na configuração da aplicação
como mostrado a seguir:
```php
[
// ...
'defaultRoute' => 'main/index',
];
```
### Rota `catchAll` <span id="catchall-route"></span>
Às vezes você pode querer colocar sua aplicação Web em modo de manutenção
temporariamente e exibir uma mesma página com informações para todas as requisições.
Existem muitas maneiras de atingir este objetivo. Mas uma das maneiras mais simples
é apenas configurar a propriedade [[yii\web\Application::catchAll]] na configuração
da aplicação como mostrado a seguir:
```php
[
// ...
'catchAll' => ['site/offline'],
];
```
Na configuração acima, a ação `site/offline` será utilizado para lidar com todas
as requisições recebidas.
A propriedade `catchAll` deve receber um array, o primeiro elemento especifica a
rota e o restante dos elementos (pares de nomes e seus valores) especificam os
parâmetros a serem [associados a ação](structure-controllers.md#action-parameters).
## Criando URLs <span id="creating-urls"></span>
O Yii fornece um método de ajuda [[yii\helpers\Url::to()]] para criar vários tipos
de URLs a partir de determinadas rotas e seus parâmetros. Por exemplo,
```php
use yii\helpers\Url;
// cria uma URL para uma rota: /index.php?r=post/index
echo Url::to(['post/index']);
// cria uma URL para uma rota com parâmetros: /index.php?r=post/view&id=100
echo Url::to(['post/view', 'id' => 100]);
// cria uma URL ancorada: /index.php?r=post/view&id=100#content
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);
// cria uma URL absoluta: http://www.example.com/index.php?r=post/index
echo Url::to(['post/index'], true);
// cria uma URL absoluta usando https: https://www.example.com/index.php?r=post/index
echo Url::to(['post/index'], 'https');
```
Observe que nos exemplos acima, assumimos o formato de URL padrão. Se o formato
de URL amigável (pretty URL) estiver habilitado, as URLs criadas serão diferentes
de acordo com as [[yii\web\UrlManager::rules|regra de URL]] em uso.
A rota passada para o método [[yii\helpers\Url::to()]] é sensível ao contexto.
Ele pode ser tanto uma rota *relativa* quanto uma rota *absoluta* que será
normalizada de acordo com as regras a seguir:
- Se a rota for uma string vazia, a requisição atual [[yii\web\Controller::route|route]] será usada;
- Se a rota não contivér barras (“/”), ele será considerado um ID da ação do
controller (controlador) atual e será antecedido pelo valor da propriedade
[[\yii\web\Controller::uniqueId|uniqueId]] do controller (controlador) atual;
- Se a rota não contivér uma barra (“/”) inicial, será considerado como uma rota
relativa ao módulo atual e será antecedido pelo valor da propriedade
[[\yii\base\Module::uniqueId|uniqueId]] do módulo atual.
A partir da versão 2.0.2, você pode especificar uma rota usando
[alias](concept-aliases.md). Se for este o caso, a alias será a primeira a ser
convertida em uma rota real e em seguida será transformada em uma rota absoluta
de acordo com as regras informadas anteriormente.
Por exemplo, assumindo que o módulo atual é `admin` e o controller (controlador)
atual é `post`,
```php
use yii\helpers\Url;
// rota atual requerida: /index.php?r=admin/post/index
echo Url::to(['']);
// uma rota relativa com apenas o ID da ação: /index.php?r=admin/post/index
echo Url::to(['index']);
// uma rota relativa: /index.php?r=admin/post/index
echo Url::to(['post/index']);
// uma rota absoluta: /index.php?r=post/index
echo Url::to(['/post/index']);
// /index.php?r=post/index assumindo que a alias "@posts" foi definida como "/post/index"
echo Url::to(['@posts']);
```
O método [[yii\helpers\Url::to()]] é implementado através das chamadas dos métodos
[[yii\web\UrlManager::createUrl()|createUrl()]] e
[[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]] do
[[yii\web\UrlManager|gerenciador de URL]].
Nas próximas subseções, iremos explicar como configurar o
[[yii\web\UrlManager|gerenciador de URL]] para personalizar os formatos das URLs criadas.
O método [[yii\helpers\Url::to()]] também suporta a criação de URLs NÃO relacionadas
a uma rota em particular. Neste caso, ao invés de passar um array como seu primeiro
parâmetro, você pode passar uma string. Por exemplo,
```php
use yii\helpers\Url;
// rota atual requerida: /index.php?r=admin/post/index
echo Url::to();
// uma alias da URL: http://example.com
Yii::setAlias('@example', 'http://example.com/');
echo Url::to('@example');
// uma URL absoluta: http://example.com/images/logo.gif
echo Url::to('/images/logo.gif', true);
```
Além do método `to()`, a classe auxiliar [[yii\helpers\Url]] também fornece uma
série de métodos referentes a criação de URLs. Por exemplo,
```php
use yii\helpers\Url;
// URL da página inicial: /index.php?r=site/index
echo Url::home();
// URL base, útil se a aplicação for implementada em uma subpasta da pasta raiz do servidor Web
echo Url::base();
// A URL canônica da requisição atual
// Veja mais detalhes em https://en.wikipedia.org/wiki/Canonical_link_element
echo Url::canonical();
// Obtêm a URL da requisição anterior para reutilizá-la em requisições futuras
Url::remember();
echo Url::previous();
```
## Usando URLs Amigáveis (Pretty URLs) <span id="using-pretty-urls"></span>
Para utilizar as URLs amigáveis (pretty URLs), configure o componente `urlManager`
na configuração da aplicação conforme o exemplo a seguir:
```php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
// ...
],
],
],
]
```
A propriedade [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] é obrigatória
para habilitar o formato de URL amigável (pretty URL).
O restante das propriedades são opcionais. No entanto, a configuração utilizada
acima é a mais utilizada.
* [[yii\web\UrlManager::showScriptName|showScriptName]]: esta propriedade determina
se o script de entrada deve ser incluído ou não nas URLs criadas. Por exemplo,
ao invés de criar uma URL `/index.php/post/100`, definindo esta propriedade
como `false`, a URL `/post/100` será gerada.
* [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: esta propriedade
habilita uma análise rigorosa (strict parsing) da requisição. Caso a análise
rigorosa estiver habilitada, a URL da requisição deve corresponder pelo menos
a uma das regras definidas pela propriedade [[yii\web\UrlManager::rules|rules]]
a fim de ser tratado como uma requisição válida, caso contrário a exceção
[[yii\web\NotFoundHttpException]] será lançada. Caso a análise rigorosa estiver
desabilitada, as regras definidas pela propriedade
[[yii\web\UrlManager::rules|rules]] NÃO serão verificadas e as informações
obtidas pela URL serão tratadas como a rota da requisição.
* [[yii\web\UrlManager::rules|rules]]: esta propriedade contém uma lista de
regras especificando como serão analisadas e criadas as URLs. Esta é a principal
propriedade que você deve trabalhar para criar URLs cujos formatos satisfaçam
a sua exigência em particular.
> Observação: A fim de esconder o nome do script de entrada nas URLs criadas,
além de definir a propriedade [[yii\web\UrlManager::showScriptName|showScriptName]]
como `false`, você também pode precisar configurar o seu servidor Web para
identificar corretamente o script PHP quando uma URL da requisição não
especificar um explicitamente. Caso você estejam utilizando um servidor Web
com Apache, você pode consultar a configuração recomendada, conforme descrito
na seção [Installation](start-installation.md#recommended-apache-configuration).
### Regras de URLs <span id="url-rules"></span>
Uma regra de URL é uma instância de [[yii\web\UrlRule]] ou de classes que as estendam.
Cada regra de URL consiste de um padrão usado para combinar as partes do caminho
das URLs, como uma rota e alguns parâmetros. Uma regra de URL pode ser usado para
analisar uma URL da requisição somente se o padrão corresponder com a esta URL.
Uma regra de URL pode ser usada para criar uma URL para corresponder a uma
determinada rota e seus parâmetros.
Quando uma formato de URL amigável (pretty URL) estiver habilitada, o
[[yii\web\UrlManager|gerenciador de URL]] utilizará as regras de URLs declaradas
na propriedade [[yii\web\UrlManager::rules|rules]] para analisar as requisições
e para criar URLs. Em particular, para analisar uma requisição, o
[[yii\web\UrlManager|gerenciador de URL]] verificará as regras na ordem em que
foram declaradas e só enxergará a *primeira* regra que corresponda a URL da
requisição. A regra que foi correspondida é então utilizada para obter a rota e
seus parâmetros a partir de sua análise. A mesma coisa acontece na criação de
URLs, o [[yii\web\UrlManager|gerenciador de URL]] enxergará apenas a primeira
regra que corresponda a rota e seus parâmetros para serem utilizados na criação
de uma URL.
Você pode configurar a propriedade [[yii\web\UrlManager::rules]] com um array
composto de pares de chave-valor, onde a chave é o padrão da regra e o valor
serão as rotas. Cada par de padrão-rota define uma regra de URL. Por exemplo,
as [[yii\web\UrlManager::rules|regras]] a seguir configuram duas regras de URL.
A primeira regra corresponde a uma URL chamada `posts` sendo mapeado para utilizar
a rota `post/index`.
A segunda regra corresponde a uma URL que combine com expressão regular
`post/(\d+)` seguido de um parâmetro chamado `id` sendo mapeado para utilizar a
rota `post/view`.
```php
[
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
```
> Informação: O padrão em uma regra é usado para identificar o caminho de uma URL.
Por exemplo, o caminho da URL `/index.php/post/100?source=ad` é `post/100`
(as barras (“/”) iniciais e finais serão ignoradas) combinando com o padrão `post/(\d+)`.
Além de declarar regras de URL como pares de padrão-rota, você também pode declarar
como array. Cada array é utilizado para configurar um único objeto da regra de URL.
Isto se faz necessário quando você deseja configurar outras propriedades de uma
regra de URL. Por exemplo,
```php
[
// ...outras regras de URL...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
```
Por padrão, se você não especificar a opção `class` na configuração de uma regra,
será utilizado a classe [[yii\web\UrlRule]].
### Parâmetros Nomeados <span id="named-parameters"></span>
Uma regra de URL pode ser associado a alguns parâmetros nomeados que são
especificados no padrão `<ParamName:RegExp>`, onde o `ParamName` especifica o
nome do parâmetro e o `RegExp` especifica uma expressão regular opcional usada
para corresponder ao valor do parâmetro. Se o `RegExp` são for especificado,
significará que o valor do parâmetro será uma string sem barras (“/”).
> Observação: Você apenas pode especificar expressões regulares para os parâmetros.
As demais partes de um padrão serão considerados como um texto simples.
Quando esta regra for utilizada para analisar uma URL, os parâmetros associados
serão preenchidos com os valores que foram correspondidos pela regra e estes
parâmetros serão disponibilizados logo a seguir no `$_GET` pelo componente da
aplicação `request`.
Vamos utilizar alguns exemplos para demonstrar como os parâmetros nomeados
funcionam. Supondo que declaramos as três regras a seguir:
```php
[
'posts/<year:\d{4}>/<category>' => 'post/index',
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
```
Quando as regras forem utilizadas para analisar as URLs:
- `/index.php/posts` obterá a rota `post/index` usando a segunda regra;
- `/index.php/posts/2014/php` obterá a rota `post/index`, o parâmetro `year`
cujo o valor é 2014 e o parâmetro `category` cujo valor é `php` usando a primeira regra;
- `/index.php/post/100` obterá a rota `post/view` e o parâmetro `id` cujo valor
é 100 usando a terceira regra;
- `/index.php/posts/php` causará uma exceção [[yii\web\NotFoundHttpException]]
quando a propriedade [[yii\web\UrlManager::enableStrictParsing]] for `true`,
por não ter correspondido a nenhum dos padrões. Se a propriedade
[[yii\web\UrlManager::enableStrictParsing]] for `false` (o valor padrão), o
caminho `posts/php` será retornado como uma rota.
E quando as regras fores utilizadas para criar as URLs:
- `Url::to(['post/index'])` cria `/index.php/posts` usando a segunda regra;
- `Url::to(['post/index', 'year' => 2014, 'category' => 'php'])` cria `/index.php/posts/2014/php` usando a primeira regra;
- `Url::to(['post/view', 'id' => 100])` cria `/index.php/post/100` usando a terceira regra;
- `Url::to(['post/view', 'id' => 100, 'source' => 'ad'])` cria `/index.php/post/100?source=ad` usando a terceira regra.
Pela razão do parâmetro `source` não foi especificado na regra, ele será acrescentado como uma query string na criação da URL.
- `Url::to(['post/index', 'category' => 'php'])` cria `/index.php/post/index?category=php` usando nenhuma das regras.
Observe que, se nenhuma das regras forem aplicadas, a URL será criada simplesmente
como a rota sendo o caminho e todos os parâmetros como query string.
### Parametrizando Rotas <span id="parameterizing-routes"></span>
Você pode incorporar nomes de parâmetros na rota de uma regra de URL. Isto permite
que uma regra de URL seja utilizada para combinar diversas rotas. Por exemplo, a
regra a seguir incorpora os parâmetros `controller` e `action` nas rotas.
```php
[
'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>',
'<controller:(post|comment)>/<id:\d+>' => '<controller>/view',
'<controller:(post|comment)>s' => '<controller>/index',
]
```
Para analisar uma URL `/index.php/comment/100/create`, a primeira regra será
aplicada, na qual foi definida o parâmetro `controller` para ser `comment` e o
parâmetro `action` para ser `create`. Sendo assim, a rota `<controller>/<action>`
é resolvida como `comment/create`.
De forma similar, para criar uma URL com a rota `comment/index`, a terceira regra
será aplicada, criando um URL `/index.php/comments`.
> Informação: Pela parametrização de rotas, é possível reduzir significativamente
o número de regras de URL, que também pode melhorar o desempenho do
[[yii\web\UrlManager|gerenciador de URL]].
Por padrão, todos os parâmetros declarados nas regras são obrigatórios. Se uma
URL da requisição não contiver um dos parâmetros em particular, ou se a URL está
sendo criado sem um dos parâmetros em particular, a regra não será aplicada. Para
fazer com que algum parâmetro em particular seja opcional, você pode configurar
a propriedade [[yii\web\UrlRule::defaults|defaults]] da regra. Os parâmetros
listados nesta propriedade são opcionais e serão utilizados quando os mesmos não
forem fornecidos.
A declaração da regra a seguir, ambos os parâmetros `page` e `tag` são opcionais
e utilizarão o valor 1 e a string vazia, respectivamente, quando não forem fornecidos.
```php
[
// ...outras regras...
[
'pattern' => 'posts/<page:\d+>/<tag>',
'route' => 'post/index',
'defaults' => ['page' => 1, 'tag' => ''],
],
]
```
A regra anterior pode ser usado para analisar ou criar qualquer uma das seguintes URLs:
* `/index.php/posts`: `page` é 1, `tag` é ''.
* `/index.php/posts/2`: `page` é 2, `tag` is ''.
* `/index.php/posts/2/news`: `page` é 2, `tag` é `'news'`.
* `/index.php/posts/news`: `page` é 1, `tag` é `'news'`.
Sem o uso dos parâmetros opcionais, você deveria criar 4 regras para alcançar o
mesmo resultado.
### Regras com Domínios <span id="rules-with-server-names"></span>
É possível incluir domínios nos padrões das regras de URL. Isto é útil quando sua
aplicação se comporta de forma diferente em diferentes domínios. Por exemplo, a
regra a seguir obtém a rota `admin/user/login` pela análise da URL
`http://admin.example.com/login` e a rota `site/login` pela análise da URL
`http://www.example.com/login`.
```php
[
'http://admin.example.com/login' => 'admin/user/login',
'http://www.example.com/login' => 'site/login',
]
```
Você também pode incorporar parâmetros nos domínios para extrair informações
dinamicamente a partir deles. Por exemplo, a regra a seguir obtém a rota
`post/index` e o parâmetro `language=en` pela análise da URL `http://en.example.com/posts`
```php
[
'http://<language:\w+>.example.com/posts' => 'post/index',
]
```
> Observação: Regras com domínios NÃO devem ser incluídos com subpastas do script
de entrada em seus padrões. Por exemplo, se a aplicação estiver sob
`http://www.example.com/sandbox/blog`, você deve usar o padrão
`http://www.example.com/posts` ao invés de `http://www.example.com/sandbox/blog/posts`.
Isto permite que sua aplicação seja implantado sob qualquer diretório sem a
necessidade de alterar o código da aplicação.
### Sufixos da URL <span id="url-suffixes"></span>
Você pode querer adicionar sufixos nas URLs para diversos fins. Por exemplo,
você pode adicionar o `.html` nas URLs para que se pareçam com páginas estáticas.
Você também pode adicionar o `.json` nas URLs para indicar o tipo de conteúdo
esperado na resposta. Você pode alcançar este objetivo configurando a propriedade
[[yii\web\UrlManager::suffix]] na configuração da aplicação conforme o exemplo a seguir:
```php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'rules' => [
// ...
],
],
],
]
```
A configuração anterior permitirá que o [[yii\web\UrlManager|gerenciador de URL]]
reconheçam as URLs solicitadas e que também criem URLs com o prefixo `.html`.
> Dica: Você pode definir `/` como o sufixo para que todas as URLs terminem com barra.
> Observação: Ao configurar um sufixo da URL e a URL da requisição não conter um,
será considerado como uma URL não válida. Isto é uma prática recomendada no
SEO (otimização para mecanismos de pesquisa, do *inglês search engine optimization*).
Ás vezes você poder querer utilizar diferentes sufixos para diferentes URLs.
Isto pode ser alcançado pela configuração da propriedade
[[yii\web\UrlRule::suffix|suffix]] individualmente para cada regra de URL.
Quando uma regra de URL possuir esta propriedade definida, sobrescreverá o
sufixo que foi definido da camada do [[yii\web\UrlManager|gerenciador de URL]].
Por exemplo, a configuração a seguir contém uma regra de URL personalizada que
usa o `.json` como sufixo ao invés do sufixo `.html` definido globalmente.
```php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'rules' => [
// ...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
],
],
],
]
```
### Métodos HTTP <span id="http-methods"></span>
Ao implementar RESTful API, é necessário que sejam obtidas rotas diferentes pela
análise de uma mesma URL de acordo com o método HTTP utilizado. Isto pode ser
alcançado facilmente adicionando o prefixo do método HTTP suportado, separando
os nomes dos métodos por vírgulas. Por exemplo, a regra a seguir possui o mesmo
padrão `post/<id:\d+>` com suporte a diferentes métodos HTTP. A análise de uma
requisição `PUT post/100` obterá a rota `post/create`, enquanto a requisição
`GET post/100` obterá a rota `post/view`.
```php
[
'PUT,POST post/<id:\d+>' => 'post/create',
'DELETE post/<id:\d+>' => 'post/delete',
'post/<id:\d+>' => 'post/view',
]
```
> Observação: Se uma regra de URL contiver método(s) HTTP, esta regra só será
utilizada para análises de URLs. A regra será ignorada quando o
[[yii\web\UrlManager|gerenciador de URL]] for chamado para criar URLs.
> Dica: Para simplificar o roteamento do RESTful APIs, o Yii fornece uma classe
especial [[yii\rest\UrlRule]] de regras que é muito diferente. Esta classe
suporta muitos recursos como a pluralização automática de IDs do controller
(controlador). Para mais detalhes, por favor, consulte a seção
[Routing](rest-routing.md) sobre o desenvolvimento de RESTful APIs.
### Regras Personalizadas <span id="customizing-rules"></span>
Nos exemplo anteriores, as regras de URL são declaradas principalmente no formato
de pares de padrão-rota. Este é um formato de atalho bastante utilizado. Em
alguns cenários, você pode querer personalizar uma regra de URL configurando
outras propriedades, tais como o [[yii\web\UrlRule::suffix]]. Isto pode ser
feito utilizando um array de configuração para especificar uma regra. O exemplo
a seguir foi retirado da subseção [Sufixos da URL](#url-suffixes),
```php
[
// ...outras regras de URL...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
```
> Informações: Por padrão, se você não especificar a opção `class` na configuração
de uma regra, será usado como padrão a classe [[yii\web\UrlRule]].
### Adicionando Regras Dinamicamente <span id="adding-rules"></span>
As regras de URL podem ser adicionadas dinamicamente ao [[yii\web\UrlManager|gerenciador de URL]].
Esta técnica muitas vezes se faz necessária em [módulos](structure-modules.md) que
são redistribuídos e que desejam gerenciar as suas próprias regras de URL. Para
que estas regras sejam adicionadas dinamicamente e terem efeito durante o processo
de roteamento, você pode adiciona-los durante a [inicialização (bootstrapping)](runtime-bootstrapping.md).
Para os módulos, significa que deve implementar a interface [[yii\base\BootstrapInterface]]
e adicionar as regras no método [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]]
conforme o exemplo a seguir:
```php
public function bootstrap($app)
{
$app->getUrlManager()->addRules([
// declare as regras aqui
], false);
}
```
Observe que você também deve listar estes módulos no [[yii\web\Application::bootstrap]]
para que eles sejam usados no processo de [inicialização (bootstrapping)](runtime-bootstrapping.md)
### Criando Classes de Regras <span id="creating-rules"></span>
Apesar do fato que a classe padrão [[yii\web\UrlRule]] é flexível o suficiente
para a maior parte dos projetos, há situações em que você terá que criar a sua
própria classe de regra. Por exemplo, em um site de venda de carros, você pode
querer dar suporte a um formato de URL como `/Manufacturer/Model`, que tanto o
`Manufacturer` quanto o `Model` devem coincidir com os dados armazenados em uma
tabela do banco de dados. A classe de regra padrão não vai funcionar nesta
situação pois vão se basear em padrões estaticamente declarados.
Podemos criar uma classe de regra de URL para resolver este formato.
```php
namespace app\components;
use yii\web\UrlRuleInterface;
use yii\base\Object;
class CarUrlRule extends Object implements UrlRuleInterface
{
public function createUrl($manager, $route, $params)
{
if ($route === 'car/index') {
if (isset($params['manufacturer'], $params['model'])) {
return $params['manufacturer'] . '/' . $params['model'];
} elseif (isset($params['manufacturer'])) {
return $params['manufacturer'];
}
}
return false; // esta regra não se aplica
}
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// checa o $matches[1] e $matches[3] para verificar
// se coincidem com um *fabricante* e um *modelo* no banco de dados.
// Caso coincida, define o $params['manufacturer'] e/ou $params['model']
// e retorna ['car/index', $params]
}
return false; // esta regra não se aplica
}
}
```
E utilize esta nova classe de regra na configuração [[yii\web\UrlManager::rules]]:
```php
[
// ...outras regras...
[
'class' => 'app\components\CarUrlRule',
// ...configurar outras propriedades...
],
]
```
## Considerando Performance <span id="performance-consideration"></span>
Ao desenvolver uma aplicação Web complexa, é importante otimizar as regras de URL
para que leve menos tempo na análise de requisições e criação de URLs.
Utilizando rotas parametrizadas, você reduz o número de regras de URL, na qual
pode melhorar significativamente o desempenho.
Na análise e criação de URLs, o [[yii\web\UrlManager|gerenciador de URL]] examina
as regras de URL na ordem em que foram declaradas.
Portanto, você pode considerar ajustar a ordem destas regras, fazendo com que as
regras mais específicas e/ou mais comuns sejam colocadas antes que os menos.
Se algumas regras de URL compartilharem o mesmo prefixo em seus padrões ou rotas,
você pode considerar utilizar o [[yii\web\GroupUrlRule]] para que sejam examinados
de forma mais eficiente pelo [[yii\web\UrlManager|gerenciador de URL]] como um
grupo. Normalmente é o caso de aplicações compostos por módulos, onde cada módulo
possui o seu próprio conjunto de regras de URL utilizando o ID do módulo como
prefixo comum.

4
docs/guide-ru/README.md

@ -108,10 +108,10 @@ All Rights Reserved.
------------
* [Аутентификация](security-authentication.md)
* **TBD** [Авторизация](security-authorization.md)
* [Авторизация](security-authorization.md)
* [Работа с паролями](security-passwords.md)
* **TBD** [Клиенты авторизации](security-auth-clients.md)
* **TBD** [Лучшие практики](security-best-practices.md)
* [Лучшие практики](security-best-practices.md)
Кеширование

368
docs/guide-ru/images/rbac-access-check-1.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-access-check-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

368
docs/guide-ru/images/rbac-access-check-2.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-access-check-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

368
docs/guide-ru/images/rbac-access-check-3.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-access-check-3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

312
docs/guide-ru/images/rbac-hierarchy-1.graphml

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n5" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-hierarchy-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

368
docs/guide-ru/images/rbac-hierarchy-2.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-hierarchy-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

518
docs/guide-ru/security-authorization.md

@ -0,0 +1,518 @@
Авторизация
===========
> Примечание: этот раздел находится на стадии разработки.
Авторизация это процесс проверки того, что пользователь имеет достаточно прав чтобы что-то сделать. Yii обеспечивает два
методв авторизации: Фильтры контроля доступа (ACF) и контроль доступа основанный на ролях (RBAC).
Фильтры контроля доступа
------------------------
Фильтры контроля доступа (ACF) является простым методом, который лучше всего использовать в приложениях с простым
контролем доступа. Как указывает его название, ACF это фильтры, который может присоединяться к контроллеру
или модулю как поведение. ACF проверяет набор [[yii\filters\AccessControl::rules|правил доступа]], чтоб убедится,
что пользователь имеет доступ к запрошенной операции.
Код ниже показывает как использовать ACF реализованный в [[yii\filters\AccessControl]]:
```php
use yii\filters\AccessControl;
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['login', 'logout', 'signup'],
'rules' => [
[
'allow' => true,
'actions' => ['login', 'signup'],
'roles' => ['?'],
],
[
'allow' => true,
'actions' => ['logout'],
'roles' => ['@'],
],
],
],
];
}
// ...
}
```
Код выше показывет ACF прикреплённы через поведение контроллера `site`. Это типичный способ использования фильтра действий.
Параметр `only` указывает, что фильтр ACF нужно применять только к действиям `login`, `logout` и `signup`.
Параметр `rules` задаёт [[yii\filters\AccessRule|правила доступа]], которые означают следующее:
- Разрешить всем гостям (ещё не прошедшим авторизацию) доступ к действиям `login` и `signup`.
Опция `roles` содержит знак вопроса `?`, это специальный токен обозначающий "гостя".
- Разрешить аутентифицированным пользователям доступ к действию `logout`. Символ `@` это другой специальный токен
обозначающий аутентифицированного пользователя.
Когда ACF проводит проверку авторизации, он проверяет правила по одному сверху вниз пока не найдёт совпадение.
Значение опции `allow` выбранного правила указывает авторизовывать пользователя или нет. Если ни одно из правил
не совпало, то пользователь считается НЕ авторизованным и ACF останавливает дальнейшее выполнение деиствия.
По умолчанию, ACF когда у пользователя отсутствует доступ к текущему действию, делает следующее:
* Если пользователь гость, вызывается [[yii\web\User::loginRequired()]], который перенаправляет браузер на страницу входа.
* Если пользователь авторизован, генерируется исключение [[yii\web\ForbiddenHttpException]].
Вы можете переопределить это поведение настроив свойство [[yii\filters\AccessControl::denyCallback]]:
```php
[
'class' => AccessControl::className(),
'denyCallback' => function ($rule, $action) {
throw new \Exception('You are not allowed to access this page');
}
]
```
[[yii\filters\AccessRule|Правила доступа]] поддерживает набор свойств. Ниже краткое описание поддерживаемых опций.
Вы также можете расширить [[yii\filters\AccessRule]], чтоб создать свой собственный класс правил доступа.
* [[yii\filters\AccessRule::allow|allow]]: указывает, что это "allow" или "deny" правило.
* [[yii\filters\AccessRule::actions|actions]]: указывает какие действия соответствуют этому правилу.
Это должен быть массив идентификаторов действий. Сравнение регисрозависимо. Если данное свойство пустое или не задано,
говорит что данное правило применяется ко всем действиям.
* [[yii\filters\AccessRule::controllers|controllers]]: задаёт контроллеры, которым соответствует данное правило.
Это должен быть массив с идентификаторами контроллеров. Сравнение регисрозависимо. Если данное свойство пустое или не задано,
то данное правило применяется ко всем действиям.
* [[yii\filters\AccessRule::roles|roles]]: задаёт роли пользователей соответствующих данному правилу.
Распознаются две специальные роли, которые проверяются с помощью [[yii\web\User::isGuest]]:
- `?`: соответствует гостевому пользователю (не аутентифицирован)
- `@`: соответствует аутентифицированному пользователю
Использование других имён ролей требует RBAC (будет описано дальше), можно будет использовать [[yii\web\User::can()]].
Если данное свойство пустое или не задано, то данное правило применяется ко всем ролям.
* [[yii\filters\AccessRule::ips|ips]]: задаёт [[yii\web\Request::userIP|клиентские IP адреса]] для которых применяется это правило.
IP адрес может содержать `*` в конце, так чтоб он соответствовал IP адресу с таким же префиксом.
Для примера, '192.168.*' соответствует всем IP адресам в сегменте '192.168.'. Если данное свойство пустое или не задано,
то данное правило применяется ко всем IP адресам.
* [[yii\filters\AccessRule::verbs|verbs]]: задаёт http метод (например `GET`, `POST`) соответствующий данному правилу.
Сравнение регисронезависимо.
* [[yii\filters\AccessRule::matchCallback|matchCallback]]: задаёт PHP колбек, который вызывается для определения,
что правило должно быть применено.
* [[yii\filters\AccessRule::denyCallback|denyCallback]]: задаёт PHP колбек, который будет вызван если доступ будет
запрещён при вызове этого правила.
Ниже покзан пример, который показывает использование опции `matchCallback`, которая позволяет писать произвольную
логику проверки доступа:
```php
use yii\filters\AccessControl;
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['special-callback'],
'rules' => [
[
'actions' => ['special-callback'],
'allow' => true,
'matchCallback' => function ($rule, $action) {
return date('d-m') === '31-10';
}
],
],
],
];
}
// Колбек сработал! Эта страница может быть отображена толко 31-ого октября
public function actionSpecialCallback()
{
return $this->render('happy-halloween');
}
}
```
Контроль доступа на основе ролей (RBAC)
---------------------------------------
Управление доступом на основе ролей (RBAC) обеспечивает простой, но мощьный централизованный контроль доступа.
Пожалуйста обратитесь к [Wikipedia](http://en.wikipedia.org/wiki/Role-based_access_control) для получения более
подробного сравнения RBAC с другими более традиционными системами контроля доступа.
Yii реализует общую иерархическую RBAC, следуя [NIST RBAC model](http://csrc.nist.gov/rbac/sandhu-ferraiolo-kuhn-00.pdf).
Обеспечивается функциональность RBAC через [[yii\rbac\ManagerInterface|authManager]] [компонент приложения](structure-application-components.md).
Использование RBAC состоит из двух частей. Первая часть - это создание RBAC данных авторизации, и вторая часть это
использование данных авторизации для проверки доступа в том месте где это нужно.
Для облегчения последующего описания, мы сначала введём некоторые основные понятия RBAC.
### Основные концепции
Роль представляет собой набор *permissions* (разрешения) (например создание сообщения, обновление сообщения).
Роль может быть назначена на одного или многих пользователей. Чтобы проверить, имеет ли пользователь указанные
разрешения, мы можем проверить назначена ли пользователю роль, которая содержит данное разрешение.
С каждой ролью или разрешением может быть связано *rule* (правило). Правило представляет собой кусок кода, который будет
выполняться в ходе проверки доступа для определения может ли быть применена соответствующая роль или разрешение
к текущему пользователю. Например, разрешение "обновление поста" может иметь правило, которое проверяет является ли
текущий пользовател автором поста. Во время проверки доступа, если пользователь не является автором поста, он/она будет
считаться не имеющими разрешения "обновление поста".
И роли и разрешения могут быть организованы в иерархию. В частности роль может содержать другие роли или разрешения; и
разрешения могут содержать другие разрешения. Yii реализует *частично упорядоченную* иерархию, которая включает в себя
специальные *деревья* иерархии. Роль может содержать разрешение, но обратное не верно.
### Настройка RBAC Manager
Перед определением авторизационных данных и проверкой прав доступа, мы должны настроить компонент приложения [[yii\base\Application::authManager|authManager]].
Yii предоставляет два типа менеджеров авторизации: [[yii\rbac\PhpManager]] и [[yii\rbac\DbManager]]. Первый использует
файл с PHP скриптом для хранения данных авторизации, второй сохраняет данные в базе данных. Вы можете использовать
первый если ваше приложение не требует слишком динамичным управлением ролями и разрешениями.
#### настройка authManager с помощью `PhpManager`
Следующий код показывает как настроить в конфигурации приложения `authManager` с использованием класса [[yii\rbac\PhpManager]]:
```php
return [
// ...
'components' => [
'authManager' => [
'class' => 'yii\rbac\PhpManager',
],
// ...
],
];
```
Теперь `authManager` может быть доступен через `\Yii::$app->authManager`.
> Замечание: По умолчанию, [[yii\rbac\PhpManager]] сохраняет данные RBAC в файлах в директории `@app/rbac/`. Убедитесь
что данная директория и файлы в них доступны для записи Web серверу, если иерархия разрешений должна меняться онлайн.
#### настройка authManager с помощью `DbManager`
Следующий код показывает как настроить в конфигурации приложения `authManager` с использованием класса [[yii\rbac\DbManager]]:
```php
return [
// ...
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
// ...
],
];
```
`DbManager` использует четыре таблицы базы данных для хранения данных:
- [[yii\rbac\DbManager::$itemTable|itemTable]]: таблица для хранения авторизационных элементов. По умолчанию "auth_item".
- [[yii\rbac\DbManager::$itemChildTable|itemChildTable]]: таблица для хранения иерархии элементов. По умолчанию "auth_item_child".
- [[yii\rbac\DbManager::$assignmentTable|assignmentTable]]: таблица для хранения назначений элементов авторизации. По умолчанию "auth_assignment".
- [[yii\rbac\DbManager::$ruleTable|ruleTable]]: таблица для хранения правил. По умолчанию "auth_rule".
Прежде чем вы начнёте его использовать вам нужно создать эти таблицы в базе данных. Чтобы сделать это,
вы можете использовать миграцию хранящуюся в файле `@yii/rbac/migrations`:
`yii migrate --migrationPath=@yii/rbac/migrations`
Теперь `authManager` может быть доступен через `\Yii::$app->authManager`.
### Создание данных авторизации
Создание данных авторизации это следущие задачи:
- определение ролей и разрешений;
- установка отношений между ролями и правами доступа;
- определение правил;
- связывание правил с ролями и разрешениями;
- назначение ролей с пользователями.
В зависимости от требований к гибкости авторизации перечисленные задачи могут быть выполнены разными путями.
Если иерархия прав не меняется и количество пользователей зафиксировано, вы можете создать
[консольную команду](tutorial-console.md#create-command), которая будет единожды инициализировать данные
через APIs предоставляемое `authManager`:
```php
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
// добавляем разрешение "createPost"
$createPost = $auth->createPermission('createPost');
$createPost->description = 'Create a post';
$auth->add($createPost);
// добавляем разрешение "updatePost"
$updatePost = $auth->createPermission('updatePost');
$updatePost->description = 'Update post';
$auth->add($updatePost);
// добавляем роль "author" и даём роли разрешение "createPost"
$author = $auth->createRole('author');
$auth->add($author);
$auth->addChild($author, $createPost);
// добавляем роль "admin" и даём роли разрешение "updatePost"
// а также все разрешения роли "author"
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $updatePost);
$auth->addChild($admin, $author);
// Назначение ролей пользователям. 1 и 2 это IDs возвращаемые IdentityInterface::getId()
// обычно реализуемый в модели User.
$auth->assign($author, 2);
$auth->assign($admin, 1);
}
}
```
После выполнения команды `yii rbac/init` мы получим следующую иерархию:
![Простая иерархия RBAC](images/rbac-hierarchy-1.png "Простая иерархия RBAC")
Автор может создавать пост, администратор может обновлять пост и делать всё, что может делать автор.
Если ваше приложение позволяет регистрировать пользователей, то вам необходимо сразу назначать роли этим новым пользователям.
Например, для того, чтобы все вошедшие пользователи могли стать авторами в расширеном шаблоне проекта вы должны изменить
`frontend\models\SignupForm::signup()` как показано ниже:
```php
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save(false);
// нужно добавить следующие три строки:
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $user->getId());
return $user;
}
return null;
}
```
Для приложений, требующих комплексного контроля доступа с динамически обновляемыми данными авторизации, существуют
специальные пользовательские интерфейсы (так называемые админ-панели), которые могут быть разработаны с
использованием API, предлагаемого `authManager`
### Использование правил
Как упомянуто выше, правила добавляют дополнительные ограничение на роли и разрешения. Правило это классы, расширяющие
[[yii\rbac\Rule]]. Он должен реализовывать метод [[yii\rbac\Rule::execute()|execute()]]. В иерархии созданой нами ранее
автор не можете редактировать свой пост. Давайте исправим это. Во-первых, мы должны создать правило проверяющее,
что пользователь является автором поста:
```php
namespace app\rbac;
use yii\rbac\Rule;
/**
* Проверяем authorID на соответствие с пользователем переданным через параметры
*/
class AuthorRule extends Rule
{
public $name = 'isAuthor';
/**
* @param string|integer $user the user ID.
* @param Item $item the role or permission that this rule is associated with
* @param array $params parameters passed to ManagerInterface::checkAccess().
* @return boolean a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
return isset($params['post']) ? $params['post']->createdBy == $user : false;
}
}
```
Правило выше проверяет, что `post` был создан `$user`. Мы создадим специальное разрешение `updateOwnPost` в команде,
которую мы использовали раньше:
```php
$auth = Yii::$app->authManager;
// add the rule
$rule = new \app\rbac\AuthorRule;
$auth->add($rule);
// добавляем разрешение "updateOwnPost" и привязываем к нему правило.
$updateOwnPost = $auth->createPermission('updateOwnPost');
$updateOwnPost->description = 'Update own post';
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);
// "updateOwnPost" будет использоваться из "updatePost"
$auth->addChild($updateOwnPost, $updatePost);
// разрешаем "автору" обновлять его посты
$auth->addChild($author, $updateOwnPost);
```
Теперь мы имеем следующую иерархию:
![Иерархия RBAC с правилом](images/rbac-hierarchy-2.png "Иерархия RBAC с правилом")
### Проверка доступа
С готовыми данными авторизациями проверка доступа это просто вызов метода [[yii\rbac\ManagerInterface::checkAccess()]].
Так как большинство проверок доступа относятся к текущему пользователю, для удобства Yii предоставляет сокращённый метод
[[yii\web\User::can()]], который можно использовать как показано ниже:
```php
if (\Yii::$app->user->can('createPost')) {
// create post
}
```
Если текущий пользователь Jane с ID=1 мы начнём с `createPost` и попробуем добраться до `Jane`:
![Проверка доступа](images/rbac-access-check-1.png "Проверка доступа")
Для того чтоб проверить может ли пользователь обновить пост, нам надо передать дополнительный параметр
необходимый для правила `AuthorRule` описанного ранее:
```php
if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
// update post
}
```
Вот что происходит если текущим пользователем является John:
![Проверка доступа](images/rbac-access-check-2.png "Проверка доступа")
Мы начинаем с `updatePost` и переходим к `updateOwnPost`. Для того чтоб это произошло правило `AuthorRule` должен вернуть
`true` при вызове метода `execute`. Метод получает `$params` переданный при вызове метода `can`, значение которого равно
`['post' => $post]`. Если всё правильно мы понимаем что `author` привязан к John.
В случае Jane это немного проще, потому что она admin:
![Проверка доступа](images/rbac-access-check-3.png "Проверка доступа")
### Использование роли по умолчанию
Роль по умолчанию это роль, которая *неявно* присваивается *всем* пользователям. Вызов метода
[[yii\rbac\ManagerInterface::assign()]] не требуется, и авторизационные данные не содержат информации о назначении.
Роль по умолчанию обычно связывают с правилом определяющим к какой роли принадлежит каждый пользователь.
Роли по умолчанию обычно используются в приложениях, которые уже имеют какое-то назначение ролей. Для примера, приложение
может иметь столбец "group" в таблице пользователей и каждый пользователь принадлежит к какой-то группе. Если каждая
группа может быть сопоставлена роли в RBAC, вы можете использовать роль по умолчанию для автоматического назначения
каждому пользователю роли RBAC. Давайте используем пример, чтобы понять как это можно сделать.
Предположим что в таблице пользователей у вам есть столбец `group`, в котором значение 1 представляет группу "администратор",
а 2 - группу "автор". Вы планируете иметь 2 RBAC роли `admin` и `author` представляющими разрешения для двух
соответствующих групп. Вы можете настроить данные роли как показано ниже.
```php
namespace app\rbac;
use Yii;
use yii\rbac\Rule;
/**
* Checks if user group matches
*/
class UserGroupRule extends Rule
{
public $name = 'userGroup';
public function execute($user, $item, $params)
{
if (!Yii::$app->user->isGuest) {
$group = Yii::$app->user->identity->group;
if ($item->name === 'admin') {
return $group == 1;
} elseif ($item->name === 'author') {
return $group == 1 || $group == 2;
}
}
return false;
}
}
$auth = Yii::$app->authManager;
$rule = new \app\rbac\UserGroupRule;
$auth->add($rule);
$author = $auth->createRole('author');
$author->ruleName = $rule->name;
$auth->add($author);
// ... add permissions as children of $author ...
$admin = $auth->createRole('admin');
$admin->ruleName = $rule->name;
$auth->add($admin);
$auth->addChild($admin, $author);
// ... add permissions as children of $admin ...
```
Обратите внимание, так как "author" добавлен как дочерняя роль к "admin", следовательно в реализации метода `execute()`
класса правила вы должны учитывать это иерархию. Именно по этому для роли "author" метод `execute()` вернёт истину
если пользователь принадлежит к группам 1 или 2 (это означает, что пользователь находится в группе
администраторов или авторов)
Далее, настроим `authManager` с помощью перечисления ролей в свойстве [[yii\rbac\BaseManager::$defaultRoles]]:
```php
return [
// ...
'components' => [
'authManager' => [
'class' => 'yii\rbac\PhpManager',
'defaultRoles' => ['admin', 'author'],
],
// ...
],
];
```
Теперь если вы выполните проверку доступа, для обойх ролей `admin` и `author` будет выполнена проверка правила
асоциированного с ними. Если правило вернёт истину, это будет означать что роль применяется к текущему пользователю.
На основании правила, реализованного выше, если пользователь входит в группу 1 пользователю будет назначена роль `admin`;
и если значение `group` равно 2 будет применена роль `author`.

179
docs/guide-ru/security-best-practices.md

@ -0,0 +1,179 @@
Лучшие практики безопасности
============================
Ниже мы рассмотрим основные принципы безопасности и опишем, как избежать угроз при разработке на Yii.
Основные принципы
-----------------
Есть два основных принципа безопасности, независимо от того, какое приложение разрабатывается:
1. Фильтрация ввода.
2. Экранирование вывода.
### Фильтрация ввода
Фильтрация ввода означает, что входные данные никогда не должны считаться безопасными и вы всегда должны проверять,
являются ли полученные данные допустимыми. Например, если мы знаем, что сортировка может быть осуществлена только
по трём полям `title`, `created_at` и `status`, и поле может передаваться через ввод пользователем, лучше проверить
значение там, где мы его получили:
```php
$sortBy = $_GET['sort'];
if (!in_array($sortBy, ['title', 'created_at', 'status'])) {
throw new Exception('Invalid sort value.');
}
```
В Yii, вы, скорее всего, будете использовать [валидацию форм](input-validation.md), чтоб делать такие проверки.
### Экранирование вывода
Экранирование вывода означает, что данные в зависимости от контекста должны экранироваться, например в контексте
HTML вы должны экранировать `<`, `>` и похожие специальные символы. В контексте JavaScript или SQL будет другой набор
символов. Так как ручное экранирование черевато ошибками, Yii предоставляет различные утилиты для экранирования в
различных контекстах.
Как избежать SQL-иньекций
-------------------------
SQL-иньекции происходят, когда текст запроса формируется склеиванием неэкранированных строк, как показано ниже:
```php
$username = $_GET['username'];
$sql = "SELECT * FROM user WHERE username = '$username'";
```
Вместо того, чтобы подставлять корректное имя пользователя, злоумышленник может передать вам в приложение что-то вроде
`'; DROP TABLE user; --`.
В результате SQL будет следующий:
```sql
SELECT * FROM user WHERE username = ''; DROP TABLE user; --'
```
Это валидный запрос, который сначала будет искать пользователей с пустым именем, а затем удалит таблицу `user`.
Скорее всего будет сломано приложение и будут потеряны данные (вы ведь делаете регулярное резервное копирование?).
Большинство запросов к базе данных в Yii происходит через [Active Record](db-active-record.md), который правильно
использует подготовленные запросы PDO внутри. При использовании подготовленных запросов невозможно манипулировать
запросом как это показано выше.
Тем не менее, иногда нужны [сырые запросы](db-dao.md) или [построитель запросов](db-query-builder.md). В этом случае
вы должны использовать безопасные способы передачи данных. Если данные используются для сравнения со значением
столбцов предпочтительнее использовать подготовленные запросы:
```php
// query builder
$userIDs = (new Query())
->select('id')
->from('user')
->where('status=:status', [':status' => $status])
->all();
// DAO
$userIDs = $connection
->createCommand('SELECT id FROM user where status=:status')
->bindValues([':status' => $status])
->queryColumn();
```
Если данные используются в качестве имён столбцов или таблиц, то лучший путь - это разрешить только предопределённый
набор значений:
```php
function actionList($orderBy = null)
{
if (!in_array($orderBy, ['name', 'status'])) {
throw new BadRequestHttpException('Only name and status are allowed to order by.')
}
// ...
}
```
Если это невозможно, то имена столбцов и таблиц должны экранироваться. Yii использует специальный синтаксис
для экранирования для всех поддерживаемых баз данных:
```php
$sql = "SELECT COUNT([[$column]]) FROM {{table}}";
$rowCount = $connection->createCommand($sql)->queryScalar();
```
Вы можете получить подробную информацию о синтаксисе в [Экранирование имён таблиц и столбцов](db-dao.md#quoting-table-and-column-names).
Как избежать XSS
----------------
XSS или крос-сайтинговый скриптинг становится возможен, когда не экранированный выходной HTML попадает в браузер.
Например, если пользователь должен ввести свой имя, но вместо `Alexander` он вводит `<script>alert('Hello!');</script>`, то
все страницы, которые его выводят без экранирования, будут выполнять JavaScript `alert('Hello!');`, и в результате
будет выводится окно сообщения в браузере. В зависимости от сайта, вместо невинных скриптов с выводом всплывающего
hello, злоумышленниками могут быть отправлены скрипты, похищающие личные данные пользователей сайта,
либо выполняющие операции от их имени.
В Yii избежать XSS легко. На месте вывода текста необходими выбрать один из двух вариантов:
1. Вы хотите вывести данные в виде обычного текста.
2. Вы хотите вывести данные в виде HTML.
Если вам нужно вывести простой текст, то экранировать лучше следующим образом:
```php
<?= \yii\helpers\Html::encode($username) ?>
```
Если нужно вывести HTML, вам лучше воспользоваться HtmlPurifier:
```php
<?= \yii\helpers\HtmlPurifier::process($description) ?>
```
Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, так что неплохо бы задуматься о кешировании.
Как избежать CSRF
-----------------
CSRF - это аббревиатура для межсайтинговой подмены запросов. Идея заключается в том, что многие приложения предполагают,
что запросы, приходящие от браузера, отправляются самим пользователем. Это может быть неправдой.
Например, сайт `an.example.com` имеет URL `/logout`, который, используя простой GET, разлогинивает пользователя. Пока
это запрос выполняется самим пользователем - всё в порядке, но в один прекрасный день злоумышленники размещают код
`<img src="http://an.example.com/logout">` на форуме с большой посещаемостью. Браузер не делает никаких отличий
между запросом изображения и запросом страницы, так что когда пользователь откроет страницу с таким тегом `img`, он
разлогинится с сайта `an.example.com`.
Вот основная идея. Можно сказать, что в разлогировании пользователя нет ничего серьёзного, но отправить POST не намного
сложнее.
Для того, чтоб избежать CSRF вы должны всегда:
1. Следуйте спецификациям HTTP, например запрос GET не должен менять состояние приложения.
2. Держите защиту CSRF в Yii включенной.
Как избежать нежелательного доступа к файлам
--------------------------------------------
По умолчанию, webroot сервера указывает на каталог `web`, где лежит `index.php`. В случае использования виртуального
хостинга, это может быть недостижимо, в конечном итоге весь код, конфиги и логи могут оказаться в webroot сервера.
Если это так, то нужно запретить доступ ко всему, кроме директории `web`. Если на вашем хостинге такое невозможно,
рассмотрите возможность смены хостинга.
Как избежать отладочной информации и утилит в продуктиве
--------------------------------------------------------
В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны во время разработки. Дело в том, что
подробные ошибки удобны для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части
вашего кода. Никогда не запускайте продуктивное приложение с `YII_DEBUG` установленным в `true` в вашем `index.php`.
Вы никогда не должны включать Gii на продуктиве. Он может быть использован для получения информации о структуре
базы данных, кода и может позволить заменить файлы, генерируемые Gii автоматически.
Также следует избегать включения на продуктиве панели отладки, если только в этом нет острой необходимости.
Она раскрывает всё приложение и детали конфигурации. Если вам все таки нужно запустить панель отладки на продуктиве,
проверьте дважды что доступ ограничен только вашими IP-адресами.

2
docs/guide/db-active-record.md

@ -202,7 +202,7 @@ $customer = Customer::findOne([
// returns all inactive customers
// SELECT * FROM `customer` WHERE `status` = 0
$customer = Customer::findAll([
$customers = Customer::findAll([
'status' => Customer::STATUS_INACTIVE,
]);
```

92
docs/guide/security-authorization.md

@ -1,23 +1,22 @@
Authorization
=============
> Note: This section is under development.
Authorization is the process of verifying that a user has enough permission to do something. Yii provides two authorization
methods: Access Control Filter (ACF) and Role-Based Access Control (RBAC).
Access Control Filter
---------------------
## Access Control Filter <span id="access-control-filter"></span>
Access Control Filter (ACF) is a simple authorization method that is best used by applications that only need some
simple access control. As its name indicates, ACF is an action filter that can be attached to a controller or a module
as a behavior. ACF will check a set of [[yii\filters\AccessControl::rules|access rules]] to make sure the current user
can access the requested action.
Access Control Filter (ACF) is a simple authorization method implemented as [[yii\filters\AccessControl]] which
is best used by applications that only need some simple access control. As its name indicates, ACF is
an action [filter](structure-filters.md) that can be used in a controller or a module. While a user is requesting
to execute an action, ACF will check a list of [[yii\filters\AccessControl::rules|access rules]]
to determine if the user is allowed to access the requested action.
The code below shows how to use ACF which is implemented as [[yii\filters\AccessControl]]:
The code below shows how to use ACF in the `site` controller:
```php
use yii\web\Controller;
use yii\filters\AccessControl;
class SiteController extends Controller
@ -48,28 +47,31 @@ class SiteController extends Controller
```
In the code above ACF is attached to the `site` controller as a behavior. This is the typical way of using an action
filter. The `only` option specifies that the ACF should only be applied to `login`, `logout` and `signup` actions.
The `rules` option specifies the [[yii\filters\AccessRule|access rules]], which reads as follows:
filter. The `only` option specifies that the ACF should only be applied to the `login`, `logout` and `signup` actions.
All other actions in the `site` controller are not subject to the access control. The `rules` option lists
the [[yii\filters\AccessRule|access rules]], which reads as follows:
- Allow all guest (not yet authenticated) users to access 'login' and 'signup' actions. The `roles` option
contains a question mark `?` which is a special token recognized as "guests".
- Allow authenticated users to access 'logout' action. The `@` character is another special token recognized as
authenticated users.
- Allow all guest (not yet authenticated) users to access the `login` and `signup` actions. The `roles` option
contains a question mark `?` which is a special token representing "guest users".
- Allow authenticated users to access the `logout` action. The `@` character is another special token representing
"authenticated users".
When ACF performs authorization check, it will examine the rules one by one from top to bottom until it finds
a match. The `allow` value of the matching rule will then be used to judge if the user is authorized. If none
of the rules matches, it means the user is NOT authorized and ACF will stop further action execution.
ACF performs the authorization check by examining the access rules one by one from top to bottom until it finds
a rule that matches the current execution context. The `allow` value of the matching rule will then be used to
judge if the user is authorized or not. If none of the rules matches, it means the user is NOT authorized,
and ACF will stop further action execution.
By default, ACF does only the following when it determines a user is not authorized to access the current action:
When ACF determines a user is not authorized to access the current action, it takes the following measure by default:
* If the user is a guest, it will call [[yii\web\User::loginRequired()]], which may redirect the browser to the login page.
* If the user is a guest, it will call [[yii\web\User::loginRequired()]] to redirect the user browser to the login page.
* If the user is already authenticated, it will throw a [[yii\web\ForbiddenHttpException]].
You may customize this behavior by configuring the [[yii\filters\AccessControl::denyCallback]] property:
You may customize this behavior by configuring the [[yii\filters\AccessControl::denyCallback]] property like the following:
```php
[
'class' => AccessControl::className(),
...
'denyCallback' => function ($rule, $action) {
throw new \Exception('You are not allowed to access this page');
}
@ -95,8 +97,8 @@ empty or not set, it means the rule applies to all controllers.
- `?`: matches a guest user (not authenticated yet)
- `@`: matches an authenticated user
Using other role names requires RBAC (to be described in the next section), and [[yii\web\User::can()]] will be called.
If this option is empty or not set, it means this rule applies to all roles.
Using other role names will trigger the invocation of [[yii\web\User::can()]], which requires enabling RBAC
(to be described in the next subsection). If this option is empty or not set, it means this rule applies to all roles.
* [[yii\filters\AccessRule::ips|ips]]: specifies which [[yii\web\Request::userIP|client IP addresses]] this rule matches.
An IP address can contain the wildcard `*` at the end so that it matches IP addresses with the same prefix.
@ -148,8 +150,7 @@ class SiteController extends Controller
```
Role based access control (RBAC)
--------------------------------
## Role Based Access Control (RBAC) <span id="rbac"></span>
Role-Based Access Control (RBAC) provides a simple yet powerful centralized access control. Please refer to
the [Wikipedia](http://en.wikipedia.org/wiki/Role-based_access_control) for details about comparing RBAC
@ -164,7 +165,7 @@ part is to use the authorization data to perform access check in places where it
To facilitate our description next, we will first introduce some basic RBAC concepts.
### Basic Concepts
### Basic Concepts <span id="basic-concepts"></span>
A role represents a collection of *permissions* (e.g. creating posts, updating posts). A role may be assigned
to one or multiple users. To check if a user has a specified permission, we may check if the user is assigned
@ -180,7 +181,7 @@ and a permission may consist of other permissions. Yii implements a *partial ord
more special *tree* hierarchy. While a role can contain a permission, it is not true vice versa.
### Configuring RBAC Manager
### Configuring RBAC <span id="configuring-rbac"></span>
Before we set off to define authorization data and perform access checking, we need to configure the
[[yii\base\Application::authManager|authManager]] application component. Yii provides two types of authorization managers:
@ -188,7 +189,8 @@ Before we set off to define authorization data and perform access checking, we n
data, while the latter stores authorization data in a database. You may consider using the former if your application
does not require very dynamic role and permission management.
#### configuring authManager with `PhpManager`
#### Using `PhpManager` <span id="using-php-manager"></span>
The following code shows how to configure the `authManager` in the application configuration using the [[yii\rbac\PhpManager]] class:
@ -206,10 +208,11 @@ return [
The `authManager` can now be accessed via `\Yii::$app->authManager`.
> Tip: By default, [[yii\rbac\PhpManager]] stores RBAC data in files under `@app/rbac/` directory. Make sure the directory
and all the files in it are writable by the Web server process if permissions hierarchy needs to be changed online.
By default, [[yii\rbac\PhpManager]] stores RBAC data in files under `@app/rbac` directory. Make sure the directory
and all the files in it are writable by the Web server process if permissions hierarchy needs to be changed online.
#### configuring authManager with `DbManager`
#### Using `DbManager` <span id="using-db-manager"></span>
The following code shows how to configure the `authManager` in the application configuration using the [[yii\rbac\DbManager]] class:
@ -238,7 +241,8 @@ Before you can go on you need to create those tables in the database. To do this
The `authManager` can now be accessed via `\Yii::$app->authManager`.
### Building Authorization Data
### Building Authorization Data <span id="generating-rbac-data"></span>
Building authorization data is all about the following tasks:
@ -333,7 +337,7 @@ For applications that require complex access control with dynamically updated au
(i.e. admin panel) may need to be developed using APIs offered by `authManager`.
### Using Rules
### Using Rules <span id="using-rules"></span>
As aforementioned, rules add additional constraint to roles and permissions. A rule is a class extending
from [[yii\rbac\Rule]]. It must implement the [[yii\rbac\Rule::execute()|execute()]] method. In the hierarchy we've
@ -387,11 +391,12 @@ $auth->addChild($updateOwnPost, $updatePost);
$auth->addChild($author, $updateOwnPost);
```
Now we've got the following hierarchy:
Now we have got the following hierarchy:
![RBAC hierarchy with a rule](images/rbac-hierarchy-2.png "RBAC hierarchy with a rule")
### Access Check
### Access Check <span id="access-check"></span>
With the authorization data ready, access check is as simple as a call to the [[yii\rbac\ManagerInterface::checkAccess()]]
method. Because most access check is about the current user, for convenience Yii provides a shortcut method
@ -403,11 +408,11 @@ if (\Yii::$app->user->can('createPost')) {
}
```
If the current user is Jane with ID=1 we're starting at `createPost` and trying to get to `Jane`:
If the current user is Jane with `ID=1` we are starting at `createPost` and trying to get to `Jane`:
![Access check](images/rbac-access-check-1.png "Access check")
In order to check if user can update post we need to pass an extra parameter that is required by the `AuthorRule` described before:
In order to check if a user can update a post, we need to pass an extra parameter that is required by `AuthorRule` described before:
```php
if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
@ -415,20 +420,21 @@ if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
}
```
Here's what happens if current user is John:
Here is what happens if the current user is John:
![Access check](images/rbac-access-check-2.png "Access check")
We're starting with the `updatePost` and going through `updateOwnPost`. In order to pass it `AuthorRule` should return
`true` from its `execute` method. The method receives its `$params` from `can` method call so the value is
`['post' => $post]`. If everything is OK we're getting to `author` that is assigned to John.
We are starting with the `updatePost` and going through `updateOwnPost`. In order to pass the access check, `AuthorRule`
should return `true` from its `execute()` method. The method receives its `$params` from the `can()` method call so the value is
`['post' => $post]`. If everything is fine, we will get to `author` which is assigned to John.
In case of Jane it is a bit simpler since she's an admin:
In case of Jane it is a bit simpler since she is an admin:
![Access check](images/rbac-access-check-3.png "Access check")
### Using Default Roles
### Using Default Roles <span id="using-default-roles"></span>
A default role is a role that is *implicitly* assigned to *all* users. The call to [[yii\rbac\ManagerInterface::assign()]]
is not needed, and the authorization data does not contain its assignment information.

5
docs/guide/security-best-practices.md

@ -139,10 +139,9 @@ from a user browser are made by the user himself. It could be false.
For example, `an.example.com` website has `/logout` URL that, when accessed using a simple GET, logs user out. As long
as it's requested by the user itself everything is OK but one day bad guys are somehow posting
`<img src="http://an.example.com/logout">` on a forum user visits frequently. Browser doesn't make any difference between
requesting an image or requesting a page so when user opens a page with such `img` tag he's being logged out from
`an.example.com`.
requesting an image or requesting a page so when user opens a page with such `img` tag, the browser will send the GET request to that URL, and the user will be logged out from `an.example.com`.
That's the basic idea. One can say that logging user out is nothing serious. Well, sending POST isn't much trickier.
That's the basic idea. One can say that logging user out is nothing serious, but bad guys can do much more, using this idea. Imagine that some website has an URL `http://an.example.com/purse/transfer?to=anotherUser&amout=2000`. Accessing it using GET request, causes transfer of $2000 from authorized user account to user `anotherUser`. We know, that browser will always send GET request to load an image, so we can modify code to accept only POST requests on that URL. Unfortunately, this will not save us, because an attacker can put some JavaScript code instead of `<img>` tag, which allows to send POST requests on that URL.
In order to avoid CSRF you should always:

2
docs/guide/structure-entry-scripts.md

@ -1,7 +1,7 @@
Entry Scripts
=============
Entry scripts are the first chain in the application bootstrapping process. An application (either
Entry scripts are the first step in the application bootstrapping process. An application (either
Web application or console application) has a single entry script. End users make requests to
entry scripts which instantiate application instances and forward the requests to them.

11
docs/guide/tutorial-core-validators.md

@ -102,7 +102,7 @@ is as specified by the `operator` property.
```
This validator checks if the input value is a date, time or datetime in a proper format.
Optionally, it can convert the input value into a UNIX timestamp and store it in an attribute
Optionally, it can convert the input value into a UNIX timestamp or other machine readable format and store it in an attribute
specified via [[yii\validators\DateValidator::timestampAttribute|timestampAttribute]].
- `format`: the date/time format that the value being validated should be in.
@ -110,10 +110,19 @@ specified via [[yii\validators\DateValidator::timestampAttribute|timestampAttrib
Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the PHP
`Datetime` class. Please refer to <http://php.net/manual/en/datetime.createfromformat.php> on supported formats.
If this is not set, it will take the value of `Yii::$app->formatter->dateFormat`.
See the [[yii\validators\DateValidator::$format|API documentation]] for more details.
- `timestampAttribute`: the name of the attribute to which this validator may assign the UNIX timestamp
converted from the input date/time. This can be the same attribute as the one being validated. If this is the case,
the original value will be overwritten with the timestamp value after validation.
See ["Handling date input with the DatePicker"](widget-jui#datepicker-date-input) for a usage example.
Since version 2.0.4, a format and timezone can be specified for this attribute using
[[yii\validators\DateValidator::$timestampAttributeFormat|$timestampAttributeFormat]] and
[[yii\validators\DateValidator::$timestampAttributeTimeZone|$timestampAttributeTimeZone]].
- Since version 2.0.4 it is also possible to specify a [[yii\validators\DateValidator::$min|minimum]] or
[[yii\validators\DateValidator::$max|maximum]] timestamp.
In case the input is optional you may also want to add a [default value filter](#default) in addition to the date validator
to ensure empty input is stored as `NULL`. Other wise you may end up with dates like `0000-00-00` in your database

5
docs/internals-pt-BR/translation-workflow.md

@ -90,6 +90,8 @@ Regras e Observações
- standalone action — ação standalone
- advanced project template — template avançado de projetos
- basic project template — template básico de projetos
- behaviors — behaviors (comportamentos)
- pretty URL — URL amigável (pretty URL)
### Termos Sem Tradução
@ -107,4 +109,5 @@ Regras e Observações
- backend
- frontend
- web service
- template
- template
- query string

2
docs/internals/translation-status.md

@ -62,7 +62,7 @@ output-data-providers.md | Yes
output-data-widgets.md |
output-theming.md | Yes
security-authentication.md | Yes
security-authorization.md |
security-authorization.md | Yes
security-passwords.md |
security-auth-clients.md |
security-best-practices.md |

2
framework/BaseYii.php

@ -93,7 +93,7 @@ class BaseYii
*/
public static function getVersion()
{
return '2.0.4-dev';
return '2.0.5-dev';
}
/**

8
framework/CHANGELOG.md

@ -1,9 +1,15 @@
Yii Framework 2 Change Log
==========================
2.0.4 under development
2.0.5 under development
-----------------------
- no changes in this release.
2.0.4 May 10, 2015
------------------
- Bug #5042: Use RETURNING for inserts for pgsql and oci to support PKs with a custom default value expression (nineinchnick, klimov-paul)
- Bug #6234: Fixed wrong table schema information for MSSQL when using multiple schemas (nineinchnick)
- Bug #6642: Fixed the bug that using confirmation dialog via `data-confirm` in an `ActiveForm` may cause the dialog to appear twice (pana1990, qiangxue)

1
framework/classes.php

@ -233,6 +233,7 @@ return [
'yii\validators\CompareValidator' => YII2_PATH . '/validators/CompareValidator.php',
'yii\validators\DateValidator' => YII2_PATH . '/validators/DateValidator.php',
'yii\validators\DefaultValueValidator' => YII2_PATH . '/validators/DefaultValueValidator.php',
'yii\validators\EachValidator' => YII2_PATH . '/validators/EachValidator.php',
'yii\validators\EmailValidator' => YII2_PATH . '/validators/EmailValidator.php',
'yii\validators\ExistValidator' => YII2_PATH . '/validators/ExistValidator.php',
'yii\validators\FileValidator' => YII2_PATH . '/validators/FileValidator.php',

2
framework/db/BaseActiveRecord.php

@ -1165,7 +1165,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
if ($relation->via !== null) {
if ($this->getIsNewRecord() || $model->getIsNewRecord()) {
throw new InvalidCallException('Unable to link models: at most one model can be newly created.');
throw new InvalidCallException('Unable to link models: the models being linked cannot be newly created.');
}
if (is_array($relation->via)) {
/* @var $viaRelation ActiveQuery */

2
framework/db/Schema.php

@ -22,6 +22,8 @@ use yii\caching\TagDependency;
* @property string $lastInsertID The row ID of the last row inserted, or the last value retrieved from the
* sequence object. This property is read-only.
* @property QueryBuilder $queryBuilder The query builder for this connection. This property is read-only.
* @property string[] $schemaNames All schema names in the database, except system schemas. This property is
* read-only.
* @property string[] $tableNames All table names in the database. This property is read-only.
* @property TableSchema[] $tableSchemas The metadata for all tables in the database. Each array element is an
* instance of [[TableSchema]] or its child class. This property is read-only.

17
framework/messages/uk/yii.php

@ -17,9 +17,6 @@
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'No help for unknown command "{command}".' => '@@Довідка недоступна для невідомої команди "{command}".@@',
'No help for unknown sub-command "{command}".' => '@@Довідка недоступна для невідомої субкоманди "{command}".@@',
'Unknown command "{command}".' => '@@Невідома команда "{command}".@@',
'(not set)' => '(не задано)',
'An internal server error occurred.' => 'Виникла внутрішня помилка сервера.',
'Are you sure you want to delete this item?' => 'Ви впевнені, що хочете видалити цей елемент?',
@ -43,16 +40,16 @@ return [
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Файл "{file}" занадто великий. Розмір не повинен перевищувати {limit, number} {limit, plural, one{байт} few{байта} many{байт} other{байта}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Файл "{file}" занадто малий. Розмір повинен бути більше, ніж {limit, number} {limit, plural, one{байт} few{байта} many{байт} other{байта}}.',
'The format of {attribute} is invalid.' => 'Невірний формат значення "{attribute}".',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл "{file}" занадто великий. Висота не повинна перевищувати {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл "{file}" занадто великий. Ширина не повинна перевищувати {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл "{file}" занадто малий. Висота повинна бути більше, ніж {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Файл "{file}" занадто малий. Ширина повинна бути більше, ніж {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Зображення "{file}" занадто велике. Висота не повинна перевищувати {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Зображення "{file}" занадто велике. Ширина не повинна перевищувати {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Зображення "{file}" занадто мале. Висота повинна бути більше, ніж {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Зображення "{file}" занадто мале. Ширина повинна бути більше, ніж {limit, number} {limit, plural, one{піксель} few{пікселя} many{пікселів} other{пікселя}}.',
'The requested view "{name}" was not found.' => 'Представлення "{name}" не знайдено.',
'The verification code is incorrect.' => 'Невірний код перевірки.',
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'Всього <b>{count, number}</b> {count, plural, one{запис} few{записи} many{записів} other{записи}}.',
'Unable to verify your data submission.' => 'Не вдалося перевірити передані дані.',
'Unknown option: --{name}' => 'Невідома опція : --{name}',
'Update' => 'Редагувати',
'Update' => 'Оновити',
'View' => 'Переглянути',
'Yes' => 'Так',
'You are not allowed to perform this action.' => 'Вам не дозволено виконувати дану дію.',
@ -72,7 +69,7 @@ return [
'{attribute} is not a valid email address.' => 'Значення "{attribute}" не є правильною email адресою.',
'{attribute} must be "{requiredValue}".' => 'Значення "{attribute}" має бути рівним "{requiredValue}".',
'{attribute} must be a number.' => 'Значення "{attribute}" має бути числом.',
'{attribute} must be a string.' => 'Значення "{attribute}" має бути рядком.',
'{attribute} must be a string.' => 'Значення "{attribute}" має бути текстовим рядком.',
'{attribute} must be an integer.' => 'Значення "{attribute}" має бути цілим числом.',
'{attribute} must be either "{true}" or "{false}".' => 'Значення "{attribute}" має дорівнювати "{true}" або "{false}".',
'{attribute} must be greater than "{compareValue}".' => 'Значення "{attribute}" повинно бути більшим значення "{compareValue}".',
@ -104,7 +101,7 @@ return [
'{nFormatted} TB' => '{nFormatted} Тб',
'{nFormatted} TiB' => '{nFormatted} ТіБ',
'{nFormatted} {n, plural, =1{byte} other{bytes}}' => '{nFormatted} {n, plural, one{байт} few{байта} many{байтів} other{байта}}',
'{nFormatted} {n, plural, =1{gibibyte} other{gibibytes}}' => '{nFormatted} {n, plural, one{гібібайт} few{гібібайта} many{гібібайтів} other{гіибібайта}}',
'{nFormatted} {n, plural, =1{gibibyte} other{gibibytes}}' => '{nFormatted} {n, plural, one{гібібайт} few{гібібайта} many{гібібайтів} other{гібібайта}}',
'{nFormatted} {n, plural, =1{gigabyte} other{gigabytes}}' => '{nFormatted} {n, plural, one{гігабайт} few{гігабайта} many{гігабайтів} other{гігабайта}}',
'{nFormatted} {n, plural, =1{kibibyte} other{kibibytes}}' => '{nFormatted} {n, plural, one{кібібайт} few{кібібайта} many{кібібайтів} other{кібібайта}}',
'{nFormatted} {n, plural, =1{kilobyte} other{kilobytes}}' => '{nFormatted} {n, plural, one{кілобайт} few{кілобайта} many{кілобайтів} other{кілобайта}}',

18
framework/validators/DateValidator.php

@ -15,7 +15,15 @@ use yii\base\InvalidConfigException;
use yii\helpers\FormatConverter;
/**
* DateValidator verifies if the attribute represents a date, time or datetime in a proper format.
* DateValidator verifies if the attribute represents a date, time or datetime in a proper [[format]].
*
* It can also parse internationalized dates in a specific [[locale]] like e.g. `12 мая 2014` when [[format]]
* is configured to use a time pattern in ICU format.
*
* It is further possible to limit the date within a certain range using [[min]] and [[max]].
*
* Additional to validating the date it can also export the parsed timestamp as a machine readable format
* which can be configured using [[timestampAttribute]].
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
@ -39,6 +47,14 @@ class DateValidator extends Validator
* 'php:m/d/Y' // the same date in PHP format
* 'MM/dd/yyyy HH:mm' // not only dates but also times can be validated
* ```
*
* **Note:** the underlying date parsers being used vary dependent on the format. If you use the ICU format and
* the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed, the [IntlDateFormatter](http://php.net/manual/en/intldateformatter.parse.php)
* is used to parse the input value. In all other cases the PHP [DateTime](http://php.net/manual/en/datetime.createfromformat.php) class
* is used. The IntlDateFormatter has the advantage that it can parse international dates like `12. Mai 2015` or `12 мая 2014`, while the
* PHP parser is limited to English only. The PHP parser however is more strict about the input format as it will not accept
* `12.05.05` for the format `php:d.m.Y`, but the IntlDateFormatter will accept it for the format `dd-MM-yyyy`.
* If you need to use the IntlDateFormatter you can avoid this problem by specifying a [[min|minimum date]].
*/
public $format;
/**

Loading…
Cancel
Save