News aggregator è una web application creata con Symfony 5.2 e permette di raccogliere un'insieme di articoli, scriverne a tua volta altri e commentare.
Il progetto contiene un'insieme di componenti che andrò ad elencare in dettaglio
Per rendere il progetto facilmente fruibile a terzi è stato predisposto un container docker con al suo interno:
- Nginx (web server)
- MariaDB (database relazionale)
- PHP 8.0.3
- MailHog (testing email)
Tale docker espone i servizi di default sulle porte indicate su
docker-compose.override.yml.dist
ma possono essere sovrascritte sudocker-compose.override.yml
.
Gli endpoint esposti sono:
docker-composer up -d
La struttura relazionale del progetto prevede l'uso di tre entity:
- User (contenente gli utenti registrati in piattaforma con ruoli diversi:
ROLE_ADMIN
oROLE_USER
)- Article (contenente tutti gli articoli scritti da utenti registrati in piattaforma)
- Comment (contenente tutti i commenti associati agli articoli che possono essere aggiunti anche da utenti non loggati in piattaforma)
I cambiamenti alla struttura del db sono stati gestiti attraverso le migration in modo da avere lo schema sempre consistente ad ogni release del codice
symfony console doctrine:database:create
symfony console doctrine:migrations:migrate --no-interaction
Per avere una base di dati di partenza sulla quale fare i test sono state caricate delle fixtures:
- 10 users (alcuni in soft-delete)
- 1 admin
- 10 articles
- 50 comments
symfony console doctrine:database:drop --force
symfony console doctrine:database:create
symfony console doctrine:migrations:migrate --no-interaction
symfony console doctrine:fixtures:load --no-interaction
E' stato creato anche un metodo per riempire il database degli articoli partendo da Feed RSS. Passando quindi un qualsiasi url standard RSS 2.0 verranno creati gli articoli in piattaforma Un esempio di importazione è:
symfony console app:import-rss-news "https://news.google.com/rss?hl=it&gl=IT&ceid=IT:it"
L'autenticazione è stata gestita attraverso JWT. Interrogando l'endpoint
POST /v1/auth/login
passando:{ "username": "admin@newsaggregator.local", "password": "admin" }ottengo un token JWT fruibile attraverso
Authorization: Bearer
nelle chiamate che richiedono l'autenticazione.
Le API sono state costruite attraverso FOSRestBundle e la loro documentazione attraverso NelmioApiDocBundle. Quest'ultima libreria esporrà sia la documentazione in OpenApi (/doc.json) sia un tool visuale (raggiungibile sotto /doc) dove provare ciascun endpoint.
Le risposte alle interrogazioni delle API sono compliant al formato HATEOAS REST. Nel caso di una collezione di elementi HATEOAS gestirà anche la parte di paginazione degli elementi.
Per interagire con le API di creazione/modifica di ciascuna entità ci si è avvalsi dei Data Transfer Object. In questo modo i dati passati dall'utente sono prima validati
#SPA
Per la parte Frontend di visualizzazione dei contenuti si è scelto di costruire una Single Page Application. Tale SPA è stata costruita basandosi su Preact e Symfony Encore esponendo due pagine pubbliche:
- Home con la lista di tutti gli articoli presenti in piattaforma (basata sull'api
GET /v1/public/articles
)- Article con il dettaglio di un singolo articolo e tutti i commenti su di esso applicati (basata sull'api
GET /v1/public/articles/{parentId}/comments
)
Per permettere che la SPA possa accedere alle API è stato necessario configurare CORS e mettere tra i domini "allowed"
news-aggregator.local
. La gestione è demandata a NelmioCorsBundle
cd spa && API_ENDPOINT=http://api.news-aggregator.local:8082/ yarn encore dev
- PHP 8.0.0 or higher;
- and the usual Symfony application requirements.
#Altri comandi utili
mkdir -p config/jwt
openssl genpkey -out config/jwt/private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096 -pass pass:${JWT_PASSPHRASE}
openssl pkey -in config/jwt/private.pem -out config/jwt/public.pem -pubout -passin pass:${JWT_PASSPHRASE}
symfony composer dump-env ${APP_ENV}
symfony console cache:clear
👤 Fabiano Roberto
- Twitter: @dr_thief
- Github: @fabianoroberto
This README was generated with ❤️ by readme-md-generator