- Added member profile GET/PATCH/POST /api/user/current/member_profile editable endpoint with QR
- Added images upload in upload_images field in PATCH /api/user/current/member_profile accepting existing URLs and base64 images.
- Added GET /api/member_projects/ endpoint with public member projects list
- Added GET /api/member_projects// endpoint with public member project detail
- Added qr regeneration in GET /api/user/current/reset_qr/
- Added legal section in GET /api/legal
- Added "email" field to stripe customer integration
- Added image processing to normalize images in backend (all converted to .jpeg and resized to 1920, 1080 FHD)
- Added REDIS database for caching api responses.
- Refactored to new infrastructure with secret-files
- Email texts updated
python manage.py test
Para poner en marcha la API, ejecutar al menos una vez:
python manage.py migrate
python manage.py compilemessages
python manage.py collectstatic
python manage.py runserver
Dataset inicial con datos reales:
python manage.py loadlocal
python manage.py dumpdata --indent 2 > demo.json
python manage.py loaddata demo.json
La localización depende únicamente del cliente, aunque se puede guardar un
lenguage preferido en /api/users/current/
El lenguage preferido se puede cambiar haciendo un PATCH e indicando el código de lenguage "es" (español), "ca" (catalán) o "en" (inglés):
PATCH /api/users/current/
--form "language": "es"
Para consultar el lenguage preferido por el usuario si lo hubiese:
GET /api/users/current/
Documentación SWAGGER de la API:
localshot:8000/api/docs
localhost:8000/admin
Para acceder al admin panel hay que tener un usuario admin. Para ello, desde django:
python manage.py createsuperuser
o desde docker:
docker-compose run --rm backend python manage.py createsuperuser
El método de authenticación es json-web-token (JWT) implementado por: DRF-SimpleJWT
Pasos para autenticar:
- POST request con la siguiente estructura:
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "whateveruser", "password": "whateverpassword"}' \
http://<ameba-site>:8000/api/token/
Response:
{
"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU",
"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"
}
- Almacenar access y refresh token en el browser local storage.
- Usar el access token en todas las siguientes requests, como "Authorization" header:
curl \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU" \
http://localhost:8000/api/some-protected-view/
- Cuando access token expira, se usa el refresh token para obtener un nuevo access token:
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"}' \
http://localhost:8000/api/token/refresh/
Response:
{"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNTY3LCJqdGkiOiJjNzE4ZTVkNjgzZWQ0NTQyYTU0NWJkM2VmMGI0ZGQ0ZSJ9.ekxRxgb9OKmHkfy-zs1Ro_xs1eMLXiR17dIDBVxeT-w"}