diff --git a/app/components/home/monitor/layout/card.jsx b/app/components/home/monitor/layout/card.jsx index 5e4a911..7820bd4 100644 --- a/app/components/home/monitor/layout/card.jsx +++ b/app/components/home/monitor/layout/card.jsx @@ -6,7 +6,7 @@ import { useNavigate } from 'react-router-dom'; // import local files import StatusBar from '../../../ui/statusBar'; import MonitorOptions from '../options'; -import { monitorPropType } from '../../../../utils/propTypes'; +import { monitorPropType } from '../../../../../shared/utils/propTypes'; const MonitorCard = ({ monitor = {} }) => { const navigate = useNavigate(); diff --git a/app/components/home/monitor/layout/compact.jsx b/app/components/home/monitor/layout/compact.jsx index 8714274..878fcec 100644 --- a/app/components/home/monitor/layout/compact.jsx +++ b/app/components/home/monitor/layout/compact.jsx @@ -4,7 +4,7 @@ import './compact.scss'; import { useNavigate } from 'react-router-dom'; // import local files -import { monitorPropType } from '../../../../utils/propTypes'; +import { monitorPropType } from '../../../../../shared/utils/propTypes'; const MonitorList = ({ monitor = {} }) => { const navigate = useNavigate(); diff --git a/app/components/home/monitor/layout/list.jsx b/app/components/home/monitor/layout/list.jsx index cf32f8a..ef7d771 100644 --- a/app/components/home/monitor/layout/list.jsx +++ b/app/components/home/monitor/layout/list.jsx @@ -5,7 +5,7 @@ import { useNavigate } from 'react-router-dom'; // import local files import StatusBar from '../../../ui/statusBar'; -import { monitorPropType } from '../../../../utils/propTypes'; +import { monitorPropType } from '../../../../../shared/utils/propTypes'; const MonitorList = ({ monitor = {} }) => { const navigate = useNavigate(); diff --git a/app/components/modal/settings/account/password.jsx b/app/components/modal/settings/account/password.jsx index a037fc2..b4088f4 100644 --- a/app/components/modal/settings/account/password.jsx +++ b/app/components/modal/settings/account/password.jsx @@ -8,7 +8,7 @@ import RegisterChecklist from '../../../register/checklist'; import { useState } from 'react'; import { MdEye, MdEyeOff } from '../../../icons'; import handleChangePassword from '../../../../handlers/settings/account/password'; -import validators from '../../../../../server/utils/validators'; +import validators from '../../../../../shared/validators'; const SettingsAccountPasswordModal = ({ modalTitle, id, closeModal }) => { const [values, setValues] = useState({ diff --git a/app/components/modal/settings/account/username.jsx b/app/components/modal/settings/account/username.jsx index 9253b04..ebc6f2c 100644 --- a/app/components/modal/settings/account/username.jsx +++ b/app/components/modal/settings/account/username.jsx @@ -28,12 +28,7 @@ const SettingsAccountUsernameModal = ({ const submit = async () => { const value = document.getElementById(`settings-edit-${id}`).value; - const query = await handleChangeUsername( - value, - setError, - closeModal, - handleError - ); + const query = await handleChangeUsername(value, handleError, closeModal); if (query === true) { updateUsingKey('displayName', value); diff --git a/app/components/modal/settings/avatar.jsx b/app/components/modal/settings/avatar.jsx index 79de98b..b59c4e2 100644 --- a/app/components/modal/settings/avatar.jsx +++ b/app/components/modal/settings/avatar.jsx @@ -10,7 +10,7 @@ import { toast } from 'react-toastify'; import Modal from '../../ui/modal'; import useContextStore from '../../../context'; import { createPostRequest } from '../../../services/axios'; -import { userPropType } from '../../../utils/propTypes'; +import { userPropType } from '../../../../shared/utils/propTypes'; const avatars = [ 'Ape', diff --git a/app/components/modal/settings/manage/approve.jsx b/app/components/modal/settings/manage/approve.jsx index 2452a05..3fc1026 100644 --- a/app/components/modal/settings/manage/approve.jsx +++ b/app/components/modal/settings/manage/approve.jsx @@ -7,7 +7,7 @@ import { observer } from 'mobx-react-lite'; import { createPostRequest } from '../../../../services/axios'; import Modal from '../../../ui/modal'; import useTeamContext from '../../../../context/team'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const MemberApproveModal = ({ member, onClose }) => { const { updateUserVerified } = useTeamContext(); diff --git a/app/components/modal/settings/manage/decline.jsx b/app/components/modal/settings/manage/decline.jsx index ca3b933..aa3f5cd 100644 --- a/app/components/modal/settings/manage/decline.jsx +++ b/app/components/modal/settings/manage/decline.jsx @@ -6,7 +6,7 @@ import { toast } from 'react-toastify'; import { createPostRequest } from '../../../../services/axios'; import Modal from '../../../ui/modal'; import useTeamContext from '../../../../context/team'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const MemberDeclineModal = ({ member, onClose }) => { const { removeUser } = useTeamContext(); diff --git a/app/components/modal/settings/manage/delete.jsx b/app/components/modal/settings/manage/delete.jsx index 76f7dc1..82ff394 100644 --- a/app/components/modal/settings/manage/delete.jsx +++ b/app/components/modal/settings/manage/delete.jsx @@ -6,7 +6,7 @@ import { toast } from 'react-toastify'; import { createPostRequest } from '../../../../services/axios'; import Modal from '../../../ui/modal'; import useTeamContext from '../../../../context/team'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const MemberDeleteModal = ({ member, onClose }) => { const { removeUser } = useTeamContext(); diff --git a/app/components/modal/settings/manage/permissions.jsx b/app/components/modal/settings/manage/permissions.jsx index d34a7db..950a92e 100644 --- a/app/components/modal/settings/manage/permissions.jsx +++ b/app/components/modal/settings/manage/permissions.jsx @@ -10,7 +10,7 @@ import classNames from 'classnames'; import { createPostRequest } from '../../../../services/axios'; import Modal from '../../../ui/modal'; import useTeamContext from '../../../../context/team'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const MemeberPermission = ({ title, description, isActive, ...props }) => { const containerClasses = classNames('permissions-container', { diff --git a/app/components/monitor/graph/index.jsx b/app/components/monitor/graph/index.jsx index 3e114a7..21f82ca 100644 --- a/app/components/monitor/graph/index.jsx +++ b/app/components/monitor/graph/index.jsx @@ -22,7 +22,7 @@ import { Chart } from 'react-chartjs-2'; import useLocalStorageContext from '../../../hooks/useLocalstorage'; import GraphMenu from './menu'; import useGraphStatus from '../../../hooks/useGraphStatus'; -import { fullMonitorPropType } from '../../../utils/propTypes'; +import { fullMonitorPropType } from '../../../../shared/utils/propTypes'; ChartJs.register( LineController, diff --git a/app/components/monitor/status.jsx b/app/components/monitor/status.jsx index df57563..828ba79 100644 --- a/app/components/monitor/status.jsx +++ b/app/components/monitor/status.jsx @@ -1,7 +1,7 @@ import './status.scss'; // import local files -import { fullMonitorPropType } from '../../utils/propTypes'; +import { fullMonitorPropType } from '../../../shared/utils/propTypes'; const MonitorStatus = ({ monitor = [] }) => { const [lastHeartbeat = {}] = monitor.heartbeats; diff --git a/app/components/monitor/updateInfo.jsx b/app/components/monitor/updateInfo.jsx index 6c70740..2953a39 100644 --- a/app/components/monitor/updateInfo.jsx +++ b/app/components/monitor/updateInfo.jsx @@ -6,7 +6,7 @@ import moment from 'moment'; import classNames from 'classnames'; // import local files -import { heartbeatPropType } from '../../utils/propTypes'; +import { heartbeatPropType } from '../../../shared/utils/propTypes'; import useLocalStorageContext from '../../hooks/useLocalstorage'; const UptimeInfo = ({ heartbeat = {} }) => { diff --git a/app/components/monitor/uptime.jsx b/app/components/monitor/uptime.jsx index 9f2ef52..44ea044 100644 --- a/app/components/monitor/uptime.jsx +++ b/app/components/monitor/uptime.jsx @@ -5,7 +5,7 @@ import 'moment-timezone'; import PropTypes from 'prop-types'; // import local files -import { heartbeatPropType } from '../../utils/propTypes'; +import { heartbeatPropType } from '../../../shared/utils/propTypes'; import UptimeInfo from './updateInfo'; const MonitorUptime = ({ heartbeats = [] }) => { diff --git a/app/components/settings/manage/member/actions.jsx b/app/components/settings/manage/member/actions.jsx index 60f6a27..db80271 100644 --- a/app/components/settings/manage/member/actions.jsx +++ b/app/components/settings/manage/member/actions.jsx @@ -19,7 +19,7 @@ import MemberDeclineModal from '../../../modal/settings/manage/decline'; import MemberDeleteModal from '../../../modal/settings/manage/delete'; import MemberPermissionsModal from '../../../modal/settings/manage/permissions'; import useContextStore from '../../../../context'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const MemberRowActions = ({ member = {}, canManage = false }) => { const classes = classNames({ diff --git a/app/components/settings/manage/member/index.jsx b/app/components/settings/manage/member/index.jsx index d8deef1..b7d43f9 100644 --- a/app/components/settings/manage/member/index.jsx +++ b/app/components/settings/manage/member/index.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; // import local files import MemberTableRow from './row'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const MembersTable = ({ members = [] }) => { const membersList = members.map((member, index) => ( diff --git a/app/components/settings/manage/member/row.jsx b/app/components/settings/manage/member/row.jsx index 9cd4c72..1aae89f 100644 --- a/app/components/settings/manage/member/row.jsx +++ b/app/components/settings/manage/member/row.jsx @@ -7,7 +7,7 @@ import { observer } from 'mobx-react-lite'; // import local files import MemberRowActions from './actions'; import useContextStore from '../../../../context'; -import { userPropType } from '../../../../utils/propTypes'; +import { userPropType } from '../../../../../shared/utils/propTypes'; const positions = { 1: 'Owner', 2: 'Admin', 3: 'Editor', 4: 'Guest' }; diff --git a/app/components/ui/button.jsx b/app/components/ui/button.jsx index 5089927..2db3f93 100644 --- a/app/components/ui/button.jsx +++ b/app/components/ui/button.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; // import local files -import { colorPropType } from '../../utils/propTypes'; +import { colorPropType } from '../../../shared/utils/propTypes'; const Button = ({ children, diff --git a/app/components/ui/dropdown/item.jsx b/app/components/ui/dropdown/item.jsx index 1da1870..3b3085d 100644 --- a/app/components/ui/dropdown/item.jsx +++ b/app/components/ui/dropdown/item.jsx @@ -3,7 +3,7 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; // import local files -import { colorPropType } from '../../../utils/propTypes'; +import { colorPropType } from '../../../../shared/utils/propTypes'; const Item = ({ dotColor, diff --git a/app/components/ui/modal/button.jsx b/app/components/ui/modal/button.jsx index 0ab21c6..67297f8 100644 --- a/app/components/ui/modal/button.jsx +++ b/app/components/ui/modal/button.jsx @@ -3,7 +3,7 @@ import './style.scss'; // import dependencies import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { colorPropType } from '../../../utils/propTypes'; +import { colorPropType } from '../../../../shared/utils/propTypes'; const Button = ({ children, color, ...props }) => { const classes = classNames('modal-button', { diff --git a/app/components/ui/select/item.jsx b/app/components/ui/select/item.jsx index 87d7926..7f9cfaf 100644 --- a/app/components/ui/select/item.jsx +++ b/app/components/ui/select/item.jsx @@ -3,7 +3,7 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; // import local files -import { colorPropType } from '../../../utils/propTypes'; +import { colorPropType } from '../../../../shared/utils/propTypes'; const Item = ({ dotColor, diff --git a/app/components/ui/statusBar.jsx b/app/components/ui/statusBar.jsx index 7a00f3c..6b3257a 100644 --- a/app/components/ui/statusBar.jsx +++ b/app/components/ui/statusBar.jsx @@ -4,7 +4,7 @@ import './statusBar.scss'; import PropTypes from 'prop-types'; // import local files -import { heartbeatPropType } from '../../utils/propTypes'; +import { heartbeatPropType } from '../../../shared/utils/propTypes'; const StatusBar = ({ heartbeats = {}, maxHeartbeats = 12 }) => { const heartbeatList = []; diff --git a/app/handlers/login.js b/app/handlers/login.js index 3b16f4f..58bd44e 100644 --- a/app/handlers/login.js +++ b/app/handlers/login.js @@ -3,7 +3,7 @@ import { toast } from 'react-toastify'; // import local files import { createPostRequest } from '../services/axios'; -import * as validators from '../utils/validators'; +import validators from '../../shared/validators'; const handleLogin = async (inputs, setErrors, navigate) => { try { diff --git a/app/handlers/register.js b/app/handlers/register.js index ddf734b..8f2ef12 100644 --- a/app/handlers/register.js +++ b/app/handlers/register.js @@ -3,7 +3,7 @@ import { toast } from 'react-toastify'; // import local files import { createPostRequest } from '../services/axios'; -import * as validators from '../utils/validators'; +import validators from '../../shared/validators'; const handleRegister = async (inputs, setErrors, setPage, navigate) => { try { @@ -12,7 +12,7 @@ const handleRegister = async (inputs, setErrors, setPage, navigate) => { const isInvalidPassword = validators.auth.password(password); if (isInvalidPassword) { - return setErrors({ password: isInvalidPassword }); + return setErrors(isInvalidPassword); } if (password !== confirmPassword) { diff --git a/app/handlers/settings/account/password.js b/app/handlers/settings/account/password.js index 2e23718..fb97ca0 100644 --- a/app/handlers/settings/account/password.js +++ b/app/handlers/settings/account/password.js @@ -2,7 +2,7 @@ import { toast } from 'react-toastify'; // import local files -import * as validators from '../../../utils/validators'; +import validators from '../../../../shared/validators'; import { createPostRequest } from '../../../services/axios'; const handleChangePassword = async ({ @@ -20,7 +20,7 @@ const handleChangePassword = async ({ const isInvalid = validators.auth.password(newPassword); if (isInvalid) { - return handleErrors('new', isInvalid); + return handleErrors('new', isInvalid.password); } const query = await createPostRequest('/api/user/update/password', { diff --git a/app/handlers/settings/account/username.js b/app/handlers/settings/account/username.js index 6d9f096..d12d8b6 100644 --- a/app/handlers/settings/account/username.js +++ b/app/handlers/settings/account/username.js @@ -2,20 +2,15 @@ import { toast } from 'react-toastify'; // import local files -import * as validators from '../../../utils/validators'; +import validators from '../../../../shared/validators'; import { createPostRequest } from '../../../services/axios'; -const handleChangeUsername = async ( - displayName, - setError, - closeModal, - handleErrors -) => { +const handleChangeUsername = async (displayName, handleError, closeModal) => { try { const isInvalid = validators.auth.username(displayName); if (isInvalid) { - return setError(isInvalid); + return handleError(isInvalid.username); } const query = await createPostRequest('/api/user/update/username', { @@ -29,12 +24,8 @@ const handleChangeUsername = async ( return true; } catch (error) { - if (error.response?.data?.current) { - return handleErrors('current', error.response?.data?.current); - } - - if (error?.response?.status === 400) { - return handleErrors('new', error.response.data?.message); + if (error.response?.data?.username) { + return handleError(error.response?.data?.username); } toast.error('Something went wrong, please try again later.'); diff --git a/app/hooks/useLogin.jsx b/app/hooks/useLogin.jsx index 4e0f7c3..1479fc3 100644 --- a/app/hooks/useLogin.jsx +++ b/app/hooks/useLogin.jsx @@ -2,7 +2,7 @@ import { useState } from 'react'; // import local files -import * as validators from '../utils/validators'; +import validators from '../../shared/validators'; const useLogin = () => { const [values, setValues] = useState({ @@ -18,12 +18,18 @@ const useLogin = () => { if (isInvalid) { return setValues((prev) => ({ - ...prev, - errors: { ...prev.errors, [id]: isInvalid }, + inputs: { + ...prev.inputs, + [id]: value, + }, + errors: { ...prev.errors, ...isInvalid }, })); } else { setValues((prev) => ({ - ...prev, + inputs: { + ...prev.inputs, + [id]: value, + }, errors: { ...prev.errors, [id]: null }, })); } diff --git a/app/hooks/useMonitorForm.jsx b/app/hooks/useMonitorForm.jsx index 208e65b..d5103bb 100644 --- a/app/hooks/useMonitorForm.jsx +++ b/app/hooks/useMonitorForm.jsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import handleMonitor from '../handlers/monitor'; -import monitorValidators from '../utils/validators/monitor'; +import monitorValidators from '../../shared/validators/monitor'; const initialPage = { page: 1, diff --git a/app/hooks/useRegister.jsx b/app/hooks/useRegister.jsx index a4b4ce8..95353c3 100644 --- a/app/hooks/useRegister.jsx +++ b/app/hooks/useRegister.jsx @@ -4,7 +4,7 @@ import { toast } from 'react-toastify'; // import local files import { createPostRequest } from '../services/axios'; -import * as validators from '../utils/validators'; +import validators from '../../shared/validators'; const useRegister = () => { const [values, setValues] = useState({ @@ -26,8 +26,8 @@ const useRegister = () => { ...prev, errors: { ...prev.errors, - email: isInvalidEmail, - username: isInvalidUsername, + ...isInvalidEmail, + ...isInvalidUsername, }, })); } @@ -79,7 +79,7 @@ const useRegister = () => { }, errors: { ...prev.errors, - [id]: isInvalid, + ...isInvalid, }, })); } else { diff --git a/app/pages/login.jsx b/app/pages/login.jsx index 088e0d7..7119645 100644 --- a/app/pages/login.jsx +++ b/app/pages/login.jsx @@ -16,9 +16,9 @@ const Login = () => { return (
-
Create your account
+
Signin to Lunalytics
- Please provide your name and email + Please provide your email and password
{errors['general'] && ( diff --git a/app/utils/cookies.js b/app/utils/cookies.js deleted file mode 100644 index 7639931..0000000 --- a/app/utils/cookies.js +++ /dev/null @@ -1,11 +0,0 @@ -import cookie from 'cookie'; - -const parseUserCookie = (cookies) => { - const parsedCookies = cookie.parse(cookies); - const { user } = parsedCookies; - - if (!user) return {}; - return JSON.parse(user); -}; - -export { parseUserCookie }; diff --git a/app/utils/validators/auth.js b/app/utils/validators/auth.js deleted file mode 100644 index 1381008..0000000 --- a/app/utils/validators/auth.js +++ /dev/null @@ -1,46 +0,0 @@ -// regex to check user has only letters, numbers, underscore, dash, spaces and should be 3-24 characters long -const usernameRegex = /^[a-zA-Z0-9_\- ]{3,32}$/; -// regex to check if email is valid -const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,254}$/; -// regex to check if one letter, one number or special character, atleast 8 characters long and max of 64 characters long -const passwordRegex = /^(?=.*[a-zA-Z])(?=.*[0-9!@#$%^&*~_\-+=]).{8,64}$/; - -const email = (email = '') => { - if (email.length < 3 || email.length > 254) { - return 'Email must be between 3 and 254 characters.'; - } - - if (!emailRegex.test(email)) { - return 'Email is not valid'; - } - - return false; -}; - -const username = (username = '') => { - if (username.length < 3 || username.length > 32) { - return 'Username must be between 3 and 32 characters.'; - } - - if (!usernameRegex.test(username)) { - return 'Username can only contain letters, numbers, underscores, and dashes.'; - } - - return false; -}; - -const password = (password = '') => { - if (password.length < 8 || password.length > 64) { - return 'Password must be between 8 and 64 characters.'; - } - - if (!passwordRegex.test(password)) { - return 'Password is not valid'; - } - - return false; -}; - -const auth = { email, username, password }; - -export default auth; diff --git a/app/utils/validators/index.js b/app/utils/validators/index.js deleted file mode 100644 index 81bb711..0000000 --- a/app/utils/validators/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import auth from './auth'; -import monitor from './monitor'; - -export { auth, monitor }; diff --git a/docs/internals/changelog.md b/docs/internals/changelog.md index f562bdd..dcda582 100644 --- a/docs/internals/changelog.md +++ b/docs/internals/changelog.md @@ -2,6 +2,25 @@ ## v0.5.1 +### Fixes issue with certificates and moves utils to shared folder + +### Summary + +There was a lot of duplicate code for utils in the server and app folders. I've decided to create a shared folder which now has all of the code. While moving the files, some of the validators also needed to be reworked so that they can now be used in both the front and backend code. Also, had to fix some issues with certificates not being updated properly. + +### Updates + +- Moves all utils from app and server to shared folder +- Changes file paths from utils to shared folder +- Fixes issues with certificates not being updated properly +- Updates handlers to support updated validator responses + +### Summary + +There was an issue where certificates were not being saved to the database due to the value not being parsed as a string. This has been fixed now. + +## v0.5.05 + ### Replaces Sonner with React-Toastify ### Summary diff --git a/package-lock.json b/package-lock.json index 6946c64..b7c257d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lunalytics", - "version": "0.5.0", + "version": "0.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lunalytics", - "version": "0.5.0", + "version": "0.5.1", "license": "SEE LICENSE IN LICENSE", "dependencies": { "axios": "^1.6.2", @@ -40,7 +40,7 @@ "@vitest/coverage-v8": "^1.6.0", "concurrently": "^8.2.2", "cross-env": "^7.0.3", - "cypress": "^13.8.1", + "cypress": "^13.12.0", "eslint": "^8.53.0", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", @@ -3439,12 +3439,11 @@ "license": "MIT" }, "node_modules/cypress": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.9.0.tgz", - "integrity": "sha512-atNjmYfHsvTuCaxTxLZr9xGoHz53LLui3266WWxXJHY7+N6OdwJdg/feEa3T+buez9dmUXHT1izCOklqG82uCQ==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.12.0.tgz", + "integrity": "sha512-udzS2JilmI9ApO/UuqurEwOvThclin5ntz7K0BtnHBs+tg2Bl9QShLISXpSEMDv/u8b6mqdoAdyKeZiSqKWL8g==", "dev": true, "hasInstallScript": true, - "license": "MIT", "dependencies": { "@cypress/request": "^3.0.0", "@cypress/xvfb": "^1.2.4", diff --git a/package.json b/package.json index ea22420..88d6c78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lunalytics", - "version": "0.5.0", + "version": "0.5.1", "description": "Open source Node.js server/website monitoring tool", "private": true, "author": "KSJaay ", @@ -65,7 +65,7 @@ "@vitest/coverage-v8": "^1.6.0", "concurrently": "^8.2.2", "cross-env": "^7.0.3", - "cypress": "^13.8.1", + "cypress": "^13.12.0", "eslint": "^8.53.0", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/scripts/loadEnv.js b/scripts/loadEnv.js index 1fcceea..3d95360 100644 --- a/scripts/loadEnv.js +++ b/scripts/loadEnv.js @@ -1,6 +1,6 @@ import { existsSync, readFileSync } from 'fs'; import path from 'path'; -import logger from '../server/utils/logger.js'; +import logger from '../shared/utils/logger.js'; const configPath = path.join(process.cwd(), 'config.json'); diff --git a/scripts/migrate.js b/scripts/migrate.js index be67dc1..fb91941 100644 --- a/scripts/migrate.js +++ b/scripts/migrate.js @@ -3,7 +3,7 @@ import fs from 'fs'; import path from 'path'; // import local files -import logger from '../server/utils/logger.js'; +import logger from '../shared/utils/logger.js'; import migrationList from '../server/migrations/index.js'; import { loadJSON } from '../shared/parseJson.js'; diff --git a/scripts/reset.js b/scripts/reset.js index 5987cc7..c93930b 100644 --- a/scripts/reset.js +++ b/scripts/reset.js @@ -4,9 +4,9 @@ import '../scripts/loadEnv.js'; import inquirer from 'inquirer'; // import local files -import logger from '../server/utils/logger.js'; +import logger from '../shared/utils/logger.js'; import SQLite from '../server/database/sqlite/setup.js'; -import { generateHash } from '../server/utils/hashPassword.js'; +import { generateHash } from '../shared/utils/hashPassword.js'; const questions = [ { type: 'input', name: 'email', message: 'Enter email added:' }, diff --git a/scripts/setup.js b/scripts/setup.js index 9a1228e..aba7015 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -5,7 +5,7 @@ import inquirer from 'inquirer'; import { v4 as uuidv4 } from 'uuid'; // import local files -import logger from '../server/utils/logger.js'; +import logger from '../shared/utils/logger.js'; import { loadJSON } from '../shared/parseJson.js'; const packageJson = loadJSON('../package.json'); diff --git a/server/cache/certificates.js b/server/cache/certificates.js index 149c8fc..743409d 100644 --- a/server/cache/certificates.js +++ b/server/cache/certificates.js @@ -28,15 +28,12 @@ class Certificates { delete certificate.lastCheck; delete certificate.nextCheck; - await updateCertificate(monitorId, { - ...certificate, - issuer: JSON.stringify(certificate.issuer), - }); + await updateCertificate(monitorId, certificate); certificate.lastCheck = Date.now(); certificate.nextCheck = certificate.lastCheck + 86400000; - this.certificates.set(monitorId, certificate); + this.certificates.set(monitorId, cleanCertificate(certificate)); } async delete(monitorId) { diff --git a/server/cache/index.js b/server/cache/index.js index 53bc632..0a65368 100644 --- a/server/cache/index.js +++ b/server/cache/index.js @@ -2,7 +2,7 @@ import Certificates from './certificates.js'; import Heartbeats from './heartbeats.js'; import Monitor from './monitors.js'; -import getCertInfo, { parseCert } from '../tools/checkCertificate.js'; +import getCertInfo from '../tools/checkCertificate.js'; import httpStatusCheck from '../tools/httpStatus.js'; import tcpStatusCheck from '../tools/tcpPing.js'; @@ -70,21 +70,12 @@ class Master { const heartbeat = await httpStatusCheck(monitor); await this.heartbeats.addHeartbeat(heartbeat); - if (monitor.url?.startsWith('https://')) { + if (monitor.url?.toLowerCase().startsWith('https')) { const certificate = await this.certificates.get(monitorId); if (!certificate?.nextCheck || certificate.nextCheck <= Date.now()) { const cert = await getCertInfo(monitor.url); - - if (cert) { - await this.certificates.update( - monitorId, - parseCert({ - ...certificate, - ...cert, - }) - ); - } + await this.certificates.update(monitorId, cert); } } diff --git a/server/database/queries/monitor.js b/server/database/queries/monitor.js index 93b5f3f..c5dd4f4 100644 --- a/server/database/queries/monitor.js +++ b/server/database/queries/monitor.js @@ -1,7 +1,7 @@ import SQLite from '../sqlite/setup.js'; -import randomId from '../../utils/randomId.js'; -import { timeToMs } from '../../utils/ms.js'; -import { UnprocessableError } from '../../utils/errors.js'; +import randomId from '../../../shared/utils/randomId.js'; +import { timeToMs } from '../../../shared/utils/ms.js'; +import { UnprocessableError } from '../../../shared/utils/errors.js'; const monitorExists = async (monitorId) => { return SQLite.client('monitor').where({ id: monitorId }).first(); diff --git a/server/database/queries/user.js b/server/database/queries/user.js index a65f368..a0674bb 100644 --- a/server/database/queries/user.js +++ b/server/database/queries/user.js @@ -1,7 +1,13 @@ import SQLite from '../sqlite/setup.js'; -import { generateHash, verifyPassword } from '../../utils/hashPassword.js'; -import { signCookie, verifyCookie } from '../../utils/jwt.js'; -import { AuthorizationError, ConflictError } from '../../utils/errors.js'; +import { + generateHash, + verifyPassword, +} from '../../../shared/utils/hashPassword.js'; +import { signCookie, verifyCookie } from '../../../shared/utils/jwt.js'; +import { + AuthorizationError, + ConflictError, +} from '../../../shared/utils/errors.js'; const passwordMatches = (user, password) => { const passwordMatches = verifyPassword(password, user.password); diff --git a/server/database/sqlite/setup.js b/server/database/sqlite/setup.js index 4a4b91d..e56c955 100644 --- a/server/database/sqlite/setup.js +++ b/server/database/sqlite/setup.js @@ -1,7 +1,7 @@ import { existsSync, closeSync, openSync } from 'fs'; import knex from 'knex'; -import logger from '../../utils/logger.js'; +import logger from '../../../shared/utils/logger.js'; export class SQLite { constructor() { diff --git a/server/index.js b/server/index.js index af4d8c5..c6c7949 100644 --- a/server/index.js +++ b/server/index.js @@ -8,10 +8,10 @@ import cookieParser from 'cookie-parser'; // import local files import cache from './cache/index.js'; -import logger from './utils/logger.js'; +import logger from '../shared/utils/logger.js'; import initialiseRoutes from './routes/index.js'; import SQLite from './database/sqlite/setup.js'; -import initialiseCronJobs from './utils/cron.js'; +import initialiseCronJobs from './../shared/utils/cron.js'; import authorization from './middleware/authorization.js'; import migrateDatabase from '../scripts/migrate.js'; import isDemo from './middleware/demo.js'; diff --git a/server/middleware/auth/login.js b/server/middleware/auth/login.js index 90c20f5..9f7f4ce 100644 --- a/server/middleware/auth/login.js +++ b/server/middleware/auth/login.js @@ -1,8 +1,11 @@ // import local files import { signInUser } from '../../database/queries/user.js'; -import { setServerSideCookie } from '../../utils/cookies.js'; -import { handleError, UnprocessableError } from '../../utils/errors.js'; -import validators from '../../utils/validators/index.js'; +import { setServerSideCookie } from '../../../shared/utils/cookies.js'; +import { + handleError, + UnprocessableError, +} from '../../../shared/utils/errors.js'; +import validators from '../../../shared/validators/index.js'; const login = async (request, response) => { try { diff --git a/server/middleware/auth/logout.js b/server/middleware/auth/logout.js index 8923832..4fdd248 100644 --- a/server/middleware/auth/logout.js +++ b/server/middleware/auth/logout.js @@ -1,6 +1,6 @@ -import { deleteCookie } from '../../utils/cookies.js'; -import { handleError } from '../../utils/errors.js'; -import { createURL } from '../../utils/url.js'; +import { deleteCookie } from '../../../shared/utils/cookies.js'; +import { handleError } from '../../../shared/utils/errors.js'; +import { createURL } from '../../../shared/utils/url.js'; const logout = (request, response) => { try { diff --git a/server/middleware/auth/register.js b/server/middleware/auth/register.js index 683bd9b..63844fe 100644 --- a/server/middleware/auth/register.js +++ b/server/middleware/auth/register.js @@ -1,8 +1,11 @@ // import local files import { registerUser, fetchMembers } from '../../database/queries/user.js'; -import { setServerSideCookie } from '../../utils/cookies.js'; -import { handleError, UnprocessableError } from '../../utils/errors.js'; -import validators from '../../utils/validators/index.js'; +import { setServerSideCookie } from '../../../shared/utils/cookies.js'; +import { + handleError, + UnprocessableError, +} from '../../../shared/utils/errors.js'; +import validators from '../../../shared/validators/index.js'; const register = async (request, response) => { try { diff --git a/server/middleware/authorization.js b/server/middleware/authorization.js index 4c7b27e..9d20489 100644 --- a/server/middleware/authorization.js +++ b/server/middleware/authorization.js @@ -1,5 +1,5 @@ import { userExists } from '../database/queries/user.js'; -import { deleteCookie } from '../utils/cookies.js'; +import { deleteCookie } from '../../shared/utils/cookies.js'; const authorization = async (request, response, next) => { const { access_token } = request.cookies; diff --git a/server/middleware/demo.js b/server/middleware/demo.js index ed6c467..8fb20c3 100644 --- a/server/middleware/demo.js +++ b/server/middleware/demo.js @@ -1,10 +1,14 @@ import { getDemoUser } from '../database/queries/user.js'; -import { setDemoCookie } from '../utils/cookies.js'; +import { setDemoCookie } from '../../shared/utils/cookies.js'; const isDemo = async (request, response, next) => { const { access_token } = request.cookies; - if (process.env.IS_DEMO === 'enabled' && !access_token) { + if ( + process.env.NODE_ENV === 'production' && + process.env.IS_DEMO === 'enabled' && + !access_token + ) { if ( !request.url.startsWith('/register') && !request.url.startsWith('/login') diff --git a/server/middleware/monitor/add.js b/server/middleware/monitor/add.js index 0e3cdf4..89dd974 100644 --- a/server/middleware/monitor/add.js +++ b/server/middleware/monitor/add.js @@ -1,6 +1,9 @@ // import local files -import { handleError, UnprocessableError } from '../../utils/errors.js'; -import * as validators from '../../utils/validators/monitor.js'; +import { + handleError, + UnprocessableError, +} from '../../../shared/utils/errors.js'; +import validators from '../../../shared/validators/monitor.js'; import cache from '../../cache/index.js'; import { userExists } from '../../database/queries/user.js'; import { cleanMonitor } from '../../class/monitor.js'; diff --git a/server/middleware/monitor/delete.js b/server/middleware/monitor/delete.js index 1d45498..76ea8f7 100644 --- a/server/middleware/monitor/delete.js +++ b/server/middleware/monitor/delete.js @@ -1,6 +1,9 @@ // import local files import cache from '../../cache/index.js'; -import { UnprocessableError, handleError } from '../../utils/errors.js'; +import { + UnprocessableError, + handleError, +} from '../../../shared/utils/errors.js'; const monitorDelete = async (request, response) => { try { diff --git a/server/middleware/monitor/edit.js b/server/middleware/monitor/edit.js index 73ec1c9..444befa 100644 --- a/server/middleware/monitor/edit.js +++ b/server/middleware/monitor/edit.js @@ -1,6 +1,9 @@ // import local files -import { handleError, UnprocessableError } from '../../utils/errors.js'; -import * as validators from '../../utils/validators/monitor.js'; +import { + handleError, + UnprocessableError, +} from '../../../shared/utils/errors.js'; +import validators from '../../../shared/validators/monitor.js'; import cache from '../../cache/index.js'; import { userExists } from '../../database/queries/user.js'; import { cleanMonitor } from '../../class/monitor.js'; diff --git a/server/middleware/monitor/id.js b/server/middleware/monitor/id.js index 93368e5..9fe1acb 100644 --- a/server/middleware/monitor/id.js +++ b/server/middleware/monitor/id.js @@ -1,6 +1,9 @@ import cache from '../../cache/index.js'; import { cleanMonitor } from '../../class/monitor.js'; -import { UnprocessableError, handleError } from '../../utils/errors.js'; +import { + UnprocessableError, + handleError, +} from '../../../shared/utils/errors.js'; const fetchMonitorUsingId = async (request, response) => { try { diff --git a/server/middleware/monitor/status.js b/server/middleware/monitor/status.js index cc63518..8211217 100644 --- a/server/middleware/monitor/status.js +++ b/server/middleware/monitor/status.js @@ -1,5 +1,8 @@ import cache from '../../cache/index.js'; -import { UnprocessableError, handleError } from '../../utils/errors.js'; +import { + UnprocessableError, + handleError, +} from '../../../shared/utils/errors.js'; const validTypes = ['latest', 'day', 'week', 'month']; const fetchMonitorStatus = async (request, response) => { diff --git a/server/middleware/user/access/approveUser.js b/server/middleware/user/access/approveUser.js index 837e0cc..3f22439 100644 --- a/server/middleware/user/access/approveUser.js +++ b/server/middleware/user/access/approveUser.js @@ -1,5 +1,5 @@ import { approveAccess } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; +import { handleError } from '../../../../shared/utils/errors.js'; const accessApproveMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/access/declineUser.js b/server/middleware/user/access/declineUser.js index ec52398..a8d1a23 100644 --- a/server/middleware/user/access/declineUser.js +++ b/server/middleware/user/access/declineUser.js @@ -1,5 +1,5 @@ import { declineAccess } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; +import { handleError } from '../../../../shared/utils/errors.js'; const accessDeclineMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/access/removeUser.js b/server/middleware/user/access/removeUser.js index 014ee5a..6316757 100644 --- a/server/middleware/user/access/removeUser.js +++ b/server/middleware/user/access/removeUser.js @@ -1,5 +1,5 @@ import { declineAccess } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; +import { handleError } from '../../../../shared/utils/errors.js'; const accessRemoveMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/deleteAccount.js b/server/middleware/user/deleteAccount.js index 975c0cb..d215ca4 100644 --- a/server/middleware/user/deleteAccount.js +++ b/server/middleware/user/deleteAccount.js @@ -1,5 +1,5 @@ import { userExists, declineAccess } from '../../database/queries/user.js'; -import { handleError } from '../../utils/errors.js'; +import { handleError } from '../../../shared/utils/errors.js'; const deleteAccountMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/hasAdmin.js b/server/middleware/user/hasAdmin.js index 7213bf6..8a9e4ac 100644 --- a/server/middleware/user/hasAdmin.js +++ b/server/middleware/user/hasAdmin.js @@ -1,5 +1,5 @@ import { userExists } from '../../database/queries/user.js'; -import { handleError } from '../../utils/errors.js'; +import { handleError } from '../../../shared/utils/errors.js'; const hasAdminPermissions = async (request, response, next) => { try { diff --git a/server/middleware/user/hasEditor.js b/server/middleware/user/hasEditor.js index 78c4d87..0de5e55 100644 --- a/server/middleware/user/hasEditor.js +++ b/server/middleware/user/hasEditor.js @@ -1,5 +1,5 @@ import { userExists } from '../../database/queries/user.js'; -import { handleError } from '../../utils/errors.js'; +import { handleError } from '../../../shared/utils/errors.js'; const hasEditorPermissions = async (request, response, next) => { try { diff --git a/server/middleware/user/permission/update.js b/server/middleware/user/permission/update.js index 17b01bb..8199b15 100644 --- a/server/middleware/user/permission/update.js +++ b/server/middleware/user/permission/update.js @@ -2,7 +2,7 @@ import { userExists, updateUserPermission, } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; +import { handleError } from '../../../../shared/utils/errors.js'; const permissionUpdateMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/team/members.js b/server/middleware/user/team/members.js index 1c1929b..fedc1a4 100644 --- a/server/middleware/user/team/members.js +++ b/server/middleware/user/team/members.js @@ -1,5 +1,5 @@ import { fetchMembers } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; +import { handleError } from '../../../../shared/utils/errors.js'; const teamMembersListMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/transferOwnership.js b/server/middleware/user/transferOwnership.js index afabd1d..1afd4e5 100644 --- a/server/middleware/user/transferOwnership.js +++ b/server/middleware/user/transferOwnership.js @@ -3,7 +3,7 @@ import { transferOwnership, userExists, } from '../../database/queries/user.js'; -import { handleError } from '../../utils/errors.js'; +import { handleError } from '../../../shared/utils/errors.js'; const transferOwnershipMiddleware = async (request, response) => { try { diff --git a/server/middleware/user/update/avatar.js b/server/middleware/user/update/avatar.js index 8eb8fa5..3e5c1b3 100644 --- a/server/middleware/user/update/avatar.js +++ b/server/middleware/user/update/avatar.js @@ -2,8 +2,8 @@ import { userExists, updateUserAvatar, } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; -import validators from '../../../utils/validators/index.js'; +import { handleError } from '../../../../shared/utils/errors.js'; +import validators from '../../../../shared/validators/index.js'; const userUpdateAvatar = async (request, response) => { try { diff --git a/server/middleware/user/update/password.js b/server/middleware/user/update/password.js index 3dc79b1..3281d20 100644 --- a/server/middleware/user/update/password.js +++ b/server/middleware/user/update/password.js @@ -2,9 +2,9 @@ import { updateUserPassword, userExists, } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; -import { verifyPassword } from '../../../utils/hashPassword.js'; -import validators from '../../../utils/validators/index.js'; +import { handleError } from '../../../../shared/utils/errors.js'; +import { verifyPassword } from '../../../../shared/utils/hashPassword.js'; +import validators from '../../../../shared/validators/index.js'; const userUpdatePassword = async (request, response) => { try { diff --git a/server/middleware/user/update/username.js b/server/middleware/user/update/username.js index 8b4946a..7e15f80 100644 --- a/server/middleware/user/update/username.js +++ b/server/middleware/user/update/username.js @@ -2,8 +2,8 @@ import { updateUserDisplayname, userExists, } from '../../../database/queries/user.js'; -import { handleError } from '../../../utils/errors.js'; -import validators from '../../../utils/validators/index.js'; +import { handleError } from '../../../../shared/utils/errors.js'; +import validators from '../../../../shared/validators/index.js'; const userUpdateUsername = async (request, response) => { try { diff --git a/server/migrations/tcpUpdate-0-4-0.js b/server/migrations/tcpUpdate-0-4-0.js index 74bb0d5..02fda38 100644 --- a/server/migrations/tcpUpdate-0-4-0.js +++ b/server/migrations/tcpUpdate-0-4-0.js @@ -1,6 +1,6 @@ // import local files import SQLite from '../database/sqlite/setup.js'; -import logger from '../utils/logger.js'; +import logger from '../../shared/utils/logger.js'; const infomation = { title: 'Support for TCP pings', diff --git a/server/tools/checkCertificate.js b/server/tools/checkCertificate.js index 02efb79..3ebcf02 100644 --- a/server/tools/checkCertificate.js +++ b/server/tools/checkCertificate.js @@ -1,6 +1,6 @@ import https from 'https'; import axios from 'axios'; -import logger from '../utils/logger.js'; +import logger from '../../shared/utils/logger.js'; const getCertInfo = async (url) => { try { @@ -17,16 +17,14 @@ const getCertInfo = async (url) => { } catch (error) { logger.error('getCertInfo', error); - return { - isValid: false, - }; + return { isValid: false }; } }; const checkCertificate = (res) => { if (!res.request.socket) { logger.error('checkCertificate', 'Socket not found'); - throw new Error('Socket not found'); + return { isValid: false }; } const info = res.request.socket.getPeerCertificate(true); @@ -34,10 +32,7 @@ const checkCertificate = (res) => { const parsedInfo = parseCert(info); - return { - isValid: valid, - ...parsedInfo, - }; + return { isValid: valid, ...parsedInfo }; }; const getDaysBetween = (validFrom, validTo) => @@ -51,7 +46,7 @@ const getDaysRemaining = (validFrom, validTo) => { return daysRemaining; }; -export const parseCert = (cert) => { +const parseCert = (cert) => { const validOn = cert.subjectaltname ?.replace(/DNS:|IP Address:/g, '') .split(', '); diff --git a/server/tools/httpStatus.js b/server/tools/httpStatus.js index f99f2f6..335d933 100644 --- a/server/tools/httpStatus.js +++ b/server/tools/httpStatus.js @@ -2,7 +2,7 @@ import axios from 'axios'; // import local files -import logger from '../utils/logger.js'; +import logger from '../../shared/utils/logger.js'; const httpStatusCheck = async (monitor) => { const options = { diff --git a/server/tools/tcpPing.js b/server/tools/tcpPing.js index 936ad81..7935b68 100644 --- a/server/tools/tcpPing.js +++ b/server/tools/tcpPing.js @@ -2,7 +2,7 @@ import net from 'net'; // import local files -import logger from '../utils/logger.js'; +import logger from '../../shared/utils/logger.js'; const tcpStatusCheck = async (monitor, callback) => { const socket = new net.Socket(); diff --git a/server/utils/ms.js b/server/utils/ms.js deleted file mode 100644 index 21e2403..0000000 --- a/server/utils/ms.js +++ /dev/null @@ -1,13 +0,0 @@ -const timeToMs = (duration, type = 'hours') => { - const types = { - months: 2592000000, - days: 86400000, - hours: 3600000, - minutes: 60000, - seconds: 1000, - }; - - return duration * types[type]; -}; - -export { timeToMs }; diff --git a/server/utils/validators/monitor.js b/server/utils/validators/monitor.js deleted file mode 100644 index f1c7b21..0000000 --- a/server/utils/validators/monitor.js +++ /dev/null @@ -1,121 +0,0 @@ -const validMethods = [ - 'DELETE', - 'GET', - 'HEAD', - 'OPTIONS', - 'PATCH', - 'POST', - 'PUT', -]; - -const validTypes = ['http', 'tcp']; - -const http = ({ - name, - type, - url, - method, - valid_status_codes, - interval, - retryInterval, - requestTimeout, -}) => { - if (!type || !validTypes.includes(type)) { - return 'Please select a valid monitor type.'; - } - - if (!name || !/^[a-zA-Z0-9-]+$/.test(name)) { - return 'Please enter a valid name. Only letters, numbers and - are allowed.'; - } - - const urlRegex = /^(http|https):\/\/[^ "]+$/; - - if (!url || !urlRegex.test(url)) { - return 'Please enter a valid URL.'; - } - - if (!method || !validMethods.includes(method)) { - return 'Please select a valid method.'; - } - if (!valid_status_codes || !valid_status_codes.length) { - return 'Please select at least one status code.'; - } - - if (!interval) { - return 'Please enter a valid interval.'; - } - - if (interval < 20 || interval > 600) { - return 'Please enter a valid interval. Interval should be between 20 and 600 seconds.'; - } - - if (!retryInterval) { - return 'Please enter a valid retry interval.'; - } - - if (retryInterval < 20 || retryInterval > 600) { - return 'Please enter a valid retry interval. Retry interval should be between 20 and 600 seconds.'; - } - - if (!requestTimeout) { - return 'Please enter a valid request timeout.'; - } - - if (requestTimeout < 20 || requestTimeout > 600) { - return 'Please enter a valid request timeout. Request timeout should be between 20 and 600 seconds.'; - } -}; - -const tcp = ({ - type, - name, - url, - port, - interval, - retryInterval, - requestTimeout, -}) => { - if (!type || !validTypes.includes(type)) { - return 'Please select a valid monitor type.'; - } - - if (!name || !/^[a-zA-Z0-9-]+$/.test(name)) { - return 'Please enter a valid name. Only letters, numbers and - are allowed.'; - } - - const isIpv4 = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/; - - if (!url || !isIpv4.test(url)) { - return 'Please enter a valid host (Only IPv4 is valid).'; - } - - if (!port || port < 1 || port > 65535) { - return 'Please enter a valid port.'; - } - - if (!interval) { - return 'Please enter a valid interval.'; - } - - if (interval < 20 || interval > 600) { - return 'Please enter a valid interval. Interval should be between 20 and 600 seconds.'; - } - - if (!retryInterval) { - return 'Please enter a valid retry interval.'; - } - - if (retryInterval < 20 || retryInterval > 600) { - return 'Please enter a valid retry interval. Retry interval should be between 20 and 600 seconds.'; - } - - if (!requestTimeout) { - return 'Please enter a valid request timeout.'; - } - - if (requestTimeout < 20 || requestTimeout > 600) { - return 'Please enter a valid request timeout. Request timeout should be between 20 and 600 seconds.'; - } -}; - -export { http, tcp }; diff --git a/server/utils/validators/user.js b/server/utils/validators/user.js deleted file mode 100644 index fcf8881..0000000 --- a/server/utils/validators/user.js +++ /dev/null @@ -1,41 +0,0 @@ -const defaultAvatars = [ - 'Ape', - 'Bear', - 'Cat', - 'Dog', - 'Doggo', - 'Duck', - 'Eagle', - 'Fox', - 'Gerbil', - 'Hamster', - 'Hedgehog', - 'Koala', - 'Ostrich', - 'Panda', - 'Rabbit', - 'Rocket', - 'Tiger', -]; - -const isImageUrl = (url) => { - if (typeof url !== 'string') { - return false; - } - - return url.match(/^https?:\/\/.+\.(jpg|jpeg|png|gif)$/gim); -}; - -const isAvatar = (avatar) => { - if (avatar === null) { - return false; - } - - if (!defaultAvatars.includes(avatar) && !isImageUrl(avatar)) { - return 'Avatar must be a valid Imgur URL or one of the default avatars.'; - } - - return false; -}; - -export { isAvatar }; diff --git a/server/utils/cookies.js b/shared/utils/cookies.js similarity index 100% rename from server/utils/cookies.js rename to shared/utils/cookies.js diff --git a/server/utils/cron.js b/shared/utils/cron.js similarity index 95% rename from server/utils/cron.js rename to shared/utils/cron.js index 040a11a..16f4137 100644 --- a/server/utils/cron.js +++ b/shared/utils/cron.js @@ -2,12 +2,12 @@ import { CronJob } from 'cron'; // import local files -import cache from '../cache/index.js'; +import cache from '../../server/cache/index.js'; import logger from './logger.js'; import { fetchHeartbeatsByDate, fetchLastDailyHeartbeat, -} from '../database/queries/heartbeat.js'; +} from '../../server/database/queries/heartbeat.js'; // fetch all monitors // fetch only heartbeats that are up for each monitor diff --git a/server/utils/errors.js b/shared/utils/errors.js similarity index 100% rename from server/utils/errors.js rename to shared/utils/errors.js diff --git a/server/utils/hashPassword.js b/shared/utils/hashPassword.js similarity index 100% rename from server/utils/hashPassword.js rename to shared/utils/hashPassword.js diff --git a/server/utils/jwt.js b/shared/utils/jwt.js similarity index 100% rename from server/utils/jwt.js rename to shared/utils/jwt.js diff --git a/server/utils/logger.js b/shared/utils/logger.js similarity index 100% rename from server/utils/logger.js rename to shared/utils/logger.js diff --git a/app/utils/ms.js b/shared/utils/ms.js similarity index 80% rename from app/utils/ms.js rename to shared/utils/ms.js index 97a5e2a..e953de0 100644 --- a/app/utils/ms.js +++ b/shared/utils/ms.js @@ -1,3 +1,15 @@ +const timeToMs = (duration, type = 'hours') => { + const types = { + months: 2592000000, + days: 86400000, + hours: 3600000, + minutes: 60000, + seconds: 1000, + }; + + return duration * types[type]; +}; + const msToTime = (duration) => { let seconds = Math.floor((duration / 1000) % 60); let minutes = Math.floor((duration / (1000 * 60)) % 60); @@ -35,4 +47,4 @@ const msToTime = (duration) => { return 'Unknown'; }; -export { msToTime }; +export { msToTime, timeToMs }; diff --git a/app/utils/propTypes.js b/shared/utils/propTypes.js similarity index 100% rename from app/utils/propTypes.js rename to shared/utils/propTypes.js diff --git a/server/utils/randomId.js b/shared/utils/randomId.js similarity index 100% rename from server/utils/randomId.js rename to shared/utils/randomId.js diff --git a/server/utils/url.js b/shared/utils/url.js similarity index 100% rename from server/utils/url.js rename to shared/utils/url.js diff --git a/server/utils/validators/auth.js b/shared/validators/auth.js similarity index 100% rename from server/utils/validators/auth.js rename to shared/validators/auth.js diff --git a/server/utils/validators/index.js b/shared/validators/index.js similarity index 100% rename from server/utils/validators/index.js rename to shared/validators/index.js diff --git a/app/utils/validators/monitor.js b/shared/validators/monitor.js similarity index 65% rename from app/utils/validators/monitor.js rename to shared/validators/monitor.js index e4e1a63..b8fd664 100644 --- a/app/utils/validators/monitor.js +++ b/shared/validators/monitor.js @@ -86,7 +86,7 @@ export const requestTimeout = (requestTimeout) => { } }; -const monitorValidators = { +const validators = { type, name, httpUrl, @@ -99,4 +99,61 @@ const monitorValidators = { requestTimeout, }; -export default monitorValidators; +const httpValidators = [ + ['name', 'name'], + ['type', 'type'], + ['url', 'httpUrl'], + ['method', 'httpMethod'], + ['valid_status_codes', 'httpStatusCodes'], + ['interval', 'interval'], + ['retryInterval', 'retryInterval'], + ['requestTimeout', 'requestTimeout'], +]; + +const tcpValidators = [ + ['name', 'name'], + ['type', 'type'], + ['url', 'tcpHost'], + ['port', 'tcpPort'], + ['interval', 'interval'], + ['retryInterval', 'retryInterval'], + ['requestTimeout', 'requestTimeout'], +]; + +const http = (data) => { + const errors = httpValidators + .map((validator) => { + const error = validators[validator[1]](data[validator[0]]); + if (error) { + return error; + } + }) + .filter(Boolean); + + if (errors.length) { + return errors[0]; + } + + return false; +}; + +const tcp = (data) => { + const errors = tcpValidators + .map((validator) => { + const error = validators[validator[1]](data[validator[0]]); + if (error) { + return error; + } + }) + .filter(Boolean); + + console.log(errors); + + if (errors.length) { + return errors[0]; + } + + return false; +}; + +export default { ...validators, http, tcp }; diff --git a/app/utils/validators/user.js b/shared/validators/user.js similarity index 89% rename from app/utils/validators/user.js rename to shared/validators/user.js index fcf8881..538e4e6 100644 --- a/app/utils/validators/user.js +++ b/shared/validators/user.js @@ -32,7 +32,7 @@ const isAvatar = (avatar) => { } if (!defaultAvatars.includes(avatar) && !isImageUrl(avatar)) { - return 'Avatar must be a valid Imgur URL or one of the default avatars.'; + return 'Avatar must be a valid image URL or one of the default avatars.'; } return false; diff --git a/test/server/middleware/auth/login.test.js b/test/server/middleware/auth/login.test.js index 723c40b..ae88592 100644 --- a/test/server/middleware/auth/login.test.js +++ b/test/server/middleware/auth/login.test.js @@ -2,12 +2,12 @@ import { beforeEach, describe, it, vi } from 'vitest'; import { createRequest, createResponse } from 'node-mocks-http'; import SQLite from '../../../../server/database/sqlite/setup'; import login from '../../../../server/middleware/auth/login'; -import { setServerSideCookie } from '../../../../server/utils/cookies'; +import { setServerSideCookie } from '../../../../shared/utils/cookies'; import { signInUser } from '../../../../server/database/queries/user'; vi.mock('../../../../server/database/sqlite/setup'); vi.mock('../../../../server/database/queries/user'); -vi.mock('../../../../server/utils/cookies'); +vi.mock('../../../../shared/utils/cookies'); describe('Login - Middleware', () => { const user = { diff --git a/test/server/middleware/auth/logout.test.js b/test/server/middleware/auth/logout.test.js index c0cdcb5..94efb2e 100644 --- a/test/server/middleware/auth/logout.test.js +++ b/test/server/middleware/auth/logout.test.js @@ -1,9 +1,9 @@ import { createRequest, createResponse } from 'node-mocks-http'; -import { deleteCookie } from '../../../../server/utils/cookies'; +import { deleteCookie } from '../../../../shared/utils/cookies'; import logout from '../../../../server/middleware/auth/logout'; -import { createURL } from '../../../../server/utils/url'; +import { createURL } from '../../../../shared/utils/url'; -vi.mock('../../../../server/utils/cookies'); +vi.mock('../../../../shared/utils/cookies'); describe('Logout - Middleware', () => { let fakeRequest; diff --git a/test/server/middleware/auth/register.test.js b/test/server/middleware/auth/register.test.js index 5e86d90..343b16e 100644 --- a/test/server/middleware/auth/register.test.js +++ b/test/server/middleware/auth/register.test.js @@ -5,10 +5,10 @@ import { fetchMembers, registerUser, } from '../../../../server/database/queries/user'; -import { setServerSideCookie } from '../../../../server/utils/cookies'; +import { setServerSideCookie } from '../../../../shared/utils/cookies'; vi.mock('../../../../server/database/queries/user'); -vi.mock('../../../../server/utils/cookies'); +vi.mock('../../../../shared/utils/cookies'); describe('Register - Middleware', () => { let fakeRequest; diff --git a/test/server/middleware/authorization.test.js b/test/server/middleware/authorization.test.js index 39c23fc..12e57ab 100644 --- a/test/server/middleware/authorization.test.js +++ b/test/server/middleware/authorization.test.js @@ -2,10 +2,10 @@ import { createRequest, createResponse } from 'node-mocks-http'; import { afterEach, beforeEach, describe, it, vi } from 'vitest'; import { userExists } from '../../../server/database/queries/user'; import authorization from '../../../server/middleware/authorization'; -import { deleteCookie } from '../../../server/utils/cookies'; +import { deleteCookie } from '../../../shared/utils/cookies'; vi.mock('../../../server/database/queries/user'); -vi.mock('../../../server/utils/cookies'); +vi.mock('../../../shared/utils/cookies'); describe('Authorization - Middleware', () => { let fakeRequest; diff --git a/test/server/middleware/user/access/approve.test.js b/test/server/middleware/user/access/approve.test.js index c048f46..d382d6a 100644 --- a/test/server/middleware/user/access/approve.test.js +++ b/test/server/middleware/user/access/approve.test.js @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { createRequest, createResponse } from 'node-mocks-http'; import { approveAccess } from '../../../../../server/database/queries/user'; import accessApproveMiddleware from '../../../../../server/middleware/user/access/approveUser'; -import { AuthorizationError } from '../../../../../server/utils/errors'; +import { AuthorizationError } from '../../../../../shared/utils/errors'; vi.mock('../../../../../server/database/queries/user'); diff --git a/test/server/middleware/user/access/decline.test.js b/test/server/middleware/user/access/decline.test.js index 3aef60d..8876cea 100644 --- a/test/server/middleware/user/access/decline.test.js +++ b/test/server/middleware/user/access/decline.test.js @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { createRequest, createResponse } from 'node-mocks-http'; import { declineAccess } from '../../../../../server/database/queries/user'; -import { AuthorizationError } from '../../../../../server/utils/errors'; +import { AuthorizationError } from '../../../../../shared/utils/errors'; import accessDeclineMiddleware from '../../../../../server/middleware/user/access/declineUser'; vi.mock('../../../../../server/database/queries/user'); diff --git a/test/server/middleware/user/access/removeUser.test.js b/test/server/middleware/user/access/removeUser.test.js index 2b9f7cb..0f9392a 100644 --- a/test/server/middleware/user/access/removeUser.test.js +++ b/test/server/middleware/user/access/removeUser.test.js @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { createRequest, createResponse } from 'node-mocks-http'; import { declineAccess } from '../../../../../server/database/queries/user'; -import { AuthorizationError } from '../../../../../server/utils/errors'; +import { AuthorizationError } from '../../../../../shared/utils/errors'; import accessRemoveMiddleware from '../../../../../server/middleware/user/access/removeUser'; vi.mock('../../../../../server/database/queries/user'); diff --git a/test/server/middleware/user/permission/update.test.js b/test/server/middleware/user/permission/update.test.js index 7420872..b6999e9 100644 --- a/test/server/middleware/user/permission/update.test.js +++ b/test/server/middleware/user/permission/update.test.js @@ -4,7 +4,7 @@ import { userExists, } from '../../../../../server/database/queries/user'; import permissionUpdateMiddleware from '../../../../../server/middleware/user/permission/update'; -import { AuthorizationError } from '../../../../../server/utils/errors'; +import { AuthorizationError } from '../../../../../shared/utils/errors'; vi.mock('../../../../../server/database/queries/user'); diff --git a/test/server/middleware/user/update/avatar.test.js b/test/server/middleware/user/update/avatar.test.js index cfa77bb..37f1910 100644 --- a/test/server/middleware/user/update/avatar.test.js +++ b/test/server/middleware/user/update/avatar.test.js @@ -4,10 +4,10 @@ import { userExists, } from '../../../../../server/database/queries/user'; import userUpdateAvatar from '../../../../../server/middleware/user/update/avatar'; -import validators from '../../../../../server/utils/validators'; +import validators from '../../../../../shared/validators'; vi.mock('../../../../../server/database/queries/user'); -vi.mock('../../../../../server/utils/validators'); +vi.mock('../../../../../shared/validators'); describe('userUpdateAvatar - Middleware', () => { const user = { diff --git a/test/server/middleware/user/update/password.test.js b/test/server/middleware/user/update/password.test.js index 85ca3c7..3cad730 100644 --- a/test/server/middleware/user/update/password.test.js +++ b/test/server/middleware/user/update/password.test.js @@ -4,10 +4,10 @@ import { userExists, } from '../../../../../server/database/queries/user'; import userUpdatePassword from '../../../../../server/middleware/user/update/password'; -import { verifyPassword } from '../../../../../server/utils/hashPassword'; +import { verifyPassword } from '../../../../../shared/utils/hashPassword'; vi.mock('../../../../../server/database/queries/user'); -vi.mock('../../../../../server/utils/hashPassword'); +vi.mock('../../../../../shared/utils/hashPassword'); describe('userUpdatePassword - Middleware', () => { const user = { diff --git a/test/server/middleware/user/update/username.test.js b/test/server/middleware/user/update/username.test.js index 3096ea4..32c50b7 100644 --- a/test/server/middleware/user/update/username.test.js +++ b/test/server/middleware/user/update/username.test.js @@ -4,10 +4,10 @@ import { userExists, } from '../../../../../server/database/queries/user'; import userUpdateUsername from '../../../../../server/middleware/user/update/username'; -import validators from '../../../../../server/utils/validators'; +import validators from '../../../../../shared/validators'; vi.mock('../../../../../server/database/queries/user'); -vi.mock('../../../../../server/utils/validators'); +vi.mock('../../../../../shared/validators'); describe('userUpdateUsername - Middleware', () => { const user = { diff --git a/test/shared/setupDatabase.js b/test/shared/setupDatabase.js index 29ea54e..72b07bb 100644 --- a/test/shared/setupDatabase.js +++ b/test/shared/setupDatabase.js @@ -3,8 +3,8 @@ import fs from 'fs'; // import local files import { SQLite } from '../../server/database/sqlite/setup.js'; -import { generateHash } from '../../server/utils/hashPassword.js'; -import logger from '../../server/utils/logger.js'; +import { generateHash } from '../../shared/utils/hashPassword.js'; +import logger from '../../shared/utils/logger.js'; import { loadJSON } from '../../shared/parseJson.js'; const loginDetails = loadJSON('../test/e2e/setup/fixtures/login.json');