From 4e117825993fb92f59ad22357b13614c029c22e6 Mon Sep 17 00:00:00 2001 From: Ricardo_Barros Date: Fri, 10 Mar 2023 22:50:55 -0300 Subject: [PATCH 01/32] feat: Iniciando o projeto Lama4 --- .gitignore | 3 + package-lock.json | 2959 ++++++++++++++++++++++++++++++ package.json | 35 + requests.rest | 11 + src/business/UserBusiness.ts | 43 + src/controller/UserController.ts | 48 + src/data/BaseDatabase.ts | 20 + src/data/UserDatabase.ts | 39 + src/error/BaseError.ts | 65 + src/index.ts | 19 + src/model/User.ts | 83 + src/routes/userRouter.ts | 10 + src/services/Authenticator.ts | 32 + src/services/HashManager.ts | 17 + src/services/IdGenerator.ts | 8 + tables.sql | 36 + tsconfig.json | 11 + 17 files changed, 3439 insertions(+) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 requests.rest create mode 100644 src/business/UserBusiness.ts create mode 100644 src/controller/UserController.ts create mode 100644 src/data/BaseDatabase.ts create mode 100644 src/data/UserDatabase.ts create mode 100644 src/error/BaseError.ts create mode 100644 src/index.ts create mode 100644 src/model/User.ts create mode 100644 src/routes/userRouter.ts create mode 100644 src/services/Authenticator.ts create mode 100644 src/services/HashManager.ts create mode 100644 src/services/IdGenerator.ts create mode 100644 tables.sql create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f563bb1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +node_modules +build \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5b240e3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2959 @@ +{ + "name": "lama-template", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "lama-template", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@types/bcryptjs": "^2.4.2", + "@types/jsonwebtoken": "^9.0.1", + "@types/uuid": "^9.0.1", + "bcryptjs": "^2.4.3", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "jsonwebtoken": "^9.0.0", + "knex": "^2.4.2", + "mysql": "^2.18.1", + "ts-node-dev": "^2.0.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/knex": "^0.16.1", + "cors": "^2.8.5" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "node_modules/@types/bcryptjs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", + "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==" + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.33", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", + "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/knex": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@types/knex/-/knex-0.16.1.tgz", + "integrity": "sha512-54gWD1HWwdVx5iLHaJ1qxH3I6KyBsj5fFqzRpXFn7REWiEB2jwspeVCombNsocSrqPd7IRPqKrsIME7/cD+TFQ==", + "deprecated": "This is a stub types definition. knex provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "knex": "*" + } + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.15.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.0.tgz", + "integrity": "sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "dev": true, + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==" + }, + "node_modules/@types/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/knex": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/knex/-/knex-2.4.2.tgz", + "integrity": "sha512-tMI1M7a+xwHhPxjbl/H9K1kHX+VncEYcvCx5K00M16bWvpYPKAZd6QrCu68PtHAdIZNQPWZn0GVhqVBEthGWCg==", + "dependencies": { + "colorette": "2.0.19", + "commander": "^9.1.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.5.0", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mysql/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + }, + "dependencies": { + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "@types/bcryptjs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", + "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==" + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.33", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", + "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==", + "requires": { + "@types/node": "*" + } + }, + "@types/knex": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@types/knex/-/knex-0.16.1.tgz", + "integrity": "sha512-54gWD1HWwdVx5iLHaJ1qxH3I6KyBsj5fFqzRpXFn7REWiEB2jwspeVCombNsocSrqPd7IRPqKrsIME7/cD+TFQ==", + "dev": true, + "requires": { + "knex": "*" + } + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "dev": true + }, + "@types/node": { + "version": "18.15.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.0.tgz", + "integrity": "sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/serve-static": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "dev": true, + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==" + }, + "@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==" + }, + "@types/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, + "dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "requires": { + "xtend": "^4.0.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + }, + "getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "requires": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "knex": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/knex/-/knex-2.4.2.tgz", + "integrity": "sha512-tMI1M7a+xwHhPxjbl/H9K1kHX+VncEYcvCx5K00M16bWvpYPKAZd6QrCu68PtHAdIZNQPWZn0GVhqVBEthGWCg==", + "requires": { + "colorette": "2.0.19", + "commander": "^9.1.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.5.0", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "requires": { + "resolve": "^1.20.0" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==" + }, + "tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "requires": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + } + }, + "tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "requires": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ca3b251 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "lama-template", + "version": "1.0.0", + "description": "Template para o projeto LAMA", + "main": "index.js", + "scripts": { + "dev": "ts-node-dev ./src/index.ts", + "start": "tsc && node ./build/index.js" + }, + "keywords": [ + "api", + "LAMA" + ], + "author": "Israel,Andréa,Júnior e Fay", + "license": "ISC", + "dependencies": { + "@types/bcryptjs": "^2.4.2", + "@types/jsonwebtoken": "^9.0.1", + "@types/uuid": "^9.0.1", + "bcryptjs": "^2.4.3", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "jsonwebtoken": "^9.0.0", + "knex": "^2.4.2", + "mysql": "^2.18.1", + "ts-node-dev": "^2.0.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/knex": "^0.16.1", + "cors": "^2.8.5" + } +} diff --git a/requests.rest b/requests.rest new file mode 100644 index 0000000..5529b21 --- /dev/null +++ b/requests.rest @@ -0,0 +1,11 @@ +### Criar Usuário + +POST http://localhost:3000/user/signup +Content-Type: application/json + +{ + "email": "exemplo-ricardo2@lbn.com", + "name": "Ricardo Barros", + "password": "102030", + "role": "ADMIN" +} \ No newline at end of file diff --git a/src/business/UserBusiness.ts b/src/business/UserBusiness.ts new file mode 100644 index 0000000..b645a82 --- /dev/null +++ b/src/business/UserBusiness.ts @@ -0,0 +1,43 @@ +import { UserInputDTO, LoginInputDTO } from "../model/User"; +import { UserDatabase } from "../data/UserDatabase"; +import { IdGenerator } from "../services/IdGenerator"; +import { HashManager } from "../services/HashManager"; +import { Authenticator } from "../services/Authenticator"; + +export class UserBusiness { + + async createUser(user: UserInputDTO) { + + const idGenerator = new IdGenerator(); + const id = idGenerator.generate(); + + const hashManager = new HashManager(); + const hashPassword = await hashManager.hash(user.password); + + const userDatabase = new UserDatabase(); + await userDatabase.createUser(id, user.email, user.name, hashPassword, user.role); + + const authenticator = new Authenticator(); + const accessToken = authenticator.generateToken({ id, role: user.role }); + + return accessToken; + } + + async getUserByEmail(user: LoginInputDTO) { + + const userDatabase = new UserDatabase(); + const userFromDB = await userDatabase.getUserByEmail(user.email); + + const hashManager = new HashManager(); + const hashCompare = await hashManager.compare(user.password, userFromDB.getPassword()); + + const authenticator = new Authenticator(); + const accessToken = authenticator.generateToken({ id: userFromDB.getId(), role: userFromDB.getRole() }); + + if (!hashCompare) { + throw new Error("Invalid Password!"); + } + + return accessToken; + } +} \ No newline at end of file diff --git a/src/controller/UserController.ts b/src/controller/UserController.ts new file mode 100644 index 0000000..be56c08 --- /dev/null +++ b/src/controller/UserController.ts @@ -0,0 +1,48 @@ +import { Request, Response } from "express" +import { UserInputDTO, LoginInputDTO} from "../model/User" +import { UserBusiness } from "../business/UserBusiness" + + +export class UserController { + async signup(req: Request, res: Response) { + try { + + const input: UserInputDTO = { + email: req.body.email, + name: req.body.name, + password: req.body.password, + role: req.body.role + } + + const userBusiness = new UserBusiness(); + const token = await userBusiness.createUser(input); + + res.status(200).send({ token }); + + } catch (error: any) { + res.status(400).send({ error: error.message }); + } + + } + + async login(req: Request, res: Response) { + + try { + + const loginData: LoginInputDTO = { + email: req.body.email, + password: req.body.password + }; + + const userBusiness = new UserBusiness(); + const token = await userBusiness.getUserByEmail(loginData); + + res.status(200).send({ token }); + + } catch (error: any) { + res.status(400).send({ error: error.message }); + } + + } + +} \ No newline at end of file diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts new file mode 100644 index 0000000..84ca189 --- /dev/null +++ b/src/data/BaseDatabase.ts @@ -0,0 +1,20 @@ +import knex from 'knex' +import dotenv from 'dotenv' + +dotenv.config() + +export class BaseDatabase { + + protected static connection = knex({ + client: 'mysql', + connection: { + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_SCHEMA, + port: 3306, + multipleStatements: true + } + }) + +} \ No newline at end of file diff --git a/src/data/UserDatabase.ts b/src/data/UserDatabase.ts new file mode 100644 index 0000000..66a883a --- /dev/null +++ b/src/data/UserDatabase.ts @@ -0,0 +1,39 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { User } from "../model/User"; + +export class UserDatabase extends BaseDatabase { + + private static TABLE_NAME = "Lama_Users"; + + public async createUser( + id: string, + email: string, + name: string, + password: string, + role: string + ): Promise { + try { + await BaseDatabase.connection + .insert({ + id, + email, + name, + password, + role + }) + .into(UserDatabase.TABLE_NAME); + } catch (error: any) { + throw new Error(error.sqlMessage || error.message); + } + } + + public async getUserByEmail(email: string): Promise { + const result = await BaseDatabase.connection + .select("*") + .from(UserDatabase.TABLE_NAME) + .where({ email }); + + return User.toUserModel(result[0]); + } + +} diff --git a/src/error/BaseError.ts b/src/error/BaseError.ts new file mode 100644 index 0000000..ba293f5 --- /dev/null +++ b/src/error/BaseError.ts @@ -0,0 +1,65 @@ +export abstract class BaseError extends Error { + constructor(message: string, public code: number) { + super(message); + } +} + + export class CustomError extends Error { + constructor(statusCode: number, message: string){ + super(message) + } +} + +export class InvalidName extends CustomError{ + constructor(){ + super(400, "Nome inválido") + } +} + +export class InvalidRole extends CustomError{ + constructor(){ + super(400, "Tipo de usuário inválido") + } +} + +export class InvalidEmail extends CustomError{ + constructor(){ + super(400, "Email inválido") + } +} + +export class InvalidPassword extends CustomError{ + constructor(){ + super(400, "Senha inválida") + } +} + +export class UserNotFound extends CustomError{ + constructor(){ + super(404, "Usuário não encontrado") + } +} + +export class Unauthorized extends CustomError{ + constructor(){ + super(401, "Usuário não autorizado") + } +} + +export class MissingToken extends CustomError{ + constructor(){ + super(404, "Token não encontrado!") + } +} + +export class ProfileNotFound extends CustomError{ + constructor(){ + super(404, "Perfil não encontrado!") + } +} + +export class EmailExist extends CustomError{ + constructor(){ + super(400, "Usuário já existe") + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..3d82c68 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,19 @@ +import dotenv from "dotenv"; +import {AddressInfo} from "net"; +import express from "express"; +import { userRouter } from "./routes/userRouter"; +dotenv.config(); +const app = express(); + +app.use(express.json()); + +app.use("/user", userRouter); + +const server = app.listen(3000, () => { + if (server) { + const address = server.address() as AddressInfo; + console.log(`Servidor rodando em http://localhost:${address.port}`); + } else { + console.error(`Falha ao rodar o servidor.`); + } + }); \ No newline at end of file diff --git a/src/model/User.ts b/src/model/User.ts new file mode 100644 index 0000000..9143a6a --- /dev/null +++ b/src/model/User.ts @@ -0,0 +1,83 @@ +export class User{ + constructor( + private id: string, + private name: string, + private email: string, + private password: string, + private role: UserRole + ){} + + getId(){ + return this.id; + } + + getName(){ + return this.name + } + + getEmail(){ + return this.email; + } + + getPassword(){ + return this.password; + } + + getRole(){ + return this.role; + } + + setId(id: string){ + this.id = id; + } + + setName(name: string){ + this.name = name; + } + + setEmail(email: string){ + this.email = email; + } + + setPassword(password: string){ + this.password = password; + } + + setRole(role: UserRole){ + this.role = role; + } + + static stringToUserRole(input: string): UserRole{ + switch (input) { + case "NORMAL": + return UserRole.NORMAL; + case "ADMIN": + return UserRole.ADMIN; + default: + throw new Error("Invalid user role"); + } + } + + static toUserModel(user: any): User { + return new User(user.id, user.name, user.email, user.password, User.stringToUserRole(user.role)); + } + + +} + +export interface UserInputDTO{ + email: string; + password: string; + name: string; + role: string; +} + +export interface LoginInputDTO{ + email: string; + password: string; +} + +export enum UserRole{ + NORMAL = "NORMAL", + ADMIN = "ADMIN" +} \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts new file mode 100644 index 0000000..1b56d3a --- /dev/null +++ b/src/routes/userRouter.ts @@ -0,0 +1,10 @@ +import express from "express"; +import { UserController } from "../controller/UserController"; + + +export const userRouter = express.Router(); + +const userController = new UserController(); + +userRouter.post("/signup", userController.signup); +userRouter.post("/login", userController.login); \ No newline at end of file diff --git a/src/services/Authenticator.ts b/src/services/Authenticator.ts new file mode 100644 index 0000000..d21c80d --- /dev/null +++ b/src/services/Authenticator.ts @@ -0,0 +1,32 @@ +import * as jwt from "jsonwebtoken"; + +export class Authenticator { + public generateToken(input: AuthenticationData, + expiresIn: string = process.env.ACCESS_TOKEN_EXPIRES_IN!): string { + const token = jwt.sign( + { + id: input.id, + role: input.role + }, + process.env.JWT_KEY as string, + { + expiresIn, + } + ); + return token; + } + + public getData(token: string): AuthenticationData { + const payload = jwt.verify(token, process.env.JWT_KEY as string) as any; + const result = { + id: payload.id, + role: payload.role + }; + return result; + } +} + +interface AuthenticationData { + id: string; + role?: string; +} \ No newline at end of file diff --git a/src/services/HashManager.ts b/src/services/HashManager.ts new file mode 100644 index 0000000..45704fb --- /dev/null +++ b/src/services/HashManager.ts @@ -0,0 +1,17 @@ +import * as bcrypt from "bcryptjs"; + + +export class HashManager { + + public async hash(text: string): Promise { + const rounds = 12; + const salt = await bcrypt.genSalt(rounds); + const result = await bcrypt.hash(text, salt); + return result; + } + + public async compare(text: string, hash: string): Promise{ + return await bcrypt.compare(text, hash); + } + +} \ No newline at end of file diff --git a/src/services/IdGenerator.ts b/src/services/IdGenerator.ts new file mode 100644 index 0000000..8dc2b8a --- /dev/null +++ b/src/services/IdGenerator.ts @@ -0,0 +1,8 @@ +import { v4 } from "uuid"; + +export class IdGenerator{ + + generate(): string{ + return v4(); + } +} \ No newline at end of file diff --git a/tables.sql b/tables.sql new file mode 100644 index 0000000..e5ced5e --- /dev/null +++ b/tables.sql @@ -0,0 +1,36 @@ +-- Active: 1676582098331@@35.226.146.116@3306@jbl-4416547-ricardo-morais + +### Query que cria a tabela de Bandas +CREATE TABLE IF NOT EXISTS Bands_Name ( + id VARCHAR(255) PRIMARY KEY, + name VARCHAR(255) UNIQUE NOT NULL, + music_genre VARCHAR(255) NOT NULL, + responsible VARCHAR(255) UNIQUE NOT NULL +); + +### Query que cria a tabela de Shows +CREATE TABLE IF NOT EXISTS Table_Shows ( + id VARCHAR(255) PRIMARY KEY, + week_day VARCHAR(255) NOT NULL, + start_time INT NOT NULL, + end_time INT NOT NULL, + band_id VARCHAR(255) NOT NULL, + FOREIGN KEY(band_id) REFERENCES Bands_Name(id) +); + +### Query que cria tabela de usuários +CREATE TABLE IF NOT EXISTS Lama_Users ( + id VARCHAR(255) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + role VARCHAR(255) NOT NULL DEFAULT "NORMAL" +); + +### + +DROP TABLE `NOME_TABELA_BANDAS`, `NOME_TABELA_SHOWS`; + +### + +SELECT * FROM `Lama_Users`; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..38600d2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, + "outDir": "./build" /* Redirect output structure to the directory. */, + "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, + "strict": true /* Enable all strict type-checking options. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } + } \ No newline at end of file From b0c0bf3b61c97e2822f0a08d161c8d8824948862 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Sat, 11 Mar 2023 11:43:13 +0000 Subject: [PATCH 02/32] Pt3 inicio --- package-lock.json | 14 +++++++++ package.json | 1 + requests.rest | 9 ++++++ src/business/BandRegisterBusiness.ts | 38 ++++++++++++++++++++++++ src/controller/BandRegisterController.ts | 31 +++++++++++++++++++ src/data/BandResisterDataBase.ts | 23 ++++++++++++++ src/model/BandRegisterDTO.ts | 19 ++++++++++++ src/routes/userRouter.ts | 5 +++- tables.sql | 2 ++ 9 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/business/BandRegisterBusiness.ts create mode 100644 src/controller/BandRegisterController.ts create mode 100644 src/data/BandResisterDataBase.ts create mode 100644 src/model/BandRegisterDTO.ts diff --git a/package-lock.json b/package-lock.json index 5b240e3..a9eff50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@types/jsonwebtoken": "^9.0.1", "@types/uuid": "^9.0.1", "bcryptjs": "^2.4.3", + "custom-error": "^0.2.1", "dotenv": "^16.0.3", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", @@ -454,6 +455,14 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, + "node_modules/custom-error": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/custom-error/-/custom-error-0.2.1.tgz", + "integrity": "sha512-J+QO3e3Z0YpEaz04gNrPQMszcnkZeiS0l4Gj0OgBGzBVVOijE59rjiVFBpo/vSNM4/2TDCCZZ+WWlt1k8m33mQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2062,6 +2071,11 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, + "custom-error": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/custom-error/-/custom-error-0.2.1.tgz", + "integrity": "sha512-J+QO3e3Z0YpEaz04gNrPQMszcnkZeiS0l4Gj0OgBGzBVVOijE59rjiVFBpo/vSNM4/2TDCCZZ+WWlt1k8m33mQ==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", diff --git a/package.json b/package.json index ca3b251..933cffa 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@types/jsonwebtoken": "^9.0.1", "@types/uuid": "^9.0.1", "bcryptjs": "^2.4.3", + "custom-error": "^0.2.1", "dotenv": "^16.0.3", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", diff --git a/requests.rest b/requests.rest index 5529b21..9998dee 100644 --- a/requests.rest +++ b/requests.rest @@ -8,4 +8,13 @@ Content-Type: application/json "name": "Ricardo Barros", "password": "102030", "role": "ADMIN" +} +### +POST http://localhost:3000/user/createBandRegister +{ + + "name": "Mauricio", + "music_genre":"ForMetal", + "responsible": "Bon Jovi", + "role": "ADMIN" } \ No newline at end of file diff --git a/src/business/BandRegisterBusiness.ts b/src/business/BandRegisterBusiness.ts new file mode 100644 index 0000000..54f53a7 --- /dev/null +++ b/src/business/BandRegisterBusiness.ts @@ -0,0 +1,38 @@ +import { BandRegisterDataBase } from "../data/BandResisterDataBase"; +import { CustomError } from "../error/BaseError"; +import { BandUpdateDTO } from "../model/BandRegisterDTO"; +import { Authenticator } from "../services/Authenticator"; +import { HashManager } from "../services/HashManager"; +import { IdGenerator } from "../services/IdGenerator"; + +const authenticator = new Authenticator() +const hashManager = new HashManager() +const idGenerator = new IdGenerator() +export class BandRegisterBusiness { + static createBand(create: { idBand: string; bandName: string; musicGenre: string; responsibleBand: string; roleAdm: import("../model/User").UserRole; }) { + throw new Error("Method not implemented."); + } + createBand = async (input: BandUpdateDTO) => { + try { + const {id,name,music_genre,responsible,role} = input + + if (!name ||!music_genre ||!responsible ||!role) { + throw new Error('name, music_genre, responsible, role is required'); + + + } + const idRegisterBand = authenticator.generateToken(id) + const idRegister = idGenerator.generate() + await BandRegisterDataBase.create({ + id: idRegisterBand, + name: name, + music_genre: music_genre, + responsible: responsible, + role: role + + }) + } catch (error:any) { + throw new CustomError(400,error.message); + } +} +} diff --git a/src/controller/BandRegisterController.ts b/src/controller/BandRegisterController.ts new file mode 100644 index 0000000..58074f5 --- /dev/null +++ b/src/controller/BandRegisterController.ts @@ -0,0 +1,31 @@ +import { Request,Response, request } from "express" +import { UserRole } from "../model/User" +import { BandRegisterBusiness } from "../business/BandRegisterBusiness" +export class BandRegisterController { + createBandRegister = async (req: Request, res: Response) =>{ + try{ + const idBand = req.headers.authorization as string + const bandName = req.body.name as string + const musicGenre = req.body.music_genre as string + const responsibleBand = req.body.responsible as string + const roleAdm = req.body.role as UserRole + + const create = { + idBand: idBand, + bandName: bandName, + musicGenre: musicGenre, + responsibleBand: responsibleBand, + roleAdm: roleAdm + } + await BandRegisterBusiness.createBand(create) + res.status(201).send({ + message: "Band Register created successfully" + }) + + } catch (error:any) { + res.status(400).send(error.message); + } + + +} +} \ No newline at end of file diff --git a/src/data/BandResisterDataBase.ts b/src/data/BandResisterDataBase.ts new file mode 100644 index 0000000..50a6798 --- /dev/null +++ b/src/data/BandResisterDataBase.ts @@ -0,0 +1,23 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { BandRegisterDTO } from "../model/BandRegisterDTO"; +import { CustomError } from "../error/BaseError"; +export class BandRegisterDataBase extends BaseDatabase { + private static TABLE_NAME : string = "Bands_Name" + + create = async ({id, name, music_genre,responsible,role }: BandRegisterDTO) => { + try{ + await BandRegisterDataBase.connection.insert ({ + id, + name, + music_genre, + responsible, + role + + }).into(BandRegisterDataBase.TABLE_NAME) + } catch (error:any) { + throw new CustomError(400, onmessage || error.sqlMessage) + } + + } + static create: any; +} \ No newline at end of file diff --git a/src/model/BandRegisterDTO.ts b/src/model/BandRegisterDTO.ts new file mode 100644 index 0000000..ab364be --- /dev/null +++ b/src/model/BandRegisterDTO.ts @@ -0,0 +1,19 @@ +import { UserRole } from "./User" + +export interface BandRegisterDTO { +id: string, +name:string, +music_genre: string +responsible: string, +role: UserRole.ADMIN + +}; + + +export interface BandUpdateDTO { + id:any, + name: string, + music_genre:string, + responsible: string, + role: UserRole.ADMIN +} \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index 1b56d3a..34cc9a9 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -1,10 +1,13 @@ import express from "express"; import { UserController } from "../controller/UserController"; +import { BandRegisterController } from "../controller/BandRegisterController"; export const userRouter = express.Router(); const userController = new UserController(); +const bandRegisterController = new BandRegisterController(); userRouter.post("/signup", userController.signup); -userRouter.post("/login", userController.login); \ No newline at end of file +userRouter.post("/login", userController.login); +userRouter.post("/createBandRegister",bandRegisterController ); \ No newline at end of file diff --git a/tables.sql b/tables.sql index e5ced5e..0674b19 100644 --- a/tables.sql +++ b/tables.sql @@ -6,6 +6,8 @@ CREATE TABLE IF NOT EXISTS Bands_Name ( name VARCHAR(255) UNIQUE NOT NULL, music_genre VARCHAR(255) NOT NULL, responsible VARCHAR(255) UNIQUE NOT NULL + role VARCHAR(255) NOT NULL DEFAULT "ADMIN" + ); ### Query que cria a tabela de Shows From 52a5524d1050623066bf9534cad694532ef5d18d Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Sat, 11 Mar 2023 16:50:20 -0300 Subject: [PATCH 03/32] Error --- src/controller/BandRController.ts | 32 ++++++++++++++++++++++++ src/controller/BandRegisterController.ts | 31 ----------------------- src/routes/userRouter.ts | 6 ++--- 3 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 src/controller/BandRController.ts delete mode 100644 src/controller/BandRegisterController.ts diff --git a/src/controller/BandRController.ts b/src/controller/BandRController.ts new file mode 100644 index 0000000..a33a93c --- /dev/null +++ b/src/controller/BandRController.ts @@ -0,0 +1,32 @@ +import { Request,Response } from "express" +import { UserRole } from "../model/User" +import { BandRegisterBusiness } from "../business/BandRegisterBusiness" + +const bandRegisterBusiness = new BandRegisterBusiness + +export class BandRController { + + createBand = async (req:Request,res:Response) =>{ + try { + const id = req.headers.authorization as any + const name = req.body.name as string + const music_genre = req.body.music_genre as string + const responsible = req.body.responsible as string + const role = req.body.role as UserRole.ADMIN + + const create = { + id: id, + name: name, + music_genre: music_genre, + responsible: responsible, + role: role + } + await bandRegisterBusiness.createBand(create) +res.status(201).send({message: "New Band on tour"}) + } catch (error:any){ + res.status(400).send(error.message) + } + + + } +} \ No newline at end of file diff --git a/src/controller/BandRegisterController.ts b/src/controller/BandRegisterController.ts deleted file mode 100644 index 58074f5..0000000 --- a/src/controller/BandRegisterController.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Request,Response, request } from "express" -import { UserRole } from "../model/User" -import { BandRegisterBusiness } from "../business/BandRegisterBusiness" -export class BandRegisterController { - createBandRegister = async (req: Request, res: Response) =>{ - try{ - const idBand = req.headers.authorization as string - const bandName = req.body.name as string - const musicGenre = req.body.music_genre as string - const responsibleBand = req.body.responsible as string - const roleAdm = req.body.role as UserRole - - const create = { - idBand: idBand, - bandName: bandName, - musicGenre: musicGenre, - responsibleBand: responsibleBand, - roleAdm: roleAdm - } - await BandRegisterBusiness.createBand(create) - res.status(201).send({ - message: "Band Register created successfully" - }) - - } catch (error:any) { - res.status(400).send(error.message); - } - - -} -} \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index 34cc9a9..fd9fa8e 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -1,13 +1,13 @@ import express from "express"; import { UserController } from "../controller/UserController"; -import { BandRegisterController } from "../controller/BandRegisterController"; +import { BandRController } from "../controller/BandRController"; export const userRouter = express.Router(); const userController = new UserController(); -const bandRegisterController = new BandRegisterController(); +const bandRController = new BandRController(); userRouter.post("/signup", userController.signup); userRouter.post("/login", userController.login); -userRouter.post("/createBandRegister",bandRegisterController ); \ No newline at end of file +userRouter.post("/createBandRegister",bandRController ); \ No newline at end of file From f8c9fc791df68953bd68ef24fa80da0380d3b002 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Sat, 11 Mar 2023 16:58:17 -0300 Subject: [PATCH 04/32] Testar endpoints --- src/routes/userRouter.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index fd9fa8e..4c00a80 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -1,6 +1,7 @@ -import express from "express"; +import { Request,Response} from "express"; import { UserController } from "../controller/UserController"; import { BandRController } from "../controller/BandRController"; +import express from "express" export const userRouter = express.Router(); @@ -10,4 +11,4 @@ const bandRController = new BandRController(); userRouter.post("/signup", userController.signup); userRouter.post("/login", userController.login); -userRouter.post("/createBandRegister",bandRController ); \ No newline at end of file +userRouter.post("/createBandRegister", bandRController.createBand); \ No newline at end of file From b94bcd4c5a95eb1efca1571776f212d2762e1931 Mon Sep 17 00:00:00 2001 From: Ricardo_Barros Date: Sat, 11 Mar 2023 22:10:32 -0300 Subject: [PATCH 05/32] Corrigindo erros! --- package-lock.json | 18 ++++++++++++++++++ package.json | 1 + requests.rest | 19 ++++++++++++++++--- src/data/BaseDatabase.ts | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a9eff50..6687a64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@types/bcryptjs": "^2.4.2", + "@types/dotenv": "^8.2.0", "@types/jsonwebtoken": "^9.0.1", "@types/uuid": "^9.0.1", "bcryptjs": "^2.4.3", @@ -115,6 +116,15 @@ "@types/node": "*" } }, + "node_modules/@types/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", + "deprecated": "This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed.", + "dependencies": { + "dotenv": "*" + } + }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -1792,6 +1802,14 @@ "@types/node": "*" } }, + "@types/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", + "requires": { + "dotenv": "*" + } + }, "@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", diff --git a/package.json b/package.json index 933cffa..c12240d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "license": "ISC", "dependencies": { "@types/bcryptjs": "^2.4.2", + "@types/dotenv": "^8.2.0", "@types/jsonwebtoken": "^9.0.1", "@types/uuid": "^9.0.1", "bcryptjs": "^2.4.3", diff --git a/requests.rest b/requests.rest index 9998dee..5e8bdf3 100644 --- a/requests.rest +++ b/requests.rest @@ -4,13 +4,26 @@ POST http://localhost:3000/user/signup Content-Type: application/json { - "email": "exemplo-ricardo2@lbn.com", - "name": "Ricardo Barros", - "password": "102030", + "email": "exemplo-mauricio@lbn.com", + "name": "Mauricio", + "password": "123456", "role": "ADMIN" } + +### Login + +POST http://localhost:3000/user/login +Content-Type: application/json + +{ + "email": "exemplo-mauricio@lbn.com", + "password": "123456" +} + ### POST http://localhost:3000/user/createBandRegister +Content-Type: application/json + { "name": "Mauricio", diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts index 84ca189..023b2be 100644 --- a/src/data/BaseDatabase.ts +++ b/src/data/BaseDatabase.ts @@ -14,7 +14,7 @@ export class BaseDatabase { database: process.env.DB_SCHEMA, port: 3306, multipleStatements: true - } + } }) } \ No newline at end of file From d39d15caef0359cfa7e3b448b7a709191cddb473 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Sun, 12 Mar 2023 11:45:26 +0000 Subject: [PATCH 06/32] Refatorando --- requests.rest | 4 +- src/business/BandCreateBusiness.ts | 51 ++++++++++++ src/business/BandRegisterBusiness.ts | 38 --------- src/business/UserBusiness.ts | 103 ++++++++++++++++++------- src/controller/BandCreateController.ts | 25 ++++++ src/controller/BandRController.ts | 32 -------- src/controller/UserController.ts | 33 ++++---- src/data/BandCreateDataBase.ts | 25 ++++++ src/data/BandResisterDataBase.ts | 23 ------ src/data/UserDatabase.ts | 55 +++++-------- src/error/BandErrors.ts | 28 +++++++ src/error/UserErros.ts | 68 ++++++++++++++++ src/index.ts | 2 + src/model/AuthenticatorData.ts | 6 ++ src/model/BandCreateDTO.ts | 20 +++++ src/model/BandRegisterDTO.ts | 19 ----- src/model/BandRepository.ts | 6 ++ src/model/GeneratorId.ts | 3 + src/model/HashGenerator.ts | 4 + src/model/IdAuthenticator.ts | 7 ++ src/model/UidGenarator.ts | 3 + src/model/User.ts | 101 ++++++------------------ src/model/UserRepository.ts | 7 ++ src/routes/bandRouter.ts | 15 ++++ src/routes/userRouter.ts | 23 +++--- src/services/Authenticator.ts | 52 ++++++------- src/services/HashManager.ts | 23 +++--- src/services/IdGenerator.ts | 11 +-- 28 files changed, 463 insertions(+), 324 deletions(-) create mode 100644 src/business/BandCreateBusiness.ts delete mode 100644 src/business/BandRegisterBusiness.ts create mode 100644 src/controller/BandCreateController.ts delete mode 100644 src/controller/BandRController.ts create mode 100644 src/data/BandCreateDataBase.ts delete mode 100644 src/data/BandResisterDataBase.ts create mode 100644 src/error/BandErrors.ts create mode 100644 src/error/UserErros.ts create mode 100644 src/model/AuthenticatorData.ts create mode 100644 src/model/BandCreateDTO.ts delete mode 100644 src/model/BandRegisterDTO.ts create mode 100644 src/model/BandRepository.ts create mode 100644 src/model/GeneratorId.ts create mode 100644 src/model/HashGenerator.ts create mode 100644 src/model/IdAuthenticator.ts create mode 100644 src/model/UidGenarator.ts create mode 100644 src/model/UserRepository.ts create mode 100644 src/routes/bandRouter.ts diff --git a/requests.rest b/requests.rest index 9998dee..e4b9bec 100644 --- a/requests.rest +++ b/requests.rest @@ -1,6 +1,6 @@ ### Criar Usuário -POST http://localhost:3000/user/signup +POST POST http://localhost:3003/users/signup Content-Type: application/json { @@ -10,7 +10,7 @@ Content-Type: application/json "role": "ADMIN" } ### -POST http://localhost:3000/user/createBandRegister +POST http://localhost:3003/create { "name": "Mauricio", diff --git a/src/business/BandCreateBusiness.ts b/src/business/BandCreateBusiness.ts new file mode 100644 index 0000000..fd5c894 --- /dev/null +++ b/src/business/BandCreateBusiness.ts @@ -0,0 +1,51 @@ + +import { DuplicateBandName, BandName, MusicGenre, Responsible } from "../error/BandErrors" +import { CustomError } from "../error/BaseError" +import { MissingToken, Unauthorized } from "../error/BaseError" +import { BandCreateDTO, inputCreateBandDTO } from "../model/BandCreateDTO" +import { BandRepository } from "../model/BandRepository" +import { IdAuthenticator } from "../model/IdAuthenticator" +import { GeneratorId } from "../model/GeneratorId" +import { UserRole } from "../model/User" +export class BandCreateBusiness { + constructor ( + private bandDatabase: BandRepository, + private authorization: IdAuthenticator, + private idGenerator: GeneratorId + ) {} + + async createBand (input: inputCreateBandDTO): Promise { + try { + if (!input.name) { + throw new BandName() + } + if (!input.musicGenre) { + throw new MusicGenre() + } + if (!input.responsible) { + throw new Responsible() + } + if (!input.token) { + throw new MissingToken() + } + + const duplicateName = await this.bandDatabase.getBandBy("name", input.name) + if (duplicateName) { + throw new DuplicateBandName() + } + + const {id, role} = this.authorization.getTokenData(input.token) + if (role.toUpperCase() !== UserRole.ADMIN) { + throw new Unauthorized() + } + + const bandId = this.idGenerator.generateId() + const newBand = new BandCreateDTO(bandId, input.name, input.musicGenre, input.responsible) + + await this.bandDatabase.createBand(newBand) + + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } +} \ No newline at end of file diff --git a/src/business/BandRegisterBusiness.ts b/src/business/BandRegisterBusiness.ts deleted file mode 100644 index 54f53a7..0000000 --- a/src/business/BandRegisterBusiness.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { BandRegisterDataBase } from "../data/BandResisterDataBase"; -import { CustomError } from "../error/BaseError"; -import { BandUpdateDTO } from "../model/BandRegisterDTO"; -import { Authenticator } from "../services/Authenticator"; -import { HashManager } from "../services/HashManager"; -import { IdGenerator } from "../services/IdGenerator"; - -const authenticator = new Authenticator() -const hashManager = new HashManager() -const idGenerator = new IdGenerator() -export class BandRegisterBusiness { - static createBand(create: { idBand: string; bandName: string; musicGenre: string; responsibleBand: string; roleAdm: import("../model/User").UserRole; }) { - throw new Error("Method not implemented."); - } - createBand = async (input: BandUpdateDTO) => { - try { - const {id,name,music_genre,responsible,role} = input - - if (!name ||!music_genre ||!responsible ||!role) { - throw new Error('name, music_genre, responsible, role is required'); - - - } - const idRegisterBand = authenticator.generateToken(id) - const idRegister = idGenerator.generate() - await BandRegisterDataBase.create({ - id: idRegisterBand, - name: name, - music_genre: music_genre, - responsible: responsible, - role: role - - }) - } catch (error:any) { - throw new CustomError(400,error.message); - } -} -} diff --git a/src/business/UserBusiness.ts b/src/business/UserBusiness.ts index b645a82..602d253 100644 --- a/src/business/UserBusiness.ts +++ b/src/business/UserBusiness.ts @@ -1,43 +1,90 @@ -import { UserInputDTO, LoginInputDTO } from "../model/User"; -import { UserDatabase } from "../data/UserDatabase"; -import { IdGenerator } from "../services/IdGenerator"; -import { HashManager } from "../services/HashManager"; -import { Authenticator } from "../services/Authenticator"; +import { CustomError } from "../error/BaseError" +import { DuplicateEmail, EmailNotFound, IncorrectPassword, InvalidEmail, InvalidPassword, MissingEmail, MissingPassword, MissingUserName, MissingUserRole } from "../error/UserErros" +import { IdAuthenticator } from "../model/IdAuthenticator" +import { HashGenarator } from "../model/HashGenerator" +import { UidGenarator } from "../model/UidGenarator" +import { inputSignUpDTO, loginInputDTO, User, UserRole } from "../model/User" +import { UserRepository } from "../model/UserRepository" -export class UserBusiness { - - async createUser(user: UserInputDTO) { - const idGenerator = new IdGenerator(); - const id = idGenerator.generate(); +export class UserBusiness { + constructor ( + private userDatabase : UserRepository, + private idGenerator: UidGenarator, + private hashManager: HashGenarator, + private authenticator: IdAuthenticator + ) {} - const hashManager = new HashManager(); - const hashPassword = await hashManager.hash(user.password); + async signup (input: inputSignUpDTO): Promise { + try { + if (!input.name) { + throw new MissingUserName() + } + if (!input.email) { + throw new MissingEmail() + } + if (!input.password) { + throw new MissingPassword() + } + if (!input.role) { + throw new MissingUserRole() + } + if (input.password.length < 8) { + throw new InvalidPassword() + } + if (!input.email.includes("@")) { + throw new InvalidEmail() + } - const userDatabase = new UserDatabase(); - await userDatabase.createUser(id, user.email, user.name, hashPassword, user.role); + const isEmailDuplicate = await this.userDatabase.getUser("email", input.email) + if (isEmailDuplicate) { + throw new DuplicateEmail() + } + + let role + input.role.toUpperCase() === UserRole.ADMIN ? role = UserRole.ADMIN : role = UserRole.NORMAL + + const id = this.idGenerator.generateId() + const hashPassword = await this.hashManager.generateHash(input.password) - const authenticator = new Authenticator(); - const accessToken = authenticator.generateToken({ id, role: user.role }); + const newUser = new User(id, input.name, input.email, hashPassword, role) + await this.userDatabase.signup(newUser) + + return this.authenticator.generateToken({id, role}) - return accessToken; + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } } - async getUserByEmail(user: LoginInputDTO) { - const userDatabase = new UserDatabase(); - const userFromDB = await userDatabase.getUserByEmail(user.email); + async login (input: loginInputDTO): Promise { + try { + if (!input.email) { + throw new MissingEmail() + } + if (!input.password) { + throw new MissingPassword() + } + if (!input.email.includes("@")) { + throw new InvalidEmail() + } - const hashManager = new HashManager(); - const hashCompare = await hashManager.compare(user.password, userFromDB.getPassword()); + const emailExists = await this.userDatabase.getUser("email", input.email) + if (!emailExists) { + throw new EmailNotFound() + } - const authenticator = new Authenticator(); - const accessToken = authenticator.generateToken({ id: userFromDB.getId(), role: userFromDB.getRole() }); + const compareHash = await this.hashManager.compareHash(input.password, emailExists.password) + if (!compareHash) { + throw new IncorrectPassword() + } - if (!hashCompare) { - throw new Error("Invalid Password!"); - } + const token = this.authenticator.generateToken({ id: emailExists.id, role: emailExists.role}) + return token - return accessToken; + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } } } \ No newline at end of file diff --git a/src/controller/BandCreateController.ts b/src/controller/BandCreateController.ts new file mode 100644 index 0000000..2563e05 --- /dev/null +++ b/src/controller/BandCreateController.ts @@ -0,0 +1,25 @@ +import { Request,Response } from "express" +import { inputCreateBandDTO } from "../model/BandCreateDTO" +import { BandCreateBusiness } from "../business/BandCreateBusiness" + +export class BandCreateController { + constructor (private bandBusiness: BandCreateBusiness) {} + + async createBand (req: Request, res: Response): Promise { + try { + const input: inputCreateBandDTO = { + name: req.body.name, + musicGenre: req.body.musicGenre, + responsible: req.body.responsible, + token: req.headers.authorization as string + } + + await this.bandBusiness.createBand(input) + + res.status(201).send("Band created successfully!") + + } catch (error: any) { + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } + } +} diff --git a/src/controller/BandRController.ts b/src/controller/BandRController.ts deleted file mode 100644 index a33a93c..0000000 --- a/src/controller/BandRController.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Request,Response } from "express" -import { UserRole } from "../model/User" -import { BandRegisterBusiness } from "../business/BandRegisterBusiness" - -const bandRegisterBusiness = new BandRegisterBusiness - -export class BandRController { - - createBand = async (req:Request,res:Response) =>{ - try { - const id = req.headers.authorization as any - const name = req.body.name as string - const music_genre = req.body.music_genre as string - const responsible = req.body.responsible as string - const role = req.body.role as UserRole.ADMIN - - const create = { - id: id, - name: name, - music_genre: music_genre, - responsible: responsible, - role: role - } - await bandRegisterBusiness.createBand(create) -res.status(201).send({message: "New Band on tour"}) - } catch (error:any){ - res.status(400).send(error.message) - } - - - } -} \ No newline at end of file diff --git a/src/controller/UserController.ts b/src/controller/UserController.ts index be56c08..954ae7b 100644 --- a/src/controller/UserController.ts +++ b/src/controller/UserController.ts @@ -1,48 +1,43 @@ import { Request, Response } from "express" -import { UserInputDTO, LoginInputDTO} from "../model/User" import { UserBusiness } from "../business/UserBusiness" +import { inputSignUpDTO, loginInputDTO } from "../model/User" export class UserController { - async signup(req: Request, res: Response) { - try { + constructor (private userBusiness: UserBusiness) {} - const input: UserInputDTO = { + async signup (req: Request, res: Response): Promise { + try { + const input: inputSignUpDTO = { email: req.body.email, name: req.body.name, password: req.body.password, role: req.body.role } - const userBusiness = new UserBusiness(); - const token = await userBusiness.createUser(input); + const token = await this.userBusiness.signup(input) - res.status(200).send({ token }); + res.status(201).send({message: "User created successfully", token}) } catch (error: any) { - res.status(400).send({ error: error.message }); + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) } - } - async login(req: Request, res: Response) { + async login (req: Request, res: Response): Promise { try { - - const loginData: LoginInputDTO = { + const input: loginInputDTO = { email: req.body.email, password: req.body.password - }; - - const userBusiness = new UserBusiness(); - const token = await userBusiness.getUserByEmail(loginData); + } - res.status(200).send({ token }); + const token = await this.userBusiness.login(input) + res.status(200).send({ token }) } catch (error: any) { - res.status(400).send({ error: error.message }); + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) } - } } \ No newline at end of file diff --git a/src/data/BandCreateDataBase.ts b/src/data/BandCreateDataBase.ts new file mode 100644 index 0000000..a0136d0 --- /dev/null +++ b/src/data/BandCreateDataBase.ts @@ -0,0 +1,25 @@ +import { BaseDatabase } from "./BaseDatabase"; +import { BandCreateDTO } from "../model/BandCreateDTO"; +import { CustomError } from "../error/BaseError"; +import { BandRepository } from "../model/BandRepository"; +export class BandCreateDatabase extends BaseDatabase implements BandRepository { + private TABLE_NAME = "Bands_Name" + + async createBand (newBand: BandCreateDTO): Promise { + try { + await BaseDatabase.connection(this.TABLE_NAME).insert(newBand) + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } + + + async getBandBy (column: string, value: string): Promise { + try { + const result = await BaseDatabase.connection(this.TABLE_NAME).select().where(column, value) + return result[0] + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } +} \ No newline at end of file diff --git a/src/data/BandResisterDataBase.ts b/src/data/BandResisterDataBase.ts deleted file mode 100644 index 50a6798..0000000 --- a/src/data/BandResisterDataBase.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { BaseDatabase } from "./BaseDatabase"; -import { BandRegisterDTO } from "../model/BandRegisterDTO"; -import { CustomError } from "../error/BaseError"; -export class BandRegisterDataBase extends BaseDatabase { - private static TABLE_NAME : string = "Bands_Name" - - create = async ({id, name, music_genre,responsible,role }: BandRegisterDTO) => { - try{ - await BandRegisterDataBase.connection.insert ({ - id, - name, - music_genre, - responsible, - role - - }).into(BandRegisterDataBase.TABLE_NAME) - } catch (error:any) { - throw new CustomError(400, onmessage || error.sqlMessage) - } - - } - static create: any; -} \ No newline at end of file diff --git a/src/data/UserDatabase.ts b/src/data/UserDatabase.ts index 66a883a..42891ab 100644 --- a/src/data/UserDatabase.ts +++ b/src/data/UserDatabase.ts @@ -1,39 +1,26 @@ -import { BaseDatabase } from "./BaseDatabase"; -import { User } from "../model/User"; +import { CustomError } from "../error/BaseError" +import { User } from "../model/User" +import { UserRepository } from "../model/UserRepository" +import { BaseDatabase } from "./BaseDatabase" -export class UserDatabase extends BaseDatabase { - private static TABLE_NAME = "Lama_Users"; - - public async createUser( - id: string, - email: string, - name: string, - password: string, - role: string - ): Promise { - try { - await BaseDatabase.connection - .insert({ - id, - email, - name, - password, - role - }) - .into(UserDatabase.TABLE_NAME); - } catch (error: any) { - throw new Error(error.sqlMessage || error.message); - } +export class UserDatabase extends BaseDatabase implements UserRepository { + private TABLE_NAME = "Lama_Users" + + async signup (newUser: User): Promise { + try { + await BaseDatabase.connection(this.TABLE_NAME).insert(newUser) + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } } - public async getUserByEmail(email: string): Promise { - const result = await BaseDatabase.connection - .select("*") - .from(UserDatabase.TABLE_NAME) - .where({ email }); - - return User.toUserModel(result[0]); + async getUser (column: string, value: string): Promise { + try { + const result = await BaseDatabase.connection(this.TABLE_NAME).select().where(column, value) + return result[0] + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } } - -} +} \ No newline at end of file diff --git a/src/error/BandErrors.ts b/src/error/BandErrors.ts new file mode 100644 index 0000000..9ab1dac --- /dev/null +++ b/src/error/BandErrors.ts @@ -0,0 +1,28 @@ +import { CustomError } from "./BaseError" + + +export class BandName extends CustomError { + constructor () { + super (422, "Provide the band name.") + } +} + +export class DuplicateBandName extends CustomError { + constructor () { + super (409, "Band name already registered.") + } +} + +export class MusicGenre extends CustomError { + constructor () { + super (422, "Provide the music genre.") + } +} + +export class Responsible extends CustomError { + constructor () { + super (422, "Provide the name of the responsible for the band.") + } +} + +export { CustomError } diff --git a/src/error/UserErros.ts b/src/error/UserErros.ts new file mode 100644 index 0000000..d819113 --- /dev/null +++ b/src/error/UserErros.ts @@ -0,0 +1,68 @@ +import { CustomError } from "./BandErrors" + + +export class Unauthorized extends CustomError { + constructor () { + super (401, "Unauthorized user.") + } +} + +export class MissingToken extends CustomError { + constructor () { + super (422, "Provide the token.") + } +} + +export class MissingUserName extends CustomError { + constructor () { + super (422, "Provide the user name.") + } +} + +export class MissingEmail extends CustomError { + constructor () { + super (422, "Provide the email address.") + } +} + +export class InvalidEmail extends CustomError { + constructor () { + super (422, "Invalid email address.") + } +} + +export class EmailNotFound extends CustomError { + constructor () { + super (404, "Email address not found.") + } +} + +export class DuplicateEmail extends CustomError { + constructor () { + super (409, "Email already in use.") + } +} + +export class MissingPassword extends CustomError { + constructor () { + super (422, "Provide the password.") + } +} + +export class InvalidPassword extends CustomError { + constructor () { + super (422, "The password must have at least 8 characters.") + } +} + +export class IncorrectPassword extends CustomError { + constructor () { + super (422, "Incorrect password.") + } +} + +export class MissingUserRole extends CustomError { + constructor () { + super (422, "Provide the user role.") + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 3d82c68..e5ce406 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,12 +2,14 @@ import dotenv from "dotenv"; import {AddressInfo} from "net"; import express from "express"; import { userRouter } from "./routes/userRouter"; +import { bandRouter } from "./routes/bandRouter"; dotenv.config(); const app = express(); app.use(express.json()); app.use("/user", userRouter); +app.use("/bands", bandRouter) const server = app.listen(3000, () => { if (server) { diff --git a/src/model/AuthenticatorData.ts b/src/model/AuthenticatorData.ts new file mode 100644 index 0000000..c60be64 --- /dev/null +++ b/src/model/AuthenticatorData.ts @@ -0,0 +1,6 @@ +import { UserRole } from "./User" + +export interface AuthenticationData { + id: string, + role: UserRole +} \ No newline at end of file diff --git a/src/model/BandCreateDTO.ts b/src/model/BandCreateDTO.ts new file mode 100644 index 0000000..58307ec --- /dev/null +++ b/src/model/BandCreateDTO.ts @@ -0,0 +1,20 @@ +export class BandCreateDTO { + constructor ( + public readonly id: string, + public readonly name: string, + public readonly music_genre: string, + public readonly responsible: string + ) { + this.id = id + this.name = name + this.music_genre = music_genre + this.responsible = responsible + } +} + +export interface inputCreateBandDTO { + name: string, + musicGenre: string, + responsible: string, + token: string +} \ No newline at end of file diff --git a/src/model/BandRegisterDTO.ts b/src/model/BandRegisterDTO.ts deleted file mode 100644 index ab364be..0000000 --- a/src/model/BandRegisterDTO.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { UserRole } from "./User" - -export interface BandRegisterDTO { -id: string, -name:string, -music_genre: string -responsible: string, -role: UserRole.ADMIN - -}; - - -export interface BandUpdateDTO { - id:any, - name: string, - music_genre:string, - responsible: string, - role: UserRole.ADMIN -} \ No newline at end of file diff --git a/src/model/BandRepository.ts b/src/model/BandRepository.ts new file mode 100644 index 0000000..6fa1fe5 --- /dev/null +++ b/src/model/BandRepository.ts @@ -0,0 +1,6 @@ +import { BandCreateDTO } from "./BandCreateDTO"; + +export interface BandRepository { + createBand (newBand: BandCreateDTO): Promise + getBandBy (column: string, value: string): Promise +} \ No newline at end of file diff --git a/src/model/GeneratorId.ts b/src/model/GeneratorId.ts new file mode 100644 index 0000000..26a29f6 --- /dev/null +++ b/src/model/GeneratorId.ts @@ -0,0 +1,3 @@ +export interface GeneratorId { + generateId (): string +} \ No newline at end of file diff --git a/src/model/HashGenerator.ts b/src/model/HashGenerator.ts new file mode 100644 index 0000000..54d8d35 --- /dev/null +++ b/src/model/HashGenerator.ts @@ -0,0 +1,4 @@ +export interface HashGenarator { + generateHash (plaintext: string): Promise + compareHash (plaintex: string, hashtext: string): Promise +} \ No newline at end of file diff --git a/src/model/IdAuthenticator.ts b/src/model/IdAuthenticator.ts new file mode 100644 index 0000000..97a84fa --- /dev/null +++ b/src/model/IdAuthenticator.ts @@ -0,0 +1,7 @@ +import { AuthenticationData } from "./AuthenticatorData" + + +export interface IdAuthenticator { + generateToken ({id, role}: AuthenticationData): string + getTokenData (token: string): AuthenticationData +} \ No newline at end of file diff --git a/src/model/UidGenarator.ts b/src/model/UidGenarator.ts new file mode 100644 index 0000000..bc869ad --- /dev/null +++ b/src/model/UidGenarator.ts @@ -0,0 +1,3 @@ +export interface UidGenarator { + generateId (): string +} \ No newline at end of file diff --git a/src/model/User.ts b/src/model/User.ts index 9143a6a..723cf6f 100644 --- a/src/model/User.ts +++ b/src/model/User.ts @@ -1,83 +1,32 @@ -export class User{ - constructor( - private id: string, - private name: string, - private email: string, - private password: string, - private role: UserRole - ){} - - getId(){ - return this.id; - } - - getName(){ - return this.name - } - - getEmail(){ - return this.email; - } - - getPassword(){ - return this.password; - } - - getRole(){ - return this.role; - } - - setId(id: string){ - this.id = id; - } - - setName(name: string){ - this.name = name; - } - - setEmail(email: string){ - this.email = email; - } - - setPassword(password: string){ - this.password = password; - } - - setRole(role: UserRole){ - this.role = role; - } - - static stringToUserRole(input: string): UserRole{ - switch (input) { - case "NORMAL": - return UserRole.NORMAL; - case "ADMIN": - return UserRole.ADMIN; - default: - throw new Error("Invalid user role"); - } - } - - static toUserModel(user: any): User { - return new User(user.id, user.name, user.email, user.password, User.stringToUserRole(user.role)); - } - - +export enum UserRole { + ADMIN = "ADMIN", + NORMAL = "NORMAL" } -export interface UserInputDTO{ - email: string; - password: string; - name: string; - role: string; +export class User { + constructor ( + public readonly id: string, + public readonly name: string, + public readonly email: string, + public readonly password: string, + public readonly role: UserRole + ) { + this.id = id + this.name = name + this.email = email + this.password = password + this.role = role + } } -export interface LoginInputDTO{ - email: string; - password: string; +export interface inputSignUpDTO { + email: string, + password: string, + name: string, + role: string } -export enum UserRole{ - NORMAL = "NORMAL", - ADMIN = "ADMIN" +export interface loginInputDTO { + email: string, + password: string } \ No newline at end of file diff --git a/src/model/UserRepository.ts b/src/model/UserRepository.ts new file mode 100644 index 0000000..25095b8 --- /dev/null +++ b/src/model/UserRepository.ts @@ -0,0 +1,7 @@ +import { User } from "./User" + + +export interface UserRepository { + signup (newUser: User): Promise + getUser (column: string, value: string): Promise +} diff --git a/src/routes/bandRouter.ts b/src/routes/bandRouter.ts new file mode 100644 index 0000000..45b6b09 --- /dev/null +++ b/src/routes/bandRouter.ts @@ -0,0 +1,15 @@ +import express from "express" +import { BandCreateBusiness } from "../business/BandCreateBusiness" +import { BandCreateController } from "../controller/BandCreateController" +import { BandCreateDatabase } from "../data/BandCreateDataBase" +import { Authenticator } from "../services/Authenticator" +import { IdGenerator } from "../services/IdGenerator" + + +export const bandRouter = express.Router() + +const bandDatabase = new BandCreateDatabase() +const bandBusiness = new BandCreateBusiness(bandDatabase, new Authenticator(), new IdGenerator()) +const bandController = new BandCreateController(bandBusiness) + +bandRouter.post("/create", (req, res) => bandController.createBand(req, res)) \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index 4c00a80..e8be5dd 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -1,14 +1,17 @@ -import { Request,Response} from "express"; -import { UserController } from "../controller/UserController"; -import { BandRController } from "../controller/BandRController"; -import express from "express" +import express from "express" +import { UserBusiness } from "../business/UserBusiness" +import { UserController } from "../controller/UserController" +import { UserDatabase } from "../data/UserDatabase" +import { Authenticator } from "../services/Authenticator" +import { HashManager } from "../services/HashManager" +import { IdGenerator } from "../services/IdGenerator" -export const userRouter = express.Router(); +export const userRouter = express.Router() -const userController = new UserController(); -const bandRController = new BandRController(); +const userDatabase = new UserDatabase() +const userBusiness = new UserBusiness(userDatabase, new IdGenerator(), new HashManager(), new Authenticator()) +const userController = new UserController(userBusiness) -userRouter.post("/signup", userController.signup); -userRouter.post("/login", userController.login); -userRouter.post("/createBandRegister", bandRController.createBand); \ No newline at end of file +userRouter.post("/signup", (req, res) => userController.signup(req, res)) +userRouter.post("/login", (req, res) => userController.login(req, res)) \ No newline at end of file diff --git a/src/services/Authenticator.ts b/src/services/Authenticator.ts index d21c80d..cf4e9e5 100644 --- a/src/services/Authenticator.ts +++ b/src/services/Authenticator.ts @@ -1,32 +1,28 @@ -import * as jwt from "jsonwebtoken"; +import dotenv from "dotenv" +import * as jwt from "jsonwebtoken" +import { Unauthorized } from "../error/BaseError" +import { AuthenticationData } from "../model/AuthenticatorData" +import { IdAuthenticator } from "../model/IdAuthenticator" -export class Authenticator { - public generateToken(input: AuthenticationData, - expiresIn: string = process.env.ACCESS_TOKEN_EXPIRES_IN!): string { - const token = jwt.sign( - { - id: input.id, - role: input.role - }, - process.env.JWT_KEY as string, - { - expiresIn, - } - ); - return token; - } +dotenv.config() - public getData(token: string): AuthenticationData { - const payload = jwt.verify(token, process.env.JWT_KEY as string) as any; - const result = { - id: payload.id, - role: payload.role - }; - return result; - } -} +export class Authenticator implements IdAuthenticator { + public generateToken = ({id, role}: AuthenticationData): string => { + const token = jwt.sign( + {id, role}, + process.env.JWT_KEY as string, + {expiresIn: "1h"} + ) -interface AuthenticationData { - id: string; - role?: string; + return token + } + + public getTokenData = (token: string): AuthenticationData => { + try { + const payload = jwt.verify(token, process.env.JWT_KEY as string) as AuthenticationData + return {id: payload.id, role: payload.role} + } catch (err: any) { + throw new Unauthorized() + } + } } \ No newline at end of file diff --git a/src/services/HashManager.ts b/src/services/HashManager.ts index 45704fb..1b47c21 100644 --- a/src/services/HashManager.ts +++ b/src/services/HashManager.ts @@ -1,17 +1,20 @@ -import * as bcrypt from "bcryptjs"; +import * as bcrypt from "bcryptjs" +import dotenv from "dotenv" +import { HashGenarator } from "../model/HashGenerator" +dotenv.config() -export class HashManager { +export class HashManager implements HashGenarator { + generateHash = async (plaintext: string): Promise => { + const cost: number = Number(process.env.BCRYPT_COST) + const salt: string = await bcrypt.genSalt(cost) + const hash: string = await bcrypt.hash(plaintext, salt) - public async hash(text: string): Promise { - const rounds = 12; - const salt = await bcrypt.genSalt(rounds); - const result = await bcrypt.hash(text, salt); - return result; + return hash } - public async compare(text: string, hash: string): Promise{ - return await bcrypt.compare(text, hash); + compareHash = async (plaintex: string, hashtext: string): Promise => { + const result = await bcrypt.compare(plaintex, hashtext) + return result } - } \ No newline at end of file diff --git a/src/services/IdGenerator.ts b/src/services/IdGenerator.ts index 8dc2b8a..e42024a 100644 --- a/src/services/IdGenerator.ts +++ b/src/services/IdGenerator.ts @@ -1,8 +1,9 @@ -import { v4 } from "uuid"; +import { v4 } from "uuid" +import { GeneratorId } from "../model/GeneratorId" -export class IdGenerator{ - generate(): string{ - return v4(); +export class IdGenerator implements GeneratorId { + generateId (): string { + return v4() } -} \ No newline at end of file +} From 7027618c7d1f1aaa802d5062686731c26dafc482 Mon Sep 17 00:00:00 2001 From: Ricardo_Barros Date: Sun, 12 Mar 2023 22:58:02 -0300 Subject: [PATCH 07/32] feat: foram criados os tratamentos de erro dos endpoints 1 e 2 --- requests.rest | 18 +++++-- src/business/UserBusiness.ts | 88 +++++++++++++++++++++++++++-------- src/error/BaseError.ts | 6 +++ src/services/Authenticator.ts | 2 +- 4 files changed, 90 insertions(+), 24 deletions(-) diff --git a/requests.rest b/requests.rest index 9998dee..05e9ee1 100644 --- a/requests.rest +++ b/requests.rest @@ -4,12 +4,22 @@ POST http://localhost:3000/user/signup Content-Type: application/json { - "email": "exemplo-ricardo2@lbn.com", - "name": "Ricardo Barros", - "password": "102030", + "email": "exemplo-victor@lbn.com", + "name": "Victor", + "password": "010203", "role": "ADMIN" } -### + +### Login +POST http://localhost:3000/user/login +Content-Type: application/json + +{ + "email": "exemplo-victor@lbn.com", + "password": "010203" +} + +### Registrar uma Banda POST http://localhost:3000/user/createBandRegister { diff --git a/src/business/UserBusiness.ts b/src/business/UserBusiness.ts index b645a82..c673e38 100644 --- a/src/business/UserBusiness.ts +++ b/src/business/UserBusiness.ts @@ -3,41 +3,91 @@ import { UserDatabase } from "../data/UserDatabase"; import { IdGenerator } from "../services/IdGenerator"; import { HashManager } from "../services/HashManager"; import { Authenticator } from "../services/Authenticator"; +import { CustomError, InvalidEmail, InvalidName, InvalidPassword, SmallEmail, UserNotFound } from "../error/BaseError"; export class UserBusiness { async createUser(user: UserInputDTO) { - const idGenerator = new IdGenerator(); - const id = idGenerator.generate(); + try { - const hashManager = new HashManager(); - const hashPassword = await hashManager.hash(user.password); + if(!user.email){ + throw new InvalidEmail + } - const userDatabase = new UserDatabase(); - await userDatabase.createUser(id, user.email, user.name, hashPassword, user.role); + const filterEmail = user.email.includes("@" && ".com") + if(filterEmail != true){ + throw new InvalidEmail + } - const authenticator = new Authenticator(); - const accessToken = authenticator.generateToken({ id, role: user.role }); + if(!user.name){ + throw new InvalidName + } - return accessToken; + if(user.email.length < 10){ + throw new SmallEmail + } + + if(user.name.length < 4){ + throw new InvalidName + } + + if(!user.password){ + throw new InvalidPassword + } + + if(user.password.length < 6){ + throw new InvalidPassword + } + + const idGenerator = new IdGenerator(); + const id = idGenerator.generate(); + + const hashManager = new HashManager(); + const hashPassword = await hashManager.hash(user.password); + + const userDatabase = new UserDatabase(); + await userDatabase.createUser(id, user.email, user.name, hashPassword, user.role); + + const authenticator = new Authenticator(); + const accessToken = authenticator.generateToken({ id, role: user.role }); + + return accessToken; + + } catch (error:any) { + throw new CustomError(error.status, error.message) + } } async getUserByEmail(user: LoginInputDTO) { - const userDatabase = new UserDatabase(); - const userFromDB = await userDatabase.getUserByEmail(user.email); + try { - const hashManager = new HashManager(); - const hashCompare = await hashManager.compare(user.password, userFromDB.getPassword()); + if(!user.email){ + throw new UserNotFound + } - const authenticator = new Authenticator(); - const accessToken = authenticator.generateToken({ id: userFromDB.getId(), role: userFromDB.getRole() }); + if(!user.password){ + throw new InvalidPassword + } - if (!hashCompare) { - throw new Error("Invalid Password!"); - } + const userDatabase = new UserDatabase(); + const userFromDB = await userDatabase.getUserByEmail(user.email); + + const hashManager = new HashManager(); + const hashCompare = await hashManager.compare(user.password, userFromDB.getPassword()); - return accessToken; + const authenticator = new Authenticator(); + const accessToken = authenticator.generateToken({ id: userFromDB.getId(), role: userFromDB.getRole() }); + + if (!hashCompare) { + throw new Error("Invalid Password!"); + } + + return accessToken; + + } catch (error:any) { + throw new CustomError(error.status, error.message) + } } } \ No newline at end of file diff --git a/src/error/BaseError.ts b/src/error/BaseError.ts index ba293f5..19dea6a 100644 --- a/src/error/BaseError.ts +++ b/src/error/BaseError.ts @@ -28,6 +28,12 @@ export class InvalidEmail extends CustomError{ } } +export class SmallEmail extends CustomError{ + constructor(){ + super(400, "Email muito pequeno") + } +} + export class InvalidPassword extends CustomError{ constructor(){ super(400, "Senha inválida") diff --git a/src/services/Authenticator.ts b/src/services/Authenticator.ts index d21c80d..a852c91 100644 --- a/src/services/Authenticator.ts +++ b/src/services/Authenticator.ts @@ -10,7 +10,7 @@ export class Authenticator { }, process.env.JWT_KEY as string, { - expiresIn, + expiresIn: "1h" } ); return token; From 08776f708cf20672fa35321f97f6de24ce0fce88 Mon Sep 17 00:00:00 2001 From: Ricardo Barros <102339228+Ricardoteleco@users.noreply.github.com> Date: Sun, 12 Mar 2023 23:49:29 -0300 Subject: [PATCH 08/32] Revert "feat: foram criados os tratamentos de erro dos endpoints 1 e 2" --- requests.rest | 6 ------ src/business/UserBusiness.ts | 8 ++------ src/error/BaseError.ts | 6 ------ src/services/Authenticator.ts | 2 -- 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/requests.rest b/requests.rest index 8ad2292..4e51161 100644 --- a/requests.rest +++ b/requests.rest @@ -4,23 +4,18 @@ POST POST http://localhost:3003/users/signup Content-Type: application/json { - "email": "exemplo-mauricio@lbn.com", "name": "Mauricio", "password": "123456", - "role": "ADMIN" } ### Login - - POST http://localhost:3000/user/login Content-Type: application/json { - "email": "exemplo-mauricio@lbn.com", "password": "123456" } @@ -29,7 +24,6 @@ Content-Type: application/json POST http://localhost:3003/create - { "name": "Mauricio", diff --git a/src/business/UserBusiness.ts b/src/business/UserBusiness.ts index b105b03..602d253 100644 --- a/src/business/UserBusiness.ts +++ b/src/business/UserBusiness.ts @@ -1,5 +1,3 @@ - -======= import { CustomError } from "../error/BaseError" import { DuplicateEmail, EmailNotFound, IncorrectPassword, InvalidEmail, InvalidPassword, MissingEmail, MissingPassword, MissingUserName, MissingUserRole } from "../error/UserErros" import { IdAuthenticator } from "../model/IdAuthenticator" @@ -9,8 +7,6 @@ import { inputSignUpDTO, loginInputDTO, User, UserRole } from "../model/User" import { UserRepository } from "../model/UserRepository" - - export class UserBusiness { constructor ( private userDatabase : UserRepository, @@ -58,10 +54,10 @@ export class UserBusiness { } catch (error: any) { throw new CustomError(error.statusCode, error.message) - } } + async login (input: loginInputDTO): Promise { try { if (!input.email) { @@ -89,6 +85,6 @@ export class UserBusiness { } catch (error: any) { throw new CustomError(error.statusCode, error.message) - + } } } \ No newline at end of file diff --git a/src/error/BaseError.ts b/src/error/BaseError.ts index 19dea6a..ba293f5 100644 --- a/src/error/BaseError.ts +++ b/src/error/BaseError.ts @@ -28,12 +28,6 @@ export class InvalidEmail extends CustomError{ } } -export class SmallEmail extends CustomError{ - constructor(){ - super(400, "Email muito pequeno") - } -} - export class InvalidPassword extends CustomError{ constructor(){ super(400, "Senha inválida") diff --git a/src/services/Authenticator.ts b/src/services/Authenticator.ts index 1b390cb..cf4e9e5 100644 --- a/src/services/Authenticator.ts +++ b/src/services/Authenticator.ts @@ -4,8 +4,6 @@ import { Unauthorized } from "../error/BaseError" import { AuthenticationData } from "../model/AuthenticatorData" import { IdAuthenticator } from "../model/IdAuthenticator" - - dotenv.config() export class Authenticator implements IdAuthenticator { From c31746bcde1265194206793224e28f2392b48b24 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Mon, 13 Mar 2023 13:40:20 -0300 Subject: [PATCH 09/32] debugando pt4 --- requests.rest | 9 ++--- src/app.ts | 13 +++++++ src/business/BandCreateBusiness.ts | 48 ++++++++++++++++++++++++-- src/controller/BandCreateController.ts | 20 +++++++++-- src/data/BaseDatabase.ts | 2 +- src/error/BandErrors.ts | 24 +++++++++++++ src/index.ts | 24 ++++--------- src/model/BandCreateDTO.ts | 6 ++++ src/routes/userRouter.ts | 1 + tables.sql | 4 +-- 10 files changed, 122 insertions(+), 29 deletions(-) create mode 100644 src/app.ts diff --git a/requests.rest b/requests.rest index 4e51161..931be4a 100644 --- a/requests.rest +++ b/requests.rest @@ -1,12 +1,12 @@ ### Criar Usuário -POST POST http://localhost:3003/users/signup +POST http://localhost:3003/users/signup Content-Type: application/json { "email": "exemplo-mauricio@lbn.com", "name": "Mauricio", - "password": "123456", + "password": "12345678", "role": "ADMIN" } @@ -22,12 +22,13 @@ Content-Type: application/json ### -POST http://localhost:3003/create +POST http://localhost:3003/bands/create { "name": "Mauricio", "music_genre":"ForMetal", "responsible": "Bon Jovi", - "role": "ADMIN" + + } \ No newline at end of file diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..105e8c5 --- /dev/null +++ b/src/app.ts @@ -0,0 +1,13 @@ +import express from "express" +import cors from "cors" +import dotenv from "dotenv" + +dotenv.config() + +export const app = express() +app.use(express.json()) +app.use(cors()) + +app.listen(process.env.PORT || 3003, () => { + console.log(`Server is running on port ${process.env.PORT || 3000}`) +}) \ No newline at end of file diff --git a/src/business/BandCreateBusiness.ts b/src/business/BandCreateBusiness.ts index fd5c894..6f15212 100644 --- a/src/business/BandCreateBusiness.ts +++ b/src/business/BandCreateBusiness.ts @@ -1,12 +1,13 @@ - +import { NameOrId,NameNotFound,IdNotFound,InvalidInfo, } from "../error/BandErrors" import { DuplicateBandName, BandName, MusicGenre, Responsible } from "../error/BandErrors" import { CustomError } from "../error/BaseError" import { MissingToken, Unauthorized } from "../error/BaseError" -import { BandCreateDTO, inputCreateBandDTO } from "../model/BandCreateDTO" +import { BandCreateDTO, inputCreateBandDTO, inputGetBandDTO } from '../model/BandCreateDTO'; import { BandRepository } from "../model/BandRepository" import { IdAuthenticator } from "../model/IdAuthenticator" import { GeneratorId } from "../model/GeneratorId" import { UserRole } from "../model/User" + export class BandCreateBusiness { constructor ( private bandDatabase: BandRepository, @@ -48,4 +49,47 @@ export class BandCreateBusiness { throw new CustomError(error.statusCode, error.message) } } + + + async getBandInfo (input: inputGetBandDTO): Promise { + try { + if (!input.token) { + throw new MissingToken() + } + if (!input.id && !input.name) { + throw new NameOrId() + } + + await this.authorization.getTokenData(input.token) + + if (input.id && input.name) { + throw new InvalidInfo() + } + + let result:any + if (input.id) { + const idExists = await this.bandDatabase.getBandBy("id", input.id) + if (!idExists) { + throw new IdNotFound() + } + result = idExists + } + + if (input.name) { + input.name = input.name.replace("","") + + const nameExists = await this.bandDatabase.getBandBy("bandName", input.name) + if (!nameExists) { + throw new NameNotFound() + } + + result = nameExists + } + + return result + + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } } \ No newline at end of file diff --git a/src/controller/BandCreateController.ts b/src/controller/BandCreateController.ts index 2563e05..9b0c937 100644 --- a/src/controller/BandCreateController.ts +++ b/src/controller/BandCreateController.ts @@ -1,7 +1,7 @@ import { Request,Response } from "express" import { inputCreateBandDTO } from "../model/BandCreateDTO" import { BandCreateBusiness } from "../business/BandCreateBusiness" - +import { inputGetBandDTO } from "../model/BandCreateDTO" export class BandCreateController { constructor (private bandBusiness: BandCreateBusiness) {} @@ -22,4 +22,20 @@ export class BandCreateController { res.status(error.statusCode || 400).send(error.message || error.sqlMessage) } } -} + +async getBandInfo (req: Request, res: Response): Promise { + try { + const input: inputGetBandDTO = { + id: req.query.id as string, + name: req.query.name as string, + token: req.headers.authorization as string + } + + const result = await this.bandBusiness.getBandInfo(input) + res.status(200).send(result) + + } catch (error: any) { + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } +} } + diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts index 023b2be..416dfcb 100644 --- a/src/data/BaseDatabase.ts +++ b/src/data/BaseDatabase.ts @@ -12,7 +12,7 @@ export class BaseDatabase { user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_SCHEMA, - port: 3306, + port: 3006, multipleStatements: true } }) diff --git a/src/error/BandErrors.ts b/src/error/BandErrors.ts index 9ab1dac..6171768 100644 --- a/src/error/BandErrors.ts +++ b/src/error/BandErrors.ts @@ -24,5 +24,29 @@ export class Responsible extends CustomError { super (422, "Provide the name of the responsible for the band.") } } +export class NameOrId extends CustomError { + constructor () { + super (422, "Provide the id or the name of the band.") + } +} + +export class IdNotFound extends CustomError { + constructor () { + super (404, "Band id not found.") + } +} + +export class NameNotFound extends CustomError { + constructor () { + super (404, "Band name not found.") + } +} + +export class InvalidInfo extends CustomError { + constructor () { + super (422, "Provide either the band id or the band name.") + } +} + export { CustomError } diff --git a/src/index.ts b/src/index.ts index e5ce406..431dc43 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,9 @@ -import dotenv from "dotenv"; -import {AddressInfo} from "net"; -import express from "express"; -import { userRouter } from "./routes/userRouter"; -import { bandRouter } from "./routes/bandRouter"; -dotenv.config(); -const app = express(); +import { app } from "./app" +import { bandRouter } from "./routes/bandRouter" +import { userRouter } from "./routes/userRouter" -app.use(express.json()); -app.use("/user", userRouter); -app.use("/bands", bandRouter) -const server = app.listen(3000, () => { - if (server) { - const address = server.address() as AddressInfo; - console.log(`Servidor rodando em http://localhost:${address.port}`); - } else { - console.error(`Falha ao rodar o servidor.`); - } - }); \ No newline at end of file + +app.use("/users", userRouter) +app.use("/bands", bandRouter) \ No newline at end of file diff --git a/src/model/BandCreateDTO.ts b/src/model/BandCreateDTO.ts index 58307ec..3e7ff0b 100644 --- a/src/model/BandCreateDTO.ts +++ b/src/model/BandCreateDTO.ts @@ -1,3 +1,4 @@ + export class BandCreateDTO { constructor ( public readonly id: string, @@ -17,4 +18,9 @@ export interface inputCreateBandDTO { musicGenre: string, responsible: string, token: string +} +export interface inputGetBandDTO { + id: string, + name: string, + token: string } \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index e8be5dd..f512ed3 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -1,3 +1,4 @@ +import { Request,Response} from "express"; import express from "express" import { UserBusiness } from "../business/UserBusiness" import { UserController } from "../controller/UserController" diff --git a/tables.sql b/tables.sql index 0674b19..6212d60 100644 --- a/tables.sql +++ b/tables.sql @@ -1,4 +1,4 @@ --- Active: 1676582098331@@35.226.146.116@3306@jbl-4416547-ricardo-morais +-- Active: 1676323408280@@35.226.146.116@3306@jbl-4416472-mauricio-toledo ### Query que cria a tabela de Bandas CREATE TABLE IF NOT EXISTS Bands_Name ( @@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS Bands_Name ( name VARCHAR(255) UNIQUE NOT NULL, music_genre VARCHAR(255) NOT NULL, responsible VARCHAR(255) UNIQUE NOT NULL - role VARCHAR(255) NOT NULL DEFAULT "ADMIN" + ); From d3d6995ede2c0441f487fce2bfd472cfc02a67a9 Mon Sep 17 00:00:00 2001 From: Ricardo_Barros Date: Mon, 13 Mar 2023 23:15:54 -0300 Subject: [PATCH 10/32] =?UTF-8?q?Arrumando=20conex=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requests.rest | 12 ++++++------ src/app.ts | 2 +- src/data/BaseDatabase.ts | 2 +- tables.sql | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/requests.rest b/requests.rest index 931be4a..cfe1cde 100644 --- a/requests.rest +++ b/requests.rest @@ -1,23 +1,23 @@ ### Criar Usuário -POST http://localhost:3003/users/signup +POST http://localhost:3003/users/signup Content-Type: application/json { - "email": "exemplo-mauricio@lbn.com", - "name": "Mauricio", + "email": "exemplo-elton@lbn.com", + "name": "Elton", "password": "12345678", "role": "ADMIN" } ### Login -POST http://localhost:3000/user/login +POST http://localhost:3003/user/login Content-Type: application/json { - "email": "exemplo-mauricio@lbn.com", - "password": "123456" + "email": "exemplo-elton@lbn.com", + "password": "12345678" } ### diff --git a/src/app.ts b/src/app.ts index 105e8c5..29ec065 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,5 +9,5 @@ app.use(express.json()) app.use(cors()) app.listen(process.env.PORT || 3003, () => { - console.log(`Server is running on port ${process.env.PORT || 3000}`) + console.log(`Server is running on port ${process.env.PORT || 3003}`) }) \ No newline at end of file diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts index 416dfcb..023b2be 100644 --- a/src/data/BaseDatabase.ts +++ b/src/data/BaseDatabase.ts @@ -12,7 +12,7 @@ export class BaseDatabase { user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_SCHEMA, - port: 3006, + port: 3306, multipleStatements: true } }) diff --git a/tables.sql b/tables.sql index 6212d60..558b2f4 100644 --- a/tables.sql +++ b/tables.sql @@ -1,4 +1,4 @@ --- Active: 1676323408280@@35.226.146.116@3306@jbl-4416472-mauricio-toledo +-- Active: 1676582098331@@35.226.146.116@3306@jbl-4416547-ricardo-morais ### Query que cria a tabela de Bandas CREATE TABLE IF NOT EXISTS Bands_Name ( From 18647ae96785c7fa8b69c92d11d8a3230304ecf5 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:07:18 +0000 Subject: [PATCH 11/32] Reafatorando --- src/app.ts | 2 +- src/data/BaseDatabase.ts | 2 +- src/data/UserDatabase.ts | 34 +++++++++++++++++----------------- src/index.ts | 1 - src/routes/userRouter.ts | 3 +-- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/app.ts b/src/app.ts index 105e8c5..7fa89ed 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,6 @@ export const app = express() app.use(express.json()) app.use(cors()) -app.listen(process.env.PORT || 3003, () => { +app.listen(process.env.PORT || 3001, () => { console.log(`Server is running on port ${process.env.PORT || 3000}`) }) \ No newline at end of file diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts index 416dfcb..1e8979b 100644 --- a/src/data/BaseDatabase.ts +++ b/src/data/BaseDatabase.ts @@ -12,7 +12,7 @@ export class BaseDatabase { user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_SCHEMA, - port: 3006, + port: 3000, multipleStatements: true } }) diff --git a/src/data/UserDatabase.ts b/src/data/UserDatabase.ts index 42891ab..75cc9cd 100644 --- a/src/data/UserDatabase.ts +++ b/src/data/UserDatabase.ts @@ -5,22 +5,22 @@ import { BaseDatabase } from "./BaseDatabase" export class UserDatabase extends BaseDatabase implements UserRepository { - private TABLE_NAME = "Lama_Users" - - async signup (newUser: User): Promise { - try { - await BaseDatabase.connection(this.TABLE_NAME).insert(newUser) - } catch (error: any) { - throw new CustomError(error.statusCode, error.message) - } - } + private TABLE_NAME = "Lama_Users" + + async signup (newUser: User): Promise { + try { + await BaseDatabase.connection(this.TABLE_NAME).insert(newUser) + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } - async getUser (column: string, value: string): Promise { - try { - const result = await BaseDatabase.connection(this.TABLE_NAME).select().where(column, value) - return result[0] - } catch (error: any) { - throw new CustomError(error.statusCode, error.message) - } - } + async getUser (column: string, value: string): Promise { + try { + const result = await BaseDatabase.connection(this.TABLE_NAME).select().where(column, value) + return result[0] + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 431dc43..dee0ca2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,5 @@ import { userRouter } from "./routes/userRouter" - app.use("/users", userRouter) app.use("/bands", bandRouter) \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index f512ed3..93f3988 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -1,4 +1,3 @@ -import { Request,Response} from "express"; import express from "express" import { UserBusiness } from "../business/UserBusiness" import { UserController } from "../controller/UserController" @@ -15,4 +14,4 @@ const userBusiness = new UserBusiness(userDatabase, new IdGenerator(), new HashM const userController = new UserController(userBusiness) userRouter.post("/signup", (req, res) => userController.signup(req, res)) -userRouter.post("/login", (req, res) => userController.login(req, res)) \ No newline at end of file +userRouter.post("/login", (req, res) => userController.login(req, res)) From 174437b2f636b44d881e40380df6092007b894ef Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Tue, 14 Mar 2023 15:38:30 -0300 Subject: [PATCH 12/32] Router --- src/routes/bandRouter.ts | 3 ++- src/routes/userRouter.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/routes/bandRouter.ts b/src/routes/bandRouter.ts index 45b6b09..299d3fd 100644 --- a/src/routes/bandRouter.ts +++ b/src/routes/bandRouter.ts @@ -12,4 +12,5 @@ const bandDatabase = new BandCreateDatabase() const bandBusiness = new BandCreateBusiness(bandDatabase, new Authenticator(), new IdGenerator()) const bandController = new BandCreateController(bandBusiness) -bandRouter.post("/create", (req, res) => bandController.createBand(req, res)) \ No newline at end of file +bandRouter.post("/create", (req, res) => bandController.createBand(req, res))// pt 3 +bandRouter.get("/info", (req, res) => bandController.getBandInfo(req, res)) // pt 4 \ No newline at end of file diff --git a/src/routes/userRouter.ts b/src/routes/userRouter.ts index f512ed3..84e5765 100644 --- a/src/routes/userRouter.ts +++ b/src/routes/userRouter.ts @@ -14,5 +14,5 @@ const userDatabase = new UserDatabase() const userBusiness = new UserBusiness(userDatabase, new IdGenerator(), new HashManager(), new Authenticator()) const userController = new UserController(userBusiness) -userRouter.post("/signup", (req, res) => userController.signup(req, res)) -userRouter.post("/login", (req, res) => userController.login(req, res)) \ No newline at end of file +userRouter.post("/signup", (req, res) => userController.signup(req, res)) // pt 1 +userRouter.post("/login", (req, res) => userController.login(req, res)) // pt2 \ No newline at end of file From c74a9741a79a826a9ae04173081cc7e401af4e23 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Tue, 14 Mar 2023 16:41:07 -0300 Subject: [PATCH 13/32] Pt3 e 4 ok --- requests.rest | 30 ++++++----- src/app.ts | 2 +- src/business/BandCreateBusiness.ts | 10 ++-- src/controller/BandCreateController.ts | 71 ++++++++++++++------------ src/data/BandCreateDataBase.ts | 8 +-- src/data/BaseDatabase.ts | 2 +- src/model/BandCreateDTO.ts | 6 ++- src/routes/bandRouter.ts | 4 +- 8 files changed, 74 insertions(+), 59 deletions(-) diff --git a/requests.rest b/requests.rest index 931be4a..4fe1199 100644 --- a/requests.rest +++ b/requests.rest @@ -1,34 +1,40 @@ ### Criar Usuário -POST http://localhost:3003/users/signup +POST http://localhost:3300/users/signup Content-Type: application/json { - "email": "exemplo-mauricio@lbn.com", - "name": "Mauricio", + "email": "maurilio9@mauricio.com", + "name": "Maurilio", "password": "12345678", "role": "ADMIN" } ### Login -POST http://localhost:3000/user/login +POST http://localhost:3300/users/login Content-Type: application/json { "email": "exemplo-mauricio@lbn.com", - "password": "123456" + "password": "12345678" } ### -POST http://localhost:3003/bands/create +POST http://localhost:3300/bands/create +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA4YjgwMDMxLWZlNWEtNDAwYy04ZTBhLTJiMmI0ZjZmMmUxOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgyMjYzMywiZXhwIjoxNjc4ODI2MjMzfQ.Pa7Ml0Zch_ZPAyce0b23cL1Be8Q2HVjAN6wV00dx1dI +Content-Type: application/json + { - - "name": "Mauricio", - "music_genre":"ForMetal", - "responsible": "Bon Jovi", - -} \ No newline at end of file +"name": "U2", + "musicGenre": "Pop", + "responsible": "Bono Vox" +} + +### +GET http://localhost:3300/bands/info?name=U2 +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA4YjgwMDMxLWZlNWEtNDAwYy04ZTBhLTJiMmI0ZjZmMmUxOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgyMjYzMywiZXhwIjoxNjc4ODI2MjMzfQ.Pa7Ml0Zch_ZPAyce0b23cL1Be8Q2HVjAN6wV00dx1dI +Content-Type: application/json \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 7fa89ed..2f59361 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,6 @@ export const app = express() app.use(express.json()) app.use(cors()) -app.listen(process.env.PORT || 3001, () => { +app.listen(process.env.PORT || 3300, () => { console.log(`Server is running on port ${process.env.PORT || 3000}`) }) \ No newline at end of file diff --git a/src/business/BandCreateBusiness.ts b/src/business/BandCreateBusiness.ts index 6f15212..f2f8a7d 100644 --- a/src/business/BandCreateBusiness.ts +++ b/src/business/BandCreateBusiness.ts @@ -2,7 +2,7 @@ import { NameOrId,NameNotFound,IdNotFound,InvalidInfo, } from "../error/BandErro import { DuplicateBandName, BandName, MusicGenre, Responsible } from "../error/BandErrors" import { CustomError } from "../error/BaseError" import { MissingToken, Unauthorized } from "../error/BaseError" -import { BandCreateDTO, inputCreateBandDTO, inputGetBandDTO } from '../model/BandCreateDTO'; +import { BandCreateDTO, inputBandDTO, inputGetBandDTO } from '../model/BandCreateDTO'; import { BandRepository } from "../model/BandRepository" import { IdAuthenticator } from "../model/IdAuthenticator" import { GeneratorId } from "../model/GeneratorId" @@ -15,7 +15,7 @@ export class BandCreateBusiness { private idGenerator: GeneratorId ) {} - async createBand (input: inputCreateBandDTO): Promise { + async createBand (input: inputBandDTO): Promise { try { if (!input.name) { throw new BandName() @@ -66,7 +66,7 @@ export class BandCreateBusiness { throw new InvalidInfo() } - let result:any + let result : any if (input.id) { const idExists = await this.bandDatabase.getBandBy("id", input.id) if (!idExists) { @@ -76,9 +76,9 @@ export class BandCreateBusiness { } if (input.name) { - input.name = input.name.replace("","") + input.name = input.name.replace("_", " ") - const nameExists = await this.bandDatabase.getBandBy("bandName", input.name) + const nameExists = await this.bandDatabase.getBandBy("name", input.name) if (!nameExists) { throw new NameNotFound() } diff --git a/src/controller/BandCreateController.ts b/src/controller/BandCreateController.ts index 9b0c937..a461ecb 100644 --- a/src/controller/BandCreateController.ts +++ b/src/controller/BandCreateController.ts @@ -1,41 +1,46 @@ import { Request,Response } from "express" -import { inputCreateBandDTO } from "../model/BandCreateDTO" +import { inputBandDTO } from "../model/BandCreateDTO" import { BandCreateBusiness } from "../business/BandCreateBusiness" import { inputGetBandDTO } from "../model/BandCreateDTO" + + + + export class BandCreateController { - constructor (private bandBusiness: BandCreateBusiness) {} - - async createBand (req: Request, res: Response): Promise { - try { - const input: inputCreateBandDTO = { - name: req.body.name, - musicGenre: req.body.musicGenre, - responsible: req.body.responsible, - token: req.headers.authorization as string - } - - await this.bandBusiness.createBand(input) - - res.status(201).send("Band created successfully!") - - } catch (error: any) { - res.status(error.statusCode || 400).send(error.message || error.sqlMessage) - } - } - -async getBandInfo (req: Request, res: Response): Promise { - try { - const input: inputGetBandDTO = { - id: req.query.id as string, - name: req.query.name as string, - token: req.headers.authorization as string - } + constructor (private bandBusiness: BandCreateBusiness) {} + + async createBand (req: Request, res: Response): Promise { + try { + const input: inputBandDTO = { + name: req.body.name, + musicGenre: req.body.musicGenre, + responsible: req.body.responsible, + token: req.headers.authorization as string + } + + await this.bandBusiness.createBand(input) - const result = await this.bandBusiness.getBandInfo(input) - res.status(200).send(result) + res.status(201).send("Band created successfully!") - } catch (error: any) { - res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } catch (error: any) { + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } } -} } + + async getBandInfo (req: Request, res: Response): Promise { + try { + const input: inputGetBandDTO = { + id: req.query.id as string, + name: req.query.name as string, + token: req.headers.authorization as string + } + + const result = await this.bandBusiness.getBandInfo(input) + res.status(200).send(result) + + } catch (error: any) { + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } + } +} diff --git a/src/data/BandCreateDataBase.ts b/src/data/BandCreateDataBase.ts index a0136d0..f474881 100644 --- a/src/data/BandCreateDataBase.ts +++ b/src/data/BandCreateDataBase.ts @@ -1,7 +1,9 @@ -import { BaseDatabase } from "./BaseDatabase"; -import { BandCreateDTO } from "../model/BandCreateDTO"; import { CustomError } from "../error/BaseError"; +import { BandCreateDTO } from "../model/BandCreateDTO"; import { BandRepository } from "../model/BandRepository"; +import { BaseDatabase } from "./BaseDatabase"; + + export class BandCreateDatabase extends BaseDatabase implements BandRepository { private TABLE_NAME = "Bands_Name" @@ -14,7 +16,7 @@ export class BandCreateDatabase extends BaseDatabase implements BandRepository { } - async getBandBy (column: string, value: string): Promise { + async getBandBy (column: string, value: string): Promise { try { const result = await BaseDatabase.connection(this.TABLE_NAME).select().where(column, value) return result[0] diff --git a/src/data/BaseDatabase.ts b/src/data/BaseDatabase.ts index 1e8979b..023b2be 100644 --- a/src/data/BaseDatabase.ts +++ b/src/data/BaseDatabase.ts @@ -12,7 +12,7 @@ export class BaseDatabase { user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_SCHEMA, - port: 3000, + port: 3306, multipleStatements: true } }) diff --git a/src/model/BandCreateDTO.ts b/src/model/BandCreateDTO.ts index 3e7ff0b..4d93836 100644 --- a/src/model/BandCreateDTO.ts +++ b/src/model/BandCreateDTO.ts @@ -1,4 +1,5 @@ + export class BandCreateDTO { constructor ( public readonly id: string, @@ -13,14 +14,15 @@ export class BandCreateDTO { } } -export interface inputCreateBandDTO { +export interface inputBandDTO { name: string, musicGenre: string, responsible: string, token: string } + export interface inputGetBandDTO { id: string, name: string, token: string -} \ No newline at end of file +} diff --git a/src/routes/bandRouter.ts b/src/routes/bandRouter.ts index 299d3fd..15347a9 100644 --- a/src/routes/bandRouter.ts +++ b/src/routes/bandRouter.ts @@ -12,5 +12,5 @@ const bandDatabase = new BandCreateDatabase() const bandBusiness = new BandCreateBusiness(bandDatabase, new Authenticator(), new IdGenerator()) const bandController = new BandCreateController(bandBusiness) -bandRouter.post("/create", (req, res) => bandController.createBand(req, res))// pt 3 -bandRouter.get("/info", (req, res) => bandController.getBandInfo(req, res)) // pt 4 \ No newline at end of file +bandRouter.post("/create", (req, res) => bandController.createBand(req, res)) +bandRouter.get("/info", (req, res) => bandController.getBandInfo(req, res)) \ No newline at end of file From 6f84248c963d284cfdf5ce8c8b07399902c19d5b Mon Sep 17 00:00:00 2001 From: Ricardo_Barros Date: Tue, 14 Mar 2023 22:13:07 -0300 Subject: [PATCH 14/32] =?UTF-8?q?feat:=20endpoint=205,=20n=C3=A3o=20funcio?= =?UTF-8?q?na!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requests.rest | 39 ++++++++++--------------- src/business/ShowBusiness.ts | 42 +++++++++++++++++++++++++++ src/controller/ShowController.ts | 25 ++++++++++++++++ src/data/ShowDataBase.ts | 33 +++++++++++++++++++++ src/index.ts | 4 ++- src/model/Show.ts | 50 ++++++++++++++++++++++++++++++++ src/routes/showRouter.ts | 14 +++++++++ tables.sql | 6 +++- 8 files changed, 187 insertions(+), 26 deletions(-) create mode 100644 src/business/ShowBusiness.ts create mode 100644 src/controller/ShowController.ts create mode 100644 src/data/ShowDataBase.ts create mode 100644 src/model/Show.ts create mode 100644 src/routes/showRouter.ts diff --git a/requests.rest b/requests.rest index 5d0a812..8f5cd04 100644 --- a/requests.rest +++ b/requests.rest @@ -16,44 +16,35 @@ POST http://localhost:3300/users/login Content-Type: application/json { - "email": "exemplo-mauricio@lbn.com", + "email": "maurilio9@mauricio.com", "password": "12345678" } -### - +### Criar Banda POST http://localhost:3300/bands/create -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA4YjgwMDMxLWZlNWEtNDAwYy04ZTBhLTJiMmI0ZjZmMmUxOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgyMjYzMywiZXhwIjoxNjc4ODI2MjMzfQ.Pa7Ml0Zch_ZPAyce0b23cL1Be8Q2HVjAN6wV00dx1dI +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRhYzg5ODZiLTNjNTgtNGNlNS1iY2Y0LTc0MWMwYjkxMjhjYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgzMTE2MiwiZXhwIjoxNjc4ODM0NzYyfQ.MIhcNvn_4IGmsqGsJ9-yPhQmYoYcxJfqUf3fxruhD88 Content-Type: application/json - { -"name": "U2", - "musicGenre": "Pop", - "responsible": "Bono Vox" + "name": "U2", + "musicGenre": "Pop", + "responsible": "Bono Vox" } -### +### Ver Bandas Criadas GET http://localhost:3300/bands/info?name=U2 -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA4YjgwMDMxLWZlNWEtNDAwYy04ZTBhLTJiMmI0ZjZmMmUxOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgyMjYzMywiZXhwIjoxNjc4ODI2MjMzfQ.Pa7Ml0Zch_ZPAyce0b23cL1Be8Q2HVjAN6wV00dx1dI +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRhYzg5ODZiLTNjNTgtNGNlNS1iY2Y0LTc0MWMwYjkxMjhjYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgzMTE2MiwiZXhwIjoxNjc4ODM0NzYyfQ.MIhcNvn_4IGmsqGsJ9-yPhQmYoYcxJfqUf3fxruhD88 Content-Type: application/json -### -POST http://localhost:3300/bands/create -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA4YjgwMDMxLWZlNWEtNDAwYy04ZTBhLTJiMmI0ZjZmMmUxOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgyMjYzMywiZXhwIjoxNjc4ODI2MjMzfQ.Pa7Ml0Zch_ZPAyce0b23cL1Be8Q2HVjAN6wV00dx1dI -Content-Type: application/json +### Criar Shows +POST http://localhost:3000/show/createShow +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRhYzg5ODZiLTNjNTgtNGNlNS1iY2Y0LTc0MWMwYjkxMjhjYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgzMTE2MiwiZXhwIjoxNjc4ODM0NzYyfQ.MIhcNvn_4IGmsqGsJ9-yPhQmYoYcxJfqUf3fxruhD88 +Content-Type: application/json { - -"name": "U2", - "musicGenre": "Pop", - "responsible": "Bono Vox" -} - -### -GET http://localhost:3300/bands/info?name=U2 -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA4YjgwMDMxLWZlNWEtNDAwYy04ZTBhLTJiMmI0ZjZmMmUxOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgyMjYzMywiZXhwIjoxNjc4ODI2MjMzfQ.Pa7Ml0Zch_ZPAyce0b23cL1Be8Q2HVjAN6wV00dx1dI -Content-Type: application/json \ No newline at end of file + "band": "U2", + "startsAt": "2023/03/17" +} \ No newline at end of file diff --git a/src/business/ShowBusiness.ts b/src/business/ShowBusiness.ts new file mode 100644 index 0000000..ff2379b --- /dev/null +++ b/src/business/ShowBusiness.ts @@ -0,0 +1,42 @@ +import { ShowDataBase } from "../data/ShowDataBase"; +import { ICreateShowInputDTO, ICreateShowOutputDTO, Show } from "../model/Show"; +import { Authenticator } from "../services/Authenticator"; +import { IdGenerator } from "../services/IdGenerator"; +import { CustomError } from "../error/BaseError"; + +export class ShowBusiness { + + public createShow = async (input: ICreateShowInputDTO): Promise => { + const showDataBase = new ShowDataBase + const authenticator = new Authenticator + const idGenerator = new IdGenerator + + + try { + const { token, band, startsAt } = input + + const payload = authenticator.getTokenData(token) + + const startsAtDate = new Date(startsAt) + + + const show = new Show( + idGenerator.generateId(), + band, + startsAtDate + ) + + await showDataBase.createShow(show) + + const response: ICreateShowOutputDTO = { + message: "Show criado com sucesso", + show + } + + return response + + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } +} \ No newline at end of file diff --git a/src/controller/ShowController.ts b/src/controller/ShowController.ts new file mode 100644 index 0000000..2ae1b7f --- /dev/null +++ b/src/controller/ShowController.ts @@ -0,0 +1,25 @@ +import { Request, Response } from "express"; +import { ICreateShowInputDTO } from "../model/Show"; +import { ShowBusiness } from "../business/ShowBusiness"; + +export class ShowController { + constructor( + private showBusiness: ShowBusiness + ) {} + + public createShow = async (req: Request, res: Response) => { + + try { + const input: ICreateShowInputDTO = { + token: req.body.authorization, + band: req.body.band, + startsAt: req.body.startsAt + } + + const response = await this.showBusiness.createShow(input) + res.status(201).send(response) + } catch (error: any) { + res.status(error.statusCode).send({ message: error.message }) + } + } +} \ No newline at end of file diff --git a/src/data/ShowDataBase.ts b/src/data/ShowDataBase.ts new file mode 100644 index 0000000..52235b6 --- /dev/null +++ b/src/data/ShowDataBase.ts @@ -0,0 +1,33 @@ +import { BaseDatabase } from "./BaseDatabase"; + +export class ShowDataBase extends BaseDatabase { + public static TABLE_NAME = "Table_Shows" + + + public toShowDBModel = (show: any) => { + const showDB = { + id: show.getId(), + band: show.getBand(), + starts_at: show.getStartsAt() + } + + return showDB + } + + public findShowByDate = async (date: Date): Promise => { + const result = await BaseDatabase + .connection(ShowDataBase.TABLE_NAME) + .select() + .where({ starts_at: date }) + + return result[0] + } + + public createShow = async (show: any): Promise => { + const showDB = this.toShowDBModel(show) + + await BaseDatabase + .connection(ShowDataBase.TABLE_NAME) + .insert(showDB) + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index dee0ca2..4aea4e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,10 @@ import { app } from "./app" import { bandRouter } from "./routes/bandRouter" +import { showRouter } from "./routes/showRouter" import { userRouter } from "./routes/userRouter" app.use("/users", userRouter) -app.use("/bands", bandRouter) \ No newline at end of file +app.use("/bands", bandRouter) +app.use("/show", showRouter) \ No newline at end of file diff --git a/src/model/Show.ts b/src/model/Show.ts new file mode 100644 index 0000000..48f8a48 --- /dev/null +++ b/src/model/Show.ts @@ -0,0 +1,50 @@ +export interface IShowDB { + id: string, + band: string, + starts_at: Date +} + +export class Show { + constructor( + private id: string, + private band: string, + private startsAt: Date, + ) {} + + public getId = () => { + return this.id + } + + public getBand = () => { + return this.band + } + + public getStartsAt = () => { + return this.startsAt + } + + public setId = (newId: string) => { + this.id = newId + } + + public setBand = (newBand: string) => { + this.band = newBand + } + + public setStartsAt = (newStartsAt: Date) => { + this.startsAt = newStartsAt + } + +} + +export interface ICreateShowInputDTO { + token: string, + band: string, + startsAt: string +} + +export interface ICreateShowOutputDTO { + message: string, + show: Show +} + diff --git a/src/routes/showRouter.ts b/src/routes/showRouter.ts new file mode 100644 index 0000000..4f6795c --- /dev/null +++ b/src/routes/showRouter.ts @@ -0,0 +1,14 @@ +import { Request, Response } from "express" +import express from "express" +import { ShowBusiness } from "../business/ShowBusiness" +import { ShowController } from "../controller/ShowController" +import { ShowDataBase } from "../data/ShowDataBase" + + +export const showRouter = express.Router() + +const showDatabase = new ShowDataBase() +const showBusiness = new ShowBusiness() +const showController = new ShowController(showBusiness) + +showRouter.post("/createShow", (req, res) => showController.createShow(req, res)) diff --git a/tables.sql b/tables.sql index 558b2f4..c2240b6 100644 --- a/tables.sql +++ b/tables.sql @@ -35,4 +35,8 @@ DROP TABLE `NOME_TABELA_BANDAS`, `NOME_TABELA_SHOWS`; ### -SELECT * FROM `Lama_Users`; \ No newline at end of file +SELECT * FROM `Lama_Users`; + +### + +SELECT * FROM `Table_Shows`; \ No newline at end of file From 3791a68880dd95fec1317e6b44ba5ec0f91c0e7e Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Wed, 15 Mar 2023 09:58:46 +0000 Subject: [PATCH 15/32] Refatorando pt5 --- src/data/ShowDataBase.ts | 75 +++++++++++++++++++++++---------- src/model/Show.ts | 83 +++++++++++++++++++------------------ src/model/ShowRepository.ts | 10 +++++ 3 files changed, 105 insertions(+), 63 deletions(-) create mode 100644 src/model/ShowRepository.ts diff --git a/src/data/ShowDataBase.ts b/src/data/ShowDataBase.ts index 52235b6..68d36f4 100644 --- a/src/data/ShowDataBase.ts +++ b/src/data/ShowDataBase.ts @@ -1,33 +1,64 @@ -import { BaseDatabase } from "./BaseDatabase"; +import { CustomError } from "../error/BaseError" +import { ShowDTO,outputGetAllShowDTO,updateShowDatabaseDTO } from "../model/Show" -export class ShowDataBase extends BaseDatabase { - public static TABLE_NAME = "Table_Shows" +import { ShowsRepository } from "../model/ShowRepository" +import { BaseDatabase } from "./BaseDatabase" +export class ShowsDatabase extends BaseDatabase implements ShowsRepository { + private TABLE_NAME = "Table_Shows" - public toShowDBModel = (show: any) => { - const showDB = { - id: show.getId(), - band: show.getBand(), - starts_at: show.getStartsAt() + async createShow (newShow: ShowDTO): Promise { + try { + await BaseDatabase.connection(this.TABLE_NAME).insert(newShow) + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) } - - return showDB } - public findShowByDate = async (date: Date): Promise => { - const result = await BaseDatabase - .connection(ShowDataBase.TABLE_NAME) + + async searchShows (weekDay: string, column: string, value: string): Promise { + try { + const result = await BaseDatabase.connection(this.TABLE_NAME) .select() - .where({ starts_at: date }) + .where("week_day", weekDay) + .andWhere(column, value) - return result[0] + return result[0] + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } + + + async getAllShows (weekDay: string): Promise { + try { + return await BaseDatabase.connection(this.TABLE_NAME) + .join("Bands_Name", "Table_Shows.band_id", "=", "Bands_Name.id") + .select("Table_Shows.week_day", "Table_Shows.start_time", "Table_Shows.end_time", "Bands_Name.name", "Bands_Name.music_genre") + .where("week_day", weekDay).orderBy("start_time") + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } } - public createShow = async (show: any): Promise => { - const showDB = this.toShowDBModel(show) - await BaseDatabase - .connection(ShowDataBase.TABLE_NAME) - .insert(showDB) - } -} \ No newline at end of file + async getShowsById (id: string): Promise { + try { + const result = await BaseDatabase.connection(this.TABLE_NAME).select().where("id", id) + return result[0] + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } + + + async updateShows (newInfo: updateShowDatabaseDTO): Promise { + try { + await BaseDatabase.connection(this.TABLE_NAME) + .update({week_day: newInfo.weekDay, start_time: newInfo.startTime, end_time: newInfo.endTime}) + .where("id", newInfo.id) + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } +} diff --git a/src/model/Show.ts b/src/model/Show.ts index 48f8a48..6180c6a 100644 --- a/src/model/Show.ts +++ b/src/model/Show.ts @@ -1,50 +1,51 @@ -export interface IShowDB { - id: string, - band: string, - starts_at: Date -} - -export class Show { - constructor( - private id: string, - private band: string, - private startsAt: Date, - ) {} - - public getId = () => { - return this.id - } - - public getBand = () => { - return this.band - } - - public getStartsAt = () => { - return this.startsAt - } - - public setId = (newId: string) => { - this.id = newId - } - - public setBand = (newBand: string) => { - this.band = newBand +export class ShowDTO { + constructor ( + public readonly id: string, + public readonly week_day: string, + public readonly start_time: string, + public readonly end_time: string, + public readonly band_id: string + ) { + this.id = id + this.week_day = week_day + this.start_time = start_time + this.end_time = end_time + this.band_id = band_id } +} - public setStartsAt = (newStartsAt: Date) => { - this.startsAt = newStartsAt - } +export interface ICreateShowtDTO { + weekDay: string, + startTime: string, + endTime: string, + bandId: string, + token: string +} +export interface IGetAllShowDTO { + weekDay: string, + token: string } -export interface ICreateShowInputDTO { - token: string, - band: string, - startsAt: string +export interface outputGetAllShowDTO { + week_day: string, + start_time: string, + end_time: string, + name: string, + music_genre: string } -export interface ICreateShowOutputDTO { - message: string, - show: Show +export interface IUpdateShowDTO { + id: string, + weekDay: string, + startTime: string, + endTime: string, + token: string } +export interface updateShowDatabaseDTO { + id: string, + weekDay: string, + startTime: string, + endTime: string +} \ No newline at end of file diff --git a/src/model/ShowRepository.ts b/src/model/ShowRepository.ts new file mode 100644 index 0000000..8571319 --- /dev/null +++ b/src/model/ShowRepository.ts @@ -0,0 +1,10 @@ +import { ShowDTO, updateShowDatabaseDTO, outputGetAllShowDTO } from "./Show" + + +export interface ShowsRepository { + createShow (newConcert: ShowDTO): Promise + searchShows (weekDay: string, column: string, value: string): Promise + getAllShows (weekDay: string): Promise + getShowsById (id: string): Promise + updateShows (newInfo: updateShowDatabaseDTO): Promise +} \ No newline at end of file From 6fd8418e0205b5c84fbd61ca69e6626fb5529da5 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:51:52 +0000 Subject: [PATCH 16/32] Refatorando bugs --- src/business/ShowBusiness.ts | 85 +++++++++++++++++++++--------------- src/error/BandErrors.ts | 6 +++ src/error/ShowError.ts | 56 ++++++++++++++++++++++++ src/model/CreateShowTime.ts | 0 4 files changed, 112 insertions(+), 35 deletions(-) create mode 100644 src/error/ShowError.ts create mode 100644 src/model/CreateShowTime.ts diff --git a/src/business/ShowBusiness.ts b/src/business/ShowBusiness.ts index ff2379b..7c715f0 100644 --- a/src/business/ShowBusiness.ts +++ b/src/business/ShowBusiness.ts @@ -1,42 +1,57 @@ import { ShowDataBase } from "../data/ShowDataBase"; -import { ICreateShowInputDTO, ICreateShowOutputDTO, Show } from "../model/Show"; +import { ICreateShowInputDTO, ICreateShowOutputDTO, ICreateShowtDTO, ShowDTO } from "../model/Show"; import { Authenticator } from "../services/Authenticator"; import { IdGenerator } from "../services/IdGenerator"; +import { IdAuthenticator } from "../model/IdAuthenticator"; import { CustomError } from "../error/BaseError"; - -export class ShowBusiness { - - public createShow = async (input: ICreateShowInputDTO): Promise => { - const showDataBase = new ShowDataBase - const authenticator = new Authenticator - const idGenerator = new IdGenerator +import { MissingToken } from "../error/BaseError"; +import { IdNotFound, BandId } from "../error/BandErrors"; +import { GeneratorId } from "../model/GeneratorId"; +import { ShowsRepository } from "../model/ShowRepository"; +import { BandRepository } from "../model/BandRepository"; +import { UserRole } from "../model/User"; +import { WeekDay, StartTime, EndTime, InvalidWeekDay } from "../error/ShowError"; +import { Unauthorized } from "../error/BaseError"; +export class ShowBusiness { + constructor( + private ShowDataBase : ShowsRepository, + private bandDataBase : BandRepository, + private generateId : GeneratorId, + private auth : IdAuthenticator, + private ShowTime : ICreateShowtDTO + ) {} + + async createShow (input: ICreateShowtDTO): Promise { try { - const { token, band, startsAt } = input - - const payload = authenticator.getTokenData(token) - - const startsAtDate = new Date(startsAt) - - - const show = new Show( - idGenerator.generateId(), - band, - startsAtDate - ) - - await showDataBase.createShow(show) - - const response: ICreateShowOutputDTO = { - message: "Show criado com sucesso", - show - } - - return response - - } catch (error: any) { - throw new CustomError(error.statusCode, error.message) - } - } -} \ No newline at end of file + if (!input.token) { + throw new MissingToken() + } + if (!input.bandId) { + throw new BandId() + } + if (!input.weekDay) { + throw new WeekDay() + } + if (!input.startTime) { + throw new StartTime() + } + if (!input.endTime) { + throw new EndTime() + } + if (input.weekDay.toLowerCase() !== "sexta" && input.weekDay.toLowerCase() !== "sábado" && input.weekDay.toLowerCase() !== "domingo") { + throw new InvalidWeekDay() + } + + const {id, role} = await this.auth.getTokenData(input.token) + if (role.toUpperCase() !== UserRole.ADMIN) { + throw new Unauthorized() + } + + const bandIdExists = await this.bandDataBase.getBandBy("id", input.bandId) + if (!bandIdExists) { + throw new IdNotFound() + } + + } \ No newline at end of file diff --git a/src/error/BandErrors.ts b/src/error/BandErrors.ts index 6171768..851189a 100644 --- a/src/error/BandErrors.ts +++ b/src/error/BandErrors.ts @@ -48,5 +48,11 @@ export class InvalidInfo extends CustomError { } } +export class BandId extends CustomError{ + constructor () { + super (422, "Provide the band id.") + } +} + export { CustomError } diff --git a/src/error/ShowError.ts b/src/error/ShowError.ts new file mode 100644 index 0000000..7bf0649 --- /dev/null +++ b/src/error/ShowError.ts @@ -0,0 +1,56 @@ +import { CustomError } from "./BaseError"; + +export class ShowId extends CustomError { + constructor () { + super (422, "Provide the show id.") + } +} + +export class ShowtId extends CustomError { + constructor () { + super (404, "Show id not found.") + } +} + +export class WeekDay extends CustomError { + constructor () { + super (422, "Provide the week day.") + } +} + +export class InvalidWeekDay extends CustomError { + constructor () { + super (422, "The week day can only be Sexta, sábado or Domingo.") + } +} + +export class StartTime extends CustomError { + constructor () { + super (422, "Provide the start time.") + } +} + +export class InvalidStartTime extends CustomError { + constructor () { + super (422, "The start time must be between 8:00 am and 11:00 pm.") + } +} + +export class EndTime extends CustomError { + constructor () { + super (422, "Provide the end time.") + } +} + + + + + + +export class DuplicateConcert extends CustomError { + constructor () { + super (422, "There is a Show already registered .") + } +} + + diff --git a/src/model/CreateShowTime.ts b/src/model/CreateShowTime.ts new file mode 100644 index 0000000..e69de29 From 9fad9dca947cc2f69e3dd5b9ef1473c4e20f5b2d Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Wed, 15 Mar 2023 15:40:10 -0300 Subject: [PATCH 17/32] tables --- tables.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tables.sql b/tables.sql index 6212d60..30a2b47 100644 --- a/tables.sql +++ b/tables.sql @@ -35,4 +35,4 @@ DROP TABLE `NOME_TABELA_BANDAS`, `NOME_TABELA_SHOWS`; ### -SELECT * FROM `Lama_Users`; \ No newline at end of file +SELECT * FROM `Lama_Users`; From 0453a07ed4bb2758e716344f9eea59e2dcc1ed64 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:46:05 +0000 Subject: [PATCH 18/32] Refatorando bugs --- src/business/ShowBusiness.ts | 4 ++-- src/model/CreateShowTime.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/business/ShowBusiness.ts b/src/business/ShowBusiness.ts index 7c715f0..8f9b885 100644 --- a/src/business/ShowBusiness.ts +++ b/src/business/ShowBusiness.ts @@ -1,5 +1,5 @@ -import { ShowDataBase } from "../data/ShowDataBase"; -import { ICreateShowInputDTO, ICreateShowOutputDTO, ICreateShowtDTO, ShowDTO } from "../model/Show"; + +import { ICreateShowtDTO, ShowDTO } from "../model/Show"; import { Authenticator } from "../services/Authenticator"; import { IdGenerator } from "../services/IdGenerator"; import { IdAuthenticator } from "../model/IdAuthenticator"; diff --git a/src/model/CreateShowTime.ts b/src/model/CreateShowTime.ts index e69de29..73c5cfa 100644 --- a/src/model/CreateShowTime.ts +++ b/src/model/CreateShowTime.ts @@ -0,0 +1,26 @@ +import { DuplicateConcert, InvalidConcertDuration, InvalidConcertTime, InvalidEndTime, InvalidStartTime } from "../error/ConcertErrors" +import { CustomError } from "../error/BaseError" + +import { ShowsRepository } from "./ShowRepository" + + +export class CheckConcertTime implements ICheckConcertTime { + constructor (private concertDatabase: ShowsRepository) {} + + public startTimeFormat (startTime: string): void { + try { + const startTimeArray = startTime.split(":") + + if (startTimeArray.length < 3) { + throw new InvalidStartTime() + } + if (Number(startTimeArray[0]) < 8 || Number(startTimeArray[0]) > 22) { + throw new InvalidStartTime() + } + if (startTimeArray[1] !== "00" || startTimeArray[2] !== "00") { + throw new InvalidStartTime() + } + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } \ No newline at end of file From e059b29dc2eca7d0c68365060821d8839beb37e8 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Wed, 15 Mar 2023 17:39:08 -0300 Subject: [PATCH 19/32] Refatorado pt5 e 6 --- Postman/Response-1678911279143.http | 10 +++++ Postman/Response-1678911314223.http | 10 +++++ Postman/Response-1678911365352.http | 10 +++++ Postman/Response-1678912700013.http | 10 +++++ README.md | 7 ++++ requests.rest | 30 ++++++++------ src/business/ShowBusiness.ts | 64 +++++++++++++++++++++++------ src/controller/ShowController.ts | 47 ++++++++++++++------- src/data/ShowDataBase.ts | 11 +---- src/error/ShowError.ts | 8 +++- src/index.ts | 2 +- src/model/CreateShowTime.ts | 32 ++++++++++++--- src/model/Show.ts | 14 ------- src/model/ShowRepository.ts | 4 +- src/model/ShowTimeDTO.ts | 7 ++++ src/routes/showRouter.ts | 16 +++++--- 16 files changed, 203 insertions(+), 79 deletions(-) create mode 100644 Postman/Response-1678911279143.http create mode 100644 Postman/Response-1678911314223.http create mode 100644 Postman/Response-1678911365352.http create mode 100644 Postman/Response-1678912700013.http create mode 100644 src/model/ShowTimeDTO.ts diff --git a/Postman/Response-1678911279143.http b/Postman/Response-1678911279143.http new file mode 100644 index 0000000..d6c9edc --- /dev/null +++ b/Postman/Response-1678911279143.http @@ -0,0 +1,10 @@ +HTTP/1.1 201 Created +X-Powered-By: Express +Access-Control-Allow-Origin: * +Content-Type: application/json; charset=utf-8 +Content-Length: 257 +ETag: W/"101-E41maHfnohjSVsQOBxj92f6EaoQ" +Date: Wed, 15 Mar 2023 20:13:27 GMT +Connection: close + +{"message":"User created successfully","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTIwNywiZXhwIjoxNjc4OTE0ODA3fQ.pngWBrtsyf3TGvgMju4ABdxbIhRHxBj6ZveEaMYKpsU"} \ No newline at end of file diff --git a/Postman/Response-1678911314223.http b/Postman/Response-1678911314223.http new file mode 100644 index 0000000..7169835 --- /dev/null +++ b/Postman/Response-1678911314223.http @@ -0,0 +1,10 @@ +HTTP/1.1 200 OK +X-Powered-By: Express +Access-Control-Allow-Origin: * +Content-Type: application/json; charset=utf-8 +Content-Length: 219 +ETag: W/"db-gwfNGxYsXWF93CIJLPFmYV7Jyfo" +Date: Wed, 15 Mar 2023 20:15:09 GMT +Connection: close + +{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEwNGJlZGNhLTM2YzUtNGFkOC05YTU4LWJiNTI5YTcyYjFhZCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTMwOSwiZXhwIjoxNjc4OTE0OTA5fQ.LcfR9AcEVr50HhqklGv5yPtt60bt6pBqRfedxi5tB_k"} \ No newline at end of file diff --git a/Postman/Response-1678911365352.http b/Postman/Response-1678911365352.http new file mode 100644 index 0000000..acc81b1 --- /dev/null +++ b/Postman/Response-1678911365352.http @@ -0,0 +1,10 @@ +HTTP/1.1 201 Created +X-Powered-By: Express +Access-Control-Allow-Origin: * +Content-Type: text/html; charset=utf-8 +Content-Length: 26 +ETag: W/"1a-PcuEgwzW/gXXsATEQgQU7E5GuWE" +Date: Wed, 15 Mar 2023 20:16:02 GMT +Connection: close + +Band created successfully! \ No newline at end of file diff --git a/Postman/Response-1678912700013.http b/Postman/Response-1678912700013.http new file mode 100644 index 0000000..c99ed27 --- /dev/null +++ b/Postman/Response-1678912700013.http @@ -0,0 +1,10 @@ +HTTP/1.1 400 Bad Request +X-Powered-By: Express +Access-Control-Allow-Origin: * +Content-Type: text/html; charset=utf-8 +Content-Length: 21 +ETag: W/"15-ERBUgNyYkq4zWicwY3ju2qW8+ZQ" +Date: Wed, 15 Mar 2023 20:38:15 GMT +Connection: close + +Provide the end time. \ No newline at end of file diff --git a/README.md b/README.md index 6a2f62f..68af457 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,10 @@ Como você deve saber muito bem, o nosso querido chefinho Astrodev é uma pessoa com Networking incrível e ele conhece vários artistas estrelados. Além disso, ele também é um grande ~~megalomaníaco~~ visionário e está planejando fazer um grande evento: o **LAMA**, *Labenu Musical Awards*, um festival com várias bandas famosas para a formatura da sua turma e, no final, vocês podem eleger a banda que mais gostaram! Entretanto, na opinião dele, vocês só serão merecedores se entregarem um sistema impecável que permita o gerenciamento completo desses shows. Para isso já deixamos algumas tabelas prontas para vocês não precisarem se preocupar com a modelagem do banco. Deixamos também um template do projeto já com a estrutura da parte de usuários. Vocês podem usá-las a vontade, mas, se quiser fazer do zero sem esse auxílio, também pode. + +Criar Usuario : ok +Login: Ok +Criar banda : ok +Procurar banda : ok +Criar show : ok fornecer id da banda +procurar show: ok fornecer id diff --git a/requests.rest b/requests.rest index 8f5cd04..99fe80b 100644 --- a/requests.rest +++ b/requests.rest @@ -4,7 +4,7 @@ POST http://localhost:3300/users/signup Content-Type: application/json { - "email": "maurilio9@mauricio.com", + "email": "maur9@mauricio.com", "name": "Maurilio", "password": "12345678", "role": "ADMIN" @@ -16,35 +16,39 @@ POST http://localhost:3300/users/login Content-Type: application/json { - "email": "maurilio9@mauricio.com", + "email": "maur9@mauricio.com", "password": "12345678" } ### Criar Banda POST http://localhost:3300/bands/create -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRhYzg5ODZiLTNjNTgtNGNlNS1iY2Y0LTc0MWMwYjkxMjhjYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgzMTE2MiwiZXhwIjoxNjc4ODM0NzYyfQ.MIhcNvn_4IGmsqGsJ9-yPhQmYoYcxJfqUf3fxruhD88 +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTgxOSwiZXhwIjoxNjc4OTE1NDE5fQ.P078iJJ20RAIQCXCQ5KX0RMRsot0r_nH_F92Wtx-LIU Content-Type: application/json { - "name": "U2", - "musicGenre": "Pop", - "responsible": "Bono Vox" + "name": "Nirvana", + "musicGenre": "Rock", + "responsible": "Kurt" } ### Ver Bandas Criadas -GET http://localhost:3300/bands/info?name=U2 -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRhYzg5ODZiLTNjNTgtNGNlNS1iY2Y0LTc0MWMwYjkxMjhjYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgzMTE2MiwiZXhwIjoxNjc4ODM0NzYyfQ.MIhcNvn_4IGmsqGsJ9-yPhQmYoYcxJfqUf3fxruhD88 +GET http://localhost:3300/bands/info?name=Nirvana +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTgxOSwiZXhwIjoxNjc4OTE1NDE5fQ.P078iJJ20RAIQCXCQ5KX0RMRsot0r_nH_F92Wtx-LIU Content-Type: application/json ### Criar Shows -POST http://localhost:3000/show/createShow -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRhYzg5ODZiLTNjNTgtNGNlNS1iY2Y0LTc0MWMwYjkxMjhjYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODgzMTE2MiwiZXhwIjoxNjc4ODM0NzYyfQ.MIhcNvn_4IGmsqGsJ9-yPhQmYoYcxJfqUf3fxruhD88 +POST http://localhost:3300/show/create +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTgxOSwiZXhwIjoxNjc4OTE1NDE5fQ.P078iJJ20RAIQCXCQ5KX0RMRsot0r_nH_F92Wtx-LIU Content-Type: application/json { - "band": "U2", - "startsAt": "2023/03/17" -} \ No newline at end of file + "bandId" : "d4c43186-52ed-4f24-8dba-382a8f742378", + "weekDay": "friday", + "startTime": "8:00", + "endTime": "10:00", + "id" : "d4c43186-52ed-4f24-8dba-382a8f742378" +} +### Retorna os shows diff --git a/src/business/ShowBusiness.ts b/src/business/ShowBusiness.ts index 8f9b885..3a9dea5 100644 --- a/src/business/ShowBusiness.ts +++ b/src/business/ShowBusiness.ts @@ -1,5 +1,5 @@ -import { ICreateShowtDTO, ShowDTO } from "../model/Show"; +import { ICreateShowtDTO, ShowDTO, outputGetAllShowDTO, IGetAllShowDTO} from "../model/Show"; import { Authenticator } from "../services/Authenticator"; import { IdGenerator } from "../services/IdGenerator"; import { IdAuthenticator } from "../model/IdAuthenticator"; @@ -10,17 +10,18 @@ import { GeneratorId } from "../model/GeneratorId"; import { ShowsRepository } from "../model/ShowRepository"; import { BandRepository } from "../model/BandRepository"; import { UserRole } from "../model/User"; -import { WeekDay, StartTime, EndTime, InvalidWeekDay } from "../error/ShowError"; +import { WeekDay, StartTime, EndTime, InvalidWeekDay, NoShows } from "../error/ShowError"; import { Unauthorized } from "../error/BaseError"; +import { CreateShowTime } from "../model/CreateShowTime"; export class ShowBusiness { - constructor( - private ShowDataBase : ShowsRepository, - private bandDataBase : BandRepository, - private generateId : GeneratorId, - private auth : IdAuthenticator, - private ShowTime : ICreateShowtDTO + constructor ( + private showDatabase: ShowsRepository, + private bandDatabase: BandRepository, + private authorization: IdAuthenticator, + private idGenerator: GeneratorId, + private checkUp: CreateShowTime ) {} async createShow (input: ICreateShowtDTO): Promise { @@ -40,18 +41,57 @@ export class ShowBusiness { if (!input.endTime) { throw new EndTime() } - if (input.weekDay.toLowerCase() !== "sexta" && input.weekDay.toLowerCase() !== "sábado" && input.weekDay.toLowerCase() !== "domingo") { + if (input.weekDay.toLowerCase() !== "friday" && input.weekDay.toLowerCase() !== "saturday" && input.weekDay.toLowerCase() !== "sunday") { throw new InvalidWeekDay() } - const {id, role} = await this.auth.getTokenData(input.token) + const {id, role} = await this.authorization.getTokenData(input.token) if (role.toUpperCase() !== UserRole.ADMIN) { throw new Unauthorized() } - const bandIdExists = await this.bandDataBase.getBandBy("id", input.bandId) + const bandIdExists = await this.bandDatabase.getBandBy("id", input.bandId) if (!bandIdExists) { throw new IdNotFound() } + + await this.checkUp.startTimeFormat(input.startTime) + await this.checkUp.endTimeFormat(input.endTime) + + + const concertId = this.idGenerator.generateId() + const newConcert = new ShowDTO(concertId, input.weekDay, input.startTime, input.endTime, input.bandId) + await this.showDatabase.createShow(newConcert) + + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } + + + async getAllShows (input: IGetAllShowDTO): Promise { + try { + if (!input.token) { + throw new MissingToken() + } + if (!input.weekDay) { + throw new WeekDay() + } + if (input.weekDay.toLowerCase() !== "friday" && input.weekDay.toLowerCase() !== "saturday" && input.weekDay.toLowerCase() !== "sunday") { + throw new InvalidWeekDay() + } - } \ No newline at end of file + await this.authorization.getTokenData(input.token) + + const result = await this.showDatabase.getAllShows(input.weekDay) + if (result.length === 0) { + throw new NoShows() + } + + return result + + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } +} \ No newline at end of file diff --git a/src/controller/ShowController.ts b/src/controller/ShowController.ts index 2ae1b7f..752d07f 100644 --- a/src/controller/ShowController.ts +++ b/src/controller/ShowController.ts @@ -1,25 +1,42 @@ -import { Request, Response } from "express"; -import { ICreateShowInputDTO } from "../model/Show"; -import { ShowBusiness } from "../business/ShowBusiness"; +import { ShowBusiness } from "../business/ShowBusiness" +import { Request, Response } from "express" +import { ICreateShowtDTO, IGetAllShowDTO } from "../model/Show" + export class ShowController { - constructor( - private showBusiness: ShowBusiness - ) {} + constructor (private concertBusiness: ShowBusiness) {} - public createShow = async (req: Request, res: Response) => { - + async createConcert (req: Request, res: Response): Promise { try { - const input: ICreateShowInputDTO = { - token: req.body.authorization, - band: req.body.band, - startsAt: req.body.startsAt + const input: ICreateShowtDTO = { + weekDay: req.body.weekDay, + startTime: req.body.startTime, + endTime: req.body.endTime, + bandId: req.body.bandId, + token: req.headers.authorization as string } - const response = await this.showBusiness.createShow(input) - res.status(201).send(response) + await this.concertBusiness.createShow(input) + res.status(201).send("Show created successfully!") + + } catch (error: any) { + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } + } + + + async getAllShows (req: Request, res: Response): Promise { + try { + const input:IGetAllShowDTO= { + weekDay: req.query.weekDay as string, + token: req.headers.authorization as string + } + + const result = await this.concertBusiness.getAllShows(input) + res.status(200).send(result) + } catch (error: any) { - res.status(error.statusCode).send({ message: error.message }) + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) } } } \ No newline at end of file diff --git a/src/data/ShowDataBase.ts b/src/data/ShowDataBase.ts index 68d36f4..1db0adc 100644 --- a/src/data/ShowDataBase.ts +++ b/src/data/ShowDataBase.ts @@ -1,5 +1,5 @@ import { CustomError } from "../error/BaseError" -import { ShowDTO,outputGetAllShowDTO,updateShowDatabaseDTO } from "../model/Show" +import { ShowDTO,outputGetAllShowDTO } from "../model/Show" import { ShowsRepository } from "../model/ShowRepository" import { BaseDatabase } from "./BaseDatabase" @@ -52,13 +52,4 @@ export class ShowsDatabase extends BaseDatabase implements ShowsRepository { } - async updateShows (newInfo: updateShowDatabaseDTO): Promise { - try { - await BaseDatabase.connection(this.TABLE_NAME) - .update({week_day: newInfo.weekDay, start_time: newInfo.startTime, end_time: newInfo.endTime}) - .where("id", newInfo.id) - } catch (error: any) { - throw new CustomError(error.statusCode, error.message) - } - } } diff --git a/src/error/ShowError.ts b/src/error/ShowError.ts index 7bf0649..53fe745 100644 --- a/src/error/ShowError.ts +++ b/src/error/ShowError.ts @@ -20,7 +20,7 @@ export class WeekDay extends CustomError { export class InvalidWeekDay extends CustomError { constructor () { - super (422, "The week day can only be Sexta, sábado or Domingo.") + super (422, "The week day can only be friday, saturday or sunday.") } } @@ -43,7 +43,11 @@ export class EndTime extends CustomError { } - +export class NoShows extends CustomError { + constructor (){ + super (422, "No Shows") + } +} diff --git a/src/index.ts b/src/index.ts index 4aea4e1..3640c6b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,4 +7,4 @@ import { userRouter } from "./routes/userRouter" app.use("/users", userRouter) app.use("/bands", bandRouter) -app.use("/show", showRouter) \ No newline at end of file +app.use("/show", showRouter) diff --git a/src/model/CreateShowTime.ts b/src/model/CreateShowTime.ts index 73c5cfa..d3d41d2 100644 --- a/src/model/CreateShowTime.ts +++ b/src/model/CreateShowTime.ts @@ -1,11 +1,12 @@ -import { DuplicateConcert, InvalidConcertDuration, InvalidConcertTime, InvalidEndTime, InvalidStartTime } from "../error/ConcertErrors" +import { InvalidStartTime, EndTime } from "../error/ShowError" import { CustomError } from "../error/BaseError" - +import { ShowsDatabase } from "../data/ShowDataBase" import { ShowsRepository } from "./ShowRepository" +import { ShowTimeDTO } from "./ShowTimeDTO" -export class CheckConcertTime implements ICheckConcertTime { - constructor (private concertDatabase: ShowsRepository) {} +export class CreateShowTime implements ShowTimeDTO { + constructor (private showsDatabase: ShowsRepository) {} public startTimeFormat (startTime: string): void { try { @@ -23,4 +24,25 @@ export class CheckConcertTime implements ICheckConcertTime { } catch (error: any) { throw new CustomError(error.statusCode, error.message) } - } \ No newline at end of file + } + + + public endTimeFormat (endTime: string): void { + try { + const endTimeArray = endTime.split(":") + + if (endTimeArray.length < 3) { + throw new EndTime() + } + if (Number(endTimeArray[0]) < 9 || Number(endTimeArray[0]) > 23) { + throw new EndTime() + } + if (endTimeArray[1] !== "00" || endTimeArray[2] !== "00") { + throw new EndTime() + } + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } + +} \ No newline at end of file diff --git a/src/model/Show.ts b/src/model/Show.ts index 6180c6a..378aeed 100644 --- a/src/model/Show.ts +++ b/src/model/Show.ts @@ -35,17 +35,3 @@ export interface outputGetAllShowDTO { music_genre: string } -export interface IUpdateShowDTO { - id: string, - weekDay: string, - startTime: string, - endTime: string, - token: string -} - -export interface updateShowDatabaseDTO { - id: string, - weekDay: string, - startTime: string, - endTime: string -} \ No newline at end of file diff --git a/src/model/ShowRepository.ts b/src/model/ShowRepository.ts index 8571319..e84aa0f 100644 --- a/src/model/ShowRepository.ts +++ b/src/model/ShowRepository.ts @@ -1,4 +1,4 @@ -import { ShowDTO, updateShowDatabaseDTO, outputGetAllShowDTO } from "./Show" +import { ShowDTO, outputGetAllShowDTO } from "./Show" export interface ShowsRepository { @@ -6,5 +6,5 @@ export interface ShowsRepository { searchShows (weekDay: string, column: string, value: string): Promise getAllShows (weekDay: string): Promise getShowsById (id: string): Promise - updateShows (newInfo: updateShowDatabaseDTO): Promise + } \ No newline at end of file diff --git a/src/model/ShowTimeDTO.ts b/src/model/ShowTimeDTO.ts new file mode 100644 index 0000000..aef35de --- /dev/null +++ b/src/model/ShowTimeDTO.ts @@ -0,0 +1,7 @@ + +export interface ShowTimeDTO + { + startTimeFormat (startTime: string): void + endTimeFormat (endTime: string): void + +} \ No newline at end of file diff --git a/src/routes/showRouter.ts b/src/routes/showRouter.ts index 4f6795c..af3e89f 100644 --- a/src/routes/showRouter.ts +++ b/src/routes/showRouter.ts @@ -1,14 +1,20 @@ -import { Request, Response } from "express" import express from "express" import { ShowBusiness } from "../business/ShowBusiness" import { ShowController } from "../controller/ShowController" -import { ShowDataBase } from "../data/ShowDataBase" +import { BandCreateDatabase } from "../data/BandCreateDataBase" +import { ShowsDatabase } from "../data/ShowDataBase" +import { Authenticator } from "../services/Authenticator" +import { IdGenerator } from "../services/IdGenerator" +import { CreateShowTime } from "../model/CreateShowTime" + export const showRouter = express.Router() -const showDatabase = new ShowDataBase() -const showBusiness = new ShowBusiness() +const showsDatabase = new ShowsDatabase() +const bandDatabase = new BandCreateDatabase() +const showBusiness = new ShowBusiness(showsDatabase, bandDatabase, new Authenticator(), new IdGenerator(), new CreateShowTime(showsDatabase)) const showController = new ShowController(showBusiness) -showRouter.post("/createShow", (req, res) => showController.createShow(req, res)) +showRouter.post("/create", (req, res) => showController.createConcert(req, res)) +showRouter.get("/", (req, res) => showController.getAllShows(req, res)) \ No newline at end of file From 04efb6eeb309c27010afbad938ba4dda600efc75 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Thu, 16 Mar 2023 10:21:03 +0000 Subject: [PATCH 20/32] Debugando Pt5 e 6 --- package.json | 3 ++- tables.sql | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index c12240d..1ad7b5f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "dev": "ts-node-dev ./src/index.ts", - "start": "tsc && node ./build/index.js" + "start": "tsc && node ./build/index.js", + "migrations": "ts-node-dev ./src/createConnection/migrations.ts" }, "keywords": [ "api", diff --git a/tables.sql b/tables.sql index 2cf2cb2..ea9743c 100644 --- a/tables.sql +++ b/tables.sql @@ -12,12 +12,12 @@ CREATE TABLE IF NOT EXISTS Bands_Name ( ### Query que cria a tabela de Shows CREATE TABLE IF NOT EXISTS Table_Shows ( - id VARCHAR(255) PRIMARY KEY, - week_day VARCHAR(255) NOT NULL, - start_time INT NOT NULL, - end_time INT NOT NULL, - band_id VARCHAR(255) NOT NULL, - FOREIGN KEY(band_id) REFERENCES Bands_Name(id) + id CHAR(36) NOT NULL PRIMARY KEY, + week_day VARCHAR(30) NOT NULL, + start_time TIME(0) NOT NULL, + end_time TIME(0) NOT NULL, + band_id CHAR(36) NOT NULL, + FOREIGN KEY(band_id) REFERENCES Bands_Name(id) ); ### Query que cria tabela de usuários From c25a4abaeb32f135f576f94d1318156bdfd5291b Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Thu, 16 Mar 2023 10:23:49 +0000 Subject: [PATCH 21/32] Debug pt 5 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1ad7b5f..54a9f17 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "index.js", "scripts": { "dev": "ts-node-dev ./src/index.ts", - "start": "tsc && node ./build/index.js", - "migrations": "ts-node-dev ./src/createConnection/migrations.ts" + "start": "tsc && node ./build/index.js" + }, "keywords": [ "api", From 946051f0b839154b4da09e60eda38d3d00d59261 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Thu, 16 Mar 2023 14:23:10 +0000 Subject: [PATCH 22/32] Render --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 54a9f17..c12240d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "scripts": { "dev": "ts-node-dev ./src/index.ts", "start": "tsc && node ./build/index.js" - }, "keywords": [ "api", From db5bf14755c08ae8fce1c706416633a2096bc0d1 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo Date: Fri, 17 Mar 2023 16:49:05 -0300 Subject: [PATCH 23/32] Pt6 --- requests.rest | 35 +++++++++++------- src/business/ShowBusiness.ts | 63 +++++++++++++++++++++++++++++--- src/controller/ShowController.ts | 25 +++++++++++-- src/data/ShowDataBase.ts | 11 +++++- src/error/ShowError.ts | 6 ++- src/model/CreateShowTime.ts | 21 ++++++++++- src/model/Show.ts | 14 +++++++ src/model/ShowRepository.ts | 3 +- tables.sql | 17 +-------- 9 files changed, 152 insertions(+), 43 deletions(-) diff --git a/requests.rest b/requests.rest index 99fe80b..1514598 100644 --- a/requests.rest +++ b/requests.rest @@ -4,7 +4,7 @@ POST http://localhost:3300/users/signup Content-Type: application/json { - "email": "maur9@mauricio.com", + "email": "maurilson@mauricio.com", "name": "Maurilio", "password": "12345678", "role": "ADMIN" @@ -16,39 +16,46 @@ POST http://localhost:3300/users/login Content-Type: application/json { - "email": "maur9@mauricio.com", + "email": "maurilson@mauricio.com", "password": "12345678" } ### Criar Banda POST http://localhost:3300/bands/create -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTgxOSwiZXhwIjoxNjc4OTE1NDE5fQ.P078iJJ20RAIQCXCQ5KX0RMRsot0r_nH_F92Wtx-LIU +Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU Content-Type: application/json { - "name": "Nirvana", + "name": "Queen", "musicGenre": "Rock", - "responsible": "Kurt" + "responsible": "Freddie" } ### Ver Bandas Criadas -GET http://localhost:3300/bands/info?name=Nirvana -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTgxOSwiZXhwIjoxNjc4OTE1NDE5fQ.P078iJJ20RAIQCXCQ5KX0RMRsot0r_nH_F92Wtx-LIU +GET http://localhost:3300/bands/info?name=Queen +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU Content-Type: application/json ### Criar Shows POST http://localhost:3300/show/create -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImIxOTI1MmNhLTg4ZDktNGEyOC04MGU5LTBiZDcyNGNiNWJhYiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3ODkxMTgxOSwiZXhwIjoxNjc4OTE1NDE5fQ.P078iJJ20RAIQCXCQ5KX0RMRsot0r_nH_F92Wtx-LIU +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU Content-Type: application/json { - "bandId" : "d4c43186-52ed-4f24-8dba-382a8f742378", - "weekDay": "friday", - "startTime": "8:00", - "endTime": "10:00", - "id" : "d4c43186-52ed-4f24-8dba-382a8f742378" -} + "bandId" : "c05fb35f-1459-4ccb-8861-96221b7d201e", + "weekDay": "sunday", + "startTime": "9:00:00", + "endTime": "10:00:00" + + } + + + ### Retorna os shows +GET http://localhost:3300/show?weekDay=friday +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU +Content-Type: application/json + diff --git a/src/business/ShowBusiness.ts b/src/business/ShowBusiness.ts index 3a9dea5..8a65802 100644 --- a/src/business/ShowBusiness.ts +++ b/src/business/ShowBusiness.ts @@ -1,5 +1,5 @@ -import { ICreateShowtDTO, ShowDTO, outputGetAllShowDTO, IGetAllShowDTO} from "../model/Show"; +import { ICreateShowtDTO, ShowDTO, outputGetAllShowDTO, IGetAllShowDTO, UShowDatabaseDTO, inputUShowDTO} from "../model/Show"; import { Authenticator } from "../services/Authenticator"; import { IdGenerator } from "../services/IdGenerator"; import { IdAuthenticator } from "../model/IdAuthenticator"; @@ -10,7 +10,7 @@ import { GeneratorId } from "../model/GeneratorId"; import { ShowsRepository } from "../model/ShowRepository"; import { BandRepository } from "../model/BandRepository"; import { UserRole } from "../model/User"; -import { WeekDay, StartTime, EndTime, InvalidWeekDay, NoShows } from "../error/ShowError"; +import { WeekDay, StartTime, EndTime, InvalidWeekDay, NoShows, ShowtId } from "../error/ShowError"; import { Unauthorized } from "../error/BaseError"; import { CreateShowTime } from "../model/CreateShowTime"; @@ -57,12 +57,13 @@ export class ShowBusiness { await this.checkUp.startTimeFormat(input.startTime) await this.checkUp.endTimeFormat(input.endTime) + await this.checkUp.showTimeCheck(input.startTime, input.endTime) + const showId = this.idGenerator.generateId() + const newShow = new ShowDTO(showId, input.weekDay, input.startTime, input.endTime, input.bandId) + await this.showDatabase.createShow(newShow) - const concertId = this.idGenerator.generateId() - const newConcert = new ShowDTO(concertId, input.weekDay, input.startTime, input.endTime, input.bandId) - await this.showDatabase.createShow(newConcert) - + } catch (error: any) { throw new CustomError(error.statusCode, error.message) } @@ -94,4 +95,54 @@ export class ShowBusiness { throw new CustomError(error.statusCode, error.message) } } + async updateConcert (input: inputUShowDTO): Promise { + try { + if (!input.token) { + throw new MissingToken() + } + if (input.id === ":id") { + throw new ShowtId() + } + if (input.weekDay && input.weekDay.toLowerCase() !== "friday" && input.weekDay.toLowerCase() !== "saturday" && input.weekDay.toLowerCase() !== "sunday") { + throw new InvalidWeekDay() + } + + const {id, role} = await this.authorization.getTokenData(input.token) + if (role.toUpperCase() !== UserRole.ADMIN) { + throw new Unauthorized() + } + + const getShow = await this.showDatabase.getShowsById(input.id) + if (!getShow) { + throw new ShowtId() + } + + if (!input.weekDay) { + input.weekDay = getShow.week_day + } + if (!input.startTime) { + input.startTime = getShow.start_time + } + if (!input.endTime) { + input.endTime = getShow.end_time + } + + await this.checkUp.startTimeFormat(input.startTime) + await this.checkUp.endTimeFormat(input.endTime) + await this.checkUp.showTimeCheck(input.startTime, input.endTime) + + + const newTime: UShowDatabaseDTO = { + id: input.id, + weekDay: input.weekDay, + startTime: input.startTime, + endTime: input.endTime + } + + await this.showDatabase.updateShow(newTime) + + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } } \ No newline at end of file diff --git a/src/controller/ShowController.ts b/src/controller/ShowController.ts index 752d07f..246159f 100644 --- a/src/controller/ShowController.ts +++ b/src/controller/ShowController.ts @@ -1,10 +1,10 @@ import { ShowBusiness } from "../business/ShowBusiness" import { Request, Response } from "express" -import { ICreateShowtDTO, IGetAllShowDTO } from "../model/Show" +import { ICreateShowtDTO, IGetAllShowDTO, inputUShowDTO } from "../model/Show" export class ShowController { - constructor (private concertBusiness: ShowBusiness) {} + constructor (private showBusiness: ShowBusiness) {} async createConcert (req: Request, res: Response): Promise { try { @@ -16,7 +16,7 @@ export class ShowController { token: req.headers.authorization as string } - await this.concertBusiness.createShow(input) + await this.showBusiness.createShow(input) res.status(201).send("Show created successfully!") } catch (error: any) { @@ -32,11 +32,28 @@ export class ShowController { token: req.headers.authorization as string } - const result = await this.concertBusiness.getAllShows(input) + const result = await this.showBusiness.getAllShows(input) res.status(200).send(result) } catch (error: any) { res.status(error.statusCode || 400).send(error.message || error.sqlMessage) } } + async showConcert (req: Request, res: Response): Promise { + try { + const input: inputUShowDTO = { + id: req.params.id, + weekDay: req.body.weekDay, + startTime: req.body.startTime, + endTime: req.body.endTime, + token: req.headers.authorization as string + } + + await this.showBusiness.updateConcert(input) + res.status(201).send("Show updated successfully!") + + } catch (error: any) { + res.status(error.statusCode || 400).send(error.message || error.sqlMessage) + } + } } \ No newline at end of file diff --git a/src/data/ShowDataBase.ts b/src/data/ShowDataBase.ts index 1db0adc..a3dd4f3 100644 --- a/src/data/ShowDataBase.ts +++ b/src/data/ShowDataBase.ts @@ -1,5 +1,5 @@ import { CustomError } from "../error/BaseError" -import { ShowDTO,outputGetAllShowDTO } from "../model/Show" +import { ShowDTO,outputGetAllShowDTO,UShowDatabaseDTO } from "../model/Show" import { ShowsRepository } from "../model/ShowRepository" import { BaseDatabase } from "./BaseDatabase" @@ -52,4 +52,13 @@ export class ShowsDatabase extends BaseDatabase implements ShowsRepository { } + async updateShow (newInfo: UShowDatabaseDTO): Promise { + try { + await BaseDatabase.connection(this.TABLE_NAME) + .update({week_day: newInfo.weekDay, start_time: newInfo.startTime, end_time: newInfo.endTime}) + .where("id", newInfo.id) + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } } diff --git a/src/error/ShowError.ts b/src/error/ShowError.ts index 53fe745..33976d2 100644 --- a/src/error/ShowError.ts +++ b/src/error/ShowError.ts @@ -41,7 +41,11 @@ export class EndTime extends CustomError { super (422, "Provide the end time.") } } - +export class InvalidShowTime extends CustomError { + constructor () { + super (422, "Has to be in the max 1hr.") + } +} export class NoShows extends CustomError { constructor (){ diff --git a/src/model/CreateShowTime.ts b/src/model/CreateShowTime.ts index d3d41d2..080a12f 100644 --- a/src/model/CreateShowTime.ts +++ b/src/model/CreateShowTime.ts @@ -1,10 +1,11 @@ -import { InvalidStartTime, EndTime } from "../error/ShowError" +import { InvalidStartTime, EndTime, InvalidShowTime } from '../error/ShowError'; import { CustomError } from "../error/BaseError" import { ShowsDatabase } from "../data/ShowDataBase" import { ShowsRepository } from "./ShowRepository" import { ShowTimeDTO } from "./ShowTimeDTO" + export class CreateShowTime implements ShowTimeDTO { constructor (private showsDatabase: ShowsRepository) {} @@ -45,4 +46,22 @@ export class CreateShowTime implements ShowTimeDTO { } } + public showTimeCheck (startTime: string, endTime: string): void { + try { + const startTimeArray = startTime.split(":") + const endTimeArray = endTime.split(":") + + if (Number(endTimeArray[0]) < Number(startTimeArray[0])) { + throw new InvalidShowTime() + } + if (Number(endTimeArray[0]) === Number(startTimeArray[0])) { + throw new InvalidShowTime() + } + if (Number(endTimeArray[0]) - Number(startTimeArray[0]) > 2) { + throw new InvalidShowTime() + } + } catch (error: any) { + throw new CustomError(error.statusCode, error.message) + } + } } \ No newline at end of file diff --git a/src/model/Show.ts b/src/model/Show.ts index 378aeed..e1710aa 100644 --- a/src/model/Show.ts +++ b/src/model/Show.ts @@ -35,3 +35,17 @@ export interface outputGetAllShowDTO { music_genre: string } +export interface inputUShowDTO { + id: string, + weekDay: string, + startTime: string, + endTime: string, + token: string +} + +export interface UShowDatabaseDTO { + id: string, + weekDay: string, + startTime: string, + endTime: string +} \ No newline at end of file diff --git a/src/model/ShowRepository.ts b/src/model/ShowRepository.ts index e84aa0f..47c6ab5 100644 --- a/src/model/ShowRepository.ts +++ b/src/model/ShowRepository.ts @@ -1,4 +1,4 @@ -import { ShowDTO, outputGetAllShowDTO } from "./Show" +import { ShowDTO, outputGetAllShowDTO, UShowDatabaseDTO} from "./Show" export interface ShowsRepository { @@ -6,5 +6,6 @@ export interface ShowsRepository { searchShows (weekDay: string, column: string, value: string): Promise getAllShows (weekDay: string): Promise getShowsById (id: string): Promise + updateShow (newInfo: UShowDatabaseDTO): Promise } \ No newline at end of file diff --git a/tables.sql b/tables.sql index ea9743c..7ee3456 100644 --- a/tables.sql +++ b/tables.sql @@ -1,4 +1,4 @@ --- Active: 1676582098331@@35.226.146.116@3306@jbl-4416547-ricardo-morais +-- Active: 1676323408280@@35.226.146.116@3306@jbl-4416472-mauricio-toledo ### Query que cria a tabela de Bandas CREATE TABLE IF NOT EXISTS Bands_Name ( @@ -29,17 +29,4 @@ CREATE TABLE IF NOT EXISTS Lama_Users ( role VARCHAR(255) NOT NULL DEFAULT "NORMAL" ); -### - -DROP TABLE `NOME_TABELA_BANDAS`, `NOME_TABELA_SHOWS`; - -### - -SELECT * FROM `Lama_Users`; -<<<<<<< HEAD -======= - -### - -SELECT * FROM `Table_Shows`; ->>>>>>> 6fd8418e0205b5c84fbd61ca69e6626fb5529da5 +DROP TABLE \ No newline at end of file From 9f2d4c60a54a258cb409c2f51b3440b3ec27687d Mon Sep 17 00:00:00 2001 From: Ricardo_Barros Date: Fri, 17 Mar 2023 23:04:20 -0300 Subject: [PATCH 24/32] feat: Readme --- README.md | 72 ++++++++++++++++++++++++++++++++++++++++++++------- requests.rest | 30 ++++++++++----------- src/app.ts | 4 +-- tables.sql | 9 +++++-- 4 files changed, 87 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 68af457..903e2d2 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,65 @@ -# Labenu Music Awards -Como você deve saber muito bem, o nosso querido chefinho Astrodev é uma pessoa com Networking incrível e ele conhece vários artistas estrelados. Além disso, ele também é um grande ~~megalomaníaco~~ visionário e está planejando fazer um grande evento: o **LAMA**, *Labenu Musical Awards*, um festival com várias bandas famosas para a formatura da sua turma e, no final, vocês podem eleger a banda que mais gostaram! Entretanto, na opinião dele, vocês só serão merecedores se entregarem um sistema impecável que permita o gerenciamento completo desses shows. +![Screenshot_1](https://user-images.githubusercontent.com/45580434/79641791-06e1c100-8170-11ea-8ecf-b6c889805d55.png) +
+ + +## :memo: Descrição +Projeto desenvolvido como didática de back-end para as turmas JBL LABENU com conteúdos que englobam o universo da criação de uma API com a temática de um sistema de gerenciamento básico da organizaçãode labenu. + +## 📌 Link Documentação Postman +[Doc_Postman](https://documenter.getpostman.com/view/22376520/2s93JzKzpB) + +## 📦 Link Deploy Render + + +## 👩🏾Pessoas Desenvolvedoras do Projeto + +| [
Ricardo Barros](https://github.com/Ricardoteleco) | [
Mauricio Luiz de toledo](https://github.com/mlt3800)| +| :---: | :---: | :---: | + +## 🎤 LAMA + +implementação de uma API para cadastro de shows e venda de tickets dos mesmos na plataforma lama. + + +## 📦 link da API + +https://lama-macedo.herokuapp.com/ + +## 🚀 Começando + +para usar a API você pode acessar o link acima ou instalar em seu computador as dependencias e rodar localmente na sua máquina conforme descrito abaixo. + +## 🔧 Instalação + +para instalar as dependências digite no terminal: + +``` +npm install +``` + +para rodar a API na porta 3003 digite: + +``` +npm run dev +``` + +para obter os dados digite no navegador o link da requisição que está na documentação e para fazer requisiçôes que criam ou alteram via body utilize o postman ou app similares. + + +## 🛠️ Construído com + +* [nodeJS] +* [express] +* [dotenv] +* [cors] +* [knex] +* [typscript] +* [javaScript] +* [jsonwebtoken] +* [uuid] +* [mysql] +* [jest] +* API desenvolvida com paradigma orientado a objetos. + -Para isso já deixamos algumas tabelas prontas para vocês não precisarem se preocupar com a modelagem do banco. Deixamos também um template do projeto já com a estrutura da parte de usuários. Vocês podem usá-las a vontade, mas, se quiser fazer do zero sem esse auxílio, também pode. -Criar Usuario : ok -Login: Ok -Criar banda : ok -Procurar banda : ok -Criar show : ok fornecer id da banda -procurar show: ok fornecer id diff --git a/requests.rest b/requests.rest index 1514598..f9e0c9f 100644 --- a/requests.rest +++ b/requests.rest @@ -1,28 +1,28 @@ ### Criar Usuário -POST http://localhost:3300/users/signup +POST http://localhost:3003/users/signup Content-Type: application/json { - "email": "maurilson@mauricio.com", - "name": "Maurilio", + "email": "ricardo@exemplo.com", + "name": "Ricardo", "password": "12345678", "role": "ADMIN" } ### Login -POST http://localhost:3300/users/login +POST http://localhost:3003/users/login Content-Type: application/json { - "email": "maurilson@mauricio.com", + "email": "ricardo@exemplo.com", "password": "12345678" } ### Criar Banda -POST http://localhost:3300/bands/create -Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU +POST http://localhost:3003/bands/create +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI1NWVmM2ZiLTFmZTAtNGE1MC05YWE5LTBlMmUyYzQyMmUwOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTEwMjQ0NiwiZXhwIjoxNjc5MTA2MDQ2fQ.lTdS5O9jXTSkYeIBd8x1SoRewklxTAb_KhbnpwKujJo Content-Type: application/json { @@ -33,29 +33,29 @@ Content-Type: application/json } ### Ver Bandas Criadas -GET http://localhost:3300/bands/info?name=Queen -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU +GET http://localhost:3003/bands/info?name=Queen +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI1NWVmM2ZiLTFmZTAtNGE1MC05YWE5LTBlMmUyYzQyMmUwOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTEwMjQ0NiwiZXhwIjoxNjc5MTA2MDQ2fQ.lTdS5O9jXTSkYeIBd8x1SoRewklxTAb_KhbnpwKujJo Content-Type: application/json ### Criar Shows -POST http://localhost:3300/show/create -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU +POST http://localhost:3003/show/create +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI1NWVmM2ZiLTFmZTAtNGE1MC05YWE5LTBlMmUyYzQyMmUwOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTEwMjQ0NiwiZXhwIjoxNjc5MTA2MDQ2fQ.lTdS5O9jXTSkYeIBd8x1SoRewklxTAb_KhbnpwKujJo Content-Type: application/json { - "bandId" : "c05fb35f-1459-4ccb-8861-96221b7d201e", + "bandId" : "eb59dde0-a670-438d-af1c-500de7940452", "weekDay": "sunday", "startTime": "9:00:00", "endTime": "10:00:00" - } +} ### Retorna os shows -GET http://localhost:3300/show?weekDay=friday -Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjlmNzlhZmQ0LWQ0YTYtNGZlNS04OTg2LWE4ODc1MDllZTliZiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTA4MjEwNiwiZXhwIjoxNjc5MDg1NzA2fQ.vrnc5_FuZqttUZH_rOC5xPv5VzQxCYMn4ALtSeSslEU +GET http://localhost:3003/show?weekDay=friday +Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI1NWVmM2ZiLTFmZTAtNGE1MC05YWE5LTBlMmUyYzQyMmUwOCIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY3OTEwMzIxMSwiZXhwIjoxNjc5MTA2ODExfQ.HOlvmEMFejMUhcsGHgc44LNRuo5q3NsJvi7EadNoCec Content-Type: application/json diff --git a/src/app.ts b/src/app.ts index 2f59361..29ec065 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,6 @@ export const app = express() app.use(express.json()) app.use(cors()) -app.listen(process.env.PORT || 3300, () => { - console.log(`Server is running on port ${process.env.PORT || 3000}`) +app.listen(process.env.PORT || 3003, () => { + console.log(`Server is running on port ${process.env.PORT || 3003}`) }) \ No newline at end of file diff --git a/tables.sql b/tables.sql index 7ee3456..b9eb922 100644 --- a/tables.sql +++ b/tables.sql @@ -1,4 +1,4 @@ --- Active: 1676323408280@@35.226.146.116@3306@jbl-4416472-mauricio-toledo +-- Active: 1676582098331@@35.226.146.116@3306@jbl-4416547-ricardo-morais ### Query que cria a tabela de Bandas CREATE TABLE IF NOT EXISTS Bands_Name ( @@ -29,4 +29,9 @@ CREATE TABLE IF NOT EXISTS Lama_Users ( role VARCHAR(255) NOT NULL DEFAULT "NORMAL" ); -DROP TABLE \ No newline at end of file +### +DROP TABLE `Lama_Users`, `Bands_Name`, `Table_Shows`; + +### + +SELECT * from `Bands_Name`; \ No newline at end of file From 5d3c04613d5a6b4debc2f6e15d921a1304f11b22 Mon Sep 17 00:00:00 2001 From: Ricardo Barros <102339228+Ricardoteleco@users.noreply.github.com> Date: Fri, 17 Mar 2023 23:19:18 -0300 Subject: [PATCH 25/32] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 903e2d2..18f98a3 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## :memo: Descrição -Projeto desenvolvido como didática de back-end para as turmas JBL LABENU com conteúdos que englobam o universo da criação de uma API com a temática de um sistema de gerenciamento básico da organizaçãode labenu. +implementação de uma API para cadastro de bandas e shows para a e evento LAMA, Labenu Musical Awards. ## 📌 Link Documentação Postman [Doc_Postman](https://documenter.getpostman.com/view/22376520/2s93JzKzpB) @@ -13,8 +13,8 @@ Projeto desenvolvido como didática de back-end para as turmas JBL LABENU com co ## 👩🏾Pessoas Desenvolvedoras do Projeto -| [
Ricardo Barros](https://github.com/Ricardoteleco) | [
Mauricio Luiz de toledo](https://github.com/mlt3800)| -| :---: | :---: | :---: | +| [
Ricardo Barros](https://github.com/Ricardoteleco) | [
Mauricio Luiz de toledo](https://github.com/mlt3800)| + ## 🎤 LAMA From f194980c205da3778d3875ceca886f172f4cfd24 Mon Sep 17 00:00:00 2001 From: Ricardo Barros <102339228+Ricardoteleco@users.noreply.github.com> Date: Fri, 17 Mar 2023 23:23:06 -0300 Subject: [PATCH 26/32] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18f98a3..86fe51a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## :memo: Descrição -implementação de uma API para cadastro de bandas e shows para a e evento LAMA, Labenu Musical Awards. +implementação de uma API para cadastro de bandas e shows para o evento LAMA, Labenu Musical Awards. ## 📌 Link Documentação Postman [Doc_Postman](https://documenter.getpostman.com/view/22376520/2s93JzKzpB) From 7fcaecd4de68178dc12af67e70f5c68e19c7c52c Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Sat, 18 Mar 2023 09:26:30 +0000 Subject: [PATCH 27/32] Readme --- src/business/ShowBusiness.ts | 2 +- src/controller/ShowController.ts | 4 ++-- src/error/ShowError.ts | 2 +- src/routes/showRouter.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/business/ShowBusiness.ts b/src/business/ShowBusiness.ts index 8a65802..5e38b28 100644 --- a/src/business/ShowBusiness.ts +++ b/src/business/ShowBusiness.ts @@ -95,7 +95,7 @@ export class ShowBusiness { throw new CustomError(error.statusCode, error.message) } } - async updateConcert (input: inputUShowDTO): Promise { + async updateShow(input: inputUShowDTO): Promise { try { if (!input.token) { throw new MissingToken() diff --git a/src/controller/ShowController.ts b/src/controller/ShowController.ts index 246159f..5d871cc 100644 --- a/src/controller/ShowController.ts +++ b/src/controller/ShowController.ts @@ -6,7 +6,7 @@ import { ICreateShowtDTO, IGetAllShowDTO, inputUShowDTO } from "../model/Show" export class ShowController { constructor (private showBusiness: ShowBusiness) {} - async createConcert (req: Request, res: Response): Promise { + async createShow (req: Request, res: Response): Promise { try { const input: ICreateShowtDTO = { weekDay: req.body.weekDay, @@ -49,7 +49,7 @@ export class ShowController { token: req.headers.authorization as string } - await this.showBusiness.updateConcert(input) + await this.showBusiness.updateShow(input) res.status(201).send("Show updated successfully!") } catch (error: any) { diff --git a/src/error/ShowError.ts b/src/error/ShowError.ts index 33976d2..2814676 100644 --- a/src/error/ShowError.ts +++ b/src/error/ShowError.ts @@ -55,7 +55,7 @@ export class NoShows extends CustomError { -export class DuplicateConcert extends CustomError { +export class DuoShow extends CustomError { constructor () { super (422, "There is a Show already registered .") } diff --git a/src/routes/showRouter.ts b/src/routes/showRouter.ts index af3e89f..d93be61 100644 --- a/src/routes/showRouter.ts +++ b/src/routes/showRouter.ts @@ -16,5 +16,5 @@ const bandDatabase = new BandCreateDatabase() const showBusiness = new ShowBusiness(showsDatabase, bandDatabase, new Authenticator(), new IdGenerator(), new CreateShowTime(showsDatabase)) const showController = new ShowController(showBusiness) -showRouter.post("/create", (req, res) => showController.createConcert(req, res)) +showRouter.post("/create", (req, res) => showController.createShow(req, res)) showRouter.get("/", (req, res) => showController.getAllShows(req, res)) \ No newline at end of file From dfd5013d4e357c9cc4e5db2e2f57f2c70c56867c Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Sat, 18 Mar 2023 09:34:34 +0000 Subject: [PATCH 28/32] Render --- package-lock.json | 17 ++++++++--------- package.json | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6687a64..8096c9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "knex": "^2.4.2", "mysql": "^2.18.1", "ts-node-dev": "^2.0.0", + "typescript": "^5.0.2", "uuid": "^9.0.0" }, "devDependencies": { @@ -1640,16 +1641,15 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true, + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "node_modules/unpipe": { @@ -2932,10 +2932,9 @@ } }, "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==" }, "unpipe": { "version": "1.0.0", diff --git a/package.json b/package.json index c12240d..c45db87 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "knex": "^2.4.2", "mysql": "^2.18.1", "ts-node-dev": "^2.0.0", + "typescript": "^5.0.2", "uuid": "^9.0.0" }, "devDependencies": { From 123036ba9875b973c580fa7977f686ac40c8f8e9 Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Sat, 18 Mar 2023 06:51:01 -0300 Subject: [PATCH 29/32] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 86fe51a..822dec4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ implementação de uma API para cadastro de bandas e shows para o evento LAMA, L [Doc_Postman](https://documenter.getpostman.com/view/22376520/2s93JzKzpB) ## 📦 Link Deploy Render - +https://lama-0ddu.onrender.com ## 👩🏾Pessoas Desenvolvedoras do Projeto From dea6b557b71ef407763b6a4a833a55b15a2b571c Mon Sep 17 00:00:00 2001 From: Mauricio Luiz de toledo <102395706+mlt3800@users.noreply.github.com> Date: Sat, 18 Mar 2023 08:41:05 -0300 Subject: [PATCH 30/32] Update package.json Add outros devs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c45db87..850cb64 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "api", "LAMA" ], - "author": "Israel,Andréa,Júnior e Fay", + "author": "Israel,Andréa,Júnior,Fay, Mauricio e Ricardo", "license": "ISC", "dependencies": { "@types/bcryptjs": "^2.4.2", From 651d0bc83f66c43d9f2ef8ee9399f557bdbda43f Mon Sep 17 00:00:00 2001 From: Ricardo Barros <102339228+Ricardoteleco@users.noreply.github.com> Date: Mon, 20 Mar 2023 22:27:40 -0300 Subject: [PATCH 31/32] Update README.md --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 822dec4..a33b363 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,11 @@ implementação de uma API para cadastro de bandas e shows para o evento LAMA, L ## 📦 Link Deploy Render https://lama-0ddu.onrender.com -## 👩🏾Pessoas Desenvolvedoras do Projeto - -| [
Ricardo Barros](https://github.com/Ricardoteleco) | [
Mauricio Luiz de toledo](https://github.com/mlt3800)| - - -## 🎤 LAMA +## 👩🏾Pessoas Desenvolvedoras do Projeto +

Mauricio Luiz de toledo

(https://github.com/mlt3800) +

Ricardo Barros

(https://github.com/Ricardoteleco) + +## 🎤 LAMA implementação de uma API para cadastro de shows e venda de tickets dos mesmos na plataforma lama. From 331eb567009b49c96c8bb9de1e7c91a347cd8f01 Mon Sep 17 00:00:00 2001 From: Ricardo Barros <102339228+Ricardoteleco@users.noreply.github.com> Date: Wed, 22 Mar 2023 20:12:53 -0300 Subject: [PATCH 32/32] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a33b363..8ebcc70 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,6 @@ para obter os dados digite no navegador o link da requisição que está na docu * [jsonwebtoken] * [uuid] * [mysql] -* [jest] * API desenvolvida com paradigma orientado a objetos.