c975l/user-bundle

用户资料管理包,由用户和管理员使用


README

直接灵感来源于 FOSUserBundle,并迁移 c975L/UserFilesBundle,UserBundle 具有以下功能

  • 确保遵守 GDPR 规则,如同意存储数据、导出数据等
  • 在数据库中存储用户信息(使用 doctrine)
  • 为用户提供了多种类型的实体(见下文)
  • 允许扩展这些实体以添加自己的字段
  • 允许用户管理其资料和数据
  • 验证数据,如 Siret、增值税号等
  • 显示注册时的“挑战”(无 Captcha 等)
  • 允许禁用注册(仅用于注册一个或多个用户,然后不再注册)
  • 提供登录、注册、修改资料、更改密码和重置密码的表单
  • 提供公共资料(您可以在配置中禁用它)
  • 允许扩展这些表单
  • 通过 c975LEmailBundle(作为 c975LEmailBundle 提供将电子邮件保存到数据库的可能性,此包中有一个选项不这样做)发送注册和密码重置的电子邮件给用户
  • c975LToolbarBundle 集成
  • 允许通过 HWIOAuthBundle 连接社交网络
  • 提供迁移到 FOSUserBundle 的 sql 脚本
  • 允许显示与电子邮件地址链接的 Gravatar 图片
  • 允许显示与账户链接的社交网络图片
  • 提供 divData 以允许从 JavaScript 访问用户数据
  • 允许轻松覆盖模板或其部分,以将覆盖的文件数量减少到必要数量
  • 允许定义登录尝试的次数,然后添加延迟才能再次登录
  • 重置密码表单将不会发送给不存在账户的电子邮件,同时显示如此,这不允许检查已注册的电子邮件
  • 允许用户在保持账户的同时删除其数据的使用权限,在这种情况下,账户将被标记为未启用
  • 当用户更改(或重置)密码时发送电子邮件,以便在用户没有发起此操作时联系网站
  • 集成一个 API 来以 JSON 格式认证/创建/显示/修改/删除用户

UserBundle 专用网页.

UserBundle API 文档.

包安装

步骤 1:下载包

v3.x 与 Symfony 4.x 兼容。请使用 v2.x 用于 Symfony 3.x。使用 Composer 安装库

    composer require c975l/user-bundle

步骤 2:配置包

检查依赖项的配置

最后,在 /config/packages/security.yml

security:
    encoders:
        #The entity you want to use
        c975L\UserBundle\Entity\User: auto
    role_hierarchy:
        ROLE_MODERATOR: 'ROLE_USER'
        ROLE_ADMIN: [ROLE_MODERATOR, ROLE_USER]
        ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_MODERATOR, ROLE_USER]
    providers:
        c975_l_userbundle:
            entity:
                #The entity you want to use
                class: c975L\UserBundle\Entity\User
    firewalls:
        main:
            pattern: ^/
            provider: c975_l_userbundle
            form_login:
                login_path: user_signin
                check_path: user_signin
                default_target_path: user_dashboard
                csrf_token_generator: security.csrf.token_manager
            remember_me:
                secret: '%secret%'
                lifetime: 31536000
                path: /
                secure: true
            anonymous: true
            logout:
                path: user_signout
                handlers: [c975L\UserBundle\Listener\LogoutListener]

步骤 3:创建 MySql 表

使用 /Resources/sql/user.sql 创建 useruser_archives 表。已注释 DROP TABLE 以避免意外删除。它还将创建一个存储过程 sp_UserArchive()

步骤 4:启用路由

然后,通过将它们添加到您项目的 /config/routes.yaml 文件中启用路由

c975_l_user:
    resource: "@c975LUserBundle/Controller/"
    type: annotation
    prefix: /
    #Multilingual website use the following
    #prefix: /{_locale}
    #defaults:   { _locale: '%locale%' }
    #requirements:
    #    _locale: en|fr|es

步骤 5:将资源安装到 web 文件夹

通过运行来安装资源

php bin/console assets:install --symlink

它将在您的 web 文件夹中创建一个从 Resources/public/ 文件夹的链接。

覆盖模板

强烈建议使用 从第三方包覆盖模板功能 来与您的网站完全集成。

为此,只需在您的应用中创建以下结构 /templates/bundles/c975LUserBundle/,然后在其中复制 layout.html.twig 文件,以覆盖现有的 Bundle 文件,然后应用您需要的更改。

