diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js index 316230ccb..0df008386 100644 --- a/src/controllers/badgeController.js +++ b/src/controllers/badgeController.js @@ -43,11 +43,11 @@ const badgeController = function (Badge) { }; /** - * Updated Date: 01/12/2024 + * Updated Date: 12/06/2023 * Updated By: Shengwei * Function added: * - Added data validation for earned date and badge count mismatch. - * - Added fillEarnedDateToMatchCount function to resolve earned date and badge count mismatch. (Deleted due to new requirement) + * - Added fillEarnedDateToMatchCount function to resolve earned date and badge count mismatch. * - Refactored data validation for duplicate badge id. * - Added data validation for badge count should greater than 0. * - Added formatDate function to format date to MMM-DD-YY. @@ -58,6 +58,14 @@ const badgeController = function (Badge) { return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY'); }; + const fillEarnedDateToMatchCount = (earnedDate, count) => { + const result = [...earnedDate]; + while (result.length < count) { + result.push(formatDate()); + } + return result; + }; + const assignBadges = async function (req, res) { if (!(await hasPermission(req.body.requestor, 'assignBadges'))) { res.status(403).send('You are not authorized to assign badges.'); @@ -80,16 +88,20 @@ const badgeController = function (Badge) { newBadgeCollection = req.body.badgeCollection.map((element) => { if (badgeCounts[element.badge]) { throw new Error('Duplicate badges sent in.'); + // res.status(500).send('Duplicate badges sent in.'); + // return; } badgeCounts[element.badge] = element.count; // Validation: count should be greater than 0 if (element.count < 1) { throw new Error('Badge count should be greater than 0.'); } + return element; }); } catch (err) { - logger.logException(`Internal Error: Badge Collection. ${err.message} User ID: ${userToBeAssigned} Badge Collection: ${JSON.stringify(req.body.badgeCollection)}`); - res.status(500).send(`Internal Error: Badge Collection. ${ err.message}`); + res + .status(500) + .send(`Internal Error: Badge Collection. ${err.message}`); return; } record.badgeCollection = newBadgeCollection; diff --git a/src/models/userProfile.js b/src/models/userProfile.js index 153028818..68a9d127a 100644 --- a/src/models/userProfile.js +++ b/src/models/userProfile.js @@ -1,9 +1,9 @@ -const mongoose = require('mongoose'); -const moment = require('moment-timezone'); +const mongoose = require("mongoose"); +const moment = require("moment-timezone"); const { Schema } = mongoose; -const validate = require('mongoose-validator'); -const bcrypt = require('bcryptjs'); +const validate = require("mongoose-validator"); +const bcrypt = require("bcryptjs"); const SALT_ROUNDS = 10; const nextDay = new Date(); @@ -15,11 +15,12 @@ const userProfileSchema = new Schema({ required: true, validate: { validator(v) { - const passwordregex = /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; + const passwordregex = + /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; return passwordregex.test(v); }, message: - '{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.', + "{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.", }, }, isActive: { type: Boolean, required: true, default: true }, @@ -49,7 +50,7 @@ const userProfileSchema = new Schema({ required: true, unique: true, validate: [ - validate({ validator: 'isEmail', message: 'Email address is invalid' }), + validate({ validator: "isEmail", message: "Email address is invalid" }), ], }, copiedAiPrompt: { type: Date, default: Date.now() }, @@ -68,17 +69,14 @@ const userProfileSchema = new Schema({ { _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }, ], adminLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: String }], - teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'team' }], - projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'project' }], + teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: "team" }], + projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: "project" }], badgeCollection: [ { - badge: { type: mongoose.SchemaTypes.ObjectId, ref: 'badge' }, + badge: { type: mongoose.SchemaTypes.ObjectId, ref: "badge" }, count: { type: Number, default: 0 }, earnedDate: { type: Array, default: [] }, - lastModified: { type: Date, required: true, default: Date.now() }, - // This field is used to determine if the badge deletion will impact the user's badge collection. - // If the user has a badge with hasBadgeDeletionImpact set to true, then the a mismatch in badge - // count and earned date will be intentionally created. + lastModified: { type: Date, required: true, default: new Date()}, hasBadgeDeletionImpact: { type: Boolean, default: false }, featured: { type: Boolean, @@ -118,13 +116,13 @@ const userProfileSchema = new Schema({ }, ], location: { - userProvided: { type: String, default: '' }, + userProvided: { type: String, default: "" }, coords: { - lat: { type: Number, default: '' }, - lng: { type: Number, default: '' }, + lat: { type: Number, default: "" }, + lng: { type: Number, default: "" }, }, - country: { type: String, default: '' }, - city: { type: String, default: '' }, + country: { type: String, default: "" }, + city: { type: String, default: "" }, }, oldInfringements: [ { @@ -146,7 +144,7 @@ const userProfileSchema = new Schema({ dueDate: { type: Date, required: true, - default: moment().tz('America/Los_Angeles').endOf('week'), + default: moment().tz("America/Los_Angeles").endOf("week"), }, summary: { type: String }, uploadDate: { type: Date }, @@ -176,17 +174,17 @@ const userProfileSchema = new Schema({ category: { type: String, enum: [ - 'Food', - 'Energy', - 'Housing', - 'Education', - 'Society', - 'Economics', - 'Stewardship', - 'Other', - 'Unspecified', + "Food", + "Energy", + "Housing", + "Education", + "Society", + "Economics", + "Stewardship", + "Other", + "Unspecified", ], - default: 'Other', + default: "Other", }, hrs: { type: Number, default: 0 }, }, @@ -197,27 +195,27 @@ const userProfileSchema = new Schema({ date: { type: Date, required: true, - default: moment().tz('America/Los_Angeles').toDate(), + default: moment().tz("America/Los_Angeles").toDate(), }, initialSeconds: { type: Number, required: true }, newSeconds: { type: Number, required: true }, }, ], weeklySummaryNotReq: { type: Boolean, default: false }, - timeZone: { type: String, required: true, default: 'America/Los_Angeles' }, + timeZone: { type: String, required: true, default: "America/Los_Angeles" }, isVisible: { type: Boolean, default: false }, weeklySummaryOption: { type: String }, - bioPosted: { type: String, default: 'default' }, + bioPosted: { type: String, default: "default" }, isFirstTimelog: { type: Boolean, default: true }, teamCode: { type: String, - default: '', + default: "", validate: { validator(v) { const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$|^$/; return teamCoderegex.test(v); }, - message: 'Please enter a code in the format of A-AAA or AAAAA', + message: "Please enter a code in the format of A-AAA or AAAAA", }, }, infoCollections: [ @@ -232,22 +230,22 @@ const userProfileSchema = new Schema({ timeOffTill: { type: Date, default: undefined }, }); -userProfileSchema.pre('save', function (next) { +userProfileSchema.pre("save", function (next) { const user = this; - if (!user.isModified('password')) return next(); + if (!user.isModified("password")) return next(); return bcrypt .genSalt(SALT_ROUNDS) - .then(result => bcrypt.hash(user.password, result)) + .then((result) => bcrypt.hash(user.password, result)) .then((hash) => { user.password = hash; return next(); }) - .catch(error => next(error)); + .catch((error) => next(error)); }); module.exports = mongoose.model( - 'userProfile', + "userProfile", userProfileSchema, - 'userProfiles', + "userProfiles" );