You are currently viewing Part 2: User registration and database models – Building the foundation of your microservice

Part 2: User registration and database models – Building the foundation of your microservice

  • Post author:
  • Post category:Python

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__.pyapp/models.py, and app/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.pyto 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.

  1. Open the SQLite database using a tool like DB Browser for SQLite.
  2. 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