A RESTful API built with Flask and MongoDB that handles user management operations. The API provides secure endpoints for creating, reading, updating, and deleting user resources with JWT authentication and proper input validation.
- Flask: Lightweight WSGI framework that allows for modular design through blueprints
- flask-smorest: Modern approach to building REST APIs with automatic OpenAPI documentation and robust request/response validation
- flask-jwt-extended: JWT implementation for secure authentication
- marshmallow: Schema-based serialization/deserialization and validation
- MongoDB: Document database that provides flexibility for future schema changes
- pymongo: Python driver for MongoDB
- passlib: Password hashing using PBKDF2-SHA256 (chosen over bcrypt due to better performance characteristics on modern hardware)
- python-dotenv: Environment variable management, separating configuration from code
- Clone the repository
- Generate a random secret key for JWT_SECRET_KEY:
python -c 'import secrets; print(secrets.token_hex(64))'
- Create
.env
file with keyJWT_SECRET_KEY
- Run with Docker:
docker compose up --build
- Use
sudo
if you get permission error:
sudo docker compose up --build
Available at 0.0.0.0:5000/swagger-ui
when running in development mode.
POST /api/v1/users
- Create userGET /api/v1/users
- List users (requires auth)GET /api/v1/users/<id>
- Get user (requires auth)PUT /api/v1/users/<id>
- Update user (requires auth)DELETE /api/v1/users/<id>
- Delete user (requires auth)POST /api/v1/login
- Authenticate user
In a new Terminal:
poetry run pytest
- Fork the repository
- Create feature branch
- Submit pull request with tests
MIT
Watchdog provides a faster, more efficient reloader for the development server.
https://flask.palletsprojects.com/en/stable/cli/
.flaskenv
should be used for public variables, such asFLASK_APP
, while.env
should not be committed to your repository so that it can set private variables. ... The files are only loaded by theflask
command or callingrun()
. If you would like to load these files when running in production, you should callload_dotenv()
manually.
https://github.com/spec-first/connexion -> doesnt really need Flask. Supports Flask.
https://github.com/noirbizarre/flask-restplus -> unmaintained
https://github.com/flask-restful/flask-restful -> unmaintained
https://github.com/marshmallow-code/flask-smorest -> chosen
https://github.com/python-restx/flask-restx -> doesnt support latest OpenAPI spec
https://github.com/apiflask/apiflask -> isn't specific to RESTful APIs\
https://www.reddit.com/r/flask/comments/1e6ct0s/comment/ldsle2p/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button Why use a library to build REST APIs? Because they do a lot of heavy lifting. Good API libraries have robust data validation models, handle URL and query parameters, support OpenAPI semantics, and generate documentation from code.
In principle, REST APIs are pretty simple. Just a collection of endpoints, query and path parameters, and payloads. The devil is in the details. What happens if your API accepts the wrong data type or format in a payload? What if it accepts malformed data? What about additional properties? There are so many things that can go wrong from a functional and especially a security perspective. Good API libraries don't take these problems away, but they give you the tools to work through them.
https://apiflask.com/comparison/
https://www.mongodb.com/developer/languages/python/flask-python-mongodb/
https://realpython.com/flask-connexion-rest-api/
https://python.plainenglish.io/flask-restful-apis-72e05f8d41fa \
“As long as the method is being used according to its own definition, REST doesn’t have much to say about it.” — Roy Fielding
Best Tutorial ever on Flask and RESTful APIs (goldmine of information on just about everything related to Flask and RESTful APIs)
https://aaronluna.dev/series/flask-api-tutorial/overview/
https://aaronluna.dev/series/flask-api-tutorial/part-5/
-> https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven \
https://aaronluna.dev/series/flask-api-tutorial/part-3/
-> https://stackoverflow.com/questions/2001773/understanding-rest-verbs-error-codes-and-authentication?noredirect=1&lq=1
https://dev.to/sparkpost/restful-api-versioning-best-practices-why-v1-is-1
-
Breaking Changes (Very Bad)
- A new required parameter
- A new required key in POST bodies
- Removal of an existing endpoint
- Removal of an existing endpoint request method
- A materially different internal behavior of an API call – such as a change to the default behavior.
-
NOT Breaking Changes (Good)
- A new resource or API endpoint
- A new optional parameter
- A change to a non-public API endpoint
- A new optional key in the JSON POST body
- A new key returned in the JSON response body
-
Separating Deployment from Release
https://datatracker.ietf.org/doc/html/rfc7519 https://jwt.io/
http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
failed to connect to cluster. Then switced to local mongoDB.