Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #121

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Dev #121

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
node_modules
/node_modules
/config/public.key.json
/config/private.key.json
.env
27 changes: 27 additions & 0 deletions app/config/api_implementation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import axios from 'axios';

// Function to search events using Eventbrite API
async function searchEvents(searchTerm) {
const response = await axios.get(`https://www.eventbriteapi.com/v3/events/search/?q=${searchTerm}&token=YOUR_EVENTBRITE_API_KEY`);
return response.data.events;
}

// Function to search conferences using Conferize API
async function searchConferences(searchTerm) {
const response = await axios.get(`https://api.conferize.com/v1/conferences?search=${searchTerm}`);
return response.data;
}

// Function to search concerts using Songkick API
async function searchConcerts(searchTerm) {
const response = await axios.get(`https://api.songkick.com/api/3.0/events.json?apikey=YOUR_SONGKICK_API_KEY&query=${searchTerm}`);
return response.data.resultsPage.results.event;
}

// Function to search travel locations using TripAdvisor API (Geoservices)
async function searchTravelLocations(searchTerm) {
const response = await axios.get(`https://api.tripadvisor.com/api/partner/2.0/location_search/${searchTerm}?key=YOUR_TRIPADVISOR_API_KEY`);
return response.data.data;
}

export default {searchTravelLocations, searchConcerts, searchEvents, searchConferences}
14 changes: 14 additions & 0 deletions app/config/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import mongoose from "mongoose";

const dbConn = async (req, res) => {
try {
// const connect = await mongoose.connect(process.env.ONLINE_DB);
// const connect = await mongoose.connect(process.env.DB_CONNECTION||process.env.ONLINE_DB);
const connect = await mongoose.connect(process.env.ONLINE_DB);
console.log(`Established connection to database ${connect.connection.host}`), connect.connection.name;
} catch (err) {
console.error(err);
}
};

export default dbConn;
68 changes: 68 additions & 0 deletions app/config/mailer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import nodemailer from 'nodemailer';
import mailGen from 'mailgen';
import dotenv from 'dotenv'

dotenv.config();

const transporter = nodemailer.createTransport({
// host: "smtp.forwardemail.net",
host: "smtp.zoho.com",
service: "Zoho",
port: 465,
secure: true,
auth: {
// TODO: replace `user` and `pass` values from <https://forwardemail.net>
user: process.env.MAILER_USERNAME,
pass: process.env.MAILER_PASSWORD,
}
});

let mailGenerator = new mailGen({
theme: "cerberus",
product: {
name: "TripMatch Experience",
link: "https://tripmatch.com",
logo: ""
}
});

// async..await is not allowed in global scope, must use a wrapper
export default async function main(params) {

var email = {
body: {
name: params.toName || params.toEmail,
intro: params.message || 'Welcome to Mailgen! We\'re very excited to have you on board.',
action: {
instructions: 'To get started with TripMatch, please click here:',
button: {
color: '#22BC66', // Optional action button color
text: 'Confirm your account',
link: params.link
}
},
outro: 'Need help, or have questions? Just reply to this email, we\'d love to help.'
}
};

var emailBody = mailGenerator.generate(email);
// send mail with defined transport object
const info = await transporter.sendMail({
from: "TripMatch Team, " + process.env.MAILER_USERNAME, // sender address
to: params.toEmail, // list of receivers
subject: params.subject, // Subject line
text: params.message, // plain text body
html: `<b>${emailBody}</b>`, // html body
});

console.log("Message sent: %s", info.messageId);
// Message sent: <[email protected]>

//
// NOTE: You can go to https://forwardemail.net/my-account/emails to see your email delivery status and preview
// Or you can use the "preview-email" npm package to preview emails locally in browsers and iOS Simulator
// <https://github.com/forwardemail/preview-email>
//
}

