Compare commits
38 Commits
dogsitters
...
feature/im
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0883fc2bc | ||
|
|
69c280b266 | ||
| 6794b01ac8 | |||
| 1cb586f55a | |||
|
|
df21879c0d | ||
|
|
30c9c86c93 | ||
|
|
2925d0f17b | ||
|
|
752dabd015 | ||
|
|
815f11d5bc | ||
| 02eb0e60b7 | |||
| a64ac93935 | |||
| 66a48d1c7e | |||
| 26c66f16b4 | |||
| 02e50bb2f9 | |||
| fadc62c8f0 | |||
| 4759f6f7ee | |||
| 14f2164a82 | |||
| 14ef1f9bad | |||
| dc99318ff0 | |||
| d2fc5f4d5c | |||
| 938bd48fff | |||
| 96f819dc91 | |||
| 25eee8adf5 | |||
| d2b2a29d3d | |||
| 1cf71261d1 | |||
| 88552eb04f | |||
| ab92c99321 | |||
| 02963de893 | |||
| 48550416d9 | |||
| 878c5ffd68 | |||
|
|
6e37fe93f7 | ||
|
|
72a2667549 | ||
|
|
39db7b4d26 | ||
| ff25c0ecb9 | |||
|
|
f1a93bffb5 | ||
| aa231d4f43 | |||
|
|
f254d57db4 | ||
| 106f835934 |
139
package-lock.json
generated
139
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-stub",
|
"name": "multi-stub",
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "multi-stub",
|
"name": "multi-stub",
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ai": "^4.1.13",
|
"ai": "^4.1.13",
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"mongoose-sequence": "^6.0.1",
|
"mongoose-sequence": "^6.0.1",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
"pbkdf2-password": "^1.2.1",
|
"pbkdf2-password": "^1.2.1",
|
||||||
"rotating-file-stream": "^3.2.5",
|
"rotating-file-stream": "^3.2.5",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
@@ -2084,6 +2085,12 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/append-field": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/aproba": {
|
"node_modules/aproba": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
||||||
@@ -2443,9 +2450,19 @@
|
|||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/busboy": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||||
|
"dependencies": {
|
||||||
|
"streamsearch": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@@ -2708,6 +2725,21 @@
|
|||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/concat-stream": {
|
||||||
|
"version": "1.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||||
|
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||||
|
"engines": [
|
||||||
|
"node >= 0.8"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^2.2.2",
|
||||||
|
"typedarray": "^0.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/console-control-strings": {
|
"node_modules/console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||||
@@ -2774,6 +2806,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/core-util-is": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/cors": {
|
"node_modules/cors": {
|
||||||
"version": "2.8.5",
|
"version": "2.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||||
@@ -4578,6 +4616,12 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@@ -5841,6 +5885,15 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minipass": {
|
"node_modules/minipass": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||||
@@ -6150,6 +6203,36 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/multer": {
|
||||||
|
"version": "1.4.5-lts.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
|
||||||
|
"integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"append-field": "^1.0.0",
|
||||||
|
"busboy": "^1.0.0",
|
||||||
|
"concat-stream": "^1.5.2",
|
||||||
|
"mkdirp": "^0.5.4",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"type-is": "^1.6.4",
|
||||||
|
"xtend": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/multer/node_modules/mkdirp": {
|
||||||
|
"version": "0.5.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||||
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.6"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "bin/cmd.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||||
@@ -6707,6 +6790,12 @@
|
|||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/prompts": {
|
"node_modules/prompts": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
||||||
@@ -6834,6 +6923,27 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "2.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream/node_modules/safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
@@ -7414,6 +7524,14 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/streamsearch": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
@@ -7806,6 +7924,12 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typedarray": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/uid-safe": {
|
"node_modules/uid-safe": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||||
@@ -8109,6 +8233,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/xtend": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-stub",
|
"name": "multi-stub",
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"mongoose-sequence": "^6.0.1",
|
"mongoose-sequence": "^6.0.1",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
"pbkdf2-password": "^1.2.1",
|
"pbkdf2-password": "^1.2.1",
|
||||||
"rotating-file-stream": "^3.2.5",
|
"rotating-file-stream": "^3.2.5",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
const { Router } = require("express");
|
|
||||||
const hash = require("pbkdf2-password")();
|
|
||||||
const { promisify } = require("node:util");
|
|
||||||
const jwt = require('jsonwebtoken')
|
|
||||||
|
|
||||||
const { getAnswer } = require("../../utils/common");
|
|
||||||
|
|
||||||
const { AuthModel } = require("./model/todo/auth");
|
|
||||||
const { TOKEN_KEY } = require('./const')
|
|
||||||
const { UserModel } = require("./model/todo/user");
|
|
||||||
|
|
||||||
const { requiredValidate } = require('./utils')
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
"/signup",
|
|
||||||
requiredValidate("login", "password", "email"),
|
|
||||||
async (req, res, next) => {
|
|
||||||
const { login, password, email } = req.body
|
|
||||||
|
|
||||||
const user = await AuthModel.findOne({ login });
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
throw new Error("Пользователь с таким логином уже существует");
|
|
||||||
}
|
|
||||||
|
|
||||||
hash({ password }, async function (err, pass, salt, hash) {
|
|
||||||
if (err) return next(err);
|
|
||||||
|
|
||||||
const user = await UserModel.create({ login, email });
|
|
||||||
await AuthModel.create({ login, hash, salt, userId: user.id });
|
|
||||||
|
|
||||||
res.json(getAnswer(null, { ok: true }))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
function authenticate(login, pass, cb) {
|
|
||||||
AuthModel.findOne({ login }).populate('userId').exec().then((user) => {
|
|
||||||
if (!user) return cb(null, null)
|
|
||||||
|
|
||||||
hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
|
|
||||||
if (err) return cb(err)
|
|
||||||
if (hash === user.hash) return cb(null, user)
|
|
||||||
cb(null, null)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const auth = promisify(authenticate)
|
|
||||||
|
|
||||||
router.post('/signin', requiredValidate('login', 'password'), async (req, res) => {
|
|
||||||
const { login, password } = req.body
|
|
||||||
|
|
||||||
const user = await auth(login, password)
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new Error("Неверный логин или пароль")
|
|
||||||
}
|
|
||||||
|
|
||||||
const accessToken = jwt.sign({
|
|
||||||
...JSON.parse(JSON.stringify(user.userId)),
|
|
||||||
}, TOKEN_KEY, {
|
|
||||||
expiresIn: '12h'
|
|
||||||
})
|
|
||||||
|
|
||||||
res.json(getAnswer(null, {
|
|
||||||
user: user.userId,
|
|
||||||
token: accessToken,
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = router
|
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
exports.DSF_AUTH_PASSWD_MODEL_NAME = 'DSF_AUTH_PASSWD'
|
|
||||||
exports.DSF_AUTH_USER_MODEL_NAME = 'DSF_AUTH_USER'
|
exports.DSF_AUTH_USER_MODEL_NAME = 'DSF_AUTH_USER'
|
||||||
exports.DSF_INTERACTION_MODEL_NAME = 'DSF_INTERACTION'
|
exports.DSF_INTERACTION_MODEL_NAME = 'DSF_INTERACTION'
|
||||||
|
|||||||
@@ -8,20 +8,20 @@ router.post("/auth", (request, response) => {
|
|||||||
const { phoneNumber, password } = request.body;
|
const { phoneNumber, password } = request.body;
|
||||||
console.log(phoneNumber, password);
|
console.log(phoneNumber, password);
|
||||||
if (phoneNumber === "89999999999" || phoneNumber === "89559999999") {
|
if (phoneNumber === "89999999999" || phoneNumber === "89559999999") {
|
||||||
response.send(require("../json/auth/success.json"));
|
response.send(require("./json/auth/success.json"));
|
||||||
} else {
|
} else {
|
||||||
response.status(401).send(require("../json/auth/error.json"));
|
response.status(401).send(require("./json/auth/error.json"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/auth/2fa", (request, response) => {
|
router.post("/auth/2fa", (request, response) => {
|
||||||
const { phoneNumber, code } = request.body;
|
const { phoneNumber, code } = request.body;
|
||||||
if (code === "0000" && phoneNumber === "89999999999") {
|
if (code === "0000" && phoneNumber === "89999999999") {
|
||||||
response.send(require("../json/2fa/dogsitter.success.json"));
|
response.send(require("./json/2fa/dogsitter.success.json"));
|
||||||
} else if (code === "0000" && phoneNumber === "89559999999") {
|
} else if (code === "0000" && phoneNumber === "89559999999") {
|
||||||
response.send(require("../json/2fa/owner.success.json"));
|
response.send(require("./json/2fa/owner.success.json"));
|
||||||
} else {
|
} else {
|
||||||
response.status(401).send(require("../json/2fa/error.json"));
|
response.status(401).send(require("./json/2fa/error.json"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -29,11 +29,11 @@ router.post("/register", (request, response) => {
|
|||||||
const { firstName, secondName, phoneNumber, password, role } = request.body;
|
const { firstName, secondName, phoneNumber, password, role } = request.body;
|
||||||
console.log(phoneNumber, password, role);
|
console.log(phoneNumber, password, role);
|
||||||
if (phoneNumber === "89999999999" || phoneNumber === "89559999999") {
|
if (phoneNumber === "89999999999" || phoneNumber === "89559999999") {
|
||||||
response.status(401).send(require("../json/register/error.json"));
|
response.status(401).send(require("./json/register/error.json"));
|
||||||
} else if (role === "dogsitter") {
|
} else if (role === "dogsitter") {
|
||||||
response.send(require("../json/register/dogsitter.success.json"));
|
response.send(require("./json/register/dogsitter.success.json"));
|
||||||
} else {
|
} else {
|
||||||
response.send(require("../json/register/owner.success.json"));
|
response.send(require("./json/register/owner.success.json"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,12 +58,171 @@ router.get("/auth/session", (request, response) => {
|
|||||||
const decoded = jwt.verify(token, secretKey);
|
const decoded = jwt.verify(token, secretKey);
|
||||||
|
|
||||||
if (decoded.role === "dogsitter") {
|
if (decoded.role === "dogsitter") {
|
||||||
response.send(require("../json/role/dogsitter.success.json"));
|
response.send(require("./json/role/dogsitter.success.json"));
|
||||||
} else {
|
} else {
|
||||||
response.send(require("../json/role/owner.success.json"));
|
response.send(require("./json/role/owner.success.json"));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("token e:", e);
|
console.log("token e:", e);
|
||||||
return response.status(403).json({ error: "Invalid token" });
|
return response.status(403).json({ error: "Invalid token" });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Проверка взаимодействия между пользователем и догситтером
|
||||||
|
router.get("/interactions/check", (req, res) => {
|
||||||
|
const { owner_id, dogsitter_id } = req.query;
|
||||||
|
|
||||||
|
const usersFilePath = path.resolve(__dirname, "./json/users/users.json");
|
||||||
|
|
||||||
|
delete require.cache[require.resolve(usersFilePath)];
|
||||||
|
const usersFile = require(usersFilePath);
|
||||||
|
|
||||||
|
const interactions = usersFile.interactions || [];
|
||||||
|
|
||||||
|
const exists = interactions.some(
|
||||||
|
(interaction) =>
|
||||||
|
interaction.owner_id === Number(owner_id) &&
|
||||||
|
interaction.dogsitter_id === Number(dogsitter_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({ exists });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Добавление нового взаимодействия
|
||||||
|
router.post("/interactions", (req, res) => {
|
||||||
|
const { owner_id, dogsitter_id, interaction_type } = req.body;
|
||||||
|
|
||||||
|
if (!owner_id || !dogsitter_id || !interaction_type) {
|
||||||
|
return res.status(400).json({ error: "Missing required fields" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const usersFilePath = path.resolve(__dirname, "./json/users/users.json");
|
||||||
|
|
||||||
|
delete require.cache[require.resolve(usersFilePath)];
|
||||||
|
const usersFile = require(usersFilePath);
|
||||||
|
|
||||||
|
if (!usersFile.interactions) {
|
||||||
|
usersFile.interactions = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, существует ли уже такое взаимодействие
|
||||||
|
const exists = usersFile.interactions.some(
|
||||||
|
(interaction) =>
|
||||||
|
interaction.owner_id === Number(owner_id) &&
|
||||||
|
interaction.dogsitter_id === Number(dogsitter_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
usersFile.interactions.push({
|
||||||
|
owner_id: Number(owner_id),
|
||||||
|
dogsitter_id: Number(dogsitter_id),
|
||||||
|
interaction_type,
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
usersFilePath,
|
||||||
|
JSON.stringify(usersFile, null, 2),
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Добавлено взаимодействие: owner_id=${owner_id}, dogsitter_id=${dogsitter_id}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/dogsitter-viewing", (req, res) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
console.log(`Получен запрос для dogsitter с ID: ${id}`);
|
||||||
|
|
||||||
|
const usersFile = require("./json/users/users.json");
|
||||||
|
const users = usersFile.data; // Извлекаем массив из свойства "data"
|
||||||
|
|
||||||
|
const user = users.find((user) => user.id === Number(id));
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
res.json(user); // Возвращаем найденного пользователя
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ error: "User not found" }); // Если пользователь не найден
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
|
||||||
|
router.post('/dogsitter-viewing/rating/:id', (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { rating } = req.body;
|
||||||
|
|
||||||
|
if (!rating || rating < 1 || rating > 5) {
|
||||||
|
return res.status(400).json({ error: 'Некорректная оценка' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const usersFilePath = path.resolve(__dirname, "./json/users/users.json");
|
||||||
|
|
||||||
|
delete require.cache[require.resolve(usersFilePath)];
|
||||||
|
const usersFile = require(usersFilePath);
|
||||||
|
const users = usersFile.data;
|
||||||
|
|
||||||
|
const userIndex = users.findIndex(user => user.id === Number(id));
|
||||||
|
if (userIndex === -1) {
|
||||||
|
return res.status(404).json({ error: 'Догситтер не найден' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!users[userIndex].ratings) {
|
||||||
|
users[userIndex].ratings = [];
|
||||||
|
}
|
||||||
|
users[userIndex].ratings.push(rating);
|
||||||
|
|
||||||
|
if (users[userIndex].ratings.length > 100) {
|
||||||
|
users[userIndex].ratings.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
const total = users[userIndex].ratings.reduce((sum, r) => sum + r, 0);
|
||||||
|
users[userIndex].rating = parseFloat((total / users[userIndex].ratings.length).toFixed(2));
|
||||||
|
|
||||||
|
fs.writeFileSync(usersFilePath, JSON.stringify({ data: users }, null, 2), 'utf8');
|
||||||
|
|
||||||
|
console.log(`Обновлен рейтинг догситтера ${id}: ${users[userIndex].rating}`);
|
||||||
|
|
||||||
|
res.json({ rating: users[userIndex].rating, ratings: users[userIndex].ratings });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.patch('/users/:id', (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
const updateData = req.body;
|
||||||
|
|
||||||
|
console.log('Полученные данные для обновления:', updateData);
|
||||||
|
|
||||||
|
|
||||||
|
const usersFilePath = path.resolve(__dirname, "./json/users/users.json");
|
||||||
|
|
||||||
|
delete require.cache[require.resolve(usersFilePath)];
|
||||||
|
const usersFile = require(usersFilePath);
|
||||||
|
const users = usersFile.data;
|
||||||
|
|
||||||
|
const userIndex = users.findIndex((user) => user.id === Number(id));
|
||||||
|
if (userIndex === -1) {
|
||||||
|
return res.status(404).json({ error: 'User not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
users[userIndex] = { ...users[userIndex], ...updateData };
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
usersFilePath,
|
||||||
|
JSON.stringify({ data: users }, null, 2),
|
||||||
|
'utf8'
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Обновлённые данные пользователя:', users[userIndex]);
|
||||||
|
|
||||||
|
res.json(users[userIndex]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
@@ -1,39 +1,69 @@
|
|||||||
[
|
{
|
||||||
{
|
"data": [
|
||||||
"id": 1,
|
{
|
||||||
"phone_number": 89283244141,
|
"id": 1,
|
||||||
"first_name": "Вася",
|
"phone_number": "89999999999",
|
||||||
"second_name": "Пупкин",
|
"first_name": "Вася",
|
||||||
"role": "dogsitter",
|
"second_name": "Пупкин",
|
||||||
"location": "Россия, республика Татарстан, Казань, улица Пушкина, 12",
|
"role": "dogsitter",
|
||||||
"price": 1500,
|
"location": "Россия, республика Татарстан, Казань, Пушкина, 12",
|
||||||
"about_me": "Я люблю собак"
|
"price": "1500",
|
||||||
},
|
"about_me": "Я люблю собак!",
|
||||||
{
|
"rating": 5,
|
||||||
"id": 2,
|
"ratings": [
|
||||||
"phone_number": 89272844541,
|
5,
|
||||||
"first_name": "Ваня",
|
5
|
||||||
"second_name": "Пуськин",
|
],
|
||||||
"role": "dogsitter",
|
"tg": "jullllllie"
|
||||||
"location": "Россия, республика Татарстан, Казань, улица Абсалямова, 19",
|
},
|
||||||
"price": 1000000,
|
{
|
||||||
"about_me": "Я не люблю собак. И вообще я котоман."
|
"id": 2,
|
||||||
},
|
"phone_number": 89272844541,
|
||||||
{
|
"first_name": "Ваня",
|
||||||
"id": 3,
|
"second_name": "Пуськин",
|
||||||
"phone_number": 89872855893,
|
"role": "dogsitter",
|
||||||
"first_name": "Гадий",
|
"location": "Россия, республика Татарстан, Казань, улица Абсалямова, 19",
|
||||||
"second_name": "Петрович",
|
"price": 2000,
|
||||||
"role": "owner"
|
"about_me": "Я не люблю собак. И вообще я котоман.",
|
||||||
},
|
"rating": 4,
|
||||||
{
|
"ratings": [
|
||||||
"id": 4,
|
4,
|
||||||
"phone_number": 89872844591,
|
4
|
||||||
"first_name": "Галкин",
|
],
|
||||||
"second_name": "Максим",
|
"tg": "vanya006"
|
||||||
"role": "dogsitter",
|
},
|
||||||
"location": "Россия, республика Татарстан, Казань, проспект Ямашева, 83",
|
{
|
||||||
"price": 1000000,
|
"id": 3,
|
||||||
"about_me": "Миллион алых роз"
|
"phone_number": 89559999999,
|
||||||
}
|
"first_name": "Гадий",
|
||||||
]
|
"second_name": "Петрович",
|
||||||
|
"role": "owner"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"phone_number": 89872844591,
|
||||||
|
"first_name": "Галкин",
|
||||||
|
"second_name": "Максим",
|
||||||
|
"role": "dogsitter",
|
||||||
|
"location": "Россия, республика Татарстан, Казань, проспект Ямашева, 83",
|
||||||
|
"price": 1750,
|
||||||
|
"about_me": "Миллион алых роз",
|
||||||
|
"rating": 4.5,
|
||||||
|
"ratings": [
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"tg": "maks100500"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"interactions": [
|
||||||
|
{
|
||||||
|
"owner_id": 3,
|
||||||
|
"dogsitter_id": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner_id": 1,
|
||||||
|
"dogsitter_id": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
const { Schema, model } = require("mongoose");
|
|
||||||
|
|
||||||
const {
|
|
||||||
DSF_AUTH_PASSWD_MODEL_NAME,
|
|
||||||
DSF_AUTH_USER_MODEL_NAME,
|
|
||||||
} = require("../../const");
|
|
||||||
|
|
||||||
const schema = new Schema({
|
|
||||||
login: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
unique: true
|
|
||||||
},
|
|
||||||
hash: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
salt: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
userId: {
|
|
||||||
type: Schema.Types.ObjectId,
|
|
||||||
ref: DSF_AUTH_USER_MODEL_NAME
|
|
||||||
},
|
|
||||||
created: {
|
|
||||||
type: Date,
|
|
||||||
default: () => new Date().toISOString(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
schema.set("toJSON", {
|
|
||||||
virtuals: true,
|
|
||||||
versionKey: false,
|
|
||||||
transform: function (doc, ret) {
|
|
||||||
delete ret._id;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
schema.virtual("id").get(function () {
|
|
||||||
return this._id.toHexString();
|
|
||||||
});
|
|
||||||
|
|
||||||
exports.AuthModel = model(DSF_AUTH_PASSWD_MODEL_NAME, schema);
|
|
||||||
9
server/routers/dry-wash/get-token.js
Normal file
9
server/routers/dry-wash/get-token.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const getGigaToken = async () => {
|
||||||
|
const response = await fetch('https://admin.bro-js.ru/api/config/v1/dev')
|
||||||
|
const data = await response.json()
|
||||||
|
return data.features['dry-wash-bh'].GIGA_TOKEN.value
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getGigaToken
|
||||||
|
}
|
||||||
29
server/routers/dry-wash/model/order.car-img.js
Normal file
29
server/routers/dry-wash/model/order.car-img.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const { Schema, model } = require('mongoose')
|
||||||
|
|
||||||
|
const schema = new Schema({
|
||||||
|
image: String,
|
||||||
|
imageRating: String,
|
||||||
|
imageDescription: String,
|
||||||
|
orderId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: 'dry-wash-order'
|
||||||
|
},
|
||||||
|
created: {
|
||||||
|
type: Date,
|
||||||
|
default: () => new Date().toISOString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
schema.set('toJSON', {
|
||||||
|
virtuals: true,
|
||||||
|
versionKey: false,
|
||||||
|
transform(_doc, ret) {
|
||||||
|
delete ret._id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
schema.virtual('id').get(function () {
|
||||||
|
return this._id.toHexString()
|
||||||
|
})
|
||||||
|
|
||||||
|
exports.OrderCarImgModel = model('dry-wash-order-car-image', schema)
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
const mongoose = require("mongoose")
|
const mongoose = require("mongoose")
|
||||||
const router = require('express').Router()
|
const router = require('express').Router()
|
||||||
|
const multer = require('multer')
|
||||||
const { MasterModel } = require('./model/master')
|
const { MasterModel } = require('./model/master')
|
||||||
const { OrderModel } = require('./model/order')
|
const { OrderModel } = require('./model/order')
|
||||||
|
const { OrderCarImgModel } = require('./model/order.car-img')
|
||||||
const { orderStatus } = require('./model/const')
|
const { orderStatus } = require('./model/const')
|
||||||
|
const { getGigaToken } = require('./get-token')
|
||||||
|
|
||||||
const isValidPhoneNumber = (value) => /^(\+)?\d{9,15}/.test(value)
|
const isValidPhoneNumber = (value) => /^(\+)?\d{9,15}/.test(value)
|
||||||
const isValidCarNumber = (value) => /^[авекмнорстух][0-9]{3}[авекмнорстух]{2}[0-9]{2,3}$/i.test(value)
|
const isValidCarNumber = (value) => /^[авекмнорстух][0-9]{3}[авекмнорстух]{2}[0-9]{2,3}$/i.test(value)
|
||||||
@@ -26,6 +29,9 @@ const isValidLocation = (value) => {
|
|||||||
const isValidOrderStatus = (value) => Object.values(orderStatus).includes(value)
|
const isValidOrderStatus = (value) => Object.values(orderStatus).includes(value)
|
||||||
const isValidOrderNotes = (value) => value.length < 500
|
const isValidOrderNotes = (value) => value.length < 500
|
||||||
|
|
||||||
|
const allowedMimeTypes = ['image/jpeg', 'image/png']
|
||||||
|
const sizeLimitInMegaBytes = 5
|
||||||
|
|
||||||
const VALIDATION_MESSAGES = {
|
const VALIDATION_MESSAGES = {
|
||||||
order: {
|
order: {
|
||||||
notFound: 'Order not found'
|
notFound: 'Order not found'
|
||||||
@@ -60,6 +66,13 @@ const VALIDATION_MESSAGES = {
|
|||||||
carColor: {
|
carColor: {
|
||||||
invalid: 'Invalid car color'
|
invalid: 'Invalid car color'
|
||||||
},
|
},
|
||||||
|
carImg: {
|
||||||
|
required: 'Car image file is required',
|
||||||
|
invalid: {
|
||||||
|
type: `Invalid car image file type. Allowed types: ${allowedMimeTypes}`,
|
||||||
|
size: `Invalid car image file size. Limit is ${sizeLimitInMegaBytes}MB`
|
||||||
|
}
|
||||||
|
},
|
||||||
washingBegin: {
|
washingBegin: {
|
||||||
required: 'Begin time of washing is required',
|
required: 'Begin time of washing is required',
|
||||||
invalid: 'Invalid begin time of washing'
|
invalid: 'Invalid begin time of washing'
|
||||||
@@ -248,4 +261,182 @@ router.delete('/:id', async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const storage = multer.memoryStorage()
|
||||||
|
const upload = multer({
|
||||||
|
storage: storage,
|
||||||
|
limits: { fileSize: sizeLimitInMegaBytes * 1024 * 1024 },
|
||||||
|
fileFilter: (req, file, cb) => {
|
||||||
|
if (allowedMimeTypes.includes(file.mimetype)) {
|
||||||
|
cb(null, true)
|
||||||
|
} else {
|
||||||
|
cb(new Error(VALIDATION_MESSAGES.carImg.invalid.type), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { v4: uuidv4 } = require("uuid")
|
||||||
|
const axios = require('axios')
|
||||||
|
|
||||||
|
const GIGA_CHAT_ACCESS_TOKEN = 'MTQwMmNmZjgtZjA5OC00OGMxLWI0OTUtNWU3ZTU4YzMzZjdjOmU5OGFiYmNiLThmMDItNGVmOC1hNjhhLTA4Y2QxYjVmOGRmMA=='
|
||||||
|
const GIGA_CHAT_OAUTH = 'https://ngw.devices.sberbank.ru:9443/api/v2/oauth'
|
||||||
|
const GIGA_CHAT_API = 'https://gigachat.devices.sberbank.ru/api/v1'
|
||||||
|
|
||||||
|
const getToken = async (req, res) => {
|
||||||
|
const gigaToken = await getGigaToken()
|
||||||
|
|
||||||
|
const rqUID = uuidv4()
|
||||||
|
const body = new URLSearchParams({
|
||||||
|
scope: "GIGACHAT_API_PERS",
|
||||||
|
})
|
||||||
|
|
||||||
|
const response = await fetch(GIGA_CHAT_OAUTH, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Basic ${gigaToken}`,
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
Accept: "application/json",
|
||||||
|
RqUID: rqUID,
|
||||||
|
},
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json()
|
||||||
|
console.error("Ошибка запроса: ", errorData)
|
||||||
|
return res.status(response.status).json(errorData)
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadImage = async (file, accessToken) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
const blob = new Blob([file.buffer], { type: file.mimetype })
|
||||||
|
formData.append('file', blob, file.originalname)
|
||||||
|
formData.append('purpose', 'general')
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
maxBodyLength: Infinity,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Authorization': `Bearer ${accessToken}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${GIGA_CHAT_API}/files`, formData, config)
|
||||||
|
return response.data.id
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const analyzeImage = async (fileId, token) => {
|
||||||
|
const response = await fetch(`${GIGA_CHAT_API}/chat/completions`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: "GigaChat-Max",
|
||||||
|
stream: false,
|
||||||
|
update_interval: 0,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content:
|
||||||
|
`Ты эксперт по оценке степени загрязнения автомобилей. Твоя задача — анализировать фотографии машин и определять степень их загрязнения.
|
||||||
|
ВАЖНО: Твой ответ ДОЛЖЕН быть СТРОГО в формате JSON и содержать ТОЛЬКО следующие поля:
|
||||||
|
{
|
||||||
|
"value": число от 0 до 10 (целое или с одним знаком после запятой),
|
||||||
|
"description": "текстовое описание на русском языке"
|
||||||
|
}
|
||||||
|
Правила:
|
||||||
|
1. Поле "value":
|
||||||
|
- Должно быть числом от 0 до 10
|
||||||
|
- 0 = машина абсолютно чистая
|
||||||
|
- 10 = машина максимально грязная
|
||||||
|
2. Поле "description":
|
||||||
|
- Должно содержать 2-3 предложения на русском языке
|
||||||
|
- Обязательно указать конкретные признаки загрязнения
|
||||||
|
- Объяснить почему выставлен именно такой балл
|
||||||
|
НЕ ДОБАВЛЯЙ никаких дополнительных полей или комментариев вне JSON структуры.
|
||||||
|
НЕ ИСПОЛЬЗУЙ markdown форматирование.
|
||||||
|
ОТВЕТ ДОЛЖЕН БЫТЬ ВАЛИДНЫМ JSON.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: 'Дай оценку для приложенного файла изображения согласно структуре, ответ должен быть на русском языке',
|
||||||
|
attachments: [fileId],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
try {
|
||||||
|
return JSON.parse(data.choices[0].message.content)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
return { description: data.choices[0].message.content }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertFileToBase64 = (file) => {
|
||||||
|
const base64Image = file.buffer.toString('base64')
|
||||||
|
return base64Image
|
||||||
|
}
|
||||||
|
|
||||||
|
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0"
|
||||||
|
|
||||||
|
router.post('/:id/upload-car-img', upload.single('file'), async (req, res) => {
|
||||||
|
const { id: orderId } = req.params
|
||||||
|
if (!mongoose.Types.ObjectId.isValid(orderId)) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.orderId.invalid)
|
||||||
|
}
|
||||||
|
const order = await OrderModel.findById(orderId)
|
||||||
|
if (!order) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.order.notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!req.file) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.carImg.required)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { access_token } = await getToken(req, res)
|
||||||
|
|
||||||
|
const fileId = await uploadImage(req.file, access_token)
|
||||||
|
const { value, description } = await analyzeImage(fileId, access_token) ?? {}
|
||||||
|
|
||||||
|
const orderCarImg = await OrderCarImgModel.create({
|
||||||
|
image: convertFileToBase64(req.file),
|
||||||
|
imageRating: value,
|
||||||
|
imageDescription: description,
|
||||||
|
orderId,
|
||||||
|
created: new Date().toISOString(),
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).send({ success: true, body: orderCarImg })
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.use((err, req, res, next) => {
|
||||||
|
if (err instanceof multer.MulterError) {
|
||||||
|
switch (err.message) {
|
||||||
|
case 'File too large':
|
||||||
|
return res.status(400).json({ success: false, error: VALIDATION_MESSAGES.carImg.invalid.size })
|
||||||
|
default:
|
||||||
|
return res.status(400).json({ success: false, error: err.message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(err.message)
|
||||||
|
})
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
@@ -8,6 +8,10 @@ router.get("/update-like", (request, response) => {
|
|||||||
response.send(require("./json/gamepage/success.json"));
|
response.send(require("./json/gamepage/success.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get("/add-to-cart", (request, response) => {
|
||||||
|
response.send(require("./json/home-page-data/games-in-cart.json"));
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/categories", (request, response) => {
|
router.get("/categories", (request, response) => {
|
||||||
response.send(require("./json/home-page-data/all-games.json"));
|
response.send(require("./json/home-page-data/all-games.json"));
|
||||||
});
|
});
|
||||||
@@ -16,18 +20,32 @@ router.get("/favourites", (request, response) => {
|
|||||||
response.send(require("./json/home-page-data/all-games.json"));
|
response.send(require("./json/home-page-data/all-games.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// router.get("/shopping-cart", (request, response) => {
|
||||||
|
// response.send(require("./json/shopping-cart/success.json"));
|
||||||
|
// });
|
||||||
|
|
||||||
router.get("/shopping-cart", (request, response) => {
|
router.get("/shopping-cart", (request, response) => {
|
||||||
response.send(require("./json/shopping-cart/success.json"));
|
response.send(require("./json/home-page-data/games-in-cart.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/home", (request, response) => {
|
// Добавляем поддержку разных ответов для /home
|
||||||
response.send(require("./json/home-page-data/success.json"));
|
router.get("/home", (req, res) => {
|
||||||
|
if (stubs.home === "success") {
|
||||||
|
res.send(require("./json/home-page-data/success.json"));
|
||||||
|
} else if (stubs.home === "empty") {
|
||||||
|
res.send({ data: [] }); // Отправляем пустой массив
|
||||||
|
} else {
|
||||||
|
res.status(500).json({ success: false, message: "Server error" });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/all-games", (request, response) => {
|
router.get("/all-games", (request, response) => {
|
||||||
response.send(require("./json/home-page-data/all-games.json"));
|
response.send(require("./json/home-page-data/all-games.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const stubs = {
|
||||||
|
home: "success",
|
||||||
|
};
|
||||||
|
|
||||||
// // Маршрут для обновления лайков
|
// // Маршрут для обновления лайков
|
||||||
// router.post("/update-like", (request, response) => {
|
// router.post("/update-like", (request, response) => {
|
||||||
@@ -42,7 +60,6 @@ router.get("/all-games", (request, response) => {
|
|||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
|
||||||
const fs = require("fs").promises;
|
const fs = require("fs").promises;
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
@@ -53,7 +70,7 @@ const commentsFilePath = path.join(__dirname, "./json/gamepage/success.json");
|
|||||||
async function readComments() {
|
async function readComments() {
|
||||||
const data = await fs.readFile(commentsFilePath, "utf-8");
|
const data = await fs.readFile(commentsFilePath, "utf-8");
|
||||||
const parsedData = JSON.parse(data);
|
const parsedData = JSON.parse(data);
|
||||||
console.log("Прочитанные данные:", parsedData); // Логируем полученные данные
|
console.log("Прочитанные данные:", parsedData); // Логируем полученные данные
|
||||||
return parsedData;
|
return parsedData;
|
||||||
}
|
}
|
||||||
// Write to JSON file
|
// Write to JSON file
|
||||||
@@ -92,5 +109,149 @@ router.post("/update-like", async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Путь к JSON-файлу с корзиной
|
||||||
|
const cartFilePath = path.join(
|
||||||
|
__dirname,
|
||||||
|
"./json/home-page-data/games-in-cart.json"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Функция для чтения JSON-файла
|
||||||
|
async function readCart() {
|
||||||
|
const data = await fs.readFile(cartFilePath, "utf-8");
|
||||||
|
return JSON.parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для записи в JSON-файл
|
||||||
|
async function writeCart(data) {
|
||||||
|
await fs.writeFile(cartFilePath, JSON.stringify(data, null, 2), "utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Маршрут для добавления/удаления товара в корзине
|
||||||
|
router.post("/add-to-cart", async (req, res) => {
|
||||||
|
const { id, action } = req.body;
|
||||||
|
|
||||||
|
// Проверка наличия id и action
|
||||||
|
if (id === undefined || action === undefined) {
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.json({ success: false, message: "Invalid id or action" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cartData = await readCart();
|
||||||
|
let ids = cartData.data.ids;
|
||||||
|
|
||||||
|
if (action === "add") {
|
||||||
|
// Если action "add", добавляем товар, если его нет в корзине
|
||||||
|
if (!ids?.includes(id)) {
|
||||||
|
ids.push(id);
|
||||||
|
}
|
||||||
|
} else if (action === "remove") {
|
||||||
|
// Если action "remove", удаляем товар, если он есть в корзине
|
||||||
|
if (ids?.includes(id)) {
|
||||||
|
ids = ids.filter((item) => item !== id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Если action невалиден
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.json({ success: false, message: "Invalid action" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Записываем обновленные данные обратно в файл
|
||||||
|
cartData.data.ids = ids;
|
||||||
|
await writeCart(cartData);
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "Cart updated successfully",
|
||||||
|
data: cartData.data, // Возвращаем обновленные данные
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating cart:", error);
|
||||||
|
res.status(500).json({ success: false, message: "Server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
const createElement = (key, value, buttonTitle, basePath) => `
|
||||||
|
<label>
|
||||||
|
<input name="${key}" type="radio" ${
|
||||||
|
stubs[key] === value ? "checked" : ""
|
||||||
|
} onclick="fetch('${basePath}/admin/set/${key}/${value}')"/>
|
||||||
|
${buttonTitle || value}
|
||||||
|
</label>
|
||||||
|
`;
|
||||||
|
|
||||||
|
router.get("/admin/home", (request, response) => {
|
||||||
|
const basePath = request.baseUrl; // Получаем базовый путь маршрутизатора
|
||||||
|
response.send(`
|
||||||
|
<div>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Настройка данных для /home</legend>
|
||||||
|
${createElement("home", "success", "Отдать успешный ответ", basePath)}
|
||||||
|
${createElement("home", "empty", "Отдать пустой массив", basePath)}
|
||||||
|
${createElement("home", "error", "Отдать ошибку", basePath)}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/admin/game-page", (request, response) => {
|
||||||
|
response.send(`
|
||||||
|
<div>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Настройка данных для /game-page</legend>
|
||||||
|
${createElement(
|
||||||
|
"game-page",
|
||||||
|
"success",
|
||||||
|
"Отдать успешный ответ"
|
||||||
|
)}
|
||||||
|
${createElement("game-page", "empty", "Отдать пустой массив")}
|
||||||
|
${createElement("game-page", "error", "Отдать ошибку")}
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/admin/categories", (request, response) => {
|
||||||
|
response.send(`
|
||||||
|
<div>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Настройка данных для /categories</legend>
|
||||||
|
${createElement(
|
||||||
|
"categories",
|
||||||
|
"success",
|
||||||
|
"Отдать успешный ответ"
|
||||||
|
)}
|
||||||
|
${createElement("categories", "empty", "Отдать пустой массив")}
|
||||||
|
${createElement("categories", "error", "Отдать ошибку")}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/admin/favourites", (request, response) => {
|
||||||
|
response.send(`
|
||||||
|
<div>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Настройка данных для /favourites</legend>
|
||||||
|
${createElement(
|
||||||
|
"favourites",
|
||||||
|
"success",
|
||||||
|
"Отдать успешный ответ"
|
||||||
|
)}
|
||||||
|
${createElement("favourites", "empty", "Отдать пустой массив")}
|
||||||
|
${createElement("favourites", "error", "Отдать ошибку")}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/admin/set/:key/:value", (request, response) => {
|
||||||
|
const { key, value } = request.params;
|
||||||
|
stubs[key] = value;
|
||||||
|
response.send("Настройки обновлены!");
|
||||||
|
});
|
||||||
@@ -5,28 +5,28 @@
|
|||||||
{
|
{
|
||||||
"username": "Пользователь1",
|
"username": "Пользователь1",
|
||||||
"text": "Текст комментария 1",
|
"text": "Текст комментария 1",
|
||||||
"likes": 11,
|
"likes": 13,
|
||||||
"rating": 8,
|
"rating": 8,
|
||||||
"date": "2025-03-01T10:00:00Z"
|
"date": "2025-03-01T10:00:00Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"username": "Пользователь2",
|
"username": "Пользователь2",
|
||||||
"text": "Текст комментария 2",
|
"text": "Текст комментария 2",
|
||||||
"likes": 7,
|
"likes": 10,
|
||||||
"rating": 7,
|
"rating": 7,
|
||||||
"date": "2025-01-01T10:00:00Z"
|
"date": "2025-01-01T10:00:00Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"username": "Пользователь3",
|
"username": "Пользователь3",
|
||||||
"text": "Текст комментария 3",
|
"text": "Текст комментария 3",
|
||||||
"likes": 2,
|
"likes": 4,
|
||||||
"rating": 3,
|
"rating": 3,
|
||||||
"date": "2025-02-01T10:00:00Z"
|
"date": "2025-02-01T10:00:00Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"username": "Пользователь4",
|
"username": "Пользователь4",
|
||||||
"text": "Текст комментария 4",
|
"text": "Текст комментария 4",
|
||||||
"likes": 15,
|
"likes": 18,
|
||||||
"rating": 2,
|
"rating": 2,
|
||||||
"date": "2025-12-01T10:00:00Z"
|
"date": "2025-12-01T10:00:00Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,23 +105,27 @@
|
|||||||
{
|
{
|
||||||
"image": "news1",
|
"image": "news1",
|
||||||
"text": "Разработчики Delta Force: Hawk Ops представили крупномасштабный режим Havoc Warfare",
|
"text": "Разработчики Delta Force: Hawk Ops представили крупномасштабный режим Havoc Warfare",
|
||||||
"imgPath": "img_news_1"
|
"imgPath": "img_news_1",
|
||||||
|
"link": "https://gamemag.ru/news/185583/delta-force-hawk-ops-gameplay-showcase-havoc-warfare"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"image": "news2",
|
"image": "news2",
|
||||||
"text": "Первый трейлер Assassin’s Creed Shadows — с темнокожим самураем в феодальной Японии",
|
"text": "Первый трейлер Assassin’s Creed Shadows — с темнокожим самураем в феодальной Японии",
|
||||||
"imgPath": "img_news_2"
|
"imgPath": "img_news_2",
|
||||||
|
"link": "https://stopgame.ru/newsdata/62686/pervyy_trailer_assassin_s_creed_shadows_s_temnokozhim_samuraem_v_feodalnoy_yaponii"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"image": "news3",
|
"image": "news3",
|
||||||
"text": "Призрак Цусимы» вышел на ПК — и уже ставит рекорды для Sony",
|
"text": "Призрак Цусимы» вышел на ПК — и уже ставит рекорды для Sony",
|
||||||
"imgPath": "img_news_3"
|
"imgPath": "img_news_3",
|
||||||
|
"link": "https://stopgame.ru/newsdata/62706/prizrak_cusimy_vyshel_na_pk_i_uzhe_stavit_rekordy_dlya_sony"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"image": "news4",
|
"image": "news4",
|
||||||
"text": "Авторы Skull and Bones расширяют планы на второй сезо",
|
"text": "Авторы Skull and Bones расширяют планы на второй сезон",
|
||||||
"imgPath": "img_news_4"
|
"imgPath": "img_news_4",
|
||||||
|
"link": "https://stopgame.ru/newsdata/62711/avtory_skull_and_bones_rasshiryayut_plany_na_vtoroy_sezon"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -607,8 +607,7 @@ function createGigachat(options = {}) {
|
|||||||
}
|
}
|
||||||
var gigachat = createGigachat();
|
var gigachat = createGigachat();
|
||||||
// Annotate the CommonJS export names for ESM import in node:
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
0 && (module.exports = {
|
module.exports = {
|
||||||
createGigachat,
|
createGigachat,
|
||||||
gigachat
|
gigachat
|
||||||
});
|
}
|
||||||
//# sourceMappingURL=index.js.map
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ router.use(async (req, res, next) => {
|
|||||||
process.env.GIGACHAT_ACCESS_TOKEN = json.access_token;
|
process.env.GIGACHAT_ACCESS_TOKEN = json.access_token;
|
||||||
process.env.GIGACHAT_EXPIRES_AT = json.expires_at;
|
process.env.GIGACHAT_EXPIRES_AT = json.expires_at;
|
||||||
console.log(JSON.stringify(response.data));
|
console.log(JSON.stringify(response.data));
|
||||||
} catch {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ const router = Router()
|
|||||||
const todoRouter = require('./routes')
|
const todoRouter = require('./routes')
|
||||||
const authRouter = require('./auth')
|
const authRouter = require('./auth')
|
||||||
const commentRouter = require('./comment')
|
const commentRouter = require('./comment')
|
||||||
|
const navRouter = require('./nav')
|
||||||
|
|
||||||
router.use('/auth', authRouter)
|
router.use('/auth', authRouter)
|
||||||
router.use('/comment', commentRouter)
|
router.use('/comment', commentRouter)
|
||||||
|
router.use('/nav', navRouter)
|
||||||
|
|
||||||
router.use(todoRouter)
|
router.use(todoRouter)
|
||||||
|
|
||||||
|
|||||||
51
server/routers/todo/nav/index.js
Normal file
51
server/routers/todo/nav/index.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
const router = require("express").Router();
|
||||||
|
|
||||||
|
router.get("/users", (req, res) => {
|
||||||
|
res.send({
|
||||||
|
success: false,
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
id: "some-user-id",
|
||||||
|
name: "alexandr",
|
||||||
|
age: 38,
|
||||||
|
surname: null,
|
||||||
|
email: null,
|
||||||
|
rated: 4,
|
||||||
|
avatar:
|
||||||
|
"https://www.gravatar.com/avatar/6529e885535ef67a3fad810ad71167c2c03f79480936e9b3a714731753cbb47e?d=robohash",
|
||||||
|
friends: [
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "not alexandr",
|
||||||
|
surname: null,
|
||||||
|
email: null,
|
||||||
|
rated: 2,
|
||||||
|
avatar: "https://www.gravatar.com/avatar/6e?d=robohash",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "not alexandr",
|
||||||
|
surname: null,
|
||||||
|
email: null,
|
||||||
|
age: 24,
|
||||||
|
rated: 5,
|
||||||
|
avatar: "https://www.gravatar.com/avatar/6e?d=robohash",
|
||||||
|
friends: [
|
||||||
|
{
|
||||||
|
id: "some-user-id",
|
||||||
|
name: "alexandr",
|
||||||
|
surname: null,
|
||||||
|
email: null,
|
||||||
|
rated: 3,
|
||||||
|
avatar:
|
||||||
|
"https://www.gravatar.com/avatar/6529e885535ef67a3fad810ad71167c2c03f79480936e9b3a714731753cbb47e?d=robohash",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
Reference in New Issue
Block a user