├── .env ├── .gitignore ├── README.md ├── app.js ├── package.json ├── pnpm-lock.yaml └── src ├── app ├── auth │ ├── controller.js │ └── router.js └── users │ ├── controller.js │ ├── model.js │ └── router.js ├── db └── dbConnection.js ├── helpers └── corsOptions.js ├── middlewares ├── auth.js ├── errorHandler.js ├── lib │ └── upload.js ├── rateLimit.js └── validations │ └── auth.validation.js ├── routers └── index.js └── utils ├── errors.js ├── response.js └── sendMail.js /.env: -------------------------------------------------------------------------------- 1 | PORT = 5001 2 | 3 | # Database 4 | DB_URL = "mongodb://localhost:27017/nodejs-starter-project" 5 | 6 | # Jwt 7 | JWT_SECRET_KEY = "D,s.M.A710m12g=ds,gak./3*" 8 | JWT_EXPIRES_IN = "7d" 9 | 10 | JWT_TEMPORARY_KEY = "D,s.M.A710m12g=ds,gak./3*" 11 | JWT_TEMPORARY_EXPIRES_IN = "3m" 12 | 13 | # email 14 | EMAIL_USER = 15 | EMAIL_PASSWORD = -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json 36 | 37 | public -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nodejs Express MongoDb Starter Project 2 | 3 | ## npm install 4 | ## npm start -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | require("express-async-errors") 2 | const express = require("express") 3 | const app = express() 4 | require("dotenv").config() 5 | require("./src/db/dbConnection") 6 | const port = process.env.PORT || 5002 7 | const router = require("./src/routers") 8 | const errorHandlerMiddleware = require("./src/middlewares/errorHandler") 9 | const cors = require("cors") 10 | const corsOptions = require("./src/helpers/corsOptions") 11 | const mongoSanitize = require('express-mongo-sanitize'); 12 | const path = require("path") 13 | const apiLimiter = require("./src/middlewares/rateLimit") 14 | const moment = require("moment-timezone") 15 | moment.tz.setDefault("Europe/Istanbul") 16 | 17 | // Middlewares 18 | app.use(express.json()) 19 | app.use(express.json({limit: "50mb"})) 20 | app.use(express.urlencoded({limit: "50mb", extended: true, parameterLimit: 50000})) 21 | 22 | app.use(express.static(path.join(__dirname, "public"))) 23 | app.use("/uploads", express.static(__dirname)) 24 | 25 | app.use(cors(corsOptions)) 26 | 27 | app.use("/api", apiLimiter) 28 | 29 | app.use( 30 | mongoSanitize({ 31 | replaceWith: '_', 32 | }), 33 | ); 34 | 35 | app.use("/api", router) 36 | 37 | 38 | 39 | app.get("/", (req, res) => { 40 | res.json({ 41 | message: "Hoş Geldiniz" 42 | }) 43 | }) 44 | 45 | 46 | // hata yakalama 47 | app.use(errorHandlerMiddleware) 48 | 49 | app.listen(port, () => { 50 | console.log(`Server ${port} portundan çalışıyor ...`); 51 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-express-mongodb-starter-project", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "nodemon app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [ 11 | "nodejs", 12 | "express", 13 | "mongodb", 14 | "starter-api", 15 | "starter-project", 16 | "mongodb-starter-project", 17 | "express-mongodb-starter-project", 18 | "express-api", 19 | "nodejs-rest-api", 20 | "api-güvenligi", 21 | "rest-api", 22 | "api-securty", 23 | "base-api", 24 | "nodejs-base-api" 25 | ], 26 | "author": "", 27 | "license": "ISC", 28 | "dependencies": { 29 | "bcrypt": "^5.1.0", 30 | "cors": "^2.8.5", 31 | "dotenv": "^16.0.2", 32 | "express": "^4.18.1", 33 | "express-async-errors": "^3.1.1", 34 | "express-mongo-sanitize": "^2.2.0", 35 | "express-rate-limit": "^7.2.0", 36 | "joi": "^17.6.1", 37 | "jsonwebtoken": "^9.0.0", 38 | "moment": "^2.29.4", 39 | "moment-timezone": "^0.5.40", 40 | "mongoose": "^8.3.2", 41 | "multer": "^1.4.5-lts.1", 42 | "nodemailer": "^6.8.0", 43 | "nodemon": "^3.1.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | bcrypt: 9 | specifier: ^5.1.0 10 | version: 5.1.1 11 | cors: 12 | specifier: ^2.8.5 13 | version: 2.8.5 14 | dotenv: 15 | specifier: ^16.0.2 16 | version: 16.4.5 17 | express: 18 | specifier: ^4.18.1 19 | version: 4.19.2 20 | express-async-errors: 21 | specifier: ^3.1.1 22 | version: 3.1.1(express@4.19.2) 23 | express-mongo-sanitize: 24 | specifier: ^2.2.0 25 | version: 2.2.0 26 | express-rate-limit: 27 | specifier: ^7.2.0 28 | version: 7.2.0(express@4.19.2) 29 | joi: 30 | specifier: ^17.6.1 31 | version: 17.12.3 32 | jsonwebtoken: 33 | specifier: ^9.0.0 34 | version: 9.0.2 35 | moment: 36 | specifier: ^2.29.4 37 | version: 2.30.1 38 | moment-timezone: 39 | specifier: ^0.5.40 40 | version: 0.5.45 41 | mongoose: 42 | specifier: ^8.3.2 43 | version: 8.3.2 44 | multer: 45 | specifier: ^1.4.5-lts.1 46 | version: 1.4.5-lts.1 47 | nodemailer: 48 | specifier: ^6.8.0 49 | version: 6.9.13 50 | nodemon: 51 | specifier: ^3.1.0 52 | version: 3.1.0 53 | 54 | packages: 55 | 56 | /@hapi/hoek@9.3.0: 57 | resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} 58 | dev: false 59 | 60 | /@hapi/topo@5.1.0: 61 | resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} 62 | dependencies: 63 | '@hapi/hoek': 9.3.0 64 | dev: false 65 | 66 | /@mapbox/node-pre-gyp@1.0.11: 67 | resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} 68 | hasBin: true 69 | dependencies: 70 | detect-libc: 2.0.3 71 | https-proxy-agent: 5.0.1 72 | make-dir: 3.1.0 73 | node-fetch: 2.7.0 74 | nopt: 5.0.0 75 | npmlog: 5.0.1 76 | rimraf: 3.0.2 77 | semver: 7.6.0 78 | tar: 6.2.1 79 | transitivePeerDependencies: 80 | - encoding 81 | - supports-color 82 | dev: false 83 | 84 | /@mongodb-js/saslprep@1.1.5: 85 | resolution: {integrity: sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==} 86 | requiresBuild: true 87 | dependencies: 88 | sparse-bitfield: 3.0.3 89 | dev: false 90 | 91 | /@sideway/address@4.1.5: 92 | resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} 93 | dependencies: 94 | '@hapi/hoek': 9.3.0 95 | dev: false 96 | 97 | /@sideway/formula@3.0.1: 98 | resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} 99 | dev: false 100 | 101 | /@sideway/pinpoint@2.0.0: 102 | resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} 103 | dev: false 104 | 105 | /@types/webidl-conversions@7.0.3: 106 | resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} 107 | dev: false 108 | 109 | /@types/whatwg-url@11.0.4: 110 | resolution: {integrity: sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==} 111 | dependencies: 112 | '@types/webidl-conversions': 7.0.3 113 | dev: false 114 | 115 | /abbrev@1.1.1: 116 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 117 | dev: false 118 | 119 | /accepts@1.3.8: 120 | resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} 121 | engines: {node: '>= 0.6'} 122 | dependencies: 123 | mime-types: 2.1.35 124 | negotiator: 0.6.3 125 | dev: false 126 | 127 | /agent-base@6.0.2: 128 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} 129 | engines: {node: '>= 6.0.0'} 130 | dependencies: 131 | debug: 4.3.4(supports-color@5.5.0) 132 | transitivePeerDependencies: 133 | - supports-color 134 | dev: false 135 | 136 | /ansi-regex@5.0.1: 137 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 138 | engines: {node: '>=8'} 139 | dev: false 140 | 141 | /anymatch@3.1.3: 142 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 143 | engines: {node: '>= 8'} 144 | dependencies: 145 | normalize-path: 3.0.0 146 | picomatch: 2.3.1 147 | dev: false 148 | 149 | /append-field@1.0.0: 150 | resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} 151 | dev: false 152 | 153 | /aproba@2.0.0: 154 | resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} 155 | dev: false 156 | 157 | /are-we-there-yet@2.0.0: 158 | resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} 159 | engines: {node: '>=10'} 160 | dependencies: 161 | delegates: 1.0.0 162 | readable-stream: 3.6.2 163 | dev: false 164 | 165 | /array-flatten@1.1.1: 166 | resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} 167 | dev: false 168 | 169 | /balanced-match@1.0.2: 170 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 171 | dev: false 172 | 173 | /bcrypt@5.1.1: 174 | resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} 175 | engines: {node: '>= 10.0.0'} 176 | requiresBuild: true 177 | dependencies: 178 | '@mapbox/node-pre-gyp': 1.0.11 179 | node-addon-api: 5.1.0 180 | transitivePeerDependencies: 181 | - encoding 182 | - supports-color 183 | dev: false 184 | 185 | /binary-extensions@2.3.0: 186 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 187 | engines: {node: '>=8'} 188 | dev: false 189 | 190 | /body-parser@1.20.2: 191 | resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} 192 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 193 | dependencies: 194 | bytes: 3.1.2 195 | content-type: 1.0.5 196 | debug: 2.6.9 197 | depd: 2.0.0 198 | destroy: 1.2.0 199 | http-errors: 2.0.0 200 | iconv-lite: 0.4.24 201 | on-finished: 2.4.1 202 | qs: 6.11.0 203 | raw-body: 2.5.2 204 | type-is: 1.6.18 205 | unpipe: 1.0.0 206 | transitivePeerDependencies: 207 | - supports-color 208 | dev: false 209 | 210 | /brace-expansion@1.1.11: 211 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 212 | dependencies: 213 | balanced-match: 1.0.2 214 | concat-map: 0.0.1 215 | dev: false 216 | 217 | /braces@3.0.2: 218 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 219 | engines: {node: '>=8'} 220 | dependencies: 221 | fill-range: 7.0.1 222 | dev: false 223 | 224 | /bson@6.6.0: 225 | resolution: {integrity: sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==} 226 | engines: {node: '>=16.20.1'} 227 | dev: false 228 | 229 | /buffer-equal-constant-time@1.0.1: 230 | resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} 231 | dev: false 232 | 233 | /buffer-from@1.1.2: 234 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 235 | dev: false 236 | 237 | /busboy@1.6.0: 238 | resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} 239 | engines: {node: '>=10.16.0'} 240 | dependencies: 241 | streamsearch: 1.1.0 242 | dev: false 243 | 244 | /bytes@3.1.2: 245 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} 246 | engines: {node: '>= 0.8'} 247 | dev: false 248 | 249 | /call-bind@1.0.7: 250 | resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} 251 | engines: {node: '>= 0.4'} 252 | dependencies: 253 | es-define-property: 1.0.0 254 | es-errors: 1.3.0 255 | function-bind: 1.1.2 256 | get-intrinsic: 1.2.4 257 | set-function-length: 1.2.2 258 | dev: false 259 | 260 | /chokidar@3.6.0: 261 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 262 | engines: {node: '>= 8.10.0'} 263 | dependencies: 264 | anymatch: 3.1.3 265 | braces: 3.0.2 266 | glob-parent: 5.1.2 267 | is-binary-path: 2.1.0 268 | is-glob: 4.0.3 269 | normalize-path: 3.0.0 270 | readdirp: 3.6.0 271 | optionalDependencies: 272 | fsevents: 2.3.3 273 | dev: false 274 | 275 | /chownr@2.0.0: 276 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} 277 | engines: {node: '>=10'} 278 | dev: false 279 | 280 | /color-support@1.1.3: 281 | resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} 282 | hasBin: true 283 | dev: false 284 | 285 | /concat-map@0.0.1: 286 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 287 | dev: false 288 | 289 | /concat-stream@1.6.2: 290 | resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} 291 | engines: {'0': node >= 0.8} 292 | dependencies: 293 | buffer-from: 1.1.2 294 | inherits: 2.0.4 295 | readable-stream: 2.3.8 296 | typedarray: 0.0.6 297 | dev: false 298 | 299 | /console-control-strings@1.1.0: 300 | resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} 301 | dev: false 302 | 303 | /content-disposition@0.5.4: 304 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} 305 | engines: {node: '>= 0.6'} 306 | dependencies: 307 | safe-buffer: 5.2.1 308 | dev: false 309 | 310 | /content-type@1.0.5: 311 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} 312 | engines: {node: '>= 0.6'} 313 | dev: false 314 | 315 | /cookie-signature@1.0.6: 316 | resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} 317 | dev: false 318 | 319 | /cookie@0.6.0: 320 | resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} 321 | engines: {node: '>= 0.6'} 322 | dev: false 323 | 324 | /core-util-is@1.0.3: 325 | resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} 326 | dev: false 327 | 328 | /cors@2.8.5: 329 | resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} 330 | engines: {node: '>= 0.10'} 331 | dependencies: 332 | object-assign: 4.1.1 333 | vary: 1.1.2 334 | dev: false 335 | 336 | /debug@2.6.9: 337 | resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} 338 | peerDependencies: 339 | supports-color: '*' 340 | peerDependenciesMeta: 341 | supports-color: 342 | optional: true 343 | dependencies: 344 | ms: 2.0.0 345 | dev: false 346 | 347 | /debug@4.3.4(supports-color@5.5.0): 348 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 349 | engines: {node: '>=6.0'} 350 | peerDependencies: 351 | supports-color: '*' 352 | peerDependenciesMeta: 353 | supports-color: 354 | optional: true 355 | dependencies: 356 | ms: 2.1.2 357 | supports-color: 5.5.0 358 | dev: false 359 | 360 | /define-data-property@1.1.4: 361 | resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} 362 | engines: {node: '>= 0.4'} 363 | dependencies: 364 | es-define-property: 1.0.0 365 | es-errors: 1.3.0 366 | gopd: 1.0.1 367 | dev: false 368 | 369 | /delegates@1.0.0: 370 | resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} 371 | dev: false 372 | 373 | /depd@2.0.0: 374 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} 375 | engines: {node: '>= 0.8'} 376 | dev: false 377 | 378 | /destroy@1.2.0: 379 | resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} 380 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 381 | dev: false 382 | 383 | /detect-libc@2.0.3: 384 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 385 | engines: {node: '>=8'} 386 | dev: false 387 | 388 | /dotenv@16.4.5: 389 | resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} 390 | engines: {node: '>=12'} 391 | dev: false 392 | 393 | /ecdsa-sig-formatter@1.0.11: 394 | resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} 395 | dependencies: 396 | safe-buffer: 5.2.1 397 | dev: false 398 | 399 | /ee-first@1.1.1: 400 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} 401 | dev: false 402 | 403 | /emoji-regex@8.0.0: 404 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 405 | dev: false 406 | 407 | /encodeurl@1.0.2: 408 | resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} 409 | engines: {node: '>= 0.8'} 410 | dev: false 411 | 412 | /es-define-property@1.0.0: 413 | resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} 414 | engines: {node: '>= 0.4'} 415 | dependencies: 416 | get-intrinsic: 1.2.4 417 | dev: false 418 | 419 | /es-errors@1.3.0: 420 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 421 | engines: {node: '>= 0.4'} 422 | dev: false 423 | 424 | /escape-html@1.0.3: 425 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} 426 | dev: false 427 | 428 | /etag@1.8.1: 429 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} 430 | engines: {node: '>= 0.6'} 431 | dev: false 432 | 433 | /express-async-errors@3.1.1(express@4.19.2): 434 | resolution: {integrity: sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==} 435 | peerDependencies: 436 | express: ^4.16.2 437 | dependencies: 438 | express: 4.19.2 439 | dev: false 440 | 441 | /express-mongo-sanitize@2.2.0: 442 | resolution: {integrity: sha512-PZBs5nwhD6ek9ZuP+W2xmpvcrHwXZxD5GdieX2dsjPbAbH4azOkrHbycBud2QRU+YQF1CT+pki/lZGedHgo/dQ==} 443 | engines: {node: '>=10'} 444 | dev: false 445 | 446 | /express-rate-limit@7.2.0(express@4.19.2): 447 | resolution: {integrity: sha512-T7nul1t4TNyfZMJ7pKRKkdeVJWa2CqB8NA1P8BwYaoDI5QSBZARv5oMS43J7b7I5P+4asjVXjb7ONuwDKucahg==} 448 | engines: {node: '>= 16'} 449 | peerDependencies: 450 | express: 4 || 5 || ^5.0.0-beta.1 451 | dependencies: 452 | express: 4.19.2 453 | dev: false 454 | 455 | /express@4.19.2: 456 | resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} 457 | engines: {node: '>= 0.10.0'} 458 | dependencies: 459 | accepts: 1.3.8 460 | array-flatten: 1.1.1 461 | body-parser: 1.20.2 462 | content-disposition: 0.5.4 463 | content-type: 1.0.5 464 | cookie: 0.6.0 465 | cookie-signature: 1.0.6 466 | debug: 2.6.9 467 | depd: 2.0.0 468 | encodeurl: 1.0.2 469 | escape-html: 1.0.3 470 | etag: 1.8.1 471 | finalhandler: 1.2.0 472 | fresh: 0.5.2 473 | http-errors: 2.0.0 474 | merge-descriptors: 1.0.1 475 | methods: 1.1.2 476 | on-finished: 2.4.1 477 | parseurl: 1.3.3 478 | path-to-regexp: 0.1.7 479 | proxy-addr: 2.0.7 480 | qs: 6.11.0 481 | range-parser: 1.2.1 482 | safe-buffer: 5.2.1 483 | send: 0.18.0 484 | serve-static: 1.15.0 485 | setprototypeof: 1.2.0 486 | statuses: 2.0.1 487 | type-is: 1.6.18 488 | utils-merge: 1.0.1 489 | vary: 1.1.2 490 | transitivePeerDependencies: 491 | - supports-color 492 | dev: false 493 | 494 | /fill-range@7.0.1: 495 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 496 | engines: {node: '>=8'} 497 | dependencies: 498 | to-regex-range: 5.0.1 499 | dev: false 500 | 501 | /finalhandler@1.2.0: 502 | resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} 503 | engines: {node: '>= 0.8'} 504 | dependencies: 505 | debug: 2.6.9 506 | encodeurl: 1.0.2 507 | escape-html: 1.0.3 508 | on-finished: 2.4.1 509 | parseurl: 1.3.3 510 | statuses: 2.0.1 511 | unpipe: 1.0.0 512 | transitivePeerDependencies: 513 | - supports-color 514 | dev: false 515 | 516 | /forwarded@0.2.0: 517 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} 518 | engines: {node: '>= 0.6'} 519 | dev: false 520 | 521 | /fresh@0.5.2: 522 | resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} 523 | engines: {node: '>= 0.6'} 524 | dev: false 525 | 526 | /fs-minipass@2.1.0: 527 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} 528 | engines: {node: '>= 8'} 529 | dependencies: 530 | minipass: 3.3.6 531 | dev: false 532 | 533 | /fs.realpath@1.0.0: 534 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 535 | dev: false 536 | 537 | /fsevents@2.3.3: 538 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 539 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 540 | os: [darwin] 541 | requiresBuild: true 542 | dev: false 543 | optional: true 544 | 545 | /function-bind@1.1.2: 546 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 547 | dev: false 548 | 549 | /gauge@3.0.2: 550 | resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} 551 | engines: {node: '>=10'} 552 | dependencies: 553 | aproba: 2.0.0 554 | color-support: 1.1.3 555 | console-control-strings: 1.1.0 556 | has-unicode: 2.0.1 557 | object-assign: 4.1.1 558 | signal-exit: 3.0.7 559 | string-width: 4.2.3 560 | strip-ansi: 6.0.1 561 | wide-align: 1.1.5 562 | dev: false 563 | 564 | /get-intrinsic@1.2.4: 565 | resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} 566 | engines: {node: '>= 0.4'} 567 | dependencies: 568 | es-errors: 1.3.0 569 | function-bind: 1.1.2 570 | has-proto: 1.0.3 571 | has-symbols: 1.0.3 572 | hasown: 2.0.2 573 | dev: false 574 | 575 | /glob-parent@5.1.2: 576 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 577 | engines: {node: '>= 6'} 578 | dependencies: 579 | is-glob: 4.0.3 580 | dev: false 581 | 582 | /glob@7.2.3: 583 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 584 | dependencies: 585 | fs.realpath: 1.0.0 586 | inflight: 1.0.6 587 | inherits: 2.0.4 588 | minimatch: 3.1.2 589 | once: 1.4.0 590 | path-is-absolute: 1.0.1 591 | dev: false 592 | 593 | /gopd@1.0.1: 594 | resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 595 | dependencies: 596 | get-intrinsic: 1.2.4 597 | dev: false 598 | 599 | /has-flag@3.0.0: 600 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 601 | engines: {node: '>=4'} 602 | dev: false 603 | 604 | /has-property-descriptors@1.0.2: 605 | resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 606 | dependencies: 607 | es-define-property: 1.0.0 608 | dev: false 609 | 610 | /has-proto@1.0.3: 611 | resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} 612 | engines: {node: '>= 0.4'} 613 | dev: false 614 | 615 | /has-symbols@1.0.3: 616 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 617 | engines: {node: '>= 0.4'} 618 | dev: false 619 | 620 | /has-unicode@2.0.1: 621 | resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} 622 | dev: false 623 | 624 | /hasown@2.0.2: 625 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 626 | engines: {node: '>= 0.4'} 627 | dependencies: 628 | function-bind: 1.1.2 629 | dev: false 630 | 631 | /http-errors@2.0.0: 632 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} 633 | engines: {node: '>= 0.8'} 634 | dependencies: 635 | depd: 2.0.0 636 | inherits: 2.0.4 637 | setprototypeof: 1.2.0 638 | statuses: 2.0.1 639 | toidentifier: 1.0.1 640 | dev: false 641 | 642 | /https-proxy-agent@5.0.1: 643 | resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} 644 | engines: {node: '>= 6'} 645 | dependencies: 646 | agent-base: 6.0.2 647 | debug: 4.3.4(supports-color@5.5.0) 648 | transitivePeerDependencies: 649 | - supports-color 650 | dev: false 651 | 652 | /iconv-lite@0.4.24: 653 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 654 | engines: {node: '>=0.10.0'} 655 | dependencies: 656 | safer-buffer: 2.1.2 657 | dev: false 658 | 659 | /ignore-by-default@1.0.1: 660 | resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} 661 | dev: false 662 | 663 | /inflight@1.0.6: 664 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 665 | dependencies: 666 | once: 1.4.0 667 | wrappy: 1.0.2 668 | dev: false 669 | 670 | /inherits@2.0.4: 671 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 672 | dev: false 673 | 674 | /ipaddr.js@1.9.1: 675 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 676 | engines: {node: '>= 0.10'} 677 | dev: false 678 | 679 | /is-binary-path@2.1.0: 680 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 681 | engines: {node: '>=8'} 682 | dependencies: 683 | binary-extensions: 2.3.0 684 | dev: false 685 | 686 | /is-extglob@2.1.1: 687 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 688 | engines: {node: '>=0.10.0'} 689 | dev: false 690 | 691 | /is-fullwidth-code-point@3.0.0: 692 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 693 | engines: {node: '>=8'} 694 | dev: false 695 | 696 | /is-glob@4.0.3: 697 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 698 | engines: {node: '>=0.10.0'} 699 | dependencies: 700 | is-extglob: 2.1.1 701 | dev: false 702 | 703 | /is-number@7.0.0: 704 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 705 | engines: {node: '>=0.12.0'} 706 | dev: false 707 | 708 | /isarray@1.0.0: 709 | resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} 710 | dev: false 711 | 712 | /joi@17.12.3: 713 | resolution: {integrity: sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==} 714 | dependencies: 715 | '@hapi/hoek': 9.3.0 716 | '@hapi/topo': 5.1.0 717 | '@sideway/address': 4.1.5 718 | '@sideway/formula': 3.0.1 719 | '@sideway/pinpoint': 2.0.0 720 | dev: false 721 | 722 | /jsonwebtoken@9.0.2: 723 | resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} 724 | engines: {node: '>=12', npm: '>=6'} 725 | dependencies: 726 | jws: 3.2.2 727 | lodash.includes: 4.3.0 728 | lodash.isboolean: 3.0.3 729 | lodash.isinteger: 4.0.4 730 | lodash.isnumber: 3.0.3 731 | lodash.isplainobject: 4.0.6 732 | lodash.isstring: 4.0.1 733 | lodash.once: 4.1.1 734 | ms: 2.1.3 735 | semver: 7.6.0 736 | dev: false 737 | 738 | /jwa@1.4.1: 739 | resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} 740 | dependencies: 741 | buffer-equal-constant-time: 1.0.1 742 | ecdsa-sig-formatter: 1.0.11 743 | safe-buffer: 5.2.1 744 | dev: false 745 | 746 | /jws@3.2.2: 747 | resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} 748 | dependencies: 749 | jwa: 1.4.1 750 | safe-buffer: 5.2.1 751 | dev: false 752 | 753 | /kareem@2.6.3: 754 | resolution: {integrity: sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==} 755 | engines: {node: '>=12.0.0'} 756 | dev: false 757 | 758 | /lodash.includes@4.3.0: 759 | resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} 760 | dev: false 761 | 762 | /lodash.isboolean@3.0.3: 763 | resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} 764 | dev: false 765 | 766 | /lodash.isinteger@4.0.4: 767 | resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} 768 | dev: false 769 | 770 | /lodash.isnumber@3.0.3: 771 | resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} 772 | dev: false 773 | 774 | /lodash.isplainobject@4.0.6: 775 | resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} 776 | dev: false 777 | 778 | /lodash.isstring@4.0.1: 779 | resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} 780 | dev: false 781 | 782 | /lodash.once@4.1.1: 783 | resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} 784 | dev: false 785 | 786 | /lru-cache@6.0.0: 787 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 788 | engines: {node: '>=10'} 789 | dependencies: 790 | yallist: 4.0.0 791 | dev: false 792 | 793 | /make-dir@3.1.0: 794 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} 795 | engines: {node: '>=8'} 796 | dependencies: 797 | semver: 6.3.1 798 | dev: false 799 | 800 | /media-typer@0.3.0: 801 | resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} 802 | engines: {node: '>= 0.6'} 803 | dev: false 804 | 805 | /memory-pager@1.5.0: 806 | resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} 807 | requiresBuild: true 808 | dev: false 809 | 810 | /merge-descriptors@1.0.1: 811 | resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} 812 | dev: false 813 | 814 | /methods@1.1.2: 815 | resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} 816 | engines: {node: '>= 0.6'} 817 | dev: false 818 | 819 | /mime-db@1.52.0: 820 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 821 | engines: {node: '>= 0.6'} 822 | dev: false 823 | 824 | /mime-types@2.1.35: 825 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 826 | engines: {node: '>= 0.6'} 827 | dependencies: 828 | mime-db: 1.52.0 829 | dev: false 830 | 831 | /mime@1.6.0: 832 | resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} 833 | engines: {node: '>=4'} 834 | hasBin: true 835 | dev: false 836 | 837 | /minimatch@3.1.2: 838 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 839 | dependencies: 840 | brace-expansion: 1.1.11 841 | dev: false 842 | 843 | /minimist@1.2.8: 844 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 845 | dev: false 846 | 847 | /minipass@3.3.6: 848 | resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} 849 | engines: {node: '>=8'} 850 | dependencies: 851 | yallist: 4.0.0 852 | dev: false 853 | 854 | /minipass@5.0.0: 855 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 856 | engines: {node: '>=8'} 857 | dev: false 858 | 859 | /minizlib@2.1.2: 860 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} 861 | engines: {node: '>= 8'} 862 | dependencies: 863 | minipass: 3.3.6 864 | yallist: 4.0.0 865 | dev: false 866 | 867 | /mkdirp@0.5.6: 868 | resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} 869 | hasBin: true 870 | dependencies: 871 | minimist: 1.2.8 872 | dev: false 873 | 874 | /mkdirp@1.0.4: 875 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} 876 | engines: {node: '>=10'} 877 | hasBin: true 878 | dev: false 879 | 880 | /moment-timezone@0.5.45: 881 | resolution: {integrity: sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==} 882 | dependencies: 883 | moment: 2.30.1 884 | dev: false 885 | 886 | /moment@2.30.1: 887 | resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} 888 | dev: false 889 | 890 | /mongodb-connection-string-url@3.0.0: 891 | resolution: {integrity: sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==} 892 | dependencies: 893 | '@types/whatwg-url': 11.0.4 894 | whatwg-url: 13.0.0 895 | dev: false 896 | 897 | /mongodb@6.5.0: 898 | resolution: {integrity: sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==} 899 | engines: {node: '>=16.20.1'} 900 | peerDependencies: 901 | '@aws-sdk/credential-providers': ^3.188.0 902 | '@mongodb-js/zstd': ^1.1.0 903 | gcp-metadata: ^5.2.0 904 | kerberos: ^2.0.1 905 | mongodb-client-encryption: '>=6.0.0 <7' 906 | snappy: ^7.2.2 907 | socks: ^2.7.1 908 | peerDependenciesMeta: 909 | '@aws-sdk/credential-providers': 910 | optional: true 911 | '@mongodb-js/zstd': 912 | optional: true 913 | gcp-metadata: 914 | optional: true 915 | kerberos: 916 | optional: true 917 | mongodb-client-encryption: 918 | optional: true 919 | snappy: 920 | optional: true 921 | socks: 922 | optional: true 923 | dependencies: 924 | '@mongodb-js/saslprep': 1.1.5 925 | bson: 6.6.0 926 | mongodb-connection-string-url: 3.0.0 927 | dev: false 928 | 929 | /mongoose@8.3.2: 930 | resolution: {integrity: sha512-3JcpDjFI25cF/3xpu+4+9nM0lURQTNLcP86X83+LvuICdn453QQLmhSrUr2IPM/ffLiDE9KPl9slNb2s0hZPpg==} 931 | engines: {node: '>=16.20.1'} 932 | dependencies: 933 | bson: 6.6.0 934 | kareem: 2.6.3 935 | mongodb: 6.5.0 936 | mpath: 0.9.0 937 | mquery: 5.0.0 938 | ms: 2.1.3 939 | sift: 16.0.1 940 | transitivePeerDependencies: 941 | - '@aws-sdk/credential-providers' 942 | - '@mongodb-js/zstd' 943 | - gcp-metadata 944 | - kerberos 945 | - mongodb-client-encryption 946 | - snappy 947 | - socks 948 | - supports-color 949 | dev: false 950 | 951 | /mpath@0.9.0: 952 | resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==} 953 | engines: {node: '>=4.0.0'} 954 | dev: false 955 | 956 | /mquery@5.0.0: 957 | resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} 958 | engines: {node: '>=14.0.0'} 959 | dependencies: 960 | debug: 4.3.4(supports-color@5.5.0) 961 | transitivePeerDependencies: 962 | - supports-color 963 | dev: false 964 | 965 | /ms@2.0.0: 966 | resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} 967 | dev: false 968 | 969 | /ms@2.1.2: 970 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 971 | dev: false 972 | 973 | /ms@2.1.3: 974 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 975 | dev: false 976 | 977 | /multer@1.4.5-lts.1: 978 | resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==} 979 | engines: {node: '>= 6.0.0'} 980 | dependencies: 981 | append-field: 1.0.0 982 | busboy: 1.6.0 983 | concat-stream: 1.6.2 984 | mkdirp: 0.5.6 985 | object-assign: 4.1.1 986 | type-is: 1.6.18 987 | xtend: 4.0.2 988 | dev: false 989 | 990 | /negotiator@0.6.3: 991 | resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} 992 | engines: {node: '>= 0.6'} 993 | dev: false 994 | 995 | /node-addon-api@5.1.0: 996 | resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} 997 | dev: false 998 | 999 | /node-fetch@2.7.0: 1000 | resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 1001 | engines: {node: 4.x || >=6.0.0} 1002 | peerDependencies: 1003 | encoding: ^0.1.0 1004 | peerDependenciesMeta: 1005 | encoding: 1006 | optional: true 1007 | dependencies: 1008 | whatwg-url: 5.0.0 1009 | dev: false 1010 | 1011 | /nodemailer@6.9.13: 1012 | resolution: {integrity: sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==} 1013 | engines: {node: '>=6.0.0'} 1014 | dev: false 1015 | 1016 | /nodemon@3.1.0: 1017 | resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==} 1018 | engines: {node: '>=10'} 1019 | hasBin: true 1020 | dependencies: 1021 | chokidar: 3.6.0 1022 | debug: 4.3.4(supports-color@5.5.0) 1023 | ignore-by-default: 1.0.1 1024 | minimatch: 3.1.2 1025 | pstree.remy: 1.1.8 1026 | semver: 7.6.0 1027 | simple-update-notifier: 2.0.0 1028 | supports-color: 5.5.0 1029 | touch: 3.1.0 1030 | undefsafe: 2.0.5 1031 | dev: false 1032 | 1033 | /nopt@1.0.10: 1034 | resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} 1035 | hasBin: true 1036 | dependencies: 1037 | abbrev: 1.1.1 1038 | dev: false 1039 | 1040 | /nopt@5.0.0: 1041 | resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} 1042 | engines: {node: '>=6'} 1043 | hasBin: true 1044 | dependencies: 1045 | abbrev: 1.1.1 1046 | dev: false 1047 | 1048 | /normalize-path@3.0.0: 1049 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1050 | engines: {node: '>=0.10.0'} 1051 | dev: false 1052 | 1053 | /npmlog@5.0.1: 1054 | resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} 1055 | dependencies: 1056 | are-we-there-yet: 2.0.0 1057 | console-control-strings: 1.1.0 1058 | gauge: 3.0.2 1059 | set-blocking: 2.0.0 1060 | dev: false 1061 | 1062 | /object-assign@4.1.1: 1063 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1064 | engines: {node: '>=0.10.0'} 1065 | dev: false 1066 | 1067 | /object-inspect@1.13.1: 1068 | resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} 1069 | dev: false 1070 | 1071 | /on-finished@2.4.1: 1072 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} 1073 | engines: {node: '>= 0.8'} 1074 | dependencies: 1075 | ee-first: 1.1.1 1076 | dev: false 1077 | 1078 | /once@1.4.0: 1079 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1080 | dependencies: 1081 | wrappy: 1.0.2 1082 | dev: false 1083 | 1084 | /parseurl@1.3.3: 1085 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} 1086 | engines: {node: '>= 0.8'} 1087 | dev: false 1088 | 1089 | /path-is-absolute@1.0.1: 1090 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1091 | engines: {node: '>=0.10.0'} 1092 | dev: false 1093 | 1094 | /path-to-regexp@0.1.7: 1095 | resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} 1096 | dev: false 1097 | 1098 | /picomatch@2.3.1: 1099 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1100 | engines: {node: '>=8.6'} 1101 | dev: false 1102 | 1103 | /process-nextick-args@2.0.1: 1104 | resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} 1105 | dev: false 1106 | 1107 | /proxy-addr@2.0.7: 1108 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} 1109 | engines: {node: '>= 0.10'} 1110 | dependencies: 1111 | forwarded: 0.2.0 1112 | ipaddr.js: 1.9.1 1113 | dev: false 1114 | 1115 | /pstree.remy@1.1.8: 1116 | resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} 1117 | dev: false 1118 | 1119 | /punycode@2.3.1: 1120 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1121 | engines: {node: '>=6'} 1122 | dev: false 1123 | 1124 | /qs@6.11.0: 1125 | resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} 1126 | engines: {node: '>=0.6'} 1127 | dependencies: 1128 | side-channel: 1.0.6 1129 | dev: false 1130 | 1131 | /range-parser@1.2.1: 1132 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} 1133 | engines: {node: '>= 0.6'} 1134 | dev: false 1135 | 1136 | /raw-body@2.5.2: 1137 | resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} 1138 | engines: {node: '>= 0.8'} 1139 | dependencies: 1140 | bytes: 3.1.2 1141 | http-errors: 2.0.0 1142 | iconv-lite: 0.4.24 1143 | unpipe: 1.0.0 1144 | dev: false 1145 | 1146 | /readable-stream@2.3.8: 1147 | resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} 1148 | dependencies: 1149 | core-util-is: 1.0.3 1150 | inherits: 2.0.4 1151 | isarray: 1.0.0 1152 | process-nextick-args: 2.0.1 1153 | safe-buffer: 5.1.2 1154 | string_decoder: 1.1.1 1155 | util-deprecate: 1.0.2 1156 | dev: false 1157 | 1158 | /readable-stream@3.6.2: 1159 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 1160 | engines: {node: '>= 6'} 1161 | dependencies: 1162 | inherits: 2.0.4 1163 | string_decoder: 1.3.0 1164 | util-deprecate: 1.0.2 1165 | dev: false 1166 | 1167 | /readdirp@3.6.0: 1168 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1169 | engines: {node: '>=8.10.0'} 1170 | dependencies: 1171 | picomatch: 2.3.1 1172 | dev: false 1173 | 1174 | /rimraf@3.0.2: 1175 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 1176 | hasBin: true 1177 | dependencies: 1178 | glob: 7.2.3 1179 | dev: false 1180 | 1181 | /safe-buffer@5.1.2: 1182 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 1183 | dev: false 1184 | 1185 | /safe-buffer@5.2.1: 1186 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1187 | dev: false 1188 | 1189 | /safer-buffer@2.1.2: 1190 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1191 | dev: false 1192 | 1193 | /semver@6.3.1: 1194 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1195 | hasBin: true 1196 | dev: false 1197 | 1198 | /semver@7.6.0: 1199 | resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} 1200 | engines: {node: '>=10'} 1201 | hasBin: true 1202 | dependencies: 1203 | lru-cache: 6.0.0 1204 | dev: false 1205 | 1206 | /send@0.18.0: 1207 | resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} 1208 | engines: {node: '>= 0.8.0'} 1209 | dependencies: 1210 | debug: 2.6.9 1211 | depd: 2.0.0 1212 | destroy: 1.2.0 1213 | encodeurl: 1.0.2 1214 | escape-html: 1.0.3 1215 | etag: 1.8.1 1216 | fresh: 0.5.2 1217 | http-errors: 2.0.0 1218 | mime: 1.6.0 1219 | ms: 2.1.3 1220 | on-finished: 2.4.1 1221 | range-parser: 1.2.1 1222 | statuses: 2.0.1 1223 | transitivePeerDependencies: 1224 | - supports-color 1225 | dev: false 1226 | 1227 | /serve-static@1.15.0: 1228 | resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} 1229 | engines: {node: '>= 0.8.0'} 1230 | dependencies: 1231 | encodeurl: 1.0.2 1232 | escape-html: 1.0.3 1233 | parseurl: 1.3.3 1234 | send: 0.18.0 1235 | transitivePeerDependencies: 1236 | - supports-color 1237 | dev: false 1238 | 1239 | /set-blocking@2.0.0: 1240 | resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} 1241 | dev: false 1242 | 1243 | /set-function-length@1.2.2: 1244 | resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} 1245 | engines: {node: '>= 0.4'} 1246 | dependencies: 1247 | define-data-property: 1.1.4 1248 | es-errors: 1.3.0 1249 | function-bind: 1.1.2 1250 | get-intrinsic: 1.2.4 1251 | gopd: 1.0.1 1252 | has-property-descriptors: 1.0.2 1253 | dev: false 1254 | 1255 | /setprototypeof@1.2.0: 1256 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} 1257 | dev: false 1258 | 1259 | /side-channel@1.0.6: 1260 | resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} 1261 | engines: {node: '>= 0.4'} 1262 | dependencies: 1263 | call-bind: 1.0.7 1264 | es-errors: 1.3.0 1265 | get-intrinsic: 1.2.4 1266 | object-inspect: 1.13.1 1267 | dev: false 1268 | 1269 | /sift@16.0.1: 1270 | resolution: {integrity: sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==} 1271 | dev: false 1272 | 1273 | /signal-exit@3.0.7: 1274 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 1275 | dev: false 1276 | 1277 | /simple-update-notifier@2.0.0: 1278 | resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} 1279 | engines: {node: '>=10'} 1280 | dependencies: 1281 | semver: 7.6.0 1282 | dev: false 1283 | 1284 | /sparse-bitfield@3.0.3: 1285 | resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} 1286 | requiresBuild: true 1287 | dependencies: 1288 | memory-pager: 1.5.0 1289 | dev: false 1290 | 1291 | /statuses@2.0.1: 1292 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} 1293 | engines: {node: '>= 0.8'} 1294 | dev: false 1295 | 1296 | /streamsearch@1.1.0: 1297 | resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} 1298 | engines: {node: '>=10.0.0'} 1299 | dev: false 1300 | 1301 | /string-width@4.2.3: 1302 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1303 | engines: {node: '>=8'} 1304 | dependencies: 1305 | emoji-regex: 8.0.0 1306 | is-fullwidth-code-point: 3.0.0 1307 | strip-ansi: 6.0.1 1308 | dev: false 1309 | 1310 | /string_decoder@1.1.1: 1311 | resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} 1312 | dependencies: 1313 | safe-buffer: 5.1.2 1314 | dev: false 1315 | 1316 | /string_decoder@1.3.0: 1317 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 1318 | dependencies: 1319 | safe-buffer: 5.2.1 1320 | dev: false 1321 | 1322 | /strip-ansi@6.0.1: 1323 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1324 | engines: {node: '>=8'} 1325 | dependencies: 1326 | ansi-regex: 5.0.1 1327 | dev: false 1328 | 1329 | /supports-color@5.5.0: 1330 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 1331 | engines: {node: '>=4'} 1332 | dependencies: 1333 | has-flag: 3.0.0 1334 | dev: false 1335 | 1336 | /tar@6.2.1: 1337 | resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} 1338 | engines: {node: '>=10'} 1339 | dependencies: 1340 | chownr: 2.0.0 1341 | fs-minipass: 2.1.0 1342 | minipass: 5.0.0 1343 | minizlib: 2.1.2 1344 | mkdirp: 1.0.4 1345 | yallist: 4.0.0 1346 | dev: false 1347 | 1348 | /to-regex-range@5.0.1: 1349 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1350 | engines: {node: '>=8.0'} 1351 | dependencies: 1352 | is-number: 7.0.0 1353 | dev: false 1354 | 1355 | /toidentifier@1.0.1: 1356 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} 1357 | engines: {node: '>=0.6'} 1358 | dev: false 1359 | 1360 | /touch@3.1.0: 1361 | resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} 1362 | hasBin: true 1363 | dependencies: 1364 | nopt: 1.0.10 1365 | dev: false 1366 | 1367 | /tr46@0.0.3: 1368 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 1369 | dev: false 1370 | 1371 | /tr46@4.1.1: 1372 | resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} 1373 | engines: {node: '>=14'} 1374 | dependencies: 1375 | punycode: 2.3.1 1376 | dev: false 1377 | 1378 | /type-is@1.6.18: 1379 | resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} 1380 | engines: {node: '>= 0.6'} 1381 | dependencies: 1382 | media-typer: 0.3.0 1383 | mime-types: 2.1.35 1384 | dev: false 1385 | 1386 | /typedarray@0.0.6: 1387 | resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} 1388 | dev: false 1389 | 1390 | /undefsafe@2.0.5: 1391 | resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} 1392 | dev: false 1393 | 1394 | /unpipe@1.0.0: 1395 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} 1396 | engines: {node: '>= 0.8'} 1397 | dev: false 1398 | 1399 | /util-deprecate@1.0.2: 1400 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1401 | dev: false 1402 | 1403 | /utils-merge@1.0.1: 1404 | resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} 1405 | engines: {node: '>= 0.4.0'} 1406 | dev: false 1407 | 1408 | /vary@1.1.2: 1409 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} 1410 | engines: {node: '>= 0.8'} 1411 | dev: false 1412 | 1413 | /webidl-conversions@3.0.1: 1414 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 1415 | dev: false 1416 | 1417 | /webidl-conversions@7.0.0: 1418 | resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} 1419 | engines: {node: '>=12'} 1420 | dev: false 1421 | 1422 | /whatwg-url@13.0.0: 1423 | resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==} 1424 | engines: {node: '>=16'} 1425 | dependencies: 1426 | tr46: 4.1.1 1427 | webidl-conversions: 7.0.0 1428 | dev: false 1429 | 1430 | /whatwg-url@5.0.0: 1431 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 1432 | dependencies: 1433 | tr46: 0.0.3 1434 | webidl-conversions: 3.0.1 1435 | dev: false 1436 | 1437 | /wide-align@1.1.5: 1438 | resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} 1439 | dependencies: 1440 | string-width: 4.2.3 1441 | dev: false 1442 | 1443 | /wrappy@1.0.2: 1444 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1445 | dev: false 1446 | 1447 | /xtend@4.0.2: 1448 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} 1449 | engines: {node: '>=0.4'} 1450 | dev: false 1451 | 1452 | /yallist@4.0.0: 1453 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1454 | dev: false 1455 | -------------------------------------------------------------------------------- /src/app/auth/controller.js: -------------------------------------------------------------------------------- 1 | const user = require("../users/model"); 2 | const bcrypt = require("bcrypt"); 3 | const Response = require("../../utils/response"); 4 | const APIError = require("../../utils/errors"); 5 | const { createToken, createTemporaryToken, decodedTemporaryToken } = require("../../middlewares/auth"); 6 | const crypto = require("crypto"); 7 | const sendEmail = require("../../utils/sendMail"); 8 | const moment = require("moment"); 9 | 10 | 11 | const login = async (req, res) => { 12 | console.log("login"); 13 | const { email, password } = req.body; 14 | 15 | const userInfo = await user.findOne({ email }); 16 | 17 | if (!userInfo) throw new APIError("Email yada Şifre Hatalıdır !", 401); 18 | 19 | const comparePassword = await bcrypt.compare(password, userInfo.password); 20 | console.log(comparePassword); 21 | 22 | if (!comparePassword) throw new APIError("Email yada Şifre Hatalıdır !", 401); 23 | 24 | createToken(userInfo, res); 25 | }; 26 | 27 | const register = async (req, res) => { 28 | const { email } = req.body; 29 | 30 | const userCheck = await user.findOne({ email }); 31 | 32 | if (userCheck) { 33 | throw new APIError("Girmiş Olduğunuz Email Kullanımda !", 401); 34 | } 35 | 36 | req.body.password = await bcrypt.hash(req.body.password, 10); 37 | 38 | console.log("hash şifre : ", req.body.password); 39 | 40 | const userSave = new user(req.body); 41 | 42 | await userSave 43 | .save() 44 | .then((data) => { 45 | return new Response(data, "Kayıt Başarıyla Eklendi").created(res); 46 | }) 47 | .catch((err) => { 48 | throw new APIError("Kullanıcı Kayıt Edilemedi !", 400); 49 | }); 50 | }; 51 | 52 | 53 | const forgetPassword = async (req, res) => { 54 | const { email } = req.body; 55 | 56 | const userInfo = await user 57 | .findOne({ email }) 58 | .select(" name lastname email "); 59 | 60 | if (!userInfo) return new APIError("Geçersiz Kullanıcı", 400); 61 | 62 | console.log("userInfo : ", userInfo); 63 | 64 | const resetCode = crypto.randomBytes(3).toString("hex"); 65 | 66 | console.log(resetCode); 67 | 68 | // await sendEmail({ 69 | // from: "base.api.proje@outlook.com", 70 | // to: userInfo.email, 71 | // subject: "Şifre Sıfırlama", 72 | // text: `Şifre Sıfırlama Kodunuz ${resetCode}` 73 | // }) 74 | 75 | await user.updateOne( 76 | { email }, 77 | { 78 | reset: { 79 | code: resetCode, 80 | time: moment(new Date()) 81 | .add(15, "minute") 82 | .format("YYYY-MM-DD HH:mm:ss"), 83 | }, 84 | } 85 | ); 86 | 87 | return new Response(true, "Lütfen Mail Kutunuzu Kontrol Ediniz").success(res); 88 | }; 89 | 90 | const resetCodeCheck = async (req, res) => { 91 | const { email, code } = req.body; 92 | 93 | const userInfo = await user 94 | .findOne({ email }) 95 | .select("_id name lastname email reset"); 96 | 97 | if (!userInfo) throw new APIError("Geçersiz Kod !", 401); 98 | 99 | const dbTime = moment(userInfo.reset.time); 100 | const nowTime = moment(new Date()); 101 | 102 | const timeDiff = dbTime.diff(nowTime, "minutes"); 103 | 104 | console.log("Zaman farkı : ", timeDiff); 105 | 106 | if (timeDiff <= 0 || userInfo.reset.code !== code) { 107 | throw new APIError("Geçersiz Kod", 401); 108 | } 109 | 110 | const temporaryToken = await createTemporaryToken( 111 | userInfo._id, 112 | userInfo.email 113 | ); 114 | 115 | return new Response( 116 | { temporaryToken }, 117 | "Şifre Sıfırlama Yapabilirsiniz" 118 | ).success(res); 119 | }; 120 | 121 | const resetPassword = async (req, res) => { 122 | const { password, temporaryToken } = req.body; 123 | 124 | const decodedToken = await decodedTemporaryToken(temporaryToken); 125 | console.log("decodedToken : ", decodedToken); 126 | 127 | const hashPassword = await bcrypt.hash(password, 10); 128 | 129 | await user.findByIdAndUpdate( 130 | { _id: decodedToken._id }, 131 | { 132 | reset: { 133 | code: null, 134 | time: null, 135 | }, 136 | password: hashPassword, 137 | } 138 | ); 139 | 140 | return new Response(decodedToken, "Şifre Sıfırlama Başarılı").success(res) 141 | }; 142 | 143 | 144 | 145 | 146 | 147 | 148 | module.exports = { 149 | login, 150 | register, 151 | forgetPassword, 152 | resetCodeCheck, 153 | resetPassword, 154 | }; 155 | -------------------------------------------------------------------------------- /src/app/auth/router.js: -------------------------------------------------------------------------------- 1 | const router = require("express").Router(); 2 | const { 3 | login, 4 | register, 5 | forgetPassword, 6 | resetCodeCheck, 7 | resetPassword, 8 | } = require("./controller"); 9 | const authValidation = require("../../middlewares/validations/auth.validation"); 10 | 11 | router.post("/login", authValidation.login, login); 12 | 13 | router.post("/register", authValidation.register, register); 14 | 15 | router.post("/forget-password", forgetPassword); 16 | 17 | router.post("/reset-code-check", resetCodeCheck); 18 | 19 | router.post("/reset-password", resetPassword); 20 | 21 | module.exports = router; 22 | -------------------------------------------------------------------------------- /src/app/users/controller.js: -------------------------------------------------------------------------------- 1 | const Response = require("../../utils/response"); 2 | 3 | const me = async (req, res) => { 4 | return new Response(req.user).success(res); 5 | }; 6 | 7 | module.exports = { 8 | me, 9 | }; 10 | -------------------------------------------------------------------------------- /src/app/users/model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose") 2 | 3 | const userShema = new mongoose.Schema({ 4 | name: { 5 | type: String, 6 | required: true, 7 | trim: true 8 | }, 9 | lastname: { 10 | type: String, 11 | required: true, 12 | trim: true 13 | }, 14 | email: { 15 | type: String, 16 | required: true, 17 | trim: true, 18 | unique: true 19 | }, 20 | password: { 21 | type: String, 22 | required: true, 23 | trim: true 24 | }, 25 | reset: { 26 | code: { 27 | type: String, 28 | default: null 29 | } , 30 | time: { 31 | type: String, 32 | default: null 33 | } 34 | } 35 | },{collection: "users", timestamps: true}) 36 | 37 | const user = mongoose.model("users", userShema) 38 | 39 | module.exports = user -------------------------------------------------------------------------------- /src/app/users/router.js: -------------------------------------------------------------------------------- 1 | const router = require("express").Router(); 2 | const { me } = require("./controller"); 3 | const { tokenCheck } = require("../../middlewares/auth"); 4 | 5 | router.get("/me", tokenCheck, me); 6 | 7 | module.exports = router; 8 | -------------------------------------------------------------------------------- /src/db/dbConnection.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose") 2 | 3 | mongoose.connect(process.env.DB_URL, { 4 | useNewUrlParser: true, 5 | useUnifiedTopology: true 6 | }) 7 | .then(() => { 8 | console.log("Veritabanına Başarıyla Bağlandı"); 9 | }) 10 | .catch((err) => { 11 | console.log("Veritabanına bağlanırken hata çıktı : ", err); 12 | }) -------------------------------------------------------------------------------- /src/helpers/corsOptions.js: -------------------------------------------------------------------------------- 1 | const whiteList = ["http://localhost:3000"] 2 | 3 | const corsOptions = (req, callback) => { 4 | let corsOptions; 5 | if (whiteList.indexOf(req.header("Origin")) !== -1) { 6 | corsOptions = {origin: true} 7 | } else { 8 | corsOptions = {origin: false} 9 | } 10 | 11 | callback(null, corsOptions) 12 | } 13 | 14 | module.exports = corsOptions -------------------------------------------------------------------------------- /src/middlewares/auth.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken") 2 | const user = require("../app/users/model") 3 | const APIError = require("../utils/errors") 4 | 5 | const createToken = async (user, res) => { 6 | const payload = { 7 | sub: user._id, 8 | name: user.name 9 | } 10 | 11 | const token = await jwt.sign(payload, process.env.JWT_SECRET_KEY, { 12 | algorithm: "HS512", 13 | expiresIn: process.env.JWT_EXPIRES_IN 14 | }) 15 | 16 | return res.status(201).json({ 17 | success: true, 18 | token, 19 | message: "Başarılı" 20 | }) 21 | } 22 | 23 | const tokenCheck = async (req, res, next) => { 24 | const headerToken = req.headers.authorization && req.headers.authorization.startsWith("Bearer ") 25 | 26 | if (!headerToken) 27 | throw new APIError("Geçersiz Oturum Lütfen Oturum Açın",401) 28 | 29 | const token = req.headers.authorization.split(" ")[1] 30 | 31 | await jwt.verify(token, process.env.JWT_SECRET_KEY, async (err, decoded) => { 32 | if (err) throw new APIError("Geçersiz Token",401) 33 | 34 | const userInfo = await user.findById(decoded.sub).select("_id name lastname email ") 35 | 36 | if (!userInfo) 37 | throw new APIError("Geçersiz Token",401) 38 | 39 | req.user = userInfo 40 | next(); 41 | }) 42 | 43 | } 44 | 45 | const createTemporaryToken = async (userId, email) => { 46 | const payload = { 47 | sub: userId, 48 | email 49 | } 50 | 51 | const token = await jwt.sign(payload, process.env.JWT_TEMPORARY_KEY, { 52 | algorithm: "HS512", 53 | expiresIn: process.env.JWT_TEMPORARY_EXPIRES_IN 54 | }) 55 | 56 | return "Bearer " + token 57 | } 58 | 59 | const decodedTemporaryToken = async (temporaryToken) => { 60 | const token = temporaryToken.split(" ")[1] 61 | let userInfo; 62 | await jwt.verify(token, process.env.JWT_TEMPORARY_KEY, async (err, decoded) => { 63 | if (err) throw new APIError("Geçersiz Token", 401) 64 | 65 | userInfo = await user.findById(decoded.sub).select("_id name lastname email") 66 | if (!userInfo) throw new APIError("Geçersiz Token", 401) 67 | 68 | }) 69 | 70 | return userInfo 71 | } 72 | 73 | module.exports = { 74 | createToken, 75 | tokenCheck, 76 | createTemporaryToken, 77 | decodedTemporaryToken 78 | } -------------------------------------------------------------------------------- /src/middlewares/errorHandler.js: -------------------------------------------------------------------------------- 1 | const APIError = require("../utils/errors") 2 | 3 | const errorHandlerMiddleware = (err, req, res, next) => { 4 | if (err instanceof APIError) { 5 | return res.status(err.statusCode || 400) 6 | .json({ 7 | success: false, 8 | message: err.message 9 | }) 10 | } 11 | 12 | console.log(err); 13 | 14 | return res.status(500).json({ 15 | success: false, 16 | message: "Bir hata ile karşılaştık lütfen apinizi kontrol ediniz !" 17 | }) 18 | } 19 | 20 | module.exports = errorHandlerMiddleware -------------------------------------------------------------------------------- /src/middlewares/lib/upload.js: -------------------------------------------------------------------------------- 1 | const multer = require("multer") 2 | const path = require("path") 3 | const fs = require("fs") 4 | 5 | const fileFilter = (req, file, cb) => { 6 | const allowedMimeTypes = ["images/jpg", "image/gif", "image/jpeg", "image/png"] 7 | 8 | if (!allowedMimeTypes.includes(file.mimetype)) { 9 | cb(new Error("Bu Resim Tipi Desteklenmemektedir. Lütfen Farklı Bir Resim Seçiniz !"), false) 10 | } 11 | cb(null, true) 12 | } 13 | 14 | const storage = multer.diskStorage({ 15 | destination: function (req, file, cb) { 16 | const rootDir = path.dirname(require.main.filename) 17 | console.log("require.main.filename : ",require.main.filename); 18 | 19 | fs.mkdirSync(path.join(rootDir, "/public/uploads"), { recursive: true }) 20 | cb(null, path.join(rootDir, "/public/uploads")) 21 | }, 22 | filename: function (req, file, cb) { 23 | const extension = file.mimetype.split("/")[1] 24 | 25 | if (!req.savedImages) req.savedImages = [] 26 | 27 | const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9) 28 | 29 | let url = `image_${uniqueSuffix}.${extension}` 30 | 31 | req.savedImages = [...req.savedImages, path.join(url)] 32 | 33 | cb(null, url) 34 | } 35 | }) 36 | 37 | const upload = multer({storage, fileFilter}).array("images") 38 | module.exports = upload -------------------------------------------------------------------------------- /src/middlewares/rateLimit.js: -------------------------------------------------------------------------------- 1 | const rateLimit = require("express-rate-limit") 2 | 3 | const allowList = ["::1"] 4 | 5 | const apiLimiter = rateLimit({ 6 | windowMs: 15 * 60 * 1000, 7 | max: (req, res) => { 8 | if (req.url === "/login" || req.url === "/register") return 5 9 | else return 100 10 | }, 11 | message: { 12 | success: false, 13 | message: "Çok fazla istekte bulundunuz !" 14 | }, 15 | skip: (req, res) => allowList.includes(req.ip), 16 | standardHeaders: true, 17 | legacyHeaders: false, 18 | }) 19 | 20 | module.exports = apiLimiter -------------------------------------------------------------------------------- /src/middlewares/validations/auth.validation.js: -------------------------------------------------------------------------------- 1 | const joi = require("joi") 2 | const APIError = require("../../utils/errors") 3 | 4 | class authValidation { 5 | constructor() {} 6 | static register = async (req, res, next) => { 7 | try { 8 | 9 | await joi.object({ 10 | name: joi.string().trim().min(3).max(100).required().messages({ 11 | "string.base": "İsim Alanı Normal Metin Olmalıdır", 12 | "string.empty": "İsim Alanı Boş Olamaz !", 13 | "string.min": "İsim Alanı Ez Az 3 Karakter Olmalıdır", 14 | "string.max": "İsim Alanı En Fazla 100 Karakterden Oluşabilir", 15 | "string.required": "İsim Alanı Zorunludur" 16 | }), 17 | lastname: joi.string().trim().min(3).max(100).required().messages({ 18 | "string.base": "Soyad Alanı Normal Metin Olmalıdır", 19 | "string.empty": "Soyad Alanı Boş Olamaz !", 20 | "string.min": "Soyad Alanı Ez Az 3 Karakter Olmalıdır", 21 | "string.max": "Soyad Alanı En Fazla 100 Karakterden Oluşabilir", 22 | "string.required": "Soyad Alanı Zorunludur" 23 | }), 24 | email: joi.string().email().trim().min(3).max(100).required().messages({ 25 | "string.base": "Email Alanı Normal Metin Olmalıdır", 26 | "string.empty": "Email Alanı Boş Olamaz !", 27 | "string.min": "Email Alanı Ez Az 3 Karakter Olmalıdır", 28 | "string.email": "Lütfen Geçerli Bir Email Giriniz", 29 | "string.max": "Email Alanı En Fazla 100 Karakterden Oluşabilir", 30 | "string.required": "Email Alanı Zorunludur" 31 | }), 32 | password: joi.string().trim().min(6).max(36).required().messages({ 33 | "string.base": "Şifre Alanı Normal Metin Olmalıdır", 34 | "string.empty": "Şifre Alanı Boş Olamaz !", 35 | "string.min": "Şifre Alanı Ez Az 6 Karakter Olmalıdır", 36 | "string.max": "Şifre Alanı En Fazla 36 Karakterden Oluşabilir", 37 | "string.required": "Şifre Alanı Zorunludur" 38 | }) 39 | }).validateAsync(req.body) 40 | } catch (error) { 41 | if (error.details && error?.details[0].message) 42 | throw new APIError(error.details[0].message, 400) 43 | else throw new APIError("Lütfen Validasyon Kullarına Uyun", 400) 44 | } 45 | next() 46 | } 47 | 48 | static login = async (req, res, next) => { 49 | try { 50 | await joi.object({ 51 | email: joi.string().email().trim().min(3).max(100).required().messages({ 52 | "string.base": "Email Alanı Normal Metin Olmalıdır", 53 | "string.empty": "Email Alanı Boş Olamaz !", 54 | "string.min": "Email Alanı Ez Az 3 Karakter Olmalıdır", 55 | "string.email": "Lütfen Geçerli Bir Email Giriniz", 56 | "string.max": "Email Alanı En Fazla 100 Karakterden Oluşabilir", 57 | "string.required": "Email Alanı Zorunludur" 58 | }), 59 | password: joi.string().trim().min(6).max(36).required().messages({ 60 | "string.base": "Şifre Alanı Normal Metin Olmalıdır", 61 | "string.empty": "Şifre Alanı Boş Olamaz !", 62 | "string.min": "Şifre Alanı Ez Az 6 Karakter Olmalıdır", 63 | "string.max": "Şifre Alanı En Fazla 36 Karakterden Oluşabilir", 64 | "string.required": "Şifre Alanı Zorunludur" 65 | }) 66 | }).validateAsync(req.body) 67 | } catch (error) { 68 | if (error.details && error?.details[0].message) 69 | throw new APIError(error.details[0].message, 400) 70 | else throw new APIError("Lütfen Validasyon Kullarına Uyun", 400) 71 | } 72 | next(); 73 | } 74 | } 75 | 76 | module.exports = authValidation -------------------------------------------------------------------------------- /src/routers/index.js: -------------------------------------------------------------------------------- 1 | const router = require("express").Router(); 2 | const multer = require("multer"); 3 | const upload = require("../middlewares/lib/upload"); 4 | const APIError = require("../utils/errors"); 5 | const Response = require("../utils/response"); 6 | 7 | const auth = require("../app/auth/router"); 8 | const user = require("../app/users/router"); 9 | 10 | router.use(auth); 11 | router.use(user); 12 | 13 | router.post("/upload", function (req, res) { 14 | upload(req, res, function (err) { 15 | if (err instanceof multer.MulterError) 16 | throw new APIError( 17 | "Resim Yüklenirken Multer Kaynaklı Hata Çıktı : ", 18 | err 19 | ); 20 | else if (err) throw new APIError("Resim Yüklenirken Hata Çıktı : ", err); 21 | else return new Response(req.savedImages, "Yükleme Başarılı").success(res); 22 | }); 23 | }); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /src/utils/errors.js: -------------------------------------------------------------------------------- 1 | class APIError extends Error { 2 | constructor(message, statusCode) { 3 | super(message) 4 | this.statusCode = statusCode || 400 5 | } 6 | } 7 | 8 | module.exports = APIError -------------------------------------------------------------------------------- /src/utils/response.js: -------------------------------------------------------------------------------- 1 | class Response { 2 | constructor(data = null, message = null) { 3 | this.data = data 4 | this.message = message 5 | } 6 | 7 | success(res) { 8 | return res.status(200).json({ 9 | success: true, 10 | data: this.data, 11 | message: this.message ?? "İşlem Başarılı" 12 | }) 13 | } 14 | 15 | created(res) { 16 | return res.status(201).json({ 17 | success: true, 18 | data: this.data, 19 | message: this.message ?? "İşlem Başarılı" 20 | }) 21 | } 22 | 23 | error500(res) { 24 | return res.status(500).json({ 25 | success: false, 26 | data: this.data, 27 | message: this.message ?? "İşlem Başarısız !" 28 | }) 29 | } 30 | 31 | error400(res) { 32 | return res.status(400).json({ 33 | success: false, 34 | data: this.data, 35 | message: this.message ?? "İşlem Başarısız !" 36 | }) 37 | } 38 | 39 | error401(res) { 40 | return res.status(401).json({ 41 | success: false, 42 | data: this.data, 43 | message: this.message ?? "Lütfen Oturum Açın !" 44 | }) 45 | } 46 | 47 | error404(res) { 48 | return res.status(404).json({ 49 | success: false, 50 | data: this.data, 51 | message: this.message ?? "İşlem Başarısız !" 52 | }) 53 | } 54 | 55 | error429(res) { 56 | return res.status(429).json({ 57 | success: false, 58 | data: this.data, 59 | message: this.message ?? "Çok Fazla İstek Atıldı !" 60 | }) 61 | } 62 | 63 | } 64 | 65 | module.exports = Response -------------------------------------------------------------------------------- /src/utils/sendMail.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require("nodemailer"); 2 | const APIError = require("./errors"); 3 | 4 | const sendEmail = async (mailOptions) => { 5 | const transporter = await nodemailer.createTransport({ 6 | host: "smtp-mail.outlook.com", 7 | port: 465, 8 | secure: true, 9 | auth: { 10 | user: process.env.EMAIL_USER, 11 | pass: process.env.EMAIL_PASSWORD 12 | } 13 | }) 14 | 15 | await transporter.sendMail(mailOptions, (error, info) => { 16 | if (error) { 17 | console.log("Hata Çıktı Mail Gönderilemedi : ", error); 18 | throw new APIError("Mail Gönderilemedi !") 19 | } 20 | console.log("info : ",info); 21 | return true 22 | }) 23 | } 24 | 25 | module.exports = sendEmail --------------------------------------------------------------------------------