// main().catch(console.error);
17 changes: 17 additions & 0 deletions app/config/private.key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
PR_KEY:`-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgHDKzzEz/Ej6atPybcUpSg0HNIv6ZMv7RVcA1RRSSlppwEazibx7
5fBG7W0Q5METsN8i9qQCxGPmfrTJCselDOoB4OY3jfwN18NOUVWdFzHYxpzIP0gp
MXFSzJho1+HUKqqdclmrluE+MfnRwhvHfXM/2oW6oUepW6buef16/w/XAgMBAAEC
gYAC5DALgtmkxUaXyE8oDrbnPpgKPpD26aoNYOgVbUaaqrtTFKcjPcnXLvpHIXe7
u1V9YtgPvEJsjSwSVlUAaSq7jBISq7tyk7L/5ZxK0v2681r3BPe19s0j4z12sk32
iMYIGnbqd8SMILQPJpexVuO8v8ku5MYjn1qooBLMUA5OgQJBAM2CFWRRLZBd/upT
h5KQyEb02kKbNGbnH+//k8/H8rdb8zM4CKvBQVvfsE//b4EMEV3V0p6NGnPvn4i+
YvAr/gUCQQCMgSQOCd0/rGtOoRdLDNI+BdEpL9IoN59Y17G87HQuZb6nVGJEQE6g
duF712g5epSLx/LPuyAuXp9crYaaReErAkA1VT0X+7lHbh1p0qOsdcaEI6dBAeZn
jjPLpRhHJCzpSQOklzYo3M6JeVPYbwIRC4C2SXePji7/R4CvjDlA+ynBAkACPy5s
awv2sLMmlrzgnlveUgl+Nx2NNxZ9PTXCZ6WT+FyMIHVR0hVvy3bfnBo2kRc/BPuF
BuEE3M5/lObKIMPxAkEAzWDV6Ty7XzlfCMyYcJkryTUg1z00Q5RD59gRUbgnb393
aDPxI31pb8hHKX2OvADyG0TU75YaoIofGGPg7roZ9g==
-----END RSA PRIVATE KEY-----`
}
7 changes: 7 additions & 0 deletions app/config/public.key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
PU_KEY:`
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHDKzzEz/Ej6atPybcUpSg0HNIv6
ZMv7RVcA1RRSSlppwEazibx75fBG7W0Q5METsN8i9qQCxGPmfrTJCselDOoB4OY3
jfwN18NOUVWdFzHYxpzIP0gpMXFSzJho1+HUKqqdclmrluE+MfnRwhvHfXM/2oW6
oUepW6buef16/w/XAgMBAAE=`
}
200 changes: 200 additions & 0 deletions app/controller/auth.controllers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import mongoose from 'mongoose';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import otpGenerator from 'otp-generator';
import userModel from '../models/users.model.js';
import secrete from '../config/public.key.js';
import mailer from '../config/mailer.js';


//Sign up user
const signUpUser = async (req, res, next) => {
let userExists;
const {email, password, confirmPassword} = req.body;

if (!email || !password || !confirmPassword) {
res.status(403).json({message: "All fields are required"});
} else if (!password === confirmPassword) {
res.status(200).json({message: "Both passwords do not match"});
}

try {
userExists = await userModel.findOne({email});
} catch (err) {
console.error(err.message);
}

if (userExists) {
res.status(200).json({message: 'User already exists'});
}
const salt = await bcrypt.genSalt(12);
const hashedPassword = await bcrypt.hash(password, salt);
const user = new userModel({
email,
password: hashedPassword
});

try {
await user.save();
} catch(err) {
res.status(404).json({message: err.message});
}

if (!user) {
res.status(500).json({message: 'Unable to complete registration'});
}

const message = `Thank you for signing up on TripMatch, please click the link bellow to verify your email`;
const params = {
'toEmail': email,
'subject': "TripMatch Registration Notification",
'message': message,
'toName': email,
'link': `http://localhost:9900/api/auth/verify_email/?token=${user._id}&isSet=true`
}
const sendMail = await mailer(params);
console.log(sendMail);
res.status(200).json({message: 'Registration successful, A verification email has been sent to your email address, please verify your email address', data: {id: user._id, email: user.email}});
};

