njeaner/symfrop

一个 Symfony 前端角色权限包。此包允许网站管理员管理用户角色权限

0.2 2022-10-18 11:29 UTC

This package is auto-updated.

Last update: 2024-09-13 00:30:46 UTC


README

一个 Symfony 前端角色权限包。此包允许网站管理员管理用户角色和权限。

内容

一些页面截图

安装

在安装此包之前,将此配置复制到您 symfony 项目中的 config/packages/symfrop.yaml 文件中

symfrop_bundle:

  resources_info:
    App/Controller:  '%kernel.project_dir%/src/Controller'

  entities:
    entity:
      user_entity: 'Njeaner\Symfrop\Entity\User'
      role_entity: 'Njeaner\Symfrop\Entity\Role'
      action_entity: 'Njeaner\Symfrop\Entity\Action'
    form: 
      role_form: 'Njeaner\Symfrop\Form\RoleType'
      action_form: 'Njeaner\Symfrop\Form\ActionType'
      user_role_form: 'Njeaner\Symfrop\Form\UserRoleType'

  app_roles:
    ROLE_USER: 'user'
    ROLE_ADMIN: 'admin'
    ROLE_SUPERADMIN: ['root', false]

当配置文件复制到 config/packages/symfrop.yaml 中时,然后使用以下命令安装包

composer require  njeaner/symfrop

包安装后,将此代码复制到 config/routes/attributes.yaml

controllers:
   resource: '@SymfropBundle/Controller/'
   type: attribute

并使用此命令生成 Symfrop 用户、角色和动作实体

php bin\console symfrop:entities [entities-folder]

或此命令

symfony console symfrop:entities [entities-folder]

可选的 [entities-folder] 参数是包含您的认证实体的文件夹。如果此参数缺失,实体将生成在 src/Entity/ 目录中。例如,"php bin\console symfrop:entities Auth" 命令将在 src/Entity/Auth/ 目录中生成 symfrop 实体。

现在在您的 config/packages/symfrop.yaml 中,将以下行更改为此

    user_entity: 'Njeaner\Symfrop\Entity\User'
    role_entity: 'Njeaner\Symfrop\Entity\Role'
    action_entity: 'Njeaner\Symfrop\Entity\Action'

通过此

    user_entity: 'App\Entity[\entities-folder]\User'
    role_entity: 'App\Entity[\entities-folder]\Role'
    action_entity: 'App\Entity[\entities-folder]\Action'

示例

    user_entity: 'App\Entity\Auth\User'
    role_entity: 'App\Entity\Auth\Role'
    action_entity: 'App\Entity\Auth\Action'

或如果实体直接生成在 src/Entity 目录中

    user_entity: 'App\Entity\User'
    role_entity: 'App\Entity\Role'
    action_entity: 'App\Entity\Action'

注意:您不必使用 symfrop 命令生成实体,此命令是一种简单地生成所有所需实体的方法。symfrop 包使用三个核心实体

  • 一个用户实体,表示应用程序用户,此实体必须实现 Njeaner\Symfrop\Entity\Contract\UserInterface,它扩展了 symfony 用户接口;
  • 一个角色实体,定义在应用程序中使用的不同类型的角色,此实体必须实现 Njeaner\Symfrop\Entity\Contract\RoleInterface。默认角色有
    1. ROLE_USER(一个简单用户角色),
    2. ROLE_ADMIN(一个管理员角色),
    3. ROLE_SUPERADMIN(具有所有特权的根角色)。
  • 一个动作实体,定义应用程序中所有用户操作,此实体必须实现 Njeaner\Symfrop\Entity\Contract\ActionInterface。每个 symfony 控制器操作都是一个 symfrop 操作,可以使用 symfrop 类和方法属性进行指定。

如何使用它?

定义 symfrop 用户操作

