diff --git a/Client/src/App.jsx b/Client/src/App.jsx index 8fb4bf932..d6fca146f 100644 --- a/Client/src/App.jsx +++ b/Client/src/App.jsx @@ -71,7 +71,7 @@ function App() { element={} /> } /> diff --git a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js index ac3ce1d6f..a8b1ea737 100644 --- a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js +++ b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js @@ -164,6 +164,44 @@ export const deleteMonitorChecksByTeamId = createAsyncThunk( } } ); +export const addDemoMonitors = createAsyncThunk( + "monitors/addDemoMonitors", + async (data, thunkApi) => { + try { + const { authToken } = data; + const res = await networkService.addDemoMonitors(authToken); + return res.data; + } catch (error) { + if (error.response && error.response.data) { + return thunkApi.rejectWithValue(error.response.data); + } + const payload = { + status: false, + msg: error.message ? error.message : "Unknown error", + }; + return thunkApi.rejectWithValue(payload); + } + } +); +export const deleteAllMonitors = createAsyncThunk( + "monitors/deleteAllMonitors", + async (data, thunkApi) => { + try { + const { authToken } = data; + const res = await networkService.deleteAllMonitors(authToken); + return res.data; + } catch (error) { + if (error.response && error.response.data) { + return thunkApi.rejectWithValue(error.response.data); + } + const payload = { + status: false, + msg: error.message ? error.message : "Unknown error", + }; + return thunkApi.rejectWithValue(payload); + } + } +); const uptimeMonitorsSlice = createSlice({ name: "uptimeMonitors", @@ -306,6 +344,42 @@ const uptimeMonitorsSlice = createSlice({ state.msg = action.payload ? action.payload.msg : "Failed to pause uptime monitor"; + }) + // ***************************************************** + // Add Demo Monitors + // ***************************************************** + .addCase(addDemoMonitors.pending, (state) => { + state.isLoading = true; + }) + .addCase(addDemoMonitors.fulfilled, (state, action) => { + state.isLoading = false; + state.success = action.payload.success; + state.msg = action.payload.msg; + }) + .addCase(addDemoMonitors.rejected, (state, action) => { + state.isLoading = false; + state.success = false; + state.msg = action.payload + ? action.payload.msg + : "Failed to add demo uptime monitors"; + }) + // ***************************************************** + // Delete all Monitors + // ***************************************************** + .addCase(deleteAllMonitors.pending, (state) => { + state.isLoading = true; + }) + .addCase(deleteAllMonitors.fulfilled, (state, action) => { + state.isLoading = false; + state.success = action.payload.success; + state.msg = action.payload.msg; + }) + .addCase(deleteAllMonitors.rejected, (state, action) => { + state.isLoading = false; + state.success = false; + state.msg = action.payload + ? action.payload.msg + : "Failed to delete all monitors"; }); }, }); diff --git a/Client/src/Pages/Incidents/index.jsx b/Client/src/Pages/Incidents/index.jsx index c86cac543..8bd2928cb 100644 --- a/Client/src/Pages/Incidents/index.jsx +++ b/Client/src/Pages/Incidents/index.jsx @@ -1,6 +1,8 @@ import { useState, useEffect } from "react"; import { useSelector } from "react-redux"; import { ButtonGroup, Stack, Typography, Button } from "@mui/material"; +import { useParams } from "react-router-dom"; + import { networkService } from "../../main"; import { useTheme } from "@emotion/react"; import Select from "../../Components/Inputs/Select"; @@ -11,6 +13,7 @@ import SkeletonLayout from "./skeleton"; const Incidents = () => { const theme = useTheme(); const authState = useSelector((state) => state.auth); + const { monitorId } = useParams(); const [monitors, setMonitors] = useState({}); const [selectedMonitor, setSelectedMonitor] = useState("0"); @@ -40,6 +43,7 @@ const Incidents = () => { return acc; }, {}); setMonitors(monitorLookup); + monitorId !== undefined && setSelectedMonitor(monitorId); } setLoading(false); }; diff --git a/Client/src/Pages/Monitors/Home/actionsMenu.jsx b/Client/src/Pages/Monitors/Home/actionsMenu.jsx index 7f2eb0d97..45c358a6c 100644 --- a/Client/src/Pages/Monitors/Home/actionsMenu.jsx +++ b/Client/src/Pages/Monitors/Home/actionsMenu.jsx @@ -125,7 +125,14 @@ const ActionsMenu = ({ monitor, isAdmin, updateCallback }) => { Details {/* TODO - pass monitor id to Incidents page */} - Incidents + { + e.stopPropagation(); + navigate(`/incidents/${actions.id}`); + }} + > + Incidents + {isAdmin && ( { @@ -137,14 +144,16 @@ const ActionsMenu = ({ monitor, isAdmin, updateCallback }) => { Configure )} - { - e.stopPropagation(); - navigate(`/monitors/create/${actions.id}`); - }} - > - Clone - + {isAdmin && ( + { + e.stopPropagation(); + navigate(`/monitors/create/${actions.id}`); + }} + > + Clone + + )} {isAdmin && ( { diff --git a/Client/src/Pages/Monitors/utils.jsx b/Client/src/Pages/Monitors/utils.jsx index ede5baec1..c6f0a8476 100644 --- a/Client/src/Pages/Monitors/utils.jsx +++ b/Client/src/Pages/Monitors/utils.jsx @@ -20,6 +20,12 @@ const useUtils = () => { down: "Your site is down.", paused: "Pending...", }; + + const pagespeedStatusMsg = { + up: "Live (collecting data)", + down: "Inactive", + paused: "Paused", + }; const statusStyles = { up: { backgroundColor: theme.palette.success.bg, @@ -51,6 +57,7 @@ const useUtils = () => { determineState, statusColor, statusMsg, + pagespeedStatusMsg, statusStyles, }; }; diff --git a/Client/src/Pages/PageSpeed/Configure/index.jsx b/Client/src/Pages/PageSpeed/Configure/index.jsx index 005583f2c..6ac2f2ba6 100644 --- a/Client/src/Pages/PageSpeed/Configure/index.jsx +++ b/Client/src/Pages/PageSpeed/Configure/index.jsx @@ -23,6 +23,7 @@ import LoadingButton from "@mui/lab/LoadingButton"; import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded"; import SkeletonLayout from "./skeleton"; import "./index.css"; +import useUtils from "../../Monitors/utils"; const PageSpeedConfigure = () => { const theme = useTheme(); @@ -34,6 +35,7 @@ const PageSpeedConfigure = () => { const { monitorId } = useParams(); const [monitor, setMonitor] = useState({}); const [errors, setErrors] = useState({}); + const { determineState, statusColor } = useUtils(); const frequencies = [ { _id: 3, name: "3 minutes" }, @@ -147,13 +149,7 @@ const PageSpeedConfigure = () => { gap={theme.spacing(12)} > - + { - Your pagespeed monitor is {monitor?.status ? "live" : "down"}. + Your pagespeed monitor is {determineState(monitor)}. diff --git a/Client/src/Pages/PageSpeed/Details/index.jsx b/Client/src/Pages/PageSpeed/Details/index.jsx index c821c27d7..2118f4197 100644 --- a/Client/src/Pages/PageSpeed/Details/index.jsx +++ b/Client/src/Pages/PageSpeed/Details/index.jsx @@ -7,7 +7,6 @@ import { Tooltip, Typography, } from "@mui/material"; -import { useDrawingArea } from "@mui/x-charts"; import { useEffect, useState } from "react"; import { useTheme } from "@emotion/react"; import { useNavigate, useParams } from "react-router-dom"; @@ -39,6 +38,7 @@ const PageSpeedDetails = () => { const [audits, setAudits] = useState({}); const { monitorId } = useParams(); const { authToken } = useSelector((state) => state.auth); + const { determineState, statusColor, pagespeedStatusMsg } = useUtils(); useEffect(() => { const fetchMonitor = async () => { diff --git a/Client/src/Pages/PageSpeed/card.jsx b/Client/src/Pages/PageSpeed/card.jsx index 22406d714..800036012 100644 --- a/Client/src/Pages/PageSpeed/card.jsx +++ b/Client/src/Pages/PageSpeed/card.jsx @@ -5,12 +5,14 @@ import { StatusLabel } from "../../Components/Label"; import { Box, Grid, Stack, Typography } from "@mui/material"; import { useNavigate } from "react-router"; import { useTheme } from "@emotion/react"; +import useUtils from "../Monitors/utils"; import PropTypes from "prop-types"; -const Card = ({ data }) => { +const Card = ({ monitor }) => { + const { determineState, pagespeedStatusMsg } = useUtils(); const theme = useTheme(); const navigate = useNavigate(); - + const monitorState = determineState(monitor); return ( { direction="row" gap={theme.spacing(6)} p={theme.spacing(8)} - onClick={() => navigate(`/pagespeed/${data._id}`)} + onClick={() => navigate(`/pagespeed/${monitor._id}`)} border={1} borderColor={theme.palette.border.light} borderRadius={theme.shape.borderRadius} @@ -46,23 +48,24 @@ const Card = ({ data }) => { mb={theme.spacing(2)} color={theme.palette.primary.main} > - {data.name} + {monitor.name} - {data.url.replace(/^https?:\/\//, "")} + {monitor.url.replace(/^https?:\/\//, "")} Last checked:{" "} - {formatDate(getLastChecked(data.checks, false))}{" "} + {formatDate(getLastChecked(monitor.checks, false))}{" "} - ({formatDurationRounded(getLastChecked(data.checks))} ago) + ({formatDurationRounded(getLastChecked(monitor.checks))} ago) @@ -72,7 +75,7 @@ const Card = ({ data }) => { }; Card.propTypes = { - data: PropTypes.object.isRequired, + monitor: PropTypes.object.isRequired, }; export default Card; diff --git a/Client/src/Pages/PageSpeed/index.jsx b/Client/src/Pages/PageSpeed/index.jsx index ba65bf436..738a5f3da 100644 --- a/Client/src/Pages/PageSpeed/index.jsx +++ b/Client/src/Pages/PageSpeed/index.jsx @@ -74,7 +74,7 @@ const PageSpeed = ({ isAdmin }) => { {monitorsSummary?.monitors?.map((monitor) => ( - + ))} diff --git a/Client/src/Pages/Settings/index.jsx b/Client/src/Pages/Settings/index.jsx index d1f15ea8c..cd00f440f 100644 --- a/Client/src/Pages/Settings/index.jsx +++ b/Client/src/Pages/Settings/index.jsx @@ -1,5 +1,5 @@ import { useTheme } from "@emotion/react"; -import { Box, Button, Stack, styled, Typography } from "@mui/material"; +import { Box, Stack, styled, Typography } from "@mui/material"; import Field from "../../Components/Inputs/Field"; import Link from "../../Components/Link"; import Select from "../../Components/Inputs/Select"; @@ -7,7 +7,11 @@ import { logger } from "../../Utils/Logger"; import "./index.css"; import { useDispatch, useSelector } from "react-redux"; import { createToast } from "../../Utils/toastUtils"; -import { deleteMonitorChecksByTeamId } from "../../Features/UptimeMonitors/uptimeMonitorsSlice"; +import { + deleteMonitorChecksByTeamId, + addDemoMonitors, + deleteAllMonitors, +} from "../../Features/UptimeMonitors/uptimeMonitorsSlice"; import PropTypes from "prop-types"; import LoadingButton from "@mui/lab/LoadingButton"; const Settings = ({ isAdmin }) => { @@ -36,6 +40,34 @@ const Settings = ({ isAdmin }) => { } }; + const handleInsertDemoMonitors = async () => { + try { + const action = await dispatch(addDemoMonitors({ authToken })); + if (addDemoMonitors.fulfilled.match(action)) { + createToast({ body: "Successfully added demo monitors" }); + } else { + createToast({ body: "Failed to add demo monitors" }); + } + } catch (error) { + logger.error(error); + createToast({ Body: "Failed to add demo monitors" }); + } + }; + + const handleDeleteAllMonitors = async () => { + try { + const action = await dispatch(deleteAllMonitors({ authToken })); + if (deleteAllMonitors.fulfilled.match(action)) { + createToast({ body: "Successfully deleted all monitors" }); + } else { + createToast({ body: "Failed to add demo monitors" }); + } + } catch (error) { + logger.error(error); + createToast({ Body: "Failed to delete all monitors" }); + } + }; + const ConfigBox = styled("div")({ display: "flex", flexDirection: "row", @@ -140,6 +172,42 @@ const Settings = ({ isAdmin }) => { )} + {isAdmin && ( + + + Demo Monitors + + Here you can add and remove demo monitors + + + + + Add demo monitors + + Add demo monitors + + + + Remove all monitors + + Remove all monitors + + + + + )} About diff --git a/Client/src/Utils/NetworkService.js b/Client/src/Utils/NetworkService.js index e4b7be526..a9d93b301 100644 --- a/Client/src/Utils/NetworkService.js +++ b/Client/src/Utils/NetworkService.js @@ -274,6 +274,46 @@ class NetworkService { ); } + /** + * ************************************ + * Adds demo monitors + * ************************************ + * + * @async + * @param {string} authToken - The authorization token to be used in the request header. + * @returns {Promise} The response from the axios POST request. + */ + async addDemoMonitors(authToken) { + return this.axiosInstance.post( + `/monitors/demo`, + {}, + { + headers: { + Authorization: `Bearer ${authToken}`, + "Content-Type": "application/json", + }, + } + ); + } + + /** + * ************************************ + * Deletes all monitors for a team by team ID + * ************************************ + * + * @async + * @param {string} authToken - The authorization token to be used in the request header. + * @returns {Promise} The response from the axios DELETE request. + */ + async deleteAllMonitors(authToken) { + return this.axiosInstance.delete(`/monitors/`, { + headers: { + Authorization: `Bearer ${authToken}`, + "Content-Type": "application/json", + }, + }); + } + /** * ************************************ * Gets the certificate expiry for a monitor diff --git a/Client/src/assets/data/hostnames.json b/Client/src/assets/data/hostnames.json deleted file mode 100644 index b66818c3a..000000000 --- a/Client/src/assets/data/hostnames.json +++ /dev/null @@ -1,1290 +0,0 @@ -[ - { - "Company Name": "0to255", - "Company Link ": "https://0to255.com" - }, - { - "Company Name": "10015.io", - "Company Link ": "https://10015.io" - }, - { - "Company Name": "3DIcons", - "Company Link ": "https://3dicons.co" - }, - { - "Company Name": "About.me", - "Company Link ": "https://about.me" - }, - { - "Company Name": "Alias", - "Company Link ": "https://alias.co" - }, - { - "Company Name": "All About Berlin", - "Company Link ": "https://allaboutberlin.com" - }, - { - "Company Name": "All Acronyms", - "Company Link ": "https://allacronyms.com" - }, - { - "Company Name": "All You Can Read ", - "Company Link ": "https://allyoucanread.com" - }, - { - "Company Name": "AllTrails", - "Company Link ": "https://alltrails.com" - }, - { - "Company Name": "Anotepad", - "Company Link ": "https://anotepad.com" - }, - { - "Company Name": "AnswerSocrates", - "Company Link ": "https://answersocrates.com" - }, - { - "Company Name": "AnswerThePublic ", - "Company Link ": "https://answerthepublic.com" - }, - { - "Company Name": "Apollo ", - "Company Link ": "https://apollo.io" - }, - { - "Company Name": "ArrayList", - "Company Link ": "https://arraylist.org" - }, - { - "Company Name": "Ask Difference", - "Company Link ": "https://askdifference.com" - }, - { - "Company Name": "Audd.io", - "Company Link ": "https://audd.io" - }, - { - "Company Name": "Audiocheck", - "Company Link ": "https://audiocheck.net" - }, - { - "Company Name": "Audionautix", - "Company Link ": "https://audionautix.com" - }, - { - "Company Name": "Authentic Jobs", - "Company Link ": "https://authenticjobs.com" - }, - { - "Company Name": "Behind the Name", - "Company Link ": "https://behindthename.com" - }, - { - "Company Name": "Bilim Terimleri", - "Company Link ": "https://terimler.org" - }, - { - "Company Name": "BitBof", - "Company Link ": "https://bitbof.com" - }, - { - "Company Name": "Blank Page", - "Company Link ": "https://blank.page" - }, - { - "Company Name": "Bonanza", - "Company Link ": "https://bonanza.com" - }, - { - "Company Name": "BookCrossing", - "Company Link ": "https://bookcrossing.com" - }, - { - "Company Name": "Browse AI", - "Company Link ": "https://browse.ai" - }, - { - "Company Name": "Bubbl.us", - "Company Link ": "https://bubbl.us" - }, - { - "Company Name": "Business Model Toolbox", - "Company Link ": "https://bmtoolbox.net" - }, - { - "Company Name": "ByClickDownloader", - "Company Link ": "https://byclickdownloader.com" - }, - { - "Company Name": "Calligraphr", - "Company Link ": "https://calligraphr.com" - }, - { - "Company Name": "CertificateClaim", - "Company Link ": "https://certificateclaim.com" - }, - { - "Company Name": "Chosic", - "Company Link ": "https://chosic.com" - }, - { - "Company Name": "ClipDrop", - "Company Link ": "https://clipdrop.co" - }, - { - "Company Name": "CloudConvert", - "Company Link ": "https://cloudconvert.com" - }, - { - "Company Name": "CodingFont", - "Company Link ": "https://codingfont.com" - }, - { - "Company Name": "Color Hunt", - "Company Link ": "https://colorhunt.co" - }, - { - "Company Name": "ColorHexa", - "Company Link ": "https://colorhexa.com" - }, - { - "Company Name": "Conversion-Tool", - "Company Link ": "https://conversion-tool.com" - }, - { - "Company Name": "Cool Startup Jobs", - "Company Link ": "https://coolstartupjobs.com" - }, - { - "Company Name": "Coroflot", - "Company Link ": "https://coroflot.com" - }, - { - "Company Name": "Corrupt-a-File", - "Company Link ": "https://corrupt-a-file.net" - }, - { - "Company Name": "Couchsurfing", - "Company Link ": "https://couchsurfing.com" - }, - { - "Company Name": "Countries Been", - "Company Link ": "https://countriesbeen.com" - }, - { - "Company Name": "Country Code", - "Company Link ": "https://countrycode.org" - }, - { - "Company Name": "Creately", - "Company Link ": "https://creately.com" - }, - { - "Company Name": "Creately ", - "Company Link ": "https://creately.com" - }, - { - "Company Name": "Crossfade.io", - "Company Link ": "https://crossfade.io" - }, - { - "Company Name": "Crunchbase", - "Company Link ": "https://crunchbase.com" - }, - { - "Company Name": "CVmkr", - "Company Link ": "https://cvwizard.com" - }, - { - "Company Name": "Daily Remote", - "Company Link ": "https://dailyremote.com" - }, - { - "Company Name": "David Li", - "Company Link ": "https://david.li" - }, - { - "Company Name": "DemandHunt", - "Company Link ": "https://demandhunt.com" - }, - { - "Company Name": "Designify", - "Company Link ": "https://designify.com" - }, - { - "Company Name": "Diff Checker", - "Company Link ": "https://diffchecker.com" - }, - { - "Company Name": "DifferenceBetween.info", - "Company Link ": "https://differencebetween.info" - }, - { - "Company Name": "Digital Glossary", - "Company Link ": "https://digital-glossary.com" - }, - { - "Company Name": "Dimensions", - "Company Link ": "https://dimensions.com" - }, - { - "Company Name": "Discoverify Music", - "Company Link ": "https://discoverifymusic.com" - }, - { - "Company Name": "discu.eu", - "Company Link ": "https://discu.eu" - }, - { - "Company Name": "Do It Yourself", - "Company Link ": "https://doityourself.com" - }, - { - "Company Name": "Donkey Car", - "Company Link ": "https://donkeycar.com" - }, - { - "Company Name": "draw.io", - "Company Link ": "https://drawio.com" - }, - { - "Company Name": "Drumeo", - "Company Link ": "https://drumeo.com" - }, - { - "Company Name": "Dummies", - "Company Link ": "https://dummies.com" - }, - { - "Company Name": "Easel.ly", - "Company Link ": "https://easel.ly" - }, - { - "Company Name": "Educalingo", - "Company Link ": "https://educalingo.com" - }, - { - "Company Name": "Emoji Combos", - "Company Link ": "https://emojicombos.com" - }, - { - "Company Name": "EquityBee", - "Company Link ": "https://equitybee.com" - }, - { - "Company Name": "EquityZen", - "Company Link ": "https://equityzen.com" - }, - { - "Company Name": "Escape Room Tips", - "Company Link ": "https://escaperoomtips.com" - }, - { - "Company Name": "Every Noise", - "Company Link ": "https://everynoise.com" - }, - { - "Company Name": "Every Time Zone", - "Company Link ": "https://everytimezone.com" - }, - { - "Company Name": "Excalideck", - "Company Link ": "https://excalideck.com" - }, - { - "Company Name": "Excalidraw", - "Company Link ": "https://excalidraw.com" - }, - { - "Company Name": "Extract pics", - "Company Link ": "https://extract.pics" - }, - { - "Company Name": "EZGIF", - "Company Link ": "https://ezgif.com" - }, - { - "Company Name": "FactSlides", - "Company Link ": "https://factslides.com" - }, - { - "Company Name": "FIGR ", - "Company Link ": "https://figr.app" - }, - { - "Company Name": "Fine Dictionary", - "Company Link ": "https://finedictionary.com" - }, - { - "Company Name": "Fiverr", - "Company Link ": "https://fiverr.com" - }, - { - "Company Name": "Fix It Club", - "Company Link ": "https://fixitclub.com" - }, - { - "Company Name": "FlexJobs", - "Company Link ": "https://flexjobs.com" - }, - { - "Company Name": "Flightradar24", - "Company Link ": "https://flightradar24.com" - }, - { - "Company Name": "FlowCV ", - "Company Link ": "https://flowcv.com" - }, - { - "Company Name": "Foco Clipping", - "Company Link ": "https://fococlipping.com" - }, - { - "Company Name": "Font Squirrel", - "Company Link ": "https://fontsquirrel.com" - }, - { - "Company Name": "FontAwesome", - "Company Link ": "https://fontawesome.com" - }, - { - "Company Name": "Fontello ", - "Company Link ": "https://fontello.com" - }, - { - "Company Name": "Form to Chatbot", - "Company Link ": "https://formtochatbot.com" - }, - { - "Company Name": "Founder Resources", - "Company Link ": "https://founderresources.io" - }, - { - "Company Name": "Franz", - "Company Link ": "https://meetfranz.com" - }, - { - "Company Name": "Fraze It", - "Company Link ": "https://fraze.it" - }, - { - "Company Name": "Freecycle", - "Company Link ": "https://freecycle.org" - }, - { - "Company Name": "FreeType", - "Company Link ": "https://freetype.org" - }, - { - "Company Name": "FutureM", - "Company Link ": "https://futureme.org" - }, - { - "Company Name": "Generated.Photos", - "Company Link ": "https://generated.photos" - }, - { - "Company Name": "Get Human", - "Company Link ": "https://gethuman.com" - }, - { - "Company Name": "Go Bento", - "Company Link ": "https://gobento.com" - }, - { - "Company Name": "Good CV", - "Company Link ": "https://goodcv.com" - }, - { - "Company Name": "Grammar Monster", - "Company Link ": "https://grammar-monster.com" - }, - { - "Company Name": "Grammar Book", - "Company Link ": "https://grammarbook.com" - }, - { - "Company Name": "Gummy Search", - "Company Link ": "https://gummysearch.com" - }, - { - "Company Name": "Gumroad", - "Company Link ": "https://gumroad.com" - }, - { - "Company Name": "HealthIcons", - "Company Link ": "https://healthicons.org" - }, - { - "Company Name": "HexColor", - "Company Link ": "https://hexcolor.co" - }, - { - "Company Name": "Hidden Life Radio", - "Company Link ": "https://hiddenliferadio.com" - }, - { - "Company Name": "Hired", - "Company Link ": "https://lhh.com" - }, - { - "Company Name": "Honey", - "Company Link ": "https://joinhoney.com" - }, - { - "Company Name": "HowStuffWorks", - "Company Link ": "https://howstuffworks.com" - }, - { - "Company Name": "HugeIcons Pro", - "Company Link ": "https://hugeicons.com" - }, - { - "Company Name": "Humble Bundle", - "Company Link ": "https://humblebundle.com" - }, - { - "Company Name": "I Have No TV", - "Company Link ": "https://ihavenotv.com" - }, - { - "Company Name": "I Miss the Office", - "Company Link ": "https://imisstheoffice.eu" - }, - { - "Company Name": "IcoMoon", - "Company Link ": "https://icomoon.io" - }, - { - "Company Name": "Iconfinder", - "Company Link ": "https://iconfinder.com" - }, - { - "Company Name": "Icon Packs", - "Company Link ": "https://iconpacks.net" - }, - { - "Company Name": "Iconshock", - "Company Link ": "https://iconshock.com" - }, - { - "Company Name": "Iconz Design", - "Company Link ": "https://iconz.design" - }, - { - "Company Name": "iFixit", - "Company Link ": "https://ifixit.com" - }, - { - "Company Name": "IFTTT", - "Company Link ": "https://ifttt.com" - }, - { - "Company Name": "Illlustrations", - "Company Link ": "https://illlustrations.co" - }, - { - "Company Name": "Illustration Kit", - "Company Link ": "https://illustrationkit.com" - }, - { - "Company Name": "IMSDB", - "Company Link ": "https://imsdb.com" - }, - { - "Company Name": "Incompetech", - "Company Link ": "https://incompetech.com" - }, - { - "Company Name": "Incredibox", - "Company Link ": "https://incredibox.com" - }, - { - "Company Name": "InnerBod", - "Company Link ": "https://innerbody.com" - }, - { - "Company Name": "Instructables", - "Company Link ": "https://instructables.com" - }, - { - "Company Name": "Integromat", - "Company Link ": "https://make.com" - }, - { - "Company Name": "Investopedia", - "Company Link ": "https://investopedia.com" - }, - { - "Company Name": "Japanese Wiki Corpus", - "Company Link ": "https://japanesewiki.com" - }, - { - "Company Name": "Jitter.Video", - "Company Link ": "https://jitter.video" - }, - { - "Company Name": "Jobspresso", - "Company Link ": "https://jobspresso.co" - }, - { - "Company Name": "JPEG-Optimizer", - "Company Link ": "https://jpeg-optimizer.com" - }, - { - "Company Name": "JS Remotely", - "Company Link ": "https://jsremotely.com" - }, - { - "Company Name": "JScreenFix", - "Company Link ": "https://jscreenfix.com" - }, - { - "Company Name": "JSON Resume", - "Company Link ": "https://jsonresume.io" - }, - { - "Company Name": "Just Join", - "Company Link ": "https://justjoin.it" - }, - { - "Company Name": "Just the Recipe", - "Company Link ": "https://justtherecipe.com" - }, - { - "Company Name": "JustRemote", - "Company Link ": "https://justremote.co" - }, - { - "Company Name": "JustWatch", - "Company Link ": "https://justwatch.com" - }, - { - "Company Name": "Kanopy", - "Company Link ": "https://kanopy.com" - }, - { - "Company Name": "Kassellabs", - "Company Link ": "https://kassellabs.io" - }, - { - "Company Name": "Key Differences", - "Company Link ": "https://keydifferences.com" - }, - { - "Company Name": "Keybase", - "Company Link ": "https://keybase.io" - }, - { - "Company Name": "KeyValues", - "Company Link ": "https://keyvalues.com" - }, - { - "Company Name": "KHInsider", - "Company Link ": "https://khinsider.com" - }, - { - "Company Name": "Killed by Google", - "Company Link ": "https://killedbygoogle.com" - }, - { - "Company Name": "Kimovil", - "Company Link ": "https://kimovil.com" - }, - { - "Company Name": "Lalal.ai", - "Company Link ": "https://www.lalal.ai" - }, - { - "Company Name": "Learn Anything", - "Company Link ": "https://learn-anything.xyz" - }, - { - "Company Name": "LendingTree", - "Company Link ": "https://lendingtree.com" - }, - { - "Company Name": "Lightyear.fm", - "Company Link ": "https://lightyear.fm" - }, - { - "Company Name": "LittleSis", - "Company Link ": "https://littlesis.org" - }, - { - "Company Name": "Looria", - "Company Link ": "https://looria.com" - }, - { - "Company Name": "Lucidchart", - "Company Link ": "https://lucidchart.com" - }, - { - "Company Name": "Lunar", - "Company Link ": "https://lunar.fyi" - }, - { - "Company Name": "Manuals Lib", - "Company Link ": "https://manualslib.com" - }, - { - "Company Name": "Map Crunch", - "Company Link ": "https://mapcrunch.com" - }, - { - "Company Name": "Masterworks", - "Company Link ": "https://masterworks.com" - }, - { - "Company Name": "MediaFire", - "Company Link ": "https://mediafire.com" - }, - { - "Company Name": "Mind Mup", - "Company Link ": "https://mindmup.com" - }, - { - "Company Name": "Mixlr", - "Company Link ": "https://mixlr.com" - }, - { - "Company Name": "Moises AI", - "Company Link ": "https://moises.ai" - }, - { - "Company Name": "Money", - "Company Link ": "https://money.com" - }, - { - "Company Name": "Mountain Project", - "Company Link ": "https://mountainproject.com" - }, - { - "Company Name": "Movie Map", - "Company Link ": "https://movie-map.com" - }, - { - "Company Name": "Movie Sounds", - "Company Link ": "https://movie-sounds.org" - }, - { - "Company Name": "MP3Cut", - "Company Link ": "https://mp3cut.net" - }, - { - "Company Name": "Murmel", - "Company Link ": "https://murmel.social" - }, - { - "Company Name": "Muscle Wiki", - "Company Link ": "https://musclewiki.com" - }, - { - "Company Name": "Music-Map", - "Company Link ": "https://music-map.com" - }, - { - "Company Name": "MusicTheory.net", - "Company Link ": "https://musictheory.net" - }, - { - "Company Name": "MyFonts", - "Company Link ": "https://myfonts.com" - }, - { - "Company Name": "MyFridgeFood", - "Company Link ": "https://myfridgefood.com" - }, - { - "Company Name": "Nameberry", - "Company Link ": "https://nameberry.com" - }, - { - "Company Name": "Namechk", - "Company Link ": "https://namechk.com" - }, - { - "Company Name": "Ncase", - "Company Link ": "https://ncase.me" - }, - { - "Company Name": "News in Levels", - "Company Link ": "https://newsinlevels.com" - }, - { - "Company Name": "Noisli", - "Company Link ": "https://noisli.com" - }, - { - "Company Name": "Notes.io", - "Company Link ": "https://notes.io" - }, - { - "Company Name": "Novoresume", - "Company Link ": "https://novoresume.com" - }, - { - "Company Name": "Ocoya", - "Company Link ": "https://ocoya.com" - }, - { - "Company Name": "Old Computers Museum", - "Company Link ": "https://oldcomputers.net" - }, - { - "Company Name": "Online Tone Generator", - "Company Link ": "https://onlinetonegenerator.com" - }, - { - "Company Name": "Online-Convert", - "Company Link ": "https://online-convert.com" - }, - { - "Company Name": "OnlineConversion", - "Company Link ": "https://onlineconversion.com" - }, - { - "Company Name": "Online OCR", - "Company Link ": "https://onlineocr.net" - }, - { - "Company Name": "OpenWeatherMap", - "Company Link ": "https://openweathermap.org" - }, - { - "Company Name": "OrgPad", - "Company Link ": "https://orgpad.com" - }, - { - "Company Name": "Passport Index", - "Company Link ": "https://passportindex.org" - }, - { - "Company Name": "PDF Candy", - "Company Link ": "https://pdfcandy.com" - }, - { - "Company Name": "PDF2DOC", - "Company Link ": "https://pdf2doc.com" - }, - { - "Company Name": "PDFescape", - "Company Link ": "https://pdfescape.com" - }, - { - "Company Name": "PfpMaker", - "Company Link ": "https://pfpmaker.com" - }, - { - "Company Name": "PIDGI Wiki ", - "Company Link ": "https://pidgi.net" - }, - { - "Company Name": "PimEyes", - "Company Link ": "https://pimeyes.com" - }, - { - "Company Name": "Pipl ", - "Company Link ": "https://pipl.com" - }, - { - "Company Name": "PixelBazaar", - "Company Link ": "https://pixelbazaar.com" - }, - { - "Company Name": "PixelPaper", - "Company Link ": "https://pixelpaper.io" - }, - { - "Company Name": "Ponly", - "Company Link ": "https://ponly.com" - }, - { - "Company Name": "PowerToFly", - "Company Link ": "https://powertofly.com" - }, - { - "Company Name": "Pretzel Rocks", - "Company Link ": "https://pretzel.rocks" - }, - { - "Company Name": "PrintIt", - "Company Link ": "https://printit.work" - }, - { - "Company Name": "Prismatext", - "Company Link ": "https://prismatext.com" - }, - { - "Company Name": "Puffin Maps", - "Company Link ": "https://puffinmaps.com" - }, - { - "Company Name": "Puzzle Loop ", - "Company Link ": "https://puzzle-loop.com" - }, - { - "Company Name": "QuoteMaster", - "Company Link ": "https://quotemaster.org" - }, - { - "Company Name": "Radio Garden", - "Company Link ": "https://radio.garden" - }, - { - "Company Name": "Radiooooo", - "Company Link ": "https://radiooooo.com" - }, - { - "Company Name": "Radiosondy", - "Company Link ": "https://radiosondy.info" - }, - { - "Company Name": "Rainy Mood", - "Company Link ": "https://rainymood.com" - }, - { - "Company Name": "Random Street View", - "Company Link ": "https://randomstreetview.com" - }, - { - "Company Name": "Rap4Ever", - "Company Link ": "https://rap4all.com" - }, - { - "Company Name": "RareFilm", - "Company Link ": "https://rarefilm.net" - }, - { - "Company Name": "Rattibha", - "Company Link ": "https://rattibha.com" - }, - { - "Company Name": "Reddit List ", - "Company Link ": "https://redditlist.com" - }, - { - "Company Name": "RedditSearch.io", - "Company Link ": "https://redditsearch.io" - }, - { - "Company Name": "Reelgood", - "Company Link ": "https://reelgood.com" - }, - { - "Company Name": "Reface", - "Company Link ": "https://reface.ai" - }, - { - "Company Name": "Rejected.us", - "Company Link ": "https://rejected.us" - }, - { - "Company Name": "Relanote", - "Company Link ": "https://relanote.com" - }, - { - "Company Name": "Remote Leaf", - "Company Link ": "https://remoteleaf.com" - }, - { - "Company Name": "Remote OK", - "Company Link ": "https://remoteok.com" - }, - { - "Company Name": "Remote Starter Kit ", - "Company Link ": "https://remotestarterkit.com" - }, - { - "Company Name": "Remote.co", - "Company Link ": "https://remote.co" - }, - { - "Company Name": "Remote Base ", - "Company Link ": "https://remotebase.com" - }, - { - "Company Name": "Remote Bear", - "Company Link ": "https://remotebear.io" - }, - { - "Company Name": "Remove.bg", - "Company Link ": "https://remove.bg" - }, - { - "Company Name": "Respresso", - "Company Link ": "https://respresso.io" - }, - { - "Company Name": "Reveddit", - "Company Link ": "https://reveddit.com" - }, - { - "Company Name": "Rhymer", - "Company Link ": "https://rhymer.com" - }, - { - "Company Name": "RhymeZone", - "Company Link ": "https://rhymezone.com" - }, - { - "Company Name": "Ribbet", - "Company Link ": "https://ribbet.com" - }, - { - "Company Name": "Roadmap.sh", - "Company Link ": "https://roadmap.sh" - }, - { - "Company Name": "Roadtrippers", - "Company Link ": "https://roadtrippers.com" - }, - { - "Company Name": "RxResu.me", - "Company Link ": "https://rxresu.me" - }, - { - "Company Name": "SchemeColor", - "Company Link ": "https://schemecolor.com" - }, - { - "Company Name": "Screenshot.Guru", - "Company Link ": "https://screenshot.guru" - }, - { - "Company Name": "SeatGuru", - "Company Link ": "https://seatguru.com" - }, - { - "Company Name": "Sessions", - "Company Link ": "https://sessions.us" - }, - { - "Company Name": "Shottr", - "Company Link ": "https://shottr.cc" - }, - { - "Company Name": "Signature Maker", - "Company Link ": "https://signature-maker.net" - }, - { - "Company Name": "Skip The Drive", - "Company Link ": "https://skipthedrive.com" - }, - { - "Company Name": "Slowby", - "Company Link ": "https://slowby.travel" - }, - { - "Company Name": "Small World", - "Company Link ": "https://smallworld.kiwi" - }, - { - "Company Name": "SmallPDF", - "Company Link ": "https://smallpdf.com" - }, - { - "Company Name": "Social Image Maker", - "Company Link ": "https://socialimagemaker.io" - }, - { - "Company Name": "Social Sizes", - "Company Link ": "https://socialsizes.io" - }, - { - "Company Name": "SoundLove", - "Company Link ": "https://soundlove.se" - }, - { - "Company Name": "Spline", - "Company Link ": "https://spline.design" - }, - { - "Company Name": "Starkey Comics", - "Company Link ": "https://starkeycomics.com" - }, - { - "Company Name": "Startups List", - "Company Link ": "https://startups-list.com" - }, - { - "Company Name": "Statista", - "Company Link ": "https://statista.com" - }, - { - "Company Name": "Stolen Camera Finder", - "Company Link ": "https://stolencamerafinder.com" - }, - { - "Company Name": "Strobe.Cool", - "Company Link ": "https://strobe.cool" - }, - { - "Company Name": "Sumo", - "Company Link ": "https://sumo.app" - }, - { - "Company Name": "SuperMeme AI", - "Company Link ": "https://supermeme.ai" - }, - { - "Company Name": "Synthesia", - "Company Link ": "https://synthesia.io" - }, - { - "Company Name": "TablerIcons", - "Company Link ": "https://tablericons.com" - }, - { - "Company Name": "Tango", - "Company Link ": "https://tango.us" - }, - { - "Company Name": "TasteDive", - "Company Link ": "https://tastedive.com" - }, - { - "Company Name": "TechSpecs", - "Company Link ": "https://techspecs.io" - }, - { - "Company Name": "Teoria", - "Company Link ": "https://teoria.com" - }, - { - "Company Name": "Text Faces", - "Company Link ": "https://textfac.es" - }, - { - "Company Name": "The Balance Money", - "Company Link ": "https://thebalancemoney.com" - }, - { - "Company Name": "The Punctuation Guide", - "Company Link ": "https://thepunctuationguide.com" - }, - { - "Company Name": "This to That", - "Company Link ": "https://thistothat.com" - }, - { - "Company Name": "This vs That", - "Company Link ": "https://thisvsthat.io" - }, - { - "Company Name": "ThreadReaderApp ", - "Company Link ": "https://threadreaderapp.com" - }, - { - "Company Name": "Thumbly", - "Company Link ": "https://tokee.ai" - }, - { - "Company Name": "Tiii.me", - "Company Link ": "https://tiii.me" - }, - { - "Company Name": "TikTok Video Downloader", - "Company Link ": "https://ttvdl.com" - }, - { - "Company Name": "Time and Date", - "Company Link ": "https://timeanddate.com" - }, - { - "Company Name": "Time.is", - "Company Link ": "https://time.is" - }, - { - "Company Name": "Title Case", - "Company Link ": "https://titlecase.com" - }, - { - "Company Name": "Toaster Central", - "Company Link ": "https://toastercentral.com" - }, - { - "Company Name": "Tongue-Twister ", - "Company Link ": "https://tongue-twister.net" - }, - { - "Company Name": "TradingView", - "Company Link ": "https://tradingview.com" - }, - { - "Company Name": "Transparent Textures", - "Company Link ": "https://transparenttextures.com" - }, - { - "Company Name": "Tubi TV", - "Company Link ": "https://tubitv.com" - }, - { - "Company Name": "Tunefind", - "Company Link ": "https://tunefind.com" - }, - { - "Company Name": "TuneMyMusic", - "Company Link ": "https://tunemymusic.com" - }, - { - "Company Name": "Tweepsmap", - "Company Link ": "https://fedica.com" - }, - { - "Company Name": "Two Peas and Their Pod", - "Company Link ": "https://twopeasandtheirpod.com" - }, - { - "Company Name": "Typatone", - "Company Link ": "https://typatone.com" - }, - { - "Company Name": "Under Glass", - "Company Link ": "https://underglass.io" - }, - { - "Company Name": "UniCorner", - "Company Link ": "https://unicorner.news" - }, - { - "Company Name": "Unita", - "Company Link ": "https://unita.co" - }, - { - "Company Name": "UnitConverters", - "Company Link ": "https://unitconverters.net" - }, - { - "Company Name": "Unreadit", - "Company Link ": "https://unreadit.com" - }, - { - "Company Name": "Unscreen", - "Company Link ": "https://unscreen.com" - }, - { - "Company Name": "UnTools ", - "Company Link ": "https://untools.co" - }, - { - "Company Name": "Upwork", - "Company Link ": "https://upwork.com" - }, - { - "Company Name": "UTF8 Icons", - "Company Link ": "https://utf8icons.com" - }, - { - "Company Name": "Vector Magic", - "Company Link ": "https://vectormagic.com" - }, - { - "Company Name": "Virtual Vacation", - "Company Link ": "https://virtualvacation.us" - }, - { - "Company Name": "Virtual Vocations", - "Company Link ": "https://virtualvocations.com" - }, - { - "Company Name": "Visiwig", - "Company Link ": "https://visiwig.com" - }, - { - "Company Name": "Visual CV", - "Company Link ": "https://visualcv.com" - }, - { - "Company Name": "Vocus.io", - "Company Link ": "https://vocus.io" - }, - { - "Company Name": "Voscreen", - "Company Link ": "https://voscreen.com" - }, - { - "Company Name": "Wanderprep", - "Company Link ": "https://wanderprep.com" - }, - { - "Company Name": "Warmshowers", - "Company Link ": "https:/warmshowers.org" - }, - { - "Company Name": "Watch Documentaries", - "Company Link ": "https://watchdocumentaries.com" - }, - { - "Company Name": "We Work Remotely", - "Company Link ": "https://weworkremotely.com" - }, - { - "Company Name": "Web2PDFConvert", - "Company Link ": "https://web2pdfconvert.com" - }, - { - "Company Name": "Welcome to My Garden", - "Company Link ": "https://welcometomygarden.org" - }, - { - "Company Name": "When2meet ", - "Company Link ": "https://when2meet.com" - }, - { - "Company Name": "Where's George", - "Company Link ": "https://wheresgeorge.com" - }, - { - "Company Name": "Where's Willy", - "Company Link ": "https://whereswilly.com" - }, - { - "Company Name": "WikiHow", - "Company Link ": "https://wikihow.com" - }, - { - "Company Name": "Windy", - "Company Link ": "https://www.windy.com" - }, - { - "Company Name": "WonderHowTo", - "Company Link ": "https://wonderhowto.com" - }, - { - "Company Name": "Working Nomads", - "Company Link ": "https://workingnomads.com" - }, - { - "Company Name": "Wormhole", - "Company Link ": "https://wormhole.app" - }, - { - "Company Name": "Y Combinator Jobs", - "Company Link ": "https://ycombinator.com" - }, - { - "Company Name": "Yes Promo", - "Company Link ": "https://yespromo.me" - }, - { - "Company Name": "YouGlish", - "Company Link ": "https://youglish.com" - }, - { - "Company Name": "Zamzar", - "Company Link ": "https://zamzar.com" - }, - { - "Company Name": "Zippyshare", - "Company Link ": "https://zippyshare.com" - }, - { - "Company Name": "Zoom Earth", - "Company Link ": "https://zoom.earth" - }, - { - "Company Name": "Zoom.it", - "Company Link ": "https://zoom.it" - } -] \ No newline at end of file diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js index fe406a6b6..b3a809a09 100644 --- a/Server/controllers/authController.js +++ b/Server/controllers/authController.js @@ -17,6 +17,7 @@ require("dotenv").config(); const { errorMessages, successMessages } = require("../utils/messages"); var jwt = require("jsonwebtoken"); const SERVICE_NAME = "auth"; +const { getTokenFromHeaders } = require("../utils/utils"); /** * Creates and returns JWT token with an arbitrary payload @@ -30,17 +31,6 @@ const issueToken = (payload) => { return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: tokenTTL }); }; -const getTokenFromHeaders = (headers) => { - const authorizationHeader = headers.authorization; - if (!authorizationHeader) throw new Error("No auth headers"); - - const parts = authorizationHeader.split(" "); - if (parts.length !== 2 || parts[0] !== "Bearer") - throw new Error("Invalid auth headers"); - - return parts[1]; -}; - /** * @function * @param {express.Request} req diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index 4571a9a65..c40135cdb 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -18,6 +18,9 @@ const { const sslChecker = require("ssl-checker"); const SERVICE_NAME = "monitorController"; const { errorMessages, successMessages } = require("../utils/messages"); +const jwt = require("jsonwebtoken"); +const { getTokenFromHeaders } = require("../utils/utils"); + /** * Returns all monitors * @async @@ -365,12 +368,24 @@ const deleteMonitor = async (req, res, next) => { const deleteAllMonitors = async (req, res) => { try { - const deleteCount = await req.db.deleteAllMonitors(); + console.log("WTF"); + const token = getTokenFromHeaders(req.headers); + const { teamId } = jwt.verify(token, process.env.JWT_SECRET); + const { monitors, deletedCount } = await req.db.deleteAllMonitors(teamId); + await monitors.forEach(async (monitor) => { + await req.jobQueue.deleteJob(monitor); + await req.db.deleteChecks(monitor._id); + await req.db.deleteAlertByMonitorId(monitor._id); + await req.db.deletePageSpeedChecksByMonitorId(monitor._id); + await req.db.deleteNotificationsByMonitorId(monitor._id); + }); + return res .status(200) - .json({ success: true, msg: `Deleted ${deleteCount} monitors` }); + .json({ success: true, msg: `Deleted ${deletedCount} monitors` }); } catch (error) { error.service = SERVICE_NAME; + error.method === undefined && error.method === "deleteAllMonitors"; next(error); } }; @@ -466,6 +481,26 @@ const pauseMonitor = async (req, res, next) => { } }; +const addDemoMonitors = async (req, res, next) => { + try { + const token = getTokenFromHeaders(req.headers); + const { _id, teamId } = jwt.verify(token, process.env.JWT_SECRET); + const demoMonitors = await req.db.addDemoMonitors(_id, teamId); + await demoMonitors.forEach(async (monitor) => { + await req.jobQueue.addJob(monitor._id, monitor); + }); + return res.status(200).json({ + success: true, + message: successMessages.MONITOR_DEMO_ADDED, + data: demoMonitors.length, + }); + } catch (error) { + error.service = SERVICE_NAME; + error.method === undefined && error.method === "addDemoMonitors"; + next(error); + } +}; + module.exports = { getAllMonitors, getMonitorAggregateStats, @@ -479,4 +514,5 @@ module.exports = { deleteAllMonitors, editMonitor, pauseMonitor, + addDemoMonitors, }; diff --git a/Server/db/mongo/MongoDB.js b/Server/db/mongo/MongoDB.js index d6a4a243f..73d55d509 100644 --- a/Server/db/mongo/MongoDB.js +++ b/Server/db/mongo/MongoDB.js @@ -73,6 +73,7 @@ const { deleteAllMonitors, deleteMonitorsByUserId, editMonitor, + addDemoMonitors, } = require("./modules/monitorModule"); //**************************************** @@ -153,6 +154,7 @@ module.exports = { deleteMonitor, deleteAllMonitors, editMonitor, + addDemoMonitors, createCheck, getChecksCount, getChecks, diff --git a/Server/db/mongo/modules/checkModule.js b/Server/db/mongo/modules/checkModule.js index 32968431d..da3ccb8f3 100644 --- a/Server/db/mongo/modules/checkModule.js +++ b/Server/db/mongo/modules/checkModule.js @@ -1,6 +1,7 @@ const Check = require("../../../models/Check"); const Monitor = require("../../../models/Monitor"); -const mongoose = require("mongoose"); +const logger = require("../../../utils/logger"); +const SERVICE_NAME = "checkModule"; const dateRangeLookup = { day: new Date(new Date().setDate(new Date().getDate() - 1)), week: new Date(new Date().setDate(new Date().getDate() - 7)), @@ -24,21 +25,25 @@ const createCheck = async (checkData) => { try { const { monitorId, status } = checkData; - const n = await Check.countDocuments({ monitorId }) + 1; + const n = (await Check.countDocuments({ monitorId })) + 1; const check = await new Check({ ...checkData }).save(); const monitor = await Monitor.findById(monitorId); if (!monitor) { - throw new Error("Monitor not found"); + logger.error("Monitor not found", { + service: SERVICE_NAME, + monitorId, + }); + return; } if (monitor.uptimePercentage === undefined) { - monitor.uptimePercentage = (status === true) ? 1 : 0; + monitor.uptimePercentage = status === true ? 1 : 0; } else { monitor.uptimePercentage = - (monitor.uptimePercentage * (n - 1) + (status === true ? 1: 0)) / n; + (monitor.uptimePercentage * (n - 1) + (status === true ? 1 : 0)) / n; } await monitor.save(); diff --git a/Server/db/mongo/modules/monitorModule.js b/Server/db/mongo/modules/monitorModule.js index e77ccc696..5eaec7bf9 100644 --- a/Server/db/mongo/modules/monitorModule.js +++ b/Server/db/mongo/modules/monitorModule.js @@ -4,6 +4,7 @@ const PageSpeedCheck = require("../../../models/PageSpeedCheck"); const { errorMessages } = require("../../../utils/messages"); const Notification = require("../../../models/Notification"); const { NormalizeData } = require("../../../utils/dataUtils"); +const demoMonitors = require("../../../utils/demoMonitors.json"); /** * Get all monitors @@ -450,10 +451,12 @@ const deleteMonitor = async (req, res) => { * DELETE ALL MONITORS (TEMP) */ -const deleteAllMonitors = async (req, res) => { +const deleteAllMonitors = async (teamId) => { try { - const deletedCount = await Monitor.deleteMany({}); - return deletedCount.deletedCount; + const monitors = await Monitor.find({ teamId }); + const { deletedCount } = await Monitor.deleteMany({ teamId }); + + return { monitors, deletedCount }; } catch (error) { throw error; } @@ -493,6 +496,28 @@ const editMonitor = async (candidateId, candidateMonitor) => { ); return editedMonitor; } catch (error) { + error.method = "editMonitor"; + throw error; + } +}; + +const addDemoMonitors = async (userId, teamId) => { + try { + const demoMonitorsToInsert = demoMonitors.map((monitor) => { + return { + userId, + teamId, + name: monitor.name, + description: monitor.name, + type: "http", + url: monitor.url, + interval: 60000, + }; + }); + const insertedMonitors = await Monitor.insertMany(demoMonitorsToInsert); + return insertedMonitors; + } catch (error) { + error.method = "addDemoMonitors"; throw error; } }; @@ -508,4 +533,5 @@ module.exports = { deleteAllMonitors, deleteMonitorsByUserId, editMonitor, + addDemoMonitors, }; diff --git a/Server/routes/monitorRoute.js b/Server/routes/monitorRoute.js index b29b7130a..c6bec5f0f 100644 --- a/Server/routes/monitorRoute.js +++ b/Server/routes/monitorRoute.js @@ -32,7 +32,7 @@ router.put( ); router.delete( - "/all", + "/", isAllowed(["superadmin"]), monitorController.deleteAllMonitors ); @@ -43,4 +43,10 @@ router.post( monitorController.pauseMonitor ); +router.post( + "/demo", + isAllowed(["admin", "superadmin"]), + monitorController.addDemoMonitors +); + module.exports = router; diff --git a/Server/service/networkService.js b/Server/service/networkService.js index e25a63ce5..0664ee05a 100644 --- a/Server/service/networkService.js +++ b/Server/service/networkService.js @@ -278,6 +278,7 @@ class NetworkService { default: logger.error(`Unsupported type: ${job.data.type}`, { service: this.SERVICE_NAME, + method: "getStatus", jobId: job.id, }); return false; @@ -296,11 +297,13 @@ class NetworkService { async logAndStoreCheck(data, writeToDB) { try { const insertedCheck = await writeToDB(data); - return insertedCheck.status; + if (insertedCheck !== null && insertedCheck !== undefined) { + return insertedCheck.status; + } } catch (error) { - console.log(error); logger.error(`Error wrtiting check for ${data.monitorId}`, { service: this.SERVICE_NAME, + method: "logAndStoreCheck", monitorId: data.monitorId, error: error, }); diff --git a/Server/utils/demoMonitors.json b/Server/utils/demoMonitors.json new file mode 100644 index 000000000..6f57940f2 --- /dev/null +++ b/Server/utils/demoMonitors.json @@ -0,0 +1,1271 @@ +[ + { + "name": "0to255", + "url": "https://0to255.com" + }, + { + "name": "10015.io", + "url": "https://10015.io" + }, + { + "name": "3DIcons", + "url": "https://3dicons.co" + }, + { + "name": "About.me", + "url": "https://about.me" + }, + { + "name": "Alias", + "url": "https://alias.co" + }, + { + "name": "All About Berlin", + "url": "https://allaboutberlin.com" + }, + { + "name": "All Acronyms", + "url": "https://allacronyms.com" + }, + { + "name": "All You Can Read ", + "url": "https://allyoucanread.com" + }, + { + "name": "AllTrails", + "url": "https://alltrails.com" + }, + { + "name": "Anotepad", + "url": "https://anotepad.com" + }, + { + "name": "AnswerSocrates", + "url": "https://answersocrates.com" + }, + { + "name": "AnswerThePublic ", + "url": "https://answerthepublic.com" + }, + { + "name": "Apollo ", + "url": "https://apollo.io" + }, + { + "name": "ArrayList", + "url": "https://arraylist.org" + }, + { + "name": "Ask Difference", + "url": "https://askdifference.com" + }, + { + "name": "Audd.io", + "url": "https://audd.io" + }, + { + "name": "Audiocheck", + "url": "https://audiocheck.net" + }, + { + "name": "Audionautix", + "url": "https://audionautix.com" + }, + { + "name": "Authentic Jobs", + "url": "https://authenticjobs.com" + }, + { + "name": "Behind the Name", + "url": "https://behindthename.com" + }, + { + "name": "Bilim Terimleri", + "url": "https://terimler.org" + }, + { + "name": "BitBof", + "url": "https://bitbof.com" + }, + { + "name": "Blank Page", + "url": "https://blank.page" + }, + { + "name": "Bonanza", + "url": "https://bonanza.com" + }, + { + "name": "BookCrossing", + "url": "https://bookcrossing.com" + }, + { + "name": "Browse AI", + "url": "https://browse.ai" + }, + { + "name": "Bubbl.us", + "url": "https://bubbl.us" + }, + { + "name": "Business Model Toolbox", + "url": "https://bmtoolbox.net" + }, + { + "name": "ByClickDownloader", + "url": "https://byclickdownloader.com" + }, + { + "name": "Calligraphr", + "url": "https://calligraphr.com" + }, + { + "name": "CertificateClaim", + "url": "https://certificateclaim.com" + }, + { + "name": "Chosic", + "url": "https://chosic.com" + }, + { + "name": "ClipDrop", + "url": "https://clipdrop.co" + }, + { + "name": "CloudConvert", + "url": "https://cloudconvert.com" + }, + { + "name": "CodingFont", + "url": "https://codingfont.com" + }, + { + "name": "Color Hunt", + "url": "https://colorhunt.co" + }, + { + "name": "ColorHexa", + "url": "https://colorhexa.com" + }, + { + "name": "Conversion-Tool", + "url": "https://conversion-tool.com" + }, + { + "name": "Cool Startup Jobs", + "url": "https://coolstartupjobs.com" + }, + { + "name": "Coroflot", + "url": "https://coroflot.com" + }, + { + "name": "Corrupt-a-File", + "url": "https://corrupt-a-file.net" + }, + { + "name": "Couchsurfing", + "url": "https://couchsurfing.com" + }, + { + "name": "Countries Been", + "url": "https://countriesbeen.com" + }, + { + "name": "Country Code", + "url": "https://countrycode.org" + }, + { + "name": "Creately", + "url": "https://creately.com" + }, + { + "name": "Creately ", + "url": "https://creately.com" + }, + { + "name": "Crossfade.io", + "url": "https://crossfade.io" + }, + { + "name": "Crunchbase", + "url": "https://crunchbase.com" + }, + { + "name": "CVmkr", + "url": "https://cvwizard.com" + }, + { + "name": "Daily Remote", + "url": "https://dailyremote.com" + }, + { + "name": "David Li", + "url": "https://david.li" + }, + { + "name": "DemandHunt", + "url": "https://demandhunt.com" + }, + { + "name": "Designify", + "url": "https://designify.com" + }, + { + "name": "Diff Checker", + "url": "https://diffchecker.com" + }, + { + "name": "DifferenceBetween.info", + "url": "https://differencebetween.info" + }, + { + "name": "Digital Glossary", + "url": "https://digital-glossary.com" + }, + { + "name": "Dimensions", + "url": "https://dimensions.com" + }, + { + "name": "Discoverify Music", + "url": "https://discoverifymusic.com" + }, + { + "name": "discu.eu", + "url": "https://discu.eu" + }, + { + "name": "Do It Yourself", + "url": "https://doityourself.com" + }, + { + "name": "draw.io", + "url": "https://drawio.com" + }, + { + "name": "Drumeo", + "url": "https://drumeo.com" + }, + { + "name": "Dummies", + "url": "https://dummies.com" + }, + { + "name": "Easel.ly", + "url": "https://easel.ly" + }, + { + "name": "Educalingo", + "url": "https://educalingo.com" + }, + { + "name": "Emoji Combos", + "url": "https://emojicombos.com" + }, + { + "name": "EquityBee", + "url": "https://equitybee.com" + }, + { + "name": "EquityZen", + "url": "https://equityzen.com" + }, + { + "name": "Escape Room Tips", + "url": "https://escaperoomtips.com" + }, + { + "name": "Every Noise", + "url": "https://everynoise.com" + }, + { + "name": "Every Time Zone", + "url": "https://everytimezone.com" + }, + { + "name": "Excalideck", + "url": "https://excalideck.com" + }, + { + "name": "Excalidraw", + "url": "https://excalidraw.com" + }, + { + "name": "Extract pics", + "url": "https://extract.pics" + }, + { + "name": "EZGIF", + "url": "https://ezgif.com" + }, + { + "name": "FactSlides", + "url": "https://factslides.com" + }, + { + "name": "FIGR ", + "url": "https://figr.app" + }, + { + "name": "Fine Dictionary", + "url": "https://finedictionary.com" + }, + { + "name": "Fiverr", + "url": "https://fiverr.com" + }, + { + "name": "Fix It Club", + "url": "https://fixitclub.com" + }, + { + "name": "Flightradar24", + "url": "https://flightradar24.com" + }, + { + "name": "FlowCV ", + "url": "https://flowcv.com" + }, + { + "name": "Font Squirrel", + "url": "https://fontsquirrel.com" + }, + { + "name": "FontAwesome", + "url": "https://fontawesome.com" + }, + { + "name": "Fontello ", + "url": "https://fontello.com" + }, + { + "name": "Form to Chatbot", + "url": "https://formtochatbot.com" + }, + { + "name": "Founder Resources", + "url": "https://founderresources.io" + }, + { + "name": "Franz", + "url": "https://meetfranz.com" + }, + { + "name": "Fraze It", + "url": "https://fraze.it" + }, + { + "name": "Freecycle", + "url": "https://freecycle.org" + }, + { + "name": "FreeType", + "url": "https://freetype.org" + }, + { + "name": "FutureM", + "url": "https://futureme.org" + }, + { + "name": "Generated.Photos", + "url": "https://generated.photos" + }, + { + "name": "Get Human", + "url": "https://gethuman.com" + }, + { + "name": "Go Bento", + "url": "https://gobento.com" + }, + { + "name": "Good CV", + "url": "https://goodcv.com" + }, + { + "name": "Grammar Monster", + "url": "https://grammar-monster.com" + }, + { + "name": "Grammar Book", + "url": "https://grammarbook.com" + }, + { + "name": "Gummy Search", + "url": "https://gummysearch.com" + }, + { + "name": "Gumroad", + "url": "https://gumroad.com" + }, + { + "name": "HealthIcons", + "url": "https://healthicons.org" + }, + { + "name": "HexColor", + "url": "https://hexcolor.co" + }, + { + "name": "Hidden Life Radio", + "url": "https://hiddenliferadio.com" + }, + { + "name": "Hired", + "url": "https://lhh.com" + }, + { + "name": "Honey", + "url": "https://joinhoney.com" + }, + { + "name": "HowStuffWorks", + "url": "https://howstuffworks.com" + }, + { + "name": "HugeIcons Pro", + "url": "https://hugeicons.com" + }, + { + "name": "Humble Bundle", + "url": "https://humblebundle.com" + }, + { + "name": "I Have No TV", + "url": "https://ihavenotv.com" + }, + { + "name": "I Miss the Office", + "url": "https://imisstheoffice.eu" + }, + { + "name": "IcoMoon", + "url": "https://icomoon.io" + }, + { + "name": "Iconfinder", + "url": "https://iconfinder.com" + }, + { + "name": "Icon Packs", + "url": "https://iconpacks.net" + }, + { + "name": "Iconshock", + "url": "https://iconshock.com" + }, + { + "name": "Iconz Design", + "url": "https://iconz.design" + }, + { + "name": "iFixit", + "url": "https://ifixit.com" + }, + { + "name": "IFTTT", + "url": "https://ifttt.com" + }, + { + "name": "Illlustrations", + "url": "https://illlustrations.co" + }, + { + "name": "Illustration Kit", + "url": "https://illustrationkit.com" + }, + { + "name": "IMSDB", + "url": "https://imsdb.com" + }, + { + "name": "Incompetech", + "url": "https://incompetech.com" + }, + { + "name": "Incredibox", + "url": "https://incredibox.com" + }, + { + "name": "InnerBod", + "url": "https://innerbody.com" + }, + { + "name": "Instructables", + "url": "https://instructables.com" + }, + { + "name": "Integromat", + "url": "https://make.com" + }, + { + "name": "Investopedia", + "url": "https://investopedia.com" + }, + { + "name": "Japanese Wiki Corpus", + "url": "https://japanesewiki.com" + }, + { + "name": "Jitter.Video", + "url": "https://jitter.video" + }, + { + "name": "Jobspresso", + "url": "https://jobspresso.co" + }, + { + "name": "JPEG-Optimizer", + "url": "https://jpeg-optimizer.com" + }, + { + "name": "JS Remotely", + "url": "https://jsremotely.com" + }, + { + "name": "JScreenFix", + "url": "https://jscreenfix.com" + }, + { + "name": "JSON Resume", + "url": "https://jsonresume.io" + }, + { + "name": "Just Join", + "url": "https://justjoin.it" + }, + { + "name": "Just the Recipe", + "url": "https://justtherecipe.com" + }, + { + "name": "JustRemote", + "url": "https://justremote.co" + }, + { + "name": "JustWatch", + "url": "https://justwatch.com" + }, + { + "name": "Kanopy", + "url": "https://kanopy.com" + }, + { + "name": "Kassellabs", + "url": "https://kassellabs.io" + }, + { + "name": "Key Differences", + "url": "https://keydifferences.com" + }, + { + "name": "Keybase", + "url": "https://keybase.io" + }, + { + "name": "KeyValues", + "url": "https://keyvalues.com" + }, + { + "name": "KHInsider", + "url": "https://khinsider.com" + }, + { + "name": "Killed by Google", + "url": "https://killedbygoogle.com" + }, + { + "name": "Kimovil", + "url": "https://kimovil.com" + }, + { + "name": "Lalal.ai", + "url": "https://www.lalal.ai" + }, + { + "name": "Learn Anything", + "url": "https://learn-anything.xyz" + }, + { + "name": "LendingTree", + "url": "https://lendingtree.com" + }, + { + "name": "Lightyear.fm", + "url": "https://lightyear.fm" + }, + { + "name": "LittleSis", + "url": "https://littlesis.org" + }, + { + "name": "Looria", + "url": "https://looria.com" + }, + { + "name": "Lucidchart", + "url": "https://lucidchart.com" + }, + { + "name": "Lunar", + "url": "https://lunar.fyi" + }, + { + "name": "Manuals Lib", + "url": "https://manualslib.com" + }, + { + "name": "Map Crunch", + "url": "https://mapcrunch.com" + }, + { + "name": "Masterworks", + "url": "https://masterworks.com" + }, + { + "name": "MediaFire", + "url": "https://mediafire.com" + }, + { + "name": "Mixlr", + "url": "https://mixlr.com" + }, + { + "name": "Moises AI", + "url": "https://moises.ai" + }, + { + "name": "Money", + "url": "https://money.com" + }, + { + "name": "Mountain Project", + "url": "https://mountainproject.com" + }, + { + "name": "Movie Map", + "url": "https://movie-map.com" + }, + { + "name": "Movie Sounds", + "url": "https://movie-sounds.org" + }, + { + "name": "MP3Cut", + "url": "https://mp3cut.net" + }, + { + "name": "Murmel", + "url": "https://murmel.social" + }, + { + "name": "Muscle Wiki", + "url": "https://musclewiki.com" + }, + { + "name": "Music-Map", + "url": "https://music-map.com" + }, + { + "name": "MusicTheory.net", + "url": "https://musictheory.net" + }, + { + "name": "MyFonts", + "url": "https://myfonts.com" + }, + { + "name": "MyFridgeFood", + "url": "https://myfridgefood.com" + }, + { + "name": "Nameberry", + "url": "https://nameberry.com" + }, + { + "name": "Namechk", + "url": "https://namechk.com" + }, + { + "name": "Ncase", + "url": "https://ncase.me" + }, + { + "name": "News in Levels", + "url": "https://newsinlevels.com" + }, + { + "name": "Noisli", + "url": "https://noisli.com" + }, + { + "name": "Notes.io", + "url": "https://notes.io" + }, + { + "name": "Novoresume", + "url": "https://novoresume.com" + }, + { + "name": "Ocoya", + "url": "https://ocoya.com" + }, + { + "name": "Old Computers Museum", + "url": "https://oldcomputers.net" + }, + { + "name": "Online Tone Generator", + "url": "https://onlinetonegenerator.com" + }, + { + "name": "Online-Convert", + "url": "https://online-convert.com" + }, + { + "name": "OnlineConversion", + "url": "https://onlineconversion.com" + }, + { + "name": "Online OCR", + "url": "https://onlineocr.net" + }, + { + "name": "OpenWeatherMap", + "url": "https://openweathermap.org" + }, + { + "name": "OrgPad", + "url": "https://orgpad.com" + }, + { + "name": "Passport Index", + "url": "https://passportindex.org" + }, + { + "name": "PDF Candy", + "url": "https://pdfcandy.com" + }, + { + "name": "PDF2DOC", + "url": "https://pdf2doc.com" + }, + { + "name": "PDFescape", + "url": "https://pdfescape.com" + }, + { + "name": "PfpMaker", + "url": "https://pfpmaker.com" + }, + { + "name": "PIDGI Wiki ", + "url": "https://pidgi.net" + }, + { + "name": "PimEyes", + "url": "https://pimeyes.com" + }, + { + "name": "Pipl ", + "url": "https://pipl.com" + }, + { + "name": "PixelBazaar", + "url": "https://pixelbazaar.com" + }, + { + "name": "PixelPaper", + "url": "https://pixelpaper.io" + }, + { + "name": "Ponly", + "url": "https://ponly.com" + }, + { + "name": "PowerToFly", + "url": "https://powertofly.com" + }, + { + "name": "Pretzel Rocks", + "url": "https://pretzel.rocks" + }, + { + "name": "PrintIt", + "url": "https://printit.work" + }, + { + "name": "Prismatext", + "url": "https://prismatext.com" + }, + { + "name": "Puffin Maps", + "url": "https://puffinmaps.com" + }, + { + "name": "Puzzle Loop ", + "url": "https://puzzle-loop.com" + }, + { + "name": "QuoteMaster", + "url": "https://quotemaster.org" + }, + { + "name": "Radio Garden", + "url": "https://radio.garden" + }, + { + "name": "Radiooooo", + "url": "https://radiooooo.com" + }, + { + "name": "Radiosondy", + "url": "https://radiosondy.info" + }, + { + "name": "Rainy Mood", + "url": "https://rainymood.com" + }, + { + "name": "Random Street View", + "url": "https://randomstreetview.com" + }, + { + "name": "Rap4Ever", + "url": "https://rap4all.com" + }, + { + "name": "RareFilm", + "url": "https://rarefilm.net" + }, + { + "name": "Rattibha", + "url": "https://rattibha.com" + }, + { + "name": "Reddit List ", + "url": "https://redditlist.com" + }, + { + "name": "RedditSearch.io", + "url": "https://redditsearch.io" + }, + { + "name": "Reelgood", + "url": "https://reelgood.com" + }, + { + "name": "Reface", + "url": "https://reface.ai" + }, + { + "name": "Rejected.us", + "url": "https://rejected.us" + }, + { + "name": "Relanote", + "url": "https://relanote.com" + }, + { + "name": "Remote Leaf", + "url": "https://remoteleaf.com" + }, + { + "name": "Remote OK", + "url": "https://remoteok.com" + }, + { + "name": "Remote Starter Kit ", + "url": "https://remotestarterkit.com" + }, + { + "name": "Remote.co", + "url": "https://remote.co" + }, + { + "name": "Remote Base ", + "url": "https://remotebase.com" + }, + { + "name": "Remote Bear", + "url": "https://remotebear.io" + }, + { + "name": "Remove.bg", + "url": "https://remove.bg" + }, + { + "name": "Respresso", + "url": "https://respresso.io" + }, + { + "name": "Reveddit", + "url": "https://reveddit.com" + }, + { + "name": "Rhymer", + "url": "https://rhymer.com" + }, + { + "name": "RhymeZone", + "url": "https://rhymezone.com" + }, + { + "name": "Ribbet", + "url": "https://ribbet.com" + }, + { + "name": "Roadmap.sh", + "url": "https://roadmap.sh" + }, + { + "name": "Roadtrippers", + "url": "https://roadtrippers.com" + }, + { + "name": "RxResu.me", + "url": "https://rxresu.me" + }, + { + "name": "SchemeColor", + "url": "https://schemecolor.com" + }, + { + "name": "Screenshot.Guru", + "url": "https://screenshot.guru" + }, + { + "name": "SeatGuru", + "url": "https://seatguru.com" + }, + { + "name": "Sessions", + "url": "https://sessions.us" + }, + { + "name": "Shottr", + "url": "https://shottr.cc" + }, + { + "name": "Signature Maker", + "url": "https://signature-maker.net" + }, + { + "name": "Skip The Drive", + "url": "https://skipthedrive.com" + }, + { + "name": "Slowby", + "url": "https://slowby.travel" + }, + { + "name": "Small World", + "url": "https://smallworld.kiwi" + }, + { + "name": "SmallPDF", + "url": "https://smallpdf.com" + }, + { + "name": "Social Image Maker", + "url": "https://socialimagemaker.io" + }, + { + "name": "Social Sizes", + "url": "https://socialsizes.io" + }, + { + "name": "SoundLove", + "url": "https://soundlove.se" + }, + { + "name": "Spline", + "url": "https://spline.design" + }, + { + "name": "Starkey Comics", + "url": "https://starkeycomics.com" + }, + + { + "name": "Statista", + "url": "https://statista.com" + }, + { + "name": "Stolen Camera Finder", + "url": "https://stolencamerafinder.com" + }, + { + "name": "Strobe.Cool", + "url": "https://strobe.cool" + }, + { + "name": "Sumo", + "url": "https://sumo.app" + }, + { + "name": "SuperMeme AI", + "url": "https://supermeme.ai" + }, + { + "name": "Synthesia", + "url": "https://synthesia.io" + }, + { + "name": "TablerIcons", + "url": "https://tablericons.com" + }, + { + "name": "Tango", + "url": "https://tango.us" + }, + { + "name": "TasteDive", + "url": "https://tastedive.com" + }, + { + "name": "TechSpecs", + "url": "https://techspecs.io" + }, + { + "name": "Teoria", + "url": "https://teoria.com" + }, + { + "name": "Text Faces", + "url": "https://textfac.es" + }, + { + "name": "The Balance Money", + "url": "https://thebalancemoney.com" + }, + { + "name": "The Punctuation Guide", + "url": "https://thepunctuationguide.com" + }, + { + "name": "This to That", + "url": "https://thistothat.com" + }, + { + "name": "This vs That", + "url": "https://thisvsthat.io" + }, + { + "name": "ThreadReaderApp ", + "url": "https://threadreaderapp.com" + }, + { + "name": "Thumbly", + "url": "https://tokee.ai" + }, + { + "name": "Tiii.me", + "url": "https://tiii.me" + }, + { + "name": "TikTok Video Downloader", + "url": "https://ttvdl.com" + }, + { + "name": "Time and Date", + "url": "https://timeanddate.com" + }, + { + "name": "Time.is", + "url": "https://time.is" + }, + { + "name": "Title Case", + "url": "https://titlecase.com" + }, + { + "name": "Toaster Central", + "url": "https://toastercentral.com" + }, + { + "name": "Tongue-Twister ", + "url": "https://tongue-twister.net" + }, + { + "name": "TradingView", + "url": "https://tradingview.com" + }, + { + "name": "Transparent Textures", + "url": "https://transparenttextures.com" + }, + { + "name": "Tubi TV", + "url": "https://tubitv.com" + }, + { + "name": "Tunefind", + "url": "https://tunefind.com" + }, + { + "name": "TuneMyMusic", + "url": "https://tunemymusic.com" + }, + { + "name": "Tweepsmap", + "url": "https://fedica.com" + }, + { + "name": "Two Peas and Their Pod", + "url": "https://twopeasandtheirpod.com" + }, + { + "name": "Typatone", + "url": "https://typatone.com" + }, + { + "name": "Under Glass", + "url": "https://underglass.io" + }, + { + "name": "UniCorner", + "url": "https://unicorner.news" + }, + { + "name": "Unita", + "url": "https://unita.co" + }, + { + "name": "UnitConverters", + "url": "https://unitconverters.net" + }, + { + "name": "Unreadit", + "url": "https://unreadit.com" + }, + { + "name": "Unscreen", + "url": "https://unscreen.com" + }, + { + "name": "UnTools ", + "url": "https://untools.co" + }, + { + "name": "Upwork", + "url": "https://upwork.com" + }, + { + "name": "UTF8 Icons", + "url": "https://utf8icons.com" + }, + { + "name": "Vector Magic", + "url": "https://vectormagic.com" + }, + { + "name": "Virtual Vacation", + "url": "https://virtualvacation.us" + }, + { + "name": "Virtual Vocations", + "url": "https://virtualvocations.com" + }, + { + "name": "Visiwig", + "url": "https://visiwig.com" + }, + { + "name": "Visual CV", + "url": "https://visualcv.com" + }, + { + "name": "Vocus.io", + "url": "https://vocus.io" + }, + { + "name": "Voscreen", + "url": "https://voscreen.com" + }, + { + "name": "Wanderprep", + "url": "https://wanderprep.com" + }, + { + "name": "Warmshowers", + "url": "https:/warmshowers.org" + }, + { + "name": "Watch Documentaries", + "url": "https://watchdocumentaries.com" + }, + { + "name": "We Work Remotely", + "url": "https://weworkremotely.com" + }, + { + "name": "Web2PDFConvert", + "url": "https://web2pdfconvert.com" + }, + { + "name": "Welcome to My Garden", + "url": "https://welcometomygarden.org" + }, + { + "name": "When2meet ", + "url": "https://when2meet.com" + }, + { + "name": "Where's George", + "url": "https://wheresgeorge.com" + }, + { + "name": "Where's Willy", + "url": "https://whereswilly.com" + }, + { + "name": "WikiHow", + "url": "https://wikihow.com" + }, + { + "name": "Windy", + "url": "https://www.windy.com" + }, + { + "name": "WonderHowTo", + "url": "https://wonderhowto.com" + }, + { + "name": "Working Nomads", + "url": "https://workingnomads.com" + }, + { + "name": "Wormhole", + "url": "https://wormhole.app" + }, + { + "name": "Y Combinator Jobs", + "url": "https://ycombinator.com" + }, + { + "name": "Yes Promo", + "url": "https://yespromo.me" + }, + { + "name": "YouGlish", + "url": "https://youglish.com" + }, + { + "name": "Zamzar", + "url": "https://zamzar.com" + }, + { + "name": "Zippyshare", + "url": "https://zippyshare.com" + }, + { + "name": "Zoom Earth", + "url": "https://zoom.earth" + }, + { + "name": "Zoom.it", + "url": "https://zoom.it" + } +] diff --git a/Server/utils/messages.js b/Server/utils/messages.js index 53a8f689f..e67e4e7e7 100644 --- a/Server/utils/messages.js +++ b/Server/utils/messages.js @@ -83,6 +83,7 @@ const successMessages = { MONITOR_DELETE: "Monitor deleted successfully", MONITOR_EDIT: "Monitor edited successfully", MONITOR_CERTIFICATE: "Got monitor certificate successfully", + MONITOR_DEMO_ADDED: "Successfully added demo monitors", //Job Queue JOB_QUEUE_DELETE_JOB: "Job removed successfully", diff --git a/Server/utils/utils.js b/Server/utils/utils.js index 934c99492..4331a4610 100644 --- a/Server/utils/utils.js +++ b/Server/utils/utils.js @@ -16,6 +16,18 @@ const ParseBoolean = (value) => { } }; +const getTokenFromHeaders = (headers) => { + const authorizationHeader = headers.authorization; + if (!authorizationHeader) throw new Error("No auth headers"); + + const parts = authorizationHeader.split(" "); + if (parts.length !== 2 || parts[0] !== "Bearer") + throw new Error("Invalid auth headers"); + + return parts[1]; +}; + module.exports = { ParseBoolean, + getTokenFromHeaders, };