Api Platform OpenApi doesn't use the JWT token - symfony

I use ApiPlatform (PHP 8 / Symfony 6) to create a simple API with a JWT authentification.
Authentification work correctly, I can generate a token. When I use PostMan to test a authenticated operation, no problem, I add manually the Bearer header with my token.
Now I would like to use the documentation auto generated to do this.
I have created a JwtDecorator to add my login route and a security schema. Now I can add my token with the "Authorize" green button. But after, when I execute a authenticated operation, the token is not add in the header of the cUrl query. I don't understand why.
security.yaml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\User: 'auto'
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login
stateless: true
json_login:
check_path: /login
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/
stateless: true
jwt: ~
access_control:
- { path: ^/$, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI
- { path: ^/docs, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI docs
- { path: ^/login, roles: PUBLIC_ACCESS }
- { path: ^/, roles: PUBLIC_ACCESS }
JwtDecorator.php
<?php
namespace App\OpenApi;
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\OpenApi\OpenApi;
use ApiPlatform\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): OpenApi
{
$openApi = ($this->decorated)($context);
$schemas = $openApi->getComponents()->getSchemas();
$schemas['Token'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'token' => [
'type' => 'string',
'readOnly' => true,
],
],
]);
$schemas['Credentials'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'username' => [
'type' => 'string',
'example' => 'test#gmail.com',
],
'password' => [
'type' => 'string',
'example' => '123456',
],
],
]);
$schemas = $openApi->getComponents()->getSecuritySchemes() ?? [];
$schemas['JWT'] = new \ArrayObject([
'type' => 'http',
'scheme' => 'bearer',
'bearerFormat' => 'JWT',
]);
$pathItem = new Model\PathItem(
ref: 'JWT Token',
post: new Model\Operation(
operationId: 'postCredentialsItem',
tags: ['Token'],
responses: [
'200' => [
'description' => 'Get JWT token',
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Token',
],
],
],
],
],
summary: 'Get JWT token to login.',
requestBody: new Model\RequestBody(
description: 'Generate new JWT Token',
content: new \ArrayObject([
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Credentials',
],
],
]),
),
security: [],
),
);
$openApi->getPaths()->addPath('/login', $pathItem);
return $openApi;
}
}
NotificationCategory.php
<?php
namespace App\Entity;
use ...
#[ORM\Entity(repositoryClass: NotificationCategoryRepository::class)]
#[ApiResource(
openapiContext: ['security' => [['Bearer Authentication' => []]]],
security: "is_granted('ROLE_USER')"
)]
class NotificationCategory
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Groups(['read:Notification:get'])]
private ?string $name = null;
#[ORM\OneToMany(mappedBy: 'category', targetEntity: Notification::class)]
private Collection $notifications;
...
}

I finally found. I was not using the correct schema name in my entity's openapiContext. In JwtDecorator file, I name the schema JWT, and in NotificationCategory entity : Bearer Authentication.
So I replaced :
#[ApiResource(
openapiContext: ['security' => [['Bearer Authentication' => []]]],
security: "is_granted('ROLE_USER')"
)]
By :
#[ApiResource(
openapiContext: ['security' => [['JWT' => []]]],
security: "is_granted('ROLE_USER')"
)]
It work.

Related

I can't create a JWT endpoint

