Skip to content

Commit

Permalink
Merge pull request #763 from OneCommunityGlobal/development
Browse files Browse the repository at this point in the history
Backend Release to Main [1.48]
  • Loading branch information
one-community authored Feb 23, 2024
2 parents e2cfdb9 + 34b6fb3 commit f0222e7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 45 deletions.
20 changes: 16 additions & 4 deletions src/controllers/badgeController.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.');
Expand All @@ -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;
Expand Down
80 changes: 39 additions & 41 deletions src/models/userProfile.js
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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 },
Expand Down Expand Up @@ -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() },
Expand All @@ -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,
Expand Down Expand Up @@ -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: [
{
Expand All @@ -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 },
Expand Down Expand Up @@ -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 },
},
Expand All @@ -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: [
Expand All @@ -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"
);

0 comments on commit f0222e7

Please sign in to comment.