gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Bienvenidos de nuevo, maravillosos devotos de JSON, al episodio 2 de API Platform. En la parte 1, ¡nos pusimos manos a la obra! Creamos una API bastante asesina para almacenar tesoros de dragón, pero... ¡nos olvidamos por completo de añadir seguridad! Cualquier criatura pequeña y de pies peludos podría colarse por una puerta trasera... ¡y no tendríamos ni idea! Así que esta vez hablaremos de todo lo relacionado con la seguridad. Como la autenticación: ¿debo utilizar una sesión con un formulario de inicio de sesión... o necesito tokens de API? Y autorización, como denegar el acceso a rutas completas. Luego entraremos en cosas más complicadas, como mostrar u ocultar resultados en función del usuario e incluso mostrar u ocultar determinados campos en función del usuario. También hablaremos de campos totalmente personalizados, del método HTTP PATCH y de la creación de un sistema de pruebas de la API que tus amigos estarán celosos.
Ya sabes lo que hay que hacer: para profundizar realmente en este tema, debes codificar conmigo. Descarga el código del curso de esta página. Después de descomprimirlo, encontrarás un directorio start/
con el mismo código que ves aquí. Abre este ingenioso archivo README.md
y sigue todas las instrucciones de configuración.
Aquí abajo estoy iniciando el servidor web symfony
. Así que iré a un terminal que ya esté dentro del proyecto y ejecutaré
symfony serve -d
para iniciar un servidor web local en segundo plano. Perfecto Mantendré pulsado Cmd
y haré clic en esa URL para abrirla en mi navegador. ¡Hola Treasure Connect! Esta es la app que creamos en el episodio 1... aunque trabajamos exclusivamente en la API. Creamos rutas para tesoros, usuarios y la posibilidad de relacionarlos.
Esta página de inicio es totalmente nueva para el episodio 2. Es una pequeña aplicación Vue que construí. Tiene un formulario de inicio de sesión... pero aún no funciona: dependerá de nosotros darle vida.
Ahora, antes de sumergirnos en la seguridad, una pregunta que me hacen a veces es:
Oye Ryan, los documentos interactivos son superguays... pero ¿podría ocultarlos en producción?
Si tu API es privada -sólo está pensada para tu JavaScript-, podría tener sentido porque no quieres dar a conocer tus rutas al mundo. Sin embargo, no me siento demasiado obligado a ocultar los documentos... porque aunque lo hagas, las rutas siguen existiendo. Así que necesitarás una seguridad adecuada de todos modos.
Pero sí, ocultarlos es posible, así que veamos cómo. Aunque muestres tus docs, éste es un proceso interesante que muestra cómo funcionan juntas varias partes del sistema.
Busca tu terminal y ejecuta:
php ./bin/console config:dump api_platform
Recuerda: este comando muestra toda la configuración posible para API Platform. Veamos... busca "swagger". Ya está. Hay una sección con cosas comoenable_swagger
, enable_swagger_ui
, enable_re_doc
, enable_entrypoint
, yenable_docs
. ¿Qué significa todo eso?
Primero quiero enseñarte qué es ReDoc, porque no hablamos de ello en el primer tutorial. Actualmente estamos viendo la versión Swagger de nuestra documentación. Pero existe un formato competidor llamado ReDoc... ¡y puedes hacer clic en el enlace "ReDoc" de la parte inferior para verlo! ¡Sí! Es la misma información de la documentación... ¡pero con un diseño diferente! Si te gusta esto, está ahí para ti.
De todas formas, volviendo al terminal, hay un montón de configuraciones de "habilitación". Todas están relacionadas... pero son ligeramente diferentes. Por ejemplo, enable_swagger
se refiere en realidad a la documentación de OpenAPI. Recuerda que es el documento JSON que alimenta los documentos de las API Swagger y ReDoc. Entonces, estos son si queremos mostrar o no esos dos tipos de documentación frontales. Y aquí abajo, enable_entrypoint
y enable_docs
controlan si ciertas rutas se añaden o no a nuestra aplicación.
Apuesto a que no ha tenido mucho sentido, así que vamos a jugar con esto. Imagina que queremos desactivar la documentación por completo. De acuerdo Abre config/packages/api_platform.yaml
y, para empezar, añade enable_docs: false
:
api_platform: | |
... lines 2 - 7 | |
enable_docs: false |
En cuanto lo hagas y actualices... ¡bien! La documentación de nuestra API ha desaparecido... pero con un error 500. Cuando enable_docs: false
, elimina literalmente la ruta a nuestra documentación.
Retrocedamos. Ir a /api
siempre fue una especie de atajo para llegar a la documentación. La ruta real era /api/docs
, /api/docs.json
o .jsonld
. Y ahora todas son 404 porque hemos desactivado esa ruta. Así que, ¡viva nuestra documentación!
Sin embargo, cuando vas a /api
, en realidad no es una página de documentación. Es lo que se conoce como "punto de entrada": es nuestra página de inicio de la API. Esta página sigue existiendo... pero intenta enlazar con nuestra documentación de la API... que no existe, y explota.
Para desactivar el punto de entrada, muévete y añade enable_entrypoint: false
:
api_platform: | |
... lines 2 - 8 | |
enable_entrypoint: false |
Ahora yendo a /api
nos da... ¡hermoso! A 404.
Vale, ya sabemos que podemos ir a /api/treasures.json
o a .jsonld
. Pero, ¿y si vamos a /api/treasures
? Eso... ¡desgraciadamente es un error 500! Cuando nuestro navegador hace una petición, envía una cabecera Accept
que dice que queremos HTML. Así que estamos pidiendo a nuestra API la versión html
de los tesoros. Y la versión html
es... la documentación. Así que intenta enlazar con la documentación y explota.
Para desactivar esto, podemos comunicar al sistema que no tenemos Swagger ni documentación de la API en absoluto... para que deje de intentar enlazar con ella. Hazlo configurandoenable_swagger: false
:
api_platform: | |
... lines 2 - 9 | |
enable_swagger: false |
Aunque... eso sólo da lugar a otro error 500 que dice:
¡Eh, no puedes activar Swagger UI sin activar Swagger!
Arregla eso con enable_swagger_ui: false
:
api_platform: | |
... lines 2 - 10 | |
enable_swagger_ui: false |
Y ahora... ¡más cerca!
No se admite la serialización para el formato
html
.
El problema es que seguimos solicitando la versión html
de este recurso. Pero ahora que no tenemos documentación, nuestra API es como:
Um... no estoy muy seguro de cómo devolver una versión HTML de esto.
Y la verdad es: si desactivamos totalmente nuestra documentación, ¡ya no necesitamos un formato HTML! Y, por tanto, podemos desactivarlo. Hazlo, muy sencillamente, eliminando html
deformats
:
api_platform: | |
formats: | |
jsonld: [ 'application/ld+json' ] | |
json: [ 'application/json' ] | |
jsonhal: [ 'application/hal+json' ] | |
... lines 7 - 10 |
Y... en realidad tenemos otro punto donde necesitamos hacerlo: ensrc/Entity/DragonTreasure.php
. Cuando añadimos nuestro formato personalizado csv
... veámoslo aquí... repetimos todos los formatos, incluido html
. Así que quita también html
de ahí:
... lines 1 - 26 | |
( | |
... lines 28 - 40 | |
formats: [ | |
'jsonld', | |
'json', | |
'jsonhal', | |
'csv' => 'text/csv', | |
], | |
... lines 47 - 53 | |
) | |
... lines 55 - 72 | |
class DragonTreasure | |
{ | |
... lines 75 - 232 | |
} |
Cuando actualicemos ahora... ¡ya está! Como no hay formato HTML, se pone por defecto JSON-LD
. Nuestros documentos están ahora totalmente desactivados.
Ah, y para desactivar los documentos sólo para producción, crearía una variable de entorno -como ENABLE_API_DOCS
- y luego haría referencia a ella en mi configuración:
# config/packages/api_platform.yaml
api_platform:
enable_swagger_ui: '%env(bool:ENABLE_API_DOCS)%'
Pero... Me gusta la documentación, así que voy a deshacer este cambio... y este cambio también para recuperar nuestros documentos.
api_platform: | |
formats: | |
jsonld: [ 'application/ld+json' ] | |
json: [ 'application/json' ] | |
html: [ 'text/html' ] | |
jsonhal: [ 'application/hal+json' ] | |
# enable_docs: false | |
# enable_entrypoint: false | |
# enable_swagger: false | |
# enable_swagger_ui: false |
... lines 1 - 26 | |
( | |
... lines 28 - 40 | |
formats: [ | |
'jsonld', | |
'json', | |
'html', | |
'jsonhal', | |
'csv' => 'text/csv', | |
], | |
... lines 48 - 54 | |
) | |
... lines 56 - 73 | |
class DragonTreasure | |
{ | |
... lines 76 - 233 | |
} |
¡Me encanta!
A continuación, vamos a tener una charla informal sobre la autenticación. Tienes una API elegante: ¿necesitas tokens de API? ¿O algo más?
Hey @Oleh-K!
Ah, you're right! I was assuming too much! The APIPlatform Symfony integration references those variables at compile time (like you said). That would need to be fixed inside API Platform, but actually, I think it's not reasonably fixable. By setting, for example, enable_swagger
to false
, a set of services is removed from the container (which is good - no reason to have those extra service around if they're not used). It would be a decent bit of work to allow this config to use environment variables, and the end result is that people who do want to disable them would still have these extra services "available" in the container, even though they're not used. Not a huge deal, but also probably a good reason not to "fix it".
Anyway, I appreciate you pointing this out! I'll add a note to the course.
Cheers!
Hello!
I have a question about how you did the initial login, since it appears created directly in the video, are you creating it through make:controller login? If not, could I create it this way?
Hey @Fran!
At the start of this tutorial, the frontend and login stuff is pretty simple. It's a MainController::homepage()
that renders main/homepage.html.twig
(and that controller is dead-simple). The template itself is pretty much empty except that it renders a Vue app, which renders the login form. All of that was created by hand. The controller and template and very simple and small (you could definitely use make:controller
to get this), but I created the Vue app by hand.
In a normal Symfony app, I would probably build my login form directly in PHP & Twig. For that, I'd use make:auth
and choose the "login form" option. That will generate you the controller & template for the login form + a few other things.
Does that help? Let me know!
Cheers!
Short question, the editor in use is Phpstrorm? Is this a special skin?
Hey @Klaus-M
Yes, it is PhpStorm, and I believe Ryan uses the "Atom Material Icons" plugin to enhance his editor's theme
Cheers!
Hey @pasquale_pellicani ,
I'm not sure I understand the question :)
I also ask the same question here
What who else is asking here and what exactly? I see only your comment on this page :)
But in case you're looking for part 1, here it is: https://symfonycasts.com/screencast/api-platform .
Cheers!
Thank you very much, it would be ideal to change the title of the courses with part 1 and part 2 because I had difficulty understanding the order of the two courses. I take the opportunity to thank you for the excellent work done ;)
Hey @pasquale_pellicani ,
I see, yeah, it might not be clear enough. I'd try to add cross-link to this course. Also, you can always can look at the track to find the related courses and the correct order: https://symfonycasts.com/tracks/rest#api-platform-3
I hope this helps!
Cheers!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^3.0", // v3.1.2
"doctrine/annotations": "^2.0", // 2.0.1
"doctrine/doctrine-bundle": "^2.8", // 2.8.3
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
"doctrine/orm": "^2.14", // 2.14.1
"nelmio/cors-bundle": "^2.2", // 2.2.0
"nesbot/carbon": "^2.64", // 2.66.0
"phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
"phpstan/phpdoc-parser": "^1.15", // 1.16.1
"symfony/asset": "6.2.*", // v6.2.5
"symfony/console": "6.2.*", // v6.2.5
"symfony/dotenv": "6.2.*", // v6.2.5
"symfony/expression-language": "6.2.*", // v6.2.5
"symfony/flex": "^2", // v2.2.4
"symfony/framework-bundle": "6.2.*", // v6.2.5
"symfony/property-access": "6.2.*", // v6.2.5
"symfony/property-info": "6.2.*", // v6.2.5
"symfony/runtime": "6.2.*", // v6.2.5
"symfony/security-bundle": "6.2.*", // v6.2.6
"symfony/serializer": "6.2.*", // v6.2.5
"symfony/twig-bundle": "6.2.*", // v6.2.5
"symfony/ux-react": "^2.6", // v2.7.1
"symfony/ux-vue": "^2.7", // v2.7.1
"symfony/validator": "6.2.*", // v6.2.5
"symfony/webpack-encore-bundle": "^1.16", // v1.16.1
"symfony/yaml": "6.2.*" // v6.2.5
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
"mtdowling/jmespath.php": "^2.6", // 2.6.1
"phpunit/phpunit": "^9.5", // 9.6.3
"symfony/browser-kit": "6.2.*", // v6.2.5
"symfony/css-selector": "6.2.*", // v6.2.5
"symfony/debug-bundle": "6.2.*", // v6.2.5
"symfony/maker-bundle": "^1.48", // v1.48.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/phpunit-bridge": "^6.2", // v6.2.5
"symfony/stopwatch": "6.2.*", // v6.2.5
"symfony/web-profiler-bundle": "6.2.*", // v6.2.5
"zenstruck/browser": "^1.2", // v1.2.0
"zenstruck/foundry": "^1.26" // v1.28.0
}
}
About environment varibale to disable docs (at 7:56).
As far as i know it is not possible for now, as
api_platform
config loaded during a compile time. So it is has not picked up ENV variables, and next configuration does not work:My current sollution, is:
So if you know the solution how to do that with Environment varibales. Please share.