I want to add an endpoint to SwaggerUI to retrieve a JWT token. I did everything as they say in the API platform documentation here.
I created a JwtDecorator.php file:
<?php
// api/src/OpenApi/JwtDecorator.php
namespace App\OpenApi;
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\OpenApi\OpenApi;
use ApiPlatform\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): OpenApi
{
$openApi = ($this->decorated)($context);
$schemas = $openApi->getComponents()->getSchemas();
$schemas['Token'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'token' => [
'type' => 'string',
'readOnly' => true,
],
],
]);
$schemas['Credentials'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'email' => [
'type' => 'string',
'example' => 'johndoe#example.com',
],
'password' => [
'type' => 'string',
'example' => 'apassword',
],
],
]);
$schemas = $openApi->getComponents()->getSecuritySchemes() ?? [];
$schemas['JWT'] = new \ArrayObject([
'type' => 'http',
'scheme' => 'bearer',
'bearerFormat' => 'JWT',
]);
$pathItem = new Model\PathItem(
ref: 'JWT Token',
post: new Model\Operation(
operationId: 'postCredentialsItem',
tags: ['Token'],
responses: [
'200' => [
'description' => 'Get JWT token',
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Token',
],
],
],
],
],
summary: 'Get JWT token to login.',
requestBody: new Model\RequestBody(
description: 'Generate new JWT Token',
content: new \ArrayObject([
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Credentials',
],
],
]),
),
security: [],
),
);
$openApi->getPaths()->addPath('/authentication_token', $pathItem);
return $openApi;
}
}
My security.yaml
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
App\Entity\User: 'auto'
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
login:
pattern: ^/api/login
stateless: true
json_login:
check_path: /api/login_check # or api_login_check as defined in config/routes.yaml
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api/
stateless: true
provider: app_user_provider
jwt: ~
main:
stateless: true
lazy: true
provider: app_user_provider
json_login:
check_path: /authentication_token
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
jwt: ~
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
- { path: /api/docs, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI
- { path: ^/authentication_token, roles: PUBLIC_ACCESS }
# - { path: ^/, roles: IS_AUTHENTICATED_FULLY }
when#test:
security:
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4
time_cost: 3
memory_cost: 10
My service.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
services:
App\OpenApi\JwtDecorator:
decorates: 'api_platform.openapi.factory'
arguments: ['#.inner']
App\State\UserProcessor:
tags: ['api_platform.state_processor']
bind:
$decorated: '#api_platform.doctrine.orm.state.persist_processor'
arguments:
$passwordHasher: '#Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface'
ApiPlatform\State\ProcessorInterface: ~
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
But I don't see "/authentication_token" endpoint in my swagger interface
stack:
Symfony : 6.1
PHP : 8.1
api platform: 3.0
You are missing two config files:
config/api_platform.yaml:
api_platform:
swagger:
api_keys:
JWT:
name: Authorization
type: header
config/routes.yaml:
authenticate:
path: /authentication_token
methods: ['POST']

Edit Sonata User data

I'm trying to override Sonata User Admin class, on my bundle. For the moment, I just override the configureListFields method:
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\UserBundle\Admin\Model\UserAdmin as BaseUserAdmin;
class UserAdmin extends BaseUserAdmin
{
/**
* #param ListMapper $listMapper
*/
protected function configureListFields(ListMapper $listMapper):void
{
$listMapper
->addIdentifier('username')
->add('email')
->add('groups')
->add('enabled', null, ['editable' => true])
->add('accountType')
->add('createdAt')
;
if ($this->isGranted('ROLE_ALLOWED_TO_SWITCH')) {
$listMapper
->add('impersonating', 'string', ['template' => '#SonataUser/Admin/Field/impersonating.html.twig'])
;
}
}
}
I refresh my page and I got the list of users without problem. But when I click into a user to edit it, I have this error: Call to a member function getClass() on null on these lines:
$now = new \DateTime();
$genderOptions = [
'choices' => \call_user_func([$this->getUserManager()->getClass(), 'getGenderList']),
'required' => true,
'translation_domain' => $this->getTranslationDomain(),
];
// NEXT_MAJOR: Remove this when dropping support for SF 2.8
if (method_exists(FormTypeInterface::class, 'setDefaultOptions')) {
$genderOptions['choices_as_values'] = true;
}
Sonata_admin.yaml file:
sonata_admin:
title: 'Staff Admin Panel'
templates:
dashboard: '#SonataAdmin/Core/dashboard.html.twig'
security:
handler: sonata.admin.security.handler.role
role_admin: ROLE_ADMIN
role_super_admin: ROLE_SUPER_ADMIN
# information:
# GUEST: [VIEW, LIST]
# STAFF: [EDIT, LIST, CREATE]
# EDITOR: [OPERATOR, EXPORT]
# ADMIN: [MASTER]
# admin_permissions: [CREATE, LIST, DELETE, UNDELETE, EXPORT, OPERATOR, MASTER]
# object_permissions: [VIEW, EDIT, DELETE, UNDELETE, OPERATOR, MASTER, OWNER]
dashboard:
blocks:
- { type: sonata.admin.block.admin_list, position: left }
groups:
content:
label: Contenu
icon: '<i class="fa fa-file-text-o"></i>'
items:
- app.admin.specialty
- app.admin.cities
- app.admin.colleges
- app.admin.building
sonata.admin.group.media:
label: Médiathèque
icon: '<i class="fa fa-camera-retro"></i>'
items:
- sonata.media.admin.media
settings:
label: Paramètres
icon: '<i class="fa fa-cog"></i>'
items:
- sonata.classification.admin.category
- sonata.classification.admin.context
- sonata.classification.admin.tag
- sonata.classification.admin.collection
- app.admin.icon
sonata.admin.group.administration:
label: Utilisateur et Groupes
label_catalogue: SonataAdminBundle
icon: '<i class="fa fa-users"></i>'
items:
- app.admin.user
- sonata.user.admin.group
sonata_block:
blocks:
sonata.admin.block.admin_list:
contexts: [admin]
sonata_user:
security_acl: true
manager_type: orm
class:
user: App\Application\Sonata\UserBundle\Entity\User
group: App\Application\Sonata\UserBundle\Entity\Group
fos_user.yaml file:
fos_user:
db_driver: orm # valid values are 'orm', 'mongodb' and 'couchdb'
user_class: App\Entity\User #App\Application\Sonata\UserBundle\Entity\User
firewall_name: main
registration:
form:
type: App\Application\Sonata\UserBundle\Form\RegistrationType
group:
group_class: App\Application\Sonata\UserBundle\Entity\Group
group_manager: sonata.user.orm.group_manager
service:
user_manager: sonata.user.orm.user_manager
mailer: fos_user.mailer.noop
from_email:
address: "%env(MAILER_SENDER_ADDRESS)%"
sender_name: "%env(MAILER_SENDER_NAME)%"
If you want to access to your method getGenderList() from configureFormFields() you can do that :
protected function configureFormFields(FormMapper $formMapper)
{
$now = new \DateTime();
$genderOptions = [
'choices' => $this->getSubject()->getGenderList(), // here
'required' => true,
'translation_domain' => $this->getTranslationDomain(),
];
// NEXT_MAJOR: Remove this when dropping support for SF 2.8
if (method_exists(FormTypeInterface::class, 'setDefaultOptions')) {
$genderOptions['choices_as_values'] = true;
}
}
See the Symfony docs about it.

Notice: Undefined index: translation_domain

I apologize for my English.
Some time ago I encountered a problem when developing my project on the Symfony. The problem arose in SonataAdminBundle.
The error looks like this
My Admin class
<?php
namespace Flatbel\FlatBundle\Admin;
use Flatbel\FlatBundle\Entity\User;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
class AdminAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Основная информация', array('class' => 'col-md-8'))
->remove('userid')
->add('flattype', 'choice', array(
'choices' => array(
'VIP' => 'VIP',
'Стандарт' => 'Стандарт',
'Бюджет' => 'Бюджет'
),
'choices_as_values' => true, 'label' => 'Тип квартиры', 'placeholder'=>'Выбрать...'
))
->add('numberofbeds','choice', array(
'choices' => array(
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4',
'5' => '5',
'6' => '6',
'6+' => '7',
),
'choices_as_values' => true, 'label'=>'Количество спальных мест', 'placeholder'=>'Выбрать...'
))
->add('rooms','choice', array(
'choices' => array(
'1' => '1',
'2' => '2',
'3' => '3',
'4+' => '4',
),
'choices_as_values' => true, 'label'=>'Число комнат', 'placeholder'=>'Выбрать...'
))
->add('streettype', 'choice', array(
'choices' => array(
'Проспект' => 'Проспект',
'Улица'=>'Улица',
'Переулок'=>'Переулок'
),
'choices_as_values' => true, 'label'=>'Тип', 'placeholder'=>'Выбрать...'
))
->add('street', 'text', array('label'=>'Название'))
->add('home',null,array('label'=>'Номер дома'))
->add('priceday',null,array('label'=>'Цена за день'))
->add('pricehour',null,array('label'=>'Цена за час'))
->add('pricenight',null,array('label'=>'Цена за ночь'))
->add('floorhome',null,array('label'=>'Число этажей в дома'))
->add('floor',null,array('label'=>'Этаж'))
->add('metro','choice', array(
'choices' => array(
'Каменная горка'=>'Каменная горка',
'Кунцевщина'=>'Кунцевщина',
),
'choices_as_values' => true, 'label'=>'Ближайшее метро', 'placeholder'=>'Выбрать...'
))
->add('telnumber',null,array('label'=>'Номер телефона'))
->add('about',null,array('label'=>'Описание'))
->end()
->with('Дополнительная информация',array('class'=>'col-md-4'))
->add('tv',null,array('label'=>'Телевизор'))
->add('wifi',null,array('label'=>'Wi-Fi'))
->add('parking',null,array('label'=>'Стоянка'))
->add('microwave',null,array('label'=>'Микроволновка'))
->add('washer',null,array('label'=>'Стиральная Машина'))
->add('bath',null,array('label'=>'Ванна'))
->add('shower',null,array('label'=>'Душ'))
->add('fridge',null,array('label'=>'Холодильник'))
->add('dishes',null,array('label'=>'Посуда'))
->add('linens',null,array('label'=>'Постельное бельё'))
->remove('payornot')
->remove('description')
->end()
->with('Фотографии',array('class'=>'col-md-8'))
->add('mainphoto', 'sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'flatphotos',
))
->add('photo1','sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'flatphotos',
))
->add('photo2','sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'flatphotos',
))
->add('photo3','sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'flatphotos',
))
->end()
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->addIdentifier('userid')
->addIdentifier('payornot')
->addIdentifier('flattype')
->addIdentifier('numberofbeds')
->addIdentifier('rooms')
->addIdentifier('street')
->addIdentifier('streettype')
->addIdentifier('home')
->addIdentifier('priceday')
->addIdentifier('pricehour')
->addIdentifier('pricenight')
->addIdentifier('floorhome')
->addIdentifier('floor')
->addIdentifier('tv')
->addIdentifier('wifi')
->addIdentifier('parking')
->addIdentifier('microwave')
->addIdentifier('washer')
->addIdentifier('bath')
->addIdentifier('shower')
->addIdentifier('fridge')
->addIdentifier('dishes')
->addIdentifier('linens')
;
}
public function toString($object)
{
return $object instanceof User
? $object->getUsername()
: 'Flat'; // shown in the breadcrumb on the create view
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('id')
->add('userid')
->add('payornot')
->add('flattype')
->add('numberofbeds')
->add('rooms')
->add('street')
->add('streettype')
->add('home')
->add('priceday')
->add('pricehour')
->add('pricenight')
->add('floorhome')
->add('floor')
->add('tv')
->add('wifi')
->add('parking')
->add('microwave')
->add('washer')
->add('bath')
->add('shower')
->add('fridge')
->add('dishes')
->add('linens')
;
}
}
My config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: "#FlatbelFlatBundle/Resources/config/config.yml"}
parameters:
locale: ru
photo_directory: 'uploads/photos/'
framework:
translator: { fallbacks: ["%locale%"] }
default_locale: ru
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
handler_id: ~
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
form:
resources:
- 'FlatbelFlatBundle:Form:media_widgets.html.twig'
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
options:
1002: 'SET NAMES UTF8'
types:
json: Sonata\Doctrine\Types\JsonType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
ApplicationSonataMediaBundle: ~
SonataMediaBundle: ~
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
#FOSUserBundle Configuration
fos_user:
db_driver: orm # other valid values are 'mongodb' and 'couchdb'
firewall_name: main
user_class: Flatbel\FlatBundle\Entity\User
use_listener: true
use_flash_notifications: true
use_authentication_listener: true
use_username_form_type: true
from_email:
address: "%mailer_user%"
sender_name: "%mailer_user%"
profile:
form:
type: fos_user_profile # or 'fos_user_profile' on Symfony < 2.8
name: fos_user_profile_form
validation_groups: [Profile, Default]
change_password:
form:
type: fos_user_change_password # or 'fos_user_change_password' on Symfony < 2.8
name: fos_user_change_password_form
validation_groups: [ChangePassword, Default]
registration:
confirmation:
from_email: # Use this node only if you don't want the global email address for the confirmation email
address: registration#flatbel.by
sender_name: Registration
enabled: true # change to true for required email confirmation
template: '#FOSUser/Registration/email.txt.twig'
form:
type: fos_user_registration # or 'fos_user_registration' on Symfony < 2.8
name: fos_user_registration_form
validation_groups: [Registration, Default]
resetting:
token_ttl: 86400
email:
from_email: # Use this node only if you don't want the global email address for the resetting email
address: resetting#flatbel.by
sender_name: Resetting
template: email/password_resetting.email.twig
form:
type: fos_user_resetting # or 'fos_user_resetting' on Symfony < 2.8
name: fos_user_resetting_form
validation_groups: [ResetPassword, Default]
service:
mailer: fos_user.mailer.default
email_canonicalizer: fos_user.util.canonicalizer.default
username_canonicalizer: fos_user.util.canonicalizer.default
token_generator: fos_user.util.token_generator.default
user_manager: fos_user.user_manager.default
#SonataAdminBundle
sonata_block:
default_contexts: [cms]
blocks:
# enable the SonataAdminBundle block
sonata.admin.block.admin_list:
contexts: [admin]
# ...
sonata_admin:
security:
handler: sonata.admin.security.handler.role
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [FlatbelFlatBundle]
filters:
cssrewrite: ~
assets:
bootstrap_js:
inputs:
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/js/bootstrap.js"
bootstrap_css:
inputs:
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/css/bootstrap.css"
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/css/bootstrap-theme.css"
filters: [cssrewrite]
bootstrap_glyphicons_ttf:
inputs:
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf"
output: "fonts/glyphicons-halflings-regular.ttf"
bootstrap_glyphicons_eot:
inputs:
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/fonts/glyphicons-halflings-regular.eot"
output: "fonts/glyphicons-halflings-regular.eot"
bootstrap_glyphicons_svg:
inputs:
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/fonts/glyphicons-halflings-regular.svg"
output: "fonts/glyphicons-halflings-regular.svg"
bootstrap_glyphicons_woff:
inputs:
- "%kernel.root_dir%/../vendor/twitter/bootstrap/dist/fonts/glyphicons-halflings-regular.woff"
output: "fonts/glyphicons-halflings-regular.woff"
jquery:
inputs:
- "%kernel.root_dir%/../vendor/components/jquery/jquery.js"
sonata_media:
db_driver: doctrine_orm # or doctrine_mongodb, doctrine_phpcr it is mandatory to choose one here
default_context: default # you need to set a context
contexts:
default: # the default context is mandatory
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
flatphotos:
providers:
- sonata.media.provider.image
formats:
big: { width: 500 , quality: 70}
cdn:
server:
path: /uploads/media # http://media.sonata-project.org/
filesystem:
local:
directory: "%kernel.root_dir%/../web/uploads/media"
create: false
Please, help me. I've been trying to find my own mistake for the second week, I've been looking for similar problems on the Internet - and I do not find anything.
EDIT
My services.yml
# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/service_container.html
parameters:
# parameter_name: value
services:
FlatbelFlatFileUploader:
class: Flatbel\FlatBundle\Service\FileUploader
arguments:
$targetDir: '%photo_directory%'
admin.user:
class: Flatbel\FlatBundle\Admin\UserAdmin
arguments: [~, Flatbel\FlatBundle\Entity\User,~]
tags:
- { name: sonata.admin, manager_type: orm, label: User }
admin.flat:
class: Flatbel\FlatBundle\Admin\FlatAdmin
arguments: [~, Flatbel\FlatBundle\Entity\Flat,~]
tags:
- { name: sonata.admin, manager_type: orm, label: Flat }
admin.admin:
class: Flatbel\FlatBundle\Admin\AdminAdmin
arguments: [~, Flatbel\FlatBundle\Entity\Flat,~]
tags:
- { name: sonata.admin, manager_type: orm, label: Admin}
Your admin class extends AbstractAdmin and has no any added fields in it's form mapper. So, you don't need this: ->remove('userid'). I tried to type in my admin class the same thing and got "Notice: Undefined index: translation_domain" too.

