andrewdwallo/filament-companies

专为 Filament 设计的综合 Laravel 认证和授权系统,专注于多租户公司管理。


README

gif (1)

FILAMENT 3.x Packagist Downloads

Filament Companies

专为 Filament 设计的综合多租户认证和授权解决方案,侧重于基于公司的租户。

  • 🔥 Socialite
  • 🔥 条款和隐私政策
  • 🔥 通过电子邮件重置密码
  • 🔥 个人资料管理
  • 🔥 浏览器会话管理
  • 🔥 Sanctum
  • 🔥 公司管理
  • 🔥 通过电子邮件邀请员工
  • 🔥 角色与权限

入门

安装面板构建器后,请确保您已使用以下命令创建了一个面板:

php artisan filament:install --panels

📝 如果您已遵循面板构建器的文档,您应该已经完成了此操作。

安装

安装包

composer require andrewdwallo/filament-companies

执行以下 Artisan 命令以生成应用程序。您将需要选择安装 基本包 或启用 Socialite 支持。

php artisan filament-companies:install

运行迁移

php artisan migrate:fresh

准备您的应用程序

创建一个主题

安装后,将为您的应用程序注册一个公司面板。它位于 FilamentCompaniesServiceProvider.php 文件中。

为了使 Tailwind 处理此包和公司面板中使用的 CSS,必须有一个用户 创建一个自定义主题

要为公司面板创建一个自定义主题,可以使用以下命令:

php artisan make:filament-theme company

🛠️ 请按照控制台中的说明完成设置过程

以下是运行命令后应显示的说明参考:

⇂ First, add a new item to the `input` array of `vite.config.js`: `resources/css/filament/company/theme.css`  
⇂ Next, register the theme in the company panel provider using `->viteTheme('resources/css/filament/company/theme.css')`  
⇂ Finally, run `npm run build` to compile the theme

在为公司面板创建自定义主题的过程完成后,将此包的 vendor 目录添加到应用程序中位于 resources/css/filament/company/ 目录的 tailwind.config.js 文件的内容数组中。

export default {
    content: [
        './resources/**/*.blade.php',
        './vendor/filament/**/*.blade.php',
        './vendor/andrewdwallo/filament-companies/resources/views/**/*.blade.php', // The package's vendor directory
    ],
    // ...
}

用户面板

如您所注意到的,安装后,将为您的应用程序注册一个公司面板。为了使此包工作,您还必须有一个包含个人资料页面和个人访问令牌页面的 "用户" 面板。

在此示例中,我将使用 Filament 在安装面板构建器时提供的默认面板,即 "Admin" 面板。

在您的 "Admin" 面板中,请确保注册以下页面:

use Wallo\FilamentCompanies\Pages\User\PersonalAccessTokens;
use Wallo\FilamentCompanies\Pages\User\Profile;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->pages([
            Profile::class,
            PersonalAccessTokens::class,
        ])
}

🛑 您可以按照 创建新面板 的文档创建一个单独的用户面板

您必须提供一种方式,让您的用户可以导航到个人资料和个人访问令牌页面。

还允许您的用户导航回公司面板也是一个明智的选择。

以下是一些指导方针:

use Filament\Navigation\MenuItem;
use Filament\Navigation\NavigationItem;
use Illuminate\Support\Facades\Auth;
use Wallo\FilamentCompanies\Pages\User\PersonalAccessTokens;
use Wallo\FilamentCompanies\Pages\User\Profile;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->userMenuItems([
            'profile' => MenuItem::make()
                ->label('Profile')
                ->icon('heroicon-o-user-circle')
                ->url(static fn () => url(Profile::getUrl())),
            MenuItem::make()
                ->label('Company')
                ->icon('heroicon-o-building-office')
                ->url(static fn () => url(Pages\Dashboard::getUrl(panel: 'company', tenant: Auth::user()->personalCompany()))),
        ])
        ->navigationItems([
            NavigationItem::make('Personal Access Tokens')
                ->label(static fn (): string => __('filament-companies::default.navigation.links.tokens'))
                ->icon('heroicon-o-key')
                ->url(static fn () => url(PersonalAccessTokens::getUrl())),
        ])
}

您可以使用面板的 id 来更改用于用户面板的值

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->userPanel('user')
            )
    }
}

🚧 确保创建一个具有您传递的 id 的面板

默认面板

