hyvor/internal

HYVOR应用的内部包

1.1.3 2024-08-05 12:22 UTC

README

此包为Laravel中的HYVOR应用提供了以下功能

  • 身份验证(带有模拟提供者)
  • HTTP辅助工具
  • 媒体路由
  • 国际化
  • 组件API

安装

composer require hyvor/internal

认证

此库为以下提供者提供统一的认证系统

  • HYVOR
  • OpenID Connect
  • 模拟(用于测试)

配置

支持以下环境变量。有关配置选项,请参阅config.php。环境变量应在.env文件中设置。

用户数据

AuthUser类用于表示用户。它具有以下属性

  • int $id - 用户ID
  • string $name - 用户名
  • string $email - 电子邮件
  • ?string $username - 用户名(仅HYVOR)
  • ?string $picture_url - 用户图片URL
  • ?string $location - 用户位置
  • ?string $bio - 用户简介
  • ?string $website_url - 用户网站URL
  • ?string $sub - 用户sub(仅OpenID Connect)
<?php
use Hyvor\Internal\Auth\AuthUser;

// new instance
new AuthUser(
    id: $id, 
    name: $name, 
    ...
);

// from array
AuthUser::fromArray([
    'id' => $id,
    'name' => $name
])

获取数据

获取用户数据应始终使用API调用,而不是在应用程序级查询中使用SQL连接,即使使用OpenID Connect也是如此。这是因为HYVOR用户数据始终存储在外部数据库中。

使用以下方法通过用户ID、电子邮件或用户名获取数据

<?php
use Hyvor\Internal\Auth\AuthUser;

AuthUser::fromId($id);
AuthUser::fromIds($ids);

AuthUser::fromEmail($email);
AuthUser::fromEmails($emails);

AuthUser::fromUsername($username);
AuthUser::fromUsernames($usernames);

认证检查

检查用户是否已登录

use Hyvor\Internal\Auth\Auth;

// AuthUser|null
$user = Auth::check();

if ($user) {
    // user is logged in
}

重定向

程序性重定向

使用以下方法获取重定向到登录、注册和注销页面的方法

use Hyvor\Internal\Auth\Auth;

$loginUrl = Auth::login();
$signupUrl = Auth::signup();
$logoutUrl = Auth::logout();

默认情况下,用户在登录或注销后将被重定向到当前页面。您还可以设置redirect参数,以便在登录或注销后将用户重定向到特定页面

use Hyvor\Internal\Auth\Auth;

$loginUrl = Auth::login('/console');
// or full URL
$loginUrl = Auth::login('https://talk.hyvor.com/console');

HTTP重定向

以下路由已添加到应用程序以进行HTTP重定向

  • /api/auth/login
  • /api/auth/signup
  • /api/auth/logout

所有端点都支持redirect参数,以便在登录或注销后将用户重定向到特定页面/URL。

测试

在测试中,提供者始终设置为fakeFakeProvider始终为所有请求的ID、电子邮件和用户名生成模拟数据。这对于测试很有用。您还可以为FakeProvider设置用户数据库,以便为特定用户返回特定数据,如下所示

use Hyvor\Internal\Auth\Providers\Fake\FakeProvider;

it('adds names to the email', function() {

    // set the database of users
    FakeProvider::databaseSet([
        [
            'id' => 1,
            'name' => 'John Doe',
        ]
    ]);
    
    // send email to user ID 1
    // then assert
    expect($email->body)->toContain('John Doe');

});
  • FakeProvider::databaseSet($database) - 设置用户数据库(集合)。
  • FakeProvider::databaseAdd($user) - 将用户添加到数据库。
  • FakeProvider::databaseClear() - 清除数据库。应在每个测试用例(tearDown)后调用此操作。

当设置数据库时,FakeProvider将仅从该数据库返回用户数据。这对于测试以下场景很有用

  • 当找不到用户时(设置空数据库)。
  • 当需要用户的具体信息时(例如,上面的示例中的姓名、电子邮件等)。