SonataFormatter ivory_ck_editor toolbar doesn't show up

I use SonataFormatter with SonataAdmin. I can see the textarea but the toolbar doesn't appear.
I can force the toolbar in runtime with the code bellow. Am i missing something ?
CKEDITOR.replace( 'textbox id', {
toolbar: [
{ name: 'document', items: [ 'Source', '-', 'NewPage', 'Preview', '-', 'Templates' ] }, // Defines toolbar group with name (used to create voice label) and items in 3 subgroups.
[ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ], // Defines toolbar group without name.
'/', // Line break - next group will be placed in new line.
{ name: 'basicstyles', items: [ 'Bold', 'Italic' ] }
]
});
My config.yml
sonata_formatter:
formatters:
markdown:
service: sonata.formatter.text.markdown
extensions:
- sonata.formatter.twig.control_flow
- sonata.formatter.twig.gist
text:
service: sonata.formatter.text.text
extensions:
- sonata.formatter.twig.control_flow
- sonata.formatter.twig.gist
rawhtml:
service: sonata.formatter.text.raw
extensions:
- sonata.formatter.twig.control_flow
- sonata.formatter.twig.gist
richhtml:
service: sonata.formatter.text.raw
extensions:
- sonata.formatter.twig.control_flow
- sonata.formatter.twig.gist
ivory_ck_editor:
configs:
default:
language: '%locale%'
toolbar: standard
My admin class:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('content', 'sonata_formatter_type', array(
'event_dispatcher' => $formMapper->getFormBuilder()->getEventDispatcher(),
'format_field' => 'contentFormatter',
'source_field' => 'rawContent',
'source_field_options' => array(
'horizontal_input_wrapper_class' => $this->getConfigurationPool()->getOption('form_type') == 'horizontal' ? 'col-lg-12': '',
'attr' => array('class' => $this->getConfigurationPool()->getOption('form_type') == 'horizontal' ? 'span10 col-sm-10 col-md-10': '', 'rows' => 20)
),
'ckeditor_context' => 'default',
'target_field' => 'content',
'listener' => true,
))
;
}
I forget to add:
form:
resources:
- 'SonataFormatterBundle:Form:formatter.html.twig'

