Account CRUD - pmvdbijl7/matching-app GitHub Wiki

Create an Account

On the login page there is an option to Sign up if the user hasn't already made an account. From there they can first fill a form just to create an account, after that the user is asked to login with the credentials they gave while creating an account.

Code:

The function in the authController used for the client's GET request to send Create Account the page:

// Get Register Page
const registerGet = (req, res) => {
        res.render('pages/auth/register', { title: 'Create an Account' });
};

The function in the authController used for the client's POST request to save the Create Account form data in the database:

// Register New User
const registerPost = async (req, res) => {
	// Validate Register Data
	const { error } = registerValidation(req.body);
	if (error) return res.status(400).send(error.details[0].message);

	// Hash Password
	const salt = await bcrypt.genSalt(10);
	const hashedPassword = await bcrypt.hash(req.body.password, salt);

	// Create New User
	const user = new User({
		name: req.body.name,
		email: req.body.email,
		password: hashedPassword,
	});

	user.save()
		.then((user) => {
			// Redirect to Home
			res.redirect('/signin');
		})
		.catch((err) => {
			res.send(err.message);
		});
};

Create Account form:

Form for creating an account

Create a Profile

When the user is logged in for the first time and the profile data hasn't been added to the database they will be directed to the page were you can enter profile data, like their birthdate or residence.

Code:

The function in the authController used for the client's GET request to send the Create Profile page:

// Get Preferences Page
const preferencesGet = (req, res) => {

	Genre.find((err, genres) => {
		res.render('pages/auth/preferences', {
			title: 'Preferences',
			genders: ['Male', 'Female', 'Non-binary'],
			interests: ['Men', 'Women', 'Everyone'],
			genres: genres
		});
	});
};

The function in the authController used for the client's POST request to save the Create Profile form data in the database:

// Update Preferences
const preferencesPost = (req, res) => {

	// Validate Preferences Data
	const { error } = preferencesValidation(req.body);
	if (error) return res.status(400).send(error.details[0].message);

	// Get Authenticated User
	const authUser = req.user._id;

	// Update User
	User.findByIdAndUpdate(authUser, {
		gender: req.body.gender,
		birthdate: req.body.birthdate,
		residence: req.body.residence,
		interested_in: req.body.interested_in,
		biography: req.body.biography,
		genres: req.body.genres
	})
		.then((user) => {
			res.redirect('/');
		})
		.catch((err) => {
			res.send(err.message);
		});
};

Create Profile form:

Form for creating a profile

Read other profiles

On the home page of the application other users their profile data is read from the database and sent to the client.

Code:

The function in the homeController used for the client's GET request to send the Home page with data from other accounts:

// Get Home page with data from other users
const homeGet = (req, res) => {
	const authUser = req.user._id;

	User.find((err, docs) => {
		if (!err) {
			res.render('pages/home', {
				title: 'Home',
				users: docs,
				authUser: authUser,
				headerLeft: { path: '/logout', text: 'Log out' },
				headerRight: { path: '/matches', text: 'Matches' },
			});
		} else {
			console.log('Error in retrieving profile data: ' + err);
		}
	});
};

Reading profiles from database into the application:

Reading profiles from database into the application

Update an Account and Profile

On this page users can edit and update their account and profile data with a form.

Code:

The function in the accountController used for the client's GET request to send the Edit Account page with the user's current set data:

// Get account edit page
const editGet = (req, res) => {
	const authUser = req.user._id;

	Genre.find((err, genres) => {
	User.findById(authUser).then((user) => {
		res.render('pages/account/edit', {
			title: 'Edit your profile',
			user: user.toJSON(),
			headerLeft: { path: '/account/profile', text: 'Back' },
			optionsRight: [{ path: '/account/edit-password', text: 'Edit password' },{ path: '/account/delete', text: 'Delete' }],
			interests: ['Men', 'Women', 'Everyone'],
			genders: ['Male', 'Female', 'Non-binary'],
			genres: genres
		});
	});
	});
};

Part of the EJS code that inserts the currently saved gender data in the form where the corresponding radio button is checked:

<%for(i=0; i < genders.length; i++){ %>
                                <div class="radio-group">
                                    <input type="radio" id="<%= genders[i] %>" name="gender" value="<%= genders[i] %>" <% if (user.gender == genders[i]){ %> checked <% } %> required>
                                    <label for="<%= genders[i] %>">
                                        <%= genders[i] %>
                                    </label>
                                </div>
                                <% } %>

The function in the accountController used for the client's POST request to update the current data in the database with the new Edit Profile form data:

// Update account profile data
const editPost = (req, res) => {
	const authUser = req.user._id;

    // Validate Edit data
	const { error } = editValidation(req.body);
	if (error) return res.status(400).send(error.details[0].message);

	User.findById(authUser).then((result) => {
		User.findByIdAndUpdate(authUser, {
			profile_image: req.file ? req.file.filename : result.profile_image,
			name: req.body.name,
			email: req.body.email,
			gender: req.body.gender,
			birthdate: req.body.birthdate,
			residence: req.body.residence,
			interested_in: req.body.interested_in,
			biography: req.body.biography,
			genres: req.body.genres,
		}).then((updatedUser) => {
			res.redirect('/account/profile');
		});
	});
};

Form for updating account and profile details:

Form for updating account and profile details

Delete an Account

For the user to delete their account they can enter a form with their password twice and confirm for deletion.

Code:

The function in the accountController used for the client's GET request to send the Delete Account page:

// Get delete account page
const deleteGet = (req, res) => {
	const authUser = req.user._id;

	User.findById(authUser).then((user) => {
		res.render('pages/account/delete', {
			title: 'Advanced account settings',
			user: user.toJSON(),
			headerLeft: { path: '/account/profile', text: 'Back' },
		});
	});
};

The function in the accountController used for the client's POST request to send the password and the repeated password data to the server and check if their both the same, if this is true the account will be deleted:

// Delete account data
const deletePost = async (req, res) => {
	const authUser = req.user._id;
	const { error } = deleteValidation(req.body);
	if (error) return res.status(400).send(error.details[0].message);

	// Check if Password is Correct
	const user = await User.findById(authUser).exec();
	console.log(req.body.password, user.password);
	const validPass = await bcrypt.compare(req.body.password, user.password);
	if (!validPass) return res.status(400).send("Your password isn't valid.");

	User.findByIdAndRemove(authUser, (error, doc) => {
		if (!error) {
			res.redirect('/logout');
		} else {
			console.log(
				'Error: No or invalid profile id given. Profile id: ' +
					req.body._id
			);
		}
	});
};

Form for deleting an account:

Form for deleting an account

⚠️ **GitHub.com Fallback** ⚠️