如果您希望用户直接从Laravel欢迎页面访问公司面板的注册或登录页面,请确保在Filament中将公司面板设置为默认。这涉及两个关键步骤:

  1. 移除默认的用户面板:确保用户面板或任何之前设置为默认的面板不使用->default()方法。
  2. 将公司面板设置为默认:将->default()方法应用于您的公司面板配置,使其成为默认入口点。

通过将公司面板设置为默认,Laravel欢迎页面上的注册或登录链接将直接引导到公司面板的认证页面。

翻译和视图

如果您希望翻译该包,可以使用以下方法发布语言文件:

php artisan vendor:publish --tag=filament-companies-translations

如果您想自定义视图,可以使用以下方法发布它们:

php artisan vendor:publish --tag=filament-companies-views

使用和配置

切换当前公司

当应用程序需要为当前请求设置租户时,Filament会触发一个内置事件。此事件是Filament\Events\TenantSet。如果您想启用或禁用切换当前公司的能力,可以在FilamentCompaniesServiceProvider类中使用switchCurrentCompany()方法。

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->switchCurrentCompany()
            );
    }
}

配置个人资料功能

您可以有选择地启用或禁用某些个人资料功能。如果您选择省略某个功能,则默认将其视为禁用(false)。

为此,修改您的FilamentCompaniesServiceProvider类,如下所示:

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->updateProfileInformation()  // Enables updating profile information
                    ->updatePasswords()           // Enables password updates
                    ->setPasswords()              // Enables setting passwords only if Socialite is enabled
                    ->connectedAccounts()         // Enables connected account management only if Socialite is enabled
                    ->manageBrowserSessions()     // Enables browser session management
                    ->accountDeletion()           // Enables account deletion
            );
    }
}

自定义组件

通过用自己的自定义组件替换默认组件,来个性化您的应用程序。这是通过将自定义组件的类名传递给相关方法的组件参数来实现的。

重要:您的自定义组件必须有一个唯一的类名。这对于防止冲突并确保正常功能至关重要,因为Livewire主要根据组件的类名来区分组件。即使您的自定义组件位于不同的命名空间中,如果与包中的组件具有相同的类名,也可能导致意外的错误和行为。

以下是如何使用自定义组件更新个人资料信息的示例:

use App\Livewire\CustomComponent;

FilamentCompanies::make()
    ->updateProfileInformation(component: CustomComponent::class);

组件排序

如果您想更改个人资料功能的顺序,可以通过设置对应方法的sort参数来实现。

默认排序顺序如下:

FilamentCompanies::make()
    ->updateProfileInformation(sort: 0)
    ->updatePasswords(sort: 1)
    ->setPasswords(sort: 2)
    ->connectedAccounts(sort: 3)
    ->manageBrowserSessions(sort: 4)
    ->accountDeletion(sort: 5);

添加组件

如果您想添加自定义个人资料组件,可以通过将组件类名和排序顺序一起传递给addProfileComponents()方法来实现。

use App\Livewire\CustomComponent;

FilamentCompanies::make()
    ->addProfileComponents([
        7 => CustomComponent::class,
    ]);

在您的组件视图中,您可以使用网格部分组件来匹配其他组件的样式。

<x-filament-companies::grid-section md="2">
    <x-slot name="title">
        {{ __('My Custom Component') }}
    </x-slot>

    <x-slot name="description">
        {{ __('This is my custom component.') }}
    </x-slot>

    <x-filament::section>
        <x-filament-panels::form wire:submit="submit">
            {{ $this->form }}

            <div class="text-left">
                <x-filament::button type="submit">
                    {{ __('Save') }}
                </x-filament::button>
            </div>
        </x-filament-panels::form>
    </x-filament::section>
</x-filament-companies::grid-section>

个人资料照片

要允许用户上传自定义个人资料照片,您可以通过在FilamentCompaniesServiceProvider中包含profilePhotos()方法来启用此功能。

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->profilePhotos()
            )
    }
}

磁盘存储

默认情况下,该包使用Laravel的public磁盘来存储图像。但是,您可以通过传递disk参数来指定不同的磁盘。

FilamentCompanies::make()
    ->profilePhotos(disk: 's3')

存储路径

如果您想将个人资料照片存储在特定目录中,可以设置storagePath参数。

FilamentCompanies::make()
    ->profilePhotos(storagePath: 'profile-avatars')

模态框