not authanticat user in symfony2

I am new in symfony2 and I am trying to learn login page in symfony2 but system gives me this error
The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.
My security.yml code is:
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: admin, roles: [ 'ROLE_ADMIN' ] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/demo/secured/login$
security: false
emp:
pattern: ^/emp
form_login:
check_path: acme_radixemp_logincheck
login_path: acme_radixemp_login
logout:
path: acme_radixemp_logout
target: demo
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
access_control:
- { path: ^/emp, roles: ROLE_ADMIN }
And I am trying to run /emp from url
And my login function in controller is :
public function loginAction(Request $request)
{
$login = new user();
$form = $this->createFormBuilder($login)
->add('Username','text',array('attr' => array('size' => '50',"value"=>"",'class'=>'form-control','placeholder'=>"Please Enter Your Username")))
->add('Password', 'password',array('attr' => array('size' => '50',"value"=>"",'class'=>'form-control','placeholder'=>"Enter Your Password")))
->add('login', 'submit',array('attr' => array('class '=>"btn btn-success btn-lg","style"=>"margin-top:15px")))
->getForm()
;
$form->handleRequest($request);
$session = $this->getRequest()->getSession();
$url = $this->generateUrl("emp");
$loginurl = $this->generateUrl("acme_radixemp_login",array("login"=>"fail"));
$postData = $request->request->get('form');
if(!empty($postData)) {
$repository = $this->getDoctrine()->getRepository('AcmeRadixempBundle:user');
$user_name = $repository->findOneBy(array('username' => $postData['Username'],'password'=>$postData['Password']));
if($user_name=="") {
return $this->redirect($loginurl);
} else {
//$this->get('security.context')->isGranted('ROLE_ADMIN');
if(TRUE ===$this->get('security.context')->isGranted('ROLE_ADMIN') )
{
$session->set('username', $postData['Username']);
return $this->redirect($url);
}
}
}
}
return $this->render('AcmeRadixempBundle:Default:login.html.twig',array('login'=> $form->createView()));
}
What did I forgot to do ?
Your check_path and login_path are not standard. If the actions for your settings are not implemented and the correct paths are not registered, your login functionality won't work.
I'd suggest you follow the example in the Symfony book:
Using a Traditional Login Form
I followed it step-by-step and it worked immediately. For simple logins you won't be needing to create the loginAction or logoutAction at all, the Symfony will do everything for you. The only thing you need to create (and you can copy-paste it from the link I've sent you) is the login form. You can find all other more complex information in the book and the cookbook, both available freely on the Symfony website.
Hope this helps.

Resources