Платформа Symfony Api: кодировщик не настроен для учетной записи «App Document Users User»

#symfony #api-platform.com

#symfony #api-platform.com

Вопрос:

У меня эта ошибка в symfony 5.1, api-platform 2.5 и MongoDB

 No encoder has been configured for account "AppDocumentUsersUser".
  

Ошибка возникает, когда я пытаюсь добавить пользователя через Swagger, и я думаю, что это ошибка с опечаткой или я что-то не настроил. Я искал несколько похожих вопросов, но они мне не помогли.

Также используется класс UserDataPersister, скопированный отсюда: https://symfonycasts.com/screencast/api-platform-security/encode-user-password

Ниже мой код:

 #config/packages/security.yaml
security:
    encoders:
        AppDocumentUsersUser:
            algorithm: auto

    role_hierarchy:
        ROLE_USER: ROLE_USER
        ROLE_ADMIN: ROLE_ADMIN
        ROLE_SUPER_ADMIN: ROLE_SUPER_ADMIN

    providers:
        app_user_provider:
            class: AppDocumentUsersUser

    firewalls:
        dev:
            pattern: (^/_(profiler|wdt))|(^/test)
            security: false
        main:
            pattern:  ^/
            stateless: true
            anonymous: true
            provider: app_user_provider

    access_control:
        - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
  
 <?php
//  src/Document/Users/User.php

namespace AppDocumentUsers;

use DoctrineODMMongoDBMappingAnnotations as ODM;
use ApiPlatformCoreAnnotationApiResource;
use SymfonyComponentSecurityCoreUserUserInterface;
use SymfonyComponentSerializerAnnotationSerializedName;
use SymfonyComponentSerializerAnnotationGroups;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use SymfonyComponentValidatorConstraints as Assert;
use DateTime;

/**
 * @ApiResource(
 *  normalizationContext={"groups"={"user:read"}},
 *  denormalizationContext={"groups"={"user:write"}},
 * )
 * @ODMDocument
 * @ODMHasLifecycleCallbacks
 */
class User implements UserInterface
{
    /**
     * @ODMId(strategy="auto")
     */
    private $id;

    /**
     * @ODMField(type="string")
     * @Groups({"user:read", "user:write"})
     */
    private $email;

    /**
     * @ODMField(type="collection")
     * @Groups({"user:read", "user:write"})
     */
    private $roles = [];

    /**
     * @ODMField(type="string")
     * #Groups({"user:write"})
     * @AssertDisableAutoMapping()
     */
    private $password;

    /**
     * @ODMField(type="string")
     * @SerializedName("password")
     * @Groups({"user:write"})
     * @AssertLength(max=4096)
     */
    private $plainPassword;

    /**
     * @ODMField(type="string")
     * @Groups({"user:read", "user:write"})
     */
    private $username;

    /**
     * @ODMField(type="string")
     * @Groups({"user:read", "user:write"})
     */
    private $firstname;

    /**
     * @ODMField(type="string")
     * @Groups({"user:read", "user:write"})
     */
    private $lastname;

    /**
     * @ODMField(type="string")
     */
    private $pseudo;

    /**
     * @ODMField(type="string")
     * @Groups({"user:read", "user:write"})
     */
    private $contact;

    /**
     * @ODMField(type="boolean")
     * @Groups({"user:read", "user:write"})
     */
    private $enabled;

    /**
     * @ODMField(type="date")
     * @Groups({"user:read"})
     */
    private $created_at;

    /**
     * @ODMField(type="date")
     * @Groups({"user:read"})
     */
    private $updated_at;

    /**
     * @ODMField(type="date")
     * @Groups({"user:read"})
     */
    private $last_login;

    public function getId()
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->username;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;
        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    public function getPlainPassword(): ?string
    {
        return $this->plainPassword;
    }

