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

[REQ-329] User/cesarjimenezvilleda02/req 329 accept reject register #111

Merged
Show file tree
Hide file tree
Changes from 17 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
22 changes: 0 additions & 22 deletions .vscode/settings.json

This file was deleted.

116 changes: 114 additions & 2 deletions caeq-backend/controllers/architect.user.controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
const factory = require('./handlerFactory.controller');
const ArchitectUser = require('../models/architect.user.model');
const RegisterRequest = require('../models/regiesterRequests.model');
const APIFeatures = require(`../utils/apiFeatures`);
const catchAsync = require('../utils/catchAsync');
const AppError = require('../utils/appError');
const Email = require('../utils/email');

exports.getAllArchitectUsers = factory.getAll(ArchitectUser, 'specialties');
exports.getAllRegistrationRequests = factory.getAll(RegisterRequest, [
'newInfo',
'overwrites',
]);
exports.getArchitectUser = factory.getOne(ArchitectUser, 'specialties');
exports.createArchitectUser = factory.createOne(ArchitectUser);
exports.updateArchitectUser = factory.updateOne(ArchitectUser);
Expand All @@ -11,7 +19,7 @@ exports.deleteArchitectUser = factory.deleteOne(ArchitectUser);
/**
* This is a function that gets all architects with authorizationToShareInfo set to true.
*/
exports.getAllPublicArchitectUsers = async (req, res) => {
exports.getAllPublicArchitectUsers = catchAsync(async (req, res) => {
let filter = {};
let query = ArchitectUser.find({
authorizationToShareInfo: true,
Expand All @@ -31,4 +39,108 @@ exports.getAllPublicArchitectUsers = async (req, res) => {
results: documents.length,
data: { documents },
});
};
});

/**
* Accepts an architect user's request to become a member.
*
* @function
* @async
* @param {Object} req - The request object.
* @param {Object} res - The response object.
* @param {function} next - The next middleware function.
* @returns {Promise<void>} A Promise that resolves when the operation is complete.
* @throws {AppError} If the request cannot be processed.
*
* @example
* // Example usage:
* acceptArchitectUser(req, res, next);
*/
exports.acceptArchitectUser = catchAsync(async (req, res, next) => {
const registrationRequestId = req.params.id;

const registerRequest = await RegisterRequest.findById(
registrationRequestId
).populate({
path: 'newInfo',
select: '-_id -email -isLegacy -overwritten -collegiateNumber -isRequest +password',
});

if (!registerRequest) {
return next(new AppError('La petición de registro ya no existe.', 400));
}

const newArchitectInfo = registerRequest.newInfo;

await ArchitectUser.findByIdAndUpdate(registerRequest.overwrites, {
email: newArchitectInfo.newEmail,
isLegacy: true,
overwritten: true,
collegiateNumber: registerRequest.architectNumber,
isRequest: false,
...newArchitectInfo._doc,
});

const registerRequestNewInfo = await RegisterRequest.findById(registrationRequestId);
await ArchitectUser.findByIdAndDelete(registerRequestNewInfo.newInfo);

await RegisterRequest.findByIdAndDelete(registrationRequestId);

// Uncomment after emails are payed
try {
newArchitectInfo.email = newArchitectInfo.newEmail;
await new Email(newArchitectInfo).sendArchitectAccepted();
} catch (error) {
// Production logging
console.log(error);
}

res.status(200).json({
status: 'success',
message: 'Arquitecto verificado. El usuario ahora cuenta con acceso al portal.',
});
});

/**
* Rejects a Architect user's request to become a member and deletes the request.
*
* @function
* @async
* @param {Object} req - The request object.
* @param {Object} res - The response object.
* @param {function} next - The next middleware function.
* @returns {Promise<void>} A Promise that resolves when the operation is complete.
*
* @example
* // Example usage:
* rejectArchitectUser(req, res, next);
*/
exports.rejectArchitectUser = catchAsync(async (req, res, next) => {
const registrationRequestId = req.params.id;

const registerRequest = await RegisterRequest.findById(
registrationRequestId
).populate('newInfo');

if (!registerRequest) {
return next(new AppError('La petición de registro ya no existe.', 400));
}

await ArchitectUser.findByIdAndDelete(registerRequest.newInfo._id);

await RegisterRequest.findByIdAndDelete(registrationRequestId);

// Uncomment after emails are payed
try {
registerRequest.newInfo.email = registerRequest.newInfo.newEmail;
await new Email(registerRequest.newInfo).sendArchitectRejected();
} catch (error) {
// Production logging
console.log(error);
}

res.status(200).json({
status: 'success',
message: 'Solicitud eliminada. El usuario no fue aceptado en el portal.',
});
});
152 changes: 81 additions & 71 deletions caeq-backend/controllers/auth.controller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const CaeqUser = require('../models/caeq.user.model');
const ArchitectUser = require('../models/architect.user.model');
const RegisterRequest = require('../models/regiesterRequests.model');
const jwt = require('jsonwebtoken');
const catchAsync = require('./../utils/catchAsync');
const AppError = require('./../utils/appError');
Expand Down Expand Up @@ -69,13 +70,12 @@ exports.signUpCaeqUser = catchAsync(async (req, res, next) => {
});

// Uncomment after emails after payed
// try {
// await new Email(newUser).sendWelcomeAdmin();
// } catch (error) {
// return next(
// new AppError('Hemos tenido problemas enviando un correo de bienvenida.', 500)
// );
// }
try {
await new Email(newUser).sendWelcomeAdmin();
} catch (error) {
// Prod logging
console.log(error);
}

// After signup a verified admin must approve the new admin
res.status(200).json({
Expand All @@ -85,6 +85,50 @@ exports.signUpCaeqUser = catchAsync(async (req, res, next) => {
});
});

/**
* Asynchronously creates a registration request for an architect.
*
* @param {Object} req - The request object containing the registration information.
* @param {Object} existingUser - The existing user object, if any.
* @param {Object} res - The response object used to send the registration status.
* @returns {Promise<void>} - A Promise that resolves when the registration process is complete.
*/
async function createRegistrationRequest(req, existingUser, res) {
const email = req.body.email;
delete req.body.email;
const updatedArchitect = await ArchitectUser.create({
...req.body,
email: `${Date.now()}${email}`,
newEmail: email,
isRequest: true,
});

await RegisterRequest.create({
overwrites: existingUser,
newInfo: updatedArchitect,
architectNumber: updatedArchitect.collegiateNumber,
});

updatedArchitect.email = email;
// Send welcome email
try {
await new Email(
updatedArchitect,
process.env.LANDING_URL
).sendWelcomeUserRegistrationRequested();
} catch (error) {
// Prod logging
console.log(error);
}

res.status(200).json({
status: 'success',
message: `Te has registrado con éxito, espera a que un administrador verifique que eres el arquitecto con el número de colegiado ${updatedArchitect.collegiateNumber} y te de acceso al portal.`,
});

return;
}

/**
* Creates a new architect user.
*
Expand All @@ -94,88 +138,51 @@ exports.signUpCaeqUser = catchAsync(async (req, res, next) => {
*/
exports.signUpArchitectUser = catchAsync(async (req, res, next) => {
const { collegiateNumber } = req.body;
let newUser;
const password = req.body.password;
const passwordConfirm = req.body.passwordConfirm;

if (password !== passwordConfirm) {
return next(new AppError('Tus contraseñas deben coincidir.', 400));
}

// Check if user already exists
const existingUser = await ArchitectUser.findOne({ collegiateNumber });
const existingUser = await ArchitectUser.findOne({
collegiateNumber,
});

if (existingUser) {
if (existingUser.isLegacy === true && existingUser.isOverwritten === false) {
const password = req.body.password;
const passwordConfirm = req.body.passwordConfirm;

if (password !== passwordConfirm) {
return next(new AppError('Tus contraseñas deben coincidir.'));
}

delete req.body.password;
delete req.body.passwordConfirm;

// Update existing user
newUser = await ArchitectUser.findOneAndUpdate(
{ _id: existingUser._id },
{ $set: req.body },
{
new: true,
runValidators: true,
useFindAndModify: true,
}
);

// Update password
newUser = await ArchitectUser.findOneAndUpdate(
{ _id: existingUser._id },
{
$set: {
password: await bcrypt.hash(password, 12),
isOverwritten: true,
},
},
{
new: true,
runValidators: false,
useFindAndModify: true,
}
);
} else if (
existingUser.isLegacy === true &&
existingUser.isOverwritten === true
) {
return next(
new AppError(
'Una persona ya se ha inscrito en el portal con estos datos. Crea una nueva cuenta o si crees que es un error contacta a gerencia.'
)
);
if (existingUser.isLegacy === true) {
return await createRegistrationRequest(req, existingUser, res);
} else if (
existingUser.isLegacy === false &&
existingUser.isOverwritten === true
) {
return next(
new AppError(
'El colegiado que intentas sobreescribir se inscribió recientemente y no forma parte del viejo sistema.'
'El colegiado que intentas sobreescribir se inscribió recientemente y no forma parte del viejo sistema.',
400
)
);
} else {
return next(
new AppError(
'Algo salió muy mal.No hemos podido sobreescribir los datos.'
'Algo salió muy mal.No hemos podido sobreescribir los datos.',
400
)
);
}
} else {
// Create new user
newUser = await ArchitectUser.create(req.body);
}

// Uncomment after emails after payed
// // Send welcome email
// try {
// await new Email(newUser, process.env.LANDING_URL).sendWelcomeUser();
// } catch (error) {
// return next(
// new AppError('Hemos tenido problemas enviando un correo de bienvenida.', 500)
// );
// }
let newUser;
newUser = await ArchitectUser.create(req.body);

// Send welcome email
try {
await new Email(newUser, process.env.LANDING_URL).sendWelcomeUser();
} catch (error) {
// Prod logging
console.log(error);
}

// Send JWT token
return createSendToken(newUser, 'architect', 201, req, res);
Expand Down Expand Up @@ -218,13 +225,16 @@ exports.loginArchitectUser = catchAsync(async (req, res, next) => {
if (!user) {
return next(
new AppError(
'Email incorrecto. No hay un usuario registrado con este correo.',
'Email incorrecto. No hay un usuario registrado con este correo. Si te registraste recientemente, por favor espera a que un administrador verifique tu perfil.',
401
)
);
} else if (!(await user.correctPassword(password, user.password))) {
return next(
new AppError('Contraseña incorrecta. Intente de nuevo por favor.', 401)
new AppError(
'Contraseña incorrecta. Intente de nuevo por favor. Si te registraste recientemente, por favor espera a que un administrador verifique tu perfil.',
401
)
);
}

Expand Down
Loading