您还可以覆盖

  • /templates/bundles/c975LUserBundle/fragments/deleteAccountInfo.html.twig,这将列出删除账户对用户的影响,显示在删除账户页面中。
  • /templates/bundles/c975LUserBundle/fragments/dashboardActions.html.twig 来添加您自己的操作(或任何内容)到仪表板中,例如。
  • /templates/bundles/c975LUserBundle/fragments/avatar.html.twig 来修改头像的显示(2018年3月26日)

您可以通过 {% include('@c975LUser/fragments/navbarMenu.html.twig') %} 添加一个导航菜单。如果需要,您也可以覆盖它,或者简单地覆盖 /templates/bundles/c975LUserBundle/fragments/navbarMenuActions.html.twig 来在其上方添加操作。

路由

可用的路由如下

  • user_signup
  • user_signup_confirm
  • user_signin
  • user_config
  • user_dashboard
  • user_display
  • user_export
  • user_modify
  • user_change_password
  • user_reset_password
  • user_reset_password_confirm
  • user_signout
  • user_delete
  • user_public_profile

实体

您必须选择与您的需求相关的实体,并在 /config/packages/security.yml 中指定它。可用的实体如下

  • c975L/UserBundle/Entity/UserLight:具有最低要求的轻量级用户
  • c975L/UserBundle/Entity/User:默认用户
  • c975L/UserBundle/Entity/UserAddress:默认用户 + 地址字段
  • c975L/UserBundle/Entity/UserBusiness:默认用户 + 业务/协会字段
  • c975L/UserBundle/Entity/UserSocial:默认用户 + 社交网络字段
  • c975L/UserBundle/Entity/UserFull:默认用户 + 地址 + 业务 + 社交 + 多语言字段

为了帮助您选择,以下列出了字段

轻量级

  • id
  • allow_use
  • identifier
  • email
  • creation
  • enabled
  • salt
  • password
  • token
  • password_request
  • roles

默认

  • gender
  • firstname
  • lastname
  • avatar
  • latest_signin
  • latest_signout
  • locale

地址

  • address
  • address2
  • postal
  • town
  • country
  • phone
  • fax

业务

  • business_type
  • business_name
  • business_address
  • business_address2
  • business_postal
  • business_town
  • business_country
  • business_siret
  • business_vat
  • business_phone
  • business_fax

社交

  • social_network
  • social_id
  • social_token
  • social_picture

您也可以通过以下代码扩展抽象类之一来创建自己的类

<?php
//Your Entity file i.e. src/App/Entity/User.php
namespace App\Entity;

use c975L\UserBundle\Entity\UserAbstract;

class User extends UserAbstract
{
    //Add your properties and methods
}

扩展表单

您可以扩展 UserSignupTypeUserProfileType。要扩展它们,包括新的属性或功能,请使用以下代码

<?php
//Your own form i.e. src/App/Form/UserProfileType
namespace App\Form;

use c975L\UserBundle\Form\UserProfileType as BaseProfileType;

class UserProfileType extends BaseProfileType
{
    //Builds the form
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //You can use the following to disable/enable fields
        $disabled = $options['data']->getAction() == 'modify' ? false : true;

        //Add the fields you need
    }

    public function getParent()
    {
        return 'c975L\UserBundle\Form\UserProfileType';
    }

    public function getBlockPrefix()
    {
        return 'app_user_profile';
    }
}

然后您必须将其添加为服务到您的 app/config/services.yml

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: true
    App\Form\:
        resource: '../../src/App/Form/*'

最后,您必须在您的 app/config/config.yml 中设置它

c975_l_user:
    signupForm: 'App\Form\UserSignupType'
    profileForm: 'App\Form\UserProfileType'

事件

有多个事件被触发以帮助您满足需求,它们都在 Event\UserEvent.php 中定义。例如,如果您需要在删除用户之前执行任务,您可以创建一个类似的监听器

<?php

namespace App\Listener;

use c975L\UserBundle\Entity\UserAbstract;
use c975L\UserBundle\Event\UserEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class UserDeleteListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            UserEvent::USER_DELETE => 'userDelete',
        );
    }

    public function userDelete($event)
    {
        $user = $event->getUser();

        if ($user instanceof UserInterface) {
            //Do your stuff...

            //Use the following is you want to stop propagation of the Event, any following instructions will be stopped
            //$event->stopPropagation();
        }
    }
}