    public function setPlainPassword(string $plainPassword): self
    {
        $this->plainPassword = $plainPassword;
        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
        return null;
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        $this->plainPassword = null;
    }

    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }

    public function getFirstname(): ?string
    {
        return $this->firstname;
    }

    public function setFirstname(?string $firstname): self
    {
        $this->firstname = $firstname;

        return $this;
    }

    public function getLastname(): ?string
    {
        return $this->lastname;
    }

    public function setLastname(?string $lastname): self
    {
        $this->lastname = $lastname;

        return $this;
    }

    public function getPseudo(): ?string
    {
        return $this->pseudo;
    }

    public function setPseudo(?string $pseudo): self
    {
        $this->pseudo = $pseudo;

        return $this;
    }

    public function getContact(): ?string
    {
        return $this->contact;
    }

    public function setContact(?string $contact): self
    {
        $this->contact = $contact;

        return $this;
    }

    public function getEnabled(): ?bool
    {
        return $this->enabled;
    }

    public function setEnabled(bool $enabled): self
    {
        $this->enabled = $enabled;

        return $this;
    }

    public function getCreatedAt(): ?DateTimeInterface
    {
        return $this->created_at;
    }

    public function setCreatedAt(DateTimeInterface $created_at): self
    {
        $this->created_at = $created_at;

        return $this;
    }

    public function getUpdatedAt(): ?DateTimeInterface
    {
        return $this->updated_at;
    }

    public function setUpdatedAt(DateTimeInterface $updated_at): self
    {
        $this->updated_at = $updated_at;

        return $this;
    }

    public function getLastLogin(): ?DateTimeInterface
    {
        return $this->last_login;
    }

    public function setLastLogin(?DateTimeInterface $last_login): self
    {
        $this->last_login = $last_login;

        return $this;
    }

    /** 
     * @ODMPrePersist 
     * @ODMPreUpdate
     */
    public function updatedTimestamps()
    {
        $dateTimeNow = new DateTime('now');
        $this->setUpdatedAt($dateTimeNow);
        if ($this->getCreatedAt() === null) {
            $this->setCreatedAt($dateTimeNow);
        }
    }

}
  
 <?php
//  src/DataPersister/UserDataPersister.php

namespace AppDataPersister;

use ApiPlatformCoreDataPersisterDataPersisterInterface;
use AppDocumentUsersUser;
use DoctrineODMMongoDBDocumentManager;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;

class UserDataPersister implements DataPersisterInterface
{
    private $entityManager;
    private $userPasswordEncoder;

    public function __construct(DocumentManager $entityManager, UserPasswordEncoderInterface $userPasswordEncoder)
    {
        $this->entityManager = $entityManager;
        $this->userPasswordEncoder = $userPasswordEncoder;
    }

    public function supports($data): bool
    {
        return $data instanceof User;
    }

    /**
     * @param User $data
     */
    public function persist($data)
    {
        if ($data->getPlainPassword()) {
            $data->setPassword(
                $this->userPasswordEncoder->encodePassword($data, $data->getPlainPassword())
            );
            $data->eraseCredentials();
        }

        $this->entityManager->persist($data);
        $this->entityManager->flush();
    }

    public function remove($data)
    {
        $this->entityManager->remove($data);
        $this->entityManager->flush();
    }
}
  

Комментарии:

1. Начните с выполнения популярной очистки кэша. Затем запустите «php bin / console security: encode-password». Если кодировщики не определены, вы получите сообщение об ошибке. Если он запрашивает пароль, то, по крайней мере, вы знаете, что определен какой-то кодировщик.

2. Я на самом деле не думаю, что ваша безопасность. файл yaml даже загружается. Причина в том, что вам не хватает уровня сущности в ваших провайдерах. Его отключение вызывает ошибку в моей системе. Или, возможно, вы работаете в рабочей среде, и кэш не очищается. symfony.com/doc/current/security /…

3. после «php bin / console security: encode-password» CLI сообщает: кодировщик использовал Symfony Component Security Core Encoder MigratingPasswordEncoder; [OK] Кодирование пароля выполнено успешно

4. Это безопасность. файл yaml в вашем вопросе фактический файл или вы отредактировали его после вставки? Причина, по которой я спрашиваю, заключается в том, что я не понимаю, почему вы не получаете нераспознанную опцию «class» в разделе «security.providers.app_user_provider». Возможно, потребуется перепроверить и убедиться, что безопасность. файл yaml, который вы просматриваете, является фактическим используемым файлом.

5. спасибо @ Cerad, я переместил «App Document Users User» в «App Document User», и теперь все почти в порядке 😉 но пароль в MongoDB не кодируется; дополнительно в целях безопасности. для изменения yaml потребовалось изменить на providers: app_user_provider: mongodb: {class: AppDocumentUser, property: username}