obsidiane/auth-sdk 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

obsidiane/auth-sdk

最新稳定版本:1.0.11

Composer 安装命令:

composer require obsidiane/auth-sdk

包简介

Symfony bundle fournissant un client Obsidiane Auth orienté API (bridge + facades, Bearer token)

README 文档

README

SDK PHP orienté API pour consommer Obsidiane Auth avec une logique proche du SDK JS (bridge + facades). Authentification via Bearer token (optionnel), pas de cookies.

Features

Bridge API-first (get/getCollection/post/patch/put/delete + request) ✅ Facades ressources avec modèles hydratés via Symfony Serializer ✅ JSON-LD par défaut (Accept: application/ld+json) ✅ Content-Type auto (POST/PUT: application/ld+json, PATCH: application/merge-patch+json) ✅ Exceptions structurées via ApiErrorException sur erreurs HTTP ✅ Configuration Symfony simple et explicite

Installation

composer require obsidiane/auth-sdk

Configuration Symfony

config/bundles.php

return [
    // ...
    Obsidiane\AuthBundle\ObsidianeAuthBundle::class => ['all' => true],
];

config/packages/obsidiane_auth.yaml

obsidiane_auth:
  base_url: '%env(OBSIDIANE_AUTH_BASE_URL)%'
  token: '%env(OBSIDIANE_AUTH_TOKEN)%' # optionnel
  defaults:
    headers: { }
    timeout_ms: 10000 # optionnel
  debug: false

.env

OBSIDIANE_AUTH_BASE_URL=https://auth.example.com
OBSIDIANE_AUTH_TOKEN=your-static-bearer-token

Le token est optionnel : s'il est absent ou vide, aucun header Authorization n'est ajouté (utile pour les endpoints publics). base_url est requis et peut inclure ou non /api selon votre usage (adaptez vos routes en conséquence).

Utilisation

FacadeFactory (ressources)

use Obsidiane\AuthBundle\Bridge\FacadeFactory;

final class UsersService
{
    public function __construct(
        private readonly FacadeFactory $factory,
    ) {}

    public function listUsers(): array
    {
        $users = $this->factory->create('/api/users', \App\Dto\UserRead::class);
        $result = $users->getCollection();

        return $result->items; // list<UserRead>
    }
}

BridgeFacade (endpoints custom)

use Obsidiane\AuthBundle\Bridge\BridgeFacade;

final class AuthService
{
    public function __construct(
        private readonly BridgeFacade $bridge,
    ) {}

    public function me(): array
    {
        return $this->bridge->get('/api/auth/me');
    }
}

Requête custom avec HttpRequestConfig

use Obsidiane\AuthBundle\Bridge\Http\HttpRequestConfig;

$req = new HttpRequestConfig(
    method: 'GET',
    url: '/api/users',
    query: ['page' => 1, 'itemsPerPage' => 20],
    headers: ['X-Request-ID' => 'req_123'],
    timeoutMs: 5000,
);

$response = $bridge->request($req);

Hydratation des modèles

Les facades utilisent Symfony\Component\Serializer\Normalizer\NormalizerInterface et DenormalizerInterface pour la sérialisation/désérialisation. Les modèles du SDK exposent @id via la propriété $iri. Si vous utilisez vos propres modèles, mappez @id avec #[SerializedName('@id')].

Note technique : Le SDK nécessite que le SerializerInterface implémente aussi NormalizerInterface et DenormalizerInterface (ce qui est le cas avec le Serializer standard de Symfony). Le FacadeFactory vérifie automatiquement ces interfaces au runtime.

API publique

Classes principales

  • BridgeFacade : appels HTTP bas niveau (GET, GET collection, POST, PUT, PATCH, DELETE, request)
  • FacadeFactory : création de ResourceFacade<T> avec hydratation automatique
  • ResourceFacade<T> : CRUD + collections hydratées (generic type-safe)
  • Collection<T> : items + metadata JSON-LD (totalItems, id, type, context, view, search)

Modèles

Les modèles exposent les propriétés JSON-LD standard :

  • Item : classe de base avec $iri (@id), $type (@type), $context (@context)
  • Tous les modèles générés héritent de Item ou exposent ces propriétés

Paramètres de configuration

Clés principales

  • base_url : URL de base du service Auth (requis).
  • token : Bearer token optionnel, ajouté si non vide.
  • debug : active les logs debug du bridge HTTP.

defaults (dans obsidiane_auth.yaml)

  • headers: headers HTTP appliqués à toutes les requêtes (peuvent être surchargés par appel)
  • timeout_ms: timeout en millisecondes (par défaut: aucun)

