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' });
}
};
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.
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
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.
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 & PostgreSQL: How to create connection between Flutter & PostgreSQL.
Date & Time in Flutter: How to Format Date and Time in Flutter
Drag and Drop in Flutte: How to Implement Drag and Drop in Flutter