Merge branch 'develop' into feat/fe/connect-config

This commit is contained in:
Alex Holliday committed 2024-07-31 11:01:51 -07:00
commit 60b408dc19
19 files changed
+373 -98

No files matched your search

+2 -2
View File
@@ -2,11 +2,11 @@ language: "en-CA"
tone_instructions: "His palms are sweaty, knees weak, arms are heavy There’s vomit on his sweater already, mom’s spaghetti"
early_access: false
reviews:
profile: "assertive"
profile: "chill"
request_changes_workflow: false
high_level_summary: false
poem: false
review_status: true
review_status: false
auto_review:
enabled: true
drafts: false
+33
View File
@@ -0,0 +1,33 @@
.MuiButtonBase-root.button-rotate90 svg {
transition: transform 500ms ease;
}
.MuiButtonBase-root.button-rotate90:hover svg {
transform: rotate(90deg);
transform-origin: center;
}
.MuiButtonBase-root.button-rotate180 svg {
transition: transform 700ms ease;
}
.MuiButtonBase-root.button-rotate180:hover svg {
transform: rotate(180deg);
transform-origin: center;
}
.MuiButtonBase-root.button-slideLeft {
padding-left: 45px;
}
.MuiButtonBase-root.button-slideLeft svg {
position: absolute;
left: 15px;
transition: left 250ms cubic-bezier(0.65, 0, 0.076, 1);
}
.MuiButtonBase-root.button-slideLeft:hover svg {
left: 11px;
}
.MuiButtonBase-root.button-slideLeft:hover,
.MuiButtonBase-root.button-rotate180:hover,
.MuiButtonBase-root.button-rotate90:hover {
background-color: rgba(71, 84, 103, 0.08);
}
+19 -2
View File
@@ -1,5 +1,6 @@
import { Button as MuiButton } from "@mui/material";
import PropTypes from "prop-types";
import "./index.css";
const levelConfig = {
primary: {
@@ -48,11 +49,22 @@ const levelConfig = {
* <Button type="submit" level="error" label="Error" disabled sx={{marginTop: "1rem"}}/>
*/
const Button = ({ id, type, level, label, disabled, img, onClick, sx }) => {
const Button = ({
id,
animate,
type,
level,
label,
disabled,
img,
onClick,
sx,
}) => {
const { variant, color } = levelConfig[level];
return (
<MuiButton
id={id}
className={`button-${animate}`}
type={type}
variant={variant}
color={color}
@@ -60,15 +72,20 @@ const Button = ({ id, type, level, label, disabled, img, onClick, sx }) => {
onClick={onClick}
disableRipple
sx={{
lineHeight: 1,
boxShadow: "none",
textTransform: "none",
"&:focus": {
outline: "none",
},
"&:hover": {
boxShadow: "none",
},
...sx,
}}
>
{img && img}
{label}
<span>{label}</span>
</MuiButton>
);
};
@@ -72,10 +72,15 @@ const ButtonSpinner = ({
loading={isLoading}
disableRipple
sx={{
boxShadow: "none",
textTransform: "none",
"&:focus": {
outline: "none",
},
"&:hover": {
boxShadow: "none",
transition: "none"
},
...sx,
}}
>
@@ -38,6 +38,7 @@
padding-bottom: 60px;
border: 1px solid var(--env-var-color-16);
border-radius: var(--env-var-radius-1);
background-color: var(--env-var-color-8);
}
.configure-monitor .config-box .MuiBox-root,
.configure-monitor .config-box .MuiStack-root {
@@ -74,4 +75,4 @@
body:has(.configure-monitor) .select-dropdown .MuiMenuItem-root,
.configure-monitor .select-wrapper .select-component > .MuiSelect-select {
text-transform: lowercase;
}
}
@@ -122,6 +122,7 @@ const Configure = () => {
<Button
level="tertiary"
label="Back"
animate="slideLeft"
img={<WestRoundedIcon />}
onClick={() => navigate(-1)}
sx={{
@@ -129,7 +130,8 @@ const Configure = () => {
mb: theme.gap.medium,
px: theme.gap.ml,
"& svg.MuiSvgIcon-root": {
pr: theme.gap.small,
mr: theme.gap.small,
fill: theme.palette.otherColors.slateGray,
},
}}
/>
@@ -166,13 +168,14 @@ const Configure = () => {
<Button
level="tertiary"
label="Pause"
animate="rotate180"
img={<PauseCircleOutlineIcon />}
sx={{
backgroundColor: "#f4f4f4",
pl: theme.gap.small,
pr: theme.gap.medium,
"& svg": {
pr: theme.gap.xs,
mr: theme.gap.xs,
},
}}
/>
@@ -48,6 +48,7 @@
border-radius: var(--env-var-radius-1);
flex-direction: row;
gap: var(--env-var-spacing-4);
background-color: var(--env-var-color-8);
}
.create-monitor .config-box .MuiBox-root,
.create-monitor .config-box .MuiStack-root {
@@ -145,6 +145,7 @@ const CreateMonitor = () => {
<Button
level="tertiary"
label="Back"
animate="slideLeft"
img={<WestRoundedIcon />}
onClick={() => navigate("/monitors")}
sx={{
@@ -152,7 +153,8 @@ const CreateMonitor = () => {
mb: theme.gap.medium,
px: theme.gap.ml,
"& svg.MuiSvgIcon-root": {
pr: theme.gap.small,
mr: theme.gap.small,
fill: theme.palette.otherColors.slateGray,
},
}}
/>
+7 -2
View File
@@ -37,13 +37,18 @@
.monitor-details .stat-box {
flex: 1;
min-width: 100px;
border: solid 1px var(--env-var-color-4);
border: solid 1px;
border-radius: var(--env-var-radius-1);
padding: var(--env-var-spacing-1-plus) var(--env-var-spacing-2);
background-color: var(--env-var-color-8);
}
.monitor-details .stat-box:not(:first-of-type) {
margin-left: var(--env-var-spacing-2);
}
.monitor-details .stat-box h6.MuiTypography-root {
margin-bottom: var(--env-var-spacing-1);
}
}
.monitor-details button.MuiButtonBase-root,
.monitor-details .stat-box {
border-color: var(--env-var-color-16);
}
+18 -6
View File
@@ -147,6 +147,7 @@ const DetailsPage = () => {
<Button
level="tertiary"
label="Back to Monitors"
animate="slideLeft"
img={<WestRoundedIcon />}
onClick={() => navigate("/monitors")}
sx={{
@@ -154,7 +155,8 @@ const DetailsPage = () => {
mb: theme.gap.medium,
px: theme.gap.ml,
"& svg.MuiSvgIcon-root": {
pr: theme.gap.small,
mr: theme.gap.small,
fill: theme.palette.otherColors.slateGray,
},
}}
/>
@@ -184,15 +186,16 @@ const DetailsPage = () => {
<Button
level="tertiary"
label="Configure"
animate="rotate90"
img={<SettingsIcon />}
onClick={() => navigate(`/monitors/configure/${monitorId}`)}
sx={{
ml: "auto",
alignSelf: "flex-end",
backgroundColor: "#f4f4f4",
px: theme.gap.ml,
px: theme.gap.medium,
"& svg": {
pr: theme.gap.xs,
mr: "6px",
},
}}
/>
@@ -222,19 +225,28 @@ const DetailsPage = () => {
level="secondary"
label="Day"
onClick={() => setFilter("day")}
sx={{ backgroundColor: filter === "day" && "#f4f4f4" }}
sx={{
backgroundColor:
filter === "day" && theme.palette.otherColors.fillGray,
}}
/>
<Button
level="secondary"
label="Week"
onClick={() => setFilter("week")}
sx={{ backgroundColor: filter === "week" && "#f4f4f4" }}
sx={{
backgroundColor:
filter === "week" && theme.palette.otherColors.fillGray,
}}
/>
<Button
level="secondary"
label="Month"
onClick={() => setFilter("month")}
sx={{ backgroundColor: filter === "month" && "#f4f4f4" }}
sx={{
backgroundColor:
filter === "month" && theme.palette.otherColors.fillGray,
}}
/>
</ButtonGroup>
</Stack>
+38 -12
View File
@@ -6,24 +6,57 @@
![](https://img.shields.io/github/issues-pr/bluewave-labs/bluewave-uptime)
![](https://img.shields.io/github/issues/bluewave-labs/bluewave-uptime)
<h1 align="center"><a href="https://bluewavelabs.ca" target="_blank">BlueWave Uptime</a></h1>
<p align="center"><strong>An open source server monitoring application</strong></p>
![bluewave-uptime-screenshot](https://github.com/user-attachments/assets/765bf060-e734-45e6-bd00-2a2eb37c9c02)
BlueWave Uptime is an open source server monitoring application used to track the operational status and performance of servers and websites. It regularly checks whether a server/website is accessible and performs optimally, providing real-time alerts and reports on the monitored services' availability, downtime, and response time.
## Features
* Completely open source, deployable on your servers
* Website monitoring
* Port monitoring
* Ping monitoring
* Incidents at a glance
* Status pages
* Page speed monitoring (in the works)
**Roadmap:**
* 3rd party integrations
* Domain monitoring
* SSL monitoring
## Tech stack
* [ReactJs](https://react.dev/)
* [MUI (React framework)](https://mui.com/)
* [Node.js](https://nodejs.org/en)
* [MongoDB](https://mongodb.com)
## Contributing
You are welcome to provide contributions to the project. It uses React on the FE, and Nodejs and MongoDB on the BE, hence if you are comfortable with working with those technologies, you are encouraged to send your PRs. Please read [Contributor's guideline](https://github.com/bluewave-labs/bluewave-uptime/blob/master/CONTRIBUTING.md). Once you start contributing, we can also add you to our weekly team calls (every Thursday).
We love contributors. Here's how you can contribute:
Note that We have a Figma file that includes:
* Check [Contributor's guideline](https://github.com/bluewave-labs/bluewave-uptime/blob/master/CONTRIBUTING.md).
* Have a look at our Figma designs [here](https://www.figma.com/design/RPSfaw66HjzSwzntKcgDUV/Uptime-Genie?node-id=0-1&t=WqOFv9jqNTFGItpL-1). We encourage you to copy to your own Figma page, then work on it as it is read-only.
* Open an issue if you believe you've encountered a bug
* Make a pull request to add new features/make quality-of-life improvements/fix bugs.
- All the dashboard elements and components
- The design guideline for the app
<a href="https://github.com/bluewave-labs/bluewave-uptime/graphs/contributors">
<img src="https://contrib.rocks/image?repo=bluewave-labs/bluewave-uptime" />
</a>
Made with [contrib.rocks](https://contrib.rocks).
![Alt](https://repobeats.axiom.co/api/embed/c35d999c82dbb31e967427ea4166c14da4172e73.svg "Repobeats analytics image")
You can see the designs [here](https://www.figma.com/design/RPSfaw66HjzSwzntKcgDUV/Uptime-Genie?node-id=0-1&t=WqOFv9jqNTFGItpL-1). Since it is read-only, we encourage you to copy to your own Figma page, then work on it.
## Getting Started
@@ -2067,10 +2100,3 @@ const myRoute = async(req, res, next) => {
Errors should not be handled at the controller level and should be left to the middleware to handle.
## Contributors
<a href="https://github.com/bluewave-labs/bluewave-uptime/graphs/contributors">
<img src="https://contrib.rocks/image?repo=bluewave-labs/bluewave-uptime" />
</a>
Made with [contrib.rocks](https://contrib.rocks).
+12 -6
View File
@@ -27,7 +27,8 @@ const createAlert = async (req, res, next) => {
await createAlertBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
error.service = SERVICE_NAME;
next(error);
return;
@@ -58,7 +59,8 @@ const getAlertsByUserId = async (req, res, next) => {
await getAlertsByUserIdParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
error.service = SERVICE_NAME;
next(error);
return;
@@ -82,7 +84,8 @@ const getAlertsByMonitorId = async (req, res, next) => {
await getAlertsByMonitorIdParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
error.service = SERVICE_NAME;
next(error);
return;
@@ -106,7 +109,8 @@ const getAlertById = async (req, res, next) => {
await getAlertByIdParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
error.service = SERVICE_NAME;
next(error);
return;
@@ -132,7 +136,8 @@ const editAlert = async (req, res, next) => {
} catch (error) {
console.log(error);
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
error.service = SERVICE_NAME;
next(error);
return;
@@ -156,7 +161,8 @@ const deleteAlert = async (req, res, next) => {
await deleteAlertParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
error.service = SERVICE_NAME;
next(error);
return;
+86 -26
View File
@@ -54,7 +54,8 @@ const registerController = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -115,14 +116,20 @@ const registerController = async (req, res, next) => {
*/
const loginController = async (req, res, next) => {
try {
// Validate input
await loginValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
// Check if user exists
const user = await req.db.getUserByEmail(req, res);
// Compare password
const match = await user.comparePassword(req.body.password);
if (match !== true) {
throw new Error(errorMessages.AUTH_INCORRECT_PASSWORD);
@@ -157,7 +164,8 @@ const userEditController = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -216,8 +224,18 @@ const inviteController = async (req, res, next) => {
// Only admins can invite
const token = getTokenFromHeaders(req.headers);
const { role, firstname } = jwt.decode(token);
await inviteRoleValidation.validateAsync({ roles: role });
await inviteBodyValidation.validateAsync(req.body);
try {
await inviteRoleValidation.validateAsync({ roles: role });
await inviteBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
const inviteToken = await req.db.requestInviteToken(req, res);
req.emailService.buildAndSendEmail(
"employeeActivationTemplate",
@@ -242,6 +260,16 @@ const inviteController = async (req, res, next) => {
const inviteVerifyController = async (req, res, next) => {
try {
await inviteVerifciationBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const invite = await req.db.getInviteToken(req, res);
res
@@ -289,6 +317,16 @@ const checkAdminController = async (req, res) => {
const recoveryRequestController = async (req, res, next) => {
try {
await recoveryValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const user = await req.db.getUserByEmail(req, res);
if (user) {
const recoveryToken = await req.db.requestRecoveryToken(req, res);
@@ -328,6 +366,16 @@ const recoveryRequestController = async (req, res, next) => {
const validateRecoveryTokenController = async (req, res, next) => {
try {
await recoveryTokenValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
await req.db.validateRecoveryToken(req, res);
// TODO Redirect user to reset password after validating token
return res.status(200).json({
@@ -354,6 +402,15 @@ const validateRecoveryTokenController = async (req, res, next) => {
const resetPasswordController = async (req, res, next) => {
try {
await newPasswordValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const user = await req.db.resetPassword(req, res);
const token = issueToken(user._doc);
res.status(200).json({
@@ -392,9 +449,18 @@ const deleteUserController = async (req, res, next) => {
};
// Validate user
await deleteUserParamValidation.validateAsync(
decodedTokenCastedAsRequest.body
);
try {
await deleteUserParamValidation.validateAsync(
decodedTokenCastedAsRequest.body
);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
// Check if the user exists
const user = await req.db.getUserByEmail(decodedTokenCastedAsRequest);
@@ -408,25 +474,19 @@ const deleteUserController = async (req, res, next) => {
);
if (monitors) {
// 2. Delete jobs associated with each monitor
for (const monitor of monitors) {
await req.jobQueue.deleteJob(monitor);
}
//2. Remove all jobs, delete checks and alerts
await Promise.all(
monitors.map(async (monitor) => {
await req.jobQueue.deleteJob(monitor);
await req.db.deleteChecks(monitor._id);
await req.db.deleteAlertByMonitorId(monitor._id);
})
);
// 3. Delete all checks associated with each monitor
for (const monitor of monitors) {
await req.db.deleteChecks(monitor._id);
}
// 4. Delete all alerts associated with each monitor
for (const monitor of monitors) {
await req.db.deleteAlertByMonitorId(monitor._id);
}
// 5. Delete each monitor
// 3. Delete each monitor
await req.db.deleteMonitorsByUserId(user._id);
// 6. Delete the user by id
// 4. Delete the user by id
await req.db.deleteUser(decodedTokenCastedAsRequest);
return res.status(200).json({
+11 -10
View File
@@ -14,7 +14,8 @@ const createCheck = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -37,7 +38,8 @@ const getChecks = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -59,20 +61,19 @@ const deleteChecks = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const deletedCount = await req.db.deleteChecks(req.params.monitorId);
return res
.status(200)
.json({
success: true,
msg: successMessages.CHECK_DELETE,
data: { deletedCount },
});
return res.status(200).json({
success: true,
msg: successMessages.CHECK_DELETE,
data: { deletedCount },
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -15,7 +15,8 @@ const createMaintenanceWindow = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -48,7 +49,15 @@ const getMaintenanceWindowsByUserId = async (req, res, next) => {
await getMaintenanceWindowsByUserIdParamValidation.validateAsync(
req.params
);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const maintenanceWindows = await req.db.getMaintenanceWindowsByUserId(
req.params.userId
);
@@ -69,7 +78,16 @@ const getMaintenanceWindowsByMonitorId = async (req, res, next) => {
await getMaintenanceWindowsByMonitorIdParamValidation.validateAsync(
req.params
);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const maintenanceWindows = await req.db.getMaintenanceWindowsByMonitorId(
req.params.monitorId
);
+24 -8
View File
@@ -9,7 +9,6 @@ const {
const SERVICE_NAME = "monitorController";
const { errorMessages, successMessages } = require("../utils/messages");
const { error } = require("winston");
/**
* Returns all monitors
@@ -47,7 +46,8 @@ const getMonitorById = async (req, res, next) => {
await getMonitorByIdQueryValidation.validateAsync(req.query);
} catch (error) {
error.status = 422;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -83,6 +83,16 @@ const getMonitorsByUserId = async (req, res, next) => {
try {
await getMonitorsByUserIdValidation.validateAsync(req.params);
await getMonitorsByUserIdQueryValidation.validateAsync(req.query);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const userId = req.params.userId;
const monitors = await req.db.getMonitorsByUserId(req, res);
@@ -112,7 +122,9 @@ const createMonitor = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
@@ -143,21 +155,24 @@ const createMonitor = async (req, res, next) => {
const deleteMonitor = async (req, res, next) => {
try {
await getMonitorByIdValidation.validateAsync(req.params);
await getMonitorByIdParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const monitor = await req.db.deleteMonitor(req, res, next);
// Delete associated checks and alerts
// Delete associated checks,alerts,and notifications
await req.jobQueue.deleteJob(monitor);
await req.db.deleteChecks(monitor._id);
await req.db.deleteAlertByMonitorId(monitor._id);
await req.db.deleteNotificationsByMonitorId(monitor._id);
/**
* TODO
* We should remove all checks and alerts associated with this monitor
@@ -195,12 +210,13 @@ const deleteAllMonitors = async (req, res) => {
*/
const editMonitor = async (req, res, next) => {
try {
await getMonitorByIdValidation.validateAsync(req.params);
await getMonitorByIdParamValidation.validateAsync(req.params);
await editMonitorBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
+28 -14
View File
@@ -1,4 +1,3 @@
const PageSpeedCheck = require("../models/PageSpeedCheck");
const PageSpeedService = require("../service/pageSpeedService");
const { successMessages } = require("../utils/messages");
const pageSpeedService = new PageSpeedService();
@@ -22,12 +21,19 @@ const getPageSpeedChecks = async (req, res, next) => {
try {
// Validate monitorId parameter
await getPageSpeedCheckParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
return res.status(200).json({ msg: "Hit getPageSpeedChecks" });
} catch (error) {
if (error.isJoi) {
return res.status(400).json({ error: error.details[0].message });
}
error.service = SERVICE_NAME;
next(error);
}
};
@@ -42,12 +48,18 @@ const getPageSpeedChecks = async (req, res, next) => {
*/
const createPageSpeedCheck = async (req, res, next) => {
try {
// Validate monitorId parameter
await createPageSpeedCheckParamValidation.validateAsync(req.params);
// Validate request body
await createPageSpeedCheckBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const { monitorId } = req.params;
const { url } = req.body;
@@ -74,9 +86,6 @@ const createPageSpeedCheck = async (req, res, next) => {
data: newPageSpeedCheck,
});
} catch (error) {
if (error.isJoi) {
return res.status(400).json({ error: error.details[0].message });
}
error.service = SERVICE_NAME;
next(error);
}
@@ -94,12 +103,17 @@ const deletePageSpeedCheck = async (req, res, next) => {
try {
// Validate monitorId parameter
await deletePageSpeedCheckParamValidation.validateAsync(req.params);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
return res.status(200).json({ msg: "Hit deletePageSpeedCheck" });
} catch (error) {
if (error.isJoi) {
return res.status(400).json({ error: error.details[0].message });
}
error.service = SERVICE_NAME;
next(error);
}
+9 -4
View File
@@ -65,8 +65,6 @@ const {
getAllMonitors,
getMonitorById,
getMonitorsByUserId,
getMonitorByIdForIncidents,
getMonitorsByUserIdForIncidents,
createMonitor,
deleteMonitor,
deleteAllMonitors,
@@ -120,6 +118,12 @@ const {
deleteMaintenanceWindowByUserId,
} = require("./modules/maintenaceWindowModule");
const {
createNotification,
getNotificationsByMonitorId,
deleteNotificationsByMonitorId,
} = require("./modules/notificationModule");
module.exports = {
connect,
insertUser,
@@ -136,8 +140,6 @@ module.exports = {
getAllMonitors,
getMonitorById,
getMonitorsByUserId,
getMonitorByIdForIncidents,
getMonitorsByUserIdForIncidents,
createMonitor,
deleteMonitor,
deleteAllMonitors,
@@ -162,4 +164,7 @@ module.exports = {
deleteMaintenaceWindowById,
deleteMaintenanceWindowByMonitorId,
deleteMaintenanceWindowByUserId,
createNotification,
getNotificationsByMonitorId,
deleteNotificationsByMonitorId,
};
@@ -0,0 +1,50 @@
const Notification = require("../../../models/Notification");
/**
* Creates a new notification.
* @param {Object} notificationData - The data for the new notification.
* @param {mongoose.Types.ObjectId} notificationData.monitorId - The ID of the monitor.
* @param {string} notificationData.type - The type of the notification (e.g., "email", "sms").
* @param {string} [notificationData.address] - The address for the notification (if applicable).
* @param {string} [notificationData.phone] - The phone number for the notification (if applicable).
* @returns {Promise<Object>} The created notification.
* @throws Will throw an error if the notification cannot be created.
*/
const createNotification = async (notificationData) => {
try {
const notification = await new Notification({ ...notificationData }).save();
return notification;
} catch (error) {
throw error;
}
};
/**
* Retrieves notifications by monitor ID.
* @param {mongoose.Types.ObjectId} monitorId - The ID of the monitor.
* @returns {Promise<Array<Object>>} An array of notifications.
* @throws Will throw an error if the notifications cannot be retrieved.
*/
const getNotificationsByMonitorId = async (monitorId) => {
try {
const notifications = await Notification.find({ monitorId });
return notifications;
} catch (error) {
throw error;
}
};
const deleteNotificationsByMonitorId = async (monitorId) => {
try {
const result = await Notification.deleteMany({ monitorId });
return result.deletedCount;
} catch (error) {
throw error;
}
};
module.exports = {
createNotification,
getNotificationsByMonitorId,
deleteNotificationsByMonitorId,
};