diff --git a/api/Controllers/Collection.js b/api/Controllers/Collection.js
index 257e6cb0..d275a917 100644
--- a/api/Controllers/Collection.js
+++ b/api/Controllers/Collection.js
@@ -22,7 +22,9 @@ module.exports.getCollectionBasicList = async function getCollectionBasicList(re
module.exports.getCollections = async function getCollections(req, res, next) {
try {
- const getCollections = await collectionService.getCollections(req.params.userName);
+ const userId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ const getCollections = await collectionService.getCollections(userId, elevate);
if (getCollections.error) {
res.status(500).json({ error: 'Internal Server Error', detail: getCollections.error });
} else {
diff --git a/api/Controllers/Marketplace.js b/api/Controllers/Marketplace.js
index 3a2dc38e..41f74efc 100644
--- a/api/Controllers/Marketplace.js
+++ b/api/Controllers/Marketplace.js
@@ -35,7 +35,7 @@ module.exports.purchaseTheme = async function purchaseTheme(req, res, next) {
module.exports.getUserThemes = async function getUserThemes(req, res, next) {
try {
- const userId = req.params.userId;
+ const userId = req.userObject.userId;
const themes = await marketplaceService.getUserThemes(userId);
res.status(200).json(themes);
} catch (error) {
@@ -45,7 +45,7 @@ module.exports.getUserThemes = async function getUserThemes(req, res, next) {
module.exports.getUserPoints = async function getUserPoints(req, res, next) {
try {
- const userId = req.params.userId;
+ const userId = req.userObject.userId;
const points = await marketplaceService.getUserPoints(userId);
res.status(200).json(points);
} catch (error) {
diff --git a/api/Controllers/Metrics.js b/api/Controllers/Metrics.js
index 1227c87c..49959b07 100644
--- a/api/Controllers/Metrics.js
+++ b/api/Controllers/Metrics.js
@@ -12,7 +12,8 @@ const metricsService = require('../Services/metricsService');
module.exports.getCollectionAssetLabel = async function getCollectionAssetLabel(req, res, next) {
try {
- const getMetrics = await metricsService.getCollectionAssetLabel(req, res, next);
+ const collectionId = req.params.collectionId;
+ const getMetrics = await metricsService.getCollectionAssetLabel(collectionId);
if (getMetrics) {
res.status(200).json(getMetrics);
} else {
@@ -25,7 +26,8 @@ module.exports.getCollectionAssetLabel = async function getCollectionAssetLabel(
module.exports.getCollectionPoamLabel = async function getCollectionPoamLabel(req, res, next) {
try {
- const getMetrics = await metricsService.getCollectionPoamLabel(req, res, next);
+ const collectionId = req.params.collectionId;
+ const getMetrics = await metricsService.getCollectionPoamLabel(collectionId);
if (getMetrics) {
res.status(200).json(getMetrics);
} else {
@@ -38,7 +40,8 @@ module.exports.getCollectionPoamLabel = async function getCollectionPoamLabel(re
module.exports.getCollectionPoamStatus = async function getCollectionPoamStatus(req, res, next) {
try {
- const getMetrics = await metricsService.getCollectionPoamStatus(req, res, next);
+ const collectionId = req.params.collectionId;
+ const getMetrics = await metricsService.getCollectionPoamStatus(collectionId);
if (getMetrics && getMetrics.poamStatus) {
res.status(200).json(getMetrics);
} else {
@@ -51,7 +54,8 @@ module.exports.getCollectionPoamStatus = async function getCollectionPoamStatus(
module.exports.getCollectionPoamSeverity = async function getCollectionPoamSeverity(req, res, next) {
try {
- const getMetrics = await metricsService.getCollectionPoamSeverity(req, res, next);
+ const collectionId = req.params.collectionId;
+ const getMetrics = await metricsService.getCollectionPoamSeverity(collectionId);
if (getMetrics && getMetrics.poamSeverity) {
res.status(200).json(getMetrics);
} else {
@@ -64,7 +68,8 @@ module.exports.getCollectionPoamSeverity = async function getCollectionPoamSever
module.exports.getCollectionPoamScheduledCompletion = async function getCollectionPoamScheduledCompletion(req, res, next) {
try {
- const getMetrics = await metricsService.getCollectionPoamScheduledCompletion(req, res, next);
+ const collectionId = req.params.collectionId;
+ const getMetrics = await metricsService.getCollectionPoamScheduledCompletion(collectionId);
if (getMetrics && getMetrics.poamScheduledCompletion) {
res.status(200).json(getMetrics);
} else {
@@ -77,7 +82,8 @@ module.exports.getCollectionPoamScheduledCompletion = async function getCollecti
module.exports.getCollectionMonthlyPoamStatus = async function getCollectionMonthlyPoamStatus(req, res, next) {
try {
- const getMetrics = await metricsService.getCollectionMonthlyPoamStatus(req, res, next);
+ const collectionId = req.params.collectionId;
+ const getMetrics = await metricsService.getCollectionMonthlyPoamStatus(collectionId);
if (getMetrics && getMetrics.poamStatus) {
res.status(200).json(getMetrics);
} else {
@@ -90,7 +96,8 @@ module.exports.getCollectionMonthlyPoamStatus = async function getCollectionMont
module.exports.getAvailableAssetLabel = async function getAvailableAssetLabel(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailableAssetLabel(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailableAssetLabel(userId);
if (getMetrics) {
res.status(200).json(getMetrics);
} else {
@@ -103,7 +110,8 @@ module.exports.getAvailableAssetLabel = async function getAvailableAssetLabel(re
module.exports.getAvailablePoamLabel = async function getAvailablePoamLabel(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailablePoamLabel(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailablePoamLabel(userId);
if (getMetrics) {
res.status(200).json(getMetrics);
} else {
@@ -116,7 +124,8 @@ module.exports.getAvailablePoamLabel = async function getAvailablePoamLabel(req,
module.exports.getAvailableCollectionPoamCounts = async function getAvailableCollectionPoamCounts(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailableCollectionPoamCounts(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailableCollectionPoamCounts(userId);
if (getMetrics) {
res.status(200).json(getMetrics);
} else {
@@ -129,7 +138,8 @@ module.exports.getAvailableCollectionPoamCounts = async function getAvailableCol
module.exports.getAvailablePoamStatus = async function getAvailablePoamStatus(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailablePoamStatus(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailablePoamStatus(userId);
if (getMetrics && getMetrics.poamStatus) {
res.status(200).json(getMetrics);
} else {
@@ -142,7 +152,8 @@ module.exports.getAvailablePoamStatus = async function getAvailablePoamStatus(re
module.exports.getAvailablePoamSeverity = async function getAvailablePoamSeverity(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailablePoamSeverity(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailablePoamSeverity(userId);
if (getMetrics && getMetrics.poamSeverity) {
res.status(200).json(getMetrics);
} else {
@@ -155,7 +166,8 @@ module.exports.getAvailablePoamSeverity = async function getAvailablePoamSeverit
module.exports.getAvailableMonthlyPoamSeverity = async function getAvailableMonthlyPoamSeverity(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailableMonthlyPoamSeverity(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailableMonthlyPoamSeverity(userId);
if (getMetrics && getMetrics.poamSeverity) {
res.status(200).json(getMetrics);
} else {
@@ -168,7 +180,8 @@ module.exports.getAvailableMonthlyPoamSeverity = async function getAvailableMont
module.exports.getAvailableMonthlyPoamStatus = async function getAvailableMonthlyPoamStatus(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailableMonthlyPoamStatus(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailableMonthlyPoamStatus(userId);
if (getMetrics && getMetrics.poamStatus) {
res.status(200).json(getMetrics);
} else {
@@ -181,7 +194,8 @@ module.exports.getAvailableMonthlyPoamStatus = async function getAvailableMonthl
module.exports.getAvailablePoamScheduledCompletion = async function getAvailablePoamScheduledCompletion(req, res, next) {
try {
- const getMetrics = await metricsService.getAvailablePoamScheduledCompletion(req, res, next);
+ const userId = req.userObject.userId;
+ const getMetrics = await metricsService.getAvailablePoamScheduledCompletion(userId);
if (getMetrics && getMetrics.poamScheduledCompletion) {
res.status(200).json(getMetrics);
} else {
diff --git a/api/Controllers/Notification.js b/api/Controllers/Notification.js
index 9eb1a491..fc645ac8 100644
--- a/api/Controllers/Notification.js
+++ b/api/Controllers/Notification.js
@@ -10,40 +10,45 @@
const notificationService = require('../Services/notificationService');
-module.exports.getAllNotificationsByUserId = async function getAllNotificationsByUserId(req, res, next) {
+module.exports.getAllNotifications = async function getAllNotifications(req, res, next) {
try {
- const userId = req.params.userId;
- const notifications = await notificationService.getAllNotificationsByUserId(userId);
+ const userId = req.userObject.userId;
+ const notifications = await notificationService.getAllNotifications(userId);
+
res.status(200).json(notifications);
} catch (error) {
res.status(500).json({ error: 'Internal Server Error', detail: error.message });
}
};
-module.exports.getUnreadNotificationsByUserId = async function getUnreadNotificationsByUserId(req, res, next) {
+module.exports.getUnreadNotifications = async function getUnreadNotifications(req, res, next) {
try {
- const userId = req.params.userId;
- const notifications = await notificationService.getUnreadNotificationsByUserId(userId);
+ const userId = req.userObject.userId;
+ const notifications = await notificationService.getUnreadNotifications(userId);
+
res.status(200).json(notifications);
} catch (error) {
res.status(500).json({ error: 'Internal Server Error', detail: error.message });
}
};
-module.exports.getUnreadNotificationCountByUserId = async function getUnreadNotificationCountByUserId(req, res, next) {
+module.exports.getUnreadNotificationCount = async function getUnreadNotificationCount(req, res, next) {
try {
- const userId = req.params.userId;
- const notificationCount = await notificationService.getUnreadNotificationCountByUserId(userId);
+ const userId = req.userObject.userId;
+ const notificationCount = await notificationService.getUnreadNotificationCount(userId);
+
res.status(200).json(notificationCount);
} catch (error) {
res.status(500).json({ error: 'Internal Server Error', detail: error.message });
}
};
-module.exports.dismissNotificationByNotificationId = async function dismissNotificationByNotificationId(req, res, next) {
+module.exports.dismissNotification = async function dismissNotification(req, res, next) {
try {
+ const userId = req.userObject.userId;
const notificationId = req.params.notificationId;
- const unreadNotifications = await notificationService.dismissNotificationByNotificationId(notificationId);
+ const unreadNotifications = await notificationService.dismissNotification(userId, notificationId);
+
if (unreadNotifications !== null) {
res.status(200).json(unreadNotifications);
} else {
@@ -54,10 +59,10 @@ module.exports.dismissNotificationByNotificationId = async function dismissNotif
}
};
-module.exports.dismissAllNotificationsByUserId = async function dismissAllNotificationsByUserId(req, res, next) {
+module.exports.dismissAllNotifications = async function dismissAllNotifications(req, res, next) {
try {
- const userId = req.params.userId;
- const dismissed = await notificationService.dismissAllNotificationsByUserId(userId);
+ const userId = req.userObject.userId;
+ const dismissed = await notificationService.dismissAllNotifications(userId);
if (dismissed) {
res.status(204).json();
} else {
@@ -68,10 +73,11 @@ module.exports.dismissAllNotificationsByUserId = async function dismissAllNotifi
}
};
-module.exports.deleteNotificationByNotificationId = async function deleteNotificationByNotificationId(req, res, next) {
+module.exports.deleteNotification = async function deleteNotification(req, res, next) {
try {
+ const userId = req.userObject.userId;
const notificationId = req.params.notificationId;
- const deleted = await notificationService.deleteNotificationByNotificationId(notificationId);
+ const deleted = await notificationService.deleteNotification(userId, notificationId);
if (deleted) {
res.status(204).send();
@@ -83,10 +89,10 @@ module.exports.deleteNotificationByNotificationId = async function deleteNotific
}
};
-module.exports.deleteAllNotificationsByUserId = async function deleteAllNotificationsByUserId(req, res, next) {
+module.exports.deleteAllNotifications = async function deleteAllNotifications(req, res, next) {
try {
- const userId = req.params.userId;
- const deleted = await notificationService.deleteAllNotificationsByUserId(userId);
+ const userId = req.userObject.userId;
+ const deleted = await notificationService.deleteAllNotifications(userId);
if (deleted) {
res.status(204).send();
diff --git a/api/Controllers/Permissions.js b/api/Controllers/Permissions.js
index e567b54c..5470c02c 100644
--- a/api/Controllers/Permissions.js
+++ b/api/Controllers/Permissions.js
@@ -10,18 +10,6 @@
const permissionService = require('../Services/permissionsService');
-module.exports.getCollectionPermission = async function getCollectionPermission(req, res, next) {
- try {
- const getCollection = await permissionService.getCollectionPermission(req.params.userName, req.params.collectionId, req, res, next);
- if (getCollection) {
- res.status(200).json(getCollection);
- } else {
- res.status(204).send();
- }
- } catch (error) {
- res.status(500).json({ error: 'Internal Server Error', detail: error.message });
- }
-};
module.exports.getCollectionPermissions = async function getCollectionPermissions(req, res, next) {
try {
@@ -38,7 +26,9 @@ module.exports.getCollectionPermissions = async function getCollectionPermission
module.exports.postPermission = async function postPermission(req, res, next) {
try {
- const permission = await permissionService.postPermission(req, res, next);
+ const userId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ const permission = await permissionService.postPermission(userId, elevate, req);
res.status(201).json(permission);
} catch (error) {
if (error.status === 400) {
@@ -51,7 +41,9 @@ module.exports.postPermission = async function postPermission(req, res, next) {
module.exports.putPermission = async function putPermission(req, res, next) {
try {
- const permission = await permissionService.putPermission(req, res, next);
+ const userId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ const permission = await permissionService.putPermission(userId, elevate, req);
res.status(200).json(permission);
} catch (error) {
if (error.status === 400) {
@@ -64,7 +56,9 @@ module.exports.putPermission = async function putPermission(req, res, next) {
module.exports.deletePermission = async function deletePermission(req, res, next) {
try {
- await permissionService.deletePermission(req, res, next);
+ const userId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ await permissionService.deletePermission(userId, elevate, req);
res.status(204).send();
} catch (error) {
if (error.status === 400) {
diff --git a/api/Controllers/Poam.js b/api/Controllers/Poam.js
index 60caffc4..97093005 100644
--- a/api/Controllers/Poam.js
+++ b/api/Controllers/Poam.js
@@ -12,7 +12,8 @@ const poamService = require('../Services/poamService');
module.exports.getAvailablePoams = async function getAvailablePoams(req, res, next) {
try {
- const poams = await poamService.getAvailablePoams(req, res, next);
+ const userId = req.userObject.userId;
+ const poams = await poamService.getAvailablePoams(userId, req);
res.status(200).json(poams);
} catch (error) {
if (error.status === 400) {
diff --git a/api/Controllers/PoamApprover.js b/api/Controllers/PoamApprover.js
index ab80ba08..506bea3b 100644
--- a/api/Controllers/PoamApprover.js
+++ b/api/Controllers/PoamApprover.js
@@ -28,24 +28,6 @@ module.exports.getPoamApproversByCollection = async function getPoamApproversByC
}
};
-module.exports.getPoamApproversByCollectionUser = async function getPoamApproversByCollectionUser(req, res, next) {
- try {
- const poamApprovers = await poamApproverService.getPoamApproversByCollectionUser(req, res, next);
- res.status(200).json(poamApprovers);
- } catch (error) {
- res.status(400).json({ error: error.message });
- }
-};
-
-module.exports.getPoamApproversByUserId = async function getPoamApproversByUserId(req, res, next) {
- try {
- const poamApprovers = await poamApproverService.getPoamApproversByUserId(req, res, next);
- res.status(200).json(poamApprovers);
- } catch (error) {
- res.status(400).json({ error: error.message });
- }
-};
-
module.exports.postPoamApprover = async function postPoamApprover(req, res, next) {
try {
const poamApprover = await poamApproverService.postPoamApprover(req, res, next);
diff --git a/api/Controllers/PoamAssignees.js b/api/Controllers/PoamAssignees.js
index 3aaaa5aa..1f97fefc 100644
--- a/api/Controllers/PoamAssignees.js
+++ b/api/Controllers/PoamAssignees.js
@@ -28,25 +28,6 @@ exports.getPoamAssigneesByPoamId = async function getPoamAssigneesByPoamId(req,
}
};
-
-exports.getPoamAssigneesByUserId = async function getPoamAssigneesByUserId(req, res, next) {
- try {
- const result = await poamAssigneeService.getPoamAssigneesByUserId(req, res, next);
- return res.status(200).json(result);
- } catch (error) {
- return res.status(500).json({ error: "An error occurred while retrieving POAM assignees by userId" });
- }
-};
-
-exports.getPoamAssignee = async function getPoamAssignee(req, res, next) {
- try {
- const result = await poamAssigneeService.getPoamAssignee(req, res, next);
- return res.status(200).json(result);
- } catch (error) {
- return res.status(500).json({ error: "An error occurred while retrieving the POAM assignee" });
- }
-};
-
exports.postPoamAssignee = async function postPoamAssignee(req, res, next) {
try {
const assignee = await poamAssigneeService.postPoamAssignee(req, res, next);
diff --git a/api/Controllers/PoamLabel.js b/api/Controllers/PoamLabel.js
index e781735e..e5c46c93 100644
--- a/api/Controllers/PoamLabel.js
+++ b/api/Controllers/PoamLabel.js
@@ -26,7 +26,8 @@ module.exports.getPoamLabels = async function getPoamLabels(req, res, next) {
module.exports.getAvailablePoamLabels = async function getAvailablePoamLabels(req, res, next) {
try {
- const poamLabels = await poamLabelService.getAvailablePoamLabels(req, res, next);
+ const userId = req.userObject.userId;
+ const poamLabels = await poamLabelService.getAvailablePoamLabels(userId);
res.status(200).json(poamLabels);
} catch (error) {
if (error.message === 'User ID is required') {
diff --git a/api/Controllers/User.js b/api/Controllers/User.js
index a9657194..4ca69725 100644
--- a/api/Controllers/User.js
+++ b/api/Controllers/User.js
@@ -12,7 +12,9 @@ const userService = require('../Services/usersService');
module.exports.getUsers = async function getUsers(req, res, next) {
try {
- const users = await userService.getUsers();
+ const userId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ const users = await userService.getUsers(elevate, userId);
res.status(200).json(users);
} catch (error) {
res.status(500).json({ error: 'Internal Server Error', detail: error.message });
@@ -21,8 +23,8 @@ module.exports.getUsers = async function getUsers(req, res, next) {
module.exports.getCurrentUser = async function getCurrentUser(req, res, next) {
try {
- const email = req.userObject.email;
- const user = await userService.getCurrentUser(email);
+ const userId = req.userObject.userId;
+ const user = await userService.getCurrentUser(userId);
res.status(200).json(user);
} catch (error) {
if (error.message === "User not found") {
@@ -36,36 +38,9 @@ module.exports.getCurrentUser = async function getCurrentUser(req, res, next) {
module.exports.getUserByUserID = async function getUserByUserID(req, res, next) {
try {
const userId = req.params.userId;
- const user = await userService.getUserByUserID(userId);
- res.status(200).json(user);
- } catch (error) {
- if (error.message === "User not found") {
- res.status(200).json(user);
- } else {
- res.status(500).json({ error: 'Internal Server Error', detail: error.message });
- }
- }
-};
-
-
-module.exports.getUserByUserName = async function getUserByUserName(req, res, next) {
- try {
- const userName = req.params.userName;
- const user = await userService.getUserByUserName(userName);
- res.status(200).json(user);
- } catch (error) {
- if (error.message === "User not found") {
- res.status(200).json(user);
- } else {
- res.status(500).json({ error: 'Internal Server Error', detail: error.message });
- }
- }
-};
-
-module.exports.getBasicUserByUserID = async function getBasicUserByUserID(req, res, next) {
- try {
- const userId = req.params.userId;
- const user = await userService.getBasicUserByUserID(userId);
+ const requestorId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ const user = await userService.getUserByUserID(requestorId, elevate, userId);
res.status(200).json(user);
} catch (error) {
if (error.message === "User not found") {
@@ -78,7 +53,9 @@ module.exports.getBasicUserByUserID = async function getBasicUserByUserID(req, r
module.exports.updateUser = async function updateUser(req, res, next) {
try {
- const updatedUser = await userService.updateUser(req, res, next);
+ const userId = req.userObject.userId;
+ const elevate = req.query.elevate;
+ const updatedUser = await userService.updateUser(userId, elevate, req);
res.status(200).json(updatedUser);
} catch (error) {
if (error.message === "User update failed") {
@@ -104,7 +81,8 @@ module.exports.updateUserTheme = async function updateUserTheme(req, res, next)
module.exports.updateUserPoints = async function updateUserPoints(req, res, next) {
try {
- const result = await userService.updateUserPoints(req, res, next);
+ const elevate = req.query.elevate;
+ const result = await userService.updateUserPoints(elevate, req);
if (result.success) {
res.status(200).json(result.message);
} else {
@@ -117,19 +95,12 @@ module.exports.updateUserPoints = async function updateUserPoints(req, res, next
module.exports.deleteUser = async function deleteUser(req, res, next) {
try {
+ const requestorId = req.userObject.userId;
+ const elevate = req.query.elevate;
const userId = req.params.userId;
- await userService.deleteUserByUserID(userId, req.userObject.username, req.userObject.displayName);
+ await userService.deleteUser(requestorId, elevate, userId);
res.status(200).json({ message: 'User deleted' });
} catch (error) {
res.status(500).json({ error: 'Internal Server Error', detail: error.message });
}
-};
-
-module.exports.loginState = async function loginState(req, res, next) {
- try {
- const message = await userService.loginState(req, res, next);
- res.status(201).json(message);
- } catch (error) {
- res.status(500).json({ error: 'Internal Server Error', detail: error.message });
- }
};
\ No newline at end of file
diff --git a/api/Models/poam.model.js b/api/Models/poam.model.js
index 1bfe84be..2fa4c1b0 100644
--- a/api/Models/poam.model.js
+++ b/api/Models/poam.model.js
@@ -67,14 +67,10 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.TEXT
},
status: {
- type: DataTypes.STRING(10),
+ type: DataTypes.STRING(50),
allowNull: false,
defaultValue: 'Draft'
},
- vulnIdRestricted: {
- type: DataTypes.STRING(255),
- defaultValue: ''
- },
submittedDate: {
type: DataTypes.DATEONLY,
defaultValue: '1900-01-01'
@@ -116,11 +112,11 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.STRING(15),
defaultValue: ''
},
- businessImpactRating: {
+ impactRating: {
type: DataTypes.STRING(15),
defaultValue: ''
},
- businessImpactDescription: {
+ impactDescription: {
type: DataTypes.TEXT
},
extensionTimeAllowed: {
diff --git a/api/Services/collectionService.js b/api/Services/collectionService.js
index 7f5c558e..5cb41957 100644
--- a/api/Services/collectionService.js
+++ b/api/Services/collectionService.js
@@ -13,6 +13,7 @@ const config = require('../utils/config')
const dbUtils = require('./utils')
const mysql = require('mysql2')
const logger = require('../utils/logger')
+const SmError = require('../utils/error')
async function withConnection(callback) {
const connection = await dbUtils.pool.getConnection();
@@ -23,77 +24,48 @@ async function withConnection(callback) {
}
}
-exports.getCollections = async function getCollections(userNameInput, req, res, next) {
- if (userNameInput == "Registrant") {
- try {
- return await withConnection(async (connection) => {
- let sql = "SELECT collectionId, collectionName FROM cpat.collection;"
- let [row] = await connection.query(sql)
- const size = Object.keys(row).length
-
- const user = {
- collections: []
- }
-
- for (let counter = 0; counter < size; counter++) {
- user.collections.push({
- "collectionId": row[counter].collectionId,
- "collectionName": row[counter].collectionName
- });
- }
-
- return user;
- });
- } catch (error) {
- return { error: error.message };
- }
- }
- let userId = 0
- let isAdmin = 0;
- let userName = "";
+exports.getCollections = async function getCollections(userId, elevate) {
try {
return await withConnection(async (connection) => {
- let sql = "SELECT * FROM user WHERE userName = ?";
- let [row] = await connection.query(sql, [userNameInput]);
- userId = row[0].userId;
- isAdmin = row[0].isAdmin;
-
- const user = {
- collections: []
- }
- if (isAdmin == 1) {
- let sql2 = "SELECT * FROM collection;"
- let [row2] = await connection.query(sql2)
- const size = Object.keys(row2).length
-
- for (let counter = 0; counter < size; counter++) {
- user.collections.push({
- ...row2[counter]
- });
+ if (elevate) {
+ let sql = "SELECT * FROM user WHERE userId = ?";
+ let [rows] = await connection.query(sql, [userId]);
+ if (rows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
}
-
- return user.collections;
- } else {
- let sql = "SELECT * FROM collectionpermissions WHERE userId = ?";
- let [row2] = await connection.query(sql, [userId])
- const numberOfCollections = Object.keys(row2).length
- const nonAdminCollections = {
+ let isAdmin = rows[0].isAdmin;
+ const user = {
collections: []
}
- for (let counter = 0; counter < numberOfCollections; counter++) {
- let sql3 = "SELECT * FROM collection WHERE collectionId = ?";
- let [row3] = await connection.query(sql3, [row2[counter].collectionId])
- nonAdminCollections.collections.push({
- "collectionId": row3[0].collectionId,
- "collectionName": row3[0].collectionName,
- "description": row3[0].description,
- "created": row3[0].created,
- "assetCount": row3[0].assetCount,
- "poamCount": row3[0].poamCount
- });
+ if (isAdmin == 1) {
+ let sql2 = "SELECT * FROM collection;"
+ let [row2] = await connection.query(sql2)
+ const size = Object.keys(row2).length
+ for (let counter = 0; counter < size; counter++) {
+ user.collections.push({
+ ...row2[counter]
+ });
+ }
+ return user.collections;
+ } else {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
}
-
- return nonAdminCollections.collections;
+ } else {
+ let collectionSql = `
+ SELECT c.*
+ FROM collection c
+ INNER JOIN collectionpermissions cp ON c.collectionId = cp.collectionId
+ WHERE cp.userId = ?;
+ `;
+ let [collections] = await connection.query(collectionSql, [userId]);
+ return collections.map(collection => ({
+ collectionId: collection.collectionId,
+ collectionName: collection.collectionName,
+ description: collection.description,
+ created: collection.created,
+ assetCount: collection.assetCount,
+ poamCount: collection.poamCount
+ }));
}
});
}
diff --git a/api/Services/importService.js b/api/Services/importService.js
index f932b36d..1d852700 100644
--- a/api/Services/importService.js
+++ b/api/Services/importService.js
@@ -50,8 +50,8 @@ const excelColumnToDbColumnMapping = {
"Relevance of Threat": "relevanceOfThreat",
"Threat Description": "threatDescription",
"Likelihood": "likelihood",
- "Impact": "businessImpactRating",
- "Impact Description": "businessImpactDescription",
+ "Impact": "impactRating",
+ "Impact Description": "impactDescription",
"Residual Risk Level": "residualRisk",
"Recommendations": "recommendations",
"Resulting Residual Risk after Proposed Mitigations": "adjSeverity"
@@ -60,13 +60,15 @@ const excelColumnToDbColumnMapping = {
function mapValueToCategory(cellValue, dbColumn) {
const severityMapping = {
rawSeverity: {
- 'I': "Cat I - Critical/High",
- 'II': "CAT II - Medium",
- 'III': "CAT III - Low"
+ 'Very High': "CAT I - Critical",
+ 'High': "CAT I - High",
+ 'Moderate': "CAT II - Medium",
+ 'Low': "CAT III - Low",
+ 'Very Low': "CAT III - Low"
},
adjSeverity: {
- 'Very High': "Cat I - Critical/High",
- 'High': "Cat I - Critical/High",
+ 'Very High': "CAT I - Critical",
+ 'High': "CAT I - High",
'Moderate': "CAT II - Medium",
'Low': "CAT III - Low",
'Very Low': "CAT III - Low"
@@ -277,25 +279,6 @@ function processVulnerabilitySource(poamEntry, cellValue) {
}
}
-function mapValueToCategory(cellValue, dbColumn) {
- const severityMapping = {
- rawSeverity: {
- 'I': "Cat I - Critical/High",
- 'II': "CAT II - Medium",
- 'III': "CAT III - Low"
- },
- adjSeverity: {
- 'Very High': "Cat I - Critical/High",
- 'High': "Cat I - Critical/High",
- 'Moderate': "CAT II - Medium",
- 'Low': "CAT III - Low",
- 'Very Low': "CAT III - Low"
- }
- };
-
- return severityMapping[dbColumn][cellValue] || cellValue;
-}
-
async function processPoamEntry(poamEntry, collectionId) {
let poam = await findOrCreatePoam(poamEntry);
await updatePoamMilestones(poam.poamId, poamEntry.milestones, poamEntry.milestoneChanges);
diff --git a/api/Services/marketplaceService.js b/api/Services/marketplaceService.js
index feac9b1e..14a534d7 100644
--- a/api/Services/marketplaceService.js
+++ b/api/Services/marketplaceService.js
@@ -22,6 +22,8 @@ async function withConnection(callback) {
}
}
+
+
exports.getAllThemes = async function getAllThemes() {
try {
return await withConnection(async (connection) => {
diff --git a/api/Services/metricsService.js b/api/Services/metricsService.js
index 41566872..15a36b78 100644
--- a/api/Services/metricsService.js
+++ b/api/Services/metricsService.js
@@ -23,7 +23,9 @@ async function withConnection(callback) {
}
}
-exports.getCollectionAssetLabel = async function getCollectionAssetLabel(req, res, next) {
+
+
+exports.getCollectionAssetLabel = async function getCollectionAssetLabel(collectionId) {
try {
return await withConnection(async (connection) => {
let sql = `
@@ -34,7 +36,7 @@ exports.getCollectionAssetLabel = async function getCollectionAssetLabel(req, re
WHERE p.collectionId = ?
GROUP BY l.labelName;
`;
- let [rows] = await connection.query(sql, [req.params.collectionId]);
+ let [rows] = await connection.query(sql, [collectionId]);
let assetLabel = rows.map(row => ({
label: row.labelName,
@@ -48,11 +50,11 @@ exports.getCollectionAssetLabel = async function getCollectionAssetLabel(req, re
}
}
-exports.getCollectionPoamStatus = async function getCollectionPoamStatus(req, res, next) {
+exports.getCollectionPoamStatus = async function getCollectionPoamStatus(collectionId) {
try {
return await withConnection(async (connection) => {
let sql = "SELECT status, COUNT(*) AS statusCount FROM poam WHERE collectionId = ? GROUP BY status;"
- let [rows] = await connection.query(sql, [req.params.collectionId])
+ let [rows] = await connection.query(sql, [collectionId])
const size = Object.keys(rows).length
@@ -72,7 +74,7 @@ exports.getCollectionPoamStatus = async function getCollectionPoamStatus(req, re
}
}
-exports.getCollectionPoamLabel = async function getCollectionPoamLabel(req, res, next) {
+exports.getCollectionPoamLabel = async function getCollectionPoamLabel(collectionId) {
try {
return await withConnection(async (connection) => {
let sql = `
@@ -83,7 +85,7 @@ exports.getCollectionPoamLabel = async function getCollectionPoamLabel(req, res,
WHERE p.collectionId = ?
GROUP BY l.labelName;
`;
- let [rows] = await connection.query(sql, [req.params.collectionId]);
+ let [rows] = await connection.query(sql, [collectionId]);
let poamLabel = rows.map(row => ({
label: row.labelName,
@@ -97,11 +99,11 @@ exports.getCollectionPoamLabel = async function getCollectionPoamLabel(req, res,
}
}
-exports.getCollectionPoamSeverity = async function getCollectionPoamSeverity(req, res, next) {
+exports.getCollectionPoamSeverity = async function getCollectionPoamSeverity(collectionId) {
try {
return await withConnection(async (connection) => {
let sql = "SELECT rawSeverity, COUNT(*) AS severityCount FROM poam WHERE collectionId = ? GROUP BY rawSeverity;"
- let [rows] = await connection.query(sql, [req.params.collectionId])
+ let [rows] = await connection.query(sql, [collectionId])
const size = Object.keys(rows).length
@@ -122,7 +124,7 @@ exports.getCollectionPoamSeverity = async function getCollectionPoamSeverity(req
}
}
-exports.getCollectionMonthlyPoamStatus = async function getCollectionMonthlyPoamStatus(req, res, next) {
+exports.getCollectionMonthlyPoamStatus = async function getCollectionMonthlyPoamStatus(collectionId) {
try {
return await withConnection(async (connection) => {
let sql = `
@@ -139,7 +141,7 @@ exports.getCollectionMonthlyPoamStatus = async function getCollectionMonthlyPoam
GROUP BY status;
`;
- let [rows] = await connection.query(sql, [req.params.collectionId]);
+ let [rows] = await connection.query(sql, [collectionId]);
const poamStatusMap = {};
@@ -167,7 +169,7 @@ exports.getCollectionMonthlyPoamStatus = async function getCollectionMonthlyPoam
}
};
-exports.getCollectionPoamScheduledCompletion = async function getCollectionPoamScheduledCompletion(req, res, next) {
+exports.getCollectionPoamScheduledCompletion = async function getCollectionPoamScheduledCompletion(collectionId) {
try {
return await withConnection(async (connection) => {
let sql = `
@@ -176,7 +178,7 @@ exports.getCollectionPoamScheduledCompletion = async function getCollectionPoamS
WHERE collectionId = ?
`;
- let [rows] = await connection.query(sql, [req.params.collectionId]);
+ let [rows] = await connection.query(sql, [collectionId]);
let buckets = {
"OVERDUE": 0,
@@ -211,11 +213,9 @@ exports.getCollectionPoamScheduledCompletion = async function getCollectionPoamS
}
}
-exports.getAvailableAssetLabel = async function getAvailableAssetLabel(req, res, next) {
+exports.getAvailableAssetLabel = async function getAvailableAssetLabel(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -261,11 +261,9 @@ exports.getAvailableAssetLabel = async function getAvailableAssetLabel(req, res,
}
}
-exports.getAvailablePoamStatus = async function getAvailablePoamStatus(req, res, next) {
+exports.getAvailablePoamStatus = async function getAvailablePoamStatus(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -306,11 +304,9 @@ exports.getAvailablePoamStatus = async function getAvailablePoamStatus(req, res,
}
}
-exports.getAvailableMonthlyPoamStatus = async function getAvailableMonthlyPoamStatus(req, res, next) {
+exports.getAvailableMonthlyPoamStatus = async function getAvailableMonthlyPoamStatus(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -375,11 +371,9 @@ exports.getAvailableMonthlyPoamStatus = async function getAvailableMonthlyPoamSt
}
};
-exports.getAvailablePoamLabel = async function getAvailablePoamLabel(req, res, next) {
+exports.getAvailablePoamLabel = async function getAvailablePoamLabel(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -425,11 +419,9 @@ exports.getAvailablePoamLabel = async function getAvailablePoamLabel(req, res, n
}
}
-exports.getAvailableCollectionPoamCounts = async function getAvailableCollectionPoamCounts(req, res, next) {
+exports.getAvailableCollectionPoamCounts = async function getAvailableCollectionPoamCounts(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -464,11 +456,9 @@ exports.getAvailableCollectionPoamCounts = async function getAvailableCollection
}
};
-exports.getAvailablePoamSeverity = async function getAvailablePoamSeverity(req, res, next) {
+exports.getAvailablePoamSeverity = async function getAvailablePoamSeverity(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -509,11 +499,9 @@ exports.getAvailablePoamSeverity = async function getAvailablePoamSeverity(req,
}
}
-exports.getAvailableMonthlyPoamSeverity = async function getAvailableMonthlyPoamSeverity(req, res, next) {
+exports.getAvailableMonthlyPoamSeverity = async function getAvailableMonthlyPoamSeverity(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -553,11 +541,9 @@ exports.getAvailableMonthlyPoamSeverity = async function getAvailableMonthlyPoam
}
};
-exports.getAvailablePoamScheduledCompletion = async function getAvailablePoamScheduledCompletion(req, res, next) {
+exports.getAvailablePoamScheduledCompletion = async function getAvailablePoamScheduledCompletion(userId) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
diff --git a/api/Services/migrations/sql/current/10-cpat-tables.sql b/api/Services/migrations/sql/current/10-cpat-tables.sql
index 3752db58..982c53d5 100644
--- a/api/Services/migrations/sql/current/10-cpat-tables.sql
+++ b/api/Services/migrations/sql/current/10-cpat-tables.sql
@@ -204,7 +204,7 @@ DROP TABLE IF EXISTS `poam`;
CREATE TABLE `poam` (
`poamId` int NOT NULL AUTO_INCREMENT,
`collectionId` int DEFAULT '0',
- `status` char(20) DEFAULT 'Draft',
+ `status` char(50) DEFAULT 'Draft',
`rawSeverity` varchar(25) DEFAULT '',
`adjSeverity` varchar(25) DEFAULT '',
`vulnerabilitySource` varchar(255) DEFAULT '',
@@ -223,7 +223,6 @@ CREATE TABLE `poam` (
`mitigations` text,
`requiredResources` text,
`residualRisk` varchar(25) DEFAULT NULL,
- `vulnIdRestricted` varchar(255) DEFAULT '',
`securityControlNumber` varchar(25) DEFAULT '',
`submitterId` int NOT NULL DEFAULT '0',
`officeOrg` varchar(100) DEFAULT '',
@@ -232,8 +231,8 @@ CREATE TABLE `poam` (
`relevanceOfThreat` varchar(15) DEFAULT '',
`threatDescription` varchar(255) DEFAULT '',
`likelihood` varchar(15) DEFAULT '',
- `businessImpactRating` varchar(15) DEFAULT '',
- `businessImpactDescription` varchar(2000) DEFAULT '',
+ `impactRating` varchar(15) DEFAULT '',
+ `impactDescription` varchar(2000) DEFAULT '',
`extensionTimeAllowed` int DEFAULT '0',
`extensionJustification` varchar(2000) DEFAULT '',
`emassStatus` varchar(15) DEFAULT 'Ongoing',
@@ -253,7 +252,7 @@ CREATE TABLE `poam` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poam_insert` AFTER INSERT ON `poam` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poam_insert` AFTER INSERT ON `poam` FOR EACH ROW BEGIN
UPDATE `collection`
SET `poamCount` = `poamCount` + 1
WHERE `collectionId` = NEW.`collectionId`;
@@ -266,7 +265,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `prevent_created_update` BEFORE UPDATE ON `poam` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `prevent_created_update` BEFORE UPDATE ON `poam` FOR EACH ROW BEGIN
IF NEW.created != OLD.created THEN
SET NEW.created = OLD.created;
END IF;
@@ -279,7 +278,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poam_update` AFTER UPDATE ON `poam` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poam_update` AFTER UPDATE ON `poam` FOR EACH ROW BEGIN
IF OLD.`collectionId` != NEW.`collectionId` THEN
UPDATE `collection` c
SET c.`poamCount` = c.`poamCount` - 1
@@ -298,22 +297,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poam_update_last_updated` AFTER UPDATE ON `poam` FOR EACH ROW BEGIN
- IF OLD.lastUpdated != NEW.lastUpdated THEN
- UPDATE poam
- SET lastUpdated = CURRENT_DATE
- WHERE poamId = NEW.poamId;
- END IF;
-END */;;
-DELIMITER ;
-/*!50003 SET sql_mode = @saved_sql_mode */ ;
-/*!50003 SET collation_connection = @saved_col_connection */ ;
-/*!50003 SET @saved_col_connection = @@collation_connection */ ;
-/*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ;
-/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
-/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
-DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poam_delete` AFTER DELETE ON `poam` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poam_delete` AFTER DELETE ON `poam` FOR EACH ROW BEGIN
UPDATE `collection`
SET `poamCount` = `poamCount` - 1
WHERE `collectionId` = OLD.`collectionId`;
@@ -340,7 +324,7 @@ CREATE TABLE `poamapprovers` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamapprovers_insert` AFTER INSERT ON `poamapprovers` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamapprovers_insert` AFTER INSERT ON `poamapprovers` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -353,7 +337,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamapprovers_update` AFTER UPDATE ON `poamapprovers` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamapprovers_update` AFTER UPDATE ON `poamapprovers` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -366,7 +350,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamapprovers_delete` AFTER DELETE ON `poamapprovers` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamapprovers_delete` AFTER DELETE ON `poamapprovers` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = OLD.poamId;
@@ -393,7 +377,7 @@ CREATE TABLE `poamassets` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamassets_insert` AFTER INSERT ON `poamassets` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamassets_insert` AFTER INSERT ON `poamassets` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -406,7 +390,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamassets_delete` AFTER DELETE ON `poamassets` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamassets_delete` AFTER DELETE ON `poamassets` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = OLD.poamId;
@@ -431,7 +415,7 @@ CREATE TABLE `poamassignees` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamassignees_insert` AFTER INSERT ON `poamassignees` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamassignees_insert` AFTER INSERT ON `poamassignees` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -444,7 +428,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamassignees_update` AFTER UPDATE ON `poamassignees` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamassignees_update` AFTER UPDATE ON `poamassignees` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -457,7 +441,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamassignees_delete` AFTER DELETE ON `poamassignees` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamassignees_delete` AFTER DELETE ON `poamassignees` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = OLD.poamId;
@@ -481,7 +465,7 @@ CREATE TABLE `poamlabels` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamlabels_insert` AFTER INSERT ON `poamlabels` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamlabels_insert` AFTER INSERT ON `poamlabels` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -494,7 +478,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamlabels_update` AFTER UPDATE ON `poamlabels` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamlabels_update` AFTER UPDATE ON `poamlabels` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -507,7 +491,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamlabels_delete` AFTER DELETE ON `poamlabels` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamlabels_delete` AFTER DELETE ON `poamlabels` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = OLD.poamId;
@@ -535,7 +519,7 @@ CREATE TABLE `poamlogs` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poamlogs_insert` AFTER INSERT ON `poamlogs` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poamlogs_insert` AFTER INSERT ON `poamlogs` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -566,7 +550,7 @@ CREATE TABLE `poammilestones` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poammilestones_insert` AFTER INSERT ON `poammilestones` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poammilestones_insert` AFTER INSERT ON `poammilestones` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -579,7 +563,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poammilestones_update` AFTER UPDATE ON `poammilestones` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poammilestones_update` AFTER UPDATE ON `poammilestones` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = NEW.poamId;
@@ -592,7 +576,7 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
-/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_poammilestones_delete` AFTER DELETE ON `poammilestones` FOR EACH ROW BEGIN
+/*!50003 CREATE*/ /*!50003 TRIGGER `after_poammilestones_delete` AFTER DELETE ON `poammilestones` FOR EACH ROW BEGIN
UPDATE poam
SET lastUpdated = CURRENT_DATE
WHERE poamId = OLD.poamId;
@@ -623,16 +607,16 @@ DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userId` int NOT NULL AUTO_INCREMENT,
`userName` varchar(20) NOT NULL,
- `email` varchar(100) NOT NULL,
- `firstName` varchar(50) NOT NULL,
- `lastName` varchar(50) NOT NULL,
+ `email` varchar(100) NOT NULL DEFAULT ' ',
+ `firstName` varchar(50) NOT NULL DEFAULT ' ',
+ `lastName` varchar(50) NOT NULL DEFAULT ' ',
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`lastAccess` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`lastCollectionAccessedId` int NOT NULL DEFAULT '0',
`accountStatus` varchar(25) NOT NULL DEFAULT 'PENDING',
`fullName` varchar(100) DEFAULT NULL,
`officeOrg` varchar(100) DEFAULT 'UNKNOWN',
- `defaultTheme` varchar(50) DEFAULT 'dark',
+ `defaultTheme` varchar(50) DEFAULT 'lara-dark-blue',
`isAdmin` int NOT NULL DEFAULT '0',
`lastClaims` json DEFAULT (_utf8mb4'{}'),
`points` int NOT NULL DEFAULT '0',
@@ -650,4 +634,4 @@ CREATE TABLE `user` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2024-08-19 12:21:32
+-- Dump completed on 2024-08-23 14:22:45
diff --git a/api/Services/migrations/sql/current/20-cpat-static.sql b/api/Services/migrations/sql/current/20-cpat-static.sql
index 20f9bfa8..c9333186 100644
--- a/api/Services/migrations/sql/current/20-cpat-static.sql
+++ b/api/Services/migrations/sql/current/20-cpat-static.sql
@@ -27,7 +27,7 @@ UNLOCK TABLES;
LOCK TABLES `themes` WRITE;
/*!40000 ALTER TABLE `themes` DISABLE KEYS */;
-INSERT INTO `themes` VALUES (1,'bootstrap4-dark-purple','Bootstrap Dark Purple','Welcome to the Eggplant Colored Extravaganza! This theme is so aubergine, you\'ll be dreaming of ratatouille while managing your POAMs.',150),(2,'bootstrap4-light-purple','Bootstrap Light Purple','Feeling royal? This lavender luxury will have you sipping imaginary Earl Grey tea while conquering your POAMs like a proper monarch.',50),(3,'bootstrap4-dark-blue','Bootstrap Dark Blue','Dive into the Deep Blue Data Sea! This theme is so oceanic, you might need scuba gear to navigate your tasks. Watch out for the occasional digital jellyfish - they sting with extra work!',150),(4,'bootstrap4-light-blue','Bootstrap Light Blue','Welcome to Cloud Nine Computing! This sky-blue theme is so light and airy, your POAMs might just float away. Don\'t forget to tie them down with a virtual paperweight!',50),(5,'soho-dark','Soho Dark','Step into the Soho Speakeasy of Productivity! This sleek, dark theme is so hip, your POAMs will start wearing tiny berets and discussing existential philosophy.',200),(6,'soho-light','Soho Light','Ah, Soho-light - where your POAMs dress in designer labels and sip overpriced lattes. It\'s so trendy, your tasks might start referring to themselves as \'bespoke action items.\' Just remember, even if a POAM asks for avocado toast, it\'s still work!',50),(7,'viva-dark','Viva Dark','Step into the Viva Las Vegas of Productivity! This dark, sleek theme is so alluring, your POAMs might start doing Elvis impersonations.',100),(8,'viva-light','Viva Light','Viva-light, where your POAMs party like it\'s 1999, but it\'s actually Monday morning. This theme is so bright and cheerful, your tasks might start wearing sunglasses indoors and calling everyone \'dude.\' ',50);
+INSERT INTO `themes` VALUES (1,'bootstrap4-dark-purple','Bootstrap Dark Purple','Welcome to the Eggplant Colored Extravaganza! This theme is so aubergine, you\'ll be dreaming of ratatouille while managing your POAMs.',150),(2,'bootstrap4-light-purple','Bootstrap Light Purple','Feeling royal? This lavender luxury will have you sipping imaginary Earl Grey tea while conquering your POAMs like a proper monarch.',50),(3,'bootstrap4-dark-blue','Bootstrap Dark Blue','Dive into the Deep Blue Data Sea! This theme is so oceanic, you might need scuba gear to navigate your tasks. Watch out for the occasional digital jellyfish - they sting with extra work!',150),(4,'bootstrap4-light-blue','Bootstrap Light Blue','Welcome to Cloud Nine Computing! This sky-blue theme is so light and airy, your POAMs might just float away. Don\'t forget to tie them down with a virtual paperweight!',50),(5,'soho-dark','Soho Dark','Step into the Soho Speakeasy of Productivity! This sleek, dark theme is so hip, your POAMs will start wearing tiny berets and discussing existential philosophy.',200),(6,'soho-light','Soho Light','Ah, Soho-light - where your POAMs dress in designer labels and sip overpriced lattes. It\'s so trendy, your tasks might start referring to themselves as \'bespoke action items.\' Just remember, even if a POAM asks for avocado toast, it\'s still work!',50),(7,'viva-dark','Viva Dark','Step into the Viva Las Vegas of Productivity! This dark, sleek theme is so alluring, your POAMs might start doing Elvis impersonations.',100),(8,'viva-light','Viva Light','Viva-light, where your POAMs party like it\'s 1999, but it\'s actually Monday morning. This theme is so bright and cheerful, your tasks might start wearing sunglasses indoors and calling everyone dude.',50);
/*!40000 ALTER TABLE `themes` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
@@ -38,4 +38,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2024-08-19 12:21:32
+-- Dump completed on 2024-08-23 14:22:45
diff --git a/api/Services/notificationService.js b/api/Services/notificationService.js
index 2a1e340c..4c673169 100644
--- a/api/Services/notificationService.js
+++ b/api/Services/notificationService.js
@@ -21,7 +21,10 @@ async function withConnection(callback) {
await connection.release();
}
}
-exports.getAllNotificationsByUserId = async function getAllNotificationsByUserId(userId) {
+
+
+
+exports.getAllNotifications = async function getAllNotifications(userId) {
try {
return await withConnection(async (connection) => {
const sql = `SELECT * FROM cpat.notification WHERE userId = ? ORDER BY timestamp DESC`;
@@ -33,7 +36,7 @@ exports.getAllNotificationsByUserId = async function getAllNotificationsByUserId
}
};
-exports.getUnreadNotificationsByUserId = async function getUnreadNotificationsByUserId(userId) {
+exports.getUnreadNotifications = async function getUnreadNotifications(userId) {
try {
return await withConnection(async (connection) => {
const sql = `SELECT * FROM cpat.notification WHERE notification.read = 0 AND userId = ? ORDER BY timestamp DESC`;
@@ -45,7 +48,7 @@ exports.getUnreadNotificationsByUserId = async function getUnreadNotificationsBy
}
};
-exports.getUnreadNotificationCountByUserId = async function getUnreadNotificationCountByUserId(userId) {
+exports.getUnreadNotificationCount = async function getUnreadNotificationCount(userId) {
try {
return await withConnection(async (connection) => {
const sql = `SELECT COUNT(userId) AS NotificationCount FROM cpat.notification WHERE notification.read = 0 AND userId = ?`;
@@ -58,7 +61,7 @@ exports.getUnreadNotificationCountByUserId = async function getUnreadNotificatio
}
};
-exports.dismissNotificationByNotificationId = async function dismissNotificationByNotificationId(notificationId, userId) {
+exports.dismissNotification = async function dismissNotification(userId, notificationId) {
try {
return await withConnection(async (connection) => {
const userIdQuery = `SELECT userId FROM cpat.notification WHERE notificationId = ?`;
@@ -77,7 +80,7 @@ exports.dismissNotificationByNotificationId = async function dismissNotification
}
};
-exports.dismissAllNotificationsByUserId = async function dismissAllNotificationsByUserId(userId) {
+exports.dismissAllNotifications = async function dismissAllNotifications(userId) {
try {
return await withConnection(async (connection) => {
const sql = `UPDATE cpat.notification SET notification.read = 1 WHERE userId = ?`;
@@ -89,11 +92,11 @@ exports.dismissAllNotificationsByUserId = async function dismissAllNotifications
}
};
-exports.deleteNotificationByNotificationId = async function deleteNotificationByNotificationId(notificationId) {
+exports.deleteNotification = async function deleteNotification(userId, notificationId) {
try {
return await withConnection(async (connection) => {
- const sql = `DELETE FROM cpat.notification WHERE notificationId = ?`;
- const [result] = await connection.query(sql, [notificationId]);
+ const sql = `DELETE FROM cpat.notification WHERE notificationId = ? AND userId = ?`;
+ const [result] = await connection.query(sql, [notificationId, userId]);
return result.affectedRows > 0;
});
} catch (error) {
@@ -101,7 +104,7 @@ exports.deleteNotificationByNotificationId = async function deleteNotificationBy
}
};
-exports.deleteAllNotificationsByUserId = async function deleteAllNotificationsByUserId(userId) {
+exports.deleteAllNotifications = async function deleteAllNotifications(userId) {
try {
return await withConnection(async (connection) => {
const sql = `DELETE FROM cpat.notification WHERE userId = ?`;
diff --git a/api/Services/permissionsService.js b/api/Services/permissionsService.js
index 033e6ce7..318739e4 100644
--- a/api/Services/permissionsService.js
+++ b/api/Services/permissionsService.js
@@ -22,51 +22,6 @@ async function withConnection(callback) {
}
}
-exports.getCollectionPermission = async function getCollectionPermission(userName, collectionId, req, res, next) {
- function collectionObj(collectionId, collectionName, description, created, poamCount) {
- this.collectionId = collectionId
- this.collectionName = collectionName
- this.description = description
- this.created = created
- this.poamCount = poamCount
- }
-
- try {
- let userInfo = await withConnection(async (connection) => {
- let sql = "SELECT * FROM user WHERE userName = ?";
- let [row] = await connection.query(sql, [userName]);
- let userId = row[0].userId;
- let isAdmin = row[0].isAdmin;
-
- try {
- let sql = "SELECT * FROM collectionpermissions WHERE userId = ? AND collectionId = ?";
- let [row] = await connection.query(sql, [userId, collectionId]);
- let userName = row[0].userName;
- return { userId, isAdmin, userName };
- } catch (error) {
- if (!isAdmin) {
- return { error: "User does not have access to this collection." };
- }
- return { userId, isAdmin };
- }
- });
-
- if (userInfo.error) {
- return { error: userInfo.error };
- }
-
- let collection = await withConnection(async (connection) => {
- let sql = "SELECT * FROM collection WHERE collectionId = ?";
- let [row] = await connection.query(sql, [collectionId]);
- return { ...row[0] };
- });
-
- return collection;
- } catch (error) {
- return { error: error.message };
- }
-}
-
exports.getCollectionPermissions = async function getCollectionPermissions(req, res, next) {
if (!req.params.collectionId) {
return next({
@@ -90,11 +45,13 @@ exports.getCollectionPermissions = async function getCollectionPermissions(req,
return permissions;
} catch (error) {
- return { error: error.message };
+ return {
+ error: error.message
+ };
}
}
-exports.postPermission = async function postPermission(req, res, next) {
+exports.postPermission = async function postPermission(userId, elevate, req) {
if (!req.body.userId) {
return next({
status: 400,
@@ -124,15 +81,33 @@ exports.postPermission = async function postPermission(req, res, next) {
try {
return await withConnection(async (connection) => {
- let sql_query = "INSERT INTO cpat.collectionpermissions (accessLevel, userId, collectionId) VALUES (?, ?, ?);";
- await connection.query(sql_query, [req.body.accessLevel, req.body.userId, req.body.collectionId]);
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [userId]);
- const message = {
- userId: req.body.userId,
- collectionId: req.body.collectionId,
- accessLevel: req.body.accessLevel,
- };
- return message;
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
+
+ const isAdmin = userRows[0].isAdmin;
+
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
+
+ let sql_query = "INSERT INTO cpat.collectionpermissions (accessLevel, userId, collectionId) VALUES (?, ?, ?);";
+ await connection.query(sql_query, [req.body.accessLevel, req.body.userId, req.body.collectionId]);
+
+ const message = {
+ userId: req.body.userId,
+ collectionId: req.body.collectionId,
+ accessLevel: req.body.accessLevel,
+ };
+ return message;
+
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
if (error.code === 'ER_DUP_ENTRY') {
@@ -141,14 +116,15 @@ exports.postPermission = async function postPermission(req, res, next) {
const [existingPermission] = await connection.query(fetchSql, [req.body.userId, req.body.collectionId]);
return existingPermission[0];
});
- }
- else {
- return { error: error.message };
+ } else {
+ return {
+ error: error.message
+ };
}
}
-}
+};
-exports.putPermission = async function putPermission(req, res, next) {
+exports.putPermission = async function putPermission(userId, elevate, req) {
if (!req.body.userId) {
return next({
status: 400,
@@ -178,22 +154,41 @@ exports.putPermission = async function putPermission(req, res, next) {
try {
return await withConnection(async (connection) => {
- let sql_query = "UPDATE cpat.collectionpermissions SET collectionId = ?, accessLevel = ? WHERE userId = ? AND collectionId = ?;";
- await connection.query(sql_query, [req.body.newCollectionId, req.body.accessLevel, req.body.userId, req.body.oldCollectionId]);
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [userId]);
- const message = {
- userId: req.body.userId,
- collectionId: req.body.newCollectionId,
- accessLevel: req.body.accessLevel,
- };
- return message;
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
+
+ const isAdmin = userRows[0].isAdmin;
+
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
+
+ let sql_query = "UPDATE cpat.collectionpermissions SET collectionId = ?, accessLevel = ? WHERE userId = ? AND collectionId = ?;";
+ await connection.query(sql_query, [req.body.newCollectionId, req.body.accessLevel, req.body.userId, req.body.oldCollectionId]);
+
+ const message = {
+ userId: req.body.userId,
+ collectionId: req.body.newCollectionId,
+ accessLevel: req.body.accessLevel,
+ };
+ return message;
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
- return { error: error.message };
+ return {
+ error: error.message
+ };
}
-}
+};
-exports.deletePermission = async function deletePermission(req, res, next) {
+exports.deletePermission = async function deletePermission(userId, elevate, req) {
if (!req.params.userId) {
return next({
status: 400,
@@ -214,12 +209,33 @@ exports.deletePermission = async function deletePermission(req, res, next) {
try {
return await withConnection(async (connection) => {
- let sql = "DELETE FROM cpat.collectionpermissions WHERE userId = ? AND collectionId = ?";
- await connection.query(sql, [req.params.userId, req.params.collectionId]);
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [userId]);
+
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
- return { permissions: [] };
+ const isAdmin = userRows[0].isAdmin;
+
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
+
+ let sql = "DELETE FROM cpat.collectionpermissions WHERE userId = ? AND collectionId = ?";
+ await connection.query(sql, [req.params.userId, req.params.collectionId]);
+
+ return {
+ permissions: []
+ };
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
- return { error: error.message };
+ return {
+ error: error.message
+ };
}
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/api/Services/poamApproverService.js b/api/Services/poamApproverService.js
index dc7cd8b6..6724ff97 100644
--- a/api/Services/poamApproverService.js
+++ b/api/Services/poamApproverService.js
@@ -14,6 +14,7 @@ const dbUtils = require('./utils');
const mysql = require('mysql2');
const usersService = require('./usersService');
const marketplaceService = require('./marketplaceService');
+
async function withConnection(callback) {
const connection = await dbUtils.pool.getConnection();
try {
@@ -84,76 +85,6 @@ exports.getPoamApproversByCollection = async function getPoamApproversByCollecti
}
}
-exports.getPoamApproversByCollectionUser = async function getPoamApproversByCollectionUser(req, res, next) {
- if (!req.params.collectionId) {
- return next({
- status: 400,
- errors: {
- collectionId: 'is required',
- }
- });
- }
- if (!req.params.userId) {
- return next({
- status: 400,
- errors: {
- userId: 'is required',
- }
- });
- }
-
- try {
- return await withConnection(async (connection) => {
- let sql = `
- SELECT T1.*, T2.firstName, T2.lastName, T2.fullName, T2.email
- FROM cpat.poamapprovers T1
- INNER JOIN cpat.user T2 ON T1.userId = T2.userId
- INNER JOIN cpat.poam T3 ON T1.poamId = T3.poamId
- WHERE T3.collectionId = ? AND T1.userId = ?
- `;
- let [rows] = await connection.query(sql, [req.params.collectionId, req.params.userId]);
- const poamApprovers = rows.map(row => ({
- ...row,
- approvedDate: row.approvedDate ? row.approvedDate.toISOString() : null,
- }));
- return poamApprovers;
- });
- } catch (error) {
- return { error: error.message };
- }
-}
-
-exports.getPoamApproversByUserId = async function getPoamApproversByUserId(req, res, next) {
- if (!req.params.userId) {
- return next({
- status: 400,
- errors: {
- userId: 'is required',
- }
- });
- }
-
- try {
- return await withConnection(async (connection) => {
- let sql = `
- SELECT T1.*, T2.firstName, T2.lastName, T2.fullName, T2.email
- FROM cpat.poamapprovers T1
- INNER JOIN cpat.user T2 ON T1.userId = T2.userId
- INNER JOIN cpat.poam T3 ON T1.poamId = T3.poamId
- WHERE T1.userId = ?
- `;
- let [rows] = await connection.query(sql, [req.params.userId]);
- const poamApprovers = rows.map(row => ({
- ...row,
- approvedDate: row.approvedDate ? row.approvedDate.toISOString() : null,
- }));
- return poamApprovers;
- });
- } catch (error) {
- return { error: error.message };
- }
-}
-
exports.postPoamApprover = async function postPoamApprover(req, res, next) {
if (!req.body.poamId) {
return next({
@@ -251,7 +182,7 @@ exports.putPoamApprover = async function putPoamApprover(req, res, next) {
(existingApproval[0].approvalStatus !== req.body.approvalStatus &&
(req.body.approvalStatus === 'Approved' || req.body.approvalStatus === 'Rejected'));
- if (isNewOrChangedApproval) {
+ if (isNewOrChangedApproval && !config.client.features.marketplaceDisabled) {
const approverPoints = await marketplaceService.getUserPoints(req.body.userId);
const newApproverPoints = approverPoints.points + 10;
await usersService.updateUserPoints({
@@ -295,45 +226,44 @@ exports.putPoamApprover = async function putPoamApprover(req, res, next) {
const hqs = poamResult[0].hqs;
if (req.body.approvalStatus === 'Approved') {
+ const userPoints = await marketplaceService.getUserPoints(submitterId);
if ((hqs === 0 || hqs === false || hqs === null) && req.body.hqs === true) {
- const userHqsPoints = await marketplaceService.getUserPoints(submitterId);
- const newHqsPoints = userHqsPoints.points + 15;
- await usersService.updateUserPoints({
- body: {
- userId: submitterId,
- points: newHqsPoints
- }
- });
-
- const hqsNotification = {
- title: `High Quality Submission`,
- message: `15 points have been added to your points balance for a High Quality submission on POAM ${req.body.poamId}.`,
- userId: submitterId
- };
- const hqsNotificationSql = `INSERT INTO cpat.notification (userId, title, message) VALUES (?, ?, ?)`;
- await connection.query(hqsNotificationSql, [submitterId, hqsNotification.title, hqsNotification.message]);
-
+ if (!config.client.features.marketplaceDisabled) {
+ const newHqsPoints = userPoints.points + 30;
+ await usersService.updateUserPoints({
+ body: {
+ userId: submitterId,
+ points: newHqsPoints
+ }
+ });
+ const hqsNotification = {
+ title: `High Quality Submission`,
+ message: `30 points have been added to your points balance for a High Quality submission on POAM ${req.body.poamId}.`,
+ userId: submitterId
+ };
+ const hqsNotificationSql = `INSERT INTO cpat.notification (userId, title, message) VALUES (?, ?, ?)`;
+ await connection.query(hqsNotificationSql, [submitterId, hqsNotification.title, hqsNotification.message]);
+ }
const hqsPoamSql = `UPDATE cpat.poam SET hqs = 1 WHERE poamId = ?`;
await connection.query(hqsPoamSql, [req.body.poamId]);
+ } else if (!config.client.features.marketplaceDisabled) {
+ const newPoints = userPoints.points + 15;
+ await usersService.updateUserPoints({
+ body: {
+ userId: submitterId,
+ points: newPoints
+ }
+ });
+
+ const pointsNotification = {
+ title: `POAM Approval Points`,
+ message: `15 points have been added to your points balance for approval of POAM ${req.body.poamId}.`,
+ userId: submitterId
+ };
+ const pointsNotificationSql = `INSERT INTO cpat.notification (userId, title, message) VALUES (?, ?, ?)`;
+ await connection.query(pointsNotificationSql, [submitterId, pointsNotification.title, pointsNotification.message]);
}
-
- const userPoints = await marketplaceService.getUserPoints(submitterId);
- const newPoints = userPoints.points + 15;
- await usersService.updateUserPoints({
- body: {
- userId: submitterId,
- points: newPoints
- }
- });
-
- const pointsNotification = {
- title: `POAM Approval Points`,
- message: `15 points have been added to your points balance for approval of POAM ${req.body.poamId}.`,
- userId: submitterId
- };
- const pointsNotificationSql = `INSERT INTO cpat.notification (userId, title, message) VALUES (?, ?, ?)`;
- await connection.query(pointsNotificationSql, [submitterId, pointsNotification.title, pointsNotification.message]);
-
+
let notificationMessage = `POAM ${req.body.poamId} has been approved by ${fullName}.`;
if (req.body.hqs === true) {
notificationMessage = `POAM ${req.body.poamId} has been approved and marked as High Quality by ${fullName}.`;
@@ -359,7 +289,7 @@ exports.putPoamApprover = async function putPoamApprover(req, res, next) {
const isApproverInPermissions = permissionResult.some(p => p.userId === req.body.poamLog[0].userId);
if (req.body.approvalStatus === 'Approved') {
- if (rawSeverity === "CAT I - Critical/High" && !isApproverInPermissions) {
+ if ((rawSeverity === "CAT I - Critical" || rawSeverity === "CAT I - High") && !isApproverInPermissions) {
for (const perm of permissionResult) {
const cat1Notification = {
title: 'CAT-I POAM Pending Approval',
diff --git a/api/Services/poamAssigneeService.js b/api/Services/poamAssigneeService.js
index 7fd35345..bff59d68 100644
--- a/api/Services/poamAssigneeService.js
+++ b/api/Services/poamAssigneeService.js
@@ -67,59 +67,6 @@ exports.getPoamAssigneesByPoamId = async function getPoamAssigneesByPoamId(poamI
});
};
-exports.getPoamAssigneesByUserId = async function getPoamAssigneesByUserId(req, res, next) {
- if (!req.params.userId) {
- throw new Error('getPoamAssigneesByUserId: userId is required');
- }
-
- return await withConnection(async (connection) => {
- let sql = `
- SELECT t1.userId, t2.fullName, t1.poamId, t3.status
- FROM cpat.poamassignees t1
- INNER JOIN cpat.user t2 ON t1.userId = t2.userId
- INNER JOIN cpat.poam t3 ON t1.poamId = t3.poamId
- WHERE t1.userId = ?
- ORDER BY t2.fullName
- `;
- let [rowPoamAssignees] = await connection.query(sql, [req.params.userId]);
- const poamAssignees = rowPoamAssignees.map(row => ({
- userId: row.userId,
- fullName: row.fullName,
- poamId: row.poamId,
- poamStatus: row.status,
- }));
- return { poamAssignees };
- });
-};
-
-exports.getPoamAssignee = async function getPoamAssignee(req, res, next) {
- if (!req.params.userId) {
- throw new Error('getPoamAssignee: userId is required');
- }
- if (!req.params.poamId) {
- throw new Error('getPoamAssignee: poamId is required');
- }
-
- return await withConnection(async (connection) => {
- let sql = `
- SELECT t1.userId, t2.fullName, t1.poamId, t3.status
- FROM cpat.poamassignees t1
- INNER JOIN cpat.user t2 ON t1.userId = t2.userId
- INNER JOIN cpat.poam t3 ON t1.poamId = t3.poamId
- WHERE t1.userId = ? AND t1.poamId = ?
- ORDER BY t2.fullName
- `;
- let [rowPoamAssignees] = await connection.query(sql, [req.params.userId, req.params.poamId]);
- const poamAssignees = rowPoamAssignees.map(row => ({
- userId: row.userId,
- fullName: row.fullName,
- poamId: row.poamId,
- poamStatus: row.status,
- }));
- const poamAssignee = poamAssignees.length > 0 ? [poamAssignees[0]] : [];
- return { poamAssignee };
- });
-};
exports.postPoamAssignee = async function postPoamAssignee(req, res, next) {
if (!req.body.userId) {
diff --git a/api/Services/poamExtensionService.js b/api/Services/poamExtensionService.js
index 14664bb1..8b20a513 100644
--- a/api/Services/poamExtensionService.js
+++ b/api/Services/poamExtensionService.js
@@ -36,24 +36,55 @@ exports.getPoamExtension = async function (poamId) {
exports.putPoamExtension = async function (extensionData) {
return withConnection(async (connection) => {
- let sql = "UPDATE cpat.poam SET extensionTimeAllowed = ?, extensionJustification = ? WHERE poamId = ?";
- await connection.query(sql, [extensionData.extensionTimeAllowed, extensionData.extensionJustification, extensionData.poamId]);
+ try {
+ let sql = `UPDATE cpat.poam SET
+ extensionTimeAllowed = ?,
+ extensionJustification = ?,
+ mitigations = ?,
+ requiredResources = ?,
+ residualRisk = ?,
+ likelihood = ?,
+ relevanceOfThreat = ?,
+ impactRating = ?,
+ impactDescription = ?,
+ status = ?
+ WHERE poamId = ?`;
- if (extensionData.poamLog && extensionData.poamLog.length > 0) {
- let scheduledCompletionDateQuery = `SELECT scheduledCompletionDate FROM cpat.poam WHERE poamId = ?`;
- let [[scheduledCompletionDateResult]] = await connection.query(scheduledCompletionDateQuery, [extensionData.poamId]);
- if (scheduledCompletionDateResult) {
- let scheduledCompletionDate = new Date(scheduledCompletionDateResult.scheduledCompletionDate);
- let deadlineWithExtension = addDays(scheduledCompletionDate, extensionData.extensionTimeAllowed);
+ const params = [
+ extensionData.extensionTimeAllowed,
+ extensionData.extensionJustification,
+ extensionData.mitigations,
+ extensionData.requiredResources,
+ extensionData.residualRisk,
+ extensionData.likelihood,
+ extensionData.relevanceOfThreat,
+ extensionData.impactRating,
+ extensionData.impactDescription,
+ extensionData.status,
+ extensionData.poamId
+ ];
- let formattedDeadline = deadlineWithExtension.toLocaleDateString("en-US");
-
- let action = `POAM Extended. Extension time requested: ${extensionData.extensionTimeAllowed} days
Extension Justification: ${extensionData.extensionJustification}
Deadline with Extension: ${formattedDeadline}`;
+ const [result] = await connection.query(sql, params);
+ if (extensionData.poamLog && extensionData.poamLog.length > 0) {
+ let action = `POAM Updated. Status: ${extensionData.status}`;
+ if (extensionData.extensionTimeAllowed > 0) {
+ let scheduledCompletionDateQuery = `SELECT scheduledCompletionDate FROM cpat.poam WHERE poamId = ?`;
+ let [[scheduledCompletionDateResult]] = await connection.query(scheduledCompletionDateQuery, [extensionData.poamId]);
+ if (scheduledCompletionDateResult) {
+ let scheduledCompletionDate = new Date(scheduledCompletionDateResult.scheduledCompletionDate);
+ let deadlineWithExtension = new Date(scheduledCompletionDate.getTime() + extensionData.extensionTimeAllowed * 24 * 60 * 60 * 1000);
+ let formattedDeadline = deadlineWithExtension.toLocaleDateString("en-US");
+ action += `
Extension time requested: ${extensionData.extensionTimeAllowed} days
Extension Justification: ${extensionData.extensionJustification}
Deadline with Extension: ${formattedDeadline}`;
+ }
+ }
let logSql = "INSERT INTO cpat.poamlogs (poamId, action, userId) VALUES (?, ?, ?)";
await connection.query(logSql, [extensionData.poamId, action, extensionData.poamLog[0].userId]);
}
+
+ return extensionData;
+ } catch (error) {
+ throw error;
}
- return extensionData;
});
};
diff --git a/api/Services/poamLabelService.js b/api/Services/poamLabelService.js
index 02441322..02722a43 100644
--- a/api/Services/poamLabelService.js
+++ b/api/Services/poamLabelService.js
@@ -22,6 +22,15 @@ async function withConnection(callback) {
}
}
+async function withConnection(callback) {
+ const connection = await dbUtils.pool.getConnection();
+ try {
+ return await callback(connection);
+ } finally {
+ await connection.release();
+ }
+}
+
exports.getPoamLabels = async function getPoamLabels(collectionId) {
try {
if (!collectionId) {
@@ -55,19 +64,8 @@ exports.getPoamLabels = async function getPoamLabels(collectionId) {
}
}
-exports.getAvailablePoamLabels = async function getAvailablePoamLabels(req, res, next) {
+exports.getAvailablePoamLabels = async function getAvailablePoamLabels(userId) {
try {
- const userId = req.params.userId;
-
- if (!req.params.userId) {
- return next({
- status: 400,
- errors: {
- userId: 'is required',
- }
- });
- }
-
return await withConnection(async (connection) => {
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
diff --git a/api/Services/poamService.js b/api/Services/poamService.js
index 15fde6ce..ab386680 100644
--- a/api/Services/poamService.js
+++ b/api/Services/poamService.js
@@ -25,17 +25,17 @@ async function withConnection(callback) {
}
}
+
+
function normalizeDate(date) {
if (!date) return null;
const d = new Date(date);
return d.toISOString().split('T')[0];
}
-exports.getAvailablePoams = async function getAvailablePoams(req, res, next) {
+exports.getAvailablePoams = async function getAvailablePoams(userId, req) {
try {
return await withConnection(async (connection) => {
- const userId = req.params.userId;
-
const [adminRows] = await connection.query("SELECT isAdmin FROM cpat.user WHERE userId = ?", [userId]);
const isAdmin = adminRows[0].isAdmin;
@@ -266,8 +266,8 @@ exports.postPoam = async function postPoam(req) {
let sql_query = `INSERT INTO cpat.poam (collectionId, vulnerabilitySource, stigTitle, stigBenchmarkId, stigCheckData, tenablePluginData,
iavmNumber, aaPackage, vulnerabilityId, description, rawSeverity, adjSeverity, iavComplyByDate, scheduledCompletionDate,
submitterId, officeOrg, predisposingConditions, mitigations, requiredResources, residualRisk, likelihood, relevanceOfThreat,
- businessImpactRating, businessImpactDescription, status, vulnIdRestricted, submittedDate, closedDate)
- values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
+ impactRating, impactDescription, status, submittedDate, closedDate)
+ values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
try {
return await withConnection(async (connection) => {
@@ -284,8 +284,8 @@ exports.postPoam = async function postPoam(req) {
await connection.query(sql_query, [req.body.collectionId, req.body.vulnerabilitySource, req.body.stigTitle, req.body.stigBenchmarkId, req.body.stigCheckData,
req.body.tenablePluginData, req.body.iavmNumber, req.body.aaPackage, req.body.vulnerabilityId, req.body.description, req.body.rawSeverity, req.body.adjSeverity,
req.body.iavComplyByDate, req.body.scheduledCompletionDate, req.body.submitterId, req.body.officeOrg, req.body.predisposingConditions, req.body.mitigations,
- req.body.requiredResources, req.body.residualRisk, req.body.likelihood, req.body.relevanceOfThreat, req.body.businessImpactRating, req.body.businessImpactDescription,
- req.body.status, req.body.vulnIdRestricted, req.body.submittedDate, req.body.closedDate]);
+ req.body.requiredResources, req.body.residualRisk, req.body.likelihood, req.body.relevanceOfThreat, req.body.impactRating, req.body.impactDescription,
+ req.body.status, req.body.submittedDate, req.body.closedDate]);
let sql = "SELECT * FROM cpat.poam WHERE poamId = LAST_INSERT_ID();";
let [rowPoam] = await connection.query(sql);
@@ -389,12 +389,11 @@ exports.putPoam = async function putPoam(req, res, next) {
"requiredResources": "Required Resources",
"residualRisk": "Residual Risk",
"status": "POAM Status",
- "vulnIdRestricted": "Vulnerability Restricted ID #",
"submittedDate": "Submitted Date",
"likelihood": "Likelihood",
"relevanceOfThreat": "Relevance of Threat",
- "businessImpactRating": "Business Impact",
- "businessImpactDescription": "Business Impact Description"
+ "impactRating": "Impact",
+ "impactDescription": "Impact Description"
};
try {
@@ -423,15 +422,15 @@ exports.putPoam = async function putPoam(req, res, next) {
const sqlInsertPoam = `UPDATE cpat.poam SET collectionId = ?, vulnerabilitySource = ?, stigTitle = ?, stigBenchmarkId = ?, stigCheckData = ?,
tenablePluginData = ?, iavmNumber = ?, aaPackage = ?, vulnerabilityId = ?, description = ?, rawSeverity = ?, adjSeverity = ?,
iavComplyByDate = ?, scheduledCompletionDate = ?, submitterId = ?, predisposingConditions = ?, mitigations = ?, requiredResources = ?,
- residualRisk = ?, likelihood = ?, relevanceOfThreat = ?, businessImpactRating = ?, businessImpactDescription = ?, status = ?,
- vulnIdRestricted = ?, submittedDate = ?, closedDate = ?, officeOrg = ? WHERE poamId = ?`;
+ residualRisk = ?, likelihood = ?, relevanceOfThreat = ?, impactRating = ?, impactDescription = ?, status = ?,
+ submittedDate = ?, closedDate = ?, officeOrg = ? WHERE poamId = ?`;
await connection.query(sqlInsertPoam, [
req.body.collectionId, req.body.vulnerabilitySource, req.body.stigTitle, req.body.stigBenchmarkId, req.body.stigCheckData,
req.body.tenablePluginData, req.body.iavmNumber, req.body.aaPackage, req.body.vulnerabilityId, req.body.description, req.body.rawSeverity,
req.body.adjSeverity, req.body.iavComplyByDate, req.body.scheduledCompletionDate, req.body.submitterId, req.body.predisposingConditions,
req.body.mitigations, req.body.requiredResources, req.body.residualRisk, req.body.likelihood, req.body.relevanceOfThreat,
- req.body.businessImpactRating, req.body.businessImpactDescription, req.body.status, req.body.vulnIdRestricted,
+ req.body.impactRating, req.body.impactDescription, req.body.status,
req.body.submittedDate, req.body.closedDate, req.body.officeOrg, req.body.poamId
]);
diff --git a/api/Services/usersService.js b/api/Services/usersService.js
index 82348cf7..8afe48dd 100644
--- a/api/Services/usersService.js
+++ b/api/Services/usersService.js
@@ -10,7 +10,7 @@
const dbUtils = require('./utils');
const logger = require('../utils/logger');
-const _this = this
+const SmError = require('../utils/error');
async function withConnection(callback) {
const connection = await dbUtils.pool.getConnection();
@@ -21,54 +21,71 @@ async function withConnection(callback) {
}
}
-exports.getUsers = async function getUsers() {
+exports.getUsers = async function getUsers(elevate, userId) {
try {
return await withConnection(async (connection) => {
- let sql = "SELECT * FROM cpat.user;";
- let [rows] = await connection.query(sql);
-
- const users = await Promise.all(rows.map(async (user) => {
- const sqlPermissions = "SELECT * FROM cpat.collectionpermissions WHERE userId = ?";
- const [permissionRows] = await connection.query(sqlPermissions, [user.userId]);
-
- const permissions = permissionRows.map(permission => ({
- userId: permission.userId,
- collectionId: permission.collectionId,
- accessLevel: permission.accessLevel,
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [userId]);
+
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
+
+ const isAdmin = userRows[0].isAdmin;
+
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
+
+ const allUsersSql = "SELECT * FROM cpat.user";
+ const [allUsersRows] = await connection.query(allUsersSql);
+
+ const users = await Promise.all(allUsersRows.map(async (user) => {
+ const permissionsSql = "SELECT * FROM cpat.collectionpermissions WHERE userId = ?";
+ const [permissionRows] = await connection.query(permissionsSql, [user.userId]);
+
+ const permissions = permissionRows.map(permission => ({
+ userId: permission.userId,
+ collectionId: permission.collectionId,
+ accessLevel: permission.accessLevel,
+ }));
+
+ return {
+ userId: user.userId,
+ userName: user.userName,
+ email: user.email,
+ firstName: user.firstName,
+ lastName: user.lastName,
+ created: user.created,
+ lastAccess: user.lastAccess,
+ lastCollectionAccessedId: user.lastCollectionAccessedId,
+ accountStatus: user.accountStatus,
+ fullName: user.fullName,
+ officeOrg: user.officeOrg,
+ defaultTheme: user.defaultTheme,
+ points: user.points,
+ isAdmin: user.isAdmin,
+ lastClaims: user.lastClaims,
+ permissions: permissions
+ };
}));
- return {
- userId: user.userId,
- userName: user.userName,
- email: user.email,
- firstName: user.firstName,
- lastName: user.lastName,
- created: user.created,
- lastAccess: user.lastAccess,
- lastCollectionAccessedId: user.lastCollectionAccessedId,
- accountStatus: user.accountStatus,
- fullName: user.fullName,
- officeOrg: user.officeOrg,
- defaultTheme: user.defaultTheme,
- points: user.points,
- isAdmin: user.isAdmin,
- lastClaims: user.lastClaims,
- permissions: permissions
- };
- }));
-
- return users;
+ return users;
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
return { error: error.message };
}
};
-exports.getCurrentUser = async function getCurrentUser(email) {
+exports.getCurrentUser = async function getCurrentUser(userId) {
try {
return await withConnection(async (connection) => {
- const sqlUser = "SELECT * FROM user WHERE email = ?";
- const [userRows] = await connection.query(sqlUser, [email]);
+ const sqlUser = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(sqlUser, [userId]);
if (userRows.length === 0) {
return userRows[0];
@@ -85,7 +102,7 @@ exports.getCurrentUser = async function getCurrentUser(email) {
accessLevel: permission.accessLevel,
}));
- return {
+ const userObject = {
userId: user.userId,
userName: user.userName,
email: user.email,
@@ -102,52 +119,70 @@ exports.getCurrentUser = async function getCurrentUser(email) {
isAdmin: user.isAdmin,
lastClaims: user.lastClaims,
permissions: permissions
- };
+ };
+ return userObject;
});
} catch (error) {
return { error: error.message };
}
};
-exports.getUserByUserID = async function getUserByUserID(userId) {
+exports.getUserByUserID = async function getUserByUserID(requestorId, elevate, userId) {
try {
return await withConnection(async (connection) => {
- let sql = "SELECT * FROM user WHERE userId = ?";
- const [userRows] = await connection.query(sql, [userId]);
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [requestorId]);
- if (userRows.length === 0) {
- return userRows[0];
- }
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
- const user = userRows[0];
+ const isAdmin = userRows[0].isAdmin;
- const sqlPermissions = "SELECT * FROM cpat.collectionpermissions WHERE userId = ?";
- const [permissionRows] = await connection.query(sqlPermissions, [user.userId]);
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
- const permissions = permissionRows.map(permission => ({
- userId: permission.userId,
- collectionId: permission.collectionId,
- accessLevel: permission.accessLevel,
- }));
+ let sql = "SELECT * FROM user WHERE userId = ?";
+ const [userQueryRows] = await connection.query(sql, [userId]);
- return {
- userId: user.userId,
- userName: user.userName,
- email: user.email,
- firstName: user.firstName,
- lastName: user.lastName,
- created: user.created,
- lastAccess: user.lastAccess,
- lastCollectionAccessedId: user.lastCollectionAccessedId,
- accountStatus: user.accountStatus,
- fullName: user.fullName,
- officeOrg: user.officeOrg,
- defaultTheme: user.defaultTheme,
- points: user.points,
- isAdmin: user.isAdmin,
- lastClaims: user.lastClaims,
- permissions: permissions
- };
+ if (userQueryRows.length === 0) {
+ return userQueryRows[0];
+ }
+
+ const user = userQueryRows[0];
+
+ const sqlPermissions = "SELECT * FROM cpat.collectionpermissions WHERE userId = ?";
+ const [permissionRows] = await connection.query(sqlPermissions, [user.userId]);
+
+ const permissions = permissionRows.map(permission => ({
+ userId: permission.userId,
+ collectionId: permission.collectionId,
+ accessLevel: permission.accessLevel,
+ }));
+
+ return {
+ userId: user.userId,
+ userName: user.userName,
+ email: user.email,
+ firstName: user.firstName,
+ lastName: user.lastName,
+ created: user.created,
+ lastAccess: user.lastAccess,
+ lastCollectionAccessedId: user.lastCollectionAccessedId,
+ accountStatus: user.accountStatus,
+ fullName: user.fullName,
+ officeOrg: user.officeOrg,
+ defaultTheme: user.defaultTheme,
+ points: user.points,
+ isAdmin: user.isAdmin,
+ lastClaims: user.lastClaims,
+ permissions: permissions
+ };
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
return { error: error.message };
@@ -200,36 +235,24 @@ exports.getUserByUserName = async function getUserByUserName(userName) {
}
};
-exports.getBasicUserByUserID = async function getBasicUserByUserID(userId) {
+exports.updateUser = async function updateUser(userId, elevate, req) {
try {
return await withConnection(async (connection) => {
- let sql = "SELECT * FROM user WHERE userId = ?";
- const [userRows] = await connection.query(sql, [userId]);
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [userId]);
- if (userRows.length === 0) {
- return userRows[0];
- }
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
- const user = userRows[0];
+ const isAdmin = userRows[0].isAdmin;
- return {
- userId: user.userId,
- email: user.email,
- firstName: user.firstName,
- lastName: user.lastName,
- fullName: user.fullName,
- officeOrg: user.officeOrg,
- };
- });
- } catch (error) {
- return { error: error.message };
- }
-};
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
-exports.updateUser = async function updateUser(req, res, next) {
- try {
- return await withConnection(async (connection) => {
- let sql = "UPDATE user SET firstName = ?, lastName = ?, email = ?, lastAccess = ?, lastCollectionAccessedId = ?, accountStatus = ?, fullName = ?, officeOrg = ?, defaultTheme = ?, isAdmin = ? WHERE userId = ?";
+ let sql = "UPDATE user SET firstName = ?, lastName = ?, email = ?, lastAccess = ?, lastCollectionAccessedId = ?, accountStatus = ?, fullName = ?, officeOrg = ?, defaultTheme = ?, isAdmin = ?, points = ? WHERE userId = ?";
await connection.query(sql, [
req.body.firstName,
@@ -242,6 +265,7 @@ exports.updateUser = async function updateUser(req, res, next) {
req.body.officeOrg,
req.body.defaultTheme,
req.body.isAdmin,
+ req.body.points,
req.body.userId
]);
@@ -249,6 +273,9 @@ exports.updateUser = async function updateUser(req, res, next) {
let [updatedUser] = await connection.query(sql, [req.body.userId]);
return updatedUser[0];
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
return { error: error.message };
@@ -272,7 +299,7 @@ exports.updateUserTheme = async function updateUserTheme(req, res, next) {
}
};
-exports.updateUserPoints = async function updateUserPoints(req, res, next) {
+exports.updateUserPoints = async function updateUserPoints(elevate, req) {
try {
return await withConnection(async (connection) => {
let sql = "UPDATE user SET points = ? WHERE userId = ?";
@@ -289,35 +316,50 @@ exports.updateUserPoints = async function updateUserPoints(req, res, next) {
}
};
-exports.setUserData = async function setUserData(userObject) {
+exports.setUserData = async function setUserData(userObject, fields, newUser) {
try {
return await withConnection(async (connection) => {
- let insertColumns = ['userName', 'email', 'firstName', 'lastName', 'fullName', 'lastClaims', 'isAdmin'];
- let updateColumns = ['userId = LAST_INSERT_ID(userId)', 'firstName = VALUES(firstName)', 'lastName = VALUES(lastName)', 'fullName = VALUES(fullName)', 'lastClaims = VALUES(lastClaims)', 'isAdmin = VALUES(isAdmin)'];
-
- let lastClaimsSerialized = JSON.stringify(userObject.lastClaims);
-
- let binds = [userObject.userName, userObject.email, userObject.firstName, userObject.lastName, userObject.fullName, lastClaimsSerialized, userObject.isAdmin];
-
- let sql = `
- INSERT INTO cpat.user (${insertColumns.join(', ')})
- VALUES (${insertColumns.map(() => '?').join(', ')})
- ON DUPLICATE KEY UPDATE ${updateColumns.join(', ')}
- `;
- const [result] = await connection.query(sql, binds);
- let userId = userObject.userId;
- if (!userId && result.insertId) {
- userId = result.insertId;
+ console.log("setUserData!@!@!@", userObject, fields, newUser);
+ let insertColumns = ['userName']
+ let updateColumns = ['userId = LAST_INSERT_ID(userId)']
+ let binds = [userObject.userName]
+
+ if (newUser && userObject.firstName) {
+ insertColumns.push('firstName')
+ updateColumns.push('firstName = VALUES(firstName)')
+ binds.push(userObject.firstName)
}
-
- sql = "SELECT * FROM user WHERE userId = ?";
- let [updatedUser] = await connection.query(sql, [userId]);
-
- if (updatedUser[0]) {
- updatedUser[0].lastClaims = JSON.parse(updatedUser[0].lastClaims);
+ if (newUser && userObject.lastName) {
+ insertColumns.push('lastName')
+ updateColumns.push('lastName = VALUES(lastName)')
+ binds.push(userObject.lastName)
}
-
- return updatedUser[0];
+ if (newUser && userObject.fullName) {
+ insertColumns.push('fullName')
+ updateColumns.push('fullName = VALUES(fullName)')
+ binds.push(userObject.fullName)
+ }
+ if (newUser && userObject.email) {
+ insertColumns.push('email')
+ updateColumns.push('email = VALUES(email)')
+ binds.push(userObject.email)
+ }
+ if (fields.lastAccess) {
+ insertColumns.push('lastAccess')
+ updateColumns.push('lastAccess = VALUES(lastAccess)')
+ binds.push(fields.lastAccess)
+ }
+ if (fields.lastClaims) {
+ insertColumns.push('lastClaims')
+ updateColumns.push('lastClaims = VALUES(lastClaims)')
+ binds.push(JSON.stringify(fields.lastClaims))
+ }
+ let sqlUpsert = `INSERT INTO cpat.user (
+ ${insertColumns.join(',\n')}
+ ) VALUES ? ON DUPLICATE KEY UPDATE
+ ${updateColumns.join(',\n')}`
+ let [result] = await connection.query(sqlUpsert, [[binds]])
+ return result;
});
} catch (error) {
return { error: error.message };
@@ -337,9 +379,23 @@ exports.setLastAccess = async function (userId, timestamp) {
}
};
-exports.deleteUserByUserID = async function deleteUserByUserID(userId, username, displayName) {
+exports.deleteUser = async function deleteUser(requestorId, elevate, userId) {
try {
return await withConnection(async (connection) => {
+ if (elevate) {
+ const userSql = "SELECT * FROM user WHERE userId = ?";
+ const [userRows] = await connection.query(userSql, [requestorId]);
+
+ if (userRows.length === 0) {
+ throw new SmError.PrivilegeError('User not found');
+ }
+
+ const isAdmin = userRows[0].isAdmin;
+
+ if (isAdmin !== 1) {
+ throw new SmError.PrivilegeError('User requesting Elevate without admin permissions.');
+ }
+
let sql = 'DELETE FROM `user` WHERE `userId`= ?';
await connection.query(sql, [userId]);
@@ -347,34 +403,11 @@ exports.deleteUserByUserID = async function deleteUserByUserID(userId, username,
logger.writeInfo("usersService", 'notification', { event: 'removed account', userId: userId });
return { message: "User deleted" };
+ } else {
+ throw new Error('Elevate parameter is required');
+ }
});
} catch (error) {
return { error: error.message };
}
-};
-
-exports.loginState = async function loginState(req, res, next) {
- let message = { message: "" };
- if (req.body.loginState == 'logIn') {
- logger.writeInfo("usersService", 'info', { event: 'Logged In' });
- message.message = "Login Success";
- } else {
- logger.writeInfo("usersService", 'info', { event: 'Logged Out' });
- message.message = "Logout Success";
- }
- return message;
-};
-
-module.exports.deleteUserByUserID = async function deleteUserByUserID(userId, req, res, next) {
- return await withConnection(async (connection) => {
- let sql_query = 'DELETE FROM `user` WHERE `id`=' + userId;
- await connection.query(sql_query);
-
- logger.writeInfo("usersService", 'log', { event: 'removed account', userId: userId });
- logger.writeInfo("usersService", 'notification', { event: 'removed account', userId: userId });
-
- let messageReturned = new Object();
- messageReturned.text = "User deleted";
- return messageReturned;
- });
};
\ No newline at end of file
diff --git a/api/package-lock.json b/api/package-lock.json
index aeb547a4..c060cc97 100644
--- a/api/package-lock.json
+++ b/api/package-lock.json
@@ -25,7 +25,7 @@
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1",
"mysql2": "^3.11.0",
- "npm-check-updates": "^17.0.6",
+ "npm-check-updates": "^17.1.0",
"on-finished": "^2.4.1",
"on-headers": "^1.0.2",
"passport": "^0.7.0",
@@ -5268,9 +5268,9 @@
}
},
"node_modules/npm-check-updates": {
- "version": "17.0.6",
- "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.0.6.tgz",
- "integrity": "sha512-KCiaJH1cfnh/RyzKiDNjNfXgcKFyQs550Uf1OF/Yzb8xO56w+RLpP/OKRUx23/GyP/mLYwEpOO65qjmVdh6j0A==",
+ "version": "17.1.0",
+ "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.0.tgz",
+ "integrity": "sha512-RcohCA/tdpxyPllBlYDkqGXFJQgTuEt0f2oPSL9s05pZ3hxYdleaUtvEcSxKl0XAg3ncBhVgLAxhXSjoryUU5Q==",
"license": "Apache-2.0",
"bin": {
"ncu": "build/cli.js",
@@ -7005,4 +7005,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/api/package.json b/api/package.json
index f5338041..4aac906c 100644
--- a/api/package.json
+++ b/api/package.json
@@ -25,7 +25,7 @@
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1",
"mysql2": "^3.11.0",
- "npm-check-updates": "^17.0.6",
+ "npm-check-updates": "^17.1.0",
"on-finished": "^2.4.1",
"on-headers": "^1.0.2",
"passport": "^0.7.0",
diff --git a/api/specification/C-PAT.yaml b/api/specification/C-PAT.yaml
index dc6488f3..cb59d8ba 100644
--- a/api/specification/C-PAT.yaml
+++ b/api/specification/C-PAT.yaml
@@ -652,14 +652,14 @@ paths:
schema:
$ref: '#/components/schemas/error'
- '/collections/{userName}':
+ '/collections':
get:
tags:
- Collection
summary: Get a list of collections accessible to the user
operationId: getCollections
parameters:
- - $ref: '#/components/parameters/collectionAuth'
+ - $ref: '#/components/parameters/ElevateQuery'
responses:
'200':
description: Collection list retrieved successfully
@@ -675,6 +675,9 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/error'
+ security:
+ - oauth:
+ - 'c-pat:read'
/collection:
post:
@@ -738,6 +741,206 @@ paths:
tags:
- Collection
+ /iav/vramUpdatedDate:
+ get:
+ summary: Get VRAM data updated date
+ description: Retrieves the last updated date of the VRAM data
+ operationId: getVramDataUpdatedDate
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ value:
+ type: string
+ '400':
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ tags:
+ - IAV
+ security:
+ - oauth:
+ - 'c-pat:op'
+
+ /iav/iavSummary:
+ get:
+ summary: Get IAV Summary
+ description: Retrieves IAV table data
+ operationId: getIAVTableData
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IAVTableData'
+ '400':
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ tags:
+ - IAV
+ security:
+ - oauth:
+ - 'c-pat:read'
+
+ /iav/pluginInfo:
+ get:
+ summary: Get IAV and Navy Comply Date for Plugin IDs
+ description: Retrieves IAV and Navy Comply Date information for given Plugin IDs
+ operationId: getIAVInfoForPlugins
+ parameters:
+ - in: query
+ name: pluginIDs
+ required: true
+ schema:
+ type: string
+ description: Comma-separated list of Plugin IDs
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ pluginID:
+ type: integer
+ iav:
+ type: string
+ navyComplyDate:
+ type: string
+ format: date
+ '400':
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ tags:
+ - IAV
+ security:
+ - oauth:
+ - 'c-pat:read'
+
+ /iav/pluginIDs:
+ get:
+ summary: Retrieves mapped IAV pluginIDs
+ description: Get all unique pluginIDs that have an associated IAV as a comma-separated string
+ operationId: getIAVPluginIds
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ pluginIDs:
+ type: string
+ description: Comma-separated list of unique plugin IDs
+ '400':
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ tags:
+ - IAV
+ security:
+ - oauth:
+ - 'c-pat:read'
+
+ /mapPluginIds:
+ post:
+ summary: Maps Plugin IDs to IAVs
+ description: Maps Plugin IDs to IAVs
+ operationId: mapIAVPluginIds
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ iav:
+ type: string
+ pattern: '^\d{4}-[A-Z]-\d{4}$'
+ description: IAV in the format 0000-A-0000
+ pluginID:
+ type: string
+ description: Comma-separated list of plugin IDs
+ required:
+ - iav
+ - pluginID
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ updatedCount:
+ type: integer
+ '400':
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ tags:
+ - IAV
+ security:
+ - oauth:
+ - 'c-pat:op'
+
'/import/poams':
post:
summary: Parse and import .xls, .xlsx, or .xlsm eMASS POAM exports
@@ -1066,17 +1269,10 @@ paths:
- oauth:
- 'c-pat:read'
- /marketplace/user-themes/{userId}:
+ /marketplace/user-themes:
get:
- summary: Get all purchased themes for a user
+ summary: Get all purchased themes
operationId: getUserThemes
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
- description: The ID of the user
responses:
'200':
description: Successfully retrieved purchased themes
@@ -1096,17 +1292,10 @@ paths:
- oauth:
- 'c-pat:read'
- /marketplace/user-points/{userId}:
+ /marketplace/user-points:
get:
- summary: Get the available points of a user
+ summary: Get available points balance
operationId: getUserPoints
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
- description: The ID of the user
responses:
'200':
description: Successfully retrieved purchased themes
@@ -1288,9 +1477,7 @@ paths:
- oauth:
- 'c-pat:read'
- '/metrics/available/{userId}/assetlabel':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/assetlabel':
get:
summary: Get all asset labels and label counts available to the user
operationId: getAvailableAssetLabel
@@ -1315,9 +1502,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/poamlabel':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/poamlabel':
get:
summary: Get all POAM labels and label counts available to the user
operationId: getAvailablePoamLabel
@@ -1342,9 +1527,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/poamstatus':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/poamstatus':
get:
summary: Get all POAM status and status counts available to the user
operationId: getAvailablePoamStatus
@@ -1369,9 +1552,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/poamseverity':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/poamseverity':
get:
summary: Get all POAM severity and severity counts available to the user
operationId: getAvailablePoamSeverity
@@ -1396,9 +1577,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/monthlypoamseverity':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/monthlypoamseverity':
get:
summary: Get all POAM severity and severity counts from within the last 30 days available to the user
operationId: getAvailableMonthlyPoamSeverity
@@ -1423,9 +1602,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/monthlypoamstatus':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/monthlypoamstatus':
get:
summary: Get a status of all POAMs available to the user with status and status counts grouped under Open or Closed from POAMs submitted within the last 30 days
operationId: getAvailableMonthlyPoamStatus
@@ -1450,9 +1627,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/poamScheduledCompletion':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/poamScheduledCompletion':
get:
summary: Get all POAM scheduled completion and scheduled completion counts available to the user
operationId: getAvailablePoamScheduledCompletion
@@ -1477,9 +1652,7 @@ paths:
- oauth:
- 'c-pat:op'
- '/metrics/available/{userId}/collectionpoamcount':
- parameters:
- - $ref: '#/components/parameters/userIdPath'
+ '/metrics/available/collectionpoamcount':
get:
summary: Get a count of poams for each collection available to the user
operationId: getAvailableCollectionPoamCounts
@@ -1504,16 +1677,10 @@ paths:
- oauth:
- 'c-pat:op'
- /notifications/all/{userId}:
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
+ /notifications/all:
get:
summary: Get all notifications for a user
- operationId: getAllNotificationsByUserId
+ operationId: getAllNotifications
responses:
'200':
description: Notification array response
@@ -1535,16 +1702,10 @@ paths:
- oauth:
- 'c-pat:read'
- /notifications/unread/{userId}:
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
+ /notifications/unread:
get:
- summary: Get all unread notifications for a user
- operationId: getUnreadNotificationsByUserId
+ summary: Get all unread notifications
+ operationId: getUnreadNotifications
responses:
'200':
description: Notification array response
@@ -1566,16 +1727,10 @@ paths:
- oauth:
- 'c-pat:read'
- /notifications/unread/count/{userId}:
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
+ /notifications/unread/count:
get:
- summary: Get a count of all unread notifications for a user
- operationId: getUnreadNotificationCountByUserId
+ summary: Get a count of all unread notifications
+ operationId: getUnreadNotificationCount
responses:
'200':
description: Notification count response
@@ -1604,7 +1759,7 @@ paths:
type: integer
delete:
summary: Delete a notification
- operationId: deleteNotificationByNotificationId
+ operationId: deleteNotification
responses:
'204':
description: Notification dismissed successfully
@@ -1626,16 +1781,10 @@ paths:
- oauth:
- 'c-pat:read'
- /notifications/all/delete/{userId}:
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
+ /notifications/all/delete:
delete:
- summary: Delete a notification
- operationId: deleteAllNotificationsByUserId
+ summary: Deletes all notifications
+ operationId: deleteAllNotifications
responses:
'204':
description: Notification dismissed successfully
@@ -1665,8 +1814,8 @@ paths:
schema:
type: integer
put:
- summary: Dismiss a notification
- operationId: dismissNotificationByNotificationId
+ summary: Dismiss an individual notification
+ operationId: dismissNotification
responses:
'200':
description: Notification array response
@@ -1694,16 +1843,10 @@ paths:
- oauth:
- 'c-pat:read'
- /notifications/all/dismiss/{userId}:
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
+ /notifications/all/dismiss:
put:
- summary: Dismiss all notifications for a user
- operationId: dismissAllNotificationsByUserId
+ summary: Dismiss all notifications
+ operationId: dismissAllNotifications
responses:
'204':
description: Notification dismissed successfully
@@ -1725,36 +1868,76 @@ paths:
- oauth:
- 'c-pat:read'
- '/collection/{collectionId}/user/{userName}':
- parameters:
- - $ref: '#/components/parameters/collectionIdPath'
- - in: path
- name: userName
- required: true
- schema:
- type: string
+ /op/configuration:
get:
+ summary: Return API version and classification
+ operationId: getConfiguration
+ responses:
+ '200':
+ description: Configuration response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiConfiguration'
tags:
- - Permissions
- summary: Return collection permissions for a user
- operationId: getCollectionPermission
+ - Operation
+ security: []
+ post:
+ summary: Set a configuration item
+ operationId: setConfigurationItem
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ConfigurationItem'
responses:
'200':
- description: Collection retrieved successfully
+ description: Configuration item updated successfully
content:
application/json:
schema:
- $ref: '#/components/schemas/collection'
- '204':
- description: No Content
- '500':
- description: Internal server error
+ $ref: '#/components/schemas/SuccessMessage'
+ '400':
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
+ tags:
+ - Operation
+ security:
+ - oauth:
+ - 'c-pat:op'
+ delete:
+ summary: Delete a configuration item
+ operationId: deleteConfigurationItem
+ parameters:
+ - name: key
+ in: query
+ required: true
+ schema:
+ $ref: '#/components/schemas/String255'
+ responses:
+ '200':
+ description: Configuration item deleted successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SuccessMessage'
+ '400':
+ description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/error'
+ tags:
+ - Operation
+ security:
+ - oauth:
+ - 'c-pat:op'
- '/collection/permissions/{collectionId}':
+ '/permissions/{collectionId}':
parameters:
- in: path
name: collectionId
@@ -1762,7 +1945,7 @@ paths:
schema:
type: integer
get:
- summary: Get all permissions for a specific collection
+ summary: Get the permission assignments of a collection by collectionId
operationId: getCollectionPermissions
responses:
'200':
@@ -1790,6 +1973,7 @@ paths:
'/permission/{userId}/{collectionId}':
parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
- in: path
name: userId
required: true
@@ -1828,6 +2012,8 @@ paths:
post:
summary: Add a user collection permission
operationId: postPermission
+ parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
requestBody:
required: true
content:
@@ -1862,6 +2048,8 @@ paths:
put:
summary: Update user collection permissions
operationId: putPermission
+ parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
requestBody:
required: true
content:
@@ -1930,43 +2118,6 @@ paths:
- oauth:
- 'c-pat:read'
- '/poamApprovers/user/{userId}':
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
- get:
- summary: Return poamApprovers by userId
- operationId: getPoamApproversByUserId
- responses:
- '200':
- description: Poam Approvers array response
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/poamApprover_Response'
- '400':
- description: Bad request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- default:
- description: Unexpected error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - PoamApprover
- security:
- - oauth:
- - 'c-pat:op'
-
'/poamApprovers/collection/{collectionId}':
parameters:
- in: path
@@ -2004,48 +2155,6 @@ paths:
- oauth:
- 'c-pat:op'
- '/poamApprovers/collection/{collectionId}/user/{userId}':
- parameters:
- - in: path
- name: collectionId
- required: true
- schema:
- type: integer
- - in: path
- name: userId
- required: true
- schema:
- type: integer
- get:
- summary: Return poamApprovers by collectionId and userId
- operationId: getPoamApproversByCollectionUser
- responses:
- '200':
- description: Poam Approvers array response
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/poamApprover_Response'
- '400':
- description: Bad request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- default:
- description: Unexpected error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - PoamApprover
- security:
- - oauth:
- - 'c-pat:op'
-
'/poamApprover/poam/{poamId}/user/{userId}':
parameters:
- in: path
@@ -2402,78 +2511,7 @@ paths:
- oauth:
- 'c-pat:read'
- /poamAssignees/user/{userId}:
- get:
- summary: Get POAM assignees by user ID
- operationId: getPoamAssigneesByUserId
- parameters:
- - name: userId
- in: path
- required: true
- schema:
- type: integer
- responses:
- '200':
- description: Successful response with POAM assignees
- content:
- application/json:
- schema:
- type: object
- properties:
- poamAssignees:
- type: array
- items:
- $ref: '#/components/schemas/poamAssignee_Object'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - PoamAssignees
- security:
- - oauth:
- - 'c-pat:read'
-
/poamAssignee/poam/{poamId}/user/{userId}:
- get:
- summary: Get a specific POAM assignee by POAM ID and user ID
- operationId: getPoamAssignee
- parameters:
- - name: poamId
- in: path
- required: true
- schema:
- type: integer
- - name: userId
- in: path
- required: true
- schema:
- type: integer
- responses:
- '200':
- description: Successful response with the POAM assignee
- content:
- application/json:
- schema:
- type: object
- properties:
- poamAssignee:
- type: array
- items:
- $ref: '#/components/schemas/poamAssignee_Object'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - PoamAssignees
- security:
- - oauth:
- - 'c-pat:read'
delete:
summary: Delete a POAM assignee
operationId: deletePoamAssignee
@@ -2705,16 +2743,10 @@ paths:
- oauth:
- 'c-pat:read'
- /poamLabels/available/{userId}:
+ /poamLabels:
get:
- summary: Return all poams with labels available to a user
+ summary: Return all poams containing labels that are available to the user
operationId: getAvailablePoamLabels
- parameters:
- - in: path
- name: userId
- schema:
- type: integer
- required: true
responses:
'200':
description: Poam array response
@@ -3112,13 +3144,7 @@ paths:
- oauth:
- 'c-pat:read'
- /poams/{userId}:
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
+ /poams:
get:
summary: Return all POAMs available to a user
operationId: getAvailablePoams
@@ -3512,8 +3538,10 @@ paths:
security:
- oauth:
- 'c-pat:read'
- summary: Update certain properties of a User
+ summary: Update properties of a User
operationId: updateUser
+ parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
requestBody:
required: true
content:
@@ -3556,377 +3584,46 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/SuccessResponse'
- '400':
- description: Bad request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:read'
-
- /user/updatePoints:
- put:
- summary: Updates a users points
- operationId: updateUserPoints
- requestBody:
- required: true
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/UpdatePointsRequest'
- responses:
- '200':
- description: Successfully updated the users points
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/SuccessResponse'
- '400':
- description: Bad request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:read'
-
- '/users':
- get:
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:op'
- summary: Return all users for admin processing (assigning collections and permissions)
- operationId: getUsers
- responses:
- '200':
- description: User response
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/current_user_Response'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
-
- '/user/{userId}':
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
- get:
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:op'
- summary: Return a User
- operationId: getUserByUserID
- responses:
- '200':
- description: User response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/user'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- delete:
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:op'
- summary: Delete a User
- operationId: deleteUser
- responses:
- '200':
- description: User response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/user'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
-
- '/user/name/{userName}':
- parameters:
- - in: path
- name: userName
- required: true
- schema:
- type: string
- get:
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:op'
- summary: Return a User by userName
- operationId: getUserByUserName
- responses:
- '200':
- description: User response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/user'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
-
- '/user/basic/{userId}':
- parameters:
- - in: path
- name: userId
- required: true
- schema:
- type: integer
- get:
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:read'
- summary: Return basic user information by userId
- operationId: getBasicUserByUserID
- responses:
- '200':
- description: Basic user response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/basic_user'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
-
- '/user/loginState':
- put:
- tags:
- - User
- security:
- - oauth:
- - 'c-pat:read'
- summary: Writes stdout log to indicate login or logout
- operationId: loginState
- requestBody:
- required: true
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/user_loginState'
- responses:
- '201':
- description: Login/Logout response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/user_Login_Response'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
-
- '/vulnerability/poam/{vulnerabilityId}':
- parameters:
- - in: path
- name: vulnerabilityId
- required: true
- schema:
- type: string
- get:
- summary: Return POAMs by vulnerabilityId
- operationId: getPoamsByVulnerabilityId
- responses:
- '200':
- description: POAM array response
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/poam_Object'
- '403':
- $ref: '#/components/responses/forbidden'
- '400':
- description: Bad Request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - Vulnerability
- security:
- - oauth:
- - 'c-pat:read'
-
- '/vulnerability/existingPoams':
- get:
- summary: Return a list of vulnerabilities associated with existing POAMs
- operationId: getExistingVulnerabilityPoams
- responses:
- '200':
- description: Successful response with existing vulnerability POAMs
- content:
- application/json:
- schema:
- type: array
- items:
- type: object
- properties:
- poamId:
- type: integer
- vulnerabilityId:
- type: string
- '500':
- description: Internal server error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - Vulnerability
- security:
- - oauth:
- - 'c-pat:read'
-
- /op/configuration:
- get:
- summary: Return API version and classification
- operationId: getConfiguration
- responses:
- '200':
- description: Configuration response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiConfiguration'
- tags:
- - Operation
- security: []
- post:
- summary: Set a configuration item
- operationId: setConfigurationItem
- requestBody:
- required: true
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ConfigurationItem'
- responses:
- '200':
- description: Configuration item updated successfully
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/SuccessMessage'
- '400':
- description: Bad request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
- tags:
- - Operation
- security:
- - oauth:
- - 'c-pat:op'
- delete:
- summary: Delete a configuration item
- operationId: deleteConfigurationItem
- parameters:
- - name: key
- in: query
- required: true
- schema:
- $ref: '#/components/schemas/String255'
- responses:
- '200':
- description: Configuration item deleted successfully
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/SuccessMessage'
+ $ref: '#/components/schemas/SuccessResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/error'
+ '500':
+ description: Internal server error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/error'
tags:
- - Operation
+ - User
security:
- oauth:
- - 'c-pat:op'
+ - 'c-pat:read'
- /vramUpdatedDate:
- get:
- summary: Get VRAM data updated date
- description: Retrieves the last updated date of the VRAM data
- operationId: getVramDataUpdatedDate
+ /user/updatePoints:
+ put:
+ summary: Updates a users points
+ operationId: updateUserPoints
+ parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdatePointsRequest'
responses:
'200':
- description: Successful response
+ description: Successfully updated the users points
content:
application/json:
schema:
- type: object
- properties:
- value:
- type: string
+ $ref: '#/components/schemas/SuccessResponse'
'400':
- description: Bad Request
+ description: Bad request
content:
application/json:
schema:
@@ -3938,126 +3635,110 @@ paths:
schema:
$ref: '#/components/schemas/error'
tags:
- - IAV
+ - User
security:
- oauth:
- - 'c-pat:op'
-
- /iavSummary:
+ - 'c-pat:read'
+
+ '/users':
get:
- summary: Get IAV Summary
- description: Retrieves IAV table data
- operationId: getIAVTableData
+ tags:
+ - User
+ security:
+ - oauth:
+ - 'c-pat:op'
+ summary: Return all users for admin processing
+ operationId: getUsers
+ parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
responses:
'200':
- description: Successful response
+ description: User response
content:
application/json:
schema:
type: array
items:
- $ref: '#/components/schemas/IAVTableData'
- '400':
- description: Bad Request
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/error'
+ $ref: '#/components/schemas/current_user_Response'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/error'
+
+ '/user/{userId}':
+ parameters:
+ - $ref: '#/components/parameters/ElevateQuery'
+ - in: path
+ name: userId
+ required: true
+ schema:
+ type: integer
+ get:
tags:
- - IAV
+ - User
security:
- oauth:
- - 'c-pat:read'
-
- /mapPluginIds:
- post:
- summary: Maps Plugin IDs to IAVs
- description: Maps Plugin IDs to IAVs
- operationId: mapIAVPluginIds
- requestBody:
- required: true
- content:
- application/json:
- schema:
- type: array
- items:
- type: object
- properties:
- iav:
- type: string
- pattern: '^\d{4}-[A-Z]-\d{4}$'
- description: IAV in the format 0000-A-0000
- pluginID:
- type: string
- description: Comma-separated list of plugin IDs
- required:
- - iav
- - pluginID
+ - 'c-pat:op'
+ summary: Return a User
+ operationId: getUserByUserID
responses:
'200':
- description: Successful response
+ description: User response
content:
application/json:
schema:
- type: object
- properties:
- message:
- type: string
- updatedCount:
- type: integer
- '400':
- description: Bad Request
+ $ref: '#/components/schemas/user'
+ '500':
+ description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/error'
+ delete:
+ tags:
+ - User
+ security:
+ - oauth:
+ - 'c-pat:op'
+ summary: Delete a User
+ operationId: deleteUser
+ responses:
+ '200':
+ description: User response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/user'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/error'
- tags:
- - IAV
- security:
- - oauth:
- - 'c-pat:op'
- /iav/pluginInfo:
+ '/vulnerability/poam/{vulnerabilityId}':
+ parameters:
+ - in: path
+ name: vulnerabilityId
+ required: true
+ schema:
+ type: string
get:
- summary: Get IAV and Navy Comply Date for Plugin IDs
- description: Retrieves IAV and Navy Comply Date information for given Plugin IDs
- operationId: getIAVInfoForPlugins
- parameters:
- - in: query
- name: pluginIDs
- required: true
- schema:
- type: string
- description: Comma-separated list of Plugin IDs
+ summary: Return POAMs by vulnerabilityId
+ operationId: getPoamsByVulnerabilityId
responses:
'200':
- description: Successful response
+ description: POAM array response
content:
application/json:
schema:
type: array
items:
- type: object
- properties:
- pluginID:
- type: integer
- iav:
- type: string
- navyComplyDate:
- type: string
- format: date
+ $ref: '#/components/schemas/poam_Object'
+ '403':
+ $ref: '#/components/responses/forbidden'
'400':
description: Bad Request
content:
@@ -4071,33 +3752,29 @@ paths:
schema:
$ref: '#/components/schemas/error'
tags:
- - IAV
+ - Vulnerability
security:
- oauth:
- 'c-pat:read'
- /iav/pluginIDs:
+ '/vulnerability/existingPoams':
get:
- summary: Retrieves mapped IAV pluginIDs
- description: Get all unique pluginIDs that have an associated IAV as a comma-separated string
- operationId: getIAVPluginIds
+ summary: Return a list of vulnerabilities associated with existing POAMs
+ operationId: getExistingVulnerabilityPoams
responses:
'200':
- description: Successful response
- content:
- application/json:
- schema:
- type: object
- properties:
- pluginIDs:
- type: string
- description: Comma-separated list of unique plugin IDs
- '400':
- description: Bad Request
+ description: Successful response with existing vulnerability POAMs
content:
application/json:
schema:
- $ref: '#/components/schemas/error'
+ type: array
+ items:
+ type: object
+ properties:
+ poamId:
+ type: integer
+ vulnerabilityId:
+ type: string
'500':
description: Internal server error
content:
@@ -4105,10 +3782,10 @@ paths:
schema:
$ref: '#/components/schemas/error'
tags:
- - IAV
+ - Vulnerability
security:
- oauth:
- - 'c-pat:read'
+ - 'c-pat:read'
components:
schemas:
@@ -4656,6 +4333,29 @@ components:
type: integer
extensionJustification:
type: string
+ mitigations:
+ type: string
+ requiredResources:
+ type: string
+ residualRisk:
+ type: string
+ likelihood:
+ type: string
+ relevanceOfThreat:
+ type: string
+ impactRating:
+ type: string
+ impactDescription:
+ type: string
+ status:
+ type: string
+ poamLog:
+ type: array
+ items:
+ type: object
+ properties:
+ userId:
+ type: integer
poam_status_object:
type: object
@@ -4745,17 +4445,14 @@ components:
relevanceOfThreat:
type: string
nullable: true
- businessImpactRating:
+ impactRating:
type: string
nullable: true
- businessImpactDescription:
+ impactDescription:
type: string
nullable: true
status:
type: string
- vulnIdRestricted:
- type: string
- nullable: true
submittedDate:
type: string
format: date
@@ -5347,32 +5044,7 @@ components:
type: integer
nullable: true
isAdmin:
- type: integer
-
- user_Login:
- required:
- - email
- type: object
- additionalProperties: false
- properties:
- email:
- type: string
-
- user_loginState:
- required:
- - loginState
- type: object
- additionalProperties: false
- properties:
- loginState:
- type: string
-
- user_Login_Response:
- type: object
- additionalProperties: false
- properties:
- message:
- type: string
+ type: integer
user_Token:
required:
@@ -5507,6 +5179,14 @@ components:
$ref: '#/components/schemas/error'
parameters:
+ ElevateQuery:
+ name: elevate
+ in: query
+ description: Elevate the user context for this request if user is permitted (isAdmin)
+ schema:
+ type: boolean
+ default: false
+
collectionQuery:
name: projection
in: query
@@ -5550,20 +5230,6 @@ components:
description: A query parameter that identifies an Asset
schema:
type: string
- userIdPath:
- name: userId
- in: path
- description: A path parameter that identifies a User
- required: true
- schema:
- type: string
- collectionAuth:
- name: userName
- in: path
- required: true
- description: Returns collections belonging to a specif User
- schema:
- type: string
securitySchemes:
oauth:
diff --git a/api/utils/auth.js b/api/utils/auth.js
index 2f425807..b0a75c96 100644
--- a/api/utils/auth.js
+++ b/api/utils/auth.js
@@ -18,58 +18,42 @@ const { promisify } = require('util');
const User = require('../Services/usersService')
const axios = require('axios');
const SmError = require('./error');
-const { format, isAfter } = require('date-fns');
+const { format, isAfter, differenceInMinutes } = require('date-fns');
-let jwksUri;
-let client;
+let jwksUri
+let client
const privilegeGetter = new Function("obj", "return obj?." + config.oauth.claims.privileges + " || [];");
const verifyRequest = async function (req, requiredScopes, securityDefinition) {
- const token = getBearerToken(req);
+
+ const token = getBearerToken(req)
if (!token) {
- throw new SmError.AuthorizeError("OIDC bearer token must be provided");
+ throw (new SmError.AuthorizeError("OIDC bearer token must be provided"))
}
-
- const options = { algorithms: ['RS256'] };
- const decoded = await verifyAndDecodeToken(token, getKey, options);
- req.access_token = decoded;
- req.bearer = token;
-
+ const options = {
+ algorithms: ['RS256']
+ }
+ const decoded = await verifyAndDecodeToken(token, getKey, options)
+ req.access_token = decoded
+ req.bearer = token
req.userObject = {
- userName: decoded[config.oauth.claims.username],
- firstName: decoded[config.oauth.claims.firstname] || 'null',
- lastName: decoded[config.oauth.claims.lastname] || 'null',
- fullName: decoded[config.oauth.claims.fullname] || 'null',
- email: decoded[config.oauth.claims.email],
- lastClaims: req.access_token,
- };
-
- const usernamePrecedence = [config.oauth.claims.username, "preferred_username", config.oauth.claims.servicename, "azp", "client_id", "clientId"];
- req.userObject.userName = decoded[usernamePrecedence.find(element => !!decoded[element])];
-
- if (req.userObject.userName === undefined) {
- throw new SmError.PrivilegeError("No token claim mappable to username found");
+ email: decoded[config.oauth.claims.email] || '',
+ firstName: decoded[config.oauth.claims.firstname] || '',
+ lastName: decoded[config.oauth.claims.lastname] || '',
+ fullName: decoded[config.oauth.claims.fullname] || '',
}
- let scopeClaim;
- if (decoded[config.oauth.claims.scope]) {
- scopeClaim = decoded[config.oauth.claims.scope];
- } else if (decoded.scope) {
- scopeClaim = decoded.scope;
- } else {
- scopeClaim = null;
+ const usernamePrecedence = [config.oauth.claims.username, "preferred_username", config.oauth.claims.servicename, "azp", "client_id", "clientId"]
+ req.userObject.userName = decoded[usernamePrecedence.find(element => !!decoded[element])]
+ if (req.userObject.userName === undefined) {
+ throw (new SmError.PrivilegeError("No token claim mappable to username found"))
}
- let grantedScopes = [];
-
- if (typeof scopeClaim === 'string') {
- grantedScopes = scopeClaim.split(' ');
- } else if (Array.isArray(scopeClaim)) {
- grantedScopes = scopeClaim;
- } else {
- logger.writeError('verifyRequest', 'invalidScopeType', { scopeClaim, grantedScopes });
- }
+ req.userObject.displayName = decoded[config.oauth.claims.name] || req.userObject.userName
+ const grantedScopes = typeof decoded[config.oauth.claims.scope] === 'string' ?
+ decoded[config.oauth.claims.scope].split(' ') :
+ decoded[config.oauth.claims.scope]
const commonScopes = _.intersectionWith(grantedScopes, requiredScopes, function (gs, rs) {
if (gs === rs) return gs
let gsTokens = gs.split(":").filter(i => i.length)
@@ -80,51 +64,49 @@ const verifyRequest = async function (req, requiredScopes, securityDefinition) {
else {
return gsTokens.every((t, i) => rsTokens[i] === t)
}
- });
-
+ })
if (commonScopes.length == 0) {
throw (new SmError.PrivilegeError("Not in scope"))
- } else {
- const permissions = {};
- permissions.canAdmin = privilegeGetter(decoded).includes('admin');
- req.userObject.isAdmin = permissions.canAdmin ? 1 : 0;
+ }
+ else {
+ let isAdmin = privilegeGetter(decoded).includes('admin');
const response = await User.getUserByUserName(req.userObject.userName);
-
+ if (response?.length > 1) req.userObject = response;
+ const adminValidation = response?.isAdmin === 1 ? isAdmin : 0;
+ req.userObject.isAdmin = adminValidation;
req.userObject.userId = response?.userId || null;
+ const refreshFields = {}
let now = new Date();
let formattedNow = format(now, 'yyyy-MM-dd HH:mm:ss');
- if (!response?.lastAccess) {
- req.userObject.lastAccess = formattedNow;
- } else {
- let lastAccessDate = new Date(response.lastAccess);
- if (isAfter(now, lastAccessDate)) {
- req.userObject.lastAccess = formattedNow;
- } else {
- req.userObject.lastAccess = response.lastAccess;
- }
+ if (!response?.lastAccess || differenceInMinutes(now, response?.lastAccess) >= config.settings.lastAccessResolution) {
+ refreshFields.lastAccess = now
}
if (!response?.lastClaims || decoded.jti !== response?.lastClaims?.jti) {
- req.userObject.lastClaims = decoded
- } else {
- req.userObject.lastClaims = response.lastClaims
+ refreshFields.lastClaims = decoded
}
- if (req.userObject.userName) {
- const userResponse = await User.setUserData(req.userObject);
- const userId = userResponse.userId;
- if (userId !== req.userObject.userId) {
- req.userObject.userId = userId;
- }
+ if (req.userObject.userName && (refreshFields.lastAccess || refreshFields.lastClaims)) {
+ if (req.userObject.userId === null) {
+ const userId = await User.setUserData(req.userObject, refreshFields, true);
+ if (userId.insertId != req.userObject.userId) {
+ req.userObject.userId = userId.insertId.toString();
+ }
+ } else {
+ const userId = await User.setUserData(req.userObject, refreshFields, false);
+ if (userId.insertId != req.userObject.userId) {
+ req.userObject.userId = userId.insertId.toString();
+ }
+ }
}
-
- if ('elevate' in req.query && req.query.elevate === 'true' && !permissions.canAdmin) {
- throw new SmError.PrivilegeError("User has insufficient privilege to complete this request.");
+ if ('elevate' in req.query && (req.query.elevate === 'true' && req.userObject.isAdmin != 1)) {
+ throw (new SmError.PrivilegeError("User has insufficient privilege to complete this request."))
}
return true;
}
-};
+
+}
const verifyAndDecodeToken = promisify(jwt.verify);
diff --git a/api/utils/config.js b/api/utils/config.js
index 8bbc3eb2..18d7d975 100644
--- a/api/utils/config.js
+++ b/api/utils/config.js
@@ -21,6 +21,7 @@ let config = {
},
settings: {
setClassification: process.env.CPAT_CLASSIFICATION || "U",
+ lastAccessResolution: 60,
responseValidation: process.env.CPAT_DEV_RESPONSE_VALIDATION || "none"
},
client: {
@@ -93,7 +94,7 @@ let config = {
oauth: {
authority: process.env.CPAT_OIDC_PROVIDER || "http://192.168.1.101:8080/auth/realms/RMFTools",
claims: {
- scope: process.env.CPAT_JWT_SCOPE_CLAIM || "c-pat:read c-pat:op openid profile offline_access",
+ scope: process.env.CPAT_JWT_SCOPE_CLAIM || "scope",
username: process.env.CPAT_JWT_USERNAME_CLAIM || "preferred_username",
servicename: process.env.CPAT_JWT_SERVICENAME_CLAIM || "clientId",
fullname: process.env.CPAT_JWT_FULL_NAME_CLAIM || process.env.CPAT_JWT_USERNAME_CLAIM || "name",
diff --git a/client/package-lock.json b/client/package-lock.json
index cd482440..aa180f27 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -8,33 +8,33 @@
"name": "cpat-frontend",
"version": "0.3.0",
"dependencies": {
- "@angular/animations": "^18.2.0",
- "@angular/cdk": "^18.2.0",
- "@angular/common": "^18.2.0",
- "@angular/compiler": "^18.2.0",
- "@angular/core": "^18.2.0",
- "@angular/forms": "^18.2.0",
- "@angular/localize": "^18.2.0",
- "@angular/material": "^18.2.0",
- "@angular/platform-browser": "^18.2.0",
- "@angular/platform-browser-dynamic": "^18.2.0",
- "@angular/router": "^18.2.0",
+ "@angular/animations": "^18.2.1",
+ "@angular/cdk": "^18.2.1",
+ "@angular/common": "^18.2.1",
+ "@angular/compiler": "^18.2.1",
+ "@angular/core": "^18.2.1",
+ "@angular/forms": "^18.2.1",
+ "@angular/localize": "^18.2.1",
+ "@angular/material": "^18.2.1",
+ "@angular/platform-browser": "^18.2.1",
+ "@angular/platform-browser-dynamic": "^18.2.1",
+ "@angular/router": "^18.2.1",
"@fortawesome/fontawesome-free": "^6.6.0",
"@ng-bootstrap/ng-bootstrap": "^17.0.0",
"@swimlane/ngx-charts": "^20.5.0",
"@tsparticles/angular": "^3.0.0",
"angular-auth-oidc-client": "^18.0.1",
"bootstrap": "^5.3.3",
- "chart.js": "^4.4.3",
+ "chart.js": "^4.4.4",
"chartjs-plugin-datalabels": "^2.2.0",
"classlist.js": "^1.1.20150312",
"date-fns": "^3.6.0",
"exceljs": "^4.4.0",
- "instantsearch.js": "^4.73.4",
+ "instantsearch.js": "^4.74.0",
"json-to-plain-text": "^1.1.4",
"jsonwebtoken": "^9.0.2",
"ng2-charts": "^6.0.1",
- "npm-check-updates": "^17.0.6",
+ "npm-check-updates": "^17.1.0",
"pace-js": "^1.2.4",
"primeflex": "^3.3.1",
"primeicons": "^7.0.0",
@@ -43,105 +43,88 @@
"subsink": "^1.0.2",
"typescript": "^5.5.4",
"web-animations-js": "^2.3.2",
- "zone.js": "^0.14.10"
+ "zone.js": "^0.15.0"
},
"devDependencies": {
- "@angular-devkit/build-angular": "^18.2.0",
- "@angular/cli": "^18.2.0",
- "@angular/compiler-cli": "^18.2.0",
+ "@angular-devkit/build-angular": "^18.2.1",
+ "@angular/cli": "^18.2.1",
+ "@angular/compiler-cli": "^18.2.1",
"@types/chart.js": "^2.9.41",
"@types/d3": "^7.4.3",
"@types/jasmine": "^5.1.4",
"@types/jquery": "^3.5.30",
- "@types/node": "^22.4.1",
+ "@types/node": "^22.5.0",
"jasmine-core": "^5.2.0"
}
},
- "node_modules/@algolia/cache-browser-local-storage": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz",
- "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@algolia/cache-common": "4.24.0"
- }
- },
- "node_modules/@algolia/cache-common": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz",
- "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/@algolia/cache-in-memory": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz",
- "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@algolia/cache-common": "4.24.0"
- }
- },
- "node_modules/@algolia/client-account": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz",
- "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==",
+ "node_modules/@algolia/client-abtesting": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.1.0.tgz",
+ "integrity": "sha512-WKL6ryH+CYCUlDz1Sr4M/SUn5qoRyqmGbKNen5PoFtEA9GWuM6lFk9XvsKvh0UwH/k20tBKq75NTOCUEA5gVRw==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/client-common": "4.24.0",
- "@algolia/client-search": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "@algolia/client-common": "5.1.0",
+ "@algolia/requester-browser-xhr": "5.1.0",
+ "@algolia/requester-node-http": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-analytics": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz",
- "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.1.0.tgz",
+ "integrity": "sha512-HqJa0z+8maRmsNTxdytyr4ADt735fEK/0S/doKuRqYgloGanIB1njxuq2wP8oW1ARfo5mlCJ7dF1csO+/V/fVQ==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/client-common": "4.24.0",
- "@algolia/client-search": "4.24.0",
- "@algolia/requester-common": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "@algolia/client-common": "5.1.0",
+ "@algolia/requester-browser-xhr": "5.1.0",
+ "@algolia/requester-node-http": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-common": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz",
- "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.1.0.tgz",
+ "integrity": "sha512-/PUtnEKpI9opioNfVKA5cBGQr0yulE3OWJCf9xWjJRFn+CvTAWkIecBWF9R+GpxeoaTqf3lWqDwYt8zEBXU11Q==",
"license": "MIT",
"peer": true,
- "dependencies": {
- "@algolia/requester-common": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-personalization": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz",
- "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.1.0.tgz",
+ "integrity": "sha512-OkUJmksAJK5Q0WAwX+QTfN84zsohD08KIljO0+IZYagm0LoPHF6corYYkF1hV1wcOmFwpjla+cIV+h8TcA59fQ==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/client-common": "4.24.0",
- "@algolia/requester-common": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "@algolia/client-common": "5.1.0",
+ "@algolia/requester-browser-xhr": "5.1.0",
+ "@algolia/requester-node-http": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-search": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz",
- "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.1.0.tgz",
+ "integrity": "sha512-zPMO+iX+PnrQAX2tzW7ViletvkDNqLG1CI0k+9wXZtyVuQrPI6pxho/mANlC9QHmiMH3eR2KibQCOBMifOd61w==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/client-common": "4.24.0",
- "@algolia/requester-common": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "@algolia/client-common": "5.1.0",
+ "@algolia/requester-browser-xhr": "5.1.0",
+ "@algolia/requester-node-http": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@algolia/events": {
@@ -150,80 +133,45 @@
"integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==",
"license": "MIT"
},
- "node_modules/@algolia/logger-common": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz",
- "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/@algolia/logger-console": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz",
- "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@algolia/logger-common": "4.24.0"
- }
- },
"node_modules/@algolia/recommend": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz",
- "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.1.0.tgz",
+ "integrity": "sha512-0pF1DcB/1fNCOU6DXcI3v1h/sADT9ueACoLcYZd5YUYl/X3wsq/BBPRi/NY1r93hi+LyTfIbywS5pgZ3v4fRDg==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/cache-browser-local-storage": "4.24.0",
- "@algolia/cache-common": "4.24.0",
- "@algolia/cache-in-memory": "4.24.0",
- "@algolia/client-common": "4.24.0",
- "@algolia/client-search": "4.24.0",
- "@algolia/logger-common": "4.24.0",
- "@algolia/logger-console": "4.24.0",
- "@algolia/requester-browser-xhr": "4.24.0",
- "@algolia/requester-common": "4.24.0",
- "@algolia/requester-node-http": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "@algolia/client-common": "5.1.0",
+ "@algolia/requester-browser-xhr": "5.1.0",
+ "@algolia/requester-node-http": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-browser-xhr": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz",
- "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.1.0.tgz",
+ "integrity": "sha512-q2HpJBxVnvmk9UfphzjGgYSKDX/qXeuPmKlybYAX1dZ1/b8LBOt066JjS5L9CXuxW26Igi/PrdbzA9tL8jD3QQ==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/requester-common": "4.24.0"
+ "@algolia/client-common": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
- "node_modules/@algolia/requester-common": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz",
- "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==",
- "license": "MIT",
- "peer": true
- },
"node_modules/@algolia/requester-node-http": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz",
- "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@algolia/requester-common": "4.24.0"
- }
- },
- "node_modules/@algolia/transporter": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz",
- "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.1.0.tgz",
+ "integrity": "sha512-P51ZDjoswq6OLVY+vES+EekkC0OPABKrJ9s4S1UKNTvggDIn38BoM9L25K7TEWEmjCG68EKDGSPUAt1q/dS0Uw==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/cache-common": "4.24.0",
- "@algolia/logger-common": "4.24.0",
- "@algolia/requester-common": "4.24.0"
+ "@algolia/client-common": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -240,13 +188,13 @@
}
},
"node_modules/@angular-devkit/architect": {
- "version": "0.1802.0",
- "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.0.tgz",
- "integrity": "sha512-s1atTSL98XLUUxfWEQAnhFaOFIJZDLWjSqec+Sb+f4iZFj+hOFejzJxPVnHMIJudOzn0Lqjk3t987KG/zNEGdg==",
+ "version": "0.1802.1",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.1.tgz",
+ "integrity": "sha512-XTnJfCBMDQl3xF4w/eNrq821gbj2Ig1cqbzpRflhz4pqrANTAfHfPoIC7piWEZ60FNlHapzb6fvh6tJUGXG9og==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/core": "18.2.0",
+ "@angular-devkit/core": "18.2.1",
"rxjs": "7.8.1"
},
"engines": {
@@ -256,17 +204,17 @@
}
},
"node_modules/@angular-devkit/build-angular": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.0.tgz",
- "integrity": "sha512-V0XKT7xt6d6duXqmDAQEQgEJNXuWAekpHEDxafvBT0MTxcEhu0ozQVwI4oAekiKOz+APIcAZyMzvw3Tlzog5cw==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.1.tgz",
+ "integrity": "sha512-ANsTWKjIlEvJ6s276TbwnDhkoHhQDfsNiRFUDRGBZu94UNR78ImQZSyKYGHJOeQQH6jpBtraA1rvW5WKozAtlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "2.3.0",
- "@angular-devkit/architect": "0.1802.0",
- "@angular-devkit/build-webpack": "0.1802.0",
- "@angular-devkit/core": "18.2.0",
- "@angular/build": "18.2.0",
+ "@angular-devkit/architect": "0.1802.1",
+ "@angular-devkit/build-webpack": "0.1802.1",
+ "@angular-devkit/core": "18.2.1",
+ "@angular/build": "18.2.1",
"@babel/core": "7.25.2",
"@babel/generator": "7.25.0",
"@babel/helper-annotate-as-pure": "7.24.7",
@@ -277,7 +225,7 @@
"@babel/preset-env": "7.25.3",
"@babel/runtime": "7.25.0",
"@discoveryjs/json-ext": "0.6.1",
- "@ngtools/webpack": "18.2.0",
+ "@ngtools/webpack": "18.2.1",
"@vitejs/plugin-basic-ssl": "1.1.0",
"ansi-colors": "4.1.3",
"autoprefixer": "10.4.20",
@@ -309,7 +257,7 @@
"postcss-loader": "8.1.1",
"resolve-url-loader": "5.0.0",
"rxjs": "7.8.1",
- "sass": "1.77.8",
+ "sass": "1.77.6",
"sass-loader": "16.0.0",
"semver": "7.6.3",
"source-map-loader": "5.0.0",
@@ -384,27 +332,30 @@
}
}
},
- "node_modules/@angular-devkit/build-angular/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "node_modules/@angular-devkit/build-angular/node_modules/@babel/generator": {
+ "version": "7.25.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz",
+ "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==",
"dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.25.0",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^2.5.1"
},
"engines": {
- "node": ">=10"
+ "node": ">=6.9.0"
}
},
"node_modules/@angular-devkit/build-webpack": {
- "version": "0.1802.0",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.0.tgz",
- "integrity": "sha512-bU7AxlI/avnlOLrgE195cokrOA1ayT6JjRv8Hxzh1bIOa1jE87HsyjxvQhOLcdEb97zwHqMqbntcgUNBgsegJQ==",
+ "version": "0.1802.1",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.1.tgz",
+ "integrity": "sha512-xOP9Hxkj/mWYdMTa/8uNxFTv7z+3UiGdt4VAO7vetV5qkU/S9rRq8FEKviCc2llXfwkhInSgeeHpWKdATa+YIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/architect": "0.1802.0",
+ "@angular-devkit/architect": "0.1802.1",
"rxjs": "7.8.1"
},
"engines": {
@@ -418,9 +369,9 @@
}
},
"node_modules/@angular-devkit/core": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.0.tgz",
- "integrity": "sha512-8SOopyUKUMqAq2rj32XkTIfr79Y274k4uglxxRtzHYoWwHlLdG0KrA+wCcsh/FU9PyR4dA+5dcDAApn358ZF+Q==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.1.tgz",
+ "integrity": "sha512-fSuGj6CxiTFR+yjuVcaWqaVb5Wts39CSBYRO1BlsOlbuWFZ2NKC/BAb5bdxpB31heCBJi7e3XbPvcMMJIcnKlA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -446,13 +397,13 @@
}
},
"node_modules/@angular-devkit/schematics": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.0.tgz",
- "integrity": "sha512-WWKwz2RKMVI6T25JFwOSSfRLB+anNzabVIRwf85R/YMIo34BUk777f2JU/7cCKlxSpQu39TqIfMQZAyzAD1z0A==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.1.tgz",
+ "integrity": "sha512-2t/q0Jcv7yqhAzEdNgsxoGSCmPgD4qfnVOJ7EJw3LNIA+kX1CmtN4FESUS0i49kN4AyNJFAI5O2pV8iJiliKaw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/core": "18.2.0",
+ "@angular-devkit/core": "18.2.1",
"jsonc-parser": "3.3.1",
"magic-string": "0.30.11",
"ora": "5.4.1",
@@ -465,9 +416,9 @@
}
},
"node_modules/@angular/animations": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.0.tgz",
- "integrity": "sha512-BFAfqDDjsa0Q91F4s33pFcBG+ydFDurEmwYGG1gmO7UXZJI6ZbRVdULaZHz75M+Bf3hJkzVB05pesvfbK+Fg/g==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.1.tgz",
+ "integrity": "sha512-jit452yuE6DMVV09E6RAjgapgw64mMVH31ccpPvMDekzPsTuP3KNKtgRFU/k2DFhYJvyczM1AqqlgccE/JGaRw==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -476,18 +427,18 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/core": "18.2.0"
+ "@angular/core": "18.2.1"
}
},
"node_modules/@angular/build": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.0.tgz",
- "integrity": "sha512-LvNJ2VOEVy3N1tGzt+xnKyweRBuUE1NsnuEEWAb9Y+V1cyRgj0s7FX2+IQZZQhP+W/pXfbsKaByOAbJ5KWV85Q==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.1.tgz",
+ "integrity": "sha512-HwzjB+I31cAtjTTbbS2NbayzfcWthaKaofJlSmZIst3PN+GwLZ8DU0DRpd/xu5AXkk+DoAIWd+lzUIaqngz6ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "2.3.0",
- "@angular-devkit/architect": "0.1802.0",
+ "@angular-devkit/architect": "0.1802.1",
"@babel/core": "7.25.2",
"@babel/helper-annotate-as-pure": "7.24.7",
"@babel/helper-split-export-declaration": "7.24.7",
@@ -507,7 +458,7 @@
"picomatch": "4.0.2",
"piscina": "4.6.1",
"rollup": "4.20.0",
- "sass": "1.77.8",
+ "sass": "1.77.6",
"semver": "7.6.3",
"vite": "5.4.0",
"watchpack": "2.4.1"
@@ -548,23 +499,10 @@
}
}
},
- "node_modules/@angular/build/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@angular/cdk": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.0.tgz",
- "integrity": "sha512-hjuUWNhxU48WB2i1j4NLwnPTaCnucRElfp7DBX5Io0rY5Lwl3HXafvyi7/A1D0Ah+YsJpktKOWPDGv8r7vxymg==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.1.tgz",
+ "integrity": "sha512-6y4MmpEPXze6igUHkLsBUPkxw32F8+rmW0xVXZchkSyGlFgqfh53ueXoryWb0qL4s5enkNY6AzXnKAqHfPNkVQ==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -579,18 +517,18 @@
}
},
"node_modules/@angular/cli": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.0.tgz",
- "integrity": "sha512-hA60QIA7Dh8LQxM42wqd7WrhwQjbjB8oIRH5Slgbiv8iocAo76scp1/qyZo2SSzjfkB7jxUiao5L4ckiJ/hvZg==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.1.tgz",
+ "integrity": "sha512-SomUFDHanY4o7k3XBGf1eFt4z1h05IGJHfcbl2vxoc0lY59VN13m/pZsD2AtpqtJTzLQT02XQOUP4rmBbGoQ+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/architect": "0.1802.0",
- "@angular-devkit/core": "18.2.0",
- "@angular-devkit/schematics": "18.2.0",
+ "@angular-devkit/architect": "0.1802.1",
+ "@angular-devkit/core": "18.2.1",
+ "@angular-devkit/schematics": "18.2.1",
"@inquirer/prompts": "5.3.8",
"@listr2/prompt-adapter-inquirer": "2.0.15",
- "@schematics/angular": "18.2.0",
+ "@schematics/angular": "18.2.1",
"@yarnpkg/lockfile": "1.1.0",
"ini": "4.1.3",
"jsonc-parser": "3.3.1",
@@ -612,23 +550,10 @@
"yarn": ">= 1.13.0"
}
},
- "node_modules/@angular/cli/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@angular/common": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.0.tgz",
- "integrity": "sha512-DELx/QYNqqjmiM+kE5PoVmyG4gPw5WB1bDDeg3hEuBCK3eS2KosgQH0/MQo3OSBZHOcAMFjfHMGqKgxndmYixQ==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.1.tgz",
+ "integrity": "sha512-N0ZJO1/iU9UhprplZRPvBcdRgA/i6l6Ng5gXs5ymHBJ0lxsB+mDVCmC4jISjR9gAWc426xXwLaOpuP5Gv3f/yg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -637,14 +562,14 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/core": "18.2.0",
+ "@angular/core": "18.2.1",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/compiler": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.0.tgz",
- "integrity": "sha512-RmGwQ7jRzotUKKMk0CwxTcIXFr5mRxSbJf9o5S3ujuIOo1lYop8SQZvjq67a5BuoYyD+1pX6iMmxZqlbKoihBQ==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.1.tgz",
+ "integrity": "sha512-5e9ygKEcsBoV6xpaGKVrtsLxLETlrM0oB7twl4qG/xuKYqCLj8cRQMcAKSqDfTPzWMOAQc7pHdk+uFVo/8dWHA==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -653,7 +578,7 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/core": "18.2.0"
+ "@angular/core": "18.2.1"
},
"peerDependenciesMeta": {
"@angular/core": {
@@ -662,9 +587,9 @@
}
},
"node_modules/@angular/compiler-cli": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.0.tgz",
- "integrity": "sha512-pPBFjMqNTNettrleLtEc6a/ysOZjG3F0Z5lyKYePcyNQmn2rpa9XmD2y6PhmzTmIhxeXrogWA84Xgg/vK5wBNw==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.1.tgz",
+ "integrity": "sha512-D+Qba0r6RfHfffzrebGYp54h05AxpkagLjit/GczKNgWSP1gIgZxSfi88D+GvFmeWvZxWN1ecAQ+yqft9hJqWg==",
"license": "MIT",
"dependencies": {
"@babel/core": "7.25.2",
@@ -685,14 +610,14 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/compiler": "18.2.0",
+ "@angular/compiler": "18.2.1",
"typescript": ">=5.4 <5.6"
}
},
"node_modules/@angular/core": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.0.tgz",
- "integrity": "sha512-7+4wXfeAk1TnG3MGho2gpBI5XHxeSRWzLK2rC5qyyRbmMV+GrIgf1HqFjQ4S02rydkQvGpjqQHtO1PYJnyn4bg==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.1.tgz",
+ "integrity": "sha512-9KrSpJ65UlJZNXrE18NszcfOwb5LZgG+LYi5Doe7amt218R1bzb3trvuAm0ZzMaoKh4ugtUCkzEOd4FALPEX6w==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -706,9 +631,9 @@
}
},
"node_modules/@angular/forms": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.0.tgz",
- "integrity": "sha512-G+4BjNCUo4cRwg9NwisGLbtG/1AbIJNOO3RUejPJJbCcAkYMSzmDWSQ+LQEGW4vC/1xaDKO8AT71DI/I09bOxA==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.1.tgz",
+ "integrity": "sha512-T7z8KUuj2PoPxrMrAruQVJha+x4a9Y6IrKYtArgOQQlTwCEJuqpVYuOk5l3fwWpHE9bVEjvgkAMI1D5YXA/U6w==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -717,16 +642,16 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.0",
- "@angular/core": "18.2.0",
- "@angular/platform-browser": "18.2.0",
+ "@angular/common": "18.2.1",
+ "@angular/core": "18.2.1",
+ "@angular/platform-browser": "18.2.1",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/localize": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.0.tgz",
- "integrity": "sha512-ul8yGmimiHkhUU87isDCst0790jTBHP1zPBMI2q7QHv7iDzSN5brV8zUMcRypxhh4mQOCnq2LtP84o5ybn4Sig==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.1.tgz",
+ "integrity": "sha512-nNdB6ehXCSBpQ75sTh6Gcwy2rgExfZEkGcPARJLpjqQlHO+Mk3b1y3ka6XT9M2qQYUeyukncTFUMEZWwHICsOA==",
"license": "MIT",
"dependencies": {
"@babel/core": "7.25.2",
@@ -743,21 +668,21 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/compiler": "18.2.0",
- "@angular/compiler-cli": "18.2.0"
+ "@angular/compiler": "18.2.1",
+ "@angular/compiler-cli": "18.2.1"
}
},
"node_modules/@angular/material": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.0.tgz",
- "integrity": "sha512-lOXk8pAVP4Mr0/Q6YrNnVYQVTnR8aEG5D9QSEWjs+607gONuh/9n7ERBdzX7xO9D0vYyXq+Vil32zcF41/Q8Cg==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.1.tgz",
+ "integrity": "sha512-DBSJGqLttT9vYpLGWTuuRoOKd1mNelS0jnNo7jNZyMpjcGfuhNzmPtYiBkXfNsAl7YoXoUmX8+4uh1JZspQGqA==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/animations": "^18.0.0 || ^19.0.0",
- "@angular/cdk": "18.2.0",
+ "@angular/cdk": "18.2.1",
"@angular/common": "^18.0.0 || ^19.0.0",
"@angular/core": "^18.0.0 || ^19.0.0",
"@angular/forms": "^18.0.0 || ^19.0.0",
@@ -766,9 +691,9 @@
}
},
"node_modules/@angular/platform-browser": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.0.tgz",
- "integrity": "sha512-yhj281TuPz5a8CehwucwIVl29Oqte9KS4X/VQkMV++GpYQE2KKKcoff4FXSdF5RUcUYkK2li4IvawIqPmUSagg==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.1.tgz",
+ "integrity": "sha512-hQABX7QotGmCIR3EhCBCDh5ZTvQao+JkuK5CCw2G1PkRfJMBwEpjNqnyhz41hZhWiGlucp9jgbeypppW+mIQEw==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -777,9 +702,9 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/animations": "18.2.0",
- "@angular/common": "18.2.0",
- "@angular/core": "18.2.0"
+ "@angular/animations": "18.2.1",
+ "@angular/common": "18.2.1",
+ "@angular/core": "18.2.1"
},
"peerDependenciesMeta": {
"@angular/animations": {
@@ -788,9 +713,9 @@
}
},
"node_modules/@angular/platform-browser-dynamic": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.0.tgz",
- "integrity": "sha512-izfaXKNC/kqOEzJG8eTnFu39VLI3vv3dTKoYOdEKRB7MTI0t0x66oZmABnHcihtkTSvXs/is+7lA5HmH2ZuIEQ==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.1.tgz",
+ "integrity": "sha512-tYJHtshbaKrtnRA15k3vrveSVBqkVUGhINvGugFA2vMtdTOfhfPw+hhzYrcwJibgU49rHogCfI9mkIbpNRYntA==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -799,16 +724,16 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.0",
- "@angular/compiler": "18.2.0",
- "@angular/core": "18.2.0",
- "@angular/platform-browser": "18.2.0"
+ "@angular/common": "18.2.1",
+ "@angular/compiler": "18.2.1",
+ "@angular/core": "18.2.1",
+ "@angular/platform-browser": "18.2.1"
}
},
"node_modules/@angular/router": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.0.tgz",
- "integrity": "sha512-6/462hvC3HSwbps8VItECHpkdkiFqRmTKdn1Trik+FjnvdupYrKB6kBsveM3eP+gZD4zyMBMKzBWB9N/xA1clw==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.1.tgz",
+ "integrity": "sha512-gVyqW6fYnG7oq1DlZSXJMQ2Py2dJQB7g6XVtRcYB1gR4aeowx5N9ws7PjqAi0ih91ASq2MmP4OlSSWLq+eaMGg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -817,9 +742,9 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.0",
- "@angular/core": "18.2.0",
- "@angular/platform-browser": "18.2.0",
+ "@angular/common": "18.2.1",
+ "@angular/core": "18.2.1",
+ "@angular/platform-browser": "18.2.1",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
@@ -891,12 +816,12 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz",
- "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.4.tgz",
+ "integrity": "sha512-NFtZmZsyzDPJnk9Zg3BbTfKKc9UlHYzD0E//p2Z3B9nCwwtJW9T0gVbCz8+fBngnn4zf1Dr3IK8PHQQHq0lDQw==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.0",
+ "@babel/types": "^7.25.4",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^2.5.1"
@@ -958,9 +883,9 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz",
- "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz",
+ "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -969,7 +894,7 @@
"@babel/helper-optimise-call-expression": "^7.24.7",
"@babel/helper-replace-supers": "^7.25.0",
"@babel/helper-skip-transparent-expression-wrappers": "^7.24.7",
- "@babel/traverse": "^7.25.0",
+ "@babel/traverse": "^7.25.4",
"semver": "^6.3.1"
},
"engines": {
@@ -1249,12 +1174,12 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.25.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz",
- "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz",
+ "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.2"
+ "@babel/types": "^7.25.4"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1699,14 +1624,14 @@
}
},
"node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz",
- "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz",
+ "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-class-features-plugin": "^7.25.4",
+ "@babel/helper-plugin-utils": "^7.24.8"
},
"engines": {
"node": ">=6.9.0"
@@ -1734,17 +1659,17 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz",
- "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz",
+ "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-compilation-targets": "^7.24.8",
+ "@babel/helper-compilation-targets": "^7.25.2",
"@babel/helper-plugin-utils": "^7.24.8",
"@babel/helper-replace-supers": "^7.25.0",
- "@babel/traverse": "^7.25.0",
+ "@babel/traverse": "^7.25.4",
"globals": "^11.1.0"
},
"engines": {
@@ -2215,14 +2140,14 @@
}
},
"node_modules/@babel/plugin-transform-private-methods": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz",
- "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz",
+ "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-class-features-plugin": "^7.25.4",
+ "@babel/helper-plugin-utils": "^7.24.8"
},
"engines": {
"node": ">=6.9.0"
@@ -2462,14 +2387,14 @@
}
},
"node_modules/@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz",
- "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz",
+ "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.2",
+ "@babel/helper-plugin-utils": "^7.24.8"
},
"engines": {
"node": ">=6.9.0"
@@ -2635,16 +2560,16 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.25.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz",
- "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz",
+ "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.25.0",
- "@babel/parser": "^7.25.3",
+ "@babel/generator": "^7.25.4",
+ "@babel/parser": "^7.25.4",
"@babel/template": "^7.25.0",
- "@babel/types": "^7.25.2",
+ "@babel/types": "^7.25.4",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -2653,9 +2578,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz",
- "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==",
+ "version": "7.25.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz",
+ "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.24.8",
@@ -3800,9 +3725,9 @@
}
},
"node_modules/@ngtools/webpack": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.0.tgz",
- "integrity": "sha512-a6hbkYzh/KUlI52huiU4vztqIuxzyddg6kJGcelUJx3Ju6MJeziu+XmJ6wqFRvfH89zmJeaSADKsGFQaBHtJLg==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.1.tgz",
+ "integrity": "sha512-v86U3jOoy5R9ZWe9Q0LbHRx/IBw1lbn0ldBU+gIIepREyVvb9CcH/vAyIb2Fw1zaYvvfG1OyzdrHyW8iGXjdnQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4297,14 +4222,14 @@
]
},
"node_modules/@schematics/angular": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.0.tgz",
- "integrity": "sha512-XePvx2ZnxCcAQw5lHVMUrJvm8MXqAWGcMyJDAuQUqNZrPCk3GpCaplWx2n+nPkinYVX2Q2v/DqtvWStQwgU4nA==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.1.tgz",
+ "integrity": "sha512-bBV7I+MCbdQmBPUFF4ECg37VReM0+AdQsxgwkjBBSYExmkErkDoDgKquwL/tH7stDCc5IfTd0g9BMeosRgDMug==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/core": "18.2.0",
- "@angular-devkit/schematics": "18.2.0",
+ "@angular-devkit/core": "18.2.1",
+ "@angular-devkit/schematics": "18.2.1",
"jsonc-parser": "3.3.1"
},
"engines": {
@@ -5056,9 +4981,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.4.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.4.1.tgz",
- "integrity": "sha512-1tbpb9325+gPnKK0dMm+/LMriX0vKxf6RnB0SZUqfyVkQ4fMgUSySqhxE/y8Jvs4NyF1yHzTfG9KlnkIODxPKg==",
+ "version": "22.5.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz",
+ "integrity": "sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5505,33 +5430,29 @@
}
},
"node_modules/algoliasearch": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz",
- "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.1.0.tgz",
+ "integrity": "sha512-fN+g3ebMNA3+pCWC9P2Jbw6m3EBaEaQViXkq/j3XCJUJ0j1+aUsic0CmsBja4wdci5Eovv8dL8VTcURmvq9Fyg==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@algolia/cache-browser-local-storage": "4.24.0",
- "@algolia/cache-common": "4.24.0",
- "@algolia/cache-in-memory": "4.24.0",
- "@algolia/client-account": "4.24.0",
- "@algolia/client-analytics": "4.24.0",
- "@algolia/client-common": "4.24.0",
- "@algolia/client-personalization": "4.24.0",
- "@algolia/client-search": "4.24.0",
- "@algolia/logger-common": "4.24.0",
- "@algolia/logger-console": "4.24.0",
- "@algolia/recommend": "4.24.0",
- "@algolia/requester-browser-xhr": "4.24.0",
- "@algolia/requester-common": "4.24.0",
- "@algolia/requester-node-http": "4.24.0",
- "@algolia/transporter": "4.24.0"
+ "@algolia/client-abtesting": "5.1.0",
+ "@algolia/client-analytics": "5.1.0",
+ "@algolia/client-common": "5.1.0",
+ "@algolia/client-personalization": "5.1.0",
+ "@algolia/client-search": "5.1.0",
+ "@algolia/recommend": "5.1.0",
+ "@algolia/requester-browser-xhr": "5.1.0",
+ "@algolia/requester-node-http": "5.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/algoliasearch-helper": {
- "version": "3.22.3",
- "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz",
- "integrity": "sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA==",
+ "version": "3.22.4",
+ "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.4.tgz",
+ "integrity": "sha512-fvBCywguW9f+939S6awvRMstqMF1XXcd2qs1r1aGqL/PJ1go/DqN06tWmDVmhCDqBJanm++imletrQWf0G2S1g==",
"license": "MIT",
"dependencies": {
"@algolia/events": "^4.0.1"
@@ -6342,9 +6263,9 @@
"license": "MIT"
},
"node_modules/chart.js": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz",
- "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==",
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.4.tgz",
+ "integrity": "sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
@@ -6817,9 +6738,9 @@
}
},
"node_modules/core-js-compat": {
- "version": "3.38.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz",
- "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==",
+ "version": "3.38.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz",
+ "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8985,9 +8906,9 @@
"license": "BSD-3-Clause"
},
"node_modules/ignore": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
- "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9125,29 +9046,29 @@
}
},
"node_modules/instantsearch-ui-components": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/instantsearch-ui-components/-/instantsearch-ui-components-0.8.0.tgz",
- "integrity": "sha512-EzV7cR5+18sjmR6DMdv8yL9WuS2hUxrkqbByiLmHnJFbB4TZ4Q7oZDAn43bOItWZ2TxMK3GoxNbB/ZhWjsptPg==",
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/instantsearch-ui-components/-/instantsearch-ui-components-0.9.0.tgz",
+ "integrity": "sha512-ugQ+XdPx3i3Sxu+woRo6tPE0Fz/kWd4KblTUfZD1TZZBsm/8qFvcbg5dVBDvXX9v7ntoyugXCzC/XCZMzrSkig==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.1.2"
}
},
"node_modules/instantsearch.js": {
- "version": "4.73.4",
- "resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.73.4.tgz",
- "integrity": "sha512-QdvExJthRBXpRaX9lzey+2sqUIzlOZEpd8N5wZyLYYs6WjDHIwrNPOzmOv7VHLBBHGqZ6YkXoCoegj5zm9QI8g==",
+ "version": "4.74.0",
+ "resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.74.0.tgz",
+ "integrity": "sha512-IbKAvnQ03cxb1Ni1OpLv6Yuu1W7Cu1zGru77rvgzYyPsurknpjQHdBicszSZlKaK/zND7D5vhSNZoliiz9nuEQ==",
"license": "MIT",
"dependencies": {
"@algolia/events": "^4.0.1",
"@types/dom-speech-recognition": "^0.0.1",
- "@types/google.maps": "^3.45.3",
+ "@types/google.maps": "^3.55.12",
"@types/hogan.js": "^3.0.0",
"@types/qs": "^6.5.3",
- "algoliasearch-helper": "3.22.3",
+ "algoliasearch-helper": "3.22.4",
"hogan.js": "^3.0.2",
"htm": "^3.0.0",
- "instantsearch-ui-components": "0.8.0",
+ "instantsearch-ui-components": "0.9.0",
"preact": "^10.10.0",
"qs": "^6.5.1 < 6.10",
"search-insights": "^2.15.0"
@@ -11304,9 +11225,9 @@
}
},
"node_modules/npm-check-updates": {
- "version": "17.0.6",
- "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.0.6.tgz",
- "integrity": "sha512-KCiaJH1cfnh/RyzKiDNjNfXgcKFyQs550Uf1OF/Yzb8xO56w+RLpP/OKRUx23/GyP/mLYwEpOO65qjmVdh6j0A==",
+ "version": "17.1.0",
+ "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.0.tgz",
+ "integrity": "sha512-RcohCA/tdpxyPllBlYDkqGXFJQgTuEt0f2oPSL9s05pZ3hxYdleaUtvEcSxKl0XAg3ncBhVgLAxhXSjoryUU5Q==",
"license": "Apache-2.0",
"bin": {
"ncu": "build/cli.js",
@@ -12180,9 +12101,9 @@
}
},
"node_modules/postcss-selector-parser": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
- "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12819,9 +12740,9 @@
"license": "MIT"
},
"node_modules/sass": {
- "version": "1.77.8",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz",
- "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==",
+ "version": "1.77.6",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz",
+ "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12963,9 +12884,9 @@
}
},
"node_modules/semver": {
- "version": "7.6.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
- "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -15567,9 +15488,9 @@
}
},
"node_modules/zone.js": {
- "version": "0.14.10",
- "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz",
- "integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==",
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz",
+ "integrity": "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==",
"license": "MIT"
}
}
diff --git a/client/package.json b/client/package.json
index 63808ec1..b48bb592 100644
--- a/client/package.json
+++ b/client/package.json
@@ -10,33 +10,33 @@
},
"private": true,
"dependencies": {
- "@angular/animations": "^18.2.0",
- "@angular/cdk": "^18.2.0",
- "@angular/common": "^18.2.0",
- "@angular/compiler": "^18.2.0",
- "@angular/core": "^18.2.0",
- "@angular/forms": "^18.2.0",
- "@angular/localize": "^18.2.0",
- "@angular/material": "^18.2.0",
- "@angular/platform-browser": "^18.2.0",
- "@angular/platform-browser-dynamic": "^18.2.0",
- "@angular/router": "^18.2.0",
+ "@angular/animations": "^18.2.1",
+ "@angular/cdk": "^18.2.1",
+ "@angular/common": "^18.2.1",
+ "@angular/compiler": "^18.2.1",
+ "@angular/core": "^18.2.1",
+ "@angular/forms": "^18.2.1",
+ "@angular/localize": "^18.2.1",
+ "@angular/material": "^18.2.1",
+ "@angular/platform-browser": "^18.2.1",
+ "@angular/platform-browser-dynamic": "^18.2.1",
+ "@angular/router": "^18.2.1",
"@fortawesome/fontawesome-free": "^6.6.0",
"@ng-bootstrap/ng-bootstrap": "^17.0.0",
"@swimlane/ngx-charts": "^20.5.0",
"@tsparticles/angular": "^3.0.0",
"angular-auth-oidc-client": "^18.0.1",
"bootstrap": "^5.3.3",
- "chart.js": "^4.4.3",
+ "chart.js": "^4.4.4",
"chartjs-plugin-datalabels": "^2.2.0",
"classlist.js": "^1.1.20150312",
"date-fns": "^3.6.0",
"exceljs": "^4.4.0",
- "instantsearch.js": "^4.73.4",
+ "instantsearch.js": "^4.74.0",
"json-to-plain-text": "^1.1.4",
"jsonwebtoken": "^9.0.2",
"ng2-charts": "^6.0.1",
- "npm-check-updates": "^17.0.6",
+ "npm-check-updates": "^17.1.0",
"pace-js": "^1.2.4",
"primeflex": "^3.3.1",
"primeicons": "^7.0.0",
@@ -45,17 +45,17 @@
"subsink": "^1.0.2",
"typescript": "^5.5.4",
"web-animations-js": "^2.3.2",
- "zone.js": "^0.14.10"
+ "zone.js": "^0.15.0"
},
"devDependencies": {
- "@angular-devkit/build-angular": "^18.2.0",
- "@angular/cli": "^18.2.0",
- "@angular/compiler-cli": "^18.2.0",
+ "@angular-devkit/build-angular": "^18.2.1",
+ "@angular/cli": "^18.2.1",
+ "@angular/compiler-cli": "^18.2.1",
"@types/chart.js": "^2.9.41",
"@types/d3": "^7.4.3",
"@types/jasmine": "^5.1.4",
"@types/jquery": "^3.5.30",
- "@types/node": "^22.4.1",
+ "@types/node": "^22.5.0",
"jasmine-core": "^5.2.0"
}
}
diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index 8823790d..b11bb4bb 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -13,17 +13,19 @@ import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import { NotificationsComponent } from './common/components/notifications/notifications.component';
import { AuthGuard } from './core/auth/guards/auth.guard'
import { UnauthorizedComponent } from './common/components/unauthorized/unauthorized.component';
+import { NotActivatedComponent } from './common/components/notActivated/notActivated.component';
import { AppLayoutComponent } from './layout/components/app.layout.component';
+import { DoDConsentComponent } from './common/components/dod-consent/dod-consent.component';
const routerOptions: ExtraOptions = {
anchorScrolling: 'enabled'
};
const routes: Routes = [
- {
+ {
path: '', component: AppLayoutComponent,
- children: [
-
+ children:
+ [
{ path: 'admin-processing', canActivate: [AuthGuard], data: { guardType: 'admin' }, loadChildren: () => import('./pages/admin-processing/admin-processing.module').then(m => m.AdminProcessingModule) },
{ path: 'asset-processing', canActivate: [AuthGuard], loadChildren: () => import('./pages/asset-processing/asset-processing.module').then(m => m.AssetProcessingModule) },
{ path: 'consent', canActivate: [AuthGuard], loadChildren: () => import('./common/components/dod-consent/dod-consent.module').then(m => m.DoDConsentModule) },
@@ -35,6 +37,7 @@ const routes: Routes = [
]
},
{ path: 'unauthorized', component: UnauthorizedComponent },
+ { path: 'not-activated', component: NotActivatedComponent },
{ path: '**', redirectTo: 'consent' },
];
@NgModule({
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index cd651cfe..451c0fb0 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -31,9 +31,7 @@ export class AppComponent implements OnInit {
try {
await this.authService.initializeAuthentication();
this.userProfile = await this.authService.getUserData('cpat');
- } catch (error) {
- console.error('Authentication Error:', error);
- } finally {
+
const apiConfig = await this.sharedService.getApiConfig().toPromise();
if (apiConfig && typeof apiConfig === 'object' && 'classification' in apiConfig) {
const apiClassification = (apiConfig as { classification: string }).classification;
@@ -41,6 +39,8 @@ export class AppComponent implements OnInit {
} else {
console.error('Invalid API configuration response');
}
+ } catch (error) {
+ console.error('Authentication Error:', error);
}
}
}
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index 88842ef3..4ab540f0 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -24,6 +24,7 @@ import { AppComponent } from './app.component';
import { NgxParticlesModule } from "@tsparticles/angular";
import { NotFoundComponent } from './common/components/not-found/not-found.component';
import { UnauthorizedComponent } from './common/components/unauthorized/unauthorized.component';
+import { NotActivatedComponent } from './common/components/notActivated/notActivated.component';
import { ButtonModule } from 'primeng/button';
import { AvatarModule } from 'primeng/avatar';
import { MenuModule } from 'primeng/menu';
@@ -34,6 +35,7 @@ import { OverlayPanelModule } from 'primeng/overlaypanel';
import { RippleModule } from 'primeng/ripple';
import { SelectButtonModule } from 'primeng/selectbutton';
import { PrimeNGConfig } from 'primeng/api';
+
function getScopeStr(configId: string) {
const cpatScopePrefix = CPAT.Env.oauth.scopePrefix;
const stigmanScopePrefix = CPAT.Env.stigman.scopePrefix;
@@ -72,7 +74,8 @@ function getScopeStr(configId: string) {
declarations: [
AppComponent,
NotFoundComponent,
- UnauthorizedComponent
+ UnauthorizedComponent,
+ NotActivatedComponent,
],
imports: [
BrowserModule,
@@ -87,10 +90,10 @@ function getScopeStr(configId: string) {
config: [
{
configId: 'cpat',
- postLoginRoute: '/consent',
+ postLoginRoute: '/verify',
authority: CPAT.Env.oauth.authority,
- redirectUrl: window.location.origin + '/consent',
- postLogoutRedirectUri: window.location.origin + '/consent',
+ redirectUrl: window.location.origin + '/verify',
+ postLogoutRedirectUri: window.location.origin + '/verify',
clientId: CPAT.Env.oauth.clientId,
scope: getScopeStr('cpat'),
responseType: 'code',
@@ -105,8 +108,8 @@ function getScopeStr(configId: string) {
{
configId: 'stigman',
authority: CPAT.Env.oauth.authority,
- redirectUrl: window.location.origin + '/consent',
- postLogoutRedirectUri: window.location.origin + '/consent',
+ redirectUrl: window.location.origin + '/verify',
+ postLogoutRedirectUri: window.location.origin + '/verify',
clientId: CPAT.Env.stigman.clientId,
scope: getScopeStr('stigman'),
responseType: 'code',
diff --git a/client/src/app/common/components/dod-consent/dod-consent.component.ts b/client/src/app/common/components/dod-consent/dod-consent.component.ts
index bc208f32..e79cf822 100644
--- a/client/src/app/common/components/dod-consent/dod-consent.component.ts
+++ b/client/src/app/common/components/dod-consent/dod-consent.component.ts
@@ -36,7 +36,6 @@ export class DoDConsentComponent implements AfterViewInit {
consentOk() {
if (this.modalWindow) {
this.modalWindow.close();
- this.router.navigate(['/poam-processing']);
}
}
}
diff --git a/client/src/app/common/components/not-found/not-found.component.html b/client/src/app/common/components/not-found/not-found.component.html
index 1a3c20d1..69179759 100644
--- a/client/src/app/common/components/not-found/not-found.component.html
+++ b/client/src/app/common/components/not-found/not-found.component.html
@@ -189,7 +189,7 @@
{{invalidDataMessage}}