diff --git a/account/server/config/passport-strategies/local.js b/account/server/config/passport-strategies/local.js index 21c5bc7..7af2c50 100644 --- a/account/server/config/passport-strategies/local.js +++ b/account/server/config/passport-strategies/local.js @@ -5,34 +5,34 @@ const LocalStrategy = require("passport-local").Strategy; const User = require("../../models/user"); - /* - By default, LocalStrategy expects to find credentials in parameters named username and password. - If your site prefers to name these fields differently, options are available to change the defaults. - */ +/* +By default, LocalStrategy expects to find credentials in parameters named username and password. +If your site prefers to name these fields differently, options are available to change the defaults. +*/ const local = new LocalStrategy({ - usernameField: "email" - }, (email, password, done) => { - User.findOne({ - $or: [{ - email - }, { - local: { - email - } - }] - }, (err, user) => { - if(!user) { - console.error("Auth Error - user not found: " + email); - return done(null, false, { message: `Invalid email or password` }) + usernameField: "email" +}, async (email, password, done) => { + console.log(`${email} ${password}`); + const user = await User.findOne({ + $or: [{ + email + }, { + local: { + email + } + }] + }); + if (!user) { + console.error("Auth Error - user not found: " + email); + return done(null, false, { message: `Invalid email or password` }) + } + user.comparePassword(password, (err, isMatch) => { + if (isMatch) { + return done(null, user) + } else { + console.error("Auth Error - password mismatch: " + email); + return done(null, false, { message: "Invalid email or password" }) } - user.comparePassword(password, (err, isMatch) => { - if (isMatch) { - return done(null, user) - } else { - console.error("Auth Error - password mismatch: " + email); - return done(null, false, { message: "Invalid email or password" }) - } - }) - }) - }) + }) +}) module.exports = local; \ No newline at end of file diff --git a/account/server/controllers/users.js b/account/server/controllers/users.js index 51cbf7a..0ab4860 100644 --- a/account/server/controllers/users.js +++ b/account/server/controllers/users.js @@ -17,7 +17,7 @@ const mailjet = new Mailjet({ -exports.isLoggedIn = function(req, res, next) { +exports.isLoggedIn = function (req, res, next) { if (req.isAuthenticated()) return next(); res.redirect("/login"); }; @@ -25,7 +25,7 @@ exports.isLoggedIn = function(req, res, next) { // ------------------------------------------- -exports.authenticated = function(req, res, next) { +exports.authenticated = function (req, res, next) { res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate'); console.log("account/server/controllers/users.js - exports.authenticated() Auth check for user: " + req.user + " is: " + req.isAuthenticated()); if (req.isAuthenticated()) { @@ -60,11 +60,13 @@ exports.authenticated = function(req, res, next) { } } -exports.login = function(req, res, next) { +exports.login = function (req, res, next) { // Do email and password validation for the server - passport.authenticate("local", function(err, user, info) { + + passport.authenticate("local", function (err, user, info) { if (err) return next(err); if (!user) { + console.log("No user"); return res.json({ success: false, message: info.message @@ -81,6 +83,7 @@ exports.login = function(req, res, next) { req.login(user, loginErr => { if (loginErr) { + console.log("error") return res.json({ success: false, message: loginErr @@ -124,199 +127,217 @@ exports.login = function(req, res, next) { })(req, res, next); }; -exports.confirmEmail = function(req, res, next) { +exports.confirmEmail = async function (req, res, next) { const userId = req.params["userId"]; const token = req.params["token"]; - User.findById(userId, (err, user) => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - if (user.confirmEmail) { - console.log("User already confirmed email: " + userId); - res.json({ - success: false, - message: "already confirmed email" - }); - return; - } - const today = new Date(); - if (user.confirmEmailTTL < today) { - res.json({ - success: false, - message: "token expired" - }); - return; - } - if (user.confirmEmailToken != token) { - console.log( - "Token Mismatch DB: " + user.confirmEmailToken + " submitted: " + token - ); - res.json({ - success: false, - message: "token mismatch" - }); - return; - } - user.confirmEmail = true; - user.confirmEmailToken = ""; - user.save(err => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - console.log("User: " + user.email + " confirmed email address"); - res.json({ - success: true - }); - return; + let user = await User.findById(userId).catch(err => { + console.error(err); + res.status(404); + res.json({ + success: false, + message: err }); + return; + }); + + if (!user) { + console.error("User not found: " + userId); + res.status(404); + res.json({ + success: false, + message: "User not found" + }); + return; + } + if (user.confirmEmail) { + console.log("User already confirmed email: " + userId); + res.status(500); + res.json({ + success: false, + message: "already confirmed email" + }); + return; + } + const today = new Date(); + if (user.confirmEmailTTL < today) { + res.status(500); + console.error("Expired token for confirming email: " + userId); + res.json({ + success: false, + message: "token expired" + }); + return; + } + if (user.confirmEmailToken != token) { + console.error( + "Token Mismatch DB: " + user.confirmEmailToken + " submitted: " + token + ); + res.json({ + success: false, + message: "token mismatch" + }); + return; + } + user.confirmEmail = true; + user.confirmEmailToken = ""; + await user.save().catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err + }); + return; + }); + + console.log("User: " + user.email + " confirmed email address"); + res.json({ + success: true }); }; -exports.resetPassword = function(req, res, next) { +exports.resetPassword = async function (req, res, next) { const userId = req.params["userId"]; const token = req.params["token"]; - User.findById(userId, (err, user) => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - - const today = new Date(); - if (user.resetPasswordTTL < today) { - res.json({ - success: false, - message: "token expired" - }); - return; - } - if (user.resetPasswordToken != token) { - console.log( - "Token Mismatch DB: " + user.resetPasswordToken + " submitted: " + token - ); - res.json({ - success: false, - message: "token mismatch" - }); - return; - } - - user.password = req.body.password - user.confirmEmail = true; - user.confirmEmailToken = ""; - user.resetPasswordToken = ""; - user.save(err => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - res.json({ - success: true - }); - return; + let user = await User.findById(userId).catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err }); + return; }); + + if (!user) { + console.error("User not found: " + userId); + res.status(404); + res.json({ + success: false, + message: "User not found" + }); + return; + } + const today = new Date(); + if (user.resetPasswordTTL < today) { + res.status(500); + res.json({ + success: false, + message: "token expired" + }); + return; + } + if (user.resetPasswordToken != token) { + console.log( + "Token Mismatch DB: " + user.resetPasswordToken + " submitted: " + token + ); + res.status(500); + res.json({ + success: false, + message: "token mismatch" + }); + return; + } + + user.password = req.body.password + user.confirmEmail = true; + user.confirmEmailToken = ""; + user.resetPasswordToken = ""; + await user.save().catch(err => { + console.error(err); + res.json({ + success: false, + message: err + }); + return; + }); + res.json({ + success: true + }); + return; }; // ------------------------------------------- -exports.sendResetPassword = function(req, res, next) { - User.findOne({ +exports.sendResetPassword = async function (req, res, next) { + let user = await User.findOne({ email: req.body.email - }, (err, user) => { - if (err) { + }).catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err + }); + return; + }); + if (!user) { + console.error("Reset password failed. No user: " + req.body.email); + res.status(404); + res.json({ + success: false, + message: "No account register for " + req.body.email + }); + return; + } + const buffer = crypto.randomBytes(20); + const token = buffer.toString("hex"); + var tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + user.resetPasswordToken = token; + user.resetPasswordTTL = tomorrow; + await user.save().catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err + }); + return; + }); + + const request = mailjet.post("send", { + version: "v3.1" + }).request({ + Messages: [{ + From: { + Email: admin_email, + Name: site_name + " Admin" + }, + To: [{ + Email: user.email, + Name: user.firstName + " " + user.lastName + }], + Subject: site_name + " - Password Reset", + TextPart: "It looks like you may have forgot your password. Copy this link to your browser to reset your password. Let us know if you are receiving this but did not request a password reset. /r" + account_server + "/reset-password/" + user.id + "/" + token, + HTMLPart: "

Thanks for using " + site_name + "!


It looks like you may have forgot your password. Copy this link to your browser to reset your password. Let us know if you are receiving this but did not request a password reset.

" + account_server + "/reset-password/" + user.id + "/" + token + "

" + }] + }); + request + .then(result => { + console.log(`Password reset sent to: ${user.email}`) + }) + .catch(err => { + console.error(err.statusCode); console.error(err); res.json({ success: false, message: err }); return; - } - if (!user) { - console.error("Reset password failed. No user: " + req.body.email); - res.json({ - success: false, - message: "No account register for " + req.body.email - }); - return; - } - const buffer = crypto.randomBytes(20); - const token = buffer.toString("hex"); - var tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); - user.resetPasswordToken = token; - user.resetPasswordTTL = tomorrow; - user.save(err => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - - const request = mailjet.post("send", { - version: "v3.1" - }).request({ - Messages: [{ - From: { - Email: admin_email, - Name: site_name + " Admin" - }, - To: [{ - Email: user.email, - Name: user.firstName + " " + user.lastName - }], - Subject: site_name + " - Password Reset", - TextPart: "It looks like you may have forgot your password. Copy this link to your browser to reset your password. Let us know if you are receiving this but did not request a password reset. /r" + account_server + "/reset-password/" + user.id + "/" + token, - HTMLPart: "

Thanks for using " + site_name + "!


It looks like you may have forgot your password. Copy this link to your browser to reset your password. Let us know if you are receiving this but did not request a password reset.

" + account_server + "/reset-password/" + user.id + "/" + token + "

" - }] - }); - request - .then(result => { - console.log(`Password reset sent to: ${user.email}`) - }) - .catch(err => { - console.error(err.statusCode); - console.error(err); - res.json({ - success: false, - message: err - }); - return; - }); - res.json({ - success: true - }); - return; }); + res.json({ + success: true }); + return; }; function handleSendConfirmEmail(user) { - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { if (user.confirmEmail) { console.log("Error - Send Confirm Email - User already confirmed email: " + user.email); reject({ @@ -332,130 +353,133 @@ function handleSendConfirmEmail(user) { tomorrow.setDate(tomorrow.getDate() + 1); user.confirmEmailToken = token; user.confirmEmailTTL = tomorrow; - user.save().then(function(user) { - return mailjet.post("send", { - version: "v3.1" - }).request({ - Messages: [{ - From: { - Email: admin_email, - Name: site_name + " Admin" - }, - To: [{ - Email: user.email, - Name: user.firstName + " " + user.lastName - }], - Subject: "Confirm " + site_name + " Account", - TextPart: "Thanks for signing up for " + site_name + ". We just wanted to check and make sure your email address was real. Copy and paste this addres in your browser to confirm your email address: " + account_server + "/confirm-email/" + user._id + "/" + token, - HTMLPart: "

Thanks for signing up for " + site_name + "


We just wanted to check and make sure your email address was real. Copy and paste this addres in your browser to confirm your email address:

" + account_server + "/confirm-email/" + user._id + "/" + token + "

" - }] - }); - }).then(result => { - console.log("Confirm email sent to: " + user.email); - resolve({ - success: true, - userId: user._id - }); - }).catch(err => { - console.error("Admin Email: " + admin_email + " User Email: " + user.email); - console.error("Error - Send Confirm Email - caught: " + err); - reject({ - success: false, - message: err - }); + await user.save(); + mailjet.post("send", { + version: "v3.1" + }).request({ + Messages: [{ + From: { + Email: admin_email, + Name: site_name + " Admin" + }, + To: [{ + Email: user.email, + Name: user.firstName + " " + user.lastName + }], + Subject: "Confirm " + site_name + " Account", + TextPart: "Thanks for signing up for " + site_name + ". We just wanted to check and make sure your email address was real. Copy and paste this addres in your browser to confirm your email address: " + account_server + "/confirm-email/" + user._id + "/" + token, + HTMLPart: "

Thanks for signing up for " + site_name + "


We just wanted to check and make sure your email address was real. Copy and paste this addres in your browser to confirm your email address:

" + account_server + "/confirm-email/" + user._id + "/" + token + "

" + }] + }); + }).then(result => { + console.log("Confirm email sent to: " + user.email); + resolve({ + success: true, + userId: user._id + }); + }).catch(err => { + console.error("Admin Email: " + admin_email + " User Email: " + user.email); + console.error("Error - Send Confirm Email - caught: " + err); + res.status(500); + reject({ + success: false, + message: err }); }); -}; +} // ------------------------------------------- -exports.sendConfirmEmail = function(req, res, next) { +exports.sendConfirmEmail = async function (req, res, next) { const userId = req.params["userId"]; - User.findById(userId, (err, user) => { - if (err) { - console.error("Error - Send Confirm Email: " + err); - res.json({ - success: false, - message: err - }); - return; - } - if (!user) { - console.error("Error - Send Confirm Email: User not found " + userId); - res.json({ - success: false, - message: "user not found" - }); - return; - } - handleSendConfirmEmail(user).then(function(result) { - res.json(result); - return; - }).catch(function(error) { - res.json(error); - return; - }); - }); + let user = await User.findById(userId).catch(err => { + + console.error("Error - Send Confirm Email: " + err); + res.status(500); + res.json({ + success: false, + message: err + }); + return; + }); + if (!user) { + console.error("Error - Send Confirm Email: User not found " + userId); + res.status(404); + res.json({ + success: false, + message: "user not found" + }); + return; + } + handleSendConfirmEmail(user).then(function (result) { + res.json(result); + return; + }).catch(function (error) { + res.json(error); + return; + }); +} + -}; // ------------------------------------------- -exports.logout = function(req, res, next) { +exports.logout = function (req, res, next) { // the logout method is added to the request object automatically by Passport req.logout(); - res.clearCookie('sessionId', {domain: cookie_domain, path:'/'}); + res.clearCookie('sessionId', { domain: cookie_domain, path: '/' }); return res.json({ success: true }); }; -exports.terms = function(req, res, next) { +exports.terms = async function (req, res, next) { const userId = req.params["userId"]; - User.findById(userId, (err, user) => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - if (req.user.id != userId) { - console.log( - "Logged in user's ID: " + - req.user.id + - " does not match Param: " + - userId - ); - res.json({ - success: false, - message: "UserID incorrect" - }); - return; - } - - user.terms = 1.1; //User.termsVer; - user.save(err => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - res.json({ - success: true - }); - return; + let user = await User.findById(userId).catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err }); + return; }); -}; + + if (req.user.id != userId) { + console.log( + "Logged in user's ID: " + + req.user.id + + " does not match Param: " + + userId + ); + res.status(500); + res.json({ + success: false, + message: "UserID incorrect" + }); + return; + } + + user.terms = 1.1; //User.termsVer; + await user.save().catch(err => { + + console.error(err); + res.status(500); + res.json({ + success: false, + message: err + }); + return; + }); + res.json({ + success: true + }); + return; +} // ------------------------------------------- -exports.validateProfile = function(req, res, next) { - console.log("Validating user profile: "+ req.body.email); +exports.validateProfile = function (req, res, next) { + console.log("Validating user profile: " + req.body.email); if (!req.body.firstName || (req.body.firstName.length < 2)) { console.error("ERROR: Validate System - req.body.firstName"); res.json({ @@ -492,68 +516,73 @@ exports.validateProfile = function(req, res, next) { next(); } -exports.updateProfile = function(req, res, next) { +exports.updateProfile = async function (req, res, next) { const userId = req.params["userId"]; - User.findById(userId, (err, user) => { - // is email address already in use? - if (req.user.id != userId) { - console.log( - "ERROR: Logged in user's ID: " + - req.user.id + - " does not match Param: " + - userId - ); - res.json({ - success: false, - message: "UserID incorrect" - }); - return; - } - // go ahead and create the new user - user.firstName = res.locals.firstName - user.lastName = res.locals.lastName - user.screenName = res.locals.screenName - user.location = res.locals.location - - - user.save(err => { - if (err) { - console.error(err); - res.json({ - success: false, - message: err - }); - return; - } - var clientUser = (({ - firstName, - lastName, - screenName, - location - }) => ({ - firstName, - lastName, - screenName, - location - }))( - user - ); - console.log("Updated Profile: " + userId) - res.json({ - success: true, - user: clientUser - }); - return; + user = await User.findById(userId).catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err }); + return; }); + + if (req.user.id != userId) { + console.log( + "ERROR: Logged in user's ID: " + + req.user.id + + " does not match Param: " + + userId + ); + res.json({ + success: false, + message: "UserID incorrect" + }); + return; + } + // go ahead and create the new user + user.firstName = res.locals.firstName + user.lastName = res.locals.lastName + user.screenName = res.locals.screenName + user.location = res.locals.location + + + await user.save().catch(err => { + console.error(err); + res.json({ + success: false, + message: err + }); + return; + }); + var clientUser = (({ + firstName, + lastName, + screenName, + location + }) => ({ + firstName, + lastName, + screenName, + location + }))( + user + ); + console.log("Updated Profile: " + userId) + res.json({ + success: true, + user: clientUser + }); + return; }; // ------------------------------------------- -exports.register = function(req, res, next) { +exports.register = async function (req, res, next) { console.log("Registration request for: " + req.body.email); - - User.findOne({ + + let user = await User.findOne({ $or: [{ email: req.body.email }, { @@ -561,49 +590,57 @@ exports.register = function(req, res, next) { email: req.body.email } }] - }, (err, user) => { - // is email address already in use? - if (user) { - res.json({ - success: false, - message: "Email already in use" - }); - return; - } - // go ahead and create the new user - var user = (({ - firstName, - lastName, - screenName, - location, - email, - password - }) => ({ - firstName, - lastName, - screenName, - location, - - }))( - res.locals - ); - user.password = req.body.password; - user.email = req.body.email; - - User.create(user).then(function(dbUser) { - console.log("Successfully registered: " + dbUser.email + ", now sending confirmation email."); - // Since regiestration worked, send a confirmation email. - return handleSendConfirmEmail(dbUser); - }).then(function(result) { - res.json(result); - return; - }).catch(function(err) { - console.error("Error creating user: " + user.email + " Error: " +err); - res.json({ - success: false, - message: err - }); - return; + }).catch(err => { + console.error(err); + res.status(500); + res.json({ + success: false, + message: err }); + return; }); -}; + // is email address already in use? + if (user) { + res.status(500); + res.json({ + success: false, + message: "Email already in use" + }); + return; + } + // go ahead and create the new user + user = (({ + firstName, + lastName, + screenName, + location, + email, + password + }) => ({ + firstName, + lastName, + screenName, + location, + + }))( + res.locals + ); + user.password = req.body.password; + user.email = req.body.email; + + await User.create(user) + + console.log("Successfully registered: " + user.email + ", now sending confirmation email."); + // Since regiestration worked, send a confirmation email. + handleSendConfirmEmail(user).then(function (result) { + res.json(result); + return; + }).catch(function (err) { + console.error("Error creating user: " + user.email + " Error: " + err); + res.json({ + success: false, + message: err + }); + return; + }); +} \ No newline at end of file diff --git a/account/server/index.js b/account/server/index.js index 0ed2e58..a127c49 100644 --- a/account/server/index.js +++ b/account/server/index.js @@ -15,39 +15,39 @@ const app = express() // ------------------------------------------- -async function connect() { +const connect = async () => { // Demonstrate the readyState and on event emitters console.log(mongoose.connection.readyState); //logs 0 - mongoose.connection.on('connecting', () => { - console.log('Mongoose is connecting') - console.log(mongoose.connection.readyState); //logs 2 + mongoose.connection.on('connecting', () => { + console.log('Mongoose is connecting') + console.log(mongoose.connection.readyState); //logs 2 }); mongoose.connection.on('connected', () => { - console.log('Mongoose is connected'); - console.log(mongoose.connection.readyState); //logs 1 + console.log('Mongoose is connected'); + console.log(mongoose.connection.readyState); //logs 1 }); mongoose.connection.on('disconnecting', () => { - console.log('Mongoose is disconnecting'); - console.log(mongoose.connection.readyState); // logs 3 + console.log('Mongoose is disconnecting'); + console.log(mongoose.connection.readyState); // logs 3 }); // Connect to a MongoDB server running on 'localhost:27017' and use the // 'test' database. - await mongoose.connect(secrets.db, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }, (err, res) => { - if (err) { - console.log(`Mongoose - Error connecting to ${secrets.db}. ${err}`) - } else { - console.log(`Mongoose Successfully connected to ${secrets.db}.`) - } - }) + await mongoose.connect(secrets.db, { useNewUrlParser: true, useUnifiedTopology: true }).catch(err => { + + console.error(`Mongoose - Error connecting to ${secrets.db}. ${err}`) + + }); console.log("All Done"); } + connect(); + mongoose.connection.on('error', err => { console.error("Mongoose Error!") console.error(err); - }); +}); mongoose.connection.on('disconnected', () => { console.log('Mongoose disconnected'); console.log(mongoose.connection.readyState); //logs 0 @@ -72,16 +72,16 @@ configurePassport(app, passport) configureExpress(app, passport) -app.all('*', function(req, res, next) { - var allowedOrigins = [account_server, admin_server, frontend_server]; - var origin = req.headers.origin; - if(allowedOrigins.indexOf(origin) > -1){ - res.setHeader('Access-Control-Allow-Origin', origin); - } - res.header("Access-Control-Allow-Credentials", "true"); - res.header("Access-Control-Allow-Headers", "X-Requested-With"); - res.header('Access-Control-Allow-Headers', 'Content-Type'); - next(); +app.all('*', function (req, res, next) { + var allowedOrigins = [account_server, admin_server, frontend_server]; + var origin = req.headers.origin; + if (allowedOrigins.indexOf(origin) > -1) { + res.setHeader('Access-Control-Allow-Origin', origin); + } + res.header("Access-Control-Allow-Credentials", "true"); + res.header("Access-Control-Allow-Headers", "X-Requested-With"); + res.header('Access-Control-Allow-Headers', 'Content-Type'); + next(); }); // ------------------------------------------- @@ -94,8 +94,8 @@ app.post("/users/:userId/reset-password/:token", users.resetPassword) app.post("/api/send-reset-password", users.sendResetPassword) app.post("/users/:userId", users.isLoggedIn, users.validateProfile, users.updateProfile) app.post("/users/:userId/terms", users.isLoggedIn, users.terms) -app.post("/users/:userId/send-confirm", users.sendConfirmEmail) -app.post("/users/:userId/confirm/:token", users.confirmEmail) +app.post("/users/:userId/send-confirm", users.sendConfirmEmail) +app.post("/users/:userId/confirm/:token", users.confirmEmail) app.get("*", (req, res, next) => { res.sendFile(__dirname + '/public/index.html'); diff --git a/account/src/User/Login.js b/account/src/User/Login.js index fae8dda..993d76f 100644 --- a/account/src/User/Login.js +++ b/account/src/User/Login.js @@ -2,7 +2,7 @@ import React, { useEffect, useState, } from "react"; import { useNavigate, useSearchParams, Link } from 'react-router-dom'; import { loginUser } from "../features/user/userSlice"; - +import { useSelector, useDispatch } from 'react-redux' import { Container, Header, @@ -35,66 +35,52 @@ const Login = (props) => { const navigate = useNavigate(); let [searchParams, setSearchParams] = useSearchParams(); const nextLocation = searchParams.get("nextLocation"); + const dispatch = useDispatch(); - - - - - - const handleInputChange = (e, { name, value }) => this.setState({ [name]: value }); - - const loginSubmit = (event) => { + const loginSubmit = async (event) => { event.preventDefault(); - /* - var success = { type: "path", nextPathname: "/" }; - if (nextLocation) { - success.type = "location"; - switch (this.props.nextLocation) { - case "frontend": - success.nextLocation = process.env.REACT_APP_FRONTEND_SERVER; - break; - default: - case "admin": - success.nextLocation = process.env.REACT_APP_ADMIN_SERVER; - break; + const result = await dispatch(loginUser({email,password})).unwrap(); + if (result.success) { + + if (nextLocation) { + switch (this.props.nextLocation) { + case "frontend": + window.location = process.env.REACT_APP_FRONTEND_SERVER; + break; + default: + case "admin": + window.location = process.env.REACT_APP_ADMIN_SERVER; + break; + } + } else { + navigate("/"); } + console.log(result) + } else { + console.error(result); + setLoginMessage(result.message); + if (result.message === "unconfirmed email") { + /*data.userId = response.data.userId; + dispatch(loginEmailError(data));*/ + navigate("/wait-confirm-email"); + } } - - // Passed in via react-redux. Returns a promise. - this.props - .manualLogin( - { - // this function is passed in via react-redux - email, - password - }, - success - - ) // holds the path to redirect to after login (if any) - .then(loginMessage => { - if (loginMessage) { - // report to the user is there was a problem during login - this.setState({ - loginMessage - }); - } - });*/ } -/* + let loginMessageDisplay =(<>) - if (this.state.loginMessage) { - loginMessage = ( + if (loginMessage) { + loginMessageDisplay = ( Problems... - {this.state.loginMessage} + {loginMessage} ); } -*/ + return (
{process.env.REACT_APP_SITE_NAME}
@@ -176,7 +162,7 @@ const Login = (props) => { - {loginMessage} + {loginMessageDisplay}
diff --git a/account/src/User/Profile.js b/account/src/User/Profile.js index 8cbead9..b567a55 100644 --- a/account/src/User/Profile.js +++ b/account/src/User/Profile.js @@ -1,45 +1,37 @@ -import React, { Component } from "react" +import React, { useEffect, useState, } from "react"; +import { useSelector, useDispatch } from 'react-redux' +import { useNavigate, useSearchParams, Link } from 'react-router-dom'; import UserForm from "./UserForm"; import { Container, Header } from "semantic-ui-react"; +import { updateProfile } from "../features/user/userSlice"; -class Profile extends Component { - constructor(props) { - super(props); - this.handleProfileSubmit = this.handleProfileSubmit.bind(this); - } +const Profile = (props) => { + const [message, setMessage] = useState(""); + const user = useSelector((state) => state.user); + const dispatch = useDispatch(); + + const handleProfileSubmit = async (updatedUser) => { + updatedUser.userId = user.userId - state = { - requestMessage: "" + const result = await dispatch(updateProfile(updatedUser)).unwrap(); + if (result.success) { + console.log(result) + } else { + setMessage = result.message; + } } - - handleProfileSubmit(user) { - user.userId = this.props.user.userId - this.props - .updateProfile(user) - .then(requestMessage => { - if (requestMessage) { - // report to the user is there was a problem during registration - this.setState({ - requestMessage - }); - } - }); - } - - render() { // The Key on UserForm get updated when the user is loaded. This forces the Component to be completely redrawn, otherwise the changes in the Prop are not copied to State. return(
Update Profile
- +
) - } } export default Profile diff --git a/account/src/User/Register.js b/account/src/User/Register.js index f1eee92..b6f2f52 100644 --- a/account/src/User/Register.js +++ b/account/src/User/Register.js @@ -1,4 +1,7 @@ -import React, { Component } from "react"; +import React, { useState } from "react"; +import { registerUser } from "../features/user/userSlice"; +import { useNavigate, useSearchParams, Link } from 'react-router-dom'; +import { useSelector, useDispatch } from 'react-redux' import { Container, Header, @@ -8,53 +11,39 @@ import { import UserForm from "./UserForm"; -// ---------------------------------------------------- -class Register extends Component { - constructor(props) { - super(props); - this._onRegisterSubmit = this._onRegisterSubmit.bind(this); +function Register(props) { + const [requestMessage, setRequestMessage] = useState(""); + const dispatch = useDispatch(); + const navigate = useNavigate(); + const onRegisterSubmit = async(user) => { + const result = await dispatch(registerUser(user)).unwrap(); + if (result.success) { + navigate("/sent-confirm-email"); + } else { + console.error(result); + setRequestMessage(result.message); } + }; - state = { - requestMessage: "" - } - - - - _onRegisterSubmit(user) { - this.props - .manualRegister(user) - .then(requestMessage => { - if (requestMessage) { - // report to the user is there was a problem during registration - this.setState({ - requestMessage - }); - } - }); - } - - render() { - return ( -
- + return ( +
+ - - - Welcome! -

Creating an account on OpenMHz is the first step in sharing radio system recordings using Trunk Recorder.

-

After creating an account, head over here to learn more about Trunk Recorder

-

- Luke

-
-
-
- -
Register
- -
-
- ); - } + + + Welcome! +

Creating an account on OpenMHz is the first step in sharing radio system recordings using Trunk Recorder.

+

After creating an account, head over here to learn more about Trunk Recorder

+

- Luke

+
+ +
+ +
Register
+ +
+
+ ); } export default Register; diff --git a/account/src/User/ResetPassword.js b/account/src/User/ResetPassword.js index a94edfa..5f8437e 100644 --- a/account/src/User/ResetPassword.js +++ b/account/src/User/ResetPassword.js @@ -1,4 +1,7 @@ -import React, { Component } from "react"; +import React, { useState } from "react"; +import { resetPassword } from "../features/user/userSlice"; +import { useParams, useNavigate } from 'react-router-dom'; +import { useDispatch } from 'react-redux' import { Container, Form, @@ -6,101 +9,101 @@ import { Button, } from "semantic-ui-react"; -class ResetPassword extends Component { - constructor(props) { - super(props); - this.handleResetPassword = this.handleResetPassword.bind(this); - this.handleInputChange = this.handleInputChange.bind(this); - } - state = { - checkInputMessages: [], - password: "", - confirmPassword: "", - passwordError: false, - confirmPasswordError: false, - sentReset: false - }; +const ResetPassword = (props) => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const [password, setPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + const [passwordError, setPasswordError] = useState(false); + const [confirmPasswordError, setConfirmPasswordError] = useState(false); + const [checkInputMessages, setCheckInputMessages] = useState([]); + const { userId, token } = useParams(); - - handleInputChange = (e, { name, value }) => this.setState({ [name]: value }); - - handleResetPassword(event) { + const handleResetPassword = async () => { let error = false; - var checkInputMessages = []; + var inputMessages = []; - if (this.state.password === "") { - this.setState({ passwordError: true }); - checkInputMessages.push("Password is required"); + if (password === "") { + setPasswordError(true); + inputMessages.push("Password is required"); error = true; - } if (this.state.password.length < 7) { - this.setState({ passwordError: true }); - checkInputMessages.push("Password must be 7 charecters or more"); - error = true; - }else { - this.setState({ passwordError: false }); - } - - if (this.state.password !== this.state.confirmPassword) { - this.setState({ confirmPasswordError: true }); - checkInputMessages.push("The passwords did not match"); + } else if (password.length < 7) { + setPasswordError(true); + inputMessages.push("Password must be 7 characters or more"); error = true; } else { - this.setState({ confirmPasswordError: false }); + setPasswordError(false); } - const { match: { params } } = this.props; - this.setState({ checkInputMessages: checkInputMessages }); + if (password !== confirmPassword) { + setConfirmPasswordError(true); + inputMessages.push("The passwords did not match"); + error = true; + } else { + setConfirmPasswordError(false); + } + + const { match: { params } } = props; + setCheckInputMessages(inputMessages); if (!error) { - this.props.resetPassword(params.userId, params.token, this.state.password).then(resetSent => { - this.setState({resetSent: true}); - }); + const result = await dispatch(resetPassword({ userId, token, password })).unwrap(); + if (result.success) { + navigate("/login"); + } else { + console.error(result); + } + } - } + }; - - render() { - return ( -
- + return ( +
+ -
- - - + + + setPassword(e.target.value)} + error={passwordError} + label="Password" + placeholder="Password..." + /> + + + setConfirmPassword(e.target.value)} + error={confirmPasswordError} + label="Confirm Password" + placeholder="Confirm Password..." + /> + + +
- ); - } -} +
+ ); +}; export default ResetPassword; + diff --git a/account/src/User/SendResetPassword.js b/account/src/User/SendResetPassword.js index 36c51c9..41e17f8 100644 --- a/account/src/User/SendResetPassword.js +++ b/account/src/User/SendResetPassword.js @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React, { useState } from "react"; import { Form, Grid, @@ -7,106 +7,99 @@ import { Message, Icon } from "semantic-ui-react"; +import { sendResetPassword } from "../features/user/userSlice"; import { Link } from "react-router-dom"; +import { useParams, useNavigate } from 'react-router-dom'; +import { useDispatch } from 'react-redux' -const returnStyle = { - marginTop: "30px" -}; -class SendResetPassword extends Component { - constructor(props) { - super(props); - this.handleSendResetPassword = this.handleSendResetPassword.bind(this); - this.handleInputChange = this.handleInputChange.bind(this); - } - state = { - checkInputMessages: "", - email: "", - emailError: false, - sentReset: false +const SendResetPassword = (props) => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const [checkInputMessages, setCheckInputMessages] = useState(""); + const [email, setEmail] = useState(""); + const [emailError, setEmailError] = useState(false); + const [resetSent, setResetSent] = useState(false); + + const returnStyle = { + marginTop: "30px" }; - handleInputChange = (e, { name, value }) => this.setState({ [name]: value }); - - handleSendResetPassword(event) { - - - if (this.state.email === "") { - this.setState({ emailError: true, checkInputMessages: "Email is required"}); - + const handleSendResetPassword = async () => { + if (email === "") { + setEmailError(true); + setCheckInputMessages("Email is required"); } else { - this.setState({ emailError: false }); - - this.props.sendResetPassword({email: this.state.email}).then(resetMessage => { - if (resetMessage) { - // report to the user is there was a problem during login - - this.setState({resetSent: false, checkInputMessages: resetMessage, emailError: true}); - } else { - this.setState({resetSent: true}); + const result = await dispatch(sendResetPassword({ email })).unwrap(); + if (result.success) { + setResetSent(true); + setEmailError(true); + } else { + setCheckInputMessages(result.message); + console.error(result); } - }); } - } - render() { - var resetMessage = ""; - if (this.state.checkInputMessages.length) { - resetMessage = ( - - - - Problems... + }; - {this.state.checkInputMessages} - - - - ); - } - return ( - - - - - - - { !this.state.resetSent ? ( -
-

Forgot your password?

-
- Enter the email address for your account. - - - -
- ) - :( -

Reset Link Sent

-
An email with a link to reset your password was sent to: {this.state.email}
- Back to OpenMHz -
- )} -
-
-
+ var resetMessage = ""; + if (checkInputMessages.length) { + resetMessage = ( + + + + Problems... + {checkInputMessages} + + ); } + + return ( + + + + {!resetSent ? ( +
+

Forgot your password?

+
+ Enter the email address for your account. + + setEmail(e.target.value)} + value={email} + error={emailError} + label="Email" + placeholder="Email..." + /> + +
+ ) : ( + +

Reset Link Sent

+
+ An email with a link to reset your password was sent to: {email} +
+ + + Back to OpenMHz + +
+ )} +
+
+
+ ); } export default SendResetPassword; diff --git a/account/src/User/SentConfirmEmail.js b/account/src/User/SentConfirmEmail.js index 483cbe2..6fd46ec 100644 --- a/account/src/User/SentConfirmEmail.js +++ b/account/src/User/SentConfirmEmail.js @@ -1,28 +1,25 @@ -import React, { Component } from "react" -import { - Container, - Message, - Icon -} from "semantic-ui-react"; +import React from "react"; +import { Container, Message, Icon } from "semantic-ui-react"; +import { useSelector } from 'react-redux' -class SentConfirmEmail extends Component { +const SentConfirmEmail = ({ user }) => { + const { email } = useSelector((state) => state.user); + return ( +
+ + + + + Confirmation email sent! +

+ We sent an email to the address you gave us: {email}
+ Please click on the link in the email to verify the email address. +

+
+
+
+
+ ); +}; - render() { - return ( -
- - - - - Confirmation email sent! -

We sent an email to the address you gave us: {this.props.user.email}
- Please click on the link in the email to verify the email address.

-
-
-
-
- ) - } -} - -export default SentConfirmEmail +export default SentConfirmEmail; diff --git a/account/src/User/UserForm.js b/account/src/User/UserForm.js index a07d781..e65bb04 100644 --- a/account/src/User/UserForm.js +++ b/account/src/User/UserForm.js @@ -1,4 +1,5 @@ -import React, { Component } from "react"; + +import React, { useEffect, useState, } from "react"; import { Form, Dimmer, @@ -10,270 +11,260 @@ import { // ---------------------------------------------------- -class UserForm extends Component { - constructor(props) { - super(props); - this.handleInputChange = this.handleInputChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.checkInputs = this.checkInputs.bind(this); - this.render = this.render.bind(this) - - this.state = { - checkInputMessages: [], - registerMessages: "", - firstName: "", - lastName: "", - screenName: "", - email: "", - location: "", - password: "", - confirmPassword: "", - firstNameError: false, - lastNameError: false, - screenNameError: false, - emailError: false, - locationError: false, - passwordError: false, - confirmPasswordError: false, - isEditing: this.props.isEditing - }; - if (this.props.isEditing) { - this.state.firstName = this.props.user.firstName; - this.state.lastName = this.props.user.lastName; - this.state.screenName = this.props.user.screenName; - this.state.email = this.props.user.email; - this.state.location = this.props.user.location; +const UserForm = (props) => { + const [checkInputMessages, setCheckInputMessages] = useState([]); + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [screenName, setScreenName] = useState(""); + const [email, setEmail] = useState(""); + const [location, setLocation] = useState(""); + const [password, setPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + const [firstNameError, setFirstNameError] = useState(false); + const [lastNameError, setLastNameError] = useState(false); + const [screenNameError, setScreenNameError] = useState(false); + const [emailError, setEmailError] = useState(false); + const [locationError, setLocationError] = useState(false); + const [passwordError, setPasswordError] = useState(false); + const [confirmPasswordError, setConfirmPasswordError] = useState(false); + const [isEditing, setIsEditing] = useState(props.isEditing); + const requestMessage = props.requestMessage; + + useEffect(() => { + if (props.isEditing) { + setFirstName(props.user.firstName); + setLastName(props.user.lastName); + setScreenName(props.user.screenName); + setEmail(props.user.email); + setLocation(props.user.location); } - } + }, [props.isEditing, props.user]); - - - checkInputs() { + const checkInputs = () => { let error = false; - var checkInputMessages = []; + let inputMessages = []; - if (this.state.firstName === "") { - this.setState({ firstNameError: true }); - checkInputMessages.push("First Name is required"); + if (firstName === "") { + setFirstNameError(true); + inputMessages.push("First Name is required"); error = true; } else { - this.setState({ firstNameError: false }); + setFirstNameError(false); } - if (this.state.lastName === "") { - this.setState({ lastNameError: true }); - checkInputMessages.push("Last Name is required"); + if (lastName === "") { + setLastNameError(true); + inputMessages.push("Last Name is required"); error = true; } else { - this.setState({ lastNameError: false }); + setLastNameError(false); } - if (this.state.email === "") { - this.setState({ emailError: true }); - checkInputMessages.push("Email is required"); + if (email === "") { + setEmailError(true); + inputMessages.push("Email is required"); error = true; } else { - this.setState({ emailError: false }); + setEmailError(false); } - if (this.state.location === "") { - this.setState({ locationError: true }); - checkInputMessages.push("Location is required"); + if (location === "") { + setLocationError(true); + inputMessages.push("Location is required"); error = true; } else { - this.setState({ locationError: false }); + setLocationError(false); } - if (this.state.screenName === "") { - this.setState({ screenNameError: true }); - checkInputMessages.push("Screen Name is required"); + if (screenName === "") { + setScreenNameError(true); + inputMessages.push("Screen Name is required"); error = true; } else { - this.setState({ screenNameError: false }); + setScreenNameError(false); } - if (this.props.isEditing) { - this.setState({ checkInputMessages: checkInputMessages }); + if (props.isEditing) { + setCheckInputMessages(checkInputMessages); return error; } - if (this.state.password === "") { - this.setState({ passwordError: true }); - checkInputMessages.push("Password is required"); + if (password === "") { + setPasswordError(true); + inputMessages.push("Password is required"); error = true; - } if (this.state.password.length < 7) { - this.setState({ passwordError: true }); - checkInputMessages.push("Password must be 7 charecters or more"); + } if (password.length < 7) { + setPasswordError(true); + inputMessages.push("Password must be 7 charecters or more"); error = true; } else { - this.setState({ passwordError: false }); + setPasswordError(false); } - if (this.state.password !== this.state.confirmPassword) { - this.setState({ confirmPasswordError: true }); - checkInputMessages.push("The passwords did not match"); + if (password !== confirmPassword) { + setConfirmPasswordError(true); + inputMessages.push("The passwords did not match"); error = true; } else { - this.setState({ confirmPasswordError: false }); + setConfirmPasswordError(false); } - this.setState({ checkInputMessages: checkInputMessages }); + setCheckInputMessages(inputMessages); return error; } - handleInputChange = (e, { name, value }) => this.setState({ [name]: value }); - handleSubmit(event) { + const handleSubmit = (event) => { event.preventDefault(); - let inputError = this.checkInputs(); + let inputError = checkInputs(); if (!inputError) { - const user = (({ firstName, lastName, screenName, location, email, password }) => ({ firstName, lastName, screenName, location, email, password }))(this.state); - this.props.onSubmit(user); + const user ={ firstName, lastName, screenName, location, email, password }; + props.onSubmit(user); } } - render() { - var registerMessage = ""; - var floatStyle = { - overflow: 'auto' - } - var dimmerProps = {}; - if (this.props.isWaiting) { - dimmerProps["active"] = true; - } - const { isEditing } = this.props; - if (this.state.checkInputMessages.length || this.props.requestMessage.length) { - var counter = 0; - registerMessage = ( - - - - Problems... -
    - {this.state.checkInputMessages.map(function (listValue) { - return
  • {listValue}
  • ; - })} - {this.props.requestMessage.length > 0 && -
  • {this.props.requestMessage}
  • - } -
-
-
- ); - } - return ( -
-
- - Updating Profile - - - - - - - - - - - - + var registerMessage = ""; + var floatStyle = { + overflow: 'auto' + } + var dimmerProps = {}; + if (props.isWaiting) { + dimmerProps["active"] = true; + } - - - -

- Shown on OpenMHz for each of your systems -

-
-
- - - - - - {isEditing !== true && ( - - - - - - - - - )} -
- -
-
- {registerMessage} -
+ if (checkInputMessages.length || requestMessage.length) { + var counter = 0; + registerMessage = ( + + + + Problems... +
    + {checkInputMessages.map(function (listValue) { + return
  • {listValue}
  • ; + })} + {requestMessage.length > 0 && +
  • {requestMessage}
  • + } +
+
+
); } + return ( +
+
+ + Updating Profile + + + + + setFirstName(e.target.value)} + error={firstNameError} + value={firstName} + label="First name" + placeholder="First Name..." + /> + + + setLastName(e.target.value)} + error={lastNameError} + value={lastName} + label="Last name" + placeholder="Last Name..." + /> + + + + + setEmail(e.target.value)} + error={emailError} + value={email} + disabled={isEditing} + label="Email" + placeholder="Email..." + /> + + + + setScreenName(e.target.value)} + error={screenNameError} + value={screenName} + label="Screen Name" + placeholder="Screen Name..." + /> +

+ Shown on OpenMHz for each of your systems +

+
+
+ + + setLocation(e.target.value)} + error={locationError} + value={location} + label="General Location" + placeholder="City, State..." + /> + + + {isEditing !== true && ( + + + setPassword(e.target.value)} + error={passwordError} + disabled={isEditing} + label="Password" + placeholder="Password..." + /> + + + setConfirmPassword(e.target.value)} + error={confirmPasswordError} + disabled={isEditing} + label="Confirm Password" + placeholder="Confirm Password..." + /> + + + )} +
+ +
+
+ {registerMessage} +
+ ); } + export default UserForm; diff --git a/account/src/User/WaitConfirmEmail.js b/account/src/User/WaitConfirmEmail.js index 72aaa31..bc13b3d 100644 --- a/account/src/User/WaitConfirmEmail.js +++ b/account/src/User/WaitConfirmEmail.js @@ -1,52 +1,43 @@ -import React, { Component } from "react" -import { - Container, - Header, - Button, - Message, - Icon -} from "semantic-ui-react"; -class WaitConfirmEmail extends Component { - constructor(props) { - super(props); - this.handleSendConfirmEmail = this.handleSendConfirmEmail.bind(this); +import React, { useState } from "react"; +import { sendConfirmEmail } from "../features/user/userSlice"; +import { useNavigate } from 'react-router-dom'; +import { useSelector, useDispatch } from 'react-redux' +import { Container, Header, Button, Message, Icon } from "semantic-ui-react"; - } - handleSendConfirmEmail(event) { - this.props.sendConfirmEmail(this.props.user.userId).then(loginMessage => { - if (loginMessage) { - // report to the user is there was a problem during login - this.setState({ - loginMessage - }); - } - }); +const WaitConfirmEmail = () => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const { email, userId } = useSelector((state) => state.user); + + const handleSendConfirmEmail = async (event) => { + const message = await dispatch(sendConfirmEmail(userId)).unwrap(); + navigate("/sent-confirm-email") }; - - render() { - return( - - - - - Confirm your email address -

We sent an email to the address you gave us: {this.props.user.email}
- Please click on the link in the email to verify the email address.

-
Didn't get an email?
-

So, you have waited a bit and haven't gotten anything?

+ + return ( + + + + + Confirm your email address +

+ We sent an email to the address you gave us: {email} +
+ Please click on the link in the email to verify the email address. +

+
Didn't get an email?
+

So, you have waited a bit and haven't gotten anything?

...and you checked your spam folder?

Well, click below.

-