diff --git a/.env.dev b/.env.dev index 312467e7..6c27bb37 100644 --- a/.env.dev +++ b/.env.dev @@ -1,15 +1,13 @@ # Set to production when deploying to production NODE_ENV=development -SET_COOKIE_SECURE=false -SET_COOKIE_SAME_SITE=Lax - -# Node.js server configuration -SERVER_PORT=8089 - # App APP_DEFAULT=AppKoa APP_PATH=/usr/app +APP_PORT=8089 +APP_SET_APP_PROXY=false +APP_SET_COOKIE_SECURE=false +APP_SET_COOKIE_SAME_SITE=Lax # Database configuration DB_HOST=db diff --git a/config/custom-environment-variables.json b/config/custom-environment-variables.json index d1ebf4e5..4c3ba5f1 100644 --- a/config/custom-environment-variables.json +++ b/config/custom-environment-variables.json @@ -1,14 +1,15 @@ { "env": "NODE_ENV", - "serverPort": "SERVER_PORT", - "setCookieSecure": "SET_COOKIE_SECURE", - "setCookieSameSite": "SET_COOKIE_SAME_SITE", "auth": { "authorization": "AUTHORIZATION" }, "app": { "default": "APP_DEFAULT", - "path": "APP_PATH" + "path": "APP_PATH", + "serverPort": "APP_PORT", + "setAppProxy": "APP_SET_APP_PROXY", + "setCookieSecure": "APP_SET_COOKIE_SECURE", + "setCookieSameSite": "APP_SET_COOKIE_SAME_SITE" }, "dbConfig": { "TypeORM": { diff --git a/config/default.json b/config/default.json index 30f4d5d8..ca38c425 100644 --- a/config/default.json +++ b/config/default.json @@ -1,11 +1,12 @@ { "env": "local", - "serverPort": 8089, - "setCookieSecure": false, - "setCookieSameSite": "Lax", "app": { "default": "AppKoa", - "path": "/usr/app" + "path": "/usr/app", + "serverPort": 8089, + "setAppProxy": false, + "setCookieSecure": false, + "setCookieSameSite": "Lax" }, "auth": { "authorization": false diff --git a/config/production.json b/config/production.json index 867c3b48..bb3e8fc3 100644 --- a/config/production.json +++ b/config/production.json @@ -1,9 +1,13 @@ { "env": "production", - "nodePath": "/app", - "serverPort": 80, - "setCookieSecure": true, - "setCookieSameSite": "None", + "app": { + "default": "AppKoa", + "path": "/usr/app", + "serverPort": 80, + "setAppProxy": true, + "setCookieSecure": false, + "setCookieSameSite": "None" + }, "auth": { "authorization": true } diff --git a/docker-compose.yml b/docker-compose.yml index 180dbe76..ccff4266 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.4' +version: '3.6' services: node: @@ -28,7 +28,7 @@ services: context: docker/mongo/ dockerfile: Dockerfile ports: - - "27017:27017" + - "27018:27017" networks: - experiencenet environment: diff --git a/nodemon.json b/nodemon.json index 9e388ac2..be5b915a 100644 --- a/nodemon.json +++ b/nodemon.json @@ -7,7 +7,7 @@ "watch": [ "src/*" ], - "exec": "pnpm build && node --inspect=0.0.0.0:9229 ./dist/src/index.js", + "exec": "pnpm build-tsc && node --inspect=0.0.0.0:9229 ./dist/src/index.js", "legacyWatch": true, "ext": "js,ts,json,hbs" } diff --git a/package.json b/package.json index 65564d7f..5e380230 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "dependencies": { "@deepkit/core": "1.0.1-alpha.77", "@deepkit/type": "1.0.1-alpha.85", + "@koa/cors": "^4.0.0", "@koa/multer": "^3.0.0", "@mikro-orm/core": "^5.6.2", "@mikro-orm/postgresql": "^5.6.2", @@ -61,7 +62,6 @@ "jwt-simple": "^0.5.6", "koa": "^2.13.4", "koa-bodyparser": "^4.3.0", - "koa-cors": "^0.0.16", "koa-helmet": "^6.1.0", "koa-qs": "^3.0.0", "koa-ratelimit": "^5.0.1", @@ -106,10 +106,10 @@ "@types/jwt-simple": "^0.5.33", "@types/koa": "^2.13.4", "@types/koa-bodyparser": "^4.3.7", - "@types/koa-cors": "^0.0.2", "@types/koa-hbs": "^1.0.7", "@types/koa-ratelimit": "^4.2.4", "@types/koa-router": "^7.4.4", + "@types/koa__cors": "^3.3.0", "@types/koa__multer": "^2.0.4", "@types/lodash": "^4.14.180", "@types/md5": "^2.3.2", @@ -136,10 +136,10 @@ "jest-environment-jsdom": "^28.1.3", "jest-environment-node": "^28.1.3", "lint-staged": "^13.1.0", - "madge": "^5.0.1", + "madge": "^6.0.0", "nodemon": "^2.0.20", "pg-mem": "^2.6.4", - "prettier": "^2.7.1", + "prettier": "^2.8.3", "rimraf": "^3.0.2", "supertest": "^6.3.0", "ts-node": "^10.9.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74482b8d..31a5fbe1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,7 @@ specifiers: '@commitlint/config-conventional': ^17.3.0 '@deepkit/core': 1.0.1-alpha.77 '@deepkit/type': 1.0.1-alpha.85 + '@koa/cors': ^4.0.0 '@koa/multer': ^3.0.0 '@mikro-orm/core': ^5.6.2 '@mikro-orm/postgresql': ^5.6.2 @@ -23,10 +24,10 @@ specifiers: '@types/jwt-simple': ^0.5.33 '@types/koa': ^2.13.4 '@types/koa-bodyparser': ^4.3.7 - '@types/koa-cors': ^0.0.2 '@types/koa-hbs': ^1.0.7 '@types/koa-ratelimit': ^4.2.4 '@types/koa-router': ^7.4.4 + '@types/koa__cors': ^3.3.0 '@types/koa__multer': ^2.0.4 '@types/lodash': ^4.14.180 '@types/md5': ^2.3.2 @@ -76,14 +77,13 @@ specifiers: jwt-simple: ^0.5.6 koa: ^2.13.4 koa-bodyparser: ^4.3.0 - koa-cors: ^0.0.16 koa-helmet: ^6.1.0 koa-qs: ^3.0.0 koa-ratelimit: ^5.0.1 koa-router: ^10.1.1 lint-staged: ^13.1.0 lodash: ^4.17.21 - madge: ^5.0.1 + madge: ^6.0.0 md5: ^2.3.0 minio: ^7.0.29 mongodb: ^3.6.0 @@ -95,7 +95,7 @@ specifiers: nodemon: ^2.0.20 pg-mem: ^2.6.4 pg-promise: ^10.11.1 - prettier: ^2.7.1 + prettier: ^2.8.3 promise-events: ^0.2.4 qs: ^6.11.0 reflect-metadata: ^0.1.13 @@ -116,6 +116,7 @@ specifiers: dependencies: '@deepkit/core': 1.0.1-alpha.77 '@deepkit/type': 1.0.1-alpha.85_mcay55ktffdozwll5wgb6oqvwq + '@koa/cors': 4.0.0 '@koa/multer': 3.0.2_multer@1.4.5-lts.1 '@mikro-orm/core': 5.6.2_2am4kkew32etkrit7wi5c4e3ze '@mikro-orm/postgresql': 5.6.2_@mikro-orm+core@5.6.2 @@ -143,7 +144,6 @@ dependencies: jwt-simple: 0.5.6 koa: 2.13.4 koa-bodyparser: 4.3.0 - koa-cors: 0.0.16 koa-helmet: 6.1.0 koa-qs: 3.0.0 koa-ratelimit: 5.0.1 @@ -188,10 +188,10 @@ devDependencies: '@types/jwt-simple': 0.5.33 '@types/koa': 2.13.5 '@types/koa-bodyparser': 4.3.10 - '@types/koa-cors': 0.0.2 '@types/koa-hbs': 1.0.7 '@types/koa-ratelimit': 4.2.4 '@types/koa-router': 7.4.4 + '@types/koa__cors': 3.3.0 '@types/koa__multer': 2.0.4 '@types/lodash': 4.14.191 '@types/md5': 2.3.2 @@ -218,10 +218,10 @@ devDependencies: jest-environment-jsdom: 28.1.3 jest-environment-node: 28.1.3 lint-staged: 13.1.0 - madge: 5.0.1 + madge: 6.0.0 nodemon: 2.0.20 pg-mem: 2.6.4_bp26lo6jhtof3heoovidy7fwyu - prettier: 2.8.0 + prettier: 2.8.3 rimraf: 3.0.2 supertest: 6.3.2 ts-node: 10.9.1_awa2wsr5thmg3i7jqycphctjfq @@ -2074,6 +2074,13 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 + /@koa/cors/4.0.0: + resolution: {integrity: sha512-Y4RrbvGTlAaa04DBoPBWJqDR5gPj32OOz827ULXfgB1F7piD1MB/zwn8JR2LAnvdILhxUbXbkXGWuNVsFuVFCQ==} + engines: {node: '>= 14.0.0'} + dependencies: + vary: 1.1.2 + dev: false + /@koa/multer/3.0.2_multer@1.4.5-lts.1: resolution: {integrity: sha512-Q6WfPpE06mJWyZD1fzxM6zWywaoo+zocAn2YA9QYz4RsecoASr1h/kSzG0c5seDpFVKCMZM9raEfuM7XfqbRLw==} engines: {node: '>= 8'} @@ -2636,12 +2643,6 @@ packages: '@types/koa': 2.13.5 dev: true - /@types/koa-cors/0.0.2: - resolution: {integrity: sha512-uNaDY26HUVO+2C6arK8ZFODs9mBjYprD8mlvkVe2bYdX9wzEeKtycVXPafXpUkePhMh4sffIMkhRDyedokG/QA==} - dependencies: - '@types/koa': 2.13.5 - dev: true - /@types/koa-hbs/1.0.7: resolution: {integrity: sha512-xs+IdwMkEQmhLB2PqqkNrQm/0l/Ewh3o56unQncFqPUj8RIl9RjPmpMV5E3SvE7l86kvt7A+Kd7QXKhJwqNJKg==} dependencies: @@ -2678,6 +2679,12 @@ packages: '@types/node': 18.11.18 dev: true + /@types/koa__cors/3.3.0: + resolution: {integrity: sha512-FUN8YxcBakIs+walVe3+HcNP+Bxd0SB8BJHBWkglZ5C1XQWljlKcEFDG/dPiCIqwVCUbc5X0nYDlH62uEhdHMA==} + dependencies: + '@types/koa': 2.13.5 + dev: true + /@types/koa__multer/2.0.4: resolution: {integrity: sha512-WRkshXhE5rpYFUbbtAjyMhdOOSdbu1XX+2AQlRNM6AZtgxd0/WXMU4lrP7e9tk5HWVTWbx8DOOsVBmfHjSGJ4w==} dependencies: @@ -4455,16 +4462,16 @@ packages: engines: {node: '>= 0.8'} dev: false - /dependency-tree/8.1.2: - resolution: {integrity: sha512-c4CL1IKxkKng0oT5xrg4uNiiMVFqTGOXqHSFx7XEFdgSsp6nw3AGGruICppzJUrfad/r7GLqt26rmWU4h4j39A==} + /dependency-tree/9.0.0: + resolution: {integrity: sha512-osYHZJ1fBSon3lNLw70amAXsQ+RGzXsPvk9HbBgTLbp/bQBmpH5mOmsUvqXU+YEWVU0ZLewsmzOET/8jWswjDQ==} engines: {node: ^10.13 || ^12 || >=14} hasBin: true dependencies: commander: 2.20.3 debug: 4.3.4 filing-cabinet: 3.3.0 - precinct: 8.3.1 - typescript: 3.9.10 + precinct: 9.0.1 + typescript: 4.9.4 transitivePeerDependencies: - supports-color dev: true @@ -4507,6 +4514,17 @@ packages: node-source-walk: 4.3.0 dev: true + /detective-amd/4.0.1: + resolution: {integrity: sha512-bDo22IYbJ8yzALB0Ow5CQLtyhU1BpDksLB9dsWHI9Eh0N3OQR6aQqhjPsNDd69ncYwRfL1sTo7OA9T3VRVSe2Q==} + engines: {node: '>=12'} + hasBin: true + dependencies: + ast-module-types: 3.0.0 + escodegen: 2.0.0 + get-amd-module-type: 4.0.0 + node-source-walk: 5.0.0 + dev: true + /detective-cjs/3.1.3: resolution: {integrity: sha512-ljs7P0Yj9MK64B7G0eNl0ThWSYjhAaSYy+fQcpzaKalYl/UoQBOzOeLCSFEY1qEBhziZ3w7l46KG/nH+s+L7BQ==} engines: {node: '>=6.0'} @@ -4515,6 +4533,14 @@ packages: node-source-walk: 4.3.0 dev: true + /detective-cjs/4.0.0: + resolution: {integrity: sha512-VsD6Yo1+1xgxJWoeDRyut7eqZ8EWaJI70C5eanSAPcBHzenHZx0uhjxaaEfIm0cHII7dBiwU98Orh44bwXN2jg==} + engines: {node: '>=12'} + dependencies: + ast-module-types: 3.0.0 + node-source-walk: 5.0.0 + dev: true + /detective-es6/2.2.2: resolution: {integrity: sha512-eZUKCUsbHm8xoeoCM0z6JFwvDfJ5Ww5HANo+jPR7AzkFpW9Mun3t/TqIF2jjeWa2TFbAiGaWESykf2OQp3oeMw==} engines: {node: '>=6.0'} @@ -4522,6 +4548,13 @@ packages: node-source-walk: 4.3.0 dev: true + /detective-es6/3.0.0: + resolution: {integrity: sha512-Uv2b5Uih7vorYlqGzCX+nTPUb4CMzUAn3VPHTV5p5lBkAN4cAApLGgUz4mZE2sXlBfv4/LMmeP7qzxHV/ZcfWA==} + engines: {node: '>=12'} + dependencies: + node-source-walk: 5.0.0 + dev: true + /detective-less/1.0.2: resolution: {integrity: sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==} engines: {node: '>= 6.0'} @@ -4545,13 +4578,13 @@ packages: - supports-color dev: true - /detective-postcss/5.1.3: - resolution: {integrity: sha512-Wo7PUpF6wqeT1aRgajdyIdDRjFFJVxlXPRAlT1aankH/RVOgrJuEZFZ4ABxYXdzaRPO5Lkg8rHxsxpLnxdJIYA==} - engines: {node: ^10 || ^12 || >=14} + /detective-postcss/6.1.0: + resolution: {integrity: sha512-ZFZnEmUrL2XHAC0j/4D1fdwZbo/anAcK84soJh7qc7xfx2Kc8gFO5Bk5I9jU7NLC/OAF1Yho1GLxEDnmQnRH2A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dependencies: is-url: 1.2.4 postcss: 8.4.19 - postcss-values-parser: 5.0.0_postcss@8.4.19 + postcss-values-parser: 6.0.2_postcss@8.4.19 dev: true /detective-sass/3.0.2: @@ -4562,6 +4595,14 @@ packages: node-source-walk: 4.3.0 dev: true + /detective-sass/4.0.1: + resolution: {integrity: sha512-80zfpxux1krOrkxCHbtwvIs2gNHUBScnSqlGl0FvUuHVz8HD6vD2ov66OroMctyvzhM67fxhuEeVjIk18s6yTQ==} + engines: {node: '>=12'} + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 5.0.0 + dev: true + /detective-scss/2.0.2: resolution: {integrity: sha512-hDWnWh/l0tht/7JQltumpVea/inmkBaanJUcXRB9kEEXVwVUMuZd6z7eusQ6GcBFrfifu3pX/XPyD7StjbAiBg==} engines: {node: '>=6.0'} @@ -4570,10 +4611,23 @@ packages: node-source-walk: 4.3.0 dev: true + /detective-scss/3.0.0: + resolution: {integrity: sha512-37MB/mhJyS45ngqfzd6eTbuLMoDgdZnH03ZOMW2m9WqJ/Rlbuc8kZAr0Ypovaf1DJiTRzy5mmxzOTja85jbzlA==} + engines: {node: '>=12'} + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 5.0.0 + dev: true + /detective-stylus/1.0.3: resolution: {integrity: sha512-4/bfIU5kqjwugymoxLXXLltzQNeQfxGoLm2eIaqtnkWxqbhap9puDVpJPVDx96hnptdERzS5Cy6p9N8/08A69Q==} dev: true + /detective-stylus/2.0.1: + resolution: {integrity: sha512-/Tvs1pWLg8eYwwV6kZQY5IslGaYqc/GACxjcaGudiNtN5nKCH6o2WnJK3j0gA3huCnoQcbv8X7oz/c1lnvE3zQ==} + engines: {node: '>=6.0'} + dev: true + /detective-typescript/7.0.2: resolution: {integrity: sha512-unqovnhxzvkCz3m1/W4QW4qGsvXCU06aU2BAm8tkza+xLnp9SOFnob2QsTxUv5PdnQKfDvWcv9YeOeFckWejwA==} engines: {node: ^10.13 || >=12.0.0} @@ -4586,6 +4640,18 @@ packages: - supports-color dev: true + /detective-typescript/9.0.0: + resolution: {integrity: sha512-lR78AugfUSBojwlSRZBeEqQ1l8LI7rbxOl1qTUnGLcjZQDjZmrZCb7R46rK8U8B5WzFvJrxa7fEBA8FoD/n5fA==} + engines: {node: ^12.20.0 || ^14.14.0 || >=16.0.0} + dependencies: + '@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.4 + ast-module-types: 3.0.0 + node-source-walk: 5.0.0 + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + /dezalgo/1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} dependencies: @@ -5611,6 +5677,14 @@ packages: node-source-walk: 4.3.0 dev: true + /get-amd-module-type/4.0.0: + resolution: {integrity: sha512-GbBawUCuA2tY8ztiMiVo3e3P95gc2TVrfYFfpUHdHQA8WyxMCckK29bQsVKhYX8SUf+w6JLhL2LG8tSC0ANt9Q==} + engines: {node: '>=12'} + dependencies: + ast-module-types: 3.0.0 + node-source-walk: 5.0.0 + dev: true + /get-caller-file/2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -5789,13 +5863,6 @@ packages: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} dev: true - /graphviz/0.0.9: - resolution: {integrity: sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==} - engines: {node: '>=0.6.8'} - dependencies: - temp: 0.4.0 - dev: true - /handlebars/4.7.7: resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} engines: {node: '>=0.4.7'} @@ -7314,10 +7381,6 @@ packages: koa-compose: 4.1.0 dev: false - /koa-cors/0.0.16: - resolution: {integrity: sha512-s15knPxe3AJBi2I/ZMPL0pSqU+PLYLO6k5tI0AqClkzavowvocPlSdFUwaHNqtjHMhsGmiq2tiX/25iILJx9YA==} - dev: false - /koa-helmet/6.1.0: resolution: {integrity: sha512-WymEv4qo/7ghh15t+1qTjvZBmZkmVlTtfnpe5oxn8m8mO2Q2rKJ3eMvWuQGW/6yVxN9+hQ75evuWcg3XBbFLbg==} engines: {node: '>= 8.0.0'} @@ -7565,31 +7628,32 @@ packages: dependencies: yallist: 4.0.0 - /madge/5.0.1: - resolution: {integrity: sha512-krmSWL9Hkgub74bOjnjWRoFPAJvPwSG6Dbta06qhWOq6X/n/FPzO3ESZvbFYVIvG2g4UHXvCJN1b+RZLaSs9nA==} - engines: {node: ^10.13 || ^12 || >=14} + /madge/6.0.0: + resolution: {integrity: sha512-dddxP62sj5pL+l9MJnq9C34VFqmRj+2+uSOdn/7lOTSliLRH0WyQ8uCEF3VxkPRNOBvMKK2xumnIE15HRSAL9A==} + engines: {node: '>=14'} hasBin: true dependencies: chalk: 4.1.2 commander: 7.2.0 commondir: 1.0.1 debug: 4.3.4 - dependency-tree: 8.1.2 - detective-amd: 3.1.2 - detective-cjs: 3.1.3 - detective-es6: 2.2.2 + dependency-tree: 9.0.0 + detective-amd: 4.0.1 + detective-cjs: 4.0.0 + detective-es6: 3.0.0 detective-less: 1.0.2 - detective-postcss: 5.1.3 - detective-sass: 3.0.2 - detective-scss: 2.0.2 - detective-stylus: 1.0.3 - detective-typescript: 7.0.2 - graphviz: 0.0.9 + detective-postcss: 6.1.0 + detective-sass: 4.0.1 + detective-scss: 3.0.0 + detective-stylus: 2.0.1 + detective-typescript: 9.0.0 ora: 5.4.1 pluralize: 8.0.0 precinct: 8.3.1 pretty-ms: 7.0.1 rc: 1.2.8 + stream-to-array: 2.3.0 + ts-graphviz: 1.5.3 typescript: 3.9.10 walkdir: 0.4.1 transitivePeerDependencies: @@ -7883,6 +7947,15 @@ packages: node-source-walk: 4.3.0 dev: true + /module-definition/4.0.0: + resolution: {integrity: sha512-wntiAHV4lDn24BQn2kX6LKq0y85phHLHiv3aOPDF+lIs06kVjEMTe/ZTdrbVLnQV5FQsjik21taknvMhKY1Cug==} + engines: {node: '>=12'} + hasBin: true + dependencies: + ast-module-types: 3.0.0 + node-source-walk: 5.0.0 + dev: true + /module-lookup-amd/7.0.1: resolution: {integrity: sha512-w9mCNlj0S8qviuHzpakaLVc+/7q50jl9a/kmJ/n8bmXQZgDPkQHnPBb8MUOYh3WpAYkXuNc2c+khsozhIp/amQ==} engines: {node: '>=10.13.0'} @@ -8172,6 +8245,13 @@ packages: '@babel/parser': 7.20.5 dev: true + /node-source-walk/5.0.0: + resolution: {integrity: sha512-58APXoMXpmmU+oVBJFajhTCoD8d/OGtngnVAWzIo2A8yn0IXwBzvIVIsTzoie/SrA37u+1hnpNz2HMWx/VIqlw==} + engines: {node: '>=12'} + dependencies: + '@babel/parser': 7.20.5 + dev: true + /nodemailer/6.7.7: resolution: {integrity: sha512-pOLC/s+2I1EXuSqO5Wa34i3kXZG3gugDssH+ZNCevHad65tc8vQlCQpOLaUjopvkRQKm2Cki2aME7fEOPRy3bA==} engines: {node: '>=6.0.0'} @@ -8812,11 +8892,11 @@ packages: uniq: 1.0.1 dev: true - /postcss-values-parser/5.0.0_postcss@8.4.19: - resolution: {integrity: sha512-2viDDjMMrt21W2izbeiJxl3kFuD/+asgB0CBwPEgSyhCmBnDIa/y+pLaoyX+q3I3DHH0oPPL3cgjVTQvlS1Maw==} + /postcss-values-parser/6.0.2_postcss@8.4.19: + resolution: {integrity: sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==} engines: {node: '>=10'} peerDependencies: - postcss: ^8.0.9 + postcss: ^8.2.9 dependencies: color-name: 1.1.4 is-url-superb: 4.0.0 @@ -8873,6 +8953,27 @@ packages: - supports-color dev: true + /precinct/9.0.1: + resolution: {integrity: sha512-hVNS6JvfvlZ64B3ezKeGAcVhIuOvuAiSVzagHX/+KjVPkYWoCNkfyMgCl1bjDtAFQSlzi95NcS9ykUWrl1L1vA==} + engines: {node: ^12.20.0 || ^14.14.0 || >=16.0.0} + hasBin: true + dependencies: + commander: 9.4.1 + detective-amd: 4.0.1 + detective-cjs: 4.0.0 + detective-es6: 3.0.0 + detective-less: 1.0.2 + detective-postcss: 6.1.0 + detective-sass: 4.0.1 + detective-scss: 3.0.0 + detective-stylus: 2.0.1 + detective-typescript: 9.0.0 + module-definition: 4.0.0 + node-source-walk: 5.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /prelude-ls/1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} @@ -8883,8 +8984,8 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prettier/2.8.0: - resolution: {integrity: sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==} + /prettier/2.8.3: + resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} engines: {node: '>=10.13.0'} hasBin: true dev: true @@ -9696,6 +9797,12 @@ packages: engines: {node: '>= 0.8'} dev: false + /stream-to-array/2.3.0: + resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==} + dependencies: + any-promise: 1.3.0 + dev: true + /streamsearch/1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -9944,11 +10051,6 @@ packages: uuid: 3.4.0 dev: false - /temp/0.4.0: - resolution: {integrity: sha512-IsFisGgDKk7qzK9erMIkQe/XwiSUdac7z3wYOsjcLkhPBy3k1SlvLoIh2dAHIlEpgA971CgguMrx9z8fFg7tSA==} - engines: {'0': node >=0.4.0} - dev: true - /terminal-link/2.1.1: resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} engines: {node: '>=8'} @@ -10094,6 +10196,11 @@ packages: engines: {node: '>=8'} dev: true + /ts-graphviz/1.5.3: + resolution: {integrity: sha512-72wo3Y6ZO8FMB9OgzHTB5W/9P5nG6JrO3L3UfWI3oXaFJRqbOyGDxVrfjvF4M7Gnq4B8a0KpeHkpNkUXINqd4A==} + engines: {node: '>=14.16'} + dev: true + /ts-mixer/6.0.2: resolution: {integrity: sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==} dev: false diff --git a/src/Auth/Domain/Entities/Role.ts b/src/Auth/Domain/Entities/Role.ts index 737a3828..d85ca0e4 100644 --- a/src/Auth/Domain/Entities/Role.ts +++ b/src/Auth/Domain/Entities/Role.ts @@ -19,7 +19,7 @@ class Role extends Base implements IRoleDomain updateBuild(payload: RoleRepPayload): void { - AuthHelper.validatePermissions(payload?.permissions ?? []); + AuthHelper.validatePermissions(payload.permissions); this.name = payload?.name; this.slug = payload?.slug; diff --git a/src/Auth/Domain/Services/AuthService.ts b/src/Auth/Domain/Services/AuthService.ts index 8cb99090..918fa078 100644 --- a/src/Auth/Domain/Services/AuthService.ts +++ b/src/Auth/Domain/Services/AuthService.ts @@ -5,6 +5,7 @@ import TokenExpiredHttpException from '../../Presentation/Exceptions/TokenExpire import TokenNotFoundHttpException from '../../Presentation/Exceptions/TokenNotFoundHttpException'; import Auth from '../Types/Auth'; import MainConfig from '../../../Config/MainConfig'; +import utc from 'dayjs/plugin/utc'; import dayjs from 'dayjs'; class AuthService @@ -137,8 +138,9 @@ class AuthService getConfirmationToken(email: string): string { + dayjs.extend(utc); const { iss, secret, aud } = MainConfig.getInstance().getConfig().jwt; - const expires = dayjs().utc().add(5, 'minute').unix(); + const expires = dayjs.utc().add(5, 'minute').unix(); const payload = { iss, diff --git a/src/Auth/Presentation/Handlers/AuthExpressHandler.ts b/src/Auth/Presentation/Handlers/AuthExpressHandler.ts index 78b57d94..8f262173 100644 --- a/src/Auth/Presentation/Handlers/AuthExpressHandler.ts +++ b/src/Auth/Presentation/Handlers/AuthExpressHandler.ts @@ -69,9 +69,9 @@ class AuthExpressHandler expires: dayjs.unix(payload.getExpires()).toDate(), maxAge: payload.getExpires(), path: '/api/auth', - secure: MainConfig.getInstance().getConfig().setCookieSecure, + secure: MainConfig.getInstance().getConfig().app.setCookieSecure, httpOnly: true, - sameSite: MainConfig.getInstance().getConfig().setCookieSameSite as any + sameSite: MainConfig.getInstance().getConfig().app.setCookieSameSite as any }); void await this.responder.send(payload, req, res, this.config['HTTP_CREATED'], new AuthTransformer()); @@ -80,6 +80,12 @@ class AuthExpressHandler @httpPost('/signup') public async register(@request() req: any, @response() res: Response): Promise { + const data = { + ...req.body, + birthday: dayjs(req.body.birthday, 'yyyy-mm-dd').toDate(), + roles: [] + }; + const payload = await this.controller.register(req.body as RegisterPayload); void await this.responder.send(payload, req, res, this.config['HTTP_CREATED'], new DefaultTransformer()); @@ -102,9 +108,9 @@ class AuthExpressHandler expires: dayjs.unix(0).toDate(), maxAge: 0, path: '/api/auth', - secure: MainConfig.getInstance().getConfig().setCookieSecure, + secure: MainConfig.getInstance().getConfig().app.setCookieSecure, httpOnly: true, - sameSite: MainConfig.getInstance().getConfig().setCookieSameSite as any + sameSite: MainConfig.getInstance().getConfig().app.setCookieSameSite as any }); void await this.responder.send(payload, req, res, this.config['HTTP_CREATED'], new DefaultTransformer()); @@ -122,9 +128,9 @@ class AuthExpressHandler expires: dayjs.unix(payload.getExpires()).toDate(), maxAge: payload.getExpires(), path: '/api/auth', - secure: MainConfig.getInstance().getConfig().setCookieSecure, + secure: MainConfig.getInstance().getConfig().app.setCookieSecure, httpOnly: true, - sameSite: MainConfig.getInstance().getConfig().setCookieSameSite as any + sameSite: MainConfig.getInstance().getConfig().app.setCookieSameSite as any }); void await this.responder.send(payload, req, res, this.config['HTTP_CREATED'], new AuthTransformer()); diff --git a/src/Auth/Presentation/Handlers/AuthKoaHandler.ts b/src/Auth/Presentation/Handlers/AuthKoaHandler.ts index 9fc19fd8..6b272bd6 100644 --- a/src/Auth/Presentation/Handlers/AuthKoaHandler.ts +++ b/src/Auth/Presentation/Handlers/AuthKoaHandler.ts @@ -55,9 +55,9 @@ AuthKoaHandler.post('/login', async(ctx: Koa.ParameterizedContext & any) => expires: dayjs.unix(payload.getExpires()).toDate(), maxAge: payload.getExpires(), path: '/api/auth', - secure: MainConfig.getInstance().getConfig().setCookieSecure, + secure: MainConfig.getInstance().getConfig().app.setCookieSecure, httpOnly: true, - sameSite: MainConfig.getInstance().getConfig().setCookieSameSite + sameSite: MainConfig.getInstance().getConfig().app.setCookieSameSite }); void await responder.send(payload, ctx, config['HTTP_CREATED'], new AuthTransformer()); @@ -65,7 +65,13 @@ AuthKoaHandler.post('/login', async(ctx: Koa.ParameterizedContext & any) => AuthKoaHandler.post('/signup', async(ctx: Koa.ParameterizedContext & any) => { - const payload = await controller.register(ctx.request.body as RegisterPayload); + const data = { + ...ctx.request.body, + birthday: dayjs(ctx.request.body.birthday, 'yyyy-mm-dd').toDate(), + roles: [] + }; + + const payload = await controller.register(data as RegisterPayload); void await responder.send(payload, ctx, config['HTTP_CREATED'], new DefaultTransformer()); }); @@ -86,9 +92,9 @@ AuthKoaHandler.post('/logout', async(ctx: Koa.ParameterizedContext & any) => expires: dayjs.unix(0).toDate(), maxAge: 0, path: '/api/auth', - secure: MainConfig.getInstance().getConfig().setCookieSecure, + secure: MainConfig.getInstance().getConfig().app.setCookieSecure, httpOnly: true, - sameSite: MainConfig.getInstance().getConfig().setCookieSameSite + sameSite: MainConfig.getInstance().getConfig().app.setCookieSameSite }); void await responder.send(payload, ctx, config['HTTP_OK'], new DefaultTransformer()); @@ -110,9 +116,9 @@ AuthKoaHandler.post('/refresh-token', RefreshTokenKoaMiddleware, async(ctx: Koa. expires: dayjs.unix(payload.getExpires()).toDate(), maxAge: payload.getExpires(), path: '/api/auth', - secure: MainConfig.getInstance().getConfig().setCookieSecure, + secure: MainConfig.getInstance().getConfig().app.setCookieSecure, httpOnly: true, - sameSite: MainConfig.getInstance().getConfig().setCookieSameSite + sameSite: MainConfig.getInstance().getConfig().app.setCookieSameSite }); void await responder.send(payload, ctx, config['HTTP_OK'], new AuthTransformer()); diff --git a/src/Auth/Presentation/Validations/Auth/RegisterSchemaValidation.ts b/src/Auth/Presentation/Validations/Auth/RegisterSchemaValidation.ts index 773768d9..9d22a6cb 100644 --- a/src/Auth/Presentation/Validations/Auth/RegisterSchemaValidation.ts +++ b/src/Auth/Presentation/Validations/Auth/RegisterSchemaValidation.ts @@ -1,9 +1,7 @@ import UserWithoutPermissionsSchemaValidation from '../User/UserWithoutPermissionsSchemaValidation'; import PasswordSchemaValidation from '../User/PasswordSchemaValidation'; -import ConfirmationTokenSchemaValidation from './ConfirmationTokenSchemaValidation'; const RegisterSchemaValidation = UserWithoutPermissionsSchemaValidation - .merge(PasswordSchemaValidation) - .merge(ConfirmationTokenSchemaValidation); + .merge(PasswordSchemaValidation); export default RegisterSchemaValidation; diff --git a/src/Auth/Tests/signup.handler.spec.ts b/src/Auth/Tests/signup.handler.spec.ts new file mode 100644 index 00000000..b04cf51d --- /dev/null +++ b/src/Auth/Tests/signup.handler.spec.ts @@ -0,0 +1,87 @@ +import { SuperAgentTest } from 'supertest'; +import initTestServer from '../../initTestServer'; +import ICreateConnection from '../../Shared/Infrastructure/Database/ICreateConnection'; +import EmailStrategy from '../../Notification/Shared/EmailStrategy'; + +describe('Start Signup Test', () => +{ + let request: SuperAgentTest; + let dbConnection: ICreateConnection; + let spy; + + beforeAll(async() => + { + spy = jest.spyOn(EmailStrategy.prototype, 'send').mockImplementation(async() => new Promise((resolve) => resolve(true))); + + const configServer = await initTestServer(); + + request = configServer.request; + dbConnection = configServer.dbConnection; + }); + + afterAll((async() => + { + await dbConnection.drop(); + await dbConnection.close(); + spy.mockRestore(); + })); + + test('Signup Success', async() => + { + const payload = { + firstName: 'Jhon', + lastName: 'Doe', + email: 'john-doe@mail.com', + password: '12345678', + passwordConfirmation: '12345678', + birthday: '1990-11-26', + documentType: 'dni', + documentNumber: '52261090712', + gender: 'M', + phone: '2234456998', + country: 'AR', + address: 'Don Trusted 123', + permissions: [] + }; + + const response: any = await request + .post('/api/auth/signup') + .set('Accept', 'application/json') + .send(payload); + + const { body: { data } } = response; + + expect(response.statusCode).toStrictEqual(201); + expect(data.messageCode).toStrictEqual('auth.domain.messages.register'); + }); + + test('Signup Fail', async() => + { + const payload = { + lastName: 'Doe', + email: 'john-doe@mail.com', + password: '12345678', + passwordConfirmation: '12345678', + birthday: '1990-11-26', + documentType: 'dni', + documentNumber: '52261090712', + gender: 'M', + phone: '2234456998', + country: 'AR', + address: 'Don Trusted 123', + permissions: [] + }; + + const response: any = await request + .post('/api/auth/signup') + .set('Accept', 'application/json') + .send(payload); + + const { body: { errors: [error1] } } = response; + + expect(response.statusCode).toStrictEqual(422); + expect(error1.code).toStrictEqual('invalid_type'); + expect(error1.path[0]).toStrictEqual('firstName'); + expect(error1.message).toStrictEqual('Required'); + }); +}); diff --git a/src/Config/MainConfig.ts b/src/Config/MainConfig.ts index a9de1104..70c424fb 100644 --- a/src/Config/MainConfig.ts +++ b/src/Config/MainConfig.ts @@ -9,6 +9,10 @@ import { validateEnv } from './validateEnv'; type AppConfig = { default: string; path: string; + setAppProxy: boolean; + setCookieSecure: boolean, + setCookieSameSite: boolean | 'None' | 'Lax' | 'Strict', + serverPort: number, } type TypeORMConfig = { @@ -129,9 +133,6 @@ export type IHttpStatusCode = type ConfigType = { env: string, - setCookieSecure: boolean, - setCookieSameSite: boolean | 'None' | 'Lax' | 'Strict', - serverPort: number, auth: { authorization: boolean }; diff --git a/src/Config/Permissions.ts b/src/Config/Permissions.ts index e9f0c56f..680362b3 100644 --- a/src/Config/Permissions.ts +++ b/src/Config/Permissions.ts @@ -2,8 +2,6 @@ import IGroupPermission from './IGroupPermission'; class Permissions { - static readonly ALL: string = 'all'; - // AUTH static readonly AUTH_SYNC_PERMISSIONS: string = 'authSyncPermissions'; static readonly GET_PERMISSIONS: string = 'getPermissions'; @@ -93,12 +91,6 @@ class Permissions Permissions.ROLES_LIST, Permissions.ROLES_DELETE ] - }, - { - group: 'OTHERS', - permissions: [ - Permissions.ALL - ] } ]; } diff --git a/src/Config/Roles.ts b/src/Config/Roles.ts index 1dfd9598..41d75705 100644 --- a/src/Config/Roles.ts +++ b/src/Config/Roles.ts @@ -9,11 +9,15 @@ class Roles static getRoles(): Record { return { - [Roles.SUPER_ADMIN]: [ - Permissions.ALL - ], [Roles.ADMIN]: [ - Permissions.ALL + Permissions.USERS_CHANGE_MY_PASSWORD, + Permissions.ITEMS_SAVE, + Permissions.ITEMS_UPDATE, + Permissions.ITEMS_SHOW, + Permissions.ITEMS_LIST, + Permissions.FILES_UPLOAD, + Permissions.FILES_DOWNLOAD, + Permissions.FILES_LIST ], [Roles.OPERATOR]: [ Permissions.USERS_CHANGE_MY_PASSWORD, diff --git a/src/Config/validateEnv.ts b/src/Config/validateEnv.ts index a7940f1c..7e0e5618 100644 --- a/src/Config/validateEnv.ts +++ b/src/Config/validateEnv.ts @@ -4,8 +4,13 @@ export function validateEnv() { return cleanEnv(process.env, { NODE_ENV: str(), - NODE_PATH: str(), - SERVER_PORT: port(), + + APP_DEFAULT: str(), + APP_PATH: str(), + APP_PORT: port(), + APP_SET_APP_PROXY: bool(), + APP_SET_COOKIE_SECURE: bool(), + APP_SET_COOKIE_SAME_SITE: str(), DB_HOST: str(), DB_USER: str(), @@ -38,8 +43,6 @@ export function validateEnv() JWT_EXPIRES: num(), JWT_ISS: str(), JWT_AUD: str(), - SET_COOKIE_SECURE: bool(), - SET_COOKIE_SAME_SITE: str(), SMTP_HOST: str(), SMTP_PORT: num(), diff --git a/src/Shared/Application/Http/AppKoa.ts b/src/Shared/Application/Http/AppKoa.ts index 09e6344e..9b28af76 100644 --- a/src/Shared/Application/Http/AppKoa.ts +++ b/src/Shared/Application/Http/AppKoa.ts @@ -1,4 +1,4 @@ -import cors from 'koa-cors'; +import cors from '@koa/cors'; import helmet from 'koa-helmet'; import { Server } from 'http'; @@ -42,9 +42,21 @@ class AppKoa implements IApp this.config = config; this.app.use(cors({ - credentials: true + credentials: true, + origin: (ctx) => + { + const { env } = MainConfig.getInstance().getConfig(); + const validDomains = env === 'development' ? ['http://localhost:5173'] : ['https://domain.com']; + + if (validDomains.indexOf(ctx.request.header.origin) !== -1) + { + return ctx.request.header.origin; + } + + return validDomains[0]; // we can't return void, so let's return one of the valid domains + } })); - this.app.proxy = MainConfig.getInstance().getConfig().env === 'production'; + this.app.proxy = MainConfig.getInstance().getConfig().app.setAppProxy; this.app.use(helmet()); this.app.use(bodyParser({ diff --git a/src/Shared/Factories/AxiosFactory.ts b/src/Shared/Factories/AxiosFactory.ts index 46a4cbc7..648ae552 100644 --- a/src/Shared/Factories/AxiosFactory.ts +++ b/src/Shared/Factories/AxiosFactory.ts @@ -1,7 +1,7 @@ import axios, { AxiosInstance } from 'axios'; import MainConfig from '../../Config/MainConfig'; -const port = MainConfig.getInstance().getConfig().serverPort; +const port = MainConfig.getInstance().getConfig().app.serverPort; const baseURL = `http://localhost:${port}/api/`; const timeout = 3000; const headersPublic = { diff --git a/src/index.ts b/src/index.ts index 66874c68..0fee989e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,7 +39,7 @@ void (async() => cronFactory.start(); app.initConfig({ - serverPort: config.serverPort + serverPort: config.app.serverPort }); await app.build(); app.listen();