diff --git a/backend-app/constants/default_roles.ts b/backend-app/constants/default_roles.ts deleted file mode 100644 index e8fcac8..0000000 --- a/backend-app/constants/default_roles.ts +++ /dev/null @@ -1,32 +0,0 @@ -import Actions from './actions'; - -interface Role { - type: string; - authorities: Array; - restrictions: Array; -} - -const Roles: { [key: string]: Role } = { - SUPER_ADMIN: { - type: 'SUPER_ADMIN', - authorities: Object.values(Actions), - restrictions: [], - }, - ADMIN: { - type: 'ADMIN', - authorities: [ - Actions.DELETE_USER, - Actions.UPDATE_USER, - Actions.BAN_USER, - ], - restrictions: [], - }, - USER: { - type: 'USER', - authorities: [Actions.UPDATE_CALANDER], - restrictions: [], - }, -}; -Object.freeze(Roles); - -export default Roles; diff --git a/backend-app/controllers/auth_controllers/auth_controller.ts b/backend-app/controllers/auth_controllers/auth_controller.ts index aa37426..b8c7760 100644 --- a/backend-app/controllers/auth_controllers/auth_controller.ts +++ b/backend-app/controllers/auth_controllers/auth_controller.ts @@ -4,7 +4,7 @@ import { promisify } from 'util'; import validator from 'validator'; import AppError from '@utils/app_error'; import Role from '@utils/authorization/role/role'; -import { REQUIRE_ACTIVATION } from '../../config/app_config'; +import { REQUIRE_ACTIVATION } from '@config/app_config'; import { getGithubOAuthUser, getGithubOAuthToken, @@ -83,6 +83,7 @@ export const githubHandler = async ( }; function validateCredentialsTypes(email: string, password: string) { + // TODO: impllement joi to validate url params ( only if it's compatible with swagger ) if (!email || !password) { throw new AppError(404, 'Please provide email or password'); } diff --git a/backend-app/controllers/auth_controllers/github_controller.ts b/backend-app/controllers/auth_controllers/github_controller.ts index dc994ad..b8c9041 100644 --- a/backend-app/controllers/auth_controllers/github_controller.ts +++ b/backend-app/controllers/auth_controllers/github_controller.ts @@ -1,6 +1,6 @@ import axios from 'axios'; import { Request, Response, NextFunction } from 'express'; -import AppError from '../../utils/app_error'; +import AppError from '@utils/app_error'; interface Repository { id: number; diff --git a/backend-app/controllers/calendar_controllers/calendar_base_controller.ts b/backend-app/controllers/calendar_controllers/calendar_base_controller.ts index a643f0a..e6e310a 100644 --- a/backend-app/controllers/calendar_controllers/calendar_base_controller.ts +++ b/backend-app/controllers/calendar_controllers/calendar_base_controller.ts @@ -1,5 +1,5 @@ import { Request, Response, NextFunction } from 'express'; -import AppError from '../../utils/app_error'; +import AppError from '@utils/app_error'; import * as calendar_validators from './calendar_validators'; export const updateCalendar = async ( diff --git a/backend-app/controllers/calendar_controllers/calendar_validators.ts b/backend-app/controllers/calendar_controllers/calendar_validators.ts index 224acc1..ed54b44 100644 --- a/backend-app/controllers/calendar_controllers/calendar_validators.ts +++ b/backend-app/controllers/calendar_controllers/calendar_validators.ts @@ -5,11 +5,11 @@ import Calendar from '@models/calendar/calendar_model'; export async function validateCalendar(req: Request) { const calendarid = req.params.calendarid; if (!calendarid) { - throw new AppError('Calendar id is required', 400); + throw new AppError(400, 'Calendar id is required'); } const calendar = await Calendar.findById(calendarid); if (!calendar) { - throw new AppError('Calendar not found with that id', 404); + throw new AppError(404, 'Calendar not found with that id'); } return calendar; } diff --git a/backend-app/controllers/calendar_controllers/participents_controller.ts b/backend-app/controllers/calendar_controllers/participents_controller.ts index 9fda81d..d5e4a44 100644 --- a/backend-app/controllers/calendar_controllers/participents_controller.ts +++ b/backend-app/controllers/calendar_controllers/participents_controller.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import AppError from '../../utils/app_error'; +import AppError from '@utils/app_error'; import validator from 'validator'; import * as calendar_validators from './calendar_validators'; import { ObjectId } from 'mongoose'; @@ -15,17 +15,17 @@ export const inviteUsersByEmail = async (req: Request, res: Response) => { // check if user is a participant and the calendar is shareable if (!calendar.participants.includes(userid)) throw new AppError( - 'You do not have permission to invite users to this calendar', - 403 + 403, + 'You do not have permission to invite users to this calendar' ); if (!calendar.isShareAble) { - throw new AppError('This calendar is not shareable', 403); + throw new AppError(403, 'This calendar is not shareable'); } } // get emails from request body const emails = req.body.emails; if (!emails) { - throw new AppError('Emails are required', 400); + throw new AppError(400, 'Emails are required'); } // check if emails are valid const validEmails: string[] = []; @@ -55,7 +55,7 @@ export const removeCalendarParticipants = async ( // check if user is the calendar owner // @ts-ignore if (calendar.owner.toString() === !userid.toString()) { - throw new AppError('You are not the owner of this calendar', 403); + throw new AppError(403, 'You are not the owner of this calendar'); } // get list of participants to remove from calendar const listOfParticipants: string[] = req.body.participants; diff --git a/backend-app/controllers/users_controllers/user_controller.ts b/backend-app/controllers/users_controllers/user_controller.ts index 81e0857..5f19213 100644 --- a/backend-app/controllers/users_controllers/user_controller.ts +++ b/backend-app/controllers/users_controllers/user_controller.ts @@ -1,8 +1,8 @@ import { Request, Response, NextFunction } from 'express'; -import User, { IUser } from '../../models/user/user_model'; +import User, { IUser } from '@models/user/user_model'; import * as base from '../base_controller'; -import AppError from '../../utils/app_error'; -import sanitizeRequestBody from '../../utils/sanitize_request_body'; +import AppError from '@utils/app_error'; +import sanitizeRequestBody from '@utils/sanitize_request_body'; import { Model } from 'mongoose'; export const getMe = (req: Request, res: Response) => { diff --git a/backend-app/interfaces/models/i_user.ts b/backend-app/interfaces/models/i_user.ts new file mode 100644 index 0000000..e69de29 diff --git a/backend-app/interfaces/vendors/i_request.ts b/backend-app/interfaces/vendors/i_request.ts new file mode 100644 index 0000000..e69de29 diff --git a/backend-app/middlewares/authorization.ts b/backend-app/middlewares/authorization.ts index 7a6e73e..8f6ab4a 100644 --- a/backend-app/middlewares/authorization.ts +++ b/backend-app/middlewares/authorization.ts @@ -1,4 +1,4 @@ -import AppError from '../utils/app_error'; +import AppError from '@utils/app_error'; import { Request, Response, NextFunction } from 'express'; interface User { diff --git a/backend-app/middlewares/global_error_handler.ts b/backend-app/middlewares/global_error_handler.ts index cd62164..40f185f 100644 --- a/backend-app/middlewares/global_error_handler.ts +++ b/backend-app/middlewares/global_error_handler.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from 'express'; import httpStatus from 'http-status-codes'; -import { CURRENT_ENV } from '../config/app_config'; -import AppError from '../utils/app_error'; +import { CURRENT_ENV } from '@config/app_config'; +import AppError from '@utils/app_error'; /** * Error handling middleware diff --git a/backend-app/middlewares/morgan.ts b/backend-app/middlewares/morgan.ts index cb45972..bfa40d0 100644 --- a/backend-app/middlewares/morgan.ts +++ b/backend-app/middlewares/morgan.ts @@ -3,7 +3,7 @@ */ import morgan from 'morgan'; import logger from '@utils/logger'; -import { CURRENT_ENV } from '../config/app_config'; +import { CURRENT_ENV } from '@config/app_config'; // Create a stream object with a 'write' function that will be used by `morgan` const stream = { diff --git a/backend-app/middlewares/rate_limit.ts b/backend-app/middlewares/rate_limit.ts index 7929e02..600cf84 100644 --- a/backend-app/middlewares/rate_limit.ts +++ b/backend-app/middlewares/rate_limit.ts @@ -1,5 +1,5 @@ import rateLimit from 'express-rate-limit'; -import { RATE_LIMIT_PER_HOUR } from '../config/app_config'; +import { RATE_LIMIT_PER_HOUR } from '@config/app_config'; export default rateLimit({ // @ts-ignore diff --git a/backend-app/models/user/role_model.ts b/backend-app/models/user/role_model.ts index 75b535f..cf2ecbe 100644 --- a/backend-app/models/user/role_model.ts +++ b/backend-app/models/user/role_model.ts @@ -1,5 +1,5 @@ import mongoose, { Schema, Document } from 'mongoose'; -import Actions from '../../constants/actions'; +import Actions from '@constants/actions'; import validator from 'validator'; export interface IRole extends Document { @@ -25,36 +25,31 @@ const roleSchema: Schema = new Schema( validator: (value: string) => value.length > 0, }, }, - authorities: [ - { - type: String, - required: true, - default: [], - validate: { - validator: (value: string[]) => - value.every((v) => - validator.isIn(v, Object.values(Actions)) - ), - }, + authorities: { + type: [String], + required: true, + default: [], + validate: { + validator: (value: string[]) => + value.every((v) => + validator.isIn(v, Object.values(Actions)) + ), }, - ], - restrictions: [ - { - type: String, - required: true, - default: [], - validate: { - validator: (value: string[]) => - value.every((v) => - validator.isIn(v, Object.values(Actions)) - ), - }, + }, + restrictions: { + type: [String], + required: true, + default: [], + validate: { + validator: (value: string[]) => + value.every((v) => + validator.isIn(v, Object.values(Actions)) + ), }, - ], + }, }, { timestamps: true, - versionKey: false, } ); diff --git a/backend-app/models/user/user_model.ts b/backend-app/models/user/user_model.ts index 156448e..69e0112 100644 --- a/backend-app/models/user/user_model.ts +++ b/backend-app/models/user/user_model.ts @@ -1,8 +1,8 @@ import mongoose, { Document, Model, Schema } from 'mongoose'; import validator from 'validator'; import bcrypt from 'bcrypt'; -import Actions from '../../constants/actions'; -import metaData from '../../constants/meta_data'; +import Actions from '@constants/actions'; +import metaData from '@constants/meta_data'; import { randomBytes, createHash } from 'crypto'; export interface IUser extends Document { diff --git a/backend-app/package-lock.json b/backend-app/package-lock.json index d892ae8..0bc55fa 100644 --- a/backend-app/package-lock.json +++ b/backend-app/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@inquirer/prompts": "3.1.1", "@typegoose/typegoose": "11.5.0", "@types/compression": "1.7.3", "@types/express-routes-versioning": "1.0.1", @@ -902,6 +903,197 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "node_modules/@inquirer/checkbox": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.3.11.tgz", + "integrity": "sha512-SaQBDr7niZQzoP5Mqzak5pQY7476mvf4Sj2V8VFrbFHWHsavy3nKGKEOgijNHy151bEgqDog1829g/pKa9Qcrw==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/confirm": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.12.tgz", + "integrity": "sha512-Oxz3L0ti+0nWYHPPUIrPkxA2KnQZUGBHnk56yF5RjKqPGFrwvgLZdIXNe/w4I/OtdLeOBqHCrJ+kCvNvHVdk9g==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/core": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-5.0.0.tgz", + "integrity": "sha512-q2o4BcANKFyuUI5V6ejmPs1f9SdbJxfnLmhQVb72Fj7hOudoKsJpByJZ0imv9a/rpKDogA+93vtBBMqsnS7/Fg==", + "dependencies": { + "@inquirer/type": "^1.1.4", + "@types/mute-stream": "^0.0.1", + "@types/node": "^20.6.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.0", + "cli-width": "^4.1.0", + "figures": "^3.2.0", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/core/node_modules/@types/node": { + "version": "20.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", + "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==" + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.10.tgz", + "integrity": "sha512-aluYpazbxIdM54L+xNmVHzOjoXGwkliTCvHxhtPg6itmqDGMVmU1z+T2akHt6Xnx9RyrTpbumFB4xn1iI0UfnA==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/expand": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.11.tgz", + "integrity": "sha512-GSZJbYKPBniyXgWeFLsqiv7TSK9QjpQqCr+i/85Yts3wwixXTrAeoqM3TVVgHO/3j+xeFcuhOm1wy/F2QY5aEg==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2", + "figures": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/input": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-1.2.11.tgz", + "integrity": "sha512-sV1nO6+RxMFTHAznmxMkbMkjGQ8NGMWr0mvXjU35YQ0OFEL+YlD+DPbNd9s3ltnswODZAcnM1yFvdko3S/Kj/w==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/password": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-1.1.11.tgz", + "integrity": "sha512-r2eiLMlTuY+k+yJf6XLbnAEz7EDyWdjOrgVAWjSKoEDBc3T9/rq2I+7WiY9FUFArYY/1LxmsNWavs5NuMICx8Q==", + "dependencies": { + "@inquirer/input": "^1.2.11", + "@inquirer/type": "^1.1.4", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/prompts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-3.1.1.tgz", + "integrity": "sha512-7m/7Q4eupJYmn0GxM1H1dcekE4F4YlIB6bSKZs2SVeShARYUVPiAKFZ9c15UzYnBtdjCv4zXI17jbNtCNqmxGQ==", + "dependencies": { + "@inquirer/checkbox": "^1.3.11", + "@inquirer/confirm": "^2.0.12", + "@inquirer/core": "^5.0.0", + "@inquirer/editor": "^1.2.10", + "@inquirer/expand": "^1.1.11", + "@inquirer/input": "^1.2.11", + "@inquirer/password": "^1.1.11", + "@inquirer/rawlist": "^1.2.11", + "@inquirer/select": "^1.2.11" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.11.tgz", + "integrity": "sha512-4S2t2pCCR3VgyB3lbPKoiJ9020HHAi9g4M+DIyXHYwGE++7wURAwKkzb6v78fS0yKfCbyFt3BTcL2UffQRQ9Fg==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/select": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-1.2.11.tgz", + "integrity": "sha512-LH2wzAsWfu/+wcapeht07zTDefuvGTpv0+9dCAQ68QigF+4gHzpWq5+AbBLbxzuH2Wz4WlHcti85nFUPPM1t3A==", + "dependencies": { + "@inquirer/core": "^5.0.0", + "@inquirer/type": "^1.1.4", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.1.4.tgz", + "integrity": "sha512-a6+RCiXBQEbiA73RT1pBfwiH2I+MPcoZoGKuuUYFkws+6ud7nb5kUQGHFGUSBim25IyVMT/mqbWIrkxetcIb/w==", + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1572,6 +1764,14 @@ "@types/node": "*" } }, + "node_modules/@types/mute-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.1.tgz", + "integrity": "sha512-0yQLzYhCqGz7CQPE3iDmYjhb7KMBFOP+tBkyw+/Y2YyDI5wpS7itXXxneN1zSsUwWx3Ji6YiVYrhAnpQGS/vkw==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "16.18.47", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.47.tgz", @@ -1652,6 +1852,11 @@ "@types/webidl-conversions": "*" } }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, "node_modules/@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -1918,7 +2123,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -2439,6 +2643,11 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2509,6 +2718,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-spinners": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", + "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-truncate": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", @@ -2575,15 +2795,12 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "engines": { + "node": ">= 12" } }, "node_modules/co": { @@ -3821,6 +4038,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3884,6 +4114,28 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4907,6 +5159,44 @@ } } }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/jest-config": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", @@ -6542,6 +6832,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6769,6 +7067,14 @@ "node": ">= 0.8.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7276,6 +7582,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7923,6 +8237,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -8194,7 +8519,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -8630,33 +8954,6 @@ "yaml2json": "bin/yaml2json" } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/backend-app/package.json b/backend-app/package.json index edc9a2c..2e0d4d0 100644 --- a/backend-app/package.json +++ b/backend-app/package.json @@ -9,11 +9,13 @@ "prod": "node server.ts NODE_ENV=PRODUCTION", "start": "ts-node-dev server.ts", "test": "jest --detectOpenHandles", - "prepare": "cd .. && husky install" + "prepare": "cd .. && husky install", + "seed": "ts-node-dev ./seeds/m.js" }, "author": "Bella Abdelouahab", "license": "ISC", "dependencies": { + "@inquirer/prompts": "3.1.1", "@typegoose/typegoose": "11.5.0", "@types/compression": "1.7.3", "@types/express-routes-versioning": "1.0.1", diff --git a/backend-app/seed/setup_seed.js b/backend-app/seed/setup_seed.js deleted file mode 100644 index 3ed4e86..0000000 --- a/backend-app/seed/setup_seed.js +++ /dev/null @@ -1,6 +0,0 @@ -const mongoose = require('mongoose'); - -mongoose.connect(process.env.MONGO_URI, { - useNewUrlParser: true, - useUnifiedTopology: true, -}); diff --git a/backend-app/seeds/index.ts b/backend-app/seeds/index.ts new file mode 100644 index 0000000..fd76f18 --- /dev/null +++ b/backend-app/seeds/index.ts @@ -0,0 +1,19 @@ +function seed() { + try { + // Connect to the database + // await connectDatabase(); + + // // Run individual seed scripts + // await seedUsers(); + // await seedProducts(); + + // // Disconnect from the database + // await disconnectDatabase(); + + console.log('Seeding completed successfully.'); + } catch (error) { + console.error('Error seeding the database:', error); + } +} + +seed(); diff --git a/backend-app/seeds/m.js b/backend-app/seeds/m.js new file mode 100644 index 0000000..810b399 --- /dev/null +++ b/backend-app/seeds/m.js @@ -0,0 +1,24 @@ +import { prompts, checkbox } from '@inquirer/prompts'; + +// create a question with five checkboxes +const answer = checkbox({ + message: 'Select toppings', + choices: [ + { + name: 'Pepperoni', + checked: true, + }, + { + name: 'Ham', + }, + { + name: 'Ground Meat', + }, + ], + validate: (answer) => { + if (answer.length < 1) { + return 'You must choose at least one topping.'; + } + return true; + }, +}); diff --git a/backend-app/seeds/setup_seed.ts b/backend-app/seeds/setup_seed.ts new file mode 100644 index 0000000..3538193 --- /dev/null +++ b/backend-app/seeds/setup_seed.ts @@ -0,0 +1,108 @@ +import mongoose from 'mongoose'; +import '../utils/register_paths'; +import Role from '../models/user/role_model'; +import User from '../models/user/user_model'; +import logger from '@utils/logger'; +import { DATABASE, ADMIN_EMAIL, ADMIN_PASSWORD } from '@config/app_config'; +import Actions from '@constants/actions'; + +// Connect to MongoDB + +async function seed() { + await mongoose + .connect( + DATABASE as string, + { + useNewUrlParser: true, + useUnifiedTopology: true, + } as mongoose.ConnectOptions + ) + .then(() => console.log('Connected to MongoDB')) + .catch((err: any) => console.error(err)); + + interface Role { + name: string; + authorities: Array; + restrictions: Array; + } + + const Roles: { [key: string]: Role } = { + SUPER_ADMIN: { + name: 'SUPER_ADMIN', + authorities: Object.values(Actions), + restrictions: [], + }, + ADMIN: { + name: 'ADMIN', + authorities: [ + Actions.DELETE_USER, + Actions.UPDATE_USER, + Actions.BAN_USER, + ], + restrictions: [], + }, + USER: { + name: 'USER', + authorities: [Actions.UPDATE_CALANDER], + restrictions: [], + }, + }; + Object.freeze(Roles); + + // Seed default roles + async function seedRoles() { + const roles = await Role.find(); + if (roles.length === 0) { + for (const role of Object.values(Roles)) { + await Role.create(role); + } + logger.info('Roles seeded'); + } else { + logger.info('Roles already seeded'); + } + } + + // seed default users + const createAdminUser = async () => { + try { + const user = await User.findOne({ email: ADMIN_EMAIL }); + if (!user) { + // make sure super admin role is created if not created throw error + const superAdminRole = await Role.findOne({ + name: 'SUPER_ADMIN', + }); + if (!superAdminRole) { + throw new Error('Super Admin role not found'); + } + await User.create({ + name: 'Supper Admin', + email: ADMIN_EMAIL, + password: ADMIN_PASSWORD, + roles: [superAdminRole._id], + authorities: superAdminRole.authorities, + restrictions: superAdminRole.restrictions, + active: true, + }); + } else { + logger.info('default users already created'); + } + } catch (err) { + logger.error(err.stack); + } + }; + + // create a default normal user + + await seedRoles(); + await createAdminUser(); +} + +seed() + .then(() => { + mongoose.disconnect(); + logger.info('Seeding completed successfully.'); + }) + .catch((err) => { + logger.error('Error seeding the database:', err); + mongoose.disconnect(); + }); diff --git a/backend-app/seed/users.json b/backend-app/seeds/users.json similarity index 100% rename from backend-app/seed/users.json rename to backend-app/seeds/users.json diff --git a/backend-app/tsconfig.json b/backend-app/tsconfig.json index 1f809d3..45fe172 100644 --- a/backend-app/tsconfig.json +++ b/backend-app/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "esModuleInterop": true, - "target": "es6", + "target": "es2022", "noImplicitAny": true, "moduleResolution": "node", "sourceMap": true, diff --git a/backend-app/utils/create_default_user.ts b/backend-app/utils/create_default_user.ts index f969d2b..7e46613 100644 --- a/backend-app/utils/create_default_user.ts +++ b/backend-app/utils/create_default_user.ts @@ -1,6 +1,5 @@ -import User from '../models/user/user_model'; -import { ADMIN_EMAIL, ADMIN_PASSWORD } from '../config/app_config'; -import Roles from '@constants/default_roles'; +import User from '@models/user/user_model'; +import { ADMIN_EMAIL, ADMIN_PASSWORD } from '@config/app_config'; import logger from '@utils/logger'; const createAdminUser = async () => { diff --git a/backend-app/utils/logger.ts b/backend-app/utils/logger.ts index f9ceec9..2b60a1c 100644 --- a/backend-app/utils/logger.ts +++ b/backend-app/utils/logger.ts @@ -3,7 +3,7 @@ */ import { createLogger, transports } from 'winston'; import DailyRotateFile from 'winston-daily-rotate-file'; -import { fileOptions, consoleOptions } from '../config/logger_config'; +import { fileOptions, consoleOptions } from '@config/logger_config'; // Define the transport for the logger const consoleTransport = new transports.Console(consoleOptions);