Enhance session and profile handling with validation and error handling improvements

This commit is contained in:
Adolfo Reyna
2025-02-27 23:12:11 -05:00
parent 606db78529
commit 56cb8b4caa
4 changed files with 235 additions and 179 deletions

View File

@@ -124,21 +124,35 @@ userDB = (DB) => {
return DB.getProfile(profileId); return DB.getProfile(profileId);
} }
DB.getProfileCache = async (profileId) => {
const cachedProfile = userProfileCache[profileId];
if (cachedProfile?.isGroup === false) {
return cachedProfile;
}
return await DB.getProfile(profileId);
};
DB.searchProfile = async (queryStr) => { DB.searchProfile = async (queryStr) => {
let regEx = new RegExp(queryStr, 'i'); let regEx = new RegExp(queryStr, 'i');
let query = { let query = {
isGroup: false, isGroup: false,
isChat: { $ne: true }, isChat: { $ne: true },
$or: [ $or: [
{"profile.firstName": { {
"profile.firstName": {
$regex: regEx $regex: regEx
}}, }
{"profile.lastName": { },
{
"profile.lastName": {
$regex: regEx $regex: regEx
}}, }
{"profile.description": { },
{
"profile.description": {
$regex: regEx $regex: regEx
}}, }
},
] ]
}; };
let r = await DB.profileCols.find(queryStr ? query : { isGroup: false, isChat: { $ne: true } }) let r = await DB.profileCols.find(queryStr ? query : { isGroup: false, isChat: { $ne: true } })
@@ -154,7 +168,7 @@ userDB = (DB) => {
const userid = DB.ObjectID(userId); const userid = DB.ObjectID(userId);
return await DB.profileCols.find({ userid }).toArray().catch((err) => { return await DB.profileCols.find({ userid }).toArray().catch((err) => {
console.log(err); console.log(err);
return false; return [];
}); });
} }
@@ -332,18 +346,26 @@ userDB = (DB) => {
isChat: { $ne: true }, isChat: { $ne: true },
isCourse: coursesB, isCourse: coursesB,
$or: [ $or: [
{"profile.firstName": { {
"profile.firstName": {
$regex: regEx $regex: regEx
}}, }
{"profile.lastName": { },
{
"profile.lastName": {
$regex: regEx $regex: regEx
}}, }
{"profile.description": { },
{
"profile.description": {
$regex: regEx $regex: regEx
}}, }
{"data.author": { },
{
"data.author": {
$regex: regEx $regex: regEx
}} }
}
] ]
} : { isGroup: true, isChat: { $ne: true }, isCourse: coursesB }; } : { isGroup: true, isChat: { $ne: true }, isCourse: coursesB };
let r = await DB.profileCols.find(query) let r = await DB.profileCols.find(query)

View File