symfrop 包使用控制器类和方法属性来定义应用程序中的用户操作和权限。可以使用两个属性来定义控制器操作

  • Njeaner\Symfrop\Core\Annotation\Route,它是 Symfony\Component\Routing\Annotation\Route 的扩展,为 symfrop 包添加了一些属性。当使用此属性时,不需要使用更多 symfony 路由属性,因为它接受所有 symfony 路由属性属性以及 symfrop 属性属性。
  • Njeaner\Symfrop\Core\Annotation\RouteAction。此属性必须与 symfony 路由属性结合使用。因此,任何 symfony 控制器操作都必须包含两个方法属性实例:一个 Symfony\Component\Routing\Annotation\Route 用于定义 symfony 路由和一个 Njeaner\Symfrop\Core\Annotation\RouteAction 用于定义 symfrop 用户操作。

symfrop 属性有

  • name(必需):用于定义操作名称
  • title(可选):用于定义操作标题,如果值缺失,则使用名称值
  • target(可选):字符串或数组值,用于定义与定义的操作关联的角色。
  • isUpdatable(默认:true):定义是否允许动作更新。
  • hasAuth(默认:true):定义控制器动作是否可以通过symfrop包进行身份验证。没有symfrop属性的动作不能通过此包进行身份验证。
  • isIndex(默认:false):指定动作是否是索引动作。
  • updatedRole(默认:false):当属性目标值更改时使用。允许更新数据库角色对应关系。
  • isUpdated(默认:false):当(某)属性属性值更改时使用。允许更新数据库值。
  • actionCondition(默认:null):在授权检查期间要检查的补充条件。
  • conditionOption:与actionCondition属性一起使用,以指定actionCondition是否将覆盖授权检查,还是与它结合。Njeaner\Symfrop\Core\Annotation\RouteAction属性只接受这些属性。Njeaner\Symfrop\Core\Annotation\Route属性将这些属性与Symfony\Component\Routing\Annotation\Route属性属性结合使用,以在指定的时间定义symfony路由动作和symfrop用户动作。一个简单示例
namespace App\Controller\Auth;

use App\Repository\Auth\UserRepository;
use Njeaner\Symfrop\Core\Annotation\Route ;
use Njeaner\Symfrop\Core\Service\CONSTANTS;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

#[Route('/auth/user/{_locale<fr|en|es|pt>?en}', requirements: ['_locale' => 'fr|en|es'])]
class UserController extends AbstractController
{
    // path, name, methods are for symfony routing. name, target, isIndex are for symfrop user action.
    #[Route(path: '', name: 'app_auth_user_index', methods: ['GET'], target: CONSTANTS::ROLE_ALL, isIndex: true)]
    public function index(UserRepository $userRepository): Response
    {
        return $this->render('auth/user/index.html.twig', [
            'users' => $userRepository->findAll(),
        ]);
    }
}

检查 symfrop 用户操作

symfrop授权在kernel.request事件和控制器实例化之前进行检查。该包使用当前路由名称和当前安全用户来检查动作授权。

在控制器中检查

有时我们可能需要在控制器动作中检查某些路由是否受授权。

//...
use Njeaner\Symfrop\Core\Manager\AnnotationManager;
class UserController extends BaseAppController
{
    // path, name, methods are for symfony routing. name, target, isIndex are for symfrop user action.
    #[Route(path: '', name: 'app_auth_user_index', methods: ['GET'], target: CONSTANTS::ROLE_ALL, isIndex: true)]
    public function index(UserRepository $userRepository, AnnotationManager $am): Response
    {
        if($am->isAuthorize('some-route-name')){ // return true or false
            // do some action;
        }
        return $this->render('auth/user/index.html.twig', [
            'users' => $userRepository->findAll(),
        ]);
    }
}

在 twig 模板中检查

在twig模板中检查用户动作授权可以显示或隐藏链接、表单,这取决于用户动作权限。例如,仅对具有编辑用户信息权限的管理员显示编辑用户信息链接或表单。