要调整模态框的布局和行为,请使用modals()方法。以下是包的默认设置:

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->modals(
                        width: '2xl', 
                        alignment: 'center', 
                        formActionsAlignment: 'center', 
                        cancelButtonAction: false
                    )
            );
    }
}

通知

要配置由包发送的通知,请使用notifications()方法。

除非指定其他情况,否则包将发送通知。为了禁用通知,您必须将false传递给notifications()方法。

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->notifications(condition: false)
            );
    }
}

覆盖通知

要覆盖包发送的默认通知,您应为每个对应操作提供以下方法。

传递给每个方法的参数是可选的,如果不需要可以省略。

更新用户个人资料信息

\App\Actions\FilamentCompanies\UpdateUserProfileInformation::class

/** @method void profileInformationUpdated(\Illuminate\Foundation\Auth\User|null $user = null, array|null $input = null) */

更新用户密码

\App\Actions\FilamentCompanies\UpdateUserPassword::class

/** @method void passwordUpdated(\Illuminate\Foundation\Auth\User|null $user = null, array|null $input = null) */

设置用户密码

\App\Actions\FilamentCompanies\SetUserPassword::class

/** @method void passwordSet(\Illuminate\Foundation\Auth\User|null $user, array|null $input = null) */

更新公司名称

\App\Actions\FilamentCompanies\UpdateCompanyName::class

/** @method void companyNameUpdated(\Illuminate\Foundation\Auth\User|null $user = null, \Illuminate\Database\Eloquent\Model|null $company = null, array|null $input = null) */

邀请公司员工

\App\Actions\FilamentCompanies\InviteCompanyEmployee::class

/** @method void employeeInvitationSent(\Illuminate\Foundation\Auth\User|null $user = null, \Illuminate\Database\Eloquent\Model|null $company = null, string|null $email = null, string|null $role = null) */

删除公司

\App\Actions\FilamentCompanies\DeleteCompany::class

/** @method void companyDeleted(\Illuminate\Database\Eloquent\Model|null $company = null) */

示例

如果您想覆盖用户更改密码时发送的通知,您可以执行以下操作

<?php

namespace App\Actions\FilamentCompanies;

use App\Models\User;
use Filament\Notifications\Notification;
use Wallo\FilamentCompanies\Contracts\UpdatesUserPasswords;

class UpdateUserPassword implements UpdatesUserPasswords
{
    /**
     * Validate and update the user's password.
     *
     * @param  array<string, string>  $input
     */
    public function update(User $user, array $input): void
    {
       // ...
    }

    public function passwordUpdated(): void
    {
        Notification::make()
            ->title('Password Updated')
            ->body('Your password has been updated.')
            ->success();
            ->send();
    }
    
}

公司邀请

示例 - Gmail

  1. 登录您的账户

  2. 转到 应用密码

  3. 点击“选择应用”,输入应用程序名称,然后点击“生成”。

  4. 复制您的应用程序密码并将其安全地存储起来。

  5. 添加凭据到应用程序的.env文件中

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=yourgmailusername@gmail.com
MAIL_PASSWORD=of9f9279g924792g49t          
MAIL_ENCRYPTION=tls                         
MAIL_FROM_ADDRESS="filament@company.com"
MAIL_FROM_NAME="${APP_NAME}"

角色 & 权限

您可以在app/Providers/FilamentCompaniesServiceProvider.php中更改角色 & 权限

/**
 * Configure the roles and permissions that are available within the application.
 */
protected function configurePermissions(): void
{
    FilamentCompanies::defaultApiTokenPermissions(['read']);

    FilamentCompanies::role('admin', 'Administrator', [
        'create',
        'read',
        'update',
        'delete',
    ])->description('Administrator users can perform any action.');

    FilamentCompanies::role('editor', 'Editor', [
        'read',
        'create',
        'update',
    ])->description('Editor users have the ability to read, create, and update.');
}

Socialite

默认情况下,GitHub提供者将启用。

您可以使用Laravel Socialite支持的任何提供者。

您可以在公司面板配置中添加或删除任何提供者

use Filament\Panel;
use Wallo\FilamentCompanies\FilamentCompanies;
use Wallo\FilamentCompanies\Enums\Feature;
use Wallo\FilamentCompanies\Enums\Provider;

class FilamentCompaniesServiceProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            // ...
            ->plugin(
                FilamentCompanies::make()
                    ->socialite(
                        providers: [
                            Provider::Github,
                            Provider::Gitlab,
                            Provider::Google,
                            Provider::Facebook,
                            Provider::Linkedin,
                            Provider::LinkedinOpenId,
                            Provider::Bitbucket,
                            Provider::Slack,
                            Provider::Twitter,
                            Provider::TwitterOAuth2,
                        ],
                        features: [
                            Feature::RememberSession,
                            Feature::ProviderAvatars,
                            Feature::GenerateMissingEmails,
                            Feature::LoginOnRegistration,
                            Feature::CreateAccountOnFirstLogin,
                        ]
                    )
            )
    }
}

⚠️ 如果需要Twitter,您只能使用Twitter OAuth1或Twitter OAuth2。

config/services.php中提供者的数组中传递提供者的凭据

    /*
    |--------------------------------------------------------------------------
    | Third Party Services
    |--------------------------------------------------------------------------
    |
    | This file is for storing the credentials for third party services such
    | as Mailgun, Postmark, AWS and more. This file provides the de facto
    | location for this type of information, allowing packages to have
    | a conventional file to locate the various service credentials.
    |
    */
    
    'github' => [
        'client_id' => env('GITHUB_CLIENT_ID'),
        'client_secret' => env('GITHUB_CLIENT_SECRET'),
        'redirect' => 'https://filament.test/company/oauth/github/callback',
    ],

‼️ 提供者的重定向URI必须类似于上述内容(例如:‘APP_URL/company/oauth/provider/callback’)

示例 - GitHub

  1. 注册一个新的OAuth应用程序

  2. 应用程序名称

Filament
  1. 主页URL
http://filament.test/company
  1. 授权回调URL
http://filament.test/company/oauth/github/callback
  1. ☑ 启用设备流程

  2. 点击注册应用程序

  3. 复制客户端密钥并将其安全地存储起来

  4. 添加客户端ID和客户端密钥到.env

GITHUB_CLIENT_ID=aluffgef97f9f79f434t
GITHUB_CLIENT_SECRET=hefliueoioffbo8338yhf2p9f4g2gg33

方法论

  • 以下示例是Laravel Jetstream实现的方法所支持的特性的视觉表示。
  • 您可以在文档中找到该软件包提供的所有功能。
  • 通过Wallo\FilamentCompanies\HasCompanies特质提供的方法可以访问用户的公司信息。
  • 此特质在安装期间自动应用于应用程序的App\Models\User模型。
  • 此特质提供了各种有用的方法,允许您检查用户的公司或公司
// Access a user's currently selected company...
$user->currentCompany : Wallo\FilamentCompanies\Company

// Access all of the companies (including owned companies) that a user belongs to...
$user->allCompanies() : Illuminate\Support\Collection

// Access all of a user's owned companies...
$user->ownedCompanies : Illuminate\Database\Eloquent\Collection

// Access all of the companies that a user belongs to but does not own...
$user->companies : Illuminate\Database\Eloquent\Collection

// Access a user's "personal" company...
$user->personalCompany() : Wallo\FilamentCompanies\Company

// Determine if a user owns a given company...
$user->ownsCompany($company) : bool

// Determine if a user belongs to a given company...
$user->belongsToCompany($company) : bool

// Get the role that the user is assigned on the company...
$user->companyRole($company) : \Wallo\FilamentCompanies\Role

// Determine if the user has the given role on the given company...
$user->hasCompanyRole($company, 'admin') : bool

// Access an array of all permissions a user has for a given company...
$user->companyPermissions($company) : array

// Determine if a user has a given company permission...
$user->hasCompanyPermission($company, 'server:create') : bool

📘 $user 代表应用程序的当前用户。可替换为 Auth::user()

致谢

注意

  • 如果您有任何问题,请提问
  • 欢迎PR和问题
  • 如果您有一个一般问题而不是问题,请在我的Discord频道中提问或创建一个讨论帖子。

贡献

  • 将此存储库分叉到您的GitHub账户中。
  • 创建一个新的Laravel & Filament项目。
  • 在应用程序根目录中克隆您的分叉。
  • /filament-companies目录中,为您的修复创建一个分支,例如fix/error-message

在应用程序的composer.json文件中安装该软件包,使用dev前缀后跟您的分支名称

{
    ...
    "require": {
        "andrewdwallo/filament-companies": "dev-fix/error-message",
    },
    "repositories": [
        {
            "type": "path",
            "url": "filament-companies/"
        }
    ],
    ...
}

现在,运行composer update,然后按照上面的安装说明继续操作。