diff --git a/controllers/auth.controller.js b/controllers/auth.controller.js index 8eb93c3..efbfa14 100644 --- a/controllers/auth.controller.js +++ b/controllers/auth.controller.js @@ -44,10 +44,8 @@ export async function logIn(req, res) { secret: jwtToken, }); } catch (error) { - console.log(error); + return response_500(res, 'Internal server error', error); } - - // return response_200(res, 'Hello there!'); } export function greet(req, res) { response_200(res, 'Hello There'); @@ -57,13 +55,16 @@ export async function signUp(req, res) { const { name, email, recaptcha_token } = req.body; if (!(name && email && recaptcha_token && req.body.password)) return response_400(res, 'Some parameters are missing!'); + if (req.body.password.length < 6) return response_400(res, 'Password must be longer than 6 letters'); + if (!validator.isEmail(email)) return response_400(res, 'Email is invalid'); const checkUser = await User.findOne({ email }); if (checkUser) return response_400(res, 'Email already in use'); if (!verifycaptcha(recaptcha_token)) return response_400(res, 'Captcha was found incorrect'); + const password = await hash_password(req.body.password); let newUser = User({ email, diff --git a/controllers/form.controller.js b/controllers/form.controller.js index a792535..0b9208b 100644 --- a/controllers/form.controller.js +++ b/controllers/form.controller.js @@ -13,21 +13,27 @@ import { generateRandomString } from '../utils/generateRandomString.js'; export async function updateForm(req, res) { const id = req.params.id; - const request = req.body; + + const { + name, + hasRecaptcha, + hasFileField, + schema, + password, + recaptcha_token, + } = req.body; + if ( - !( - 'name' in request || - 'hasRecaptcha' in request || - 'hasFileField' in request || - 'schema' in request || - 'password' in request || - 'recaptcha_token' in request - ) + !name || + !hasRecaptcha || + !hasFileField || + !schema || + !password || + !recaptcha_token ) { response_400(res, 'Fields missing for updation'); } - let { name, hasRecaptcha, hasFileField, schema, password, recaptcha_token } = - request; + if (!verifycaptcha(recaptcha_token)) return response_400(res, 'Captcha not verified'); password = await hash_password(password); @@ -93,7 +99,6 @@ export async function createForm(req, res) { 'Number of forms in this project has already reached max limit of 5.', ); } - try { let formId = generateRandomString(16); let submisssionLinkGeneratedAt = Date.now(); @@ -220,21 +225,21 @@ export async function deleteForm(req, res) { select: '_id name email passwordHash', }); if (!form) { - return res.status(400).json({ msg: "Form not found" }); + return res.status(400).json({ msg: 'Form not found' }); } const isOwner = req.user._id === form.project.owner._id; if (!isOwner) { - return res.status(401).json({ msg: "Unauthorized" }); + return res.status(401).json({ msg: 'Unauthorized' }); } const password = req.body.password; password = await hash_password(password); // Assuming the password is provided in the request body if (password !== form.project.owner.passwordHash) { - return res.status(400).json({ msg: "User is not the owner" }); + return res.status(400).json({ msg: 'User is not the owner' }); } await form.deleteOne(); - res.status(200).json({ data: form, msg: "Form deleted successfully" }); + res.status(200).json({ data: form, msg: 'Form deleted successfully' }); } catch (error) { - res.status(500).json({ msg: "An error occurred while deleting the form" }); + res.status(500).json({ msg: 'An error occurred while deleting the form' }); } } @@ -256,4 +261,3 @@ export async function generateSubmissionLink(req, res) { return response_500(res, 'Server Error', error); } } - diff --git a/controllers/project.controller.js b/controllers/project.controller.js index 490dfbf..018a93b 100644 --- a/controllers/project.controller.js +++ b/controllers/project.controller.js @@ -1,6 +1,7 @@ import Project from '../models/project.model.js'; import User from '../models/user.model.js'; import Form from '../models/form.model.js'; +import Collaborators from '../models/invitedCollaborators.model.js'; import verifycaptcha from '../utils/recaptcha.js'; import { sendCollabInvitationLink } from '../utils/mailer.js'; import { getJwt, hash_password } from '../utils/password.js'; @@ -49,15 +50,7 @@ export async function createProject(req, res) { await newProject.save(); req.user.projects.push(newProject._id); await req.user.save(); - if (req.body.collaborators) { - inviteCollaborators( - req.body.collaborators, - newProject.projectId, - newProject.name, - req.user.name, - req.user.email, - ); - } + return response_201(res, 'Project created', { name: newProject.name, id: newProject.projectId, @@ -126,6 +119,7 @@ export async function updateProject(req, res) { } updatedProject.allowedOrigins = req.body.allowedOrigins; } + if (req.body.collaborators) { if (req.body.collaborators.length > 5) { return response_400(res, 'Number of collaborators cannot be greater than 5'); @@ -139,6 +133,7 @@ export async function updateProject(req, res) { ); } + // updating the project details in DB const finalProject = await Project.findOneAndUpdate( { projectId: projectId }, @@ -193,6 +188,57 @@ export async function projectDashboard(req, res) { } } +export async function updateCollaborator(req, res) { + try { + let project=await Project.findById(req.params.projectId).populate('owner', 'name email') + let is_owner = String(project.owner._id) === String(req.user._id); + if(!is_owner){ + response_401('The user is not the owner of project.'); + }else{ + //storing emails we got in an array + const emails=req.body.collaborators; + + // finding all collaborators with projectId + const projectCollaborators=await Collaborators.find({projectId:req.params.projectId}); + + //store emails of every collaborator in an array + const collaboratorsEmails=await projectCollaborators.map((projectCollaborator)=>(projectCollaborator.email)) + + //iterating on every email we got + emails.forEach(async (email)=>{ + //check this email is present in array of collaborators list of this project + const isPresent= collaboratorsEmails.includes(email); + if(!isPresent){ + + //Invite new Collaborator with this email + + // creating collaborator in db + await Collaborators.create({ + email:email, + projectId:req.params.projectId, + status:'Invited' + }); + } + }) + + //checking if any removed collaborators and deleting + collaboratorsEmails.forEach(async (collaboratorEmail)=>{ + const isPresent= emails.includes(collaboratorEmail); + if(!isPresent){ + await Collaborators.findOneAndDelete({ + email:collaboratorEmail, + projectId:req.params.projectId + }) + } + }) + + } + } catch (error) { + console.log(error); + return response_500(res, 'Server error', error); + } +} + function inviteCollaborators( email, projectId, diff --git a/controllers/user.controller.js b/controllers/user.controller.js index c0562ed..2979a2b 100644 --- a/controllers/user.controller.js +++ b/controllers/user.controller.js @@ -8,7 +8,7 @@ import User from '../models/user.model.js'; export function getVerificationLink(req, res) { if (req.user.verified) - return response_400(res, 'The user is already verified'); + return response_200(res, 'The user is already verified'); const payload = { name: req.user.name, email: req.user.email, diff --git a/models/invitedCollaborators.model.js b/models/invitedCollaborators.model.js new file mode 100644 index 0000000..f6a092b --- /dev/null +++ b/models/invitedCollaborators.model.js @@ -0,0 +1,28 @@ +import { model, Schema } from 'mongoose'; + +const invitedCollaboratorsSchema = new Schema({ + email:{ + type: String, + required:true + }, + userId:{ + type: Schema.Types.ObjectId , + ref: 'user', + null:true, + default:null + }, + projectId:{ + type: Schema.Types.ObjectId , + ref: 'project', + required:true, + }, + status:{ + type:String, + required:true, + enum:['Invited','Rejected','Accepted'] + } +}, { timestamps: true }); + +const InvitedCollaborator = model('Collaborators', invitedCollaboratorsSchema); + +export default InvitedCollaborator; diff --git a/package-lock.json b/package-lock.json index ae319e5..1c171b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9703,7 +9703,8 @@ "pg-pool": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz", - "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==" + "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==", + "requires": {} }, "pg-protocol": { "version": "1.6.0", diff --git a/routes/project.routes.js b/routes/project.routes.js index 800243b..32d77e7 100644 --- a/routes/project.routes.js +++ b/routes/project.routes.js @@ -1,6 +1,6 @@ // import handler (controller) functions to route them import { greet } from '../controllers/auth.controller.js'; -import { createProject, deleteProject, projectDashboard, updateProject } from '../controllers/project.controller.js'; +import { createProject, deleteProject, projectDashboard, updateProject ,updateCollaborator} from '../controllers/project.controller.js'; import verifiedMiddleware from '../middlewares/verify.middleware.js'; import { Router } from 'express'; @@ -12,5 +12,6 @@ router.post("/new", verifiedMiddleware, createProject); router.get("/dashboard/:id", verifiedMiddleware, projectDashboard); router.patch("/update/:projectId", verifiedMiddleware, updateProject); router.delete("/delete/:id", verifiedMiddleware, deleteProject) +router.post("/updateCollaborator", verifiedMiddleware,updateCollaborator) export default router; \ No newline at end of file