Symfrop包提供三种在twig模板中检查用户动作授权的方法。

  • create_symfrop_link函数,允许创建链接。使用此twig函数,只有在当前用户有处理此链接的动作权限时才会生成链接。它接受2到4个参数。

    1. 必需的第一个参数(类型为字符串)是路由名称。
    2. 必需的第二个参数(类型为字符串或两个字符串的数组)是链接标签。如果是一个数组参数,第一个数组项将是链接标签,第二个数组项将是链接未生成时显示的文本。
    3. 可选的第三个参数是生成链接href的参数。
    4. 可选的最后参数是添加一些html标签属性到链接中,如class、id、title、style等。

    示例

    {{ create_symfrop_link(
        'my_route_name',
        'link_label', {# or ['link_label', 'default_label'] #}
        {'param': 'param_value'},
        {'class': 'btn btn-primary', 'title': 'link_title'}
    ) }}    
  • symfrop标签,允许仅在用户获得动作权限时渲染块。这对于仅当用户有处理表单动作的权限时渲染表单很有用。例如,仅对有权限编辑用户信息的管理员显示编辑用户信息表单。symfrop标签有一个else标签,允许在用户没有权限处理指定动作时渲染其他内容。

示例

{% symfrop route_name %}
 {# show some block #}
{% endsymfrop %}

{# or #}

{% symfrop route_name %}
{# show some block #}
{% else %}
{# show other block  #}
{% endsymfrop %}
  • is action autorized标签,允许检查用户是否获得动作路由权限。

示例

{% if route_name is authorized action %}
 {# show some block #}
{% endsymfrop %}

{# or #}

{% symfrop route_name %}
{# show some block #}
{% else %}
{# show other block  #}
{% endsymfrop %}

在 Symfrop 包中翻译

Symfrop包提供一些twig函数来处理翻译。

  • __函数是symfrop基本区域翻译函数。
  • __u__U函数是ucfirst区域翻译函数。
  • __t__T是symfony title过滤器的衍生。

用法示例

    __('name') {# will return: "name" if request locale is english(en), "nom" if french(fr) or "nombre" if request locale is spanish(es)  #}

生成实体 CRUD

Symfrop包提供了一个symfony等效的make:crud命令,可以轻松创建一个crud,它使用Njeaner\Symfrop\Annotations\RouteAction方法属性、包含区域翻译的表单以及带有symfrop动作链接和表单权限检查的视图。

使用php命令生成symfrop crud

php bin/console symfrop:crud

覆盖默认 symfrop 控制器方法操作

Symfrop包默认使用七个(07)控制器方法来管理默认包动作。这些是

  • njeaner_symfrop_role_index显示所有定义的角色;
  • njeaner_symfrop_user_index显示应用程序中所有用户的角色;
  • njeaner_symfrop_role_create用于角色创建;
  • njeaner_symfrop_role_update 用于角色编辑;
  • njeaner_symfrop_role_delete 用于删除角色;
  • njeaner_symfrop_user_role_edit 用于编辑用户角色;
  • njeaner_symfrop_action_edit 用于编辑用户行为。

要覆盖这些行为之一或全部,您只需创建一个具有相同 symfony 路由属性名和相同 symfrop 属性名的 symfony 控制器方法。

例如

use Njeaner\Symfrop\Core\Annotation\RouteAction;

class MyCostumActionController{

    /*This will override default njeaner_symfrop_role_index that list all role list*/

    #[RouteAction(name: 'njeaner_symfrop_role_index')]
    public function roleIndex(){
        return $this->getRoleRepostory()->findAll();
    }
}

注入顶部或/和底部导航栏、样式表标签和脚本标签

symfrop 包允许在包默认视图中注入顶部和底部导航栏、样式表和脚本标签。这允许在所有应用程序(包括 symfrop 视图)中具有相同的导航栏。这种注入必须在 config/packages/symfrop.yaml 中配置,在 templates 部分如下

templates: 
    navbar_top: my_top_navbar_file.html
    navbar_bottom: my_bottom_navbar_file.html
    scripts: ['my_first_script.js', 'my_other_script.js']
    stylesheets: ['my_first_style.css', 'my_other_style.css']

注意:每个部分都是可选的。您只需注入其中之一。

更改默认 symfrop 样式值

以下列出了所有 symfrop 自定义 CSS 类及其值。如果您想覆盖一些类的值,可以在自定义 CSS 样式文件中做到。通过使用您的浏览器检查 symfrop 视图页面,您可以确定要覆盖哪些类值。

            .symfrop-container{
                margin: 8px;
                padding: 8px;
                display: flex;
                justify-content: center; 
                flex-direction: column;
                padding-top: 40px;
                padding-bottom:60px;
            }

            .symfrop-row{
                display: flex;
                align-items: stretch;
                justify-content: space-between;
                flex-wrap: wrap;
            }
            
            .symfrop-col{
                padding: 4px;
                margin: 4px;
                width: 100%;
            }

            .symfrop-col-4{
                padding: 4px;
                margin: 4px;
                width: 25vw;
            }

            .symfrop-col-3{
                padding: 4px;
                margin: 4px;
                width: 30.5vw;
            }

            .symfrop-width-3{
                width: 30.5vw;
            }

            .symfrop-width-4{
                width: 25vw;
            }

            .symfrop-width-2{
                width: 50vw;
            }
            
            .symfrop-bg-dark{
                background-color: rgb(26, 26, 32);
            }
            
            .symfrop-form{
                width: 40vw;
                padding: 5px;
                padding: 10px;
                background-color: rgba(26, 100, 32, 0.4);
            }
            
            .symfrop-form-group{
                margin: 10px;
            }
            
            .symfrop-form-group > ul {
                color: red;
                padding-top: 0;
                padding-bottom: 0;
                margin-top: 0;
                margin-bottom: 0;
            }

            .symfrop-card{
                width: 100%;
                background-color: rgba(26, 100, 32, 0.4);
                min-height: 50px;
                border-radius: 5px;
                position: relative;
            }

            .symfrop-card-body{
                padding: 2px;
                min-height: 40px;
            }

            .symfrop-card-title{
                font-size: 1.2rem;
                padding: 8px;
                background-color: #50cece;
                border-radius: 5px 5px 0px 0px;

            }

            .symfrop-card-footer{
                font-size: 1.2rem;
                padding: 4px;
                border-radius: 0px 0px 5px 5px;
                min-height: 30px;
                display: flex;
                justify-content: center;
            }

            .symfrop-card-footer a{
                text-decoration: none;
            }
            
            .symfrop-display-block{
                display:block;
            }

            a{
                text-decoration: none;
            }
            
            .symfrop-input {
                width: 100%;
                height: 1.2rem;
                border-radius: 5px;
            }

            .symfrop-btn{
                min-width: 80px;
                min-height: 20px;
                border-radius: 4px;
                padding: 5px;
                border: 1px solid grey;
                background-color: grey;
            }
            
            .symfrop-btn:hover, input:hover{
                opacity: 0.7;
            }
            
            .symfrop-btn.symfrop-btn-primary{
                background-color: rgb(0, 150, 200);
                color: white;
            }

            .symfrop-btn.symfrop-btn-success{
                background-color: rgb(0, 150, 20);
                color: white;
            }

            .symfrop-btn.symfrop-btn-danger{
                background-color: rgb(200, 50, 0);
                color: white;
            }
            
            .symfrop-text-white{
                color: white;
            }
            .symfrop-text-center{
                text-align: center;
            }

            .symfrop-text-left{
                text-align: left;
            }
            .symfrop-text-right{
                text-align: right;
            }
            th, td{
                padding: 2px;
            }

            .symfrop-flex{
                display: flex;
            }
            .symfrop-flex-center{
                align-items: center;
                justify-content: center;
            }

            .symfrop-alert{
                margin: 4px;
                padding: 8px;
                border-radius: 5px;
                background-color: #cacaca;
                color: white;
                text-align: center;
            }
            .symfrop-alert.error{
                background-color: rgba(186, 86, 86, 0.7);
            }

            .symfrop-alert.symfrop-success{
                background-color: rgba(86, 186, 86, 0.7);
            }