Options par requête

Toutes les méthodes de ResourceFacade et BridgeFacade acceptent un paramètre HttpCallOptions optionnel :

use Obsidiane\AuthBundle\Bridge\Http\HttpCallOptions;

$options = new HttpCallOptions(
    headers: ['X-Custom-Header' => 'value'],
    timeoutMs: 5000, // en ms
    responseType: 'text',
);

$users->getCollection([], $options);

responseType: 'text' retourne la réponse brute (string). Par défaut, la réponse est décodée en JSON.

Exemples avancés

Filtrage et pagination

$users = $factory->create('/api/users', UserRead::class);

// Pagination
$result = $users->getCollection([
    'page' => 2,
    'itemsPerPage' => 10,
]);

// Filtres
$result = $users->getCollection([
    'filters' => [
        'email' => 'user@example.com',
        'role' => 'ROLE_ADMIN',
    ],
]);

// Metadata
echo $result->totalItems;  // Nombre total d'items
echo $result->id;          // IRI de la collection (@id)

Headers personnalisés

use Obsidiane\AuthBundle\Bridge\Http\HttpCallOptions;

$options = new HttpCallOptions(
    headers: [
        'X-Request-ID' => uniqid(),
        'Accept-Language' => 'fr-FR',
    ],
);

$user = $users->get('/api/users/1', $options);

Gestion d'erreurs

use Obsidiane\AuthBundle\Exception\ApiErrorException;

try {
    $user = $users->get('/api/users/999');
} catch (ApiErrorException $e) {
    // Erreur HTTP (404, 500, etc.)
    error_log($e->getMessage());
    error_log('Status code: ' . $e->getStatusCode());
    error_log('Error code: ' . $e->getErrorCode());
}

ApiErrorException expose aussi getDetails() et getPayload() pour inspecter la réponse.

Codes d’erreur (API)

Statuts HTTP exposés par l’API Auth :

HTTP Cas principaux Détails
400 Requête invalide, token invalide verify-email (id manquant), reset/verify token invalide, invitation sans token (details.token = INVALID_INVITATION).
401 Non authentifié me, JWT invalide/expiré, service token invalide, login refusé.
403 Accès refusé Origin/Referer non autorisé, endpoints admin sans rôle.
404 Introuvable Invitation inconnue, user introuvable, inscription désactivée.
409 Conflit Email déjà utilisé, invitation déjà acceptée, bootstrap requis ou déjà fait.
410 Expiré Invitation expirée, lien de vérification expiré, reset token expiré.
422 Validation Email/mot de passe invalides, champs requis, INVALID_ROLES, confirmation mot de passe.
423 Verrouillé Email non vérifié lors du login.
429 Rate limit Login, register, invite, invite/complete, password/forgot/reset, setup/admin.
500 Erreur interne Échec de reset password non géré (ResetRequestFailedException).
503 Service indisponible Échec d’envoi d’email (MailDispatchException).

Identifiants d’erreurs utiles dans les payloads/validations :

  • INVALID_INVITATION
  • INVALID_ROLES

Invitation (règles métiers)

  • Un utilisateur déjà vérifié ne peut pas être ré-invité.
  • Un utilisateur non vérifié peut être ré-invité : l’email est renvoyé si l’invitation est encore valide, sinon elle est régénérée.

Qualité du code

Le SDK maintient une qualité de code stricte :

  • PHPStan Level 6 : Zero erreur d'analyse statique
  • Types stricts : declare(strict_types=1) dans tous les fichiers
  • Generics : ResourceFacade<T>, Collection<T> pour type-safety
  • Readonly : Classes immuables avec readonly
  • PSR-12 : Standard de code PHP

Troubleshooting

Erreur "Serializer must implement NormalizerInterface"

Si vous obtenez cette erreur, assurez-vous que votre SerializerInterface est bien le Serializer standard de Symfony (pas un mock ou une implémentation custom sans normalizer).

Timeout des requêtes

Par défaut, aucun timeout n'est appliqué. Pour en définir un :

# config/packages/obsidiane_auth.yaml
obsidiane_auth:
  defaults:
    timeout_ms: 30000  # 30 secondes

Ou par requête :

use Obsidiane\AuthBundle\Bridge\Http\HttpCallOptions;

$options = new HttpCallOptions(timeoutMs: 30000);
$result = $users->getCollection([], $options);

统计信息

  • 总下载量: 125
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-11-15