//Login controller
const signInUser = async (req, res, next) => {
let user, data;
const {email, password} = req.body;
try {
user = await userModel.findOne({email});
// const {password, updatedAt, ...dataOb} = user._doc;
data = user._doc;
const validPassword = await bcrypt.compare(password, data.password);
if (!validPassword) {
res.status(403).json({message: 'Invalid password'});
}

const jwtToken = await jwt.sign({
userId: data._id,
userEmail: data.email,
}, secrete.PU_KEY, {expiresIn: '1800s'});
res.status(200).json({message: "Login successful", token: jwtToken});
} catch (err) {
res.status(403).json(err.message);
}
};

const verifyUser = async (req, res, next) => {
const { email} = req.body;
// const { email, password } = req.method = "GET" ? req.query : req.body;
try {
if (!email) {
res.status(403).json({message: "The user's email is required"});
} else {
const exists = await userModel.findOne({ email, isVerified: true });
if (!exists) {
res.status(404).json({message: 'Unknown user or Unverified account'});
} else {
next();
}
}
} catch (error) {
res.status(404).json({message: 'Authentication failed'});
}
};

const verifyUserEmail = async (req, res, next) => {
const { token, isSet} = req.query;
try {
if (!token) {
res.status(500).json({message: "Email verification failed"});
} else {
const exists = await userModel.findOne({ _id: token });
if (!exists) {
res.status(404).json({message: 'Unknown user'});
} else {
const update = await userModel.findByIdAndUpdate(token,{isVerified: isSet}, {new: true});
if (!update) {
res.status(500).json({message:"Email verification Failed"});
} else {
res.status(201).json({message: "Your email has been successfully verified"});
}
}
}
} catch (error) {
res.status(404).json({message: 'Email verification failed'});
}
};

const generateOTP = async (req, res, next) => {
req.app.locals.OTP = await otpGenerator.generate(6, {lowerCaseAlphabets:false, upperCaseAlphabets :false, specialChars:false});
const message = `<p>You received this email because you requested for a password reset.</p><br />
Use the OTP bellow to reset your password <a href="http://localhost:9900/api/auth/verify_email/?token=${user._id}&isSet=true"><h1>${req.app.locals.OTP}</h1></a>`;
const params = {
'toEmail': req.body.email,
'subject': "TripMatch Registration Notification",
'message': message,
'toName': req.body.email
}
const sendMail = await mailer(params);
let msg = "An OTP has been sent to your email address " + sendMail;
res.status(200).json({message: msg});
};

const verifyOTP = async (req, res, next) => {
const {code} = req.body;
if (parseInt(req.app.locals.OTP) === parseInt(code)) {
req.app.locals.OTP = null;
req.app.locals.resetSession = true;
// res.status(200).json({message: "OTP is valid"});
next();
} else {
res.status(400).json({message: "Invalid OTP"});
}
}

const createResetSession = async (req, res) => {
if (req.app.locals.resetSession) {
req.app.locals.resetSession = false;
res.status(200).json({message: "Reset code is sent to your email address"});
} else {
res.status(400).json({message: "Session expired"});
}
}

const resetUserPassword = async (req, res) => {
const { email, password } = req.body;
const salt = await bcrypt.genSalt(12);
const hashedPassword = await bcrypt.hash(password, salt);
if (!req.app.locals.resetSession) {
res.status(500).json({message: 'Invalid session'});
} else {
try {
try {
await userModel.findOne({ email })
.then(user =>{
userModel.findByIdAndUpdate(user._id, {password:hashedPassword},{new: true})
.then(result => {
res.status(200).json({message: "Password reset successful "});
})
.catch(err =>
res.status(404).json({message: "Unable to reset password " + result.error})
)
})
.catch(err => {
res.status(404).json({message: "Unknown email address"});
});
} catch (err) {
res.status(500).json({err});
}
} catch (error) {
res.status(400).json({ error: error });
}
}
}

function localVariables (req, res, next) {
req.app.locals = {
OTP: null,
resetSession: false,
}
next();
}

export default {signUpUser, signInUser, verifyUser, localVariables, generateOTP, verifyOTP, createResetSession, resetUserPassword, verifyUserEmail};
Loading