upload file/avatar
This commit is contained in:
377
package-lock.json
generated
377
package-lock.json
generated
@@ -24,17 +24,21 @@
|
|||||||
"@types/hapi__joi": "^17.1.15",
|
"@types/hapi__joi": "^17.1.15",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
|
"aws-sdk": "^2.1692.0",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.2",
|
"class-validator": "^0.14.2",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"joi": "^17.13.3",
|
"joi": "^17.13.3",
|
||||||
|
"multer": "^1.4.5-lts.2",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"pg": "^8.15.6",
|
"pg": "^8.15.6",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
@@ -46,6 +50,7 @@
|
|||||||
"@swc/core": "^1.10.7",
|
"@swc/core": "^1.10.7",
|
||||||
"@types/express": "^5.0.1",
|
"@types/express": "^5.0.1",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
|
"@types/multer": "^1.4.12",
|
||||||
"@types/node": "^22.10.7",
|
"@types/node": "^22.10.7",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.26.0",
|
||||||
@@ -3688,6 +3693,16 @@
|
|||||||
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
|
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/multer": {
|
||||||
|
"version": "1.4.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz",
|
||||||
|
"integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.15.17",
|
"version": "22.15.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz",
|
||||||
@@ -3812,6 +3827,12 @@
|
|||||||
"@types/superagent": "^8.1.0"
|
"@types/superagent": "^8.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/validator": {
|
"node_modules/@types/validator": {
|
||||||
"version": "13.15.0",
|
"version": "13.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.0.tgz",
|
||||||
@@ -5197,6 +5218,78 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/available-typed-arrays": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"possible-typed-array-names": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk": {
|
||||||
|
"version": "2.1692.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1692.0.tgz",
|
||||||
|
"integrity": "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "4.9.2",
|
||||||
|
"events": "1.1.1",
|
||||||
|
"ieee754": "1.1.13",
|
||||||
|
"jmespath": "0.16.0",
|
||||||
|
"querystring": "0.2.0",
|
||||||
|
"sax": "1.2.1",
|
||||||
|
"url": "0.10.3",
|
||||||
|
"util": "^0.12.4",
|
||||||
|
"uuid": "8.0.0",
|
||||||
|
"xml2js": "0.6.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/buffer": {
|
||||||
|
"version": "4.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
||||||
|
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.0.2",
|
||||||
|
"ieee754": "^1.1.4",
|
||||||
|
"isarray": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/events": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/ieee754": {
|
||||||
|
"version": "1.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
||||||
|
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/uuid": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/b4a": {
|
"node_modules/b4a": {
|
||||||
"version": "1.6.7",
|
"version": "1.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
|
||||||
@@ -5635,6 +5728,24 @@
|
|||||||
"node": ">=14.16"
|
"node": ">=14.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/call-bind": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.0",
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"set-function-length": "^1.2.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/call-bind-apply-helpers": {
|
"node_modules/call-bind-apply-helpers": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
@@ -6329,6 +6440,23 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/define-data-property": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/delayed-stream": {
|
"node_modules/delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
@@ -7355,6 +7483,21 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/for-each": {
|
||||||
|
"version": "0.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
||||||
|
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-callable": "^1.2.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/foreground-child": {
|
"node_modules/foreground-child": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||||
@@ -7848,6 +7991,18 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-property-descriptors": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/has-symbols": {
|
"node_modules/has-symbols": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
@@ -7864,7 +8019,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-symbols": "^1.0.3"
|
"has-symbols": "^1.0.3"
|
||||||
@@ -8086,6 +8240,22 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-arguments": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"has-tostringtag": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-arrayish": {
|
"node_modules/is-arrayish": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||||
@@ -8093,6 +8263,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/is-callable": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-core-module": {
|
"node_modules/is-core-module": {
|
||||||
"version": "2.16.1",
|
"version": "2.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||||
@@ -8138,6 +8320,24 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-generator-function": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.3",
|
||||||
|
"get-proto": "^1.0.0",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"safe-regex-test": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-glob": {
|
"node_modules/is-glob": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
@@ -8187,6 +8387,24 @@
|
|||||||
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/is-regex": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-stream": {
|
"node_modules/is-stream": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
@@ -8200,6 +8418,21 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-typed-array": {
|
||||||
|
"version": "1.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
|
||||||
|
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"which-typed-array": "^1.1.16"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-unicode-supported": {
|
"node_modules/is-unicode-supported": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||||
@@ -9011,6 +9244,15 @@
|
|||||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jmespath": {
|
||||||
|
"version": "0.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
|
||||||
|
"integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/joi": {
|
"node_modules/joi": {
|
||||||
"version": "17.13.3",
|
"version": "17.13.3",
|
||||||
"resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
|
"resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
|
||||||
@@ -10540,6 +10782,15 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/possible-typed-array-names": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postgres-array": {
|
"node_modules/postgres-array": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz",
|
||||||
@@ -10728,6 +10979,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/querystring": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
|
||||||
|
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/queue-microtask": {
|
"node_modules/queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
@@ -11098,12 +11358,35 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-regex-test": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"is-regex": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safer-buffer": {
|
"node_modules/safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/sax": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/schema-utils": {
|
"node_modules/schema-utils": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||||
@@ -11241,6 +11524,23 @@
|
|||||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/set-function-length": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"define-data-property": "^1.1.4",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"gopd": "^1.0.1",
|
||||||
|
"has-property-descriptors": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/setprototypeof": {
|
"node_modules/setprototypeof": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||||
@@ -12807,6 +13107,35 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/url": {
|
||||||
|
"version": "0.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
|
||||||
|
"integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "1.3.2",
|
||||||
|
"querystring": "0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/url/node_modules/punycode": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/util": {
|
||||||
|
"version": "0.12.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
|
||||||
|
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"is-arguments": "^1.0.4",
|
||||||
|
"is-generator-function": "^1.0.7",
|
||||||
|
"is-typed-array": "^1.1.3",
|
||||||
|
"which-typed-array": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@@ -12831,7 +13160,6 @@
|
|||||||
"https://github.com/sponsors/ctavan"
|
"https://github.com/sponsors/ctavan"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"uuid": "dist/esm/bin/uuid"
|
"uuid": "dist/esm/bin/uuid"
|
||||||
}
|
}
|
||||||
@@ -13154,6 +13482,27 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/which-typed-array": {
|
||||||
|
"version": "1.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
|
||||||
|
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"available-typed-arrays": "^1.0.7",
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.4",
|
||||||
|
"for-each": "^0.3.5",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-tostringtag": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wide-align": {
|
"node_modules/wide-align": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
|
||||||
@@ -13277,6 +13626,28 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/xml2js": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sax": ">=0.6.0",
|
||||||
|
"xmlbuilder": "~11.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xmlbuilder": {
|
||||||
|
"version": "11.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||||
|
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|||||||
@@ -35,17 +35,21 @@
|
|||||||
"@types/hapi__joi": "^17.1.15",
|
"@types/hapi__joi": "^17.1.15",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
|
"aws-sdk": "^2.1692.0",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.2",
|
"class-validator": "^0.14.2",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"joi": "^17.13.3",
|
"joi": "^17.13.3",
|
||||||
|
"multer": "^1.4.5-lts.2",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"pg": "^8.15.6",
|
"pg": "^8.15.6",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
@@ -57,6 +61,7 @@
|
|||||||
"@swc/core": "^1.10.7",
|
"@swc/core": "^1.10.7",
|
||||||
"@types/express": "^5.0.1",
|
"@types/express": "^5.0.1",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
|
"@types/multer": "^1.4.12",
|
||||||
"@types/node": "^22.10.7",
|
"@types/node": "^22.10.7",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.26.0",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {UsersModule} from "./users/user.module";
|
|||||||
import {AuthenticationModule} from "./authentication/authentication.module";
|
import {AuthenticationModule} from "./authentication/authentication.module";
|
||||||
import { PostsModule } from './posts/posts.module';
|
import { PostsModule } from './posts/posts.module';
|
||||||
import { CategoriesModule } from './categories/categories.module';
|
import { CategoriesModule } from './categories/categories.module';
|
||||||
|
import {FilesModule} from "./files/file.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -32,12 +33,16 @@ import { CategoriesModule } from './categories/categories.module';
|
|||||||
validationSchema: Joi.object({
|
validationSchema: Joi.object({
|
||||||
JWT_SECRET: Joi.string().required(),
|
JWT_SECRET: Joi.string().required(),
|
||||||
JWT_EXPIRATION_TIME: Joi.string().required(),
|
JWT_EXPIRATION_TIME: Joi.string().required(),
|
||||||
|
S3_BUCKET: Joi.string().required(),
|
||||||
|
S3_ACCESS_KEY: Joi.string().required(),
|
||||||
|
S3_ENDPOINT: Joi.string().required(),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
UsersModule,
|
UsersModule,
|
||||||
AuthenticationModule,
|
AuthenticationModule,
|
||||||
PostsModule,
|
PostsModule,
|
||||||
CategoriesModule
|
CategoriesModule,
|
||||||
|
FilesModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Strategy } from 'passport-local';
|
|||||||
import { PassportStrategy } from '@nestjs/passport';
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { AuthenticationService } from './authentication.service';
|
import { AuthenticationService } from './authentication.service';
|
||||||
import User from '../users/user.entity';
|
import User from '../users/entities/user.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LocalStrategy extends PassportStrategy(Strategy) {
|
export class LocalStrategy extends PassportStrategy(Strategy) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import User from '../users/user.entity';
|
import User from '../users/entities/user.entity';
|
||||||
|
|
||||||
interface RequestWithUser extends Request {
|
interface RequestWithUser extends Request {
|
||||||
user: User;
|
user: User;
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import {Module} from '@nestjs/common';
|
||||||
import { CategoriesService } from './categories.service';
|
import {CategoriesService} from './categories.service';
|
||||||
import { CategoriesController } from './categories.controller';
|
import {CategoriesController} from './categories.controller';
|
||||||
|
import {TypeOrmModule} from "@nestjs/typeorm";
|
||||||
|
import Post from "../posts/entities/post.entity";
|
||||||
|
import Category from "./entities/category.entity";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [CategoriesController],
|
controllers: [CategoriesController],
|
||||||
providers: [CategoriesService],
|
imports: [TypeOrmModule.forFeature([Category])],
|
||||||
|
|
||||||
|
providers: [CategoriesService],
|
||||||
|
exports: [CategoriesService],
|
||||||
})
|
})
|
||||||
export class CategoriesModule {}
|
export class CategoriesModule {
|
||||||
|
}
|
||||||
|
|||||||
11
src/core/file.interface.ts
Normal file
11
src/core/file.interface.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export interface File {
|
||||||
|
fieldname: string;
|
||||||
|
originalname: string;
|
||||||
|
encoding: string;
|
||||||
|
mimetype: string;
|
||||||
|
size: number;
|
||||||
|
destination: string;
|
||||||
|
filename: string;
|
||||||
|
path: string;
|
||||||
|
buffer: Buffer;
|
||||||
|
}
|
||||||
21
src/core/s3-config.ts
Normal file
21
src/core/s3-config.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export const BUCKET = 'nest-reno';
|
||||||
|
|
||||||
|
|
||||||
|
export const IMAGES = 'images';
|
||||||
|
export const FILES = 'files';
|
||||||
|
export const THUMBNAILS = 'thumbnails';
|
||||||
|
|
||||||
|
export const ACCESSKEY = '004a8f97aa7c9b90000000004';
|
||||||
|
export const SECRETKEY = 'K004lokMgbjY5cfVoFwrzl2gD4AW6yk';
|
||||||
|
|
||||||
|
const aws = require('aws-sdk');
|
||||||
|
|
||||||
|
aws.config.update({
|
||||||
|
accessKeyId: ACCESSKEY,
|
||||||
|
secretAccessKey: SECRETKEY
|
||||||
|
});
|
||||||
|
|
||||||
|
const spacesEndpoint = new aws.Endpoint('s3.us-west-004.backblazeb2.com');
|
||||||
|
export const s3 = new aws.S3({
|
||||||
|
endpoint: spacesEndpoint
|
||||||
|
});
|
||||||
12
src/files/file.module.ts
Normal file
12
src/files/file.module.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { FilesService } from './files.service';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import PublicFile from './publicFile.entity';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([PublicFile]), ConfigModule],
|
||||||
|
providers: [FilesService],
|
||||||
|
exports: [FilesService],
|
||||||
|
})
|
||||||
|
export class FilesModule {}
|
||||||
78
src/files/files.service.ts
Normal file
78
src/files/files.service.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import {Injectable} from '@nestjs/common';
|
||||||
|
import {InjectRepository} from '@nestjs/typeorm';
|
||||||
|
import {Repository, QueryRunner} from 'typeorm';
|
||||||
|
import PublicFile from './publicFile.entity';
|
||||||
|
import {S3} from 'aws-sdk';
|
||||||
|
import {ConfigService} from '@nestjs/config';
|
||||||
|
import {v4 as uuid} from 'uuid';
|
||||||
|
import {File} from "../core/file.interface";
|
||||||
|
import {s3} from "../core/s3-config";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FilesService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(PublicFile)
|
||||||
|
private publicFilesRepository: Repository<PublicFile>,
|
||||||
|
private readonly configService: ConfigService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
async uploadPublicFile(dataBuffer: Buffer, filename: string) {
|
||||||
|
const uploadResult = await s3.upload({
|
||||||
|
ACL: 'public-read',
|
||||||
|
Bucket: 'nest-reno',
|
||||||
|
Body: dataBuffer,
|
||||||
|
Key: filename,
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
|
||||||
|
|
||||||
|
const newFile = this.publicFilesRepository.create({
|
||||||
|
key: uploadResult.Key,
|
||||||
|
url: uploadResult.Location,
|
||||||
|
});
|
||||||
|
await this.publicFilesRepository.save(newFile);
|
||||||
|
return newFile;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async uploadFile(file: File, folder: String) {
|
||||||
|
const uploadResult = await s3.upload({
|
||||||
|
ACL: 'public-read',
|
||||||
|
Bucket: folder,
|
||||||
|
Body: file.buffer,
|
||||||
|
Key: file.originalname,
|
||||||
|
ContentType: file.mimetype,
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
return uploadResult['Location'];
|
||||||
|
}
|
||||||
|
|
||||||
|
async deletePublicFile(fileId: number) {
|
||||||
|
const file = await this.publicFilesRepository.findOneBy({id: fileId});
|
||||||
|
await s3
|
||||||
|
.deleteObject({
|
||||||
|
Bucket: this.configService.get('S3_BUCKET'),
|
||||||
|
Key: file.key,
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
await this.publicFilesRepository.delete(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deletePublicFileWithQueryRunner(
|
||||||
|
fileId: number,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
) {
|
||||||
|
const file = await queryRunner.manager.findOneBy(PublicFile, {
|
||||||
|
id: fileId,
|
||||||
|
});
|
||||||
|
const s3 = new S3();
|
||||||
|
await s3
|
||||||
|
.deleteObject({
|
||||||
|
Bucket: this.configService.get('S3_BUCKET'),
|
||||||
|
Key: file.key,
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
await queryRunner.manager.delete(PublicFile, fileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/files/publicFile.entity.ts
Normal file
15
src/files/publicFile.entity.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
class PublicFile {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
public id: number;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
public url: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
public key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PublicFile;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn, ManyToMany, JoinTable} from 'typeorm';
|
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn, ManyToMany, JoinTable} from 'typeorm';
|
||||||
import User from "../../users/user.entity";
|
import User from "../../users/entities/user.entity";
|
||||||
import Category from "../../categories/entities/category.entity";
|
import Category from "../../categories/entities/category.entity";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import {Module} from '@nestjs/common';
|
||||||
import { PostsService } from './posts.service';
|
import {PostsService} from './posts.service';
|
||||||
import { PostsController } from './posts.controller';
|
import {PostsController} from './posts.controller';
|
||||||
|
import {TypeOrmModule} from "@nestjs/typeorm";
|
||||||
|
import User from "../users/entities/user.entity";
|
||||||
|
import Post from "./entities/post.entity";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [PostsController],
|
controllers: [PostsController],
|
||||||
providers: [PostsService],
|
imports: [TypeOrmModule.forFeature([Post])],
|
||||||
|
providers: [PostsService],
|
||||||
|
exports: [PostsService],
|
||||||
})
|
})
|
||||||
export class PostsModule {}
|
export class PostsModule {
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {Injectable} from '@nestjs/common';
|
import {Injectable} from '@nestjs/common';
|
||||||
import {CreatePostDto} from './dto/create-post.dto';
|
import {CreatePostDto} from './dto/create-post.dto';
|
||||||
import {UpdatePostDto} from './dto/update-post.dto';
|
import {UpdatePostDto} from './dto/update-post.dto';
|
||||||
import User from "../users/user.entity";
|
import User from "../users/entities/user.entity";
|
||||||
import {InjectRepository} from "@nestjs/typeorm";
|
import {InjectRepository} from "@nestjs/typeorm";
|
||||||
import {Repository} from "typeorm";
|
import {Repository} from "typeorm";
|
||||||
import Post from './entities/post.entity';
|
import Post from './entities/post.entity';
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import {Column, Entity, PrimaryGeneratedColumn, OneToOne, JoinColumn, OneToMany} from 'typeorm';
|
import {Column, Entity, PrimaryGeneratedColumn, OneToOne, JoinColumn, OneToMany} from 'typeorm';
|
||||||
import {Exclude, Expose} from 'class-transformer';
|
import {Exclude, Expose} from 'class-transformer';
|
||||||
import Address from "./address.entity";
|
import Address from "./address.entity";
|
||||||
import Post from "../posts/entities/post.entity";
|
import Post from "../../posts/entities/post.entity";
|
||||||
|
import PublicFile from "../../files/publicFile.entity";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
class User {
|
class User {
|
||||||
@@ -30,6 +31,15 @@ class User {
|
|||||||
@OneToMany(() => Post, (post: Post) => post.author)
|
@OneToMany(() => Post, (post: Post) => post.author)
|
||||||
public posts: Post[];
|
public posts: Post[];
|
||||||
|
|
||||||
|
@JoinColumn()
|
||||||
|
@OneToOne(
|
||||||
|
() => PublicFile,
|
||||||
|
{
|
||||||
|
eager: true,
|
||||||
|
nullable: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public avatar?: PublicFile;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
nullable: true,
|
nullable: true,
|
||||||
21
src/users/user.controller.ts
Normal file
21
src/users/user.controller.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Controller, Post, Req, UploadedFile, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||||
|
import JwtAuthenticationGuard from '../authentication/jwt-authentication.guard';
|
||||||
|
import RequestWithUser from '../authentication/requestWithUser.interface';
|
||||||
|
import { FileInterceptor } from '@nestjs/platform-express';
|
||||||
|
import { Express } from 'express';
|
||||||
|
import {UsersService} from "./user.service";
|
||||||
|
import 'multer';
|
||||||
|
|
||||||
|
@Controller('user')
|
||||||
|
export class UsersController {
|
||||||
|
constructor(
|
||||||
|
private readonly usersService: UsersService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Post('avatar')
|
||||||
|
@UseGuards(JwtAuthenticationGuard)
|
||||||
|
@UseInterceptors(FileInterceptor('file'))
|
||||||
|
async addAvatar(@Req() request: RequestWithUser, @UploadedFile() file: Express.Multer.File) {
|
||||||
|
return this.usersService.addAvatar(request.user.id, file.buffer, file.originalname);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,20 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import User from './user.entity';
|
import User from './entities/user.entity';
|
||||||
import { UsersService } from './user.service';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import {UsersService} from "./user.service";
|
||||||
|
import {UsersController} from "./user.controller";
|
||||||
|
import {FilesModule} from "../files/file.module";
|
||||||
|
import Address from "./entities/address.entity";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([User])],
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([User, Address]),
|
||||||
|
ConfigModule,
|
||||||
|
FilesModule,
|
||||||
|
],
|
||||||
providers: [UsersService],
|
providers: [UsersService],
|
||||||
exports: [UsersService],
|
exports: [UsersService],
|
||||||
|
controllers: [UsersController],
|
||||||
})
|
})
|
||||||
export class UsersModule {}
|
export class UsersModule {}
|
||||||
@@ -1,53 +1,66 @@
|
|||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
import {HttpException, HttpStatus, Injectable} from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import {InjectRepository} from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import {Repository} from 'typeorm';
|
||||||
import User from './user.entity';
|
import User from './entities/user.entity';
|
||||||
import CreateUserDto from './dto/createUser.dto';
|
import CreateUserDto from './dto/createUser.dto';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
|
import {FilesService} from "../files/files.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UsersService {
|
export class UsersService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(User)
|
@InjectRepository(User)
|
||||||
private usersRepository: Repository<User>,
|
private usersRepository: Repository<User>,
|
||||||
) {}
|
private readonly filesService: FilesService
|
||||||
|
) {
|
||||||
async getByEmail(email: string) {
|
|
||||||
const user = await this.usersRepository.findOne({ where: { email } });
|
|
||||||
if (user) {
|
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
throw new HttpException(
|
|
||||||
'User with this email does not exist',
|
|
||||||
HttpStatus.NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getById(id: number) {
|
async getByEmail(email: string) {
|
||||||
const user = await this.usersRepository.findOne({ where: { id } });
|
const user = await this.usersRepository.findOne({where: {email}});
|
||||||
if (user) {
|
if (user) {
|
||||||
return user;
|
return user;
|
||||||
|
}
|
||||||
|
throw new HttpException(
|
||||||
|
'User with this email does not exist',
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
throw new HttpException('User with this id does not exist', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
async create(userData: CreateUserDto) {
|
async getById(id: number) {
|
||||||
const newUser = this.usersRepository.create(userData);
|
const user = await this.usersRepository.findOne({where: {id}});
|
||||||
await this.usersRepository.save(newUser);
|
if (user) {
|
||||||
return newUser;
|
return user;
|
||||||
}
|
}
|
||||||
|
throw new HttpException('User with this id does not exist', HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addAvatar(userId: number, imageBuffer: Buffer, filename: string) {
|
||||||
|
const avatar = await this.filesService.uploadPublicFile(imageBuffer, filename);
|
||||||
|
const user = await this.getById(userId);
|
||||||
|
await this.usersRepository.update(userId, {
|
||||||
|
...user,
|
||||||
|
avatar
|
||||||
|
});
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(userData: CreateUserDto) {
|
||||||
|
const newUser = this.usersRepository.create(userData);
|
||||||
|
await this.usersRepository.save(newUser);
|
||||||
|
return newUser;
|
||||||
|
}
|
||||||
|
|
||||||
async setCurrentRefreshToken(refreshToken: string, userId: number) {
|
async setCurrentRefreshToken(refreshToken: string, userId: number) {
|
||||||
const currentHashedRefreshToken = await bcrypt.hash(refreshToken, 10);
|
const currentHashedRefreshToken = await bcrypt.hash(refreshToken, 10);
|
||||||
await this.usersRepository.update(userId, {
|
await this.usersRepository.update(userId, {
|
||||||
currentHashedRefreshToken,
|
currentHashedRefreshToken,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeRefreshToken(userId: number) {
|
async removeRefreshToken(userId: number) {
|
||||||
return this.usersRepository.update(userId, {
|
return this.usersRepository.update(userId, {
|
||||||
currentHashedRefreshToken: null,
|
currentHashedRefreshToken: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user