@@ -1,15 +1,15 @@
class User { class User {
constructor(info){ constructor(info){
if(!info || !info.userid) throw "Can not construct empty profile"; if(!info || !info.userid) throw new Error("Cannot construct empty profile");
this.userid = info.userid; this.userid = info.userid;
this.profile = { this.profile = {
firstName: info.profile && info.profile.firstName || '', firstName: info.profile?.firstName || '',
lastName: info.profile && info.profile.lastName || '', lastName: info.profile?.lastName || '',
photo: info.profile && info.profile.photo || '', photo: info.profile?.photo || '',
location: info.profile && info.profile.location || 'USA', location: info.profile?.location || 'USA',
language: info.profile && info.profile.language || 'en', language: info.profile?.language || 'en',
status: info.profile && info.profile.status || '', status: info.profile?.status || '',
description: info.profile && info.profile.description || '', description: info.profile?.description || '',
}; };
this.data = info.data || {}; this.data = info.data || {};
this.username = info.username || ''; this.username = info.username || '';
@@ -23,8 +23,8 @@ class User {
this.isCourse = info.isCourse || false; this.isCourse = info.isCourse || false;
this.isPrivate = info.isPrivate || false; this.isPrivate = info.isPrivate || false;
this.isChat = info.isChat || false; this.isChat = info.isChat || false;
this.subscribed = info.subscribed || {}; //Subscribed user to groups this.subscribed = JSON.parse(JSON.stringify(info.subscribed || {})); //Subscribed user to groups
this.pending = info.pending || {}; //Private groups require authorization this.pending = JSON.parse(JSON.stringify(info.pending || {})); //Private groups require authorization
} }
toObj(){ toObj(){

View File

@@ -4,26 +4,18 @@ var router = express.Router()
const DB = require("../mongoDB.js"); const DB = require("../mongoDB.js");
const Profile = require("../def/profile.js"); const Profile = require("../def/profile.js");
const Notifications = require("./../notifications.js"); const Notifications = require("./../notifications.js");
const { getSessionId, getUserId, getProfileId } = require("./../utils/sessionUtils.js");
DB.getDB.then((DB) => { DB.getDB.then((DB) => {
const getUserId = function(req){
const user_sid = req.cookies.user_sid || req.query.user_sid || req.body.user_sid;
return DB.ObjectID(user_sid);
}
const getProfileId = (req)=>{
return DB.ObjectID(req.cookies.profile_id || req.query.profile_id || req.body.profile_id);
}
const profileBelongsToUser = async (profileid, userid) => { const profileBelongsToUser = async (profileid, userid) => {
const profile = await DB.getProfileCache(profileid); const profile = await DB.getProfileCache(profileid);
if (!profile) return false; if (!profile) return false;
return profile.userid == (userid + ''); return profile.userid === String(userid);
} }
router.get("/mine", async (req, res) => { router.get("/mine", async (req, res) => {
let userid = req.cookies.user_sid; let userid = getUserId(req);
let profiles = await DB.getUserProfiles(userid); let profiles = await DB.getUserProfiles(userid);
return res.json({ return res.json({
status: "ok", status: "ok",
@@ -49,32 +41,57 @@ DB.getDB.then((DB)=>{
userid: getUserId(req), userid: getUserId(req),
...req.body.content ...req.body.content
}; };
try {
let profileObj = new Profile(profile); let profileObj = new Profile(profile);
let r = await DB.newProfile(profileObj); let r = await DB.newProfile(profileObj);
return res.json({ return res.json({
status: "ok", status: "ok",
...profileObj.toObj() ...profileObj.toObj()
}); });
} catch (error) {
console.error("Error creating profile", error);
return res.json({
status: error,
});
}
}); });
router.post("/invite", async (req, res) => { router.post("/invite", async (req, res) => {
try {
const userid = getUserId(req); const userid = getUserId(req);
const name = req.body.name; let { name, email } = req.body; // Destructuring for clarity
const email = req.body.email; // Validate required fields
//validate email? if (!name || !email) {
if(!name || !email) return res.json({status: "incomplete request"}); return res.status(400).json({ status: "Name and email are required" });
}
// Validate email format
email = email.trim().toLowerCase()
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return res.status(400).json({ status: "Invalid email format" });
}
// Create new invitation, this returns a string if failed
let r = await DB.newInvitation(userid, name, email); let r = await DB.newInvitation(userid, name, email);
if(!r.toLowerCase){ if (r instanceof String) {
//send email invitation // Handle failure response from DB.newInvitation
let senderProfile = await DB.getProfile(getProfileId(req)); return res.status(400).json({
Notifications.youHaveAnInvitation(name, email, senderProfile); status: r,
return res.json({ message: `Failed to send invitation: ${r}`
status: "ok"
}); });
} }
return res.json({ // Handle response from DB.newInvitation
status: r // Send email invitation
let senderProfile = await DB.getProfile(getProfileId(req));
Notifications.youHaveAnInvitation(name, email, senderProfile);
return res.status(200).json({
status: "ok",
message: `Invitation sent to ${name} (${email})`
}); });
} catch (error) {
console.error("Error during invitation process:", error);
return res.status(500).json({ status: "error", message: "Something went wrong, please try again later" });
}
}); });
router.get("/invite/:email", async (req, res) => { router.get("/invite/:email", async (req, res) => {

View File

@@ -1,14 +1,31 @@
const { ObjectId } = require("mongodb");
const isValidObjectId = (id) => ObjectId.isValid(id);
// Utilities // Utilities
const getSessionId = function (req) { const getSessionId = function (req) {
const session_id = req.cookies.session_id || req.query.session_id || req.body.session_id; const session_id = req.cookies.session_id || req.query.session_id || req.body.session_id;
if(isValidObjectId(session_id)) {
return session_id;
}
console.error("Invalid session_id format: ", session_id);
return session_id; return session_id;
} }
const getUserId = function (req) { const getUserId = function (req) {
const user_sid = req.cookies.user_sid || req.query.user_sid || req.body.user_sid; const user_sid = req.cookies.user_sid || req.query.user_sid || req.body.user_sid;
// validate user_sid
if(isValidObjectId(user_sid)) {
return user_sid;
}
console.error("Invalid user_sid format: ", user_sid);
return user_sid; return user_sid;
} }
const getProfileId = function (req) { const getProfileId = function (req) {
const profile_id = req.cookies.profile_id || req.query.profile_id || req.body.profile_id; const profile_id = req.cookies.profile_id || req.query.profile_id || req.body.profile_id;
if(isValidObjectId(profile_id)) {
return profile_id;
}
console.error("Invalid profile_id format: ", profile_id);
return profile_id; return profile_id;
} }