change some files
This commit is contained in:
3
.env
Normal file
3
.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
JWT_SECRET=a4f6c1f6b9b5c1c7c3a63cce9f9c5b7d6f8e3c7c2a0f7a1d9e0b4c8d2a1f5e6c3b2d9f0a6e7c4b1d8f3a2c5e6d9b7a0
|
||||||
|
CDN_BASE_URL=http://localhost:3500
|
||||||
|
CDN_SERVICE_TOKEN=5075761248974997bf50fdf2a136e2d27320c15358d59ab09e37438b3ee7f08e1d15770a114a8774bf90e14189560832
|
||||||
@@ -1 +1,3 @@
|
|||||||
JWT_SECRET=a4f6c1f6b9b5c1c7c3a63cce9f9c5b7d6f8e3c7c2a0f7a1d9e0b4c8d2a1f5e6c3b2d9f0a6e7c4b1d8f3a2c5e6d9b7a0
|
JWT_SECRET=a4f6c1f6b9b5c1c7c3a63cce9f9c5b7d6f8e3c7c2a0f7a1d9e0b4c8d2a1f5e6c3b2d9f0a6e7c4b1d8f3a2c5e6d9b7a0
|
||||||
|
CDN_BASE_URL=http://localhost:3500
|
||||||
|
CDN_SERVICE_TOKEN=5075761248974997bf50fdf2a136e2d27320c15358d59ab09e37438b3ee7f08e1d15770a114a8774bf90e14189560832
|
||||||
@@ -1 +1,3 @@
|
|||||||
JWT_SECRET=a4f6c1f6b9b5c1c7c3a63cce9f9c5b7d6f8e3c7c2a0f7a1d9e0b4c8d2a1f5e6c3b2d9f0a6e7c4b1d8f3a2c5e6d9b7a0
|
JWT_SECRET=a4f6c1f6b9b5c1c7c3a63cce9f9c5b7d6f8e3c7c2a0f7a1d9e0b4c8d2a1f5e6c3b2d9f0a6e7c4b1d8f3a2c5e6d9b7a0
|
||||||
|
CDN_BASE_URL=http://localhost:3500
|
||||||
|
CDN_SERVICE_TOKEN=5075761248974997bf50fdf2a136e2d27320c15358d59ab09e37438b3ee7f08e1d15770a114a8774bf90e14189560832
|
||||||
178
package-lock.json
generated
178
package-lock.json
generated
@@ -10,12 +10,14 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"auto-bind": "^4.0.0",
|
"auto-bind": "^4.0.0",
|
||||||
|
"axios": "^1.16.1",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
"csurf": "^1.11.0",
|
"csurf": "^1.11.0",
|
||||||
"express": "^5.2.1",
|
"express": "^5.2.1",
|
||||||
"express-rate-limit": "^8.5.2",
|
"express-rate-limit": "^8.5.2",
|
||||||
|
"form-data": "^4.0.5",
|
||||||
"helmet": "^8.1.0",
|
"helmet": "^8.1.0",
|
||||||
"hpp": "^0.2.3",
|
"hpp": "^0.2.3",
|
||||||
"http-errors": "^2.0.1",
|
"http-errors": "^2.0.1",
|
||||||
@@ -32,6 +34,7 @@
|
|||||||
"@types/express": "^5.0.6",
|
"@types/express": "^5.0.6",
|
||||||
"@types/hpp": "^0.2.7",
|
"@types/hpp": "^0.2.7",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
|
"@types/multer": "^2.1.0",
|
||||||
"@types/node": "^25.9.0",
|
"@types/node": "^25.9.0",
|
||||||
"dotenv": "^17.4.2",
|
"dotenv": "^17.4.2",
|
||||||
"nodemon": "^3.1.14",
|
"nodemon": "^3.1.14",
|
||||||
@@ -211,7 +214,6 @@
|
|||||||
"integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
|
"integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/body-parser": "*",
|
"@types/body-parser": "*",
|
||||||
"@types/express-serve-static-core": "^5.0.0",
|
"@types/express-serve-static-core": "^5.0.0",
|
||||||
@@ -265,12 +267,21 @@
|
|||||||
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/multer": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/@types/multer/-/multer-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-zYZb0+nJhOHtPpGDb3vqPjwpdeGlGC157VpkqNQL+UU2qwoacoQ7MpsAmUptI/0Oa127X32JzWDqQVEXp2RcIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "25.9.0",
|
"version": "25.9.0",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/@types/node/-/node-25.9.0.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/@types/node/-/node-25.9.0.tgz",
|
||||||
"integrity": "sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ==",
|
"integrity": "sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": ">=7.24.0 <7.24.7"
|
"undici-types": ">=7.24.0 <7.24.7"
|
||||||
}
|
}
|
||||||
@@ -365,6 +376,18 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.2",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/ansi-regex/-/ansi-regex-6.2.2.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/ansi-regex/-/ansi-regex-6.2.2.tgz",
|
||||||
@@ -418,6 +441,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/at-least-node": {
|
"node_modules/at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/at-least-node/-/at-least-node-1.0.0.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||||
@@ -440,6 +469,18 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.16.1",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/axios/-/axios-1.16.1.tgz",
|
||||||
|
"integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.16.0",
|
||||||
|
"form-data": "^4.0.5",
|
||||||
|
"https-proxy-agent": "^5.0.1",
|
||||||
|
"proxy-from-env": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/balanced-match/-/balanced-match-4.0.4.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||||
@@ -726,6 +767,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "10.0.1",
|
"version": "10.0.1",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/commander/-/commander-10.0.1.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/commander/-/commander-10.0.1.tgz",
|
||||||
@@ -971,6 +1024,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/depd/-/depd-2.0.0.tgz",
|
||||||
@@ -1144,6 +1206,21 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escalade": {
|
"node_modules/escalade": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/escalade/-/escalade-3.2.0.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/escalade/-/escalade-3.2.0.tgz",
|
||||||
@@ -1174,7 +1251,6 @@
|
|||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/express/-/express-5.2.1.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/express/-/express-5.2.1.tgz",
|
||||||
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "^2.0.0",
|
"accepts": "^2.0.0",
|
||||||
"body-parser": "^2.2.1",
|
"body-parser": "^2.2.1",
|
||||||
@@ -1265,6 +1341,26 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.16.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/follow-redirects/-/follow-redirects-1.16.0.tgz",
|
||||||
|
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/foreground-child": {
|
"node_modules/foreground-child": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/foreground-child/-/foreground-child-3.3.1.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||||
@@ -1282,6 +1378,43 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/form-data/-/form-data-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/form-data/node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/form-data/node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/forwarded/-/forwarded-0.2.0.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
@@ -1496,6 +1629,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/hasown/-/hasown-2.0.3.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/hasown/-/hasown-2.0.3.tgz",
|
||||||
@@ -1593,6 +1741,19 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/https-proxy-agent": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.7.2",
|
"version": "0.7.2",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
||||||
@@ -2248,7 +2409,6 @@
|
|||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/pg/-/pg-8.20.0.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/pg/-/pg-8.20.0.tgz",
|
||||||
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
|
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pg-connection-string": "^2.12.0",
|
"pg-connection-string": "^2.12.0",
|
||||||
"pg-pool": "^3.13.0",
|
"pg-pool": "^3.13.0",
|
||||||
@@ -2424,6 +2584,15 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://package-mirror.liara.ir/repository/npm/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pstree.remy": {
|
"node_modules/pstree.remy": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://package-mirror.liara.ir/repository/npm/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
"resolved": "https://package-mirror.liara.ir/repository/npm/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
@@ -3152,7 +3321,6 @@
|
|||||||
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
|||||||
@@ -16,12 +16,14 @@
|
|||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"auto-bind": "^4.0.0",
|
"auto-bind": "^4.0.0",
|
||||||
|
"axios": "^1.16.1",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
"csurf": "^1.11.0",
|
"csurf": "^1.11.0",
|
||||||
"express": "^5.2.1",
|
"express": "^5.2.1",
|
||||||
"express-rate-limit": "^8.5.2",
|
"express-rate-limit": "^8.5.2",
|
||||||
|
"form-data": "^4.0.5",
|
||||||
"helmet": "^8.1.0",
|
"helmet": "^8.1.0",
|
||||||
"hpp": "^0.2.3",
|
"hpp": "^0.2.3",
|
||||||
"http-errors": "^2.0.1",
|
"http-errors": "^2.0.1",
|
||||||
@@ -38,6 +40,7 @@
|
|||||||
"@types/express": "^5.0.6",
|
"@types/express": "^5.0.6",
|
||||||
"@types/hpp": "^0.2.7",
|
"@types/hpp": "^0.2.7",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
|
"@types/multer": "^2.1.0",
|
||||||
"@types/node": "^25.9.0",
|
"@types/node": "^25.9.0",
|
||||||
"dotenv": "^17.4.2",
|
"dotenv": "^17.4.2",
|
||||||
"nodemon": "^3.1.14",
|
"nodemon": "^3.1.14",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const express = require("express") as typeof import("express");
|
|||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
export default class ServerApplication {
|
export default class ServerApplication {
|
||||||
#PORT = 4000;
|
#PORT = 5000;
|
||||||
#APP = express();
|
#APP = express();
|
||||||
constructor() {
|
constructor() {
|
||||||
this.serverConfiguration();
|
this.serverConfiguration();
|
||||||
@@ -47,8 +47,6 @@ export default class ServerApplication {
|
|||||||
await initDB();
|
await initDB();
|
||||||
// await seedRBAC();
|
// await seedRBAC();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.#APP.listen(this.#PORT, () => {
|
this.#APP.listen(this.#PORT, () => {
|
||||||
console.log(
|
console.log(
|
||||||
`Server Running on PORT ${this.#PORT} url : ${"http://localhost:"}${
|
`Server Running on PORT ${this.#PORT} url : ${"http://localhost:"}${
|
||||||
@@ -64,11 +62,12 @@ export default class ServerApplication {
|
|||||||
// this.#APP.get("/", (req, res) => res.send(""));
|
// this.#APP.get("/", (req, res) => res.send(""));
|
||||||
|
|
||||||
this.#APP.use("/api/v1", mainRouter);
|
this.#APP.use("/api/v1", mainRouter);
|
||||||
|
|
||||||
}
|
}
|
||||||
ErrorHandlingConfiguration() {
|
ErrorHandlingConfiguration() {
|
||||||
this.#APP.use((req: any, res: Response, next: NextFunction) => {
|
this.#APP.use((req: any, res: Response, next: NextFunction) => {
|
||||||
next(createHttpError.NotFound("این آدرس یافت نشد"));
|
console.log("dasdadasd");
|
||||||
|
|
||||||
|
next(createHttpError.NotFound("این آدرس یافت نشddد"));
|
||||||
});
|
});
|
||||||
this.#APP.use(
|
this.#APP.use(
|
||||||
async (error: any, req: any, res: ServerResponse, next: NextFunction) => {
|
async (error: any, req: any, res: ServerResponse, next: NextFunction) => {
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export const TOKEN_NAME = 'tid'
|
export const TOKEN_NAME = "tid";
|
||||||
|
|
||||||
|
|||||||
68
src/core/middleware/authApplicant.middleware.ts
Normal file
68
src/core/middleware/authApplicant.middleware.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { Request, NextFunction } from "express";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
import { ServerResponse } from "../types";
|
||||||
|
import { Applicant } from "../../models/Applicant";
|
||||||
|
import { TOKEN_NAME } from "../constant";
|
||||||
|
|
||||||
|
interface JwtPayload {
|
||||||
|
userId: string;
|
||||||
|
iat?: number;
|
||||||
|
exp?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const authApplicant = async (
|
||||||
|
req: any, // یا استفاده از تیپ سفارشی که قبلاً بحث کردیم
|
||||||
|
res: ServerResponse,
|
||||||
|
next: NextFunction,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const token = req.cookies[TOKEN_NAME];
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return res.status(401).json({
|
||||||
|
status: 401,
|
||||||
|
data: {},
|
||||||
|
message: "نشست شما منقضی شده است. لطفا دوباره وارد شوید",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. تایید توکن
|
||||||
|
const decoded = jwt.verify(
|
||||||
|
token,
|
||||||
|
process.env.JWT_SECRET || "secret",
|
||||||
|
) as JwtPayload;
|
||||||
|
|
||||||
|
// console.log(decoded)
|
||||||
|
// if (!decoded.userId) {
|
||||||
|
// return res.status(401).json({
|
||||||
|
// status: 401,
|
||||||
|
// data: {},
|
||||||
|
// message: "توکن نامعتبر است",
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
console.log(decoded);
|
||||||
|
// 3. چک کردن وجود متقاضی در دیتابیس
|
||||||
|
const applicant = await Applicant.findByPk(decoded.userId);
|
||||||
|
|
||||||
|
// if (!applicant) {
|
||||||
|
// return res.status(401).json({
|
||||||
|
// status: 401,
|
||||||
|
// data: {},
|
||||||
|
// message: "متقاضی یافت نشد",
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 4. قرار دادن ID در Request برای استفاده در مراحل بعدی (مانند selectCenter)
|
||||||
|
req.applicantId = applicant?.id;
|
||||||
|
|
||||||
|
next();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
return res.status(401).json({
|
||||||
|
status: 401,
|
||||||
|
data: {},
|
||||||
|
message: "اعتبارنامه نامعتبر است",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from "express";
|
||||||
import AuthRouter from '../../modules/auth/router/auth.routes';
|
import AuthRouter from "../../modules/auth/router/auth.routes";
|
||||||
import formRouter from '../../modules/forms/index.routes';
|
import formRouter from "../../modules/forms/index.routes";
|
||||||
import userRouter from '../../modules/user/routes/user.routes';
|
import userRouter from "../../modules/user/routes/user.routes";
|
||||||
import CenterRouter from '../../modules/forms/center/routes/center.routes';
|
import CenterRouter from "../../modules/center/routes/center.routes";
|
||||||
|
import fileRouter from "../../modules/file/routes/file.routes";
|
||||||
|
|
||||||
const mainRouter = Router();
|
const mainRouter = Router();
|
||||||
|
|
||||||
|
mainRouter.use("/auth", AuthRouter);
|
||||||
mainRouter.use('/auth',AuthRouter)
|
mainRouter.use("/user", userRouter);
|
||||||
mainRouter.use('/user',userRouter)
|
mainRouter.use("/form", formRouter);
|
||||||
mainRouter.use('/form',formRouter)
|
mainRouter.use("/center", CenterRouter);
|
||||||
mainRouter.use('/center',CenterRouter)
|
mainRouter.use("/files", fileRouter);
|
||||||
export default mainRouter;
|
export default mainRouter;
|
||||||
@@ -2,20 +2,24 @@ import { Model, DataTypes, Sequelize, Optional } from "sequelize";
|
|||||||
|
|
||||||
export interface ApplicantAttributes {
|
export interface ApplicantAttributes {
|
||||||
id: string;
|
id: string;
|
||||||
isCompleted:boolean,
|
centerId?: string | null;
|
||||||
formStep:number,
|
isCompleted: boolean;
|
||||||
|
formStep: number;
|
||||||
createdAt?: Date;
|
createdAt?: Date;
|
||||||
updatedAt?: Date;
|
updatedAt?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApplicantCreationAttributes
|
export interface ApplicantCreationAttributes extends Optional<
|
||||||
extends Optional<ApplicantAttributes, "id" |"isCompleted" | "formStep" | "createdAt" | "updatedAt"> {}
|
ApplicantAttributes,
|
||||||
|
"id" | "isCompleted" | "formStep" | "createdAt" | "updatedAt"
|
||||||
|
> {}
|
||||||
|
|
||||||
export class Applicant
|
export class Applicant
|
||||||
extends Model<ApplicantAttributes, ApplicantCreationAttributes>
|
extends Model<ApplicantAttributes, ApplicantCreationAttributes>
|
||||||
implements ApplicantAttributes
|
implements ApplicantAttributes
|
||||||
{
|
{
|
||||||
public id!: string;
|
public id!: string;
|
||||||
|
public centerId?: string | null;
|
||||||
public isCompleted!: boolean;
|
public isCompleted!: boolean;
|
||||||
public formStep!: number;
|
public formStep!: number;
|
||||||
public readonly createdAt!: Date;
|
public readonly createdAt!: Date;
|
||||||
@@ -30,22 +34,30 @@ export class Applicant
|
|||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
centerId: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: "centers",
|
||||||
|
key: "id",
|
||||||
|
},
|
||||||
|
},
|
||||||
isCompleted: {
|
isCompleted: {
|
||||||
type: DataTypes.BOOLEAN,
|
type: DataTypes.BOOLEAN,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue:false
|
defaultValue: false,
|
||||||
},
|
},
|
||||||
formStep: {
|
formStep: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue:0
|
defaultValue: 1,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize,
|
sequelize,
|
||||||
tableName: "applicants",
|
tableName: "applicants",
|
||||||
timestamps: true
|
timestamps: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return Applicant;
|
return Applicant;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Model, DataTypes, Sequelize, Optional } from "sequelize";
|
import { Model, DataTypes, Sequelize, Optional } from "sequelize";
|
||||||
|
import { Applicant } from "./Applicant";
|
||||||
|
|
||||||
export interface IdentityAttributes {
|
export interface IdentityAttributes {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -45,6 +46,7 @@ export class Identity
|
|||||||
public gender!: string;
|
public gender!: string;
|
||||||
public religion!: string;
|
public religion!: string;
|
||||||
public nationality!: string;
|
public nationality!: string;
|
||||||
|
public readonly applicant?: Applicant;
|
||||||
|
|
||||||
public profilePhotoId?: string;
|
public profilePhotoId?: string;
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ const models = {
|
|||||||
JobRequest: JobRequest.initModel(sequelize),
|
JobRequest: JobRequest.initModel(sequelize),
|
||||||
Job: Job.initModel(sequelize),
|
Job: Job.initModel(sequelize),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Applicant.belongsTo(Center, { foreignKey: "centerId", as: "center" });
|
||||||
|
Center.hasMany(Applicant, { foreignKey: "centerId", as: "applicants" });
|
||||||
// Role.hasMany(User, { foreignKey: "roleId" });
|
// Role.hasMany(User, { foreignKey: "roleId" });
|
||||||
// User.belongsTo(Role, { foreignKey: "roleId" });
|
// User.belongsTo(Role, { foreignKey: "roleId" });
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ class AuthControllerClass extends Controller {
|
|||||||
}
|
}
|
||||||
async applicantLogin(req: any, res: ServerResponse, next: NextFunction) {
|
async applicantLogin(req: any, res: ServerResponse, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const data = await this.#service.applicantLogin(
|
const data = await this.#service.applicantLogin(req?.body?.nationalCode);
|
||||||
req?.body?.nationalCode,
|
|
||||||
);
|
|
||||||
res.cookie(TOKEN_NAME, data.token, {
|
res.cookie(TOKEN_NAME, data.token, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
@@ -47,7 +45,13 @@ class AuthControllerClass extends Controller {
|
|||||||
});
|
});
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
status: 200,
|
status: 200,
|
||||||
data,
|
data: {
|
||||||
|
applicant: {
|
||||||
|
id: data.applicant.id,
|
||||||
|
formStep: data?.applicant?.formStep || 1, // <--- این را اضافه کنید
|
||||||
|
centerId: data?.applicant?.centerId, // <--- برای تکمیل دیتای فرانت
|
||||||
|
},
|
||||||
|
},
|
||||||
message: "Ok",
|
message: "Ok",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -57,21 +57,44 @@ class AuthServiceClass extends Controller {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let applicant = identity?.applicant;
|
||||||
|
|
||||||
|
// // اگر identity وجود داشت ولی applicant نداشت
|
||||||
|
// if (identity && !applicant) {
|
||||||
|
// applicant = await Applicant.create({
|
||||||
|
// formStep: 1,
|
||||||
|
// isCompleted: false,
|
||||||
|
// centerId: null, // باید nullable باشد
|
||||||
|
// });
|
||||||
|
|
||||||
|
// await identity.update({
|
||||||
|
// applicantId: applicant.id,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // اگر identity اصلاً وجود نداشت => applicant جدید بساز
|
||||||
|
// if (!identity) {
|
||||||
|
// applicant = await Applicant.create({
|
||||||
|
// formStep: 1,
|
||||||
|
// isCompleted: false,
|
||||||
|
// centerId: null, // باید nullable باشد
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
const token = jwt.sign(
|
const token = jwt.sign(
|
||||||
{ userId: identity?.applicantId },
|
{ userId: applicant?.id },
|
||||||
process.env.JWT_SECRET || "secret",
|
process.env.JWT_SECRET || "secret",
|
||||||
{ expiresIn: "24h" }, // طول عمر توکن
|
{ expiresIn: "24h" },
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
applicant: {
|
applicant: {
|
||||||
id: identity?.applicantId,
|
id: identity?.applicant?.id,
|
||||||
fullname: `${identity?.firstName} ${identity?.lastName}`,
|
formStep: identity?.applicant?.formStep || 1,
|
||||||
role: identity,
|
centerId: identity?.applicant?.centerId ?? null,
|
||||||
},
|
},
|
||||||
|
isNewUser: !identity,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { NextFunction } from "express";
|
import { NextFunction } from "express";
|
||||||
import { Controller } from "../../../../core/controller/main.controller";
|
import { Controller } from "../../../core/controller/main.controller";
|
||||||
import { ServerResponse } from "../../../../core/types";
|
import { ServerResponse } from "../../../core/types";
|
||||||
import CenterService from "../service/center.service";
|
import CenterService from "../service/center.service";
|
||||||
|
|
||||||
class CenterControllerClass extends Controller {
|
class CenterControllerClass extends Controller {
|
||||||
@@ -74,6 +74,18 @@ class CenterControllerClass extends Controller {
|
|||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async selectCenter(req: any, res: ServerResponse, next: NextFunction) {
|
||||||
|
try {
|
||||||
|
await this.#service.selectCenter(req.body || {}, req?.applicantId ?? "");
|
||||||
|
return res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
data: {},
|
||||||
|
message: "ايجاد شد",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CenterController = new CenterControllerClass();
|
const CenterController = new CenterControllerClass();
|
||||||
16
src/modules/center/routes/center.routes.ts
Normal file
16
src/modules/center/routes/center.routes.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Router } from "express";
|
||||||
|
import CenterController from "../controller/center.controller";
|
||||||
|
import { requireAuth } from "../../../core/middleware/auth.middleware";
|
||||||
|
import { authApplicant } from "../../../core/middleware/authApplicant.middleware";
|
||||||
|
|
||||||
|
const CenterRouter = Router();
|
||||||
|
|
||||||
|
CenterRouter.post("/select", authApplicant, CenterController.selectCenter);
|
||||||
|
|
||||||
|
CenterRouter.post("/create", requireAuth, CenterController.create); // ایجاد
|
||||||
|
CenterRouter.get("/all", CenterController.getAll); // لیست همه
|
||||||
|
CenterRouter.get("/get/:id", requireAuth, CenterController.getById); // مشاهده یکی
|
||||||
|
CenterRouter.put("/update/:id", requireAuth, CenterController.update); // ویرایش
|
||||||
|
CenterRouter.delete("/delete/:id", requireAuth, CenterController.delete); // حذف
|
||||||
|
|
||||||
|
export default CenterRouter;
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { Controller } from "../../../../core/controller/main.controller";
|
import { UUIDV4 } from "sequelize";
|
||||||
import { Center } from "../../../../models/Center";
|
import { Controller } from "../../../core/controller/main.controller";
|
||||||
import { JobCategory } from "../../../../models/JobCategory";
|
import { Applicant } from "../../../models/Applicant";
|
||||||
|
import { Center } from "../../../models/Center";
|
||||||
|
import { JobCategory } from "../../../models/JobCategory";
|
||||||
|
import createHttpError from "http-errors";
|
||||||
|
import { GlobalErrorMessages } from "../../../core/messages/errors";
|
||||||
|
|
||||||
class CenterServiceClass extends Controller {
|
class CenterServiceClass extends Controller {
|
||||||
// ایجاد مرکز جدید
|
// ایجاد مرکز جدید
|
||||||
@@ -8,6 +12,33 @@ class CenterServiceClass extends Controller {
|
|||||||
return await Center.create(data);
|
return await Center.create(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async selectCenter(data: { centerId: string },applicantId:string) {
|
||||||
|
try {
|
||||||
|
const applicant = await Applicant.findByPk( applicantId);
|
||||||
|
|
||||||
|
if (!applicant) {
|
||||||
|
throw new createHttpError.NotFound("متقاضی یافت نشد");
|
||||||
|
}
|
||||||
|
|
||||||
|
applicant.centerId = data.centerId;
|
||||||
|
applicant.formStep = 2;
|
||||||
|
applicant.isCompleted = false;
|
||||||
|
|
||||||
|
await applicant.save();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: applicant.id,
|
||||||
|
centerId: applicant.centerId,
|
||||||
|
formStep: applicant.formStep,
|
||||||
|
isCompleted: applicant.isCompleted,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
throw new createHttpError.InternalServerError(
|
||||||
|
GlobalErrorMessages.server.internal,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
// دریافت لیست تمام مراکز (همراه با رستههای شغلی مرتبط)
|
// دریافت لیست تمام مراکز (همراه با رستههای شغلی مرتبط)
|
||||||
async getAll() {
|
async getAll() {
|
||||||
return await Center.findAll({
|
return await Center.findAll({
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
// src/controllers/file.controller.ts
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import multer from "multer";
|
||||||
|
import { uploadFileToCDN } from "../service/file.service";
|
||||||
|
import axios from "axios";
|
||||||
|
import { File } from "../../../models/File";
|
||||||
|
|
||||||
|
const upload = multer({
|
||||||
|
storage: multer.memoryStorage(),
|
||||||
|
limits: {
|
||||||
|
fileSize: 2 * 1024 * 1024, // 2MB
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const uploadMiddleware = upload.single("file");
|
||||||
|
|
||||||
|
export const uploadFileController = async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
if (!req.file) {
|
||||||
|
return res.status(400).json({ message: "فایلی ارسال نشده است" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await uploadFileToCDN(
|
||||||
|
req.file.buffer,
|
||||||
|
req.file.originalname,
|
||||||
|
req.file.mimetype,
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(201).json(result);
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("Upload Error:", error?.response?.data || error.message);
|
||||||
|
|
||||||
|
return res.status(500).json({
|
||||||
|
message: "خطا در آپلود فایل",
|
||||||
|
error: error?.response?.data || error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const deleteFileController = async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const { fileId } = req.body;
|
||||||
|
|
||||||
|
if (!fileId) {
|
||||||
|
return res.status(400).json({ message: "fileId is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = await File.findByPk(fileId);
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
return res.status(404).json({ message: "File not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`${process.env.CDN_BASE_URL}/upload/delete`);
|
||||||
|
|
||||||
|
await axios.post(
|
||||||
|
`${process.env.CDN_BASE_URL}/upload/delete`,
|
||||||
|
{ fileUrl: file.path },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.CDN_SERVICE_TOKEN}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await file.destroy();
|
||||||
|
|
||||||
|
return res.json({ success: true });
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error(
|
||||||
|
"deleteFileController error:",
|
||||||
|
error?.response?.data || error.message,
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(error?.response?.status || 500).json({
|
||||||
|
message: "Error deleting file",
|
||||||
|
error: error?.response?.data || error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
11
src/modules/file/routes/file.routes.ts
Normal file
11
src/modules/file/routes/file.routes.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// src/routes/file.routes.ts
|
||||||
|
import { Router } from "express";
|
||||||
|
import { deleteFileController, uploadFileController, uploadMiddleware } from "../controller/file.controller";
|
||||||
|
|
||||||
|
|
||||||
|
const fileRouter = Router();
|
||||||
|
|
||||||
|
fileRouter.post("/upload", uploadMiddleware, uploadFileController);
|
||||||
|
fileRouter.post("/delete", uploadMiddleware, deleteFileController);
|
||||||
|
|
||||||
|
export default fileRouter;
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// src/services/file.service.ts
|
||||||
|
import axios from "axios";
|
||||||
|
import FormData from "form-data";
|
||||||
|
import { File } from "../../../models/File";
|
||||||
|
require("dotenv").config();
|
||||||
|
|
||||||
|
interface UploadResult {
|
||||||
|
id: string;
|
||||||
|
url: string;
|
||||||
|
size: number;
|
||||||
|
mimeType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const uploadFileToCDN = async (
|
||||||
|
fileBuffer: Buffer,
|
||||||
|
originalName: string,
|
||||||
|
mimeType: string,
|
||||||
|
): Promise<UploadResult> => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", fileBuffer, {
|
||||||
|
filename: originalName,
|
||||||
|
contentType: mimeType,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Bearer ${process.env.CDN_SERVICE_TOKEN}`);
|
||||||
|
// 1️⃣ ارسال به CDN
|
||||||
|
const response = await axios.post(`http://localhost:3500/upload`, formData, {
|
||||||
|
headers: {
|
||||||
|
...formData.getHeaders(),
|
||||||
|
Authorization: `Bearer ${process.env.CDN_SERVICE_TOKEN}`,
|
||||||
|
},
|
||||||
|
maxContentLength: Infinity,
|
||||||
|
maxBodyLength: Infinity,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
|
||||||
|
const { url, size, mime } = response.data;
|
||||||
|
|
||||||
|
// 2️⃣ ذخیره در دیتابیس
|
||||||
|
const createdFile = await File.create({
|
||||||
|
fileName: url.split("/").pop()!,
|
||||||
|
originalName,
|
||||||
|
mimeType: mime,
|
||||||
|
|
||||||
|
path: url,
|
||||||
|
size,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(url);
|
||||||
|
return {
|
||||||
|
id: createdFile.id,
|
||||||
|
url,
|
||||||
|
|
||||||
|
size,
|
||||||
|
mimeType: mime,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import { Router } from "express";
|
|
||||||
import CenterController from "../controller/center.controller";
|
|
||||||
|
|
||||||
const CenterRouter = Router();
|
|
||||||
|
|
||||||
CenterRouter.post("/", CenterController.create); // ایجاد
|
|
||||||
CenterRouter.get("/all", CenterController.getAll); // لیست همه
|
|
||||||
CenterRouter.get("/get/:id", CenterController.getById); // مشاهده یکی
|
|
||||||
CenterRouter.put("/update/:id", CenterController.update); // ویرایش
|
|
||||||
CenterRouter.delete("/delete/:id", CenterController.delete); // حذف
|
|
||||||
|
|
||||||
export default CenterRouter;
|
|
||||||
@@ -27,7 +27,8 @@ class IdentityFormControllerClass extends Controller {
|
|||||||
// create and import identity form (step 1 in system)
|
// create and import identity form (step 1 in system)
|
||||||
async create(req: any, res: ServerResponse, next: NextFunction) {
|
async create(req: any, res: ServerResponse, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
await this.#service.create(req.body);
|
const applicantId = req?.applicantId;
|
||||||
|
await this.#service.create(req.body, applicantId);
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
status: 200,
|
status: 200,
|
||||||
@@ -53,7 +54,6 @@ class IdentityFormControllerClass extends Controller {
|
|||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const IdentityFormController = new IdentityFormControllerClass();
|
const IdentityFormController = new IdentityFormControllerClass();
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import IdentityFormController from "./controller/identityForm.controller";
|
import IdentityFormController from "./controller/identityForm.controller";
|
||||||
|
import { authApplicant } from "../../../core/middleware/authApplicant.middleware";
|
||||||
|
|
||||||
const identityRouter = Router();
|
const identityRouter = Router();
|
||||||
|
|
||||||
identityRouter.post("/create", IdentityFormController.create);
|
identityRouter.post("/create", authApplicant,IdentityFormController.create);
|
||||||
// identityRouter.get("/all", IdentityFormController.getAll);
|
// identityRouter.get("/all", IdentityFormController.getAll);
|
||||||
identityRouter.get("/get/:id", IdentityFormController.getById);
|
identityRouter.get("/get/:id", IdentityFormController.getById);
|
||||||
identityRouter.put("/update/:id", IdentityFormController.update);
|
identityRouter.put("/update/:id", IdentityFormController.update);
|
||||||
|
|||||||
@@ -18,22 +18,23 @@ class IdentityFormServiceClass extends Controller {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async create(data: any) {
|
async create(data: any, applicantId: string) {
|
||||||
let applicantId = null;
|
if (!applicantId) {
|
||||||
|
let newApplicant;
|
||||||
try {
|
try {
|
||||||
applicantId = await Applicant.create({
|
newApplicant = await Applicant.create({
|
||||||
id: UUIDV4().toString({}),
|
centerId: data?.centerId,
|
||||||
|
formStep: 3,
|
||||||
|
isCompleted: false,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new createHttpError.InternalServerError(
|
throw new createHttpError.InternalServerError(
|
||||||
GlobalErrorMessages.server.internal,
|
GlobalErrorMessages.server.internal,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Identity.create({
|
await Identity.create({
|
||||||
applicantId: applicantId.id,
|
applicantId: newApplicant.id,
|
||||||
birthDate: data.birthDate,
|
birthDate: data.birthDate,
|
||||||
birthPlace: data.birthPlace,
|
birthPlace: data.birthPlace,
|
||||||
fatherName: data.fatherName,
|
fatherName: data.fatherName,
|
||||||
@@ -46,10 +47,39 @@ class IdentityFormServiceClass extends Controller {
|
|||||||
profilePhotoId: data.profilePhotoId,
|
profilePhotoId: data.profilePhotoId,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
throw new createHttpError.InternalServerError(
|
throw new createHttpError.InternalServerError(
|
||||||
GlobalErrorMessages.server.internal,
|
GlobalErrorMessages.server.internal,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await Identity.update(
|
||||||
|
{
|
||||||
|
birthDate: data.birthDate,
|
||||||
|
birthPlace: data.birthPlace,
|
||||||
|
fatherName: data.fatherName,
|
||||||
|
firstName: data.firstName,
|
||||||
|
nationalCode: data.nationalCode,
|
||||||
|
gender: data.gender,
|
||||||
|
lastName: data.lastName,
|
||||||
|
nationality: data.nationality,
|
||||||
|
religion: data.religion,
|
||||||
|
profilePhotoId: data.profilePhotoId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
where: {
|
||||||
|
applicantId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
throw new createHttpError.InternalServerError(
|
||||||
|
GlobalErrorMessages.server.internal,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async update(formID: string, data: any) {
|
async update(formID: string, data: any) {
|
||||||
const [affectedRows] = await Identity.update(
|
const [affectedRows] = await Identity.update(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import identityRouter from "./identity/index.routes";
|
|||||||
import PhysicalInfoRouter from "./physicalInfo/index.routes";
|
import PhysicalInfoRouter from "./physicalInfo/index.routes";
|
||||||
import EducationInfoRouter from "./education/index.routes";
|
import EducationInfoRouter from "./education/index.routes";
|
||||||
import CourseInfoRouter from "./course/index.routes";
|
import CourseInfoRouter from "./course/index.routes";
|
||||||
import CenterRouter from "./center/routes/center.routes";
|
import CenterRouter from "../center/routes/center.routes";
|
||||||
import referralRouter from "./referral/routes/referral.routes";
|
import referralRouter from "./referral/routes/referral.routes";
|
||||||
import JobRequestRouter from "./jobRequest/routes/jobRequest.routes";
|
import JobRequestRouter from "./jobRequest/routes/jobRequest.routes";
|
||||||
import computerSkillRouter from "./computerSkill/routes/computerSkill.routes";
|
import computerSkillRouter from "./computerSkill/routes/computerSkill.routes";
|
||||||
@@ -13,12 +13,12 @@ import workExperienceRouter from "./workExperience/routes/workExperience.routes"
|
|||||||
|
|
||||||
const formRouter = Router();
|
const formRouter = Router();
|
||||||
|
|
||||||
|
formRouter.use("/select-center", CenterRouter);
|
||||||
formRouter.use("/identity", identityRouter);
|
formRouter.use("/identity", identityRouter);
|
||||||
formRouter.use("/personal-info", PersonalInfoRouter);
|
formRouter.use("/personal-info", PersonalInfoRouter);
|
||||||
formRouter.use("/physical-info", PhysicalInfoRouter);
|
formRouter.use("/physical-info", PhysicalInfoRouter);
|
||||||
formRouter.use("/education", EducationInfoRouter);
|
formRouter.use("/education", EducationInfoRouter);
|
||||||
formRouter.use("/course", CourseInfoRouter);
|
formRouter.use("/course", CourseInfoRouter);
|
||||||
formRouter.use("/center", CenterRouter);
|
|
||||||
formRouter.use("/referral", referralRouter);
|
formRouter.use("/referral", referralRouter);
|
||||||
formRouter.use("/job-request", JobRequestRouter);
|
formRouter.use("/job-request", JobRequestRouter);
|
||||||
formRouter.use("/computer-skill", computerSkillRouter);
|
formRouter.use("/computer-skill", computerSkillRouter);
|
||||||
|
|||||||
Reference in New Issue
Block a user