Do somthings

Introduction

In this tutorial, we’ll walk through the process of creating a user registration system with a Flutter frontend and a Node.js backend, using PostgreSQL as our database. We’ll cover everything from setting up the backend and database, to connecting it with the Flutter frontend. By the end of this tutorial, you’ll have a complete, working registration system where users can create accounts, and their information will be stored securely in PostgreSQL.

What You’ll Learn:

  • Setting up PostgreSQL and creating a user table.
  • Building a Node.js backend using Express to handle user registration and authentication.
  • Connecting Flutter frontend to your backend API for user registration.
  • Hashing user passwords with SHA-256 for secure storage.

Step 1: Setting Up the PostgreSQL Database

Creating a PostgreSQL Database and Table

Before we start with the code, we need to set up the PostgreSQL database. You can do this by running the following SQL commands:

-- Create the database
CREATE DATABASE myapp;

-- Switch to the new database
\c myapp;

-- Create a users table
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  firstname VARCHAR(100),
  lastname VARCHAR(100),
  email VARCHAR(100) UNIQUE NOT NULL,
  phonenumber VARCHAR(15) UNIQUE NOT NULL,
  password VARCHAR(255) NOT NULL,
  status BOOLEAN DEFAULT FALSE
);

Here, we’re creating a users table with fields for firstname, lastname, email, phonenumber, password, and status. Notice that email and phonenumber are unique.

Screenshot Caption: The PostgreSQL database setup with the users table.

Step 2: Setting Up the Backend with Node.js and Express

Initialize Node.js Project

Create a new folder for the backend and initialize it with npm:

mkdir myapp-backend
cd myapp-backend
npm init -y

Install Dependencies

We’ll need a few packages to get started:

npm install express pg bcrypt express-validator dotenv helmet
  • express: Web framework for Node.js.
  • pg: PostgreSQL client for Node.js.
  • bcrypt: To hash passwords securely.
  • express-validator: For validating input.
  • dotenv: To manage environment variables securely.
  • helmet: To secure our API.

Creating the Server

Here’s the server.js file that sets up the Express server and API routes:

require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const helmet = require('helmet');
const authRoutes = require('./routes/authRoutes');

const app = express();

app.use(bodyParser.json());
app.use(helmet());

// Routes
app.use('/api/auth', authRoutes);

app.listen(3000, () => console.log('Server running on port 3000'));

Screenshot Caption: The backend setup for handling requests.

Creating the Authentication Routes

Now let’s create routes to handle registration and login in authRoutes.js:

const express = require('express');
const { body } = require('express-validator');
const { register } = require('../controllers/authController');

const router = express.Router();

router.post('/register', [
  body('firstname').isString().notEmpty(),
  body('lastname').isString().notEmpty(),
  body('email').isEmail(),
  body('phonenumber').isMobilePhone(),
  body('password').isLength({ min: 6 })
], register);

module.exports = router;

Step 3: Hashing the Password with SHA-256 in Node.js

We’re going to use SHA-256 for password hashing. The password will be hashed before being stored in the database to ensure security.

Here’s the code to handle the registration process and password hashing in authController.js:

const { validationResult } = require('express-validator');
const pool = require('../models/db');
const crypto = require('crypto');

// Register User
exports.register = async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  const { firstname, lastname, email, phonenumber, password } = req.body;
  const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');

  try {
    const result = await pool.query(
      `INSERT INTO users (firstname, lastname, email, phonenumber, password, status)
      VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`,
      [firstname, lastname, email, phonenumber, hashedPassword, false]
    );

    res.status(201).json({ message: 'User registered successfully', user: result.rows[0] });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Database error' });
  }
};
How to Build a Full-Stack User Registration System with PostgreSQL and Flutter

Step 4: Setting Up the Flutter Frontend

Flutter Folder Structure

Before we start coding the front end, let’s first decide on a clean folder structure for the Flutter project.

How to Build a Full-Stack User Registration System with PostgreSQL and Flutter