服务

您可以将 c975L\UserBundle\Service\UserServiceInterface 注入以访问其方法。例如,您可以使用其 id、email、socialId 等检索用户

//Within a controller
use c975L\UserBundle\Service\UserServiceInterface;

    public function yourAction(UserServiceInterface $userService)
    {
        //With Id
        $user = $userService->findUserById(USER_ID);

        //With Email
        $user = $userService->findUserByEmail(USER_EMAIL);

        //With Identifier
        $user = $userService->findUserByIdentifier(USER_IDENTIFIER);

        //With SocialId
        $user = $userService->findUserBySocialId(USER_SOCIAL_ID);
    }

登录/注销链接

如果您想在页脚中插入登录/注销链接,例如,您可以通过以下代码实现

{# Sign in/Sign out #}
<p class="text-center">
    {% include '@c975LUser/fragments/signinSignout.html.twig' %}
</p>

用户 div 数据供javascript使用

如果您想插入包含用户数据的div,并用于javascript,您可以通过Twig扩展来实现。

{# User DivData #}
{{ user_divData() }}

然后您可以通过以下方式访问它:

$(document).ready(function() {
    var firstname = $('#user').data('firstname');
});

查看它以了解所覆盖的属性。

登录后自定义重定向

如果您想重定向到特定页面,可以使用以下代码中的请求参数

//In a Controller file
return $this->redirectToRoute('user_signin', array('_target_path' => 'THE_ABSOLUTE_OR_RELATIVE_URL_TO_REDIRECT_TO'));

用户头像

您可以通过调用要放置的位置的Twig扩展来显示与用户账户关联的头像(如果已在config.yml中启用)

{{ user_avatar() }}
{# Or with specifying its size, 128 by default #}
{{ user_avatar(64) }}

Twig扩展

您可以使用Twig扩展来格式化VAT和Siret号码。

{{ 'YOUR_VAT_NUMBER'|user_vat }}
{{ 'YOUR_SIRET_NUMBER'|user_siret }}

使用HwiOauth(社交网络登录)

在登录表单中,您可以通过HWIOAuthBundle添加链接以通过社交网络登录/注册。如果您想使用此功能,只需在您的/config/config_bundles.yaml中添加c975L\ConfigBundle并清除缓存,以下内容

c975LUser:
    hwiOauth: ['facebook', 'google', 'live']
    social: true

然后在您的/config/services.yaml中,以下内容

services:
    c975L\UserBundle\Security\OAuthUserProvider:
        public: true

c975L/UserBundle不实现与社交网络的连接,而是提供与HWIOAuthBundle的桥梁。为了在登录页面上显示按钮并将用户存储在数据库中,您必须自行配置HWIOAuthBundle。 这主要涉及在配置文件中设置不同的信息。以下是一个示例,用于Facebook,但其他网络将以相同的方式工作

#routes.yaml
hwi_oauth_redirect:
    resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
    prefix:   /connect
hwi_oauth_connect:
    resource: "@HWIOAuthBundle/Resources/config/routing/connect.xml"
    prefix:   /connect
hwi_oauth_login:
    resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
    prefix:   /login
facebook_login:
    path: /login/facebook
#parameters.yml
#As a Best Practice, it is preferable to declare your secret parameters in parameters.yml file in place of config.yml.
#Then you can re-use them with "%facebook_app_id%".
parameters:
    facebook_app_id: 'YOUR_FACEBOOK_APP_ID'
    facebook_app_secret: 'YOUR_FACEBOOK_APP_SECRET'
#parameters.yml.dist
parameters:
    facebook_app_id: ~
    facebook_app_secret: ~

您必须声明account_connector c975L\UserBundle\Security\OAuthUserProvider

#config.yml
hwi_oauth:
    connect:
        confirmation: true
        account_connector: c975L\UserBundle\Security\OAuthUserProvider
    firewall_names: [main]
    resource_owners:
        facebook:
            type: facebook
            client_id: "%facebook_app_id%"
            client_secret: "%facebook_app_secret%"
            scope: "email"
            options:
                csrf: true
                display: popup

您必须声明oauth_user_provider c975L\UserBundle\Security\OAuthUserProvider

#security.yml
security:
    #...
    firewalls:
        main:
            oauth:
                resource_owners:
                    facebook: "/login/facebook"
                login_path: user_signin
                failure_path: user_signin
                use_forward: true
                default_target_path: user_dashboard
                oauth_user_provider:
                    service: c975L\UserBundle\Security\OAuthUserProvider

社交网络图片

c975L/UserBundle为一些社交网络提供了图片,当您安装资源时,它们被链接到您的web文件夹中(见上面)。如果您想使用的网络还没有图片,您可以使用文件`Resources/SocialNetwork/signin.svg``来创建一个,并创建一个PR将其添加到捆绑包中 :-)

您还可以覆盖Resources/views/fragments/socialNetworkImage.html.twig以使用您自己的图片集或更改使用的样式。

作为“Bonus”,如果用户已使用其电子邮件地址注册,然后使用社交网络进行登录,它将获得其现有用户账户,IF 电子邮件地址相同,否则,它将创建另一个账户。

在已经使用不同的社交网络注册后,再次使用另一个社交网络进行注册,将替换当前的账户。

从FOSUserBundle迁移

如果您想从FOSUserBundle迁移,您必须执行以下操作

从composer中删除

composer remove friendsofsymfony/user-bundle

使用Resources\sql\MigrateFosUser.sql迁移您的数据库表。它将创建一个user_migrate表,将修改所有需要的字段,将添加缺失的字段,然后,当您准备就绪时,您可以将FOSUSerBundle表重命名为user_fosuserbundle(或您想要的任何名称)并将user_migrate重命名为user字段usernamegroups被保留但不使用,因此如果您不使用它们,您可以删除它们。

API文档

您还可以使用c975LUserBundle提供的API,以下内容

您必须使用https://github.com/lcobucci/jwt(需要openssl扩展)。

然后创建您的RSA密钥

cd <your_root_project_dir>;
mkdir -p config/jwt;
openssl genrsa -out config/jwt/private.pem -aes256 4096;
#If it requires passPhrase then enter one and un-comment and run the following
#openssl rsa -in config/jwt/private.pem -out config/jwt/private2.pem;
#mv config/jwt/private.pem config/jwt/private.pem-back;
#mv config/jwt/private2.pem config/jwt/private.pem;
#rm config/jwt/private.pem-back;
openssl rsa -pubout -in config/jwt/private.pem -out config/jwt/public.pem;

将这些路径添加到/config/config_bundles.yaml或使用c975L\ConfigBundle

c975LUser:
    privateKey: 'config/jwt/private.pem'
    publicKey: 'config/jwt/public.pem'
    api: true
    apiOnly: true #If you wish to only use API and not the web forms

在您的security.yaml中定义JSON端点

security:
    firewalls:
        main:
            json_login:
                check_path: user_api_authenticate
            anonymous: true
            guard:
                authenticators:
                    - c975L\UserBundle\Security\TokenAuthenticator

然后您可以使用不同的路由

除了user_api_createuser_api_authenticate之外,您需要将JWT(通过user_api_authenticate获得)发送到头部Authorization: Bearer <token>(推荐)或发送到头部X-AUTH-TOKEN: <token>,用于所有API路由请求。

/user/api/create

methods={"HEAD", "POST"}. 创建用户时,通过调用POST请求中的路由user_api_create,并传递用户实体所需的数据表单字段(见上文)。字段emailplainPassword是必填项,其他字段如果方法存在则将添加到实体中。您还需要添加一个字段apiKey,该字段由sha1($email . apiPassword)组成,其中apiPassworduser_config路由中定义。还建议定义CORS访问。

/user/api/authenticate

methods={"HEAD", "POST"}. 要进行认证,调用user_api_authenticate路由,通过在POST请求中使用JSON体{"username": "<email>", "password": "<password>"},并设置头部Content-Type: application/json,您将收到一个令牌。您可以通过在发送的JSON数据中添加"expiration": <delay_inseconds>来设置JWT的过期时间。

/user/api/display/{identifier}

methods={"HEAD", "GET"}, {identifier} -> [0-9a-z]{32}. 显示用户时,调用user_api_display路由,通过GET请求,并使用用户的identifier。JWT中定义的用户必须具有在user_config路由中配置的足够权限,或者就是用户本人。

/user/api/list[?page=1&size=50]

methods={"HEAD", "GET"}. 要列出用户,调用user_api_list路由,通过GET请求。您可以使用查询参数page(默认1)来定义要显示的页码,以及使用size(默认50)来定义要显示的记录数。JWT中定义的用户必须具有在user_config路由中配置的足够权限。

/user/api/search/{term}[?page=1&size=50]

methods={"HEAD", "GET"}, {term} -> [0-9a-zA-Z]+. 在用户中进行搜索时,调用user_api_search路由,通过GET请求,并使用搜索的term,该term将与用户实体的电子邮件字段匹配为%term%。您可以使用查询参数page(默认1)来定义要显示的页码,以及使用size(默认50)来定义要显示的记录数。JWT中定义的用户必须具有在user_config路由中配置的足够权限。

/user/api/modify/{identifier}

methods={"HEAD", "PUT"}, {identifier} -> [0-9a-z]{32}. 要修改用户,通过在PUT请求中调用user_api_modify路由,并使用用户identifier和请求体中的数据字段(例如{"email": "mail@example.com"}),所需的用户实体字段(见上文)。JWT中定义的用户必须具有在user_config路由中配置的足够权限,或者就是用户本人。

/user/api/delete/{identifier}

methods={"HEAD", "DELETE"}, {identifier} -> [0-9a-z]{32}. 要删除用户,通过在DELETE请求中调用user_api_delete路由,并使用用户的identifier。如果已在配置参数中定义,则用户将被存档。JWT中定义的用户必须具有在user_config路由中配置的足够权限,或者就是用户本人。

/user/api/add-role/{identifier}/{role}

methods={"HEAD", "PUT"}, {identifier} -> [0-9a-z]{32}, {role} -> [a-zA-Z\_]+. 要向用户添加角色,通过在PUT请求中调用user_api_add_role路由,并使用用户identifier和要分配的角色role。JWT中定义的用户必须具有在user_config路由中配置的足够权限。

/user/api/delete-role/{identifier}/{role}

methods={"HEAD", "PUT"}, {identifier} -> [0-9a-z]{32}, {role} -> [a-zA-Z\_]+. 要删除用户的角色,通过在PUT请求中调用user_api_delete_role路由,并使用用户identifier和要删除的角色role。JWT中定义的用户必须具有在user_config路由中配置的足够权限。

/user/api/modify-roles/{identifier}

methods={"HEAD", "PUT"}{identifier} -> [0-9a-z]{32}。要修改用户的角色,请通过一个 PUT 请求调用 user_api_modify_roles 路由,并在请求体中包含用户的 identifier 和角色数组,例如 {"roles": ["ROLE_ADMIN", "ROLE_USER"]}。JWT 中定义的用户必须拥有足够的权限,权限配置在 user_config 路由中。

/user/api/change-password

methods={"HEAD", "PUT"}。要更改指定用户的密码,请通过一个包含 plainPassword 数据字段的 PUT 请求调用 user_api_change_password 路由,例如 {"plainPassword": "BrandNewPass*$1"}。只有 JWT 中定义的用户可以更改其密码。

/user/api/reset-password & /user/api/reset-password-confirm

methods={"HEAD", "PUT"}。要重置指定用户的密码,请通过一个包含 email 字段的数组调用 user_api_reset_password 路由的 PUT 请求,例如 {"email": "email@example.com"},您将收到一个令牌及其有效期(2小时后)。然后,为了确认(并更改)密码,您必须通过包含 plainPassword 数据字段的请求调用 user_api_reset_password_confirm 路由,例如 /user/api/reset-password-confirm/{token}

/user/api/export

methods={"HEAD", "GET"}。要导出用户数据,请通过一个 GET 请求调用 user_api_export 路由。只有 JWT 中定义的用户可以访问其数据。如果您想添加数据,可以监听 UserEvent::API_USER_EXPORT 并更新用户,或者您可以通过在 EventListener 中使用以下方法来导出您自己的格式化数据

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\UserInterface;

class UserListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            UserEvent::API_USER_EXPORT => 'userApiExport',
        );
    }

    public function userApiExport($event)
    {
        $response = null;
        $user = $event->getUser();
        if ($user instanceof UserInterface) {
            $userFormattedData = array();

            $response = new Response(json_encode($userFormattedData));
            $response->headers->set('Content-Type', 'application/json');
        }

        $event
            ->setResponse($response)
            ->stopPropagation()
        ;
    }
}

如果这个项目 帮助您减少了开发时间,您可以通过顶部“赞助”按钮赞助我 :)