Welcome to Part 2 of the tutorial series: “Build a Production-Ready User Management Microservice with Flask and SQLAlchemy: A Step-by-Step Guide”. In this part, we’ll dive into designing the User model, implementing user registration, and securing passwords using Werkzeug. By the end of this tutorial, you’ll have a fully functional user registration system and a solid understanding of how to interact with your database using SQLAlchemy.
What you learn in part 2
- How to design and implement the
User
model using SQLAlchemy. - How to create a user registration endpoint with CRUD operations.
- How to securely hash passwords using Werkzeug.
- How to test the registration endpoint using
curl
.
Prerequisites
Before we begin, ensure you’ve completed Part 1 of the series. You should have:
- A Flask application with SQLAlchemy configured.
- A basic project structure with
app/__init__.py
,app/models.py
, andapp/routes.py
. - A running Flask application with a
/api/test
endpoint.
Step 1: Design the user model
In Part 1, we created a basic User
model. Let’s expand it to include password hashing and additional methods.
Updateapp/models.py
to have the following code snippet:
from . import db from werkzeug.security import generate_password_hash, check_password_hash class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False) def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password) def __repr__(self): return f'<User {self.username}>'
This code defines a User
model in a Flask application and uses Werkzeug’s security functions to handle password hashing and verification. It imports generate_password_hash
and check_password_hash
from werkzeug.security
to securely manage user passwords. The set_password
method hashes a given password using generate_password_hash
and stores it in the password_hash
field. The check_password
method verifies a provided password by comparing it against the stored hash using check_password_hash
. This approach ensures that the application does not store plain-text passwords, improving security.
Step 2: Implement user registration
Now, let’s create a user registration endpoint in app/routes.py
.
Update app/routes.py
to have the following code snippet:
from flask import Blueprint, request, jsonify from .models import User from . import db bp = Blueprint('api', __name__, url_prefix='/api') @bp.route('/test', methods=['GET']) def test(): return jsonify({"message": "Welcome to the user management microservice"}) @bp.route('/register', methods=['POST']) def register(): data = request.get_json() # Validate input if not data or 'username' not in data or 'email' not in data or 'password' not in data: return jsonify({"error": "Username, email, and password are required"}), 400 # Check if username or email already exists if User.query.filter_by(username=data['username']).first(): return jsonify({"error": "Username already exists"}), 400 if User.query.filter_by(email=data['email']).first(): return jsonify({"error": "Email already exists"}), 400 # Create a new user new_user = User(username=data['username'], email=data['email']) new_user.set_password(data['password']) db.session.add(new_user) db.session.commit() return jsonify({ "id": new_user.id, "username": new_user.username, "email": new_user.email }), 201
This code defines a user registration endpoint at /api/register
. It validates the input, checks for duplicate usernames or emails, and returns errors if necessary. If the data is valid, it creates a new User
, hashes the password with set_password
, saves the user to the database, and responds with the user’s ID, username, and email.
Step 3: Test the registration endpoint
Let’s test the /api/register
endpoint using curl
or Postman. Start the application by running python run.py
.
Using curl
curl -X POST -H "Content-Type: application/json" -d '{"username": "testuser", "email": "test@example.com", "password": "testpass"}' http://127.0.0.1:5000/api/register
This cURL command sends a POST request to the /api/register
endpoint of a Flask application running on http://127.0.0.1:5000
. It includes a JSON payload with a username
, email
, and password
. The -H "Content-Type: application/json"
header specifies that the request body is in JSON format. The -d
flag sends the JSON data, allowing the server to process the registration request and create a new user.
Expected Response
{ "id": 1, "username": "testuser", "email": "test@example.com" }
Step 4: Verify the database
After registering a user, verify that the data is correctly stored in the database.
- Open the SQLite database using a tool like DB Browser for SQLite.
- Check the
user
table to ensure the new user’s details (including the hashed password) are stored.
Full Code for Part 2
You can find the complete code for this tutorial in the GitHub repository.
What’s Next?
In Part 3, we’ll implement user authentication using JSON Web Tokens (JWT). Stay tuned! 🚀
Facebook Comments