Screenshot Caption: The folder structure of the Flutter project, with key files like DatabaseConnection.dart and RegisterPage.dart.

When you done for this process then check to connection or start the server like:

itfox-technology@Itfox-Technologys-MacBook-Pro trimio_test % cd backend
itfox-technology@Itfox-Technologys-MacBook-Pro backend % node server.js
Server running on port 3000
How to Build a User Registration System with PostgreSQL and Flutter

Register Page UI

In RegisterPage.dart, we create the form for the user to enter their information. The form includes validation for the name, email, phone number, and password. The password is hashed on the frontend using SHA-256 before being sent to the backend.

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:crypto/crypto.dart';

class RegisterPage extends StatefulWidget {
  @override
  _RegisterPageState createState() => _RegisterPageState();
}

class _RegisterPageState extends State<RegisterPage> {
  final _formKey = GlobalKey<FormState>();
  final TextEditingController _firstnameController = TextEditingController();
  final TextEditingController _lastnameController = TextEditingController();
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _phoneController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  
  bool loading = false;

  void _registerUser() async {
    if (_formKey.currentState!.validate()) {
      setState(() {
        loading = true;
      });

      final hashedPassword = _hashPassword(_passwordController.text);

      try {
        final response = await http.post(
          Uri.parse('http://localhost:3000/api/auth/register'),
          headers: {'Content-Type': 'application/json'},
          body: jsonEncode({
            'firstname': _firstnameController.text,
            'lastname': _lastnameController.text,
            'email': _emailController.text,
            'phonenumber': _phoneController.text,
            'password': hashedPassword,
          }),
        );

        if (response.statusCode == 201) {
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
            content: Text('Registration successful!'),
            backgroundColor: Colors.green,
          ));
        } else {
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
            content: Text('Registration failed'),
            backgroundColor: Colors.red,
          ));
        }
      } catch (e) {
        setState(() {
          loading = false;
        });
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('An error occurred: $e'),
          backgroundColor: Colors.red,
        ));
      }
    }
  }

  String _hashPassword(String password) {
    final bytes = utf8.encode(password); // Convert to UTF-8
    final hashedPassword = sha256.convert(bytes).toString(); // Hash the password
    return hashedPassword;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Register')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              // Input fields for Firstname, Lastname, Email, Phone, Password
              // (Similar to the code in your original `RegisterPage.dart`)
              // Register Button
            ],
          ),
        ),
      ),
    );
  }
}

Step 5: How the Registration Process Works

Here’s a quick GIF demonstrating how the user can register by filling out the form and hitting the “Register” button.

How to Build a Full-Stack User Registration System with PostgreSQL and Flutter

Sure! Here’s a structured article outline for the tutorial, complete with explanations for each step and suggestions for images and gifs to enhance the content. The goal is to break the process into digestible steps, so the reader can follow along easily and stay engaged. I’ll also recommend where the screenshots and gifs could be placed for maximum effect.


Conclusion

In this tutorial, we’ve walked through the entire process of building a user registration system with a PostgreSQL database, a Node.js backend, and a Flutter frontend. We learned how to securely hash passwords, create API routes for user registration, and how to connect Flutter to the backend using HTTP requests.

Key Takeaways:

  • PostgreSQL for storing user data.
  • SHA-256 hashing to securely store passwords.
  • Express.js to create a RESTful API.
  • Flutter to build a beautiful registration page and handle API calls.

By following the steps in this guide, you can now create your own user registration system and further expand it to include user authentication, profile management, and more!

❤️❤️ Thanks for reading this article ❤️❤️

If I got something wrong? Let me know in the comments. I would love to improve 🥰🥰🥰.

Clap 👏👏👏 If this article helps you,

if you like our work, please follow us on this Dosomthings

Our more attractive articles:

Connection between Flutter & PostgreSQLHow to create connection between Flutter & PostgreSQL.

Date & Time in FlutterHow to Format Date and Time in Flutter

Drag and Drop in FlutteHow to Implement Drag and Drop in Flutter