在大多数其他情况下,您应该能够使用模拟提供者而不需要设置数据库。因为它自动为所有用户生成模拟数据,所以您不需要在每个测试用例之前对数据库进行初始化。但是请注意,用户数据在每个测试用例中都会不同。

HTTP

本库提供了一些处理HTTP请求的辅助函数。

异常

HttpException

使用Hyvor\Internal\Http\Exceptions\HttpException抛出HTTP异常。在大多数情况下,这个错误将发送到客户端的JSON响应中。因此,仅在中间件和控制层中使用(永远不在领域层中使用)。消息中不要共享敏感信息。

use Hyvor\Internal\Http\Exceptions\HttpException;

throw new HttpException('User not found', 404);

中间件

身份验证中间件

使用Hyvor\Internal\Http\Middleware\AuthMiddleware要求对路由进行身份验证。

use Hyvor\Internal\Http\Middleware\AuthMiddleware;

Route::get()->middleware(AuthMiddleware::class);

如果用户未登录,将抛出一个状态码为401的HttpException。如果用户已登录,则将一个AccessAuthUser对象(继承自AuthUser)添加到服务容器中,可以使用如下方式使用

use Hyvor\Internal\Http\Middleware\AccessAuthUser;

class MyController 
{
    public function index(AccessAuthUser $user) {
        // $user is an instance of AccessAuthUser (extends AuthUser)
    }
}

function myFunction() {
    $user = app(AccessAuthUser::class);
}

路由

以下是本库添加的路由列表

  • POST /api/auth/check - 返回登录用户或null。
  • GET /api/auth/login - 重定向到登录页面。
  • GET /api/auth/signup - 重定向到注册页面。
  • GET /api/auth/logout - 重定向到注销页面。

模型

HasUser特性

您可以将Hyvor\Internal\Auth\HasUser特性添加到任何模型中,以便为它添加一个user()方法。该方法返回AuthUser对象,使用模型的user_id列。

class Post extends Model
{
    use HasUser;
}

国际化

本库提供了一些处理国际化的辅助函数。在HYVOR应用中,大多数时间字符串都用于前端,但对于某些情况,如电子邮件,您可能需要在后端翻译字符串。类似于我们的设计系统,我们使用ICU消息格式。因此,您可以在前后端之间共享相同的翻译。

所有JSON翻译文件都应该放在一个目录中,该目录在配置文件中设置。默认目录是resources/lang。文件名应该是语言代码(例如en-US.json)。文件应该是一个JSON对象,键是消息ID,值是翻译。也支持嵌套键。区域设置是从目录中的文件加载的。

{
    "welcome": "Welcome to HYVOR",
    "email": "Your email is {email}.",
    "signup": {
        "title": "Sign Up"
    }
}

用法

use Hyvor\Internal\Internationalization\Strings;

$strings = new Strings('en-US');
$welcome = $strings->get('welcome');
$email = $strings->get('email', ['email' => 'me@hyvor.com']);
$signupTitle = $strings->get('signup.title');

区域设置与最接近的区域设置相匹配。例如,如果您有以下区域设置

  • en-US
  • fr-FR
  • es
new Strings('en');; // locale -> `en-US`
new Strings('en-GB'); // locale -> `en-US`
new Strings('fr-FR'); // locale -> `fr-FR`
new Strings('fr'); // locale -> `fr-FR`
new Strings('es-ES'); // locale -> `es`

您还可以使用ClosestLocale类获取给定区域设置的最接近的区域设置。

use Hyvor\Internal\Internationalization\ClosestLocale;

ClosestLocale::get('en', ['en-US', 'fr-FR', 'es']); // returns `en-US`

I18n单例类是管理应用中区域设置的基础类。

use Hyvor\Internal\Internationalization\I18n;

$i18n = app(I18n::class);

$i18n->getAvailableLocales(); // ['en-US', 'fr-FR', 'es', ...]
$i18n->getLocaleStrings('en-US'); // returns the strings from the JSON file as an array
$i18n->getDefaultLocaleStrings(); // strings of the default locale

媒体

本库向您的应用添加了/api/media/{path}路由。此路由将服务/流式传输默认存储磁盘上的文件。这使得从同一域